Advertisement
lufusol

FC-RNS-LRA_exploration.ws

Apr 6th, 2022
1,478
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /***********************************************************************/
  2. /**     © 2015 CD PROJEKT S.A. All rights reserved.
  3. /**     THE WITCHER® is a trademark of CD PROJEKT S. A.
  4. /**     The Witcher game is based on the prose of Andrzej Sapkowski.
  5. /***********************************************************************/
  6. enum EHorseWaterTestResult
  7. {
  8.     HWTR_Normal,
  9.     HWTR_Adjusted,
  10.     HWTR_ToDeep
  11. }
  12.  
  13. state Exploration in W3HorseComponent
  14. {
  15.     private var parentActor : CActor;
  16.    
  17.     private var isStopping : bool;
  18.     private var isSlowlyStopping : bool;
  19.     private var destSpeed : float;
  20.     private var currSpeed : float;
  21.     private var staminaCooldown : float;
  22.     private var staminaCooldownTimer : float;
  23.     private var staminaBreak : bool;
  24.     private var speedImpulseTimestamp : float;
  25.     private var dismountRequest : bool;
  26.     private var roadFollowBlock : float;
  27.     private var speedLocks  : array<name>;
  28.     private var speedRestriction : float;
  29.     private var useSimpleStaminaManagement : bool;
  30.     private var inclinationCheckCollisionGroups : array<name>;
  31.     private var waterCheckCollisionGroups : array<name>;
  32.     private var threatSum : float;
  33.     private var triedDoubleTap : bool;             
  34.     private var mac : CMovingAgentComponent;
  35.     private var isFollowingRoad : bool;
  36.     //private var shouldGoToCanterAfterStop : bool; //this one doesn't seem to be true ever
  37.     private var grassCollider : CComponent;
  38.    
  39.     private var currSpeedSound : float;
  40.     private var desiredSpeedSound : float;
  41.    
  42.     private var jumpStartPos, jumpEndPos : Vector;
  43.     private var noSaveLock : int;
  44.    
  45.     const var MIN_SPEED : float;
  46.     const var SLOW_SPEED : float;
  47.     const var WALK_SPEED : float;
  48.     const var TROT_SPEED : float;
  49.     const var GALLOP_SPEED : float;
  50.     const var CANTER_SPEED : float;
  51.    
  52.     default isStopping = false;
  53.     default staminaCooldown = 3.f;
  54.     default dismountRequest = false;
  55.     default speedRestriction = 5.f;
  56.     default useSimpleStaminaManagement = false;
  57.    
  58.    
  59.     default MIN_SPEED = 0.f;
  60.     default SLOW_SPEED = 0.5f;
  61.     default WALK_SPEED = 1.f;
  62.     default TROT_SPEED = 2.f;
  63.     default GALLOP_SPEED = 3.f;
  64.     default CANTER_SPEED = 4.f;
  65.    
  66.     //modFriendlyMouseWheel begin
  67.     //turn rates for different speeds
  68.     const var MIN_TURN_SPEED_MULT : float;      default MIN_TURN_SPEED_MULT     = 0.6f;
  69.     const var SLOW_TURN_SPEED_MULT : float;     default SLOW_TURN_SPEED_MULT    = 1.2f;
  70.     const var WALK_TURN_SPEED_MULT : float;     default WALK_TURN_SPEED_MULT    = 1.5f;
  71.     const var TROT_TURN_SPEED_MULT : float;     default TROT_TURN_SPEED_MULT    = 2.1f;
  72.     const var GALLOP_TURN_SPEED_MULT : float;   default GALLOP_TURN_SPEED_MULT  = 2.7f;
  73.     const var CANTER_TURN_SPEED_MULT : float;   default CANTER_TURN_SPEED_MULT  = 3.0f;
  74.    
  75.     var turnRateAdj : float; default turnRateAdj = 1.0f; //final turn rate multiplier
  76.  
  77.     var dirAdj : float; //direction multiplier, shouldn't exceed 1.0!
  78.  
  79.     const var DIR_ADJ_MIN : float;          default DIR_ADJ_MIN         = 0.3f;
  80.     const var DIR_ADJ_MAX : float;          default DIR_ADJ_MAX         = 0.9f; //should not exceed 1.0!
  81.     const var DIR_ADJ_DELAY : float;        default DIR_ADJ_DELAY       = 0.3f;
  82.     const var DIR_ADJ_PER_SEC : float;      default DIR_ADJ_PER_SEC     = 0.6f;
  83.     const var DIR_ADJ_CONTROLLER : float;   default DIR_ADJ_CONTROLLER  = 0.8f;
  84.     //modFriendlyMouseWheel end
  85.    
  86.    
  87.    
  88.    
  89.    
  90.        
  91.     //modFriendlyMouseWheel begin
  92.     const var KBM_BASE_SPEED_LEVEL : int; default KBM_BASE_SPEED_LEVEL = 3;
  93.     private var horseSpeedLevel : int; default horseSpeedLevel = 3;
  94.    
  95.     private function ResetBaseSpeed()
  96.     {
  97.         horseSpeedLevel = KBM_BASE_SPEED_LEVEL;
  98.     }
  99.    
  100.     function GetHorseSpeedFromSpeedLevel(lvl : int) : float
  101.     {
  102.         switch(lvl)
  103.         {
  104.             case 0:     return MIN_SPEED;
  105.             case 1:     return SLOW_SPEED;
  106.             case 2:     return WALK_SPEED;
  107.             case 3:     return TROT_SPEED;
  108.             case 4:     return GALLOP_SPEED;
  109.             case 5:     return CANTER_SPEED;
  110.             default:    return TROT_SPEED;
  111.         }
  112.         return TROT_SPEED;
  113.     }
  114.    
  115.     function GetHorseSpeedFromInputMagnitude(mag : float) : float //controller compatibility
  116.     {
  117.         if(mag < 0.1)       return MIN_SPEED;
  118.         else if(mag < 0.5)  return SLOW_SPEED;
  119.         else if(mag < 0.9)  return WALK_SPEED;
  120.         else                return TROT_SPEED;
  121.     }
  122.    
  123.     function GetSpeedLevelFromHorseSpeed(spd : float) : int
  124.     {
  125.         if(spd <= MIN_SPEED)    return 0;
  126.         if(spd <= SLOW_SPEED)   return 1;
  127.         if(spd <= WALK_SPEED)   return 2;
  128.         if(spd <= TROT_SPEED)   return 3;
  129.         if(spd <= GALLOP_SPEED) return 4;
  130.         if(spd <= CANTER_SPEED) return 5;
  131.         return 3;
  132.     }
  133.    
  134.     function DecreaseSpeedOneLevel(spd : float) : float
  135.     {
  136.         return GetHorseSpeedFromSpeedLevel(Clamp(GetSpeedLevelFromHorseSpeed(spd) - 1, 0, 5));
  137.     }
  138.    
  139.     function IncreaseSpeedOneLevel(spd : float) : float
  140.     {
  141.         return GetHorseSpeedFromSpeedLevel(Clamp(GetSpeedLevelFromHorseSpeed(spd) + 1, 0, 5));
  142.     }
  143.     //modFriendlyMouseWheel end
  144.    
  145.     event OnEnterState( prevStateName : name )
  146.     {
  147.         super.OnEnterState( prevStateName );
  148.        
  149.         //modFriendlyMouseWheel begin
  150.         theInput.RegisterListener( this, 'OnHorseSpeedChange', 'HorseSpeedChange' );
  151.         //modFriendlyMouseWheel end
  152.         theInput.RegisterListener( this, 'OnSpeedPress', 'Canter' );
  153.         theInput.RegisterListener( this, 'OnSpeedHold', 'Gallop' );
  154.         theInput.RegisterListener( this, 'OnDecelerate', 'Decelerate' );
  155.         theInput.RegisterListener( this, 'OnStop', 'Stop' );
  156.         theInput.RegisterListener( this, 'OnHorseJump', 'HorseJump' );
  157.         theInput.RegisterListener( this, 'OnHorseDismountKeyboard', 'HorseDismount' );
  158.        
  159.         parentActor = (CActor)(parent.GetEntity());
  160.         mac = parentActor.GetMovingAgentComponent();
  161.        
  162.         parentActor.SetBehaviorVariable( 'isCanterEnabled', 0.0 );
  163.        
  164.         Prepare();
  165.         InitCollisionGroups();
  166.         ResetSoundParameters();
  167.         ResetBaseSpeed(); //modFriendlyMouseWheel
  168.        
  169.         mac.SetEnabledFeetIK(true);
  170.        
  171.         theGame.GetGuiManager().EnableHudHoldIndicator(IK_Pad_B_CIRCLE, IK_None, "panel_input_action_horsedismount", 0.4, 'HorseDismount');
  172.        
  173.         grassCollider = parent.GetEntity().GetComponent( "CDynamicColliderComponent4" );
  174.     }
  175.  
  176.     event OnLeaveState( nextStateName : name )
  177.     {
  178.         CleanUpJump();
  179.         ResetForceStop();
  180.         Restore();
  181.         UnregisterInput();
  182.         ResetBaseSpeed(); //modFriendlyMouseWheel
  183.        
  184.         mac.SetEnabledFeetIK(true);
  185.  
  186.         super.OnLeaveState( nextStateName );
  187.     }
  188.  
  189.     private function CleanUpJump()
  190.     {
  191.         EndJump();
  192.         OnBehJumpEnded();
  193.     }
  194.    
  195.     private function UnregisterInput()
  196.     {
  197.         //modFriendlyMouseWheel begin
  198.         theInput.UnregisterListener( this, 'HorseSpeedChange' );
  199.         //modFriendlyMouseWheel end
  200.         theInput.UnregisterListener( this, 'Canter' );
  201.         theInput.UnregisterListener( this, 'Gallop' );
  202.         theInput.UnregisterListener( this, 'Decelerate' );
  203.         theInput.UnregisterListener( this, 'Stop' );
  204.         theInput.UnregisterListener( this, 'HorseJump' );
  205.         theInput.UnregisterListener( this, 'HorseDismount' );
  206.         theGame.GetGuiManager().DisableHudHoldIndicator();
  207.     }
  208.    
  209.    
  210.    
  211.    
  212.    
  213.     private function IsSpeedLocked( optional ignoredLock : name ) : bool
  214.     {
  215.         if( ignoredLock != '' )
  216.         {
  217.             if( speedLocks.Size() == 1 && speedLocks.Contains( ignoredLock ) )
  218.             {
  219.                 return false;
  220.             }
  221.             else
  222.             {
  223.                 return speedLocks.Size() > 0;
  224.             }
  225.         }
  226.         else
  227.         {
  228.             return speedLocks.Size() > 0;
  229.         }
  230.     }
  231.    
  232.     private function ToggleSpeedLock( lockName : name, toggle : bool )
  233.     {
  234.         if( toggle )
  235.         {
  236.             if( !speedLocks.Contains( lockName ) )
  237.             {
  238.                 speedLocks.PushBack( lockName );
  239.             }
  240.             //modFriendlyMouseWheel begin
  241.             if(lockName == 'OnStop' || lockName == 'OnNavStop')
  242.             {
  243.                 speedLocks.Remove('OnGallop');
  244.             }
  245.             //modFriendlyMouseWheel end
  246.         }
  247.         else
  248.         {
  249.             speedLocks.Remove( lockName );
  250.            
  251.             //if( !speedLocks.Contains( 'OnStop' ) && lockName != 'OnGallop' && theInput.IsActionPressed( 'Gallop' ) && !dismountRequest && currSpeed <= GALLOP_SPEED )
  252.             //{
  253.             //  //if( shouldGoToCanterAfterStop ) //this var seems to never be true
  254.             //  //{
  255.             //  //  destSpeed = CANTER_SPEED;
  256.             //  //}
  257.             //  GallopPressed();
  258.             //}
  259.         }
  260.     }
  261.    
  262.     private function LeaveThisState()
  263.     {
  264.         timeAfterDismountFinished = 0.f;
  265.         parent.PopState( true );
  266.     }
  267.    
  268.    
  269.    
  270.    
  271.    
  272.     var threatApplicationTimestamp : float;
  273.    
  274.     private var dismountFinishedTimeStamp : float;
  275.     private var timeAfterDismountFinished : float;
  276.    
  277.     default dismountFinishedTimeStamp = -1.f;
  278.     default timeAfterDismountFinished = 0.f;
  279.    
  280.     event OnTick( dt : float )
  281.     {
  282.         parent.OnTick( dt );
  283.        
  284.         if( dismountRequest || thePlayer.IsActionAllowed( EIAB_Movement ) )
  285.         {
  286.             UpdateLogic( dt );
  287.             UpdateDebugGUI();
  288.         }
  289.         else
  290.         {
  291.             ResetRotation();
  292.         }
  293.        
  294.         if ( !parent.user )
  295.         {
  296.             timeAfterDismountFinished += dt;
  297.            
  298.            
  299.             if ( timeAfterDismountFinished > 2.f )
  300.             {
  301.                 LeaveThisState();
  302.             }
  303.         }
  304.     }
  305.    
  306.     event OnMountStarted( entity : CEntity, vehicleSlot : EVehicleSlot )
  307.     {
  308.         parent.OnMountStarted( entity, vehicleSlot );
  309.         LeaveThisState();
  310.     }
  311.    
  312.     event OnMountFinished( entity : CEntity )
  313.     {
  314.         parent.OnMountFinished(entity);
  315.     }
  316.    
  317.     event OnDismountStarted( entity : CEntity )
  318.     {
  319.         thePlayer.SetBehaviorVariable( 'playerWouldLikeToMove', 0.0f );
  320.         UnregisterInput();
  321.         parent.OnDismountStarted( entity );
  322.     }
  323.     event OnDismountFinished( entity : CEntity, vehicleSlot : EVehicleSlot  )
  324.     {
  325.         parent.OnDismountFinished( entity, vehicleSlot );
  326.         parent.ResetPanic();
  327.         timeAfterDismountFinished = 0.f;
  328.     }
  329.    
  330.     event OnIdleBegin()
  331.     {
  332.         parent.OnIdleBegin();
  333.         isInJumpAnim = false;
  334.         isStopping = false;
  335.         isSlowlyStopping = false;
  336.        
  337.         if ( !parent.user )
  338.             LeaveThisState();
  339.        
  340.         ResetForceStop();
  341.        
  342.        
  343.     }
  344.    
  345.     event OnIdleEnd()
  346.     {
  347.         parent.OnIdleEnd();
  348.     }
  349.    
  350.     event OnHorseFastStopBegin()
  351.     {
  352.         isStopping = true;
  353.     }
  354.    
  355.     event OnHorseFastStopEnd()
  356.     {
  357.         if ( dismountRequest )
  358.             parent.IssueCommandToDismount( DT_normal );
  359.        
  360.         isStopping = false;
  361.     }
  362.    
  363.     event OnTakeDamage( action : W3DamageAction )
  364.     {  
  365.         var actorAttacker : CNewNPC;
  366.         var isMonster : bool;
  367.         var threatMult : int;
  368.        
  369.         if( parentActor.HasAbility( 'DisableHorsePanic' ) || thePlayer.HasBuff( EET_Mutagen25 ) )
  370.             return false;
  371.        
  372.         actorAttacker = (CNewNPC)action.attacker;
  373.         isMonster = actorAttacker.IsMonster();
  374.        
  375.         if( isMonster )
  376.             threatMult = 2;
  377.         else
  378.             threatMult = 1;
  379.        
  380.         parentActor.AddPanic( actorAttacker.GetThreatLevel() * 10 * threatMult );
  381.     }
  382.    
  383.    
  384.     event OnCriticalEffectAdded( criticalEffect : ECriticalStateType )
  385.     {
  386.         if( parentActor.HasAbility( 'DisableHorsePanic' ) || thePlayer.HasBuff( EET_Mutagen25 ) )
  387.         {
  388.             if( thePlayer.IsActionAllowed( EIAB_Movement ) )
  389.             {
  390.                 return false;
  391.             }
  392.             else if( !isInJumpAnim )
  393.             {
  394.                 parent.ShakeOffRider( DT_shakeOff );
  395.             }
  396.         }  
  397.         else if( criticalEffect != ECST_Swarm )
  398.         {
  399.             parentActor.AddPanic( 100 );   
  400.            
  401.            
  402.             if( !thePlayer.IsInCombat() )
  403.             {
  404.                 parent.ShakeOffRider( DT_shakeOff );
  405.             }  
  406.         }
  407.     }
  408.    
  409.     var cachedCombatAction : EVehicleCombatAction;
  410.     event OnCombatAction( action : EVehicleCombatAction )
  411.     {
  412.         cachedCombatAction = action;
  413.    
  414.         if ( action == EHCA_Attack || action == EHCA_ShootCrossbow || action == EHCA_ThrowBomb )
  415.         {
  416.             if ( currSpeed > MIN_SPEED )
  417.             {
  418.                 if ( action != EHCA_Attack )
  419.                     speedRestriction = GALLOP_SPEED;
  420.                
  421.                 ToggleSpeedLock('OnAttack',true);
  422.             }
  423.         }
  424.         else if ( action == EHCA_CastSign )
  425.             speedRestriction = TROT_SPEED;
  426.         else
  427.             speedRestriction = GALLOP_SPEED;
  428.     }
  429.    
  430.     event OnCombatActionEnd()
  431.     {
  432.         speedRestriction = CANTER_SPEED;
  433.         ToggleSpeedLock('OnAttack',false);
  434.     }
  435.    
  436.     event OnSettlementEnter()
  437.     {  
  438.        
  439.         if( thePlayer.GetIsHorseRacing() )
  440.         {
  441.             return false;
  442.         }
  443.         else
  444.         {
  445.             speedRestriction = GALLOP_SPEED;
  446.            
  447.            
  448.             if( currSpeed > speedRestriction )
  449.                 thePlayer.DisplayActionDisallowedHudMessage(EIAB_Undefined, , true);
  450.         }  
  451.     }
  452.    
  453.     event OnSettlementExit()
  454.     {
  455.         speedRestriction = CANTER_SPEED;
  456.     }
  457.    
  458.     event OnCanGallop()
  459.     {
  460.         return speedRestriction >= CANTER_SPEED && CanCanter();
  461.     }
  462.    
  463.     event OnCanCanter()
  464.     {
  465.         if ( speedRestriction >= GALLOP_SPEED )
  466.             return true;
  467.         return false;
  468.     }
  469.    
  470.     event OnStopTheVehicleInstant()
  471.     {
  472.         Reset();
  473.         parent.OnStopTheVehicleInstant();
  474.     }
  475.    
  476.     private var stopRequest : bool;
  477.    
  478.     event OnForceStop()
  479.     {
  480.         destSpeed = MIN_SPEED;
  481.         speedRestriction = MIN_SPEED;
  482.         stopRequest = true;
  483.     }
  484.    
  485.     event OnHorseStop()
  486.     {
  487.         destSpeed = MIN_SPEED;
  488.     }
  489.    
  490.     private function ResetForceStop()
  491.     {
  492.         if ( stopRequest )
  493.         {
  494.             stopRequest = false;
  495.             speedRestriction = CANTER_SPEED;
  496.         }
  497.     }
  498.    
  499.     event OnJumpHack()
  500.     {
  501.         if( !isInJumpAnim )
  502.             parent.GenerateEvent( 'jumpHACK' );
  503.     }
  504.    
  505.     private var isRefusingToGo : bool;
  506.     public var collisionAnimTimestamp : float;
  507.     public var collsionAnimCooldown : float;
  508.     default collsionAnimCooldown = 1.0;
  509.    
  510.     event OnHorseWalkBackWallStart()
  511.     {
  512.         isRefusingToGo = true;
  513.     }
  514.    
  515.     event OnHorseWalkBackWallEnd()
  516.     {
  517.         isRefusingToGo = false;
  518.     }
  519.    
  520.     private function CanPlayCollisionAnim() : bool
  521.     {
  522.         return collisionAnimTimestamp + collsionAnimCooldown < theGame.GetEngineTimeAsSeconds();
  523.     }
  524.    
  525.    
  526.    
  527.    
  528.    
  529.     private var prediction : CHorsePrediction;
  530.    
  531.     private final function Prepare()
  532.     {
  533.         Reset();
  534.        
  535.         if( !prediction )
  536.         {
  537.             prediction = new CHorsePrediction in this;
  538.         }
  539.     }
  540.    
  541.     private final function Restore()
  542.     {
  543.         Reset();
  544.        
  545.         parent.InternalResetVariables();
  546.        
  547.         thePlayer.GetVisualDebug().RemoveBar( 'horseSpeed' );
  548.         thePlayer.GetVisualDebug().RemoveBar( 'horseStamina' );
  549.         thePlayer.GetVisualDebug().RemoveBar( 'horseStaminaBar' );
  550.         thePlayer.GetVisualDebug().RemoveBar( 'horsePanic' );
  551.         thePlayer.GetVisualDebug().RemoveBar( 'pitch' );
  552.     }
  553.    
  554.     private final function Reset()
  555.     {
  556.         currSpeed = MIN_SPEED;
  557.         destSpeed = MIN_SPEED;
  558.        
  559.         ResetBaseSpeed(); //modFriendlyMouseWheel
  560.        
  561.         speedLocks.Clear();
  562.        
  563.         staminaBreak    = false;
  564.         dismountRequest = false;
  565.         stopRequest     = false;
  566.         isInJumpAnim    = false;
  567.         isStopping      = false;
  568.        
  569.         startSlidingTimeStamp   = -1.f;
  570.         notSlidingTimeStamp     = -1.f;
  571.        
  572.         parent.GetEntity().SetBehaviorVariable('rotationBlend',0.f);
  573.        
  574.         theGame.ReleaseNoSaveLock( noSaveLock );       
  575.        
  576.         theGame.GetGuiManager().EnableHudHoldIndicator(IK_Pad_B_CIRCLE, IK_None, "panel_input_action_horsedismount", 0.4, 'HorseDismount');
  577.     }
  578.    
  579.     private final function ResetRotation()
  580.     {
  581.         parent.InternalSetRotation( 0.f );
  582.         parent.InternalSetDirection( 0.f );
  583.     }
  584.    
  585.    
  586.    
  587.    
  588.    
  589.     //private const var INPUTMAG_TROT : float;
  590.     //private const var INPUTMAG_WALK : float;
  591.     //
  592.     //default INPUTMAG_TROT = 0.9;
  593.     //default INPUTMAG_WALK = 0.6;
  594.    
  595.     //modFriendlyMouseWheel begin
  596.     private var dirPressedTimestamp : float;
  597.     private var lockedSpeedMovementTimestamp : float;
  598.     private var buttonMashCounter : int; default buttonMashCounter = 0;
  599.     private var braking : bool;
  600.     private var movingAtLockedSpeed : bool;
  601.     //modFriendlyMouseWheel end
  602.    
  603.     private final function ProcessControlInput( lr : float, fb : float, timeDelta : float, useLocalSpace : bool )
  604.     {
  605.         var inputVec, inputVecInWS : Vector;
  606.         var mac : CMovingAgentComponent;
  607.         var horseHeadingInCamSpace : float;
  608.         var dir, rot : float;
  609.         var inputMagnitude : float;
  610.         var predInfo : SPredictionInfo;
  611.         //var braking : bool;
  612.         var prevDir : float;
  613.         var steeringCorrection : bool;
  614.         var stickInput : bool;
  615.        
  616.         if( ( !thePlayer.GetIsMovable() && !dismountRequest ) || speedRestriction == MIN_SPEED )
  617.         {
  618.             destSpeed = MIN_SPEED;
  619.             parent.InternalSetRotation( 0.f );
  620.             parent.InternalSetDirection( 0.f );
  621.             return;
  622.         }
  623.  
  624.         if( lr || fb )
  625.         {
  626.             inputVec.X = lr;
  627.             inputVec.Y = fb;
  628.             //if( useLocalSpace )
  629.             //  inputVecInWS = GetInputVectorInLocalSpace( lr, fb );
  630.             //else
  631.             //  inputVecInWS = GetInputVectorInCamSpace( lr, fb );
  632.             inputVecInWS = GetInputVectorInLocalSpace( lr, fb ); //modFriendlyMouseWheel
  633.                
  634.             stickInput = true;
  635.         }
  636.         else
  637.         {
  638.             inputVec = parent.GetEntity().GetHeadingVector();
  639.             inputVecInWS = inputVec;
  640.         }
  641.        
  642.         if( ShouldApplyCorrection( lr, fb ) )
  643.         {
  644.             steeringCorrection = ApplyCorrection( inputVecInWS, dir, lr, fb );
  645.             thePlayer.GetVisualDebug().AddText( 'SteeringCorrection', "SteeringCorrection : On ", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) );
  646.         }
  647.         else
  648.         {
  649.             if( isFollowingRoad && roadFollowBlock == 0.0 )
  650.             {
  651.                 roadFollowBlock = 1.0;
  652.                 isFollowingRoad = false;
  653.                 mac = ((CActor)parent.GetEntity()).GetMovingAgentComponent();
  654.                 mac.ResetRoadFollowing();
  655.             }
  656.             thePlayer.GetVisualDebug().AddText( 'SteeringCorrection', "SteeringCorrection : Off", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 255, 0, 0 ) );
  657.         }
  658.        
  659.         if( isFollowingRoad && ( lr || fb ) && roadFollowBlock == 0.0 )
  660.         {
  661.             roadFollowBlock = 1.0;
  662.             isFollowingRoad = false;
  663.             mac = ((CActor)parent.GetEntity()).GetMovingAgentComponent();
  664.             mac.ResetRoadFollowing();
  665.         }
  666.        
  667.        
  668.         //modFriendlyMouseWheel start
  669.         if( lr || fb || steeringCorrection )
  670.         {
  671.             if( theInput.LastUsedGamepad() ) //controller compatibility
  672.                 inputMagnitude = VecLength2D( inputVec );
  673.             else
  674.                 inputMagnitude = MaxF(AbsF(inputVec.X), AbsF(inputVec.Y));
  675.  
  676.             if( braking )
  677.             {
  678.                 dir = 0.0f;
  679.                 rot = 0.0f;
  680.             }
  681.             else
  682.             {
  683.                 if( theInput.LastUsedPCInput() ) //for KB&M only
  684.                 {
  685.                     if( theInput.GetActionValue('GI_AxisLeftX') != 0 ) //left/right is pressed
  686.                     {
  687.                         if( theInput.IsActionJustPressed('GI_AxisLeftX') ) //just pressed
  688.                         {
  689.                             dirAdj = DIR_ADJ_MIN;
  690.                             dirPressedTimestamp = theGame.GetEngineTimeAsSeconds();
  691.                         }
  692.                         else if( theGame.GetEngineTimeAsSeconds() - dirPressedTimestamp > DIR_ADJ_DELAY )
  693.                         {
  694.                             dirAdj = MinF(dirAdj + DIR_ADJ_PER_SEC * timeDelta, DIR_ADJ_MAX);
  695.                         }
  696.                     }
  697.                 }
  698.                 else
  699.                 {
  700.                     dirAdj = DIR_ADJ_CONTROLLER;
  701.                 }
  702.            
  703.                 if( !steeringCorrection )
  704.                 {
  705.                     dir = -VecHeading( inputVec ) * dirAdj;
  706.                 }
  707.                
  708.                 dir = AngleNormalize180( dir ) / 180.f;
  709.                
  710.                 if( steeringCorrection )
  711.                 {
  712.                     rot = dir * 2;
  713.                 }
  714.                 else
  715.                 {
  716.                     if( currSpeed < SLOW_SPEED )
  717.                         rot = dir * MIN_TURN_SPEED_MULT;
  718.                     else if( currSpeed < WALK_SPEED )
  719.                         rot = dir * SLOW_TURN_SPEED_MULT;
  720.                     else if( currSpeed < TROT_SPEED )
  721.                         rot = dir * WALK_TURN_SPEED_MULT;
  722.                     else if( currSpeed < GALLOP_SPEED )
  723.                         rot = dir * TROT_TURN_SPEED_MULT;
  724.                     else if( currSpeed < CANTER_SPEED )
  725.                         rot = dir * GALLOP_TURN_SPEED_MULT;
  726.                     else
  727.                         rot = dir * CANTER_TURN_SPEED_MULT;
  728.                     rot *= turnRateAdj;
  729.                 }
  730.             }
  731.            
  732.             prevDir = parent.InternalGetDirection();
  733.            
  734.             if( speedLocks.Contains( 'OnStop' ) )
  735.             {
  736.                 rot = 0.0f;
  737.                 dir = 0.0f;
  738.             }
  739.             else if( theInput.GetActionValue('GI_AxisLeftY') <= -0.9 && currSpeed > MIN_SPEED && !parent.IsInCustomSpot() )
  740.             {
  741.                 rot = 0.0f;
  742.                 dir = 0.0f;
  743.                 destSpeed = MIN_SPEED;
  744.                 braking = true;
  745.             }
  746.            
  747.             if( braking )
  748.             {
  749.                 buttonMashCounter = 0;
  750.             }
  751.             else if( speedLocks.Contains('OnGallop') )
  752.             {
  753.                 lockedSpeedMovementTimestamp = theGame.GetEngineTimeAsSeconds();
  754.                 movingAtLockedSpeed = true;
  755.             }
  756.             else if( movingAtLockedSpeed )
  757.             {
  758.                 if( theGame.GetEngineTimeAsSeconds() - lockedSpeedMovementTimestamp > DOUBLE_TAP_WINDOW )
  759.                 {
  760.                     movingAtLockedSpeed = false;
  761.                     if(destSpeed > TROT_SPEED)
  762.                     {
  763.                         destSpeed = MinF(TROT_SPEED, speedRestriction);
  764.                     }
  765.                 }
  766.             }
  767.             else if( !IsSpeedLocked() && theInput.GetActionValue('GI_AxisLeftY') > 0 )
  768.             {
  769.                 movingAtLockedSpeed = false;
  770.                 if( theInput.LastUsedGamepad() ) //controller compatibility
  771.                 {
  772.                     usedMouseWheel = false;
  773.                     buttonMashCounter = 0;
  774.                     if( currSpeed < GALLOP_SPEED )
  775.                     {
  776.                         destSpeed = GetHorseSpeedFromInputMagnitude(inputMagnitude);
  777.                     }
  778.                 }
  779.                 else //new KB&M controls
  780.                 {
  781.                     if( usedMouseWheel )
  782.                     {
  783.                         usedMouseWheel = false;
  784.                         buttonMashCounter = 0;
  785.                     }
  786.                     else
  787.                     {
  788.                         if( currSpeed < GALLOP_SPEED )
  789.                         {
  790.                             destSpeed = GetHorseSpeedFromSpeedLevel(horseSpeedLevel);
  791.                         }
  792.                         if( theInput.GetActionValue('GI_AxisLeftY') > 0 && theInput.IsActionJustPressed('GI_AxisLeftY') )
  793.                         {
  794.                             if( theGame.GetEngineTimeAsSeconds() - speedImpulseTimestamp < theGame.params.GetHorseDoubleTapWindow() )
  795.                             {
  796.                                 //theGame.witcherLog.AddMessage("kick");
  797.                                 //theGame.witcherLog.AddMessage("times mashed: " + buttonMashCounter);
  798.                                 if(buttonMashCounter < 1) //double-tap
  799.                                 {
  800.                                     if(currSpeed < TROT_SPEED)
  801.                                     {
  802.                                         horseSpeedLevel = Clamp(horseSpeedLevel + 1, 1, 3);
  803.                                         destSpeed = GetHorseSpeedFromSpeedLevel(horseSpeedLevel);
  804.                                     }
  805.                                     else
  806.                                     {
  807.                                         destSpeed = IncreaseSpeedOneLevel(currSpeed);
  808.                                     }
  809.                                 }
  810.                                 else
  811.                                 {
  812.                                     if(currSpeed < CANTER_SPEED)
  813.                                     {
  814.                                         destSpeed = CANTER_SPEED;
  815.                                     }
  816.                                 }
  817.                                 buttonMashCounter += 1;
  818.                             }
  819.                             else
  820.                             {
  821.                                 buttonMashCounter = 0;
  822.                             }
  823.                             speedImpulseTimestamp = theGame.GetEngineTimeAsSeconds();
  824.                         }
  825.                     }
  826.                 }
  827.                
  828.                 if( destSpeed > GALLOP_SPEED && (staminaBreak || !CanCanter()) )
  829.                 {
  830.                     destSpeed = GALLOP_SPEED;
  831.                 }
  832.                
  833.                 destSpeed = MinF(destSpeed, speedRestriction);
  834.                
  835.                 if( currSpeed < destSpeed )
  836.                 {
  837.                     SpursKick();
  838.                 }
  839.                
  840.                 maintainSpeedTimer = 0.0f;
  841.                
  842.             }
  843.         }
  844.         else
  845.         {
  846.             braking = false;
  847.             movingAtLockedSpeed = false;
  848.            
  849.             rot = 0.0f;
  850.             dir = 0.0f;
  851.            
  852.             if( destSpeed > MIN_SPEED )
  853.             {
  854.                 predInfo = prediction.CollectPredictionInfo( parent, 10.f, 0.f, parent.inWater );
  855.                
  856.                 if( predInfo.turnAngle != 0.f )
  857.                 {
  858.                     dir = -predInfo.turnAngle / 180.f;
  859.                     rot = dir;
  860.                 }
  861.             }
  862.         }
  863.  
  864.         parent.InternalSetRotation( rot );
  865.         parent.InternalSetDirection( dir );
  866.         //modFriendlyMouseWheel end
  867.        
  868.         if ( IsRiderInCombatAction() )
  869.             OnCombatAction( cachedCombatAction );
  870.     }
  871.    
  872.     private function ShouldApplyCorrection( stickInputX : float, stickInputY : float ) : bool
  873.     {
  874.         var inputVec : Vector;
  875.         var inputHeading : float;
  876.         var horseHeading : float;
  877.         var angleDistanceBetweenInputAndHorse : float;
  878.  
  879.         //inputVec = GetInputVectorInCamSpace( stickInputX, stickInputY );
  880.         inputVec = GetInputVectorInLocalSpace( stickInputX, stickInputY ); //modFriendlyMouseWheel
  881.         angleDistanceBetweenInputAndHorse = AbsF( AngleDistance( VecHeading( inputVec ), parent.GetHeading() ) );
  882.  
  883.         if( !stickInputX && !stickInputY )
  884.         {
  885.             if( theInput.IsActionPressed( 'Canter' ) )
  886.                 return true;
  887.             else
  888.                 return false;
  889.         }  
  890.         //else if( currSpeed > TROT_SPEED && angleDistanceBetweenInputAndHorse > 55.0 )
  891.         //{
  892.         //  return false;
  893.         //}
  894.         //else if( currSpeed > MIN_SPEED && angleDistanceBetweenInputAndHorse < 55.0 )
  895.         //{
  896.         //  return true;
  897.         //}
  898.         else if( isStopping )
  899.         {
  900.             return true;
  901.         }
  902.         else
  903.             return false;
  904.  
  905.     }
  906.    
  907.     private function ApplyCorrection( inputVector : Vector, out correctedDir, stickInputX : float, stickInputY : float ) : bool
  908.     {
  909.         var stickInput : bool;
  910.         var horseHeadingVec : Vector;
  911.         var mac : CMovingAgentComponent;
  912.         var currentDir : float;
  913.        
  914.         var speed : float;
  915.         var speedModifier : float;
  916.         var dirModifier : float = 1.0;
  917.         var followRoad : bool;
  918.         var maxAngleForAdjustingDir : float;
  919.        
  920.         var cachedVec : Vector;
  921.         var correctedDirV : Vector;
  922.         var desiredDirectionVec : Vector;
  923.         var angleDistance : float;
  924.        
  925.         var startPos, endPos : Vector;
  926.        
  927.         stickInput = stickInputX || stickInputY;
  928.         horseHeadingVec = parent.GetEntity().GetHeadingVector();
  929.         mac = ((CActor)parent.GetEntity()).GetMovingAgentComponent();
  930.         currentDir = parent.GetEntity().GetHeading();
  931.         speedModifier = MaxF( 0.25, stickInputY );
  932.  
  933.         if( currSpeed == CANTER_SPEED )
  934.         {
  935.             speed = 18.75;
  936.            
  937.             if( !stickInput && !thePlayer.GetIsHorseRacing() )
  938.             {
  939.                 dirModifier = 3.0;
  940.                 followRoad = true;
  941.                 maxAngleForAdjustingDir = 90.0;
  942.             }
  943.             else
  944.             {
  945.                 dirModifier = 2.0;
  946.                 speed *= speedModifier;
  947.                 maxAngleForAdjustingDir = 15.0;
  948.             }
  949.            
  950.             correctedDirV = VecNormalize2D( inputVector * 0.3 + horseHeadingVec * 0.7 );
  951.         }
  952.         else if( currSpeed == GALLOP_SPEED )
  953.         {
  954.             speed = 12.5;
  955.            
  956.             if ( !stickInput && !thePlayer.GetIsHorseRacing() )
  957.             {
  958.                 dirModifier = 2.0;
  959.                 followRoad = true;
  960.                 maxAngleForAdjustingDir = 90.0;
  961.             }
  962.             else
  963.             {
  964.                 dirModifier = 2.0;
  965.                 speed *= speedModifier;
  966.                 maxAngleForAdjustingDir = 15.0;
  967.             }
  968.            
  969.             correctedDirV = VecNormalize2D( inputVector * 0.3 + horseHeadingVec * 0.7 );
  970.         }
  971.         else
  972.         {
  973.             speed = 3.75 * speedModifier;
  974.             dirModifier = 1.5;
  975.             maxAngleForAdjustingDir = 90.0;
  976.            
  977.             correctedDirV = VecNormalize2D( inputVector * 0.4 + horseHeadingVec * 0.6 );
  978.         }
  979.        
  980.         cachedVec = correctedDirV;
  981.        
  982.         desiredDirectionVec = inputVector;
  983.            
  984.         if( followRoad && !thePlayer.GetIsHorseRacing() && roadFollowBlock == 0.0 )
  985.         {
  986.             if( mac.StartRoadFollowing( speed, 45.0, 10.0, correctedDirV ) )
  987.                 isFollowingRoad = true;
  988.             else
  989.                 isFollowingRoad = false;
  990.         }
  991.        
  992.         if( !parent.IsInCustomSpot() )
  993.         {
  994.             if( !isFollowingRoad )
  995.                 mac.AdjustRequestedMovementDirectionNavMesh( correctedDirV, speed, maxAngleForAdjustingDir, 10, 6, desiredDirectionVec );
  996.         }
  997.         else
  998.         {
  999.             if( currSpeed > TROT_SPEED )
  1000.             {
  1001.                 isFollowingRoad = true;
  1002.             }
  1003.         }
  1004.        
  1005.        
  1006.         if( cachedVec == correctedDirV )
  1007.         {
  1008.             correctedDirV = inputVector;
  1009.         }
  1010.        
  1011.         correctedDir = VecHeading( correctedDirV );
  1012.         angleDistance = AngleDistance( currentDir, correctedDir );
  1013.        
  1014.         correctedDir = ClampF( angleDistance * dirModifier, -180, 180 );
  1015.  
  1016.        
  1017.         startPos = parent.GetEntity().GetWorldPosition();
  1018.         endPos = startPos + speed * correctedDirV;
  1019.         ((CActor)parent.GetEntity()).GetVisualDebug().AddArrow( 'correctionLine', startPos, endPos, 1, 0.3, 0.3, true, Color( 255, 255, 255 ), true, 1.0 );
  1020.        
  1021.         return true;
  1022.     }
  1023.    
  1024.     private function ShouldStopBecauseOfCorrection( inputVecInWS : Vector, correctionVec : Vector ) : bool
  1025.     {
  1026.         var angleDistBetwenHorseHeadingAndInput         : float;
  1027.         var angleDistBetwenHorseHeadingAndCorrection    : float;
  1028.         var angleDistBetwenInputAndCorrection           : float;
  1029.         var horseHeading                                : float;
  1030.        
  1031.         horseHeading = parent.GetEntity().GetHeading();
  1032.         angleDistBetwenHorseHeadingAndInput         = AngleDistance( horseHeading, VecHeading(inputVecInWS) );
  1033.         angleDistBetwenHorseHeadingAndCorrection    = AngleDistance( horseHeading, VecHeading(correctionVec) );
  1034.         angleDistBetwenInputAndCorrection           = AngleDistance( VecHeading(inputVecInWS), VecHeading(correctionVec) );
  1035.        
  1036.        
  1037.         if ( AbsF(angleDistBetwenInputAndCorrection) < 10 )
  1038.             return false;
  1039.        
  1040.         if ( AbsF(angleDistBetwenHorseHeadingAndInput) > 45 && ( AbsF(angleDistBetwenHorseHeadingAndCorrection) > 150 || AbsF(angleDistBetwenInputAndCorrection) > 45 ) )
  1041.         {
  1042.             return true;
  1043.         }
  1044.        
  1045.         return false;
  1046.     }
  1047.    
  1048.     const var HEADING_WT : float;
  1049.     const var INPUT_WT : float;
  1050.    
  1051.     default HEADING_WT = 1.0;
  1052.     default INPUT_WT = 0.25;
  1053.    
  1054.    
  1055.    
  1056.  
  1057.  
  1058.  
  1059.    
  1060.     const var NAVDATA_RADIUS : float;
  1061.     const var NAVDATA_LENGTH_MOD_TROT : float;
  1062.     const var NAVDATA_LENGTH_MOD_GALLOP : float;
  1063.     const var NAVDATA_LENGTH_MOD_CANTER : float;
  1064.    
  1065.     default NAVDATA_RADIUS = 2.0;
  1066.     default NAVDATA_LENGTH_MOD_TROT = 5.0;
  1067.     default NAVDATA_LENGTH_MOD_GALLOP = 10.0;
  1068.     default NAVDATA_LENGTH_MOD_CANTER = 15.0;
  1069.    
  1070.     private function PerformNavDataTest() : bool
  1071.     {
  1072.         var startPoint, endPoint : Vector;
  1073.         var initialHeading : Vector;
  1074.         var lengthMod : float;
  1075.        
  1076.         startPoint = parent.GetWorldPosition();
  1077.         initialHeading = parent.GetHeadingVector();
  1078.        
  1079.         if( currSpeed <= TROT_SPEED )
  1080.         {
  1081.             lengthMod = NAVDATA_LENGTH_MOD_TROT;
  1082.         }
  1083.         else if( currSpeed == GALLOP_SPEED )
  1084.         {
  1085.             lengthMod = NAVDATA_LENGTH_MOD_GALLOP;
  1086.         }
  1087.         else
  1088.         {
  1089.             lengthMod = NAVDATA_LENGTH_MOD_CANTER;
  1090.         }
  1091.        
  1092.         endPoint = startPoint + initialHeading * lengthMod;
  1093.        
  1094.         if( theGame.GetWorld().NavigationLineTest( startPoint, endPoint, NAVDATA_RADIUS, false, true ) )
  1095.         {
  1096.             return true;
  1097.         }
  1098.        
  1099.         return false;
  1100.     }
  1101.    
  1102.     const var INCLINATION_MAX_ANGLE : float;
  1103.     const var INCLINATION_BASE_DIST : float;
  1104.     const var INCLINATION_TESTS_COUNT_TROT : int;
  1105.     const var INCLINATION_TESTS_COUNT_GALLOP : int;
  1106.     const var INCLINATION_TESTS_COUNT_CANTER : int;
  1107.     const var INCLINATION_Z_OFFSET : float;
  1108.    
  1109.     default INCLINATION_MAX_ANGLE = 45.0;
  1110.     default INCLINATION_BASE_DIST = 2.0;
  1111.     default INCLINATION_TESTS_COUNT_TROT = 2;
  1112.     default INCLINATION_TESTS_COUNT_GALLOP = 4;
  1113.     default INCLINATION_TESTS_COUNT_CANTER = 6;
  1114.     default INCLINATION_Z_OFFSET = 2.1;
  1115.    
  1116.     private function PerformInclinationTest( stickInputX : float, stickInputY : float ) : bool
  1117.     {
  1118.         var startPoint, rawEndPoint, tempEndPoint : Vector;
  1119.         var linkingStartPoint, linkingEndPoint, linkingTempPoint, normal : Vector;
  1120.         var initialHeading : Vector;
  1121.         var inputVec : Vector;
  1122.         var horseHeadingVec : Vector;
  1123.         var angle : float;
  1124.         var i, iterationsCount : int;
  1125.         var speed : float;
  1126.        
  1127.        
  1128.         startPoint = parent.GetWorldPosition();
  1129.         speed = MaxF( currSpeed, destSpeed );
  1130.        
  1131.         //if( stickInputX || stickInputY )
  1132.         //{
  1133.         //  //inputVec = GetInputVectorInCamSpace( stickInputX, stickInputY );
  1134.         //  inputVec = GetInputVectorInLocalSpace( stickInputX, stickInputY ); //modFriendlyMouseWheel
  1135.         //  horseHeadingVec = parent.GetHeadingVector();
  1136.         //         
  1137.         //  initialHeading = VecNormalize2D( inputVec * 0.5 + horseHeadingVec * 1.0 );
  1138.         //}
  1139.         //else
  1140.         //{
  1141.             initialHeading = parent.GetHeadingVector();
  1142.         //}
  1143.        
  1144.         if( speed <= TROT_SPEED )
  1145.         {
  1146.             iterationsCount = INCLINATION_TESTS_COUNT_TROT;
  1147.         }
  1148.         else if( speed == GALLOP_SPEED )
  1149.         {
  1150.             iterationsCount = INCLINATION_TESTS_COUNT_GALLOP;
  1151.         }
  1152.         else
  1153.         {
  1154.             iterationsCount = INCLINATION_TESTS_COUNT_CANTER;
  1155.         }
  1156.        
  1157.         //if( thePlayer.GetIsHorseRacing() )
  1158.         //{
  1159.             iterationsCount =  (int)( MaxF( 2.0, ( iterationsCount / 2 ) ) );
  1160.         //}
  1161.        
  1162.         for( i = 0; i < iterationsCount; i += 1 )
  1163.         {
  1164.             rawEndPoint = startPoint + initialHeading * INCLINATION_BASE_DIST;
  1165.             angle = GetInclinationBetweenPoints( startPoint, rawEndPoint, tempEndPoint, INCLINATION_Z_OFFSET );
  1166.            
  1167.             if( angle == 180.0 )
  1168.                 return false;
  1169.            
  1170.             //if( i < 2 && !thePlayer.GetIsHorseRacing() )
  1171.             //{
  1172.             //  linkingStartPoint = startPoint;
  1173.             //  linkingStartPoint.Z += 2.35;
  1174.             //  linkingEndPoint = tempEndPoint;
  1175.             //  linkingEndPoint.Z += 0.5;
  1176.             // 
  1177.             //  if( theGame.GetWorld().StaticTrace( linkingStartPoint, linkingEndPoint, linkingTempPoint, normal, inclinationCheckCollisionGroups ) )
  1178.             //      return false;
  1179.             //}
  1180.            
  1181.             if( angle < -INCLINATION_MAX_ANGLE )
  1182.             {
  1183.                
  1184.                 return false;
  1185.             }
  1186.             //else if( angle > INCLINATION_MAX_ANGLE && !thePlayer.GetIsHorseRacing() )
  1187.             //{
  1188.             //  if( currSpeed > TROT_SPEED )
  1189.             //  {
  1190.             //      destSpeed = MinF( currSpeed, TROT_SPEED );
  1191.             //  }
  1192.             //  else
  1193.             //  {
  1194.             //      return false;
  1195.             //  }
  1196.             //}
  1197.            
  1198.             //switch( i )
  1199.             //{
  1200.             //  case 0:
  1201.             //      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c1', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
  1202.             //      break;
  1203.             //  case 1:
  1204.             //      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c2', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
  1205.             //      break;
  1206.             //  case 2:
  1207.             //      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c3', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
  1208.             //      break;
  1209.             //  case 3:
  1210.             //      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c4', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
  1211.             //      break;
  1212.             //  case 4:
  1213.             //      ((CActor)parent.GetEntity()).GetVisualDebug().AddSphere( 'c5', 1, tempEndPoint, true, Color( 255, 1, 0 ), 3.0 );
  1214.             //      break;
  1215.             //  default:
  1216.             //      break;
  1217.             //}
  1218.            
  1219.            
  1220.            
  1221.             startPoint = tempEndPoint;
  1222.         }
  1223.            
  1224.         return true;
  1225.     }
  1226.    
  1227.     private function GetInclinationBetweenPoints( startPoint : Vector, rawEndPoint : Vector, out endPoint : Vector, zOffset : float ) : float
  1228.     {
  1229.        
  1230.         var rawEndPointWithZOffsetUp, rawEndPointWithZOffsetDown, normal : Vector;
  1231.         var heightDiff : float;
  1232.        
  1233.         rawEndPointWithZOffsetUp = rawEndPoint;
  1234.         rawEndPointWithZOffsetUp.Z += zOffset;
  1235.         rawEndPointWithZOffsetDown = rawEndPoint;
  1236.         rawEndPointWithZOffsetDown.Z -= zOffset;
  1237.        
  1238.         if( !theGame.GetWorld().SweepTest( rawEndPointWithZOffsetUp, rawEndPointWithZOffsetDown, 0.05, endPoint, normal, inclinationCheckCollisionGroups ) )
  1239.         {
  1240.             return 180.0;
  1241.         }
  1242.        
  1243.        
  1244.        
  1245.        
  1246.         if( startPoint.Z * endPoint.Z >= 0 )
  1247.         {
  1248.             heightDiff = AbsF( startPoint.Z - endPoint.Z );
  1249.         }
  1250.         else
  1251.         {
  1252.             heightDiff = AbsF( startPoint.Z ) + AbsF( endPoint.Z );
  1253.         }
  1254.        
  1255.         if( startPoint.Z >= endPoint.Z )
  1256.         {
  1257.             return -Rad2Deg( AtanF( heightDiff, INCLINATION_BASE_DIST ) );
  1258.         }
  1259.         else
  1260.         {
  1261.             return Rad2Deg( AtanF( heightDiff, INCLINATION_BASE_DIST ) );
  1262.         }
  1263.     }
  1264.    
  1265.     private function GetLocalInclination( optional inPoint : Vector ) : float
  1266.     {
  1267.         var startPoint, rawEndPoint, tempEndPoint : Vector;
  1268.         var initialHeading : Vector;
  1269.        
  1270.         if( inPoint != Vector( 0, 0, 0 ) )
  1271.             startPoint = inPoint;
  1272.         else
  1273.             startPoint = parent.GetWorldPosition();
  1274.            
  1275.         initialHeading = parent.GetHeadingVector();
  1276.         rawEndPoint = startPoint + initialHeading * 1.5;
  1277.        
  1278.         return GetInclinationBetweenPoints( startPoint, rawEndPoint, tempEndPoint, 2.0 );
  1279.     }
  1280.    
  1281.     const var WATER_MAX_DEPTH : float;
  1282.     const var WATER_DIST_TROT : float;
  1283.     const var WATER_DIST_GALLOP : float;
  1284.     const var WATER_DIST_CANTER : float;
  1285.    
  1286.     default WATER_MAX_DEPTH = 1.75;
  1287.     default WATER_DIST_TROT = 3.0;
  1288.     default WATER_DIST_GALLOP = 8.0;
  1289.     default WATER_DIST_CANTER = 10.0;
  1290.    
  1291.     private function PerformWaterTest( stickInputX : float, stickInputY : float ) : bool
  1292.     {
  1293.         var startPoint, endPoint, cachedEndPoint, bridgeCheckUp, bridgeCheckDown, bridgeCheckOutPoint, normal : Vector;
  1294.         var initialHeading : Vector;
  1295.         var inputVec : Vector;
  1296.         var horseHeadingVec : Vector;
  1297.         var waterDepth : float;
  1298.         var speed : float;
  1299.        
  1300.         startPoint = parent.GetWorldPosition();
  1301.         speed = MaxF( currSpeed, destSpeed );
  1302.        
  1303.         //if( stickInputX || stickInputY )
  1304.         //{
  1305.         //  //inputVec = GetInputVectorInCamSpace( stickInputX, stickInputY );
  1306.         //  inputVec = GetInputVectorInLocalSpace( stickInputX, stickInputY ); //modFriendlyMouseWheel
  1307.         //  horseHeadingVec = parent.GetHeadingVector();
  1308.         //         
  1309.         //  initialHeading = VecNormalize2D( inputVec * 0.5 + horseHeadingVec * 1.0 );
  1310.         //}
  1311.         //else
  1312.         //{
  1313.             initialHeading = parent.GetHeadingVector();
  1314.         //}
  1315.  
  1316.         if( speed <= TROT_SPEED )
  1317.         {
  1318.             endPoint = startPoint + initialHeading * WATER_DIST_TROT;
  1319.             cachedEndPoint = endPoint;
  1320.             endPoint.Z += WATER_DIST_TROT + 1.0;
  1321.         }
  1322.         else if( speed == GALLOP_SPEED )
  1323.         {
  1324.             endPoint = startPoint + initialHeading * WATER_DIST_GALLOP;
  1325.             cachedEndPoint = endPoint;
  1326.             endPoint.Z += WATER_DIST_GALLOP + 1.0;
  1327.         }
  1328.         else
  1329.         {
  1330.             endPoint = startPoint + initialHeading * WATER_DIST_CANTER;
  1331.             cachedEndPoint = endPoint;
  1332.             endPoint.Z += WATER_DIST_CANTER + 1.0;
  1333.         }
  1334.        
  1335.        
  1336.         bridgeCheckUp = cachedEndPoint;
  1337.         bridgeCheckUp.Z += 5.0;
  1338.         bridgeCheckDown = cachedEndPoint;
  1339.         bridgeCheckDown.Z -= 10.0;
  1340.         if( theGame.GetWorld().SweepTest( bridgeCheckUp, bridgeCheckDown, 0.05, bridgeCheckOutPoint, normal, waterCheckCollisionGroups ) )
  1341.         {
  1342.             return true;
  1343.         }
  1344.        
  1345.         waterDepth = theGame.GetWorld().GetWaterDepth( endPoint, true );
  1346.        
  1347.         if( waterDepth < WATER_MAX_DEPTH || waterDepth == 10000.0 )
  1348.         {
  1349.            
  1350.             return true;
  1351.         }
  1352.         else
  1353.         {
  1354.            
  1355.            
  1356.            
  1357.             return false;
  1358.         }
  1359.     }
  1360.    
  1361.  
  1362.  
  1363.  
  1364.  
  1365.     private function PerformWaterJumpTest() : bool
  1366.     {
  1367.         var startPoint, endPoint, endPointWithBuffer, bridgeCheckUp, bridgeCheckDown, bridgeCheckOutPoint, normal : Vector;
  1368.         var initialHeading : Vector;
  1369.         var horseHeadingVec : Vector;
  1370.         var waterDepth : float;
  1371.         var testedPoints : array<Vector>;
  1372.         var i : int;
  1373.        
  1374.         startPoint = parent.GetWorldPosition();
  1375.         initialHeading = parent.GetHeadingVector();
  1376.  
  1377.         if( currSpeed <= TROT_SPEED )
  1378.         {
  1379.             endPoint = startPoint + initialHeading * 5.0;
  1380.             endPointWithBuffer = startPoint + initialHeading * 10.0;
  1381.         }
  1382.         else if( currSpeed == GALLOP_SPEED )
  1383.         {
  1384.             endPoint = startPoint + initialHeading * 8.0;
  1385.             endPointWithBuffer = startPoint + initialHeading * 14.0;
  1386.         }
  1387.         else
  1388.         {
  1389.             endPoint = startPoint + initialHeading * 9.0;
  1390.             endPointWithBuffer = startPoint + initialHeading * 22.0;
  1391.         }
  1392.        
  1393.        
  1394.        
  1395.         testedPoints.PushBack( endPoint );
  1396.         testedPoints.PushBack( endPointWithBuffer );
  1397.        
  1398.         for( i = 0; i < 2; i += 1 )
  1399.         {
  1400.            
  1401.             bridgeCheckUp = testedPoints[i];
  1402.             bridgeCheckUp.Z += 5.0;
  1403.             bridgeCheckDown = testedPoints[i];
  1404.             bridgeCheckDown.Z -= 10.0; 
  1405.             if( !theGame.GetWorld().SweepTest( bridgeCheckUp, bridgeCheckDown, 0.05, bridgeCheckOutPoint, normal, waterCheckCollisionGroups ) )
  1406.             {
  1407.                 waterDepth = theGame.GetWorld().GetWaterDepth( testedPoints[i], true );
  1408.                
  1409.                
  1410.                
  1411.                
  1412.                
  1413.                 if( waterDepth > WATER_MAX_DEPTH && waterDepth != 10000.0 )
  1414.                 {
  1415.                     return false;
  1416.                 }
  1417.             }
  1418.             else
  1419.             {
  1420.                
  1421.                
  1422.             }
  1423.         }
  1424.        
  1425.         return true;
  1426.     }
  1427.    
  1428.     private function PerformFallJumpTest() : bool
  1429.     {
  1430.         var startPoint, endPoint, endPointWithZOffsetUp, endPointWithZOffsetDown, intersectionPoint, tempVector : Vector;
  1431.         var afterLandingEndPoint : Vector;
  1432.         var initialHeading : Vector;
  1433.         var anticipationDist : float;
  1434.         var afterLandingDist : float;
  1435.         var angle : float;
  1436.        
  1437.         startPoint = parent.GetWorldPosition();
  1438.         initialHeading = parent.GetHeadingVector();
  1439.  
  1440.         if( currSpeed <= TROT_SPEED )
  1441.         {
  1442.             anticipationDist = 5.0;
  1443.             afterLandingDist = 4.0;
  1444.         }
  1445.         else if( currSpeed == GALLOP_SPEED )
  1446.         {
  1447.             anticipationDist = 7.0;
  1448.             afterLandingDist = 5.0;
  1449.         }
  1450.         else
  1451.         {
  1452.             anticipationDist = 9.0;
  1453.             afterLandingDist = 6.0;
  1454.         }
  1455.        
  1456.         endPoint = startPoint + initialHeading * anticipationDist;
  1457.        
  1458.        
  1459.         endPointWithZOffsetUp = endPoint;
  1460.         endPointWithZOffsetUp.Z += 10.0;
  1461.         endPointWithZOffsetDown = endPoint;
  1462.        
  1463.         if( theGame.GetWorld().StaticTrace( endPointWithZOffsetUp, endPointWithZOffsetDown, intersectionPoint, tempVector, inclinationCheckCollisionGroups ) )
  1464.         {
  1465.            
  1466.             afterLandingEndPoint = intersectionPoint + initialHeading * afterLandingDist;
  1467.             angle = GetInclinationBetweenPoints( intersectionPoint, afterLandingEndPoint, tempVector, 4.5 );
  1468.            
  1469.            
  1470.            
  1471.            
  1472.            
  1473.             if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE )
  1474.             {
  1475.                 return false;
  1476.             }
  1477.             else
  1478.             {
  1479.                
  1480.                 angle = GetInclinationBetweenPoints( afterLandingEndPoint, afterLandingEndPoint - parent.GetWorldRight()*0.5 , tempVector, 4.5 );
  1481.                 if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE || angle > 90 )
  1482.                 {
  1483.                     return false;
  1484.                 }
  1485.                
  1486.                
  1487.                 angle = GetInclinationBetweenPoints( afterLandingEndPoint, afterLandingEndPoint + parent.GetWorldRight()*0.5 , tempVector, 4.5 );
  1488.                 if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE || angle > 90 )
  1489.                 {
  1490.                     return false;
  1491.                 }
  1492.                
  1493.                
  1494.                 angle = GetLocalInclination( tempVector );
  1495.                 if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE )
  1496.                     return false;
  1497.                 else
  1498.                     return true;
  1499.             }
  1500.         }
  1501.  
  1502.        
  1503.         endPointWithZOffsetUp = endPoint;
  1504.         endPointWithZOffsetDown = startPoint + initialHeading * ( anticipationDist + 4.0 );
  1505.         endPointWithZOffsetDown.Z -= 8.0;
  1506.  
  1507.         if( !theGame.GetWorld().StaticTrace( endPointWithZOffsetUp, endPointWithZOffsetDown, intersectionPoint, tempVector, inclinationCheckCollisionGroups ) )
  1508.         {
  1509.             return false;
  1510.         }
  1511.         else
  1512.         {
  1513.            
  1514.             afterLandingEndPoint = intersectionPoint + initialHeading * afterLandingDist;
  1515.             angle = GetInclinationBetweenPoints( intersectionPoint, afterLandingEndPoint, tempVector, 4.5 );
  1516.            
  1517.            
  1518.            
  1519.             if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE )
  1520.             {
  1521.                 return false;
  1522.             }
  1523.             else   
  1524.             {
  1525.                
  1526.                 angle = GetLocalInclination( tempVector );
  1527.                 if( angle < -INCLINATION_MAX_ANGLE || angle > INCLINATION_MAX_ANGLE )
  1528.                     return false;
  1529.                 else
  1530.                     return true;
  1531.             }
  1532.         }
  1533.        
  1534.         return true;
  1535.     }
  1536.    
  1537.     private function PerformObstructionJumpTest() : bool
  1538.     {
  1539.         var startPoint, endPoint, tempEndPoint, normal : Vector;
  1540.         var initialHeading : Vector;
  1541.  
  1542.         startPoint = parent.GetWorldPosition();
  1543.         initialHeading = parent.GetHeadingVector();
  1544.         endPoint = startPoint + initialHeading * 3.0;
  1545.  
  1546.         startPoint.Z += 1.5;
  1547.         endPoint.Z += 1.5;
  1548.        
  1549.         if( theGame.GetWorld().StaticTrace( startPoint, endPoint, tempEndPoint, normal, inclinationCheckCollisionGroups ) )
  1550.         {
  1551.             return false;
  1552.         }
  1553.  
  1554.         return true;
  1555.     }
  1556.    
  1557.     private function PerformAutoJumpTest( stickInputX : float, stickInputY : float ) : bool
  1558.     {
  1559.         var startPoint : Vector;
  1560.         var testedHeading : Vector;
  1561.         var inputVec : Vector;
  1562.         var horseHeadingVec : Vector;
  1563.         var furthestAccessiblePointForJumpTest : Vector;
  1564.         var angleDistanceBetweenInputAndHorse : float;
  1565.         var angleDistanceBetweenCameraAndHorse : float;
  1566.         var anticipationDist : float;
  1567.         var afterLandingDist : float;
  1568.        
  1569.         startPoint = parent.GetWorldPosition();
  1570.        
  1571.        
  1572.         //if( stickInputX || stickInputY )
  1573.         //{
  1574.         //  //inputVec = GetInputVectorInCamSpace( stickInputX, stickInputY );
  1575.         //  inputVec = GetInputVectorInLocalSpace( stickInputX, stickInputY ); //modFriendlyMouseWheel
  1576.         //  horseHeadingVec = parent.GetHeadingVector();
  1577.         //         
  1578.         //  testedHeading = VecNormalize2D( inputVec * 0.25 + horseHeadingVec * 1.0 );
  1579.         //}
  1580.         //else
  1581.         //{
  1582.             testedHeading = parent.GetHeadingVector();
  1583.         //}
  1584.        
  1585.        
  1586.         if( theInput.IsActionPressed( 'Canter' ) )
  1587.         {
  1588.             if( !LineTest( startPoint, testedHeading, 2.5, 1.0, furthestAccessiblePointForJumpTest, true ) )
  1589.             {
  1590.                 if( SweepTest( startPoint, testedHeading, anticipationDist, 0.9, 0.45 ) )
  1591.                 {
  1592.                     return false;  
  1593.                 }
  1594.                
  1595.                 angleDistanceBetweenInputAndHorse = AbsF( AngleDistance( VecHeading( inputVec ), parent.GetHeading() ) );
  1596.                 angleDistanceBetweenCameraAndHorse = AbsF( AngleDistance( VecHeading( theCamera.GetCameraDirection() ), parent.GetHeading() ) );
  1597.                 if( ( !( stickInputX || stickInputY ) && angleDistanceBetweenCameraAndHorse <= 45 ) || ( ( stickInputX || stickInputY ) && angleDistanceBetweenInputAndHorse <= 45 ) )
  1598.                 {
  1599.                     if( currSpeed == CANTER_SPEED )
  1600.                     {
  1601.                         anticipationDist = 8.0;
  1602.                         afterLandingDist = 4.0;
  1603.                     }
  1604.                     else
  1605.                     {
  1606.                         anticipationDist = 6.5;
  1607.                         afterLandingDist = 3.0;
  1608.                     }
  1609.                    
  1610.                     if( CircleTest( startPoint, testedHeading, anticipationDist, 0.5 ) )
  1611.                     {
  1612.                         if( SweepTest( startPoint, testedHeading, anticipationDist, 2.1, 0.75 ) )
  1613.                         {
  1614.                             if( LineTest( startPoint + testedHeading * anticipationDist, testedHeading, afterLandingDist, 0.0, furthestAccessiblePointForJumpTest ) )
  1615.                             {
  1616.                                 return true;
  1617.                             }
  1618.                         }
  1619.                     }
  1620.                 }
  1621.             }
  1622.         }
  1623.  
  1624.         return false;
  1625.     }
  1626.    
  1627.     //private function GetInputVectorInCamSpace( stickInputX : float, stickInputY : float ) : Vector
  1628.     //{
  1629.     //  var inputVec : Vector;
  1630.     //  var inputHeading : float;
  1631.     // 
  1632.     //  inputVec.X = stickInputX;
  1633.     //  inputVec.Y = stickInputY;
  1634.     //  inputVec = VecNormalize2D(inputVec);
  1635.     //  inputHeading = AngleDistance( theCamera.GetCameraHeading(), -VecHeading( inputVec ) );
  1636.     //  inputVec = VecFromHeading( inputHeading );
  1637.     // 
  1638.     //  return inputVec;
  1639.     //}
  1640.    
  1641.     private function GetInputVectorInLocalSpace( stickInputX : float, stickInputY : float ) : Vector
  1642.     {
  1643.         var inputVec : Vector;
  1644.         var inputHeading : float;
  1645.        
  1646.         inputVec.X = stickInputX;
  1647.         inputVec.Y = stickInputY;
  1648.         inputVec = VecNormalize2D(inputVec);
  1649.         inputHeading = AngleDistance( parent.GetEntity().GetHeading(), -VecHeading( inputVec ) );
  1650.         inputVec = VecFromHeading( inputHeading );
  1651.        
  1652.         return inputVec;
  1653.     }
  1654.    
  1655.    
  1656.  
  1657.            
  1658.    
  1659.     private const var NAVTEST_RADIUS : float;
  1660.    
  1661.     default NAVTEST_RADIUS = 0.2;
  1662.    
  1663.     private function LineTest( startPos : Vector, heading : Vector, anticipationDist : float, speedFactor : float, out furthestAccessiblePoint : Vector, optional sideTests : bool ) : bool
  1664.     {
  1665.         var endPos : Vector;
  1666.         var endPosLeft, endPosRight : Vector;
  1667.        
  1668.         endPos = startPos + heading * anticipationDist + ( parent.GetHeadingVector() * speedFactor * currSpeed );
  1669.                
  1670.         if( theGame.GetWorld().NavigationLineTest( startPos, endPos, NAVTEST_RADIUS, false, true ) )
  1671.         {
  1672.            
  1673.             return true;
  1674.         }
  1675.         else if( sideTests )
  1676.         {
  1677.            
  1678.            
  1679.             endPosLeft = startPos + VecRotateAxis( endPos - startPos, Vector( 0, 0, 1 ), Deg2Rad( 30.0 ) );
  1680.             endPosRight = startPos + VecRotateAxis( endPos - startPos, Vector( 0, 0, 1 ), Deg2Rad( -30.0 ) );
  1681.            
  1682.             if( theGame.GetWorld().NavigationLineTest( startPos, endPosLeft, NAVTEST_RADIUS, false, true ) )
  1683.             {
  1684.                
  1685.                 return true;
  1686.             }
  1687.             else if ( theGame.GetWorld().NavigationLineTest( startPos, endPosRight, 0.15, false, true ) )
  1688.             {
  1689.                
  1690.                
  1691.                 return true;
  1692.             }
  1693.             else
  1694.             {
  1695.                
  1696.                
  1697.                 theGame.GetWorld().NavigationClearLineInDirection( startPos, endPos, NAVTEST_RADIUS, furthestAccessiblePoint );
  1698.                 return false;
  1699.             }
  1700.            
  1701.         }
  1702.         else
  1703.         {
  1704.            
  1705.             theGame.GetWorld().NavigationClearLineInDirection( startPos, endPos, NAVTEST_RADIUS, furthestAccessiblePoint );
  1706.             return false;
  1707.         }
  1708.     }
  1709.    
  1710.     private function CircleTest( startPos : Vector, heading : Vector, anticipationDist : float, radius : float ) : bool
  1711.     {
  1712.         var endPos : Vector;
  1713.         var dummyFloat : float;
  1714.    
  1715.         endPos = startPos + heading * anticipationDist;
  1716.        
  1717.        
  1718.        
  1719.        
  1720.         if( theGame.GetWorld().NavigationCircleTest( endPos, radius ) )
  1721.         {
  1722.             if( theGame.GetWorld().NavigationComputeZ( endPos, endPos.Z - 4.0, endPos.Z + 1.0, dummyFloat ) )
  1723.             {
  1724.                 return true;
  1725.             }
  1726.             else
  1727.             {
  1728.                 return false;
  1729.             }
  1730.         }  
  1731.         else
  1732.         {
  1733.             return false;
  1734.         }
  1735.     }
  1736.    
  1737.     private function SweepTest( startPos : Vector, heading : Vector, anticipationDist : float, heightOffset : float, radius : float ) : bool
  1738.     {
  1739.         var endPos, outPos, normal : Vector;
  1740.        
  1741.         endPos = startPos + heading * anticipationDist;
  1742.    
  1743.         startPos.Z += heightOffset;
  1744.         endPos.Z += heightOffset;
  1745.        
  1746.        
  1747.        
  1748.        
  1749.         if( !theGame.GetWorld().SweepTest( startPos, endPos, radius, outPos, normal, inclinationCheckCollisionGroups ) )
  1750.             return true;
  1751.         else
  1752.             return false;
  1753.     }
  1754.    
  1755.    
  1756.    
  1757.    
  1758.    
  1759.     private var rl, fb : float;
  1760.     private final function UpdateLogic( dt : float )
  1761.     {
  1762.         var actorParent : CActor;
  1763.         var player : W3PlayerWitcher;
  1764.         var slidingDisablesControll : bool;
  1765.        
  1766.         if( GetSubmergeDepth() < -2.f || CheckSliding( slidingDisablesControll ) )
  1767.             OnHideHorse();
  1768.        
  1769.         if( roadFollowBlock > 0.0 )
  1770.         {
  1771.             roadFollowBlock -= dt;
  1772.             if( roadFollowBlock < 0.0 )
  1773.                 roadFollowBlock = 0.0;
  1774.         }
  1775.        
  1776.         useSimpleStaminaManagement = parent.ShouldUseSimpleStaminaManagement();
  1777.        
  1778.         if( thePlayer.GetIsMovable() && IsHorseControllable() && !dismountRequest && !slidingDisablesControll )
  1779.         {
  1780.             rl = theInput.GetActionValue( 'GI_AxisLeftX' );
  1781.             fb = theInput.GetActionValue( 'GI_AxisLeftY' );
  1782.         }
  1783.         else
  1784.         {
  1785.             rl = 0.0;
  1786.             fb = 0.0;
  1787.         }
  1788.        
  1789.         parent.inputApplied = rl || fb;
  1790.        
  1791.         SetTimeoutForCurrentSpeed();
  1792.         MaintainCameraVariables( dt );
  1793.         MaintainGrassCollider();
  1794.        
  1795.         //if( ( !useSimpleStaminaManagement && destSpeed > GALLOP_SPEED ) || ( !IsSpeedLocked() && destSpeed > MIN_SPEED && !rl && !fb ) || ( !IsSpeedLocked() && destSpeed > TROT_SPEED ) )
  1796.         if( !IsSpeedLocked() && destSpeed > MIN_SPEED && theInput.GetActionValue( 'GI_AxisLeftY' ) <= 0 ) //modFriendlyMouseWheel
  1797.         {
  1798.             if( maintainSpeedTimer > speedTimeoutValue )
  1799.             {
  1800.                 //destSpeed = MaxF( MIN_SPEED, destSpeed - 1.f );
  1801.                 destSpeed = DecreaseSpeedOneLevel( destSpeed ); //modFriendlyMouseWheel
  1802.                 maintainSpeedTimer = 0.0;
  1803.             }
  1804.             else
  1805.             {
  1806.                 maintainSpeedTimer += dt;
  1807.             }
  1808.         }
  1809.        
  1810.         actorParent = (CActor)parent.GetEntity();
  1811.        
  1812.         if ( useSimpleStaminaManagement && currSpeed > GALLOP_SPEED /*&& !isFollowingRoad*/ )
  1813.         {
  1814.             actorParent.DrainStamina( ESAT_FixedValue, 3.33f*dt, 1.f, '', 0.f, 1.f );
  1815.            
  1816.             if ( actorParent.GetStat( BCS_Stamina ) <= 0.f )
  1817.             {
  1818.                 staminaBreak = true;
  1819.                 staminaCooldownTimer = 0.f;
  1820.                 theGame.VibrateControllerVeryLight();  
  1821.             }
  1822.         }
  1823.        
  1824.         //destSpeed = MinF( destSpeed, speedRestriction );
  1825.         //
  1826.         //if( currSpeed > destSpeed && currSpeed < GALLOP_SPEED )
  1827.         //  PlayVoicesetSlowerHorse();
  1828.        
  1829.         //modFriendlyMouseWheel begin
  1830.         if( speedRestriction < destSpeed )
  1831.         {
  1832.             destSpeed = speedRestriction;
  1833.         }
  1834.         //modFriendlyMouseWheel end
  1835.        
  1836.         ProcessControlInput( rl, fb, dt, /*parent.IsControllableInLocalSpace() || parent.riderSharedParams.mountStatus == VMS_mountInProgress*/ true ); //modFriendlyMouseWheel
  1837.  
  1838.         // START modRoachNeverStops
  1839.         /*if( !PerformNavDataTest() && !isInJumpAnim )
  1840.         {
  1841.             if( PerformInclinationTest( rl, fb ) && PerformWaterTest( rl, fb ) )
  1842.             {
  1843.                 ToggleSpeedLock( 'OnNavStop', false );
  1844.                
  1845.                 if( PerformAutoJumpTest( rl, fb ) )
  1846.                 {
  1847.                     Jump();
  1848.                 }
  1849.             }
  1850.             else if( !isFollowingRoad && !parent.ShouldIgnoreTests() )
  1851.             {
  1852.                 destSpeed = MIN_SPEED;
  1853.                 ToggleSpeedLock( 'OnNavStop', true );
  1854.                 if( !isRefusingToGo && parent.isInIdle && CanPlayCollisionAnim() && ( rl != 0.0 || fb != 0.0 ) )
  1855.                 {
  1856.                     parent.GenerateEvent( 'WallCollision' );
  1857.                     collisionAnimTimestamp = theGame.GetEngineTimeAsSeconds();
  1858.                 }  
  1859.             }
  1860.             else
  1861.             {
  1862.                 ToggleSpeedLock( 'OnNavStop', false );
  1863.             }
  1864.         }
  1865.         else
  1866.         {
  1867.             ToggleSpeedLock( 'OnNavStop', false );
  1868.         }*/
  1869.         ToggleSpeedLock( 'OnNavStop', false );
  1870.         // END modRoachNeverStops
  1871.        
  1872.         if( requestJump )
  1873.         {
  1874.             if( PerformObstructionJumpTest() && PerformWaterJumpTest() && PerformFallJumpTest() )
  1875.             {
  1876.                 Jump();
  1877.             }
  1878.             else
  1879.             {
  1880.                 if( !isRefusingToGo && parent.isInIdle && CanPlayCollisionAnim() )
  1881.                 {
  1882.                     parent.GenerateEvent( 'WallCollision' );
  1883.                     collisionAnimTimestamp = theGame.GetEngineTimeAsSeconds();
  1884.                 }
  1885.                 requestJump = false;
  1886.             }
  1887.         }
  1888.        
  1889.         if( staminaBreak )
  1890.         {
  1891.             if ( staminaCooldownTimer > staminaCooldown )
  1892.             {
  1893.                 staminaBreak = false;
  1894.             }
  1895.            
  1896.             staminaCooldownTimer += dt;
  1897.            
  1898.             currSpeed = MinF( GALLOP_SPEED, currSpeed );
  1899.             destSpeed = currSpeed;
  1900.         }
  1901.        
  1902.        
  1903.         if ( currSpeed != destSpeed )
  1904.         {
  1905.             currSpeed = destSpeed;
  1906.             if ( currSpeed == MIN_SPEED && !parent.isInIdle )
  1907.                 isSlowlyStopping = true;
  1908.             else
  1909.                 isSlowlyStopping = false;
  1910.         }
  1911.        
  1912.         parent.InternalSetSpeedMultiplier( 1.f );
  1913.         parent.InternalSetSpeed( currSpeed );
  1914.        
  1915.        
  1916.         CalculateSoundParameters( dt );
  1917.         thePlayer.SoundParameter( "horse_speed", currSpeedSound, 'head' );
  1918.         actorParent.SoundParameter( "horse_stamina", actorParent.GetStatPercents( BCS_Stamina ) * 100 );
  1919.     }
  1920.    
  1921.     private var startSlidingTimeStamp : float;
  1922.     private var notSlidingTimeStamp : float;
  1923.    
  1924.     private const var SLIDING_MINSLIDINGCOEF        : float;
  1925.     private const var SLIDING_MAXSLIDINTIME         : float;
  1926.     private const var SLIDING_MAXROTATIONSPEED      : float;
  1927.    
  1928.     default SLIDING_MINSLIDINGCOEF      = 0.4f;
  1929.     default SLIDING_MAXSLIDINTIME       = 2.5f;
  1930.     default SLIDING_MAXROTATIONSPEED    = 60.f;
  1931.    
  1932.     private final function CheckSliding( out _slidingDisablesControll : bool ) : bool
  1933.     {
  1934.         var mac : CMovingPhysicalAgentComponent;
  1935.         var movementAdjustor    : CMovementAdjustor;
  1936.         var ticket, emptyTicket : SMovementAdjustmentRequestTicket;
  1937.         var l_sliding, l_onGround : bool;
  1938.         var l_slidingTime, l_slideCoef : float;
  1939.         var l_slideDir : Vector;
  1940.        
  1941.         _slidingDisablesControll = false;
  1942.        
  1943.         mac = (CMovingPhysicalAgentComponent)parentActor.GetMovingAgentComponent();
  1944.        
  1945.         if ( mac )
  1946.         {
  1947.             l_sliding = mac.IsSliding();
  1948.             l_onGround = mac.IsOnGround();
  1949.            
  1950.             if ( l_sliding || ( !l_onGround && !isInJumpAnim ) )
  1951.             {
  1952.                 notSlidingTimeStamp = -1.f;
  1953.                
  1954.                 if ( startSlidingTimeStamp <= 0.f )
  1955.                     startSlidingTimeStamp = theGame.GetEngineTimeAsSeconds();
  1956.                
  1957.                 if ( l_sliding )
  1958.                 {
  1959.                     l_slideDir = mac.GetSlideDir();
  1960.                     l_slideCoef = mac.GetSlideCoef();
  1961.                    
  1962.                    
  1963.                    
  1964.                     LogChannel('HorseSliding',"Sliding Coef: " + l_slideCoef );
  1965.                     movementAdjustor = mac.GetMovementAdjustor();
  1966.                     ticket = movementAdjustor.GetRequest('HorseSliding');
  1967.                     if ( ticket == emptyTicket )
  1968.                         ticket = movementAdjustor.CreateNewRequest('HorseSliding');
  1969.                     movementAdjustor.MaxRotationAdjustmentSpeed( ticket,SLIDING_MAXROTATIONSPEED );
  1970.                     movementAdjustor.RotateTo(ticket,VecHeading( l_slideDir ) );
  1971.                     _slidingDisablesControll = true;
  1972.                 }
  1973.                
  1974.                 l_slidingTime = theGame.GetEngineTimeAsSeconds() - startSlidingTimeStamp;
  1975.                
  1976.                 if ( l_slidingTime >= SLIDING_MAXSLIDINTIME && l_slideCoef >= SLIDING_MINSLIDINGCOEF  )
  1977.                 {
  1978.                     LogChannel('HideHorse',"Hide reason: slidingTime: " + l_slidingTime + " and slideCoef: " + l_slideCoef);
  1979.                     return true;
  1980.                 }
  1981.             }
  1982.             else
  1983.             {
  1984.                 movementAdjustor = mac.GetMovementAdjustor();
  1985.                 movementAdjustor.CancelByName('HorseSliding');
  1986.                 mac.SetEnabledFeetIK( true, 0.5 );
  1987.                 if ( notSlidingTimeStamp <= 0 )
  1988.                     notSlidingTimeStamp = theGame.GetEngineTimeAsSeconds();
  1989.                
  1990.                
  1991.                 if ( theGame.GetEngineTimeAsSeconds() - notSlidingTimeStamp >= 0.5 )
  1992.                 {
  1993.                     if ( startSlidingTimeStamp > 0.f )
  1994.                     {
  1995.                         l_slidingTime = theGame.GetEngineTimeAsSeconds() - startSlidingTimeStamp;
  1996.                         LogChannel('HorseSliding',"Sliding Stopped. Slide time: " + l_slidingTime );
  1997.                     }
  1998.                     startSlidingTimeStamp = -1.f;
  1999.                 }
  2000.             }
  2001.         }
  2002.        
  2003.         return false;
  2004.     }
  2005.    
  2006.    
  2007.    
  2008.    
  2009.    
  2010.    
  2011.     private var requestJump     : bool;
  2012.     private var isInJumpAnim    : bool;
  2013.    
  2014.     private final function Jump()
  2015.     {
  2016.         if( !((CActor)parent.GetEntity()).IsInAir() )
  2017.         {
  2018.             parent.GenerateEvent( 'jump' );
  2019.         }
  2020.        
  2021.         requestJump = false;
  2022.     }
  2023.    
  2024.     event OnBehJumpStarted()
  2025.     {
  2026.         var horse : CActor;
  2027.         horse = (CActor)parent.GetEntity();
  2028.        
  2029.         isInJumpAnim = true;
  2030.         requestJump = false;
  2031.         startTestingLanding = false;
  2032.         jumpStartPos = parent.GetEntity().GetWorldPosition();
  2033.        
  2034.         parent.SetVariable( 'onGround', 0.f );
  2035.        
  2036.         horse.AddAnimEventChildCallback(parent,'Jumping','OnAnimEvent_Jumping');
  2037.         ((CMovingPhysicalAgentComponent)horse.GetMovingAgentComponent()).SetAnimatedMovement( true );
  2038.         horse.SetIsInAir(true);
  2039.        
  2040.         parent.userCombatManager.OnAirBorn();
  2041.         theGame.CreateNoSaveLock( 'horse_in_air', noSaveLock );
  2042.        
  2043.         theGame.GetGuiManager().DisableHudHoldIndicator(); 
  2044.     }
  2045.    
  2046.     event OnBehJumpEnded()
  2047.     {
  2048.         var horse : CActor;
  2049.         horse = (CActor)parent.GetEntity();
  2050.        
  2051.         horse.RemoveAnimEventChildCallback(parent,'Jumping');
  2052.        
  2053.         isInJumpAnim = false;
  2054.         theGame.ReleaseNoSaveLock( noSaveLock );
  2055.         if ( parent.user == thePlayer )
  2056.             theGame.GetGuiManager().EnableHudHoldIndicator(IK_Pad_B_CIRCLE, IK_None, "panel_input_action_horsedismount", 0.4, 'HorseDismount');
  2057.     }
  2058.    
  2059.     event OnHideHorse()
  2060.     {
  2061.         parent.OnHideHorse();
  2062.     }
  2063.    
  2064.     event OnKillHorse()
  2065.     {
  2066.         parent.OnKillHorse();
  2067.     }
  2068.    
  2069.     private var startTestingLanding : bool;
  2070.    
  2071.     event OnAnimEvent_Jumping( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  2072.     {
  2073.         var mac : CMovingPhysicalAgentComponent;
  2074.         if( animEventType == AET_DurationStart )
  2075.         {
  2076.             startTestingLanding = true;
  2077.         }
  2078.         else
  2079.         {
  2080.             mac = (CMovingPhysicalAgentComponent)((CActor)parent.GetEntity()).GetMovingAgentComponent();
  2081.             if( mac.IsOnGround() )
  2082.                 OnHitGround();
  2083.         }
  2084.     }
  2085.    
  2086.     event OnHitGround()
  2087.     {
  2088.         var horse : CActor;
  2089.         horse = (CActor)parent.GetEntity();
  2090.        
  2091.         if( horse.IsInAir() && startTestingLanding )
  2092.         {
  2093.             jumpEndPos = parent.GetEntity().GetWorldPosition();
  2094.            
  2095.             if( parent.CanTakeDamageFromFalling() )
  2096.             {
  2097.                 ((CGameplayEntity)parent.GetEntity()).OnDamageFromFalling( parent, 0.0, -(jumpStartPos.Z - jumpEndPos.Z) + 5.0 );
  2098.             }
  2099.             else
  2100.             {
  2101.                 parent.SetCanTakeDamageFromFalling( true );
  2102.             }
  2103.  
  2104.             EndJump();
  2105.            
  2106.             theGame.VibrateControllerLight();  
  2107.             if ( parent.user == thePlayer )
  2108.                 theGame.GetGuiManager().EnableHudHoldIndicator(IK_Pad_B_CIRCLE, IK_None, "panel_input_action_horsedismount", 0.4, 'HorseDismount');
  2109.         }
  2110.     }
  2111.  
  2112.     function EndJump()
  2113.     {
  2114.         var horse : CActor;
  2115.         horse = (CActor) parent.GetEntity();
  2116.  
  2117.         if ( horse && horse.IsInAir() )
  2118.         {
  2119.             parent.SetVariable( 'onGround', 1.f );
  2120.  
  2121.             ((CMovingPhysicalAgentComponent)horse.GetMovingAgentComponent()).SetAnimatedMovement( false );
  2122.             horse.SetIsInAir( false );
  2123.            
  2124.             parent.userCombatManager.OnLanded();
  2125.         }
  2126.     }
  2127.    
  2128.     event OnCheckHorseJump()
  2129.     {
  2130.         return isInJumpAnim;
  2131.     }
  2132.    
  2133.    
  2134.    
  2135.    
  2136.    
  2137.     private var maintainSpeedTimer : float;
  2138.     private var speedTimeoutValue : float;
  2139.     private var accelerateTimestamp : float;
  2140.     private const var DOUBLE_TAP_WINDOW : float;
  2141.    
  2142.     default DOUBLE_TAP_WINDOW = 0.4;
  2143.    
  2144.     private function CanCanter() : bool
  2145.     {
  2146.         // Horse Gallop In Cities: remove the speed limit in cities
  2147.         return true;
  2148.        
  2149.         // The original code:
  2150.         /*
  2151.         return ( thePlayer.m_SettlementBlockCanter < 1 ) || ( thePlayer.GetIsHorseRacing() ); // #B shouldn't be also here speedRestriction <= CANTER_SPEED ?
  2152.         */
  2153.     }
  2154.    
  2155.     //modFriendlyMouseWheel begin
  2156.     private var usedMouseWheel : bool; default usedMouseWheel = false;
  2157.    
  2158.     event OnHorseSpeedChange( action : SInputAction )
  2159.     {
  2160.         var tolerance : float = 2.5f;
  2161.        
  2162.         usedMouseWheel = false;
  2163.        
  2164.         if(IsHorseControllable() && !dismountRequest && !speedLocks.Contains('OnGallop') && !speedLocks.Contains('OnStop'))
  2165.         {
  2166.             if(action.value < -tolerance) //slow down
  2167.             {
  2168.                 if(currSpeed > MIN_SPEED) //the horse is moving
  2169.                 {
  2170.                     if(currSpeed < WALK_SPEED) //go to stop
  2171.                     {
  2172.                         if(theInput.GetActionValue('GI_AxisLeftY') <= 0)
  2173.                         {
  2174.                             destSpeed = MIN_SPEED;
  2175.                         }
  2176.                     }
  2177.                     else if(currSpeed < GALLOP_SPEED)
  2178.                     {
  2179.                         horseSpeedLevel = Clamp(horseSpeedLevel - 1, 1, 3);
  2180.                         destSpeed = GetHorseSpeedFromSpeedLevel(horseSpeedLevel);
  2181.                     }
  2182.                     else
  2183.                     {
  2184.                         destSpeed = DecreaseSpeedOneLevel(currSpeed);
  2185.                     }
  2186.                     destSpeed = MinF(destSpeed, speedRestriction);
  2187.                     if(currSpeed > destSpeed)
  2188.                     {
  2189.                         usedMouseWheel = true;
  2190.                     }
  2191.                 }
  2192.             }
  2193.             else if(action.value > tolerance) //speed up
  2194.             {
  2195.                 if(currSpeed < speedRestriction) //not at the max speed yet
  2196.                 {
  2197.                     if(currSpeed < SLOW_SPEED) //standing still
  2198.                     {
  2199.                         //destSpeed = SLOW_SPEED;
  2200.                     }
  2201.                     else if(currSpeed < TROT_SPEED)
  2202.                     {
  2203.                         horseSpeedLevel = Clamp(horseSpeedLevel + 1, 1, 3);
  2204.                         destSpeed = GetHorseSpeedFromSpeedLevel(horseSpeedLevel);
  2205.                     }
  2206.                     else
  2207.                     {
  2208.                         destSpeed = IncreaseSpeedOneLevel(currSpeed);
  2209.                         if(destSpeed > GALLOP_SPEED)
  2210.                         {
  2211.                             if(staminaBreak || !CanCanter())
  2212.                             {
  2213.                                 destSpeed = GALLOP_SPEED;
  2214.                             }
  2215.                         }
  2216.                     }
  2217.                     destSpeed = MinF(destSpeed, speedRestriction);
  2218.                     if(currSpeed < destSpeed)
  2219.                     {
  2220.                         usedMouseWheel = true;
  2221.                     }
  2222.                 }
  2223.             }
  2224.         }
  2225.     }
  2226.     //modFriendlyMouseWheel end
  2227.    
  2228.    
  2229.     event OnSpeedPress( action : SInputAction )
  2230.     {
  2231.         var actorParent : CActor;
  2232.        
  2233.         if( IsHorseControllable() && !dismountRequest && thePlayer.IsActionAllowed( EIAB_Movement ) )
  2234.         {
  2235.             if( IsPressed( action ) )          
  2236.             {
  2237.                
  2238.                 if( accelerateTimestamp + DOUBLE_TAP_WINDOW >= theGame.GetEngineTimeAsSeconds() )
  2239.                 {
  2240.                     triedDoubleTap = true;
  2241.                 }
  2242.                 else
  2243.                 {
  2244.                     triedDoubleTap = false;
  2245.                 }
  2246.                
  2247.                 if(CanCanter() && (!IsSpeedLocked() || speedLocks.Contains( 'OnAttack' )) )
  2248.                 {
  2249.                     if( currSpeed >= CANTER_SPEED )
  2250.                     {
  2251.                         destSpeed = CANTER_SPEED;
  2252.                         ToggleSpeedLock( 'OnGallop', true );
  2253.                     }
  2254.                     else if(triedDoubleTap)
  2255.                     {
  2256.                         triedDoubleTap = false; //modFriendlyMouseWheel
  2257.                        
  2258.                         destSpeed = CANTER_SPEED;
  2259.                        
  2260.                         SpursKick();
  2261.                        
  2262.                         if( useSimpleStaminaManagement )
  2263.                             ToggleSpeedLock( 'OnGallop', true );
  2264.                     }
  2265.                    
  2266.                     if( !FactsDoesExist("debug_fact_stamina_pony") && !useSimpleStaminaManagement )
  2267.                     {
  2268.                         if( destSpeed > GALLOP_SPEED )
  2269.                         {
  2270.                             actorParent = (CActor)parent.GetEntity();
  2271.                             actorParent.DrainStamina( ESAT_Sprint, 0.f, speedTimeoutValue );
  2272.                            
  2273.                             if( actorParent.GetStat( BCS_Stamina ) < 0.1f )
  2274.                             {
  2275.                                 staminaBreak = true;
  2276.                                 staminaCooldownTimer = 0.f;
  2277.                             }
  2278.                         }
  2279.                     }
  2280.                 }
  2281.                
  2282.                 accelerateTimestamp = theGame.GetEngineTimeAsSeconds();
  2283.                 maintainSpeedTimer = 0.f;              
  2284.             }          
  2285.             else if( IsReleased( action ) )
  2286.             {
  2287.                 //shouldGoToCanterAfterStop = false; //never set to true anywhere
  2288.                 ToggleSpeedLock( 'OnGallop', false );
  2289.             }
  2290.         }
  2291.     }
  2292.    
  2293.    
  2294.     event OnSpeedHold( action : SInputAction )
  2295.     {
  2296.         var horseCompToFollow : W3HorseComponent;
  2297.  
  2298.         thePlayer.SetBehaviorVariable( 'playerWouldLikeToMove', 1.0f );
  2299.        
  2300.         if( IsHorseControllable() && IsPressed( action ) && !dismountRequest )
  2301.         {  
  2302.             if ( !IsSpeedLocked() && OnCanCanter() )
  2303.             {
  2304.                
  2305.                 GallopPressed();
  2306.                 SpursKick();
  2307.             }
  2308.         }
  2309.         else if( IsReleased( action ) )
  2310.         {
  2311.             ToggleSpeedLock( 'OnGallop', false );
  2312.         }
  2313.        
  2314.        
  2315.         if( triedDoubleTap && !CanCanter() && IsPressed( action ) )
  2316.         {
  2317.             thePlayer.DisplayActionDisallowedHudMessage( EIAB_Undefined, , thePlayer.m_SettlementBlockCanter >= 1 );
  2318.         }
  2319.     }
  2320.    
  2321.     event OnDecelerate( action : SInputAction )
  2322.     {
  2323.         if( IsReleased( action ) )
  2324.         {
  2325.             if( IsHorseControllable() && !IsRiderInCombatAction() && !dismountRequest )
  2326.             {
  2327.                 if( currSpeed == MIN_SPEED )
  2328.                 {
  2329.                     parent.GenerateEvent( 'rearing' );
  2330.                 }
  2331.             }
  2332.         }
  2333.     }
  2334.    
  2335.     event OnStop( action : SInputAction )
  2336.     {
  2337.         if( IsPressed( action ) && IsHorseControllable() && !dismountRequest )
  2338.         {
  2339.             destSpeed = MIN_SPEED;
  2340.             ToggleSpeedLock( 'OnStop', true );
  2341.            
  2342.             if(ShouldProcessTutorial('TutorialHorseStop'))
  2343.             {
  2344.                 FactsAdd("tut_horse_stopping");
  2345.             }
  2346.         }
  2347.         else if( IsReleased( action ) )
  2348.         {
  2349.             ToggleSpeedLock( 'OnStop', false );
  2350.             parent.InternalSetDirection( 0.f );
  2351.             if(ShouldProcessTutorial('TutorialHorseStop'))
  2352.             {
  2353.                 FactsRemove("tut_horse_stopping");
  2354.             }
  2355.         }
  2356.     }
  2357.    
  2358.     private var jumpPressTimestamp : float;
  2359.    
  2360.     event OnHorseJump( action : SInputAction )
  2361.     {
  2362.         var dummyParameter : Vector;
  2363.        
  2364.         if ( IsPressed( action ) )
  2365.             jumpPressTimestamp = theGame.GetEngineTimeAsSeconds();
  2366.        
  2367.         if ( thePlayer.playerAiming.GetCurrentStateName() == 'Aiming' )
  2368.             return false;
  2369.        
  2370.         if( IsHorseControllable() && !IsRiderInCombatAction() && parent.IsFullyMounted() && parent.GetPanicPercent() < 0.99 )
  2371.         {
  2372.             if( !dismountRequest && IsReleased( action ) && ( jumpPressTimestamp + 0.2 > theGame.GetEngineTimeAsSeconds() )&& thePlayer.GetIsMovable() && !isInJumpAnim )
  2373.             {
  2374.                 requestJump = true;
  2375.                
  2376.             }
  2377.         }
  2378.     }
  2379.        
  2380.     event OnHorseDismountKeyboard( action : SInputAction )
  2381.     {
  2382.         if( IsPressed( action ) )
  2383.         {
  2384.             if( !DismountHorse() )
  2385.             {
  2386.                 theInput.ForceDeactivateAction('HorseJump');
  2387.             }
  2388.             else
  2389.             {
  2390.                 theGame.GetGuiManager().DisableHudHoldIndicator();
  2391.             }
  2392.         }
  2393.     }
  2394.    
  2395.     event OnHorseDismount()
  2396.     {
  2397.         if( !DismountHorse() )
  2398.         {
  2399.             theInput.ForceDeactivateAction('HorseJump');
  2400.         }
  2401.         else
  2402.         {
  2403.             theGame.GetGuiManager().DisableHudHoldIndicator();
  2404.         }
  2405.     }
  2406.    
  2407.     private function DismountHorse() : bool
  2408.     {
  2409.         if ( thePlayer.IsActionAllowed( EIAB_DismountVehicle ) && !IsRiderInCombatAction() && !isInJumpAnim && !dismountRequest && parent.canDismount && !parent.IsInHorseAction() )
  2410.         {
  2411.             SetupDismount();
  2412.             return true;
  2413.         }
  2414.         return false;
  2415.     }
  2416.    
  2417.     event OnSmartDismount()
  2418.     {
  2419.         SetupDismount();
  2420.     }
  2421.    
  2422.     public function SetupDismount()
  2423.     {
  2424.         if( ( currSpeed == MIN_SPEED && !isSlowlyStopping ) || isStopping )
  2425.         {
  2426.             OnForceStop();
  2427.             parent.user.SetBehaviorVariable('dismountType',0.f);
  2428.         }
  2429.         else if( currSpeed >= GALLOP_SPEED && VecLength2D( GetHorseVelocity() ) > 6.0 )
  2430.         {
  2431.             parent.user.SetBehaviorVariable('dismountType',2.f);
  2432.             destSpeed = GALLOP_SPEED;
  2433.         }
  2434.         else
  2435.         {
  2436.             parent.user.SetBehaviorVariable('dismountType',1.f);
  2437.             destSpeed = TROT_SPEED;
  2438.         }
  2439.        
  2440.         if( !isStopping )
  2441.             parent.IssueCommandToDismount( DT_normal );
  2442.        
  2443.         dismountRequest = true;
  2444.     }
  2445.    
  2446.    
  2447.    
  2448.    
  2449.    
  2450.     private function IsRiderInCombatAction() : bool
  2451.     {
  2452.         return parent.userCombatManager.IsInCombatAction();
  2453.     }
  2454.    
  2455.     private final function UpdateDebugGUI()
  2456.     {
  2457.         var p : float;
  2458.         var text : string;
  2459.         var rot : EulerAngles;
  2460.        
  2461.         var actorParent : CActor;
  2462.        
  2463.         rot = parent.GetWorldRotation();
  2464.        
  2465.         p = currSpeed / 2.f;
  2466.         text = "Speed: " + currSpeed;
  2467.        
  2468.         thePlayer.GetVisualDebug().AddBarColorAreas( 'horseSpeed', 50, 50, 250, 50, p, text );
  2469.        
  2470.         thePlayer.GetVisualDebug().AddBar( 'horseStamina', 305, 50, 25, 50, 1.f, Color(0,0,0) );
  2471.        
  2472.         actorParent = (CActor)parent.GetEntity();
  2473.         if ( !staminaBreak )
  2474.         {
  2475.             text = "Stamina: " + actorParent.GetStat( BCS_Stamina );
  2476.         }
  2477.         else
  2478.         {
  2479.             text = "Stamina: " + actorParent.GetStat( BCS_Stamina ) + " <break>";
  2480.         }
  2481.         p = actorParent.GetStatPercents( BCS_Stamina );
  2482.         thePlayer.GetVisualDebug().AddBarColorSmooth( 'horseStaminaBar', 50, 110, 280, 30, p, Color(255,255,0), text );
  2483.        
  2484.         text = "Panic: " + actorParent.GetStat( BCS_Panic ) + " / " + actorParent.GetStatMax( BCS_Panic );
  2485.         p = actorParent.GetStatPercents( BCS_Panic );
  2486.         thePlayer.GetVisualDebug().AddBarColorAreas( 'horsePanic', 50, 150, 280, 30, p, text );
  2487.        
  2488.         text = "pitch: " + rot.Pitch;
  2489.         thePlayer.GetVisualDebug().AddBarColorSmooth( 'pitch', 50, 180, 280, 30, 0, Color(0,255,0), text );
  2490.     }
  2491.    
  2492.     private function SetTimeoutForCurrentSpeed()
  2493.     {
  2494.         //switch( currSpeed )
  2495.         //{
  2496.         //  case CANTER_SPEED:
  2497.         //  {
  2498.         //      if( thePlayer.IsInCombat() )
  2499.         //          speedTimeoutValue = 2.0;
  2500.         //      else
  2501.         //          speedTimeoutValue = 0.5;
  2502.         //      break;
  2503.         //  }
  2504.         //  case GALLOP_SPEED:
  2505.         //  {
  2506.         //      if( thePlayer.IsInCombat() )
  2507.         //          speedTimeoutValue = 2.0;
  2508.         //      else
  2509.         //          speedTimeoutValue = 0.5;
  2510.         //      break;
  2511.         //  }
  2512.         //  case TROT_SPEED:
  2513.         //      if ( dismountRequest )
  2514.         //          speedTimeoutValue = 0.5;
  2515.         //      else
  2516.         //          speedTimeoutValue = 0.0;
  2517.         //      break;
  2518.         // 
  2519.         //  case WALK_SPEED:
  2520.         //      if ( dismountRequest )
  2521.         //          speedTimeoutValue = 0.5;
  2522.         //      else
  2523.         //          speedTimeoutValue = 0.0;
  2524.         //      break;
  2525.         //     
  2526.         //  case SLOW_SPEED:
  2527.         //      if ( dismountRequest )
  2528.         //          speedTimeoutValue = 0.5;
  2529.         //      else
  2530.         //          speedTimeoutValue = 0.0;
  2531.         //      break;
  2532.         //     
  2533.         //  case MIN_SPEED:
  2534.         //      speedTimeoutValue = 0.0;
  2535.         //      break;
  2536.         //}
  2537.         //modFriendlyMouseWheel begin
  2538.         if( currSpeed < CANTER_SPEED && dismountRequest )
  2539.             speedTimeoutValue = 0.5;
  2540.         else if( currSpeed > TROT_SPEED )
  2541.             speedTimeoutValue = 1.5;
  2542.         else
  2543.             speedTimeoutValue = 2.0;
  2544.         //modFriendlyMouseWheel end
  2545.     }
  2546.    
  2547.     private function IsHorseControllable() : bool
  2548.     {
  2549.         var actor : CActor;
  2550.        
  2551.         actor = (CActor)parent.GetEntity();
  2552.        
  2553.         return actor && actor.GetBaseAttitudeGroup() != 'animals_peacefull' && parent.controllable;
  2554.     }
  2555.    
  2556.     private function MaintainCameraVariables( dt : float )
  2557.     {
  2558.         if( currSpeed == CANTER_SPEED )
  2559.         {
  2560.             parent.inCanter = true;
  2561.             parent.inGallop = false;
  2562.         }
  2563.         else if( currSpeed == GALLOP_SPEED )
  2564.         {
  2565.             parent.inGallop = true;
  2566.             parent.inCanter = false;
  2567.         }
  2568.         else
  2569.         {
  2570.             parent.inCanter = false;
  2571.             parent.inGallop = false;
  2572.         }
  2573.     }
  2574.    
  2575.     private function MaintainGrassCollider()
  2576.     {
  2577.         if( !grassCollider )
  2578.             return;
  2579.            
  2580.         if( currSpeed == CANTER_SPEED )
  2581.         {
  2582.             grassCollider.SetPosition( Vector( 1.5, -0.3, 0.0, 1.0 ) );
  2583.         }
  2584.         else if( currSpeed == GALLOP_SPEED )
  2585.         {
  2586.             grassCollider.SetPosition( Vector( 1.1, -0.3, 0.0, 1.0 ) );
  2587.         }
  2588.         else
  2589.         {
  2590.             grassCollider.SetPosition( Vector( 0.7, -0.3, 0.0, 1.0 ) );
  2591.         }
  2592.     }
  2593.    
  2594.     private function GallopPressed()
  2595.     {
  2596.         if( OnCanCanter() )
  2597.         {
  2598.             if( currSpeed < GALLOP_SPEED && destSpeed != CANTER_SPEED )
  2599.                 destSpeed = GALLOP_SPEED;
  2600.            
  2601.             ToggleSpeedLock( 'OnGallop', true );
  2602.         }
  2603.     }
  2604.    
  2605.     private function SpursKick()
  2606.     {
  2607.         if( !IsRiderInCombatAction() && currSpeed < destSpeed )
  2608.         {
  2609.             //if( currSpeed != GALLOP_SPEED )
  2610.             //{
  2611.                 //PlayVoicesetFasterHorse();
  2612.                
  2613.                 //if( destSpeed == CANTER_SPEED )
  2614.                 if( destSpeed > GALLOP_SPEED )
  2615.                 {
  2616.                     parent.GenerateEvent( 'spursKickHard' );
  2617.                     //theGame.witcherLog.AddMessage("spursKickHard");
  2618.                 }
  2619.                 else
  2620.                 {
  2621.                     parent.GenerateEvent( 'spursKick' );
  2622.                     //theGame.witcherLog.AddMessage("spursKick");
  2623.                 }
  2624.             //}
  2625.         }
  2626.     }
  2627.    
  2628.     private var voicsetTimeStamp : float;
  2629.     private var voicsetFasterTimeStamp : float;
  2630.     private var voicsetSlowerTimeSTamp : float;
  2631.    
  2632.     private const var VOICESET_COOLDOWN         : float; default VOICESET_COOLDOWN          = 2.0;
  2633.     private const var VOICESET_FASTER_COOLDOWN  : float; default VOICESET_FASTER_COOLDOWN   = 5.0;
  2634.     private const var VOICESET_SLOWER_COOLDOWN  : float; default VOICESET_SLOWER_COOLDOWN   = 5.0;
  2635.    
  2636.     private function PlayVoicesetFasterHorse()
  2637.     {/*
  2638.         var currentTime : float = theGame.GetEngineTimeAsSeconds();
  2639.        
  2640.         if( thePlayer.IsInGameplayScene() )
  2641.         {
  2642.             return;
  2643.         }
  2644.        
  2645.         if ( CanPlayVoiceset(currentTime) && voicsetFasterTimeStamp + VOICESET_FASTER_COOLDOWN <= currentTime && RandRange(100) < 25 )
  2646.         {
  2647.             if ( parent.IsPlayerHorse() )
  2648.                 thePlayer.PlayVoiceset( 100,'FasterHorseRoach' );
  2649.             else
  2650.                 thePlayer.PlayVoiceset( 100,'FasterHorse' );
  2651.            
  2652.             voicsetFasterTimeStamp = currentTime;
  2653.             voicsetTimeStamp = currentTime;
  2654.         }*/
  2655.     }
  2656.    
  2657.     private function PlayVoicesetSlowerHorse()
  2658.     {/*
  2659.         var currentTime : float = theGame.GetEngineTimeAsSeconds();
  2660.        
  2661.         if( thePlayer.IsInGameplayScene() )
  2662.         {
  2663.             return;
  2664.         }
  2665.        
  2666.         if ( CanPlayVoiceset(currentTime) && voicsetSlowerTimeSTamp + VOICESET_SLOWER_COOLDOWN <= currentTime && RandRange(100) < 25 )
  2667.         {
  2668.             if ( parent.IsPlayerHorse() )
  2669.                 thePlayer.PlayVoiceset( 100,'SlowerHorseRoach' );
  2670.             else
  2671.                 thePlayer.PlayVoiceset( 100,'SlowerHorse' );
  2672.            
  2673.             voicsetSlowerTimeSTamp = currentTime;
  2674.             voicsetTimeStamp = currentTime;
  2675.         }*/
  2676.     }
  2677.    
  2678.     private function CanPlayVoiceset( _currentTime : float ) : bool
  2679.     {
  2680.         return ( parent.user == GetWitcherPlayer() ) && !dismountRequest && thePlayer.IsUsingHorse() && !thePlayer.IsThreatened() && !thePlayer.IsSpeaking() && (voicsetTimeStamp + VOICESET_COOLDOWN <= _currentTime );
  2681.     }
  2682.    
  2683.     private function GetHorseVelocity() : Vector
  2684.     {
  2685.         return ((CActor)parent.GetEntity()).GetMovingAgentComponent().GetVelocity();
  2686.     }
  2687.    
  2688.     private function GetSubmergeDepth() : float
  2689.     {
  2690.         return ((CMovingPhysicalAgentComponent)((CActor)parent.GetEntity()).GetMovingAgentComponent()).GetSubmergeDepth();
  2691.     }
  2692.    
  2693.     private function IsHorseOnNavMesh() : bool
  2694.     {
  2695.         return ((CMovingPhysicalAgentComponent)((CActor)parent.GetEntity()).GetMovingAgentComponent()).IsOnNavigableSpace();
  2696.     }
  2697.    
  2698.     private function InitCollisionGroups()
  2699.     {
  2700.         inclinationCheckCollisionGroups.PushBack( 'Terrain' );
  2701.         inclinationCheckCollisionGroups.PushBack( 'Static' );
  2702.         inclinationCheckCollisionGroups.PushBack( 'Destructible' );
  2703.         inclinationCheckCollisionGroups.PushBack( 'Door' );
  2704.        
  2705.         waterCheckCollisionGroups.PushBack( 'Static' );
  2706.         waterCheckCollisionGroups.PushBack( 'Destructible' );
  2707.     }
  2708.    
  2709.     private function CalculateSoundParameters( dt : float )
  2710.     {
  2711.         if( desiredSpeedSound != currSpeed )
  2712.         {
  2713.             desiredSpeedSound = currSpeed;
  2714.         }
  2715.        
  2716.         currSpeedSound = InterpTo_F( currSpeedSound, desiredSpeedSound, dt, 2.0 );
  2717.     }
  2718.    
  2719.     private function ResetSoundParameters()
  2720.     {
  2721.         currSpeedSound = 0.0;
  2722.         desiredSpeedSound = 0.0;
  2723.     }
  2724. }
  2725.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement