Guest User

Untitled

a guest
Jun 10th, 2018
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 438.10 KB | None | 0 0
  1. statemachine abstract import class CR4Player extends CPlayer
  2. {
  3. public saved var newCraftables : array<name>;
  4. //---=== modFriendlyHUD ===---
  5.  
  6. // PC Controls
  7. private var pcMode : bool; // MS: Use control/camera modifications for keyboard/mouse
  8. default pcMode = true;
  9.  
  10. // COMBAT MECHANICS
  11. protected saved var weaponHolster : WeaponHolster; // Makes Geralt holster and unholster the swords
  12. public var rangedWeapon : Crossbow; // Handles ranged weapons
  13. public var crossbowDontPopStateHack : bool; default crossbowDontPopStateHack = false;
  14.  
  15. private var hitReactTransScale : float; //dynamic scale for npc's hitreaction animation translation to force CloseCombat
  16.  
  17. private var bIsCombatActionAllowed : bool;
  18. private var currentCombatAction : EBufferActionType;
  19.  
  20. private var uninterruptedHitsCount : int; //amount of uninterrupted hints performed by the player (gets reset when we get hit or stop attacking etc.)
  21. private var uninterruptedHitsCameraStarted : bool; //set to true once we enable the uninterrupted hits camera effect
  22. private var uninterruptedHitsCurrentCameraEffect : name; //currently used camera blurr effect for uninterrupted hits
  23.  
  24. private var counterTimestamps : array<EngineTime>; //times when player pressed counter attack button - we check it later to prevent spamming
  25.  
  26. private var hitReactionEffect : bool; //blurr
  27.  
  28. private var lookAtPosition : Vector; //Position that Geralt is looking at, also where he will shoot
  29. private var orientationTarget : EOrientationTarget;
  30. private var customOrientationTarget : EOrientationTarget;
  31. protected var customOrientationStack : array<SCustomOrientationParams>;
  32.  
  33. public var delayOrientationChange : bool;
  34. protected var delayCameraOrientationChange : bool;
  35. private var actionType : int; // 0 = sign, 1 = guard, 2 = specialAttack, 3 = throwItem
  36. private var customOrientationStackIndex : int; //Used by Player only: will disable the previous combat action's orientation target and add to the stack everytime he performs a new combat action
  37.  
  38. private var emptyMoveTargetTimer : float;
  39.  
  40. private var onlyOneEnemyLeft : bool;
  41.  
  42. public var isInFinisher : bool;
  43. private var finisherTarget : CGameplayEntity;
  44.  
  45. private var combatStance : EPlayerCombatStance;
  46.  
  47. public var approachAttack : int; //Enable/Disable approach attack prototype, 0 = enabled, 1 = disabled with no far attack limit, 2 = disabled with far attack limit
  48. default approachAttack = 1;
  49. protected var specialAttackCamera : bool;
  50.  
  51. private var specialAttackTimeRatio : float;
  52.  
  53. public saved var itemsPerLevel : array<name>;
  54. public var itemsPerLevelGiven : array<bool>;
  55.  
  56. private var playerTickTimerPhase : int;
  57. default playerTickTimerPhase = 0;
  58.  
  59. protected var evadeHeading : float;
  60.  
  61. public var vehicleCbtMgrAiming : bool; //MS: hack variable to pass vehicleCbtMgr aiming variable to UseGenericVehicle
  62.  
  63. public var specialHeavyChargeDuration : float; //duration of charge-up event
  64. public var specialHeavyStartEngineTime : EngineTime; //timestamp of when the charge-up started
  65. public var playedSpecialAttackMissingResourceSound : bool; //if missing resource sound was played or not (used in loop)
  66. public function SetPlayedSpecialAttackMissingResourceSound(b : bool) {playedSpecialAttackMissingResourceSound = b;}
  67.  
  68. public var counterCollisionGroupNames : array<name>;
  69.  
  70. public saved var lastInstantKillTime : GameTime;
  71.  
  72. // Save locks
  73. private var noSaveLockCombatActionName : string; default noSaveLockCombatActionName = 'combat_action';
  74. private var noSaveLockCombatAction : int;
  75. private var deathNoSaveLock : int;
  76. private var noSaveLock : int;
  77.  
  78. //new game plus
  79. protected saved var newGamePlusInitialized : bool;
  80. default newGamePlusInitialized = false;
  81.  
  82. // action buffer
  83. protected var BufferAllSteps : bool;
  84. protected var BufferCombatAction : EBufferActionType;
  85. protected var BufferButtonStage : EButtonStage;
  86.  
  87. default BufferAllSteps = false;
  88. default customOrientationTarget = OT_None;
  89. default hitReactionEffect = true;
  90. default uninterruptedHitsCount = 0;
  91. default uninterruptedHitsCameraStarted = false;
  92. default customOrientationStackIndex = -1;
  93.  
  94. // CRITICAL STATES
  95. private var keepRequestingCriticalAnimStart : bool; //set to true while we are trying to start critical anim
  96.  
  97. default keepRequestingCriticalAnimStart = false;
  98.  
  99. // EXPLORATION
  100. private var currentCustomAction : EPlayerExplorationAction;
  101. public var substateManager : CExplorationStateManager;
  102. protected var isOnBoat : bool; //set to true if player is on boat (but not necessarily sailing, but e.g. standing)
  103. protected var isInShallowWater : bool;
  104. public var medallion : W3MedallionFX;
  105. protected var lastMedallionEffect : float;
  106. private var isInRunAnimation : bool;
  107. public var interiorTracker :CPlayerInteriorTracker;
  108. public var m_SettlementBlockCanter : int;
  109.  
  110. // FISTFIGHT MINIGAME
  111. private var fistFightMinigameEnabled : bool;
  112. private var isFFMinigameToTheDeath : bool;
  113. private var FFMinigameEndsithBS : bool;
  114. public var fistFightTeleportNode : CNode;
  115. public var isStartingFistFightMinigame : bool;
  116. public var GeraltMaxHealth : float;
  117. public var fistsItems : array< SItemUniqueId >;
  118.  
  119. default FFMinigameEndsithBS = false;
  120. default fistFightMinigameEnabled = false;
  121. default isFFMinigameToTheDeath = false;
  122.  
  123. // GWINT MINIGAME
  124. private var gwintAiDifficulty : EGwintDifficultyMode; default gwintAiDifficulty = EGDM_Easy;
  125. private var gwintAiAggression : EGwintAggressionMode; default gwintAiAggression = EGAM_Defensive;
  126. private var gwintMinigameState : EMinigameState; default gwintMinigameState = EMS_None;
  127.  
  128. // HORSE
  129. import private var horseWithInventory : EntityHandle; // if spawned handle is valid ( horse with inventory )
  130. private var currentlyMountedHorse : CNewNPC;
  131. private var horseSummonTimeStamp : float;
  132. private saved var isHorseRacing : bool;
  133. private var horseCombatSlowMo : bool;
  134. default isHorseRacing = false;
  135. default horseCombatSlowMo = true;
  136.  
  137. // HUD FIXME - shouldn't this all be in hud / ui rather than player?
  138. private var HudMessages : array <string>; //#B change to struct with message type, message duration etc
  139. protected var fShowToLowStaminaIndication : float;
  140. public var showTooLowAdrenaline : bool;
  141. private var HAXE3Container : W3Container; //#B temp for E3
  142. private var HAXE3bAutoLoot: bool; //#B temp for E3
  143. private var bShowHud : bool;
  144. private var dodgeFeedbackTarget : CActor;
  145.  
  146. default HAXE3bAutoLoot = false;
  147. default fShowToLowStaminaIndication = 0.0f;
  148. default bShowHud = true;
  149.  
  150. saved var displayedQuestsGUID : array< CGUID >; // #B moved here because saved in journal doesn't work.
  151. saved var rewardsMultiplier : array< SRewardMultiplier >; // #B moved here because saved in journal doesn't work.s
  152. saved var glossaryImageOverride : array< SGlossaryImageOverride >; // #B moved here because saved in journal doesn't work.s
  153.  
  154. // INPUT
  155. private var prevRawLeftJoyRot : float;
  156. protected var explorationInputContext : name;
  157. protected var combatInputContext : name;
  158. protected var combatFistsInputContext : name;
  159.  
  160. // INTERACTIONS
  161. private var isInsideInteraction : bool; //set to true when player is inside any interaction range, used to prioritize input
  162. private var isInsideHorseInteraction : bool;
  163. public var horseInteractionSource : CEntity;
  164. public var nearbyLockedContainersNoKey : array<W3LockableEntity>; //to update tooltip if player is close to a locked container and is THEN given a key
  165.  
  166. // MOVEMENT
  167. private var bMoveTargetChangeAllowed : bool; default bMoveTargetChangeAllowed = true;
  168. private var moveAdj : CMovementAdjustor;
  169. private var defaultLocomotionController : CR4LocomotionPlayerControllerScript;
  170. //private var isFollowing : bool;
  171. //private var followingStartTime : float;
  172. private var canFollowNpc : bool;
  173. private var actorToFollow : CActor;
  174. public var terrainPitch : float;
  175. public var steepSlopeNormalPitch : float; default steepSlopeNormalPitch = 65.f;
  176. public var disableSprintTerrainPitch : float; default disableSprintTerrainPitch = 54.f;
  177. private var submergeDepth : float;
  178.  
  179. private var m_useSelectedItemIfSpawned : bool; default m_useSelectedItemIfSpawned = false; // Used only in WaitForItemSpawnAndProccesTask
  180.  
  181.  
  182. var navQuery : CNavigationReachabilityQueryInterface;
  183.  
  184. // BARBER
  185. public saved var rememberedCustomHead : name;
  186.  
  187. // EPISODE1
  188. public saved var proudWalk : bool;
  189. private var etherealCount : int;
  190. default etherealCount = 0;
  191.  
  192. // PHANTOM WEAPON
  193. private var phantomWeaponMgr : CPhantomWeaponManager;
  194.  
  195. public var ic : icControl;
  196. public editable var mMeditation : CMeditationUI;
  197. private var slowMoActive : bool;
  198. public var motionSicknessFocusMode : bool;
  199. public var runningLanding : float;
  200. public var sprintSpeed : float;
  201.  
  202. public saved var icHBDepthAdj : float;
  203. public saved var icHBOffsetAdj : float;
  204. public saved var icHBHeightAdj : float;
  205. private saved var icComOffsetAdj : float;
  206. private saved var icComDepthAdj : float;
  207. private saved var icComHeightAdj : float;
  208.  
  209. //(headtracking controls)
  210. private var lookTarget : CActor;
  211. private var savedTarget : CActor;
  212. private var nextlooktime : float;
  213. private var nextchecktime : float;
  214. private var potentiallookattargets : array<CActor>;
  215.  
  216. // (camera control functions)
  217. private function DecreaseOffset() { icOffsetAdj -= 0.02; }
  218. private function IncreaseOffset() { icOffsetAdj += 0.02; }
  219. private function DecreaseDepth() { icDepthAdj -= 0.02; }
  220. private function IncreaseDepth() { icDepthAdj += 0.02; }
  221. private function DecreaseHeight() { icHeightAdj -= 0.02; }
  222. private function IncreaseHeight() { icHeightAdj += 0.02; }
  223. public function DecreaseHBOffset() { icHBOffsetAdj -= 0.01; }
  224. public function IncreaseHBOffset() { icHBOffsetAdj += 0.01; }
  225. public function DecreaseHBDepth() { icHBDepthAdj -= 0.01; }
  226. public function IncreaseHBDepth() { icHBDepthAdj += 0.01; }
  227. public function DecreaseHBHeight() { icHBHeightAdj -= 0.01; }
  228. public function IncreaseHBHeight() { icHBHeightAdj += 0.01; }
  229. private function DecreaseComOffset() { icComOffsetAdj -= 0.05; }
  230. private function IncreaseComOffset() { icComOffsetAdj += 0.05; }
  231. private function DecreaseComDepth() { icComDepthAdj -= 0.05; }
  232. private function IncreaseComDepth() { icComDepthAdj += 0.05; }
  233. private function DecreaseComHeight() { icComHeightAdj -= 0.05; }
  234. private function IncreaseComHeight() { icComHeightAdj += 0.05; }
  235.  
  236. public function ResetExpCam() { icOffsetAdj = 0; icDepthAdj = 0; icHeightAdj = 0;}
  237. public function ResetHBCam() { icHBOffsetAdj = 0; icHBDepthAdj = 0; icHBHeightAdj = 0;}
  238. public function ResetComCam() { icComOffsetAdj = 0; icComDepthAdj = 0; icComHeightAdj = 0;}
  239.  
  240. public function SetExpCam()
  241. {
  242. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsExploration', 'expOffset', FloatToString( ic.expOffset + icOffsetAdj ) );
  243. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsExploration', 'expDepth', FloatToString( ic.expDepth + icDepthAdj ) );
  244. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsExploration', 'expHeight', FloatToString( ic.expHeight + icHeightAdj ) );
  245. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsWS', 'eWSOffset', FloatToString( ic.eWSOffset + icOffsetAdj ) );
  246. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsWS', 'eWSDepth', FloatToString( ic.eWSDepth + icDepthAdj ) );
  247. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsWS', 'eWSHeight', FloatToString( ic.eWSHeight + icHeightAdj ) );
  248. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsExploration', 'expOffset', FloatToString( ic.expOffset + icOffsetAdj ) );
  249. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsExploration', 'expDepth', FloatToString( ic.expDepth + icDepthAdj ) );
  250. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsExploration', 'expHeight', FloatToString( ic.expHeight + icHeightAdj ) );
  251. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsWS', 'eWSOffset', FloatToString( ic.eWSOffset + icOffsetAdj ) );
  252. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsWS', 'eWSDepth', FloatToString( ic.eWSDepth + icDepthAdj ) );
  253. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsWS', 'eWSHeight', FloatToString( ic.eWSHeight + icHeightAdj ) );
  254.  
  255. ResetExpCam();
  256. ic.SetImmCamVars();
  257. thePlayer.DisplayHudMessage("default exploration camera position set");
  258. }
  259.  
  260. public function SetHBCam()
  261. {
  262. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsHorse', 'hbOffset', FloatToString( ic.hbOffset + icHBOffsetAdj ) );
  263. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsHorse', 'hbDepth', FloatToString( ic.hbDepth + icHBDepthAdj ) );
  264. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsHorse', 'hbHeight', FloatToString( ic.hbHeight + icHBHeightAdj ) );
  265. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsHorse', 'hbOffset', FloatToString( ic.hbOffset + icHBOffsetAdj ) );
  266. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsHorse', 'hbDepth', FloatToString( ic.hbDepth + icHBDepthAdj ) );
  267. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsHorse', 'hbHeight', FloatToString( ic.hbHeight + icHBHeightAdj ) );
  268.  
  269. ResetHBCam();
  270. ic.SetImmCamVars();
  271. thePlayer.DisplayHudMessage("default horseback camera position set");
  272. }
  273.  
  274. public function SetComCam()
  275. {
  276. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsCombat', 'comOffset', FloatToString( ic.comOffset + icComOffsetAdj ) );
  277. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsCombat', 'comDepth', FloatToString( ic.comDepth + icComDepthAdj ) );
  278. theGame.GetInGameConfigWrapper().SetVarValue( 'ImmersiveCamPositionsCombat', 'comHeight', FloatToString( ic.comHeight + icComHeightAdj ) );
  279. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsCombat', 'comOffset', FloatToString( ic.comOffset + icComOffsetAdj ) );
  280. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsCombat', 'comDepth', FloatToString( ic.comDepth + icComDepthAdj ) );
  281. theGame.GetGuiManager().GetInGameConfigBufferedWrapper().SetVarValue( 'ImmersiveCamPositionsCombat', 'comHeight', FloatToString( ic.comHeight + icComHeightAdj ) );
  282.  
  283. ResetComCam();
  284. ic.SetImmCamVars();
  285. thePlayer.DisplayHudMessage("default combat camera position set");
  286. }
  287.  
  288. timer function SetImmCamVars(dt : float, id : int)
  289. {
  290. ic.SetImmCamVars();
  291. }
  292.  
  293. public function EnableMotionSicknessFocusMode( active : bool )
  294. {
  295. motionSicknessFocusMode = active;
  296. }
  297.  
  298. // (meditation functions)
  299. public function getMeditation() : CMeditationUI
  300. {
  301. return this.mMeditation;
  302. }
  303.  
  304. public function setMeditation( mMeditation : CMeditationUI)
  305. {
  306. this.mMeditation = mMeditation;
  307. }
  308.  
  309. timer function BeginNewMeditation(dt : float, id : int)
  310. {
  311. this.mMeditation.NewMeditate();
  312. }
  313.  
  314. public function UpdateCameraMeditation( out moveData : SCameraMovementData, timeDelta : float )
  315. {
  316. theGame.GetGameCamera().ChangePivotRotationController( 'ExplorationInterior' );
  317. theGame.GetGameCamera().ChangePivotDistanceController( 'Default' );
  318. theGame.GetGameCamera().ChangePivotPositionController( 'Default' );
  319.  
  320. // HACK
  321. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  322. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  323. moveData.pivotPositionController = theGame.GetGameCamera().GetActivePivotPositionController();
  324. // END HACK
  325.  
  326. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition(), 15.f );
  327.  
  328. moveData.pivotDistanceController.SetDesiredDistance( 3.0 );
  329. moveData.pivotPositionController.offsetZ = 0.3f;
  330.  
  331. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( ic.medOffset , ic.medDepth, ic.medHeight ), 0.6, timeDelta );
  332. }
  333.  
  334. // (headtracking functions)
  335. public function ProcessHeadTracking()
  336. {
  337. var lookDistance : float;
  338. var i : int;
  339. var curtime : float;
  340. var npccount : int;
  341.  
  342. curtime = theGame.GetEngineTimeAsSeconds();
  343.  
  344. if ( !ic.headTracking )
  345. return;
  346.  
  347. if ( IsInInterior() )
  348. lookDistance = ic.intHTDis;
  349. else
  350. lookDistance = ic.extHTDis;
  351.  
  352. if( curtime > nextchecktime )
  353. {
  354. potentiallookattargets = GetActorsInRange(thePlayer, lookDistance, , ,0);
  355. for(i = 0; i < potentiallookattargets.Size(); i += 1)
  356. {
  357. if ( (CNewNPC)potentiallookattargets[i] )
  358. {
  359. lookTarget = potentiallookattargets[i];
  360. npccount = 1;
  361. break;
  362. }
  363. else
  364. npccount = 0;
  365. }
  366. if ( npccount )
  367. {
  368. if ( lookTarget != savedTarget )
  369. {
  370. ((CActor)thePlayer).DisableLookAt();
  371. ((CActor)thePlayer).EnableDynamicLookAt(lookTarget, 2.0);
  372. nextlooktime = theGame.GetEngineTimeAsSeconds() + 2.75;
  373. savedTarget = lookTarget;
  374. }
  375. else if( curtime >= nextlooktime)
  376. {
  377. ((CActor)thePlayer).DisableLookAt();
  378. ((CActor)thePlayer).EnableDynamicLookAt(lookTarget, 10.0);
  379. nextlooktime = theGame.GetEngineTimeAsSeconds() + 12.0;
  380. }
  381. }
  382. else
  383. nextchecktime = theGame.GetEngineTimeAsSeconds() + 0.1;
  384. }
  385.  
  386. }
  387.  
  388. public function DisableHeadTracking()
  389. {
  390. ((CActor)thePlayer).DisableLookAt();
  391. }
  392.  
  393. // (slow mo camera functions)
  394. public function SetSlowMoActive( active : bool )
  395. {
  396. slowMoActive = active;
  397. }
  398.  
  399. public function IsSlowMoActive() : bool
  400. {
  401. return slowMoActive;
  402. }
  403.  
  404. public timer function DeactivateSlowMoCam(dt : float, id : int)
  405. {
  406. ic.SlowMoController(false);
  407. slowMoActive = false;
  408. }
  409.  
  410. event OnStopTimeSlow(duration : float, id : Int32)
  411. {
  412. theGame.RemoveTimeScale(theGame.GetTimescaleSource(7));
  413. slowMoActive = false;
  414. }
  415.  
  416. // (immersive motion functions)
  417. private timer function DeactivateRunningLanding(dt: float, id: int)
  418. {
  419. runningLanding = 0;
  420. }
  421.  
  422. public function EnableRunningLanding(rlSpeed : float, time : float)
  423. {
  424. if( runningLanding == 0)
  425. {
  426. runningLanding = rlSpeed;
  427. AddTimer('DeactivateRunningLanding', time, false);
  428. }
  429. }
  430.  
  431. var slowStartID : int; default slowStartID = -1;
  432. var slowStartActive : bool;
  433.  
  434. private timer function RemoveStartSlow( dt: float, id: int )
  435. {
  436. ResetAnimationSpeedMultiplier(slowStartID);
  437. slowStartID = SetAnimationSpeedMultiplier(0.9);
  438. AddTimer( 'RemoveStartSlow2', 1.0, false );
  439. }
  440.  
  441. private timer function RemoveStartSlow2( dt: float, id: int )
  442. {
  443. ResetAnimationSpeedMultiplier(slowStartID);
  444. slowStartActive = false;
  445. }
  446.  
  447. public function StartSlow()
  448. {
  449. if( !slowStartActive )
  450. {
  451. slowStartActive = true;
  452. slowStartID = SetAnimationSpeedMultiplier(0.8);
  453. AddTimer( 'RemoveStartSlow', 1.0, false );
  454. }
  455. }
  456.  
  457. public function SetSprintSpeed( speed : float )
  458. {
  459. sprintSpeed = speed;
  460. }
  461. // ImmersiveCam--
  462.  
  463. function EnablePCMode( flag : bool )
  464. {
  465. pcMode = flag;
  466. }
  467.  
  468. public function IsPCModeEnabled() : bool
  469. {
  470. return pcMode && theInput.LastUsedPCInput();
  471. }
  472.  
  473. public function ShouldUsePCModeTargeting() : bool
  474. {
  475. return IsPCModeEnabled() && !lastAxisInputIsMovement;
  476. }
  477.  
  478. public function SetDodgeFeedbackTarget( target : CActor )
  479. {
  480. dodgeFeedbackTarget = target;
  481. }
  482.  
  483. public function GetDodgeFeedbackTarget() : CActor
  484. {
  485. return dodgeFeedbackTarget;
  486. }
  487.  
  488. public function SetSubmergeDepth( depth : float )
  489. {
  490. submergeDepth = depth;
  491. }
  492.  
  493. public function GetSubmergeDepth() : float
  494. {
  495. return submergeDepth;
  496. }
  497.  
  498. // ONELINERS
  499. editable var delayBetweenIllusionOneliners : float;
  500.  
  501. hint delayBetweenIllusionOneliners = "delay in secs between oneliners about illusionary objects";
  502.  
  503. default delayBetweenIllusionOneliners = 5;
  504.  
  505. // Battlecry
  506. private var battlecry_timeForNext : float;
  507. private var battlecry_delayMin : float; default battlecry_delayMin = 15;
  508. private var battlecry_delayMax : float; default battlecry_delayMax = 60;
  509. private var battlecry_lastTry : name;
  510.  
  511. // Weather
  512. private var previousWeather : name;
  513. private var previousRainStrength : float;
  514.  
  515. //OTHER
  516. protected var receivedDamageInCombat : bool; //set when you got hit
  517. protected var prevDayNightIsNight : bool; //Day-Night cycle check - value of previous check
  518. public var failedFundamentalsFirstAchievementCondition : bool; //achievement
  519.  
  520. private var spawnedTime : float;
  521.  
  522. public var currentMonsterHuntInvestigationArea : W3MonsterHuntInvestigationArea;
  523.  
  524. private var isPerformingPhaseChangeAnimation : bool; // flag for suppressing game camera update during synced animation in eredin fight
  525. default isPerformingPhaseChangeAnimation = false;
  526.  
  527. default receivedDamageInCombat = false;
  528.  
  529. // PLAYER MODE
  530. public var playerMode : W3PlayerMode;
  531.  
  532. // QUICKSLOTS
  533. protected saved var selectedItemId : SItemUniqueId; //id of item selected from quickslots
  534. protected saved var blockedRadialSlots : array < SRadialSlotDef >; // radial menu slots blocked by different sources
  535.  
  536. // SOFT LOCK TARGETING
  537. public var enemyCollectionDist : float;
  538. public var findMoveTargetDistMin : float; //distance from player to get softlocked targets
  539. public var findMoveTargetDistMax : float; //distance from player that target gets disengaged from soft lock
  540. private var findMoveTargetScaledFrame : float; //xaxis scale to find non-hostile targets when stationary
  541. public var interactDist : float; //distance from player to attack or interact with a non-hostile npc
  542. protected var bCanFindTarget : bool;
  543. private var bIsConfirmingEmptyTarget : bool;
  544. private var displayTarget : CGameplayEntity; //entity to show health bar on hud;
  545. private var isShootingFriendly : bool;
  546.  
  547. default findMoveTargetDistMax = 18.f;
  548. default findMoveTargetScaledFrame = 0.5f;
  549. default interactDist = 3.5f;
  550.  
  551. //Target Selection
  552. private var currentSelectedTarget : CActor;
  553. private var selectedTargetToConfirm : CActor;
  554. private var bConfirmTargetTimerIsEnabled : bool;
  555.  
  556. // THROWABLES
  557. public saved var thrownEntityHandle : EntityHandle; //entity of currently thrown item (in aiming)
  558. private var isThrowingItemWithAim : bool;
  559. private saved var isThrowingItem : bool; //used for aim mode to check if we're in throwing logic
  560. private var isThrowHoldPressed : bool;
  561.  
  562. // CROSSBOW
  563. private var isAimingCrossbow : bool;
  564.  
  565. default isThrowingItemWithAim = false;
  566.  
  567. // AIMING MODE
  568. public var playerAiming : PlayerAiming;
  569.  
  570. // DISMEMBERMENT
  571. public var forceDismember : bool;
  572. public var forceDismemberName : name;
  573. public var forceDismemberChance : int;
  574. public var forceDismemberExplosion : bool;
  575.  
  576. // FINISHER
  577. private var finisherVictim : CActor;
  578. public var forceFinisher : bool;
  579. public var forceFinisherAnimName : name;
  580. public var forceFinisherChance : int;
  581. public var forcedStance : bool;
  582.  
  583. // WEAPON COLLISION FX
  584. private var m_WeaponFXCollisionGroupNames : array <name>;
  585. private var m_CollisionEffect : CEntity;
  586. private var m_LastWeaponTipPos : Vector;
  587. private var m_CollisionFxTemplate : CEntityTemplate;
  588. private var m_RefreshWeaponFXType : bool;
  589. private var m_PlayWoodenFX : bool;
  590.  
  591. // POSTERS
  592. private var m_activePoster : W3Poster;
  593.  
  594. public function SetActivePoster ( poster : W3Poster )
  595. {
  596. m_activePoster = poster;
  597. }
  598.  
  599. public function RemoveActivePoster ()
  600. {
  601. m_activePoster = NULL;
  602. }
  603.  
  604. public function GetActivePoster () : W3Poster
  605. {
  606. return m_activePoster;
  607. }
  608. // SAVE / LOAD
  609. //private saved var safePositionStored: bool; default safePositionStored = false;
  610. //private saved var lastSafePosition : Vector;
  611. //private saved var lastSafeRotation : EulerAngles;
  612.  
  613. public var horseOnNavMesh : bool;
  614. default horseOnNavMesh = true;
  615.  
  616. public function SetHorseNav( val : bool ) { horseOnNavMesh = val; }
  617.  
  618. // TEST
  619. public var testAdjustRequestedMovementDirection : bool; // TEST
  620. default testAdjustRequestedMovementDirection = false;
  621.  
  622. // State
  623. default autoState = 'Exploration';
  624.  
  625. ///////////////////////////////////////////////////////////////////////////
  626. /////////////////// IMPORTED C++ FUNCTIONS //////////////////////////////
  627. ///////////////////////////////////////////////////////////////////////////
  628.  
  629. // All following functions give cached data from previous frame
  630. import final function GetEnemiesInRange( out enemies : array< CActor > );
  631. import final function GetVisibleEnemies( out enemies : array< CActor > );
  632. import final function IsEnemyVisible( enemy : CActor ) : bool;
  633.  
  634. // Set this up in order to use above functions and get the proper data
  635. import final function SetupEnemiesCollection( range, heightTolerance : float,
  636. maxEnemies : int,
  637. optional tag : name,
  638. optional flags : int ); // please combine EScriptQueryFlags - FLAG_ExcludePlayer is always on
  639.  
  640. import final function IsInInterior() : bool;
  641. import final function IsInSettlement() : bool;
  642. import final function EnterSettlement( isEntering : bool );
  643. import final function ActionDirectControl( controller : CR4LocomotionDirectController ) : bool;
  644. import final function SetPlayerTarget( target : CActor );
  645. import final function SetPlayerCombatTarget( target : CActor );
  646. import final function ObtainTicketFromCombatTarget( ticketName : CName, ticketsCount : int );
  647. import final function FreeTicketAtCombatTarget();
  648. import final function SetScriptMoveTarget( target : CActor );
  649. import final function GetRiderData() : CAIStorageRiderData;
  650. import final function SetIsInCombat( inCombat : bool );
  651. import final function SaveLastMountedHorse( mountedHorse : CActor );
  652.  
  653. import final function SetBacklightFromHealth( healthPercentage : float );
  654. import private final function SetBacklightColor( color : Vector );
  655.  
  656. import final function GetCombatDataComponent() : CCombatDataComponent;
  657.  
  658. import final function GetTemplatePathAndAppearance( out templatePath : string, out appearance : name );
  659.  
  660. import final function HACK_BoatDismountPositionCorrection( slotPos : Vector );
  661.  
  662. import final function HACK_ForceGetBonePosition( boneIndex : int ) : Vector;
  663.  
  664.  
  665. public function GetLevel() : int
  666. {
  667. return 0;
  668. }
  669.  
  670. ///////////////////////////////////////////////////////////////////////////
  671. // (new) targeting
  672.  
  673. var targeting : CR4PlayerTargeting;
  674. var targetingPrecalcs : SR4PlayerTargetingPrecalcs;
  675. var targetingIn : SR4PlayerTargetingIn;
  676. var targetingOut : SR4PlayerTargetingOut;
  677. var useNativeTargeting : bool;
  678. default useNativeTargeting = true;
  679.  
  680. var visibleActors : array< CActor >;
  681. var visibleActorsTime : array< float >;
  682.  
  683. ///////////////////////////////////////////////////////////////////////////
  684.  
  685. event OnSpawned( spawnData : SEntitySpawnData )
  686. {
  687. var atts : array<name>;
  688. var skill : ESkill;
  689. var i : int;
  690. var item : SItemUniqueId;
  691.  
  692. //---=== modFriendlyHUD ===---
  693. fHUDConfig = new CModFriendlyHUDConfig in this;
  694. fHUDConfig.Init();
  695. //---=== modFriendlyHUD ===---
  696.  
  697. AddAnimEventCallback('ThrowHoldTest', 'OnAnimEvent_ThrowHoldTest');
  698. AddAnimEventCallback('OnWeaponDrawReady', 'OnAnimEvent_OnWeaponDrawReady');
  699. AddAnimEventCallback('OnWeaponHolsterReady', 'OnAnimEvent_OnWeaponHolsterReady');
  700. AddAnimEventCallback('AllowTempLookAt', 'OnAnimEvent_AllowTempLookAt');
  701. AddAnimEventCallback('SlideToTarget', 'OnAnimEvent_SlideToTarget');
  702. AddAnimEventCallback('PlayFinisherBlood', 'OnAnimEvent_PlayFinisherBlood');
  703. AddAnimEventCallback('SlowMo', 'OnAnimEvent_SlowMo');
  704. AddAnimEventCallback('BloodTrailForced', 'OnAnimEvent_BloodTrailForced');
  705. AddAnimEventCallback('FadeOut', 'OnAnimEvent_FadeOut');
  706. AddAnimEventCallback('FadeIn', 'OnAnimEvent_FadeIn');
  707. AddAnimEventCallback('DisallowHitAnim', 'OnAnimEvent_DisallowHitAnim');
  708. AddAnimEventCallback('AllowFall', 'OnAnimEvent_AllowFall');
  709. AddAnimEventCallback('AllowFall2', 'OnAnimEvent_AllowFall2');
  710. AddAnimEventCallback('DettachGround', 'OnAnimEvent_DettachGround');
  711. AddAnimEventCallback('KillWithRagdoll', 'OnAnimEvent_KillWithRagdoll');
  712. AddAnimEventCallback('pad_vibration', 'OnAnimEvent_pad_vibration');
  713. AddAnimEventCallback('pad_vibration_light', 'OnAnimEvent_pad_vibration_light');
  714. AddAnimEventCallback('RemoveBurning', 'OnAnimEvent_RemoveBurning');
  715. AddAnimEventCallback('RemoveTangled', 'OnAnimEvent_RemoveTangled');
  716.  
  717. AddItemPerLevelList();
  718.  
  719. enemyCollectionDist = findMoveTargetDistMax;
  720.  
  721. //give items
  722. if(!spawnData.restored && !((W3ReplacerCiri)this) )
  723. {
  724. AddTimer('GiveStartingItems', 0.00001, true, , , true);
  725.  
  726. if(!theGame.IsFinalBuild())
  727. {
  728. //unlock skills for testing purposes
  729. AddAbility('GeraltSkills_Testing');
  730. AddTimer('Debug_GiveTestingItems',0.0001,true);
  731. }
  732. }
  733.  
  734. InitTargeting();
  735.  
  736. // After load
  737. if( spawnData.restored )
  738. {
  739. // ED this line was not called before, because of extra if conditions regarding "safe position stored" but it was uncommented
  740. //OnUseSelectedItem();
  741. }
  742.  
  743.  
  744. // Create the sword holster (it is a saved property, there is no need of re-creating it when playing from save)
  745. if ( !weaponHolster )
  746. {
  747. weaponHolster = new WeaponHolster in this;
  748. }
  749. // temp workaround of not saving states:
  750. weaponHolster.Initialize( this, spawnData.restored );
  751.  
  752. if ( !interiorTracker )
  753. {
  754. interiorTracker = new CPlayerInteriorTracker in this;
  755. }
  756. interiorTracker.Init( spawnData.restored );
  757.  
  758.  
  759. super.OnSpawned( spawnData );
  760.  
  761. if( ! ic )
  762. {
  763. ic = new icControl in this;
  764. ic.icInit();
  765. }
  766. if( ! mMeditation )
  767. {
  768. mMeditation = new CMeditationUI in this;
  769. }
  770. // ImmersiveCam--
  771. medallion = new W3MedallionFX in this;
  772.  
  773. playerMode = new W3PlayerMode in this;
  774. playerMode.Initialize( this );
  775.  
  776. // Initialize Aiming Mode
  777. playerAiming = new PlayerAiming in this;
  778. playerAiming.Initialize( this );
  779.  
  780. // Initialize reachability query
  781. navQuery = new CNavigationReachabilityQueryInterface in this;
  782.  
  783. // Start looking for soft-lock targets
  784. EnableFindTarget( true );
  785. AddTimer( 'CombatCheck', 0.2f, true );
  786.  
  787. // Get the exploration state manager component
  788. substateManager = ( CExplorationStateManager ) GetComponentByClassName( 'CExplorationStateManager' );
  789.  
  790. findMoveTargetDist = findMoveTargetDistMax;
  791.  
  792. SetupEnemiesCollection( enemyCollectionDist, findMoveTargetDist, 10, 'None', FLAG_Attitude_Neutral + FLAG_Attitude_Hostile + FLAG_Attitude_Friendly + FLAG_OnlyAliveActors );
  793.  
  794. //for geralt-replacer switching
  795. inputHandler.RemoveLocksOnSpawn();
  796.  
  797. // Player has the lowest push priority
  798. ((CActor) this ).SetInteractionPriority( IP_Prio_0 );
  799.  
  800. prevDayNightIsNight = theGame.envMgr.IsNight();
  801. CheckDayNightCycle();
  802.  
  803. // Debug
  804. EnableVisualDebug( SHOW_AI, true );
  805.  
  806. //oneliners delay
  807. FactsRemove("blocked_illusion_oneliner");
  808.  
  809. SetFailedFundamentalsFirstAchievementCondition(false);
  810. m_CollisionFxTemplate = (CEntityTemplate) LoadResource( 'sword_colision_fx' );
  811. if( m_WeaponFXCollisionGroupNames.Size() == 0 )
  812. {
  813. m_WeaponFXCollisionGroupNames.PushBack('Static');
  814. m_WeaponFXCollisionGroupNames.PushBack('Foliage');
  815. m_WeaponFXCollisionGroupNames.PushBack('Fence');
  816. m_WeaponFXCollisionGroupNames.PushBack('BoatSide');
  817. m_WeaponFXCollisionGroupNames.PushBack('Door');
  818. m_WeaponFXCollisionGroupNames.PushBack('RigidBody');
  819. m_WeaponFXCollisionGroupNames.PushBack('Dynamic');
  820. m_WeaponFXCollisionGroupNames.PushBack('Destructible');
  821. }
  822.  
  823. if ( counterCollisionGroupNames.Size() == 0 )
  824. {
  825. counterCollisionGroupNames.PushBack('Static');
  826. counterCollisionGroupNames.PushBack('Foliage');
  827. counterCollisionGroupNames.PushBack('Fence');
  828. counterCollisionGroupNames.PushBack('Terrain');
  829. counterCollisionGroupNames.PushBack('Door');
  830. counterCollisionGroupNames.PushBack('RigidBody');
  831. counterCollisionGroupNames.PushBack('Dynamic');
  832. counterCollisionGroupNames.PushBack('Destructible');
  833. }
  834.  
  835. //ps4 pad backlight color
  836. ResetPadBacklightColor();
  837.  
  838. if( spawnData.restored )
  839. {
  840. if (IsCurrentlyUsingItemL())
  841. {
  842. if (inv.HasItemById( currentlyEquipedItemL ))
  843. {
  844. OnUseSelectedItem();
  845. }
  846. else
  847. {
  848. HideUsableItem(true);
  849. }
  850. }
  851. if ( GetCurrentMeleeWeaponType() == PW_Steel || GetCurrentMeleeWeaponType() == PW_Silver )
  852. {
  853. OnEquipMeleeWeapon(GetCurrentMeleeWeaponType(), true, true);
  854. }
  855.  
  856. AddTimer( 'UnmountCrossbowTimer', 0.01, true );
  857.  
  858. ClearBlockedSlots();
  859. }
  860.  
  861. ((CR4PlayerStateSwimming)this.GetState('Swimming')).OnParentSpawned();
  862.  
  863. //hack for possible immortality from finishers
  864. SetImmortalityMode( AIM_None, AIC_SyncedAnim );
  865.  
  866. //disable Dimeritium Bomb skill locks after load
  867. theGame.GetDefinitionsManager().GetContainedAbilities('DwimeritiumBomb_3', atts);
  868. for(i=0; i<atts.Size(); i+=1)
  869. {
  870. skill = SkillNameToEnum(atts[i]);
  871. if(skill != S_SUndefined)
  872. BlockSkill(skill, false);
  873. }
  874.  
  875. // phantom weapon manager
  876. this.GetInventory().GetItemEquippedOnSlot( EES_SteelSword, item );
  877. if( this.GetInventory().ItemHasTag( item, 'PhantomWeapon' ) )
  878. {
  879. this.InitPhantomWeaponMgr();
  880. }
  881.  
  882. //retoractive fix
  883. if(FactsQuerySum("mq3036_fact_done") > 0)
  884. BlockAllActions('mq3036', false);
  885.  
  886. spawnedTime = theGame.GetEngineTimeAsSeconds();
  887.  
  888. if ( theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'EnableUberMovement' ) == "1" )
  889. theGame.EnableUberMovement( true );
  890. else
  891. theGame.EnableUberMovement( false );
  892.  
  893. // Initial level for Gwint Difficulty (Normal)
  894. if ( !FactsDoesExist("gwent_difficulty") )
  895. FactsAdd("gwent_difficulty", 2);
  896. }
  897.  
  898. public function GetTimeSinceSpawned() : float
  899. {
  900. return theGame.GetEngineTimeAsSeconds() - spawnedTime;
  901. }
  902.  
  903. timer function UnmountCrossbowTimer( dt : float, id : int )
  904. {
  905. var itemId : SItemUniqueId;
  906.  
  907. itemId = this.inv.GetItemFromSlot( 'l_weapon' );
  908. if ( inv.IsIdValid( itemId ) && inv.IsItemCrossbow( itemId ) )
  909. {
  910. rangedWeapon = (Crossbow)( inv.GetItemEntityUnsafe( itemId ) );
  911.  
  912. if (rangedWeapon)
  913. {
  914. rangedWeapon.Initialize( (CActor)( rangedWeapon.GetParentEntity() ) );
  915. OnRangedForceHolster( true, true );
  916. RemoveTimer( 'UnmountCrossbowTimer' );
  917. }
  918. }
  919. else
  920. RemoveTimer( 'UnmountCrossbowTimer' );
  921. }
  922.  
  923. event OnDestroyed()
  924. {
  925. playerAiming.RemoveAimingSloMo();
  926.  
  927. if(rangedWeapon)
  928. rangedWeapon.ClearDeployedEntity(true);
  929.  
  930. ResetPadBacklightColor();
  931.  
  932. //remove combat mode no-save lock
  933. theGame.ReleaseNoSaveLock( noSaveLock );
  934. }
  935.  
  936. /////////////////////////////////////////////////////////////////////
  937. ////////////////////////Radial Menu//////////////////////////////////
  938. ////////////////////////////////////////////////////////////////////
  939.  
  940. public function GetBlockedSlots () : array < SRadialSlotDef >
  941. {
  942. return blockedRadialSlots;
  943. }
  944.  
  945. public function ClearBlockedSlots()
  946. {
  947. var i : int;
  948. //var blockedSigns : array<ESignType>;
  949. //var playerWitcher : W3PlayerWitcher;
  950.  
  951. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  952. {
  953. if( !IsSwimming() )
  954. {
  955. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'swimming'))
  956. {
  957. i-=1;
  958. continue;
  959. }
  960. }
  961. if (!IsUsingVehicle())
  962. {
  963. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'useVehicle'))
  964. {
  965. i-=1;
  966. continue;
  967. }
  968. }
  969. if ( !IsCurrentlyUsingItemL() || !IsUsableItemLBlocked() )
  970. {
  971. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'usableItemL'))
  972. {
  973. i-=1;
  974. continue;
  975. }
  976. }
  977. if ( !IsThrowingItem() )
  978. {
  979. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'throwBomb'))
  980. {
  981. i-=1;
  982. continue;
  983. }
  984. }
  985. }
  986. // this is a hack that had to be added because someone ignored existing functionality of blocking radial slots propely and created BlockSignSelection. Unfortunately to keep the backwawrd compatibility I had to hack it.
  987. /*playerWitcher = (W3PlayerWitcher)this;
  988.  
  989. if ( playerWitcher )
  990. {
  991. blockedSigns = playerWitcher.GetBlockedSigns();
  992.  
  993. i = 0;
  994. for ( i = 0; i < blockedSigns.Size(); i+=1 )
  995. {
  996. switch( blockedSigns[i] )
  997. {
  998. case ST_Aard :
  999. if ( !IsRadialSlotBlocked ( 'Aard') )
  1000. {
  1001. playerWitcher.BlockSignSelection(ST_Aard, false);
  1002. }
  1003. break;
  1004. case ST_Axii :
  1005. if ( !IsRadialSlotBlocked ( 'Axii') )
  1006. {
  1007. playerWitcher.BlockSignSelection(ST_Axii, false );
  1008. }
  1009. break;
  1010. case ST_Igni :
  1011. if ( !IsRadialSlotBlocked ( 'Igni') )
  1012. {
  1013. playerWitcher.BlockSignSelection(ST_Igni, false );
  1014. }
  1015. break;
  1016. case ST_Quen :
  1017. if ( !IsRadialSlotBlocked ( 'Quen') )
  1018. {
  1019. playerWitcher.BlockSignSelection(ST_Quen, false );
  1020. }
  1021. break;
  1022. case ST_Yrden :
  1023. if ( !IsRadialSlotBlocked ( 'Yrden') )
  1024. {
  1025. playerWitcher.BlockSignSelection(ST_Yrden, false );
  1026. }
  1027. break;
  1028. default:
  1029. break;
  1030. }
  1031. }
  1032. }*/
  1033.  
  1034. }
  1035.  
  1036. public function RestoreBlockedSlots ()
  1037. {
  1038. var i : int;
  1039. var slotsToBlock : array<name>;
  1040.  
  1041. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  1042. {
  1043. slotsToBlock.PushBack ( blockedRadialSlots[i].slotName );
  1044. }
  1045. if ( slotsToBlock.Size() > 0 )
  1046. {
  1047. EnableRadialSlots ( false, slotsToBlock );
  1048. }
  1049. }
  1050. private function DisableRadialSlot ( slotName : name, sourceName : name ) : bool
  1051. {
  1052. var i : int;
  1053. var k : int;
  1054. var slotsToBlock : array<name>;
  1055.  
  1056. var blockedRadialSlotEntry : SRadialSlotDef;
  1057.  
  1058. slotsToBlock.PushBack ( slotName );
  1059.  
  1060. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  1061. {
  1062. if ( blockedRadialSlots[i].slotName == slotName )
  1063. {
  1064. if ( sourceName != '' )
  1065. {
  1066. for ( k = 0; k < blockedRadialSlots[i].disabledBySources.Size(); k += 1 )
  1067. {
  1068. if ( blockedRadialSlots[i].disabledBySources[k] == sourceName )
  1069. {
  1070. return false;
  1071. }
  1072. }
  1073. blockedRadialSlots[i].disabledBySources.PushBack ( sourceName );
  1074. return false;
  1075. }
  1076.  
  1077. return false;
  1078. }
  1079. }
  1080.  
  1081. blockedRadialSlotEntry = InitBlockedRadialSlotEntry ( slotName );
  1082.  
  1083. if ( sourceName != '' )
  1084. {
  1085. blockedRadialSlotEntry.disabledBySources.PushBack ( sourceName );
  1086. }
  1087. blockedRadialSlots.PushBack ( blockedRadialSlotEntry );
  1088. EnableRadialSlots ( false, slotsToBlock );
  1089. return true;
  1090. }
  1091.  
  1092. public function EnableRadialSlot ( slotName : name, sourceName : name ) : bool
  1093. {
  1094. var i : int;
  1095. var k : int;
  1096.  
  1097. var slotsToBlock : array<name>;
  1098.  
  1099. slotsToBlock.PushBack ( slotName );
  1100.  
  1101. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  1102. {
  1103. if ( blockedRadialSlots[i].slotName == slotName )
  1104. {
  1105.  
  1106. if ( sourceName != '' )
  1107. {
  1108. for ( k = 0; k < blockedRadialSlots[i].disabledBySources.Size(); k += 1 )
  1109. {
  1110. if ( blockedRadialSlots[i].disabledBySources[k] == sourceName )
  1111. {
  1112. blockedRadialSlots[i].disabledBySources.Remove ( blockedRadialSlots[i].disabledBySources[k] );
  1113. }
  1114. }
  1115. }
  1116. if ( blockedRadialSlots[i].disabledBySources.Size() <= 0 )
  1117. {
  1118. blockedRadialSlots.Remove( blockedRadialSlots[i] );
  1119. EnableRadialSlots ( true, slotsToBlock );
  1120. return true;
  1121. }
  1122. return false;
  1123. }
  1124. }
  1125. return false;
  1126.  
  1127. }
  1128.  
  1129. private function InitBlockedRadialSlotEntry ( slotName : name ) : SRadialSlotDef
  1130. {
  1131. var blockedRadialSlotEntry : SRadialSlotDef;
  1132.  
  1133. blockedRadialSlotEntry.slotName = slotName;
  1134.  
  1135. return blockedRadialSlotEntry;
  1136.  
  1137. }
  1138.  
  1139. public function EnableRadialSlotsWithSource ( enable : bool, slotsToBlock : array < name >, sourceName : name )
  1140. {
  1141. var i : int;
  1142.  
  1143. for ( i = 0; i < slotsToBlock.Size(); i+=1 )
  1144. {
  1145. if ( enable )
  1146. {
  1147. EnableRadialSlot ( slotsToBlock[i], sourceName );
  1148. }
  1149. else
  1150. {
  1151. DisableRadialSlot ( slotsToBlock[i], sourceName );
  1152. }
  1153. }
  1154. if ( blockedRadialSlots.Size() <= 0 )
  1155. {
  1156. blockedRadialSlots.Clear();
  1157. }
  1158. }
  1159.  
  1160. public function IsRadialSlotBlocked ( slotName : name ) : bool
  1161. {
  1162. var i : int;
  1163.  
  1164. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  1165. {
  1166. if ( blockedRadialSlots[i].slotName == slotName )
  1167. {
  1168. return true;
  1169. }
  1170. }
  1171. return false;
  1172. }
  1173.  
  1174.  
  1175. /////////////////////////////////////////////////////////////////////
  1176. ////////////////////////////////////////////////////////////////////
  1177. /////////////////////// @Reapir Kits ////////////////////////////////////
  1178. ////////////////////////////////////////////////////////////////////
  1179. public function RepairItem ( rapairKitId : SItemUniqueId, usedOnItem : SItemUniqueId );
  1180. public function HasRepairAbleGearEquiped () : bool;
  1181. public function HasRepairAbleWaponEquiped () : bool;
  1182. public function IsItemRepairAble ( item : SItemUniqueId ) : bool;
  1183.  
  1184. /////////////////////////////////////////////////////////////////////
  1185. ////////////////////////////////////////////////////////////////////
  1186. /////////////////////// @OILS ////////////////////////////////////
  1187. ////////////////////////////////////////////////////////////////////
  1188. public function ApplyOil( oilId : SItemUniqueId, usedOnItem : SItemUniqueId );
  1189. public function IsEquippedSwordUpgradedWithOil(steel : bool, optional oilName : name) : bool;
  1190. public function GetOilAppliedOnSword(steel : bool) : name;
  1191.  
  1192. public function CanApplyOilOnItem(oilId : SItemUniqueId, usedOnItem : SItemUniqueId) : bool
  1193. {
  1194. if(inv.ItemHasTag(oilId, theGame.params.TAG_STEEL_OIL) && inv.IsItemSteelSwordUsableByPlayer(usedOnItem))
  1195. return true;
  1196.  
  1197. if(inv.ItemHasTag(oilId, theGame.params.TAG_SILVER_OIL) && inv.IsItemSilverSwordUsableByPlayer(usedOnItem))
  1198. return true;
  1199.  
  1200. return false;
  1201. }
  1202. ////////////////////////////////////////////////////////////////////
  1203.  
  1204. public final function DidFailFundamentalsFirstAchievementCondition() : bool
  1205. {
  1206. return failedFundamentalsFirstAchievementCondition;
  1207. }
  1208.  
  1209. public final function SetFailedFundamentalsFirstAchievementCondition(b : bool)
  1210. {
  1211. var i : int;
  1212. var npc : CNewNPC;
  1213.  
  1214. failedFundamentalsFirstAchievementCondition = b;
  1215.  
  1216. //save info in enemy since we might run away from combat and return, triggering new combat encounter
  1217. if(failedFundamentalsFirstAchievementCondition)
  1218. {
  1219. for(i=0; i<hostileEnemies.Size(); i+=1)
  1220. {
  1221. if(hostileEnemies[i].HasTag(theGame.params.MONSTER_HUNT_ACTOR_TAG))
  1222. {
  1223. npc = (CNewNPC)hostileEnemies[i];
  1224. npc.AddTag('failedFundamentalsAchievement');
  1225. npc.AddTimer('FundamentalsAchFailTimer', 30*60, , , , true, true);
  1226. }
  1227. }
  1228. }
  1229. }
  1230.  
  1231. public function IsInCombatFist() : bool
  1232. {
  1233. return this.GetCurrentStateName() == 'CombatFists';
  1234. }
  1235.  
  1236. public function IsInitialized() : bool;
  1237.  
  1238. public function IsCiri() : bool
  1239. {
  1240. return ((W3ReplacerCiri)this);
  1241. }
  1242.  
  1243. protected function WouldLikeToMove() : bool
  1244. {
  1245. var speedVec : Vector;
  1246. var speed, speedMult : float;
  1247.  
  1248. // Get speed from input
  1249. speedVec.X = theInput.GetActionValue( 'GI_AxisLeftX' ); //player.mainInput.aLeftJoyX;
  1250. speedVec.Y = theInput.GetActionValue( 'GI_AxisLeftY' );//player.mainInput.aLeftJoyY;
  1251. speed = VecLength2D( speedVec );
  1252.  
  1253. return speed > 0.1f;
  1254. }
  1255.  
  1256. function HandleMovement( deltaTime : float )
  1257. {
  1258. // just to see if player would like to move if there would be possibility
  1259. // example of use: movement is blocked when in critical state, but it can end earlier only if it would be desired by player
  1260. // and this is nothing but desire to move
  1261. // note: for some reason, when doing WouldLikeToMove()? 1.0f : 0.0f it just doesn't care and gives 0.0f
  1262. if (WouldLikeToMove())
  1263. SetBehaviorVariable( 'playerWouldLikeToMove', 1.0f);
  1264. else
  1265. SetBehaviorVariable( 'playerWouldLikeToMove', 0.0f);
  1266.  
  1267. super.HandleMovement( deltaTime );
  1268. }
  1269.  
  1270. function BattleCryIsReady( ) : bool
  1271. {
  1272. var l_currentTime : float;
  1273.  
  1274. l_currentTime = theGame.GetEngineTimeAsSeconds();
  1275.  
  1276. if( l_currentTime >= battlecry_timeForNext )
  1277. {
  1278. return true;
  1279. }
  1280. return false;
  1281. }
  1282.  
  1283. function PlayBattleCry( _BattleCry : name , _Chance : float, optional _IgnoreDelay, ignoreRepeatCheck : bool )
  1284. {
  1285. var l_randValue : float;
  1286. var fact : int;
  1287.  
  1288. fact = FactsQuerySum("force_stance_normal");
  1289.  
  1290. if( IsSwimming()
  1291. || theGame.IsDialogOrCutscenePlaying()
  1292. || IsInNonGameplayCutscene()
  1293. || IsInGameplayScene()
  1294. || theGame.IsCurrentlyPlayingNonGameplayScene()
  1295. || theGame.IsFading()
  1296. || theGame.IsBlackscreen()
  1297. || FactsQuerySum("force_stance_normal") > 0 )
  1298. {
  1299. return;
  1300. }
  1301.  
  1302. // To avoid calling too often the same type of battle cry
  1303. if ( !ignoreRepeatCheck )
  1304. {
  1305. if( battlecry_lastTry == _BattleCry )
  1306. return;
  1307. }
  1308.  
  1309. battlecry_lastTry = _BattleCry;
  1310.  
  1311. l_randValue = RandF();
  1312.  
  1313. // Either use delay or chance
  1314. if( l_randValue < _Chance && ( _IgnoreDelay || BattleCryIsReady() ) )
  1315. {
  1316. thePlayer.PlayVoiceset( 90, _BattleCry );
  1317. // Restart counter
  1318. battlecry_timeForNext = theGame.GetEngineTimeAsSeconds() + RandRangeF( battlecry_delayMax, battlecry_delayMin );
  1319. }
  1320.  
  1321. }
  1322.  
  1323. public final function OnWeatherChanged()
  1324. {
  1325. if( IsInInterior()
  1326. || GetCurrentStateName() != 'Exploration'
  1327. || theGame.IsDialogOrCutscenePlaying()
  1328. || IsInNonGameplayCutscene()
  1329. || IsInGameplayScene()
  1330. || theGame.IsCurrentlyPlayingNonGameplayScene()
  1331. || theGame.IsFading()
  1332. || theGame.IsBlackscreen()
  1333. || GetTimeSinceSpawned() < 60 )
  1334. {
  1335. return;
  1336. }
  1337.  
  1338. AddTimer( 'CommentOnWeather', 1 );
  1339. }
  1340.  
  1341. public final timer function CommentOnWeather( _Delta : float, _Id : int )
  1342. {
  1343. var l_weather : name;
  1344. var l_currentArea : EAreaName;
  1345. var l_rand : float;
  1346.  
  1347. l_weather = GetWeatherConditionName();
  1348.  
  1349. l_currentArea = theGame.GetCommonMapManager().GetCurrentArea();
  1350.  
  1351. switch ( l_weather )
  1352. {
  1353. case 'WT_Clear':
  1354.  
  1355. l_rand = RandF();
  1356.  
  1357. if( l_rand > 0.66f && !AreaIsCold() && theGame.envMgr.IsDay() )
  1358. {
  1359. thePlayer.PlayVoiceset( 90, 'WeatherHot' );
  1360. }
  1361. else if ( l_rand > 0.33f )
  1362. {
  1363. thePlayer.PlayVoiceset( 90, 'WeatherClearingUp' );
  1364. }
  1365. break;
  1366.  
  1367. case 'WT_Rain_Storm':
  1368. thePlayer.PlayVoiceset( 90, 'WeatherStormy' );
  1369. break;
  1370.  
  1371. case 'WT_Light_Clouds':
  1372. if( previousRainStrength < GetRainStrength() )
  1373. {
  1374. thePlayer.PlayVoiceset( 90, 'WeatherLooksLikeRain' );
  1375. }
  1376. else if( AreaIsCold() && previousWeather == 'WT_Clear' )
  1377. {
  1378. thePlayer.PlayVoiceset( 90, 'WeatherCold' );
  1379. }
  1380. break;
  1381.  
  1382. case 'WT_Mid_Clouds':
  1383. if( previousRainStrength < GetRainStrength() )
  1384. {
  1385. thePlayer.PlayVoiceset( 90, 'WeatherRaining' );
  1386. }
  1387. else if( AreaIsCold() && previousWeather == 'WT_Clear' )
  1388. {
  1389. thePlayer.PlayVoiceset( 90, 'WeatherCold' );
  1390. }
  1391. break;
  1392.  
  1393. case 'WT_Mid_Clouds_Dark':
  1394. if( previousWeather != 'WT_Heavy_Clouds' && previousWeather != 'WT_Heavy_Clouds_Dark' )
  1395. thePlayer.PlayVoiceset( 90, 'WeatherWindy' );
  1396. break;
  1397.  
  1398. case 'WT_Heavy_Clouds':
  1399. if( previousWeather != 'WT_Mid_Clouds_Dark' && previousWeather != 'WT_Heavy_Clouds_Dark' )
  1400. thePlayer.PlayVoiceset( 90, 'WeatherWindy' );
  1401. break;
  1402.  
  1403. case 'WT_Heavy_Clouds_Dark':
  1404. if( thePlayer.IsOnBoat() )
  1405. {
  1406. thePlayer.PlayVoiceset( 90, 'WeatherSeaWillStorm' );
  1407. }
  1408. else if( previousRainStrength < GetRainStrength() )
  1409. {
  1410. thePlayer.PlayVoiceset( 90, 'WeatherLooksLikeRain' );
  1411. }
  1412. else
  1413. {
  1414. thePlayer.PlayVoiceset( 90, 'WeatherWindy' );
  1415. }
  1416. break;
  1417.  
  1418. case 'WT_Snow':
  1419. if( RandF() > 0.5f )
  1420. thePlayer.PlayVoiceset( 90, 'WeatherSnowy' );
  1421. else
  1422. thePlayer.PlayVoiceset( 90, 'WeatherCold' );
  1423. break;
  1424. }
  1425.  
  1426. previousRainStrength = GetRainStrength();
  1427. previousWeather = l_weather;
  1428. }
  1429.  
  1430. function CanUpdateMovement() : bool
  1431. {
  1432. if ( rangedWeapon
  1433. && GetBehaviorVariable( 'fullBodyAnimWeight' ) >= 1.f
  1434. && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  1435. return false;
  1436.  
  1437. return true;
  1438. }
  1439.  
  1440. public function SetDefaultLocomotionController()
  1441. {
  1442. if( !defaultLocomotionController )
  1443. {
  1444. defaultLocomotionController = new CR4LocomotionPlayerControllerScript in this;
  1445. }
  1446.  
  1447. ActionDirectControl( defaultLocomotionController );
  1448. }
  1449.  
  1450. event OnPlayerTickTimer( deltaTime : float )
  1451. {
  1452. var focusModeController : CFocusModeController;
  1453. var cnt : int;
  1454.  
  1455. super.OnPlayerTickTimer( deltaTime );
  1456.  
  1457. HandleMovement( deltaTime );
  1458.  
  1459. if ( playerAiming.GetCurrentStateName() == 'Aiming' )
  1460. {
  1461. FindTarget();
  1462. FindNonActorTarget( false );
  1463. UpdateDisplayTarget();
  1464. UpdateLookAtTarget();
  1465. }
  1466. else
  1467. {
  1468. if( playerTickTimerPhase == 0 )
  1469. {
  1470. FindTarget();
  1471. }
  1472. else if( playerTickTimerPhase == 1 )
  1473. {
  1474. FindNonActorTarget( false );
  1475. }
  1476. else if ( playerTickTimerPhase == 2 )
  1477. {
  1478. UpdateDisplayTarget();
  1479. UpdateLookAtTarget();
  1480. }
  1481. }
  1482.  
  1483. //CombatModeDebug();
  1484.  
  1485. playerTickTimerPhase = ( playerTickTimerPhase + 1 ) % 3;
  1486.  
  1487. focusModeController = theGame.GetFocusModeController();
  1488. focusModeController.UpdateFocusInteractions( deltaTime );
  1489.  
  1490. //some behavior hack for critical states, moved from effectsManager.PerformUpdate() since it does not tick continuously anymore
  1491. cnt = (int)( effectManager.GetCriticalBuffsCount() > 0 );
  1492. SetBehaviorVariable('hasCriticalBuff', cnt);
  1493. }
  1494.  
  1495. event OnDeath( damageAction : W3DamageAction )
  1496. {
  1497. super.OnDeath( damageAction );
  1498.  
  1499. RemoveTimer('RequestCriticalAnimStart');
  1500. //theInput.SetContext('Death');
  1501. EnableFindTarget( false );
  1502. BlockAllActions('Death', true);
  1503.  
  1504. EnableHardLock( false );
  1505.  
  1506. theGame.CreateNoSaveLock( 'player_death', deathNoSaveLock, false, false );
  1507. theGame.SetDeathSaveLockId( deathNoSaveLock );
  1508.  
  1509. ClearHostileEnemiesList();
  1510. RemoveReactions();
  1511. SetPlayerCombatTarget(NULL);
  1512. OnEnableAimingMode( false );
  1513. }
  1514.  
  1515. // Called when the actor gets out of unconscious state
  1516. function OnRevived()
  1517. {
  1518. super.OnRevived();
  1519. BlockAllActions('Death', false);
  1520.  
  1521. theGame.ReleaseNoSaveLock(deathNoSaveLock);
  1522.  
  1523. this.RestartReactionsIfNeeded();
  1524. }
  1525.  
  1526. public function CanStartTalk() : bool
  1527. {
  1528. if ( beingWarnedBy.Size() > 0 )
  1529. return false;
  1530.  
  1531. return super.CanStartTalk();
  1532. }
  1533.  
  1534. ///////////////////////////////////////////////////////////////////////////
  1535. // @Counters
  1536. ///////////////////////////////////////////////////////////////////////////
  1537.  
  1538. //caches timestamp of counter use (button press)
  1539. public function AddCounterTimeStamp(time : EngineTime) {counterTimestamps.PushBack(time);}
  1540.  
  1541. /*
  1542. This function checks if we have performed a counter
  1543. It checks timestamps of moments when we pressed the parry/counter button in order
  1544. to determine if the player was spamming the button. If so then this is not a counter.
  1545.  
  1546. Returns true if the counter is valid
  1547. */
  1548. public function CheckCounterSpamming(attacker : CActor) : bool
  1549. {
  1550. var counterWindowStartTime : EngineTime; //the time when the counter window (in anim) started
  1551. var i, spamCounter : int;
  1552. var reflexAction : bool;
  1553. var testEngineTime : EngineTime;
  1554.  
  1555. if(!attacker)
  1556. return false;
  1557.  
  1558. counterWindowStartTime = ((CNewNPC)attacker).GetCounterWindowStartTime();
  1559. spamCounter = 0;
  1560. reflexAction = false;
  1561.  
  1562. //if counterWindowStartTime was never set return false - PF
  1563. if ( counterWindowStartTime == testEngineTime )
  1564. {
  1565. return false;
  1566. }
  1567.  
  1568. for(i = counterTimestamps.Size() - 1; i>=0; i-=1)
  1569. {
  1570. //log number of button presses since 0.4 seconds before the counter timewindow
  1571. if(counterTimestamps[i] >= (counterWindowStartTime - EngineTimeFromFloat(0.4)) )
  1572. {
  1573. spamCounter += 1;
  1574. }
  1575. //and at the same time remove all outdated data on the fly
  1576. else
  1577. {
  1578. counterTimestamps.Remove(counterTimestamps[i]);
  1579. continue;
  1580. }
  1581.  
  1582. //set info that we have a potential parry if this press was after the counter timewindow started
  1583. if(!reflexAction && (counterTimestamps[i] >= counterWindowStartTime))
  1584. reflexAction = true;
  1585. }
  1586.  
  1587. /*
  1588. If reflexAction is set then we have at least 1 button press within the counter timewindow.
  1589.  
  1590. As for the spam counter:
  1591. 0 means no button was pressed - no counter
  1592. 1 means exactly one button press - a potential counter (if reflexAction is set as well)
  1593. >1 means spamming
  1594. */
  1595. if(spamCounter == 1 && reflexAction)
  1596. return true;
  1597.  
  1598. return false;
  1599. }
  1600.  
  1601. protected function PerformCounterCheck(parryInfo: SParryInfo) : bool
  1602. {
  1603. var mult : float;
  1604. var parryType : EParryType;
  1605. var validCounter, useKnockdown : bool;
  1606. var slideDistance, duration : float;
  1607. var playerToTargetRot : EulerAngles;
  1608. var zDifference : float;
  1609. var effectType : EEffectType;
  1610. var repelType : EPlayerRepelType = PRT_Random;
  1611. var params : SCustomEffectParams;
  1612. var thisPos, attackerPos : Vector;
  1613. var fistFightCheck : bool;
  1614. var fistFightCounter : bool;
  1615. var attackerInventory : CInventoryComponent;
  1616. var weaponId : SItemUniqueId;
  1617. var weaponTags : array<name>;
  1618. var playerToAttackerVector : Vector;
  1619. var tracePosStart : Vector;
  1620. var tracePosEnd : Vector;
  1621. var hitPos : Vector;
  1622. var hitNormal : Vector;
  1623.  
  1624. if(ShouldProcessTutorial('TutorialDodge') || ShouldProcessTutorial('TutorialCounter'))
  1625. {
  1626. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) );
  1627. FactsRemove("tut_fight_slomo_ON");
  1628. }
  1629.  
  1630. if ( !parryInfo.canBeParried || parryInfo.attacker.HasAbility( 'CannotBeCountered' ) )
  1631. return false;
  1632.  
  1633. fistFightCheck = FistFightCheck( parryInfo.target, parryInfo.attacker, fistFightCounter );
  1634.  
  1635. if( ParryCounterCheck() && parryInfo.targetToAttackerAngleAbs < theGame.params.PARRY_HALF_ANGLE && fistFightCheck )
  1636. {
  1637. //check if this is a valid counter
  1638. validCounter = CheckCounterSpamming(parryInfo.attacker);
  1639.  
  1640. if(validCounter)
  1641. {
  1642. if ( IsInCombatActionFriendly() )
  1643. RaiseEvent('CombatActionFriendlyEnd');
  1644.  
  1645. SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) );
  1646. SetBehaviorVariable( 'counter', (float)validCounter); //1/true when the parry is a counter/reflex_parry
  1647.  
  1648. //PPPP counter success sound
  1649. //SoundEvent("global_machines_lift_wood1_mechanism_stop" );
  1650. SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) );
  1651. SetBehaviorVariable( 'counter', (float)validCounter); //1/true when the parry is a counter/reflex_parry
  1652. this.SetBehaviorVariable( 'combatActionType', (int)CAT_Parry );
  1653.  
  1654.  
  1655. if ( !fistFightCounter )
  1656. {
  1657. attackerInventory = parryInfo.attacker.GetInventory();
  1658. weaponId = attackerInventory.GetItemFromSlot('r_weapon');
  1659. attackerInventory.GetItemTags( weaponId , weaponTags );
  1660.  
  1661. /*if( parryInfo.attacker.HasTag( 'olgierd_gpl' ) && parryInfo.attackActionName == 'attack_heavy' )
  1662. {
  1663. //DealCounterDamageToOlgierd();
  1664. GetTarget().AddAbility( 'HitCounterEnabled', false );
  1665. GetTarget().AddTimer( 'DisableHitCounterAfter', 3.0 );
  1666. }*/
  1667.  
  1668. //don't look at me like that. It is NOT a hack... follow the white rabbit...
  1669. if ( parryInfo.attacker.HasAbility('mon_gravehag') )
  1670. {
  1671. repelType = PRT_Slash;
  1672. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, 'ReflexParryPerformed');
  1673. //parryInfo.attacker.RemoveAbility('TongueAttack');
  1674. }
  1675. else if ( (CNewNPC)parryInfo.attacker && !((CNewNPC)parryInfo.attacker).IsHuman() )
  1676. {
  1677. repelType = PRT_SideStepSlash;
  1678. }
  1679. else if ( weaponTags.Contains('spear2h') )
  1680. {
  1681. repelType = PRT_SideStepSlash;
  1682. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed");
  1683. parryInfo.attacker.SignalGameplayEvent( 'SpearDestruction');
  1684. }
  1685. else
  1686. {
  1687. //-----pitch check------
  1688. thisPos = this.GetWorldPosition();
  1689. attackerPos = parryInfo.attacker.GetWorldPosition();
  1690. playerToTargetRot = VecToRotation( thisPos - attackerPos );
  1691. zDifference = thisPos.Z - attackerPos.Z;
  1692.  
  1693. if ( playerToTargetRot.Pitch < -5.f && zDifference > 0.35 )
  1694. {
  1695. repelType = PRT_Kick;
  1696. //Pass attacker to the timer so that he ragdolls after a delay
  1697. ragdollTarget = parryInfo.attacker;
  1698. AddTimer( 'ApplyCounterRagdollTimer', 0.3 );
  1699. }
  1700. else
  1701. {
  1702. useKnockdown = false;
  1703. if ( CanUseSkill(S_Sword_s11) )
  1704. {
  1705. if( GetSkillLevel(S_Sword_s11) > 1 && RandF() < GetWitcherPlayer().GetStat(BCS_Focus) )//CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s11, 'chance', false, true)) )
  1706. {
  1707. duration = CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s11, 'duration', false, true));
  1708. useKnockdown = true;
  1709. }
  1710. }
  1711. else if ( parryInfo.attacker.IsHuman() )
  1712. {
  1713. //Apply knockdown if npc is countered on ledge
  1714. tracePosStart = parryInfo.attacker.GetWorldPosition();
  1715. tracePosStart.Z += 1.f;
  1716. playerToAttackerVector = VecNormalize( parryInfo.attacker.GetWorldPosition() - parryInfo.target.GetWorldPosition() );
  1717. tracePosEnd = ( playerToAttackerVector * 0.75f ) + ( playerToAttackerVector * parryInfo.attacker.GetRadius() ) + parryInfo.attacker.GetWorldPosition();
  1718. tracePosEnd.Z += 1.f;
  1719.  
  1720. if ( !theGame.GetWorld().StaticTrace( tracePosStart, tracePosEnd, hitPos, hitNormal, counterCollisionGroupNames ) )
  1721. {
  1722. tracePosStart = tracePosEnd;
  1723. tracePosEnd -= 3.f;
  1724.  
  1725. if ( !theGame.GetWorld().StaticTrace( tracePosStart, tracePosEnd, hitPos, hitNormal, counterCollisionGroupNames ) )
  1726. useKnockdown = true;
  1727. }
  1728. }
  1729.  
  1730. if(useKnockdown && (!parryInfo.attacker.IsImmuneToBuff(EET_HeavyKnockdown) || !parryInfo.attacker.IsImmuneToBuff(EET_Knockdown)))
  1731. {
  1732. if(!parryInfo.attacker.IsImmuneToBuff(EET_HeavyKnockdown))
  1733. {
  1734. params.effectType = EET_HeavyKnockdown;
  1735. }
  1736. else
  1737. {
  1738. params.effectType = EET_Knockdown;
  1739. }
  1740.  
  1741. repelType = PRT_Kick;
  1742. params.creator = this;
  1743. params.sourceName = "ReflexParryPerformed";
  1744. params.duration = duration;
  1745.  
  1746. parryInfo.attacker.AddEffectCustom(params);
  1747. }
  1748. else
  1749. {
  1750. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed");
  1751. }
  1752. }
  1753. }
  1754.  
  1755. parryInfo.attacker.GetInventory().PlayItemEffect(parryInfo.attackerWeaponId, 'counterattack');
  1756.  
  1757. //by default repelType is PRT_Random
  1758. if ( repelType == PRT_Random )
  1759. if ( RandRange(100) > 50 )
  1760. repelType = PRT_Bash;
  1761. else
  1762. repelType = PRT_Kick;
  1763.  
  1764. this.SetBehaviorVariable( 'repelType', (int)repelType );
  1765. parryInfo.attacker.SetBehaviorVariable( 'repelType', (int)repelType );
  1766. }
  1767. else
  1768. {
  1769. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed");
  1770. }
  1771.  
  1772. //SetCustomOrientationTargetForCombatActions( OT_None );
  1773. SetParryTarget ( parryInfo.attacker );
  1774. SetSlideTarget( parryInfo.attacker );
  1775. if ( !IsActorLockedToTarget() )
  1776. SetMoveTarget( parryInfo.attacker );
  1777.  
  1778. if ( RaiseForceEvent( 'PerformCounter' ) )
  1779. OnCombatActionStart();
  1780.  
  1781. SetCustomRotation( 'Counter', VecHeading( parryInfo.attacker.GetWorldPosition() - this.GetWorldPosition() ), 0.0f, 0.2f, false );
  1782. AddTimer( 'UpdateCounterRotation', 0.4f, true );
  1783. AddTimer( 'SetCounterRotation', 0.2f );
  1784.  
  1785. IncreaseUninterruptedHitsCount(); //counters also count as uninterrupted hits
  1786.  
  1787. //drain stamina
  1788. if(IsHeavyAttack(parryInfo.attackActionName))
  1789. mult = theGame.params.HEAVY_STRIKE_COST_MULTIPLIER;
  1790.  
  1791. DrainStamina(ESAT_Counterattack, 0, 0, '', 0, mult);
  1792.  
  1793. theGame.GetGamerProfile().IncStat(ES_CounterattackChain);
  1794.  
  1795. }
  1796. else
  1797. {
  1798. ResetUninterruptedHitsCount();
  1799. }
  1800. return validCounter;
  1801. }
  1802.  
  1803. return false;
  1804. }
  1805.  
  1806. timer function UpdateCounterRotation( dt : float, id : int )
  1807. {
  1808. UpdateCustomRotationHeading( 'Counter', VecHeading( parryTarget.GetWorldPosition() - this.GetWorldPosition() ) );
  1809. }
  1810.  
  1811. timer function SetCounterRotation( dt : float, id : int )
  1812. {
  1813. SetCustomRotation( 'Counter', VecHeading( parryTarget.GetWorldPosition() - this.GetWorldPosition() ), 360.f, 0.2f, false );
  1814. }
  1815.  
  1816. private var parryTarget : CActor;
  1817. private function SetParryTarget( t : CActor )
  1818. {
  1819. parryTarget = t;
  1820. }
  1821.  
  1822. private var ragdollTarget : CActor;
  1823. timer function ApplyCounterRagdollTimer( time : float , id : int)
  1824. {
  1825. var actor : CActor;
  1826.  
  1827. actor = (CActor)ragdollTarget;
  1828.  
  1829. if(actor)
  1830. {
  1831. actor.AddEffectDefault(EET_HeavyKnockdown, this, 'ReflexParryPerformed');
  1832. }
  1833. }
  1834.  
  1835. ///////////////////////////////////////////////////////////////////////////
  1836. // Player Mode
  1837.  
  1838. public function EnableMode( mode : EPlayerMode, enable : bool )
  1839. {
  1840. playerMode.EnableMode( mode, enable );
  1841. }
  1842.  
  1843. public function GetPlayerMode() : W3PlayerMode
  1844. {
  1845. return playerMode;
  1846. }
  1847.  
  1848. private function GetClosestIncomingAttacker() : CActor
  1849. {
  1850. var i, size : int;
  1851. var attackerToPlayerDistances : array< float >;
  1852. var closestAttackerIndex : int;
  1853. var incomingAttackers : array<CActor>;
  1854.  
  1855. //incomingAttackers = this.combatManager.SendTicketOwners( CTT_Attack );
  1856. if(playerMode && playerMode.combatDataComponent)
  1857. {
  1858. if ( incomingAttackers.Size() <= 0 )
  1859. this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Charge' );
  1860.  
  1861. if ( incomingAttackers.Size() <= 0 )
  1862. this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Melee' );
  1863.  
  1864. if ( incomingAttackers.Size() <= 0 )
  1865. this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Range' );
  1866. }
  1867.  
  1868. size = incomingAttackers.Size();
  1869. attackerToPlayerDistances.Resize( size );
  1870.  
  1871. if ( size > 0 )
  1872. {
  1873. for ( i = incomingAttackers.Size()-1; i >= 0; i -= 1)
  1874. {
  1875. if ( !IsEnemyVisible( incomingAttackers[i] ) )
  1876. {
  1877. incomingAttackers.EraseFast( i );
  1878. }
  1879. }
  1880. }
  1881.  
  1882. if ( size > 0 )
  1883. {
  1884. for ( i = 0; i < size; i += 1 )
  1885. {
  1886. attackerToPlayerDistances[i] = VecDistance( incomingAttackers[i].GetWorldPosition(), this.GetWorldPosition() );
  1887. }
  1888. closestAttackerIndex = ArrayFindMinF( attackerToPlayerDistances );
  1889. return incomingAttackers[ closestAttackerIndex ];
  1890. }
  1891. else
  1892. {
  1893. return NULL;
  1894. }
  1895. }
  1896.  
  1897. // Combat Timer
  1898. timer function CombatCheck( time : float , id : int)
  1899. {
  1900. var i : int;
  1901. var strLevel, temp : string;
  1902. var enemies : array<CActor>;
  1903.  
  1904. UpdateFinishableEnemyList();
  1905. FindMoveTarget();
  1906. playerMode.UpdateCombatMode();
  1907.  
  1908. if( GetPlayerCombatStance() == PCS_Guarded )
  1909. {
  1910. if( GetTarget().GetHealthPercents() > 0.25f )
  1911. {
  1912. PlayBattleCry( 'BattleCryTaunt', 0.2f );
  1913. }
  1914. else
  1915. {
  1916. if( GetTarget().IsHuman() )
  1917. PlayBattleCry( 'BattleCryHumansEnd', 0.3f );
  1918. else
  1919. PlayBattleCry( 'BattleCryMonstersEnd', 0.3f );
  1920. }
  1921. }
  1922.  
  1923. if(IsThreatened() && ShouldProcessTutorial('TutorialMonsterThreatLevels') && FactsQuerySum("q001_nightmare_ended") > 0)
  1924. {
  1925. GetEnemiesInRange(enemies);
  1926. for(i=0; i<enemies.Size(); i+=1)
  1927. {
  1928. strLevel = ((CNewNPC)enemies[i]).GetExperienceDifferenceLevelName(temp);
  1929. if(strLevel == "deadlyLevel" || strLevel == "highLevel")
  1930. {
  1931. FactsAdd("tut_high_threat_monster");
  1932. break;
  1933. }
  1934. }
  1935. }
  1936. }
  1937.  
  1938. public function ReceivedDamageInCombat() : bool
  1939. {
  1940. return receivedDamageInCombat;
  1941. }
  1942.  
  1943. timer function PinEssentialGroupTimer( deltaTime : float, id : int )
  1944. {
  1945. ToggleEssentialModules( !IsHUDGroupEnabledForReason( GetFHUDConfig().essentialModules, "PinEssentialGroup" ), "PinEssentialGroup" );
  1946. }
  1947.  
  1948. timer function EssentialsOnTimer( deltaTime : float, id : int )
  1949. {
  1950. ToggleEssentialModules( true, "EssentialModulesHotkey" );
  1951. }
  1952.  
  1953. timer function MapOnTimer( deltaTime : float, id : int )
  1954. {
  1955. ToggleMinimapModules( true, "MinimapModulesHotkey" );
  1956. }
  1957.  
  1958. timer function QuestsOnTimer( deltaTime : float, id : int )
  1959. {
  1960. ToggleQuestsModules( true, "QuestsModulesHotkey" );
  1961. }
  1962.  
  1963. timer function CharOnTimer( deltaTime : float, id : int )
  1964. {
  1965. ToggleCharacterModules( true, "CharModulesHotkey" );
  1966. }
  1967.  
  1968. timer function DamageOffTimer( deltaTime : float, id : int ) //still needed as workaround
  1969. {
  1970. ToggleHUDModule( "WolfHeadModule", false, "OnDamage" );
  1971. }
  1972.  
  1973. timer function MeditationModulesOnTimer( deltaTime : float, id : int ) //needed for compatibility
  1974. {
  1975. if ( GetFHUDConfig().enableMeditationModules )
  1976. {
  1977. ToggleMeditModules( true, "RealTimeMeditation" );
  1978. }
  1979. }
  1980.  
  1981. timer function MeditationModulesOffTimer( deltaTime : float, id : int ) //needed for compatibility
  1982. {
  1983. if ( GetFHUDConfig().enableMeditationModules )
  1984. {
  1985. ToggleMeditModules( false, "RealTimeMeditation" );
  1986. }
  1987. }
  1988. //---=== modFriendlyHUD ===---
  1989. event OnCombatStart()
  1990. {
  1991. var weaponType : EPlayerWeapon;
  1992.  
  1993. //---=== modFriendlyHUD ===---
  1994. if ( GetFHUDConfig().enableCombatModules )
  1995. {
  1996. ToggleCombatModules( true, "InCombat" );
  1997. }
  1998. //---=== modFriendlyHUD ===---
  1999.  
  2000. theGame.CreateNoSaveLock( 'combat', noSaveLock );
  2001.  
  2002. //cerberus achievement
  2003. FactsRemove("statistics_cerberus_sign");
  2004. FactsRemove("statistics_cerberus_petard");
  2005. FactsRemove("statistics_cerberus_bolt");
  2006. FactsRemove("statistics_cerberus_fists");
  2007. FactsRemove("statistics_cerberus_melee");
  2008. FactsRemove("statistics_cerberus_environment");
  2009.  
  2010. BlockAction(EIAB_OpenMeditation, 'InCombat');
  2011. BlockAction(EIAB_HighlightObjective, 'InCombat');
  2012.  
  2013. if ( !this.IsUsingBoat() && GetTarget().GetAttitude(this) == AIA_Hostile )
  2014. {
  2015. weaponType = GetMostConvenientMeleeWeapon( GetTarget() );
  2016.  
  2017. if ( weaponType == PW_Steel || weaponType == PW_Silver )
  2018. this.OnEquipMeleeWeapon( weaponType, false );
  2019. }
  2020. }
  2021.  
  2022. //called when combat finishes
  2023. event OnCombatFinished()
  2024. {
  2025. var cnt : int;
  2026.  
  2027. //---=== modFriendlyHUD ===---
  2028. if ( GetFHUDConfig().enableCombatModules )
  2029. {
  2030. ToggleCombatModules( false, "InCombat" );
  2031. }
  2032. //---=== modFriendlyHUD ===---
  2033.  
  2034. reevaluateCurrentWeapon = false;
  2035.  
  2036. thePlayer.HardLockToTarget( false );
  2037.  
  2038. receivedDamageInCombat = false;
  2039.  
  2040. //cerberus achievement
  2041. cnt = 0;
  2042. if(FactsQuerySum("statistics_cerberus_sign") > 0)
  2043. cnt += 1;
  2044. if(FactsQuerySum("statistics_cerberus_petard") > 0)
  2045. cnt += 1;
  2046. if(FactsQuerySum("statistics_cerberus_bolt") > 0)
  2047. cnt += 1;
  2048. if(FactsQuerySum("statistics_cerberus_fists") > 0)
  2049. cnt += 1;
  2050. if(FactsQuerySum("statistics_cerberus_melee") > 0)
  2051. cnt += 1;
  2052. if(FactsQuerySum("statistics_cerberus_environment") > 0)
  2053. cnt += 1;
  2054.  
  2055. //failsafe
  2056. FactsRemove("statistics_cerberus_sign");
  2057. FactsRemove("statistics_cerberus_petard");
  2058. FactsRemove("statistics_cerberus_bolt");
  2059. FactsRemove("statistics_cerberus_fists");
  2060. FactsRemove("statistics_cerberus_melee");
  2061. FactsRemove("statistics_cerberus_environment");
  2062.  
  2063. if(cnt >= 3)
  2064. theGame.GetGamerProfile().AddAchievement(EA_Cerberus);
  2065. //end of cerberus
  2066.  
  2067. if(theGame.GetTutorialSystem() && FactsQuerySum("TutorialShowSilver") > 0)
  2068. {
  2069. FactsAdd("tut_show_silver_sword", 1);
  2070. FactsRemove("TutorialShowSilver");
  2071. }
  2072. this.SetBehaviorVariable('isInCombatForOverlay',0.f);
  2073. GoToExplorationIfNeeded();
  2074. theGame.ReleaseNoSaveLock( noSaveLock );
  2075. LogChannel( 'OnCombatFinished', "OnCombatFinished: ReleaseNoSaveLock" );
  2076.  
  2077. SetFailedFundamentalsFirstAchievementCondition(false);
  2078.  
  2079. UnblockAction(EIAB_OpenMeditation, 'InCombat');
  2080. UnblockAction(EIAB_HighlightObjective, 'InCombat');
  2081. }
  2082.  
  2083. event OnReactToBeingHit( damageAction : W3DamageAction )
  2084. {
  2085. var weaponType : EPlayerWeapon;
  2086.  
  2087. super.OnReactToBeingHit(damageAction);
  2088.  
  2089. if ( IsInCombat() && damageAction.attacker && damageAction.attacker == GetTarget() && !( this.IsUsingVehicle() && this.IsOnBoat() ) )
  2090. {
  2091. weaponType = GetMostConvenientMeleeWeapon( GetTarget() );
  2092. if ( weaponType != PW_Fists && weaponType != PW_None && weaponType != this.GetCurrentMeleeWeaponType() )
  2093. OnEquipMeleeWeapon( weaponType, false );
  2094. }
  2095. }
  2096.  
  2097. //called when player receives damage in combat(except for toxicity)
  2098. public function ReceivedCombatDamage()
  2099. {
  2100. receivedDamageInCombat = true;
  2101. }
  2102.  
  2103. ///////////////////////////////////////////////////////////////////////////
  2104. // @Uninterrupted hits
  2105. ///////////////////////////////////////////////////////////////////////////
  2106.  
  2107.  
  2108. timer function UninterruptedHitsResetOnIdle(dt : float, id : int)
  2109. {
  2110. ResetUninterruptedHitsCount();
  2111. }
  2112.  
  2113. public function ResetUninterruptedHitsCount()
  2114. {
  2115. uninterruptedHitsCount = 0;
  2116. LogUnitAtt("Uninterrupted attacks reset!!!!");
  2117. }
  2118.  
  2119. public function IncreaseUninterruptedHitsCount()
  2120. {
  2121. uninterruptedHitsCount += 1;
  2122. LogUnitAtt("Uninterrupted attacks count increased to " + uninterruptedHitsCount);
  2123.  
  2124. if(uninterruptedHitsCount == 4)
  2125. AddTimer('StartUninterruptedBlurr', 1, false);
  2126.  
  2127. //idle turn off timer
  2128. AddTimer('UninterruptedHitsResetOnIdle', 4.f, false);
  2129. }
  2130.  
  2131. timer function StartUninterruptedBlurr(dt : float, id : int)
  2132. {
  2133. var changed : bool;
  2134. var movingAgent : CMovingPhysicalAgentComponent;
  2135. var target : CActor;
  2136.  
  2137. //check if the timer is to be turned off
  2138. if(uninterruptedHitsCount < 4)
  2139. {
  2140. LogUnitAtt("Stopping camera effect");
  2141. thePlayer.StopEffect(uninterruptedHitsCurrentCameraEffect);
  2142. uninterruptedHitsCurrentCameraEffect = '';
  2143. uninterruptedHitsCameraStarted = false;
  2144. RemoveTimer('StartUninterruptedBlurr');
  2145. }
  2146. else //still valid
  2147. {
  2148. target = GetTarget();
  2149.  
  2150. if( target )
  2151. {
  2152. movingAgent = ( (CMovingPhysicalAgentComponent) (target.GetMovingAgentComponent()) );
  2153. }
  2154.  
  2155. if(!uninterruptedHitsCameraStarted)
  2156. {
  2157. LogUnitAtt("Starting camera effect");
  2158. AddTimer('StartUninterruptedBlurr', 0.001, true); //need to update per tick
  2159. if(movingAgent && movingAgent.GetCapsuleHeight() > 2)
  2160. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY;
  2161. else
  2162. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY;
  2163. thePlayer.PlayEffect(uninterruptedHitsCurrentCameraEffect);
  2164. uninterruptedHitsCameraStarted = true;
  2165. }
  2166. else
  2167. {
  2168. changed = false;
  2169. if(movingAgent && movingAgent.GetCapsuleHeight() > 2 && uninterruptedHitsCurrentCameraEffect != theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY)
  2170. changed = true;
  2171. else if(!movingAgent || ( movingAgent.GetCapsuleHeight() <= 2 && uninterruptedHitsCurrentCameraEffect != theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY) )
  2172. changed = true;
  2173.  
  2174. //if the target's height has changed then swap the camera effect
  2175. if(changed)
  2176. {
  2177. //stop current effect
  2178. thePlayer.StopEffect(uninterruptedHitsCurrentCameraEffect);
  2179.  
  2180. //change mode
  2181. if(uninterruptedHitsCurrentCameraEffect == theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY)
  2182. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY;
  2183. else
  2184. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY;
  2185.  
  2186. //turn new camera effect on
  2187. thePlayer.PlayEffect(uninterruptedHitsCurrentCameraEffect);
  2188. }
  2189. }
  2190. }
  2191. }
  2192.  
  2193. ///////////////////////////////////////////////////////////////////////////
  2194. // Exploration Actions
  2195. ///////////////////////////////////////////////////////////////////////////
  2196.  
  2197. private var playerActionEventListeners : array<CGameplayEntity>;
  2198. private var playerActionEventBlockingListeners : array<CGameplayEntity>;
  2199.  
  2200. private function PlayerActionBlockGameplayActions( sourceName : name, lock : bool, isFromPlace : bool )
  2201. {
  2202. if ( lock )
  2203. {
  2204. thePlayer.BlockAction( EIAB_Signs, sourceName, false, false, isFromPlace );
  2205. thePlayer.BlockAction( EIAB_DrawWeapon, sourceName, false, false, isFromPlace );
  2206. thePlayer.BlockAction( EIAB_CallHorse, sourceName, false, false, isFromPlace );
  2207. thePlayer.BlockAction( EIAB_FastTravel, sourceName, false, false, isFromPlace );
  2208. thePlayer.BlockAction( EIAB_Fists, sourceName, false, false, isFromPlace );
  2209. thePlayer.BlockAction( EIAB_InteractionAction, sourceName, false, false, isFromPlace );
  2210. thePlayer.DisableCombatState();
  2211. }
  2212. else
  2213. {
  2214. thePlayer.UnblockAction( EIAB_Signs, sourceName );
  2215. thePlayer.UnblockAction( EIAB_DrawWeapon, sourceName );
  2216. thePlayer.UnblockAction( EIAB_CallHorse, sourceName );
  2217. thePlayer.UnblockAction( EIAB_FastTravel, sourceName );
  2218. thePlayer.UnblockAction( EIAB_Fists, sourceName );
  2219. thePlayer.UnblockAction( EIAB_InteractionAction, sourceName );
  2220. }
  2221. }
  2222.  
  2223. public function GetPlayerActionEventListeners() : array<CGameplayEntity>
  2224. {
  2225. return playerActionEventListeners;
  2226. }
  2227.  
  2228. //Registers for event + blocks GameplayActions
  2229. public function RegisterForPlayerAction( listener : CGameplayEntity, isLockedByPlace : bool )
  2230. {
  2231. if ( !playerActionEventListeners.Contains( listener ) )
  2232. {
  2233. playerActionEventListeners.PushBack( listener );
  2234. }
  2235. if ( listener.ShouldBlockGameplayActionsOnInteraction() )
  2236. {
  2237. if ( !playerActionEventBlockingListeners.Contains( listener ) )
  2238. {
  2239. playerActionEventBlockingListeners.PushBack( listener );
  2240. }
  2241. if ( playerActionEventBlockingListeners.Size() == 1 )
  2242. {
  2243. PlayerActionBlockGameplayActions( 'PlayerAction', true, isLockedByPlace );
  2244. }
  2245. }
  2246. }
  2247.  
  2248. //Unregisters for event + unblocks GameplayActions
  2249. public function UnregisterForPlayerAction( listener : CGameplayEntity, isLockedByPlace : bool )
  2250. {
  2251. playerActionEventListeners.Remove( listener );
  2252. playerActionEventBlockingListeners.Remove( listener );
  2253. if ( playerActionEventBlockingListeners.Size() == 0 )
  2254. {
  2255. PlayerActionBlockGameplayActions( 'PlayerAction', false, isLockedByPlace );
  2256. }
  2257. }
  2258.  
  2259. event OnPlayerActionStart()
  2260. {
  2261. //MS: Only used for ProudWalk
  2262. thePlayer.SetBehaviorVariable( 'inJumpState', 1.f );
  2263. }
  2264.  
  2265. event OnPlayerActionEnd()
  2266. {
  2267. var i : int;
  2268. for ( i = playerActionEventListeners.Size() - 1; i >= 0; i-=1 )
  2269. {
  2270. playerActionEventListeners[i].OnPlayerActionEnd();
  2271. }
  2272. currentCustomAction = PEA_None;
  2273.  
  2274. //MS: Only used for ProudWalk
  2275. thePlayer.SetBehaviorVariable( 'inJumpState', 0.f );
  2276. }
  2277.  
  2278. event OnPlayerActionStartFinished()
  2279. {
  2280. var i : int;
  2281. for ( i = playerActionEventListeners.Size() - 1; i >= 0; i-=1 )
  2282. {
  2283. playerActionEventListeners[i].OnPlayerActionStartFinished();
  2284. }
  2285. }
  2286.  
  2287. function PlayerStartAction( playerAction : EPlayerExplorationAction, optional animName : name ) : bool
  2288. {
  2289. if ( playerAction == PEA_SlotAnimation && !IsNameValid(animName) )
  2290. {
  2291. return false;
  2292. }
  2293.  
  2294. SetBehaviorVariable( 'playerStopAction', 0.0);
  2295. SetBehaviorVariable( 'playerExplorationAction', (float)(int)playerAction);
  2296.  
  2297. /*if ( playerAction == PEA_SlotAnimation )
  2298. {
  2299. if ( !this.ActionPlaySlotAnimationAsync('PLAYER_ACTION_SLOT',animName) )
  2300. return false;
  2301. }*/
  2302.  
  2303. if ( RaiseForceEvent('playerActionStart') )
  2304. {
  2305. currentCustomAction = playerAction;
  2306. if ( playerAction == PEA_SlotAnimation )
  2307. {
  2308. playerActionSlotAnimName = animName;
  2309. AddTimer('PlayActionAnimWorkaround',0,false);
  2310. }
  2311. return true;
  2312. }
  2313. return false;
  2314. }
  2315.  
  2316. private var playerActionSlotAnimName : name;
  2317.  
  2318. timer function PlayActionAnimWorkaround( dt : float , id : int)
  2319. {
  2320. this.ActionPlaySlotAnimationAsync('PLAYER_ACTION_SLOT',playerActionSlotAnimName, 0.2, 0.2, true);
  2321. }
  2322.  
  2323. function PlayerStopAction( playerAction : EPlayerExplorationAction )
  2324. {
  2325. SetBehaviorVariable( 'playerExplorationAction', (float)(int)playerAction);
  2326. SetBehaviorVariable( 'playerStopAction', 1.0);
  2327. currentCustomAction = PEA_None;
  2328. }
  2329.  
  2330. function GetPlayerAction() : EPlayerExplorationAction
  2331. {
  2332. return currentCustomAction;
  2333. }
  2334.  
  2335. function MedallionPing()
  2336. {
  2337. var currTime : float = theGame.GetEngineTimeAsSeconds();
  2338.  
  2339. if ( lastMedallionEffect < currTime )
  2340. {
  2341. lastMedallionEffect = theGame.GetEngineTimeAsSeconds() + medallion.effectDuration;
  2342. medallion.TriggerMedallionFX();
  2343. }
  2344. }
  2345.  
  2346. ///////////////////////////////////////////////////////////////////////////
  2347. // @INTERACTIONS
  2348. ///////////////////////////////////////////////////////////////////////////
  2349.  
  2350. public function CanPerformPlayerAction(optional alsoOutsideExplorationState : bool) : bool
  2351. {
  2352. //if in exploration or in any state and flag set
  2353. if(!alsoOutsideExplorationState && GetCurrentStateName() != 'Exploration')
  2354. return false;
  2355.  
  2356. if( isInAir || (substateManager && !substateManager.CanInteract()) || IsInCombatAction() || GetCriticalBuffsCount() > 0)
  2357. return false;
  2358.  
  2359. return true;
  2360. }
  2361.  
  2362. //called when we receive an item
  2363. event OnItemGiven(data : SItemChangedData)
  2364. {
  2365. var keyName : name;
  2366. var i : int;
  2367. var hud : CR4ScriptedHud;
  2368. var message : string;
  2369. var inve : CInventoryComponent;
  2370.  
  2371. if(data.informGui)
  2372. {
  2373. hud = (CR4ScriptedHud)theGame.GetHud();
  2374. if(hud)
  2375. {
  2376. message = GetLocStringByKeyExt("panel_common_item_received") + ": " + GetLocStringByKeyExt(inv.GetItemLocalizedNameByUniqueID(data.ids[0]));
  2377. if(data.quantity > 1)
  2378. message += " x" + data.quantity;
  2379. hud.HudConsoleMsg(message);
  2380. }
  2381. }
  2382.  
  2383. inve = GetInventory(); //OnItemGiven can be called before we cache inventory component
  2384.  
  2385. //key - check if we're next to a lock that uses this key and update interaction if needed
  2386. if(inve.ItemHasTag(data.ids[0], 'key'))
  2387. {
  2388. keyName = inve.GetItemName(data.ids[0]);
  2389. for(i=nearbyLockedContainersNoKey.Size()-1; i>=0; i-=1)
  2390. {
  2391. if(nearbyLockedContainersNoKey[i].GetKeyName() == keyName && nearbyLockedContainersNoKey[i].IsEnabled())
  2392. {
  2393. nearbyLockedContainersNoKey[i].UpdateComponents("Unlock");
  2394. nearbyLockedContainersNoKey.Remove(nearbyLockedContainersNoKey[i]);
  2395. }
  2396. }
  2397. }
  2398.  
  2399. //alchemy level 3 items
  2400. if(inve.IsItemAlchemyItem(data.ids[0]))
  2401. {
  2402. UpgradeAlchemyItem(data.ids[0], CanUseSkill(S_Perk_08));
  2403. }
  2404.  
  2405. if(inve.ItemHasTag(data.ids[0], theGame.params.TAG_OFIR_SET))
  2406. CheckOfirSetAchievement();
  2407. }
  2408.  
  2409. private final function CheckOfirSetAchievement()
  2410. {
  2411. var hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders : bool;
  2412.  
  2413. //check player items
  2414. CheckOfirItems(GetInventory(), hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders);
  2415.  
  2416. //check stash items
  2417. CheckOfirItems(GetWitcherPlayer().GetHorseManager().GetInventoryComponent(), hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders);
  2418.  
  2419. if(hasArmor && hasBoots && hasGloves && hasPants && hasSword && hasSaddle && hasBag && hasBlinders)
  2420. theGame.GetGamerProfile().AddAchievement(EA_LatestFashion);
  2421. }
  2422.  
  2423. private final function CheckOfirItems(inv : CInventoryComponent, out hasArmor : bool, out hasBoots : bool, out hasGloves : bool, out hasPants : bool, out hasSword : bool, out hasSaddle : bool, out hasBag : bool, out hasBlinders : bool)
  2424. {
  2425. var ofirs : array<SItemUniqueId>;
  2426. var i : int;
  2427.  
  2428. ofirs = inv.GetItemsByTag(theGame.params.TAG_OFIR_SET);
  2429. for(i=0; i<ofirs.Size(); i+=1)
  2430. {
  2431. if(inv.IsItemChestArmor(ofirs[i]))
  2432. {
  2433. hasArmor = true;
  2434. continue;
  2435. }
  2436. else if(inv.IsItemBoots(ofirs[i]))
  2437. {
  2438. hasBoots = true;
  2439. continue;
  2440. }
  2441. else if(inv.IsItemGloves(ofirs[i]))
  2442. {
  2443. hasGloves = true;
  2444. continue;
  2445. }
  2446. else if(inv.IsItemPants(ofirs[i]))
  2447. {
  2448. hasPants = true;
  2449. continue;
  2450. }
  2451. else if(inv.IsItemSteelSwordUsableByPlayer(ofirs[i]))
  2452. {
  2453. hasSword = true;
  2454. continue;
  2455. }
  2456. else if(inv.IsItemSilverSwordUsableByPlayer(ofirs[i]))
  2457. {
  2458. hasSword = true;
  2459. continue;
  2460. }
  2461. else if(inv.IsItemSaddle(ofirs[i]))
  2462. {
  2463. hasSaddle = true;
  2464. continue;
  2465. }
  2466. else if(inv.IsItemHorseBag(ofirs[i]))
  2467. {
  2468. hasBag = true;
  2469. continue;
  2470. }
  2471. else if(inv.IsItemBlinders(ofirs[i]))
  2472. {
  2473. hasBlinders = true;
  2474. continue;
  2475. }
  2476. }
  2477. }
  2478.  
  2479. //changes all alchemy items of level 3 abilities from level 2 to 3 (if upgrade) or from 3 to 2 (if not upgrading)
  2480. public function ChangeAlchemyItemsAbilities(upgrade : bool)
  2481. {
  2482. var i : int;
  2483. var dm : CDefinitionsManagerAccessor;
  2484. var items : array<SItemUniqueId>;
  2485.  
  2486. inv.GetAllItems(items);
  2487. dm = theGame.GetDefinitionsManager();
  2488.  
  2489. for(i=0; i<items.Size(); i+=1)
  2490. if(inv.IsItemAlchemyItem(items[i]))
  2491. UpgradeAlchemyItem(items[i], upgrade);
  2492. }
  2493.  
  2494. //changes all alchemy items of level 3 abilities from level 2 to 3 (if upgrade) or from 3 to 2 (if not upgrading)
  2495. public function UpgradeAlchemyItem(itemID : SItemUniqueId, upgrade : bool)
  2496. {
  2497. var j, currLevel, otherLevel : int;
  2498. var dm : CDefinitionsManagerAccessor;
  2499. var abs, currAbilities, otherAbilities : array<name>;
  2500. var min, max : SAbilityAttributeValue;
  2501.  
  2502. if(!inv.IsItemAlchemyItem(itemID))
  2503. return;
  2504.  
  2505. //get current level
  2506. currLevel = (int)CalculateAttributeValue(inv.GetItemAttributeValue(itemID, 'level'));
  2507.  
  2508. //if level ok then exit
  2509. if(currLevel == 3 || currLevel == 2 || currLevel < 2 || currLevel > 3)
  2510. return;
  2511.  
  2512. //get current ability name
  2513. currAbilities = inv.GetItemAbilitiesWithAttribute(itemID, 'level', currLevel);
  2514.  
  2515. //get other ability name
  2516. inv.GetItemContainedAbilities(itemID, abs);
  2517. dm = theGame.GetDefinitionsManager();
  2518. for(j=0; j<abs.Size(); j+=1)
  2519. {
  2520. dm.GetAbilityAttributeValue(abs[j], 'level', min, max);
  2521. otherLevel = (int)CalculateAttributeValue(GetAttributeRandomizedValue(min, max));
  2522. if( (otherLevel == 2 || otherLevel == 3) && otherLevel != currLevel)
  2523. otherAbilities.PushBack(abs[j]);
  2524. }
  2525.  
  2526. //swap abilities
  2527. if(otherAbilities.Size() == 0)
  2528. {
  2529. LogAssert(false, "CR4Player.UpgradeAlchemyItem: cannot find ability to swap to from <<" + currAbilities[0] + ">> on item <<" + inv.GetItemName(itemID) + ">> !!!");
  2530. }
  2531. else
  2532. {
  2533. for(j=0; j<currAbilities.Size(); j+=1)
  2534. inv.RemoveItemBaseAbility(itemID, currAbilities[j]);
  2535.  
  2536. for(j=0; j<otherAbilities.Size(); j+=1)
  2537. inv.AddItemBaseAbility(itemID, otherAbilities[j]);
  2538. }
  2539. }
  2540.  
  2541. ///////////////////////////////////////////////////////////////////////////
  2542. // Movement adjustment helper functions
  2543. ///////////////////////////////////////////////////////////////////////////
  2544.  
  2545. public function MovAdjRotateToTarget( ticket : SMovementAdjustmentRequestTicket )
  2546. {
  2547. var movementAdjustor : CMovementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  2548. var localOrientationTarget : EOrientationTarget = GetOrientationTarget();
  2549.  
  2550. if ( localOrientationTarget == OT_CustomHeading )
  2551. {
  2552. movementAdjustor.RotateTo( ticket, GetOrientationTargetCustomHeading() );
  2553. }
  2554. else if ( localOrientationTarget == OT_Actor )
  2555. {
  2556. /*if ( parryTarget && IsGuarded() )
  2557. movementAdjustor.RotateTowards( ticket, parryTarget );
  2558. else*/ if ( slideTarget )
  2559. movementAdjustor.RotateTowards( ticket, slideTarget );
  2560. else if ( lAxisReleasedAfterCounter )
  2561. movementAdjustor.RotateTo( ticket, GetHeading() );
  2562. else
  2563. movementAdjustor.RotateTo( ticket, GetCombatActionHeading() );//rawPlayerHeading );
  2564. }
  2565. else if ( localOrientationTarget == OT_Player )
  2566. {
  2567. if ( bLAxisReleased )
  2568. movementAdjustor.RotateTo( ticket, GetHeading() );
  2569. else
  2570. movementAdjustor.RotateTo( ticket, rawPlayerHeading );//GetCombatActionHeading() );
  2571. }
  2572. else if ( localOrientationTarget == OT_CameraOffset )
  2573. {
  2574. //movementAdjustor.RotateTo( ticket, VecHeading( cachedCameraVector ) );//rawCameraHeading - oTCameraOffset );
  2575. movementAdjustor.RotateTo( ticket, VecHeading( theCamera.GetCameraDirection() ) );//rawCameraHeading );
  2576. }
  2577. else
  2578. {
  2579. // default to camera
  2580. movementAdjustor.RotateTo( ticket, rawCameraHeading );
  2581. }
  2582. // never rotate to player
  2583. }
  2584.  
  2585. ////////////////////////////////////////////////////////////////////////////////////
  2586. // Look at targets - moved here from movables
  2587. ////////////////////////////////////////////////////////////////////////////////////
  2588. //var cachedCameraVector : Vector;
  2589. public function UpdateLookAtTarget()
  2590. {
  2591. var localOrientationTarget : EOrientationTarget;
  2592. var playerRot : EulerAngles;
  2593. var lookAtActive : Float;
  2594. var lookAtTarget : Vector;
  2595. var headBoneIdx : int;
  2596. var tempComponent : CDrawableComponent;
  2597. var entityHeight : float;
  2598. var useTorsoBone : bool;
  2599.  
  2600. var angles : EulerAngles;
  2601. var dir : Vector;
  2602. var camZ : float;
  2603.  
  2604. var target : CActor;
  2605.  
  2606. lookAtActive = 0.0f;
  2607.  
  2608. localOrientationTarget = GetOrientationTarget();
  2609.  
  2610. if ( localOrientationTarget == OT_Player || localOrientationTarget == OT_CustomHeading )
  2611. {
  2612. /*headBoneIdx = GetTorsoBoneIndex();
  2613. if ( headBoneIdx >= 0 )
  2614. {
  2615. lookAtTarget = MatrixGetTranslation( GetBoneWorldMatrixByIndex( headBoneIdx ) );
  2616. }*/
  2617.  
  2618. //lookAtTarget = GetHeadingVector() * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2619.  
  2620. if ( localOrientationTarget == OT_Player )
  2621. angles = VecToRotation( GetHeadingVector() );
  2622. else if ( customOrientationInfoStack.Size() > 0 )
  2623. angles = VecToRotation( VecFromHeading( customOrientationInfoStack[ customOrientationInfoStack.Size() - 1 ].customHeading ) );
  2624. else
  2625. angles = VecToRotation( GetHeadingVector() );
  2626.  
  2627. //angles.Pitch = oTCameraPitchOffset;
  2628. dir = RotForward( angles );
  2629. lookAtTarget = dir * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2630. lookAtTarget.Z += 1.6f;
  2631. lookAtActive = 1.0f;
  2632. }
  2633. else if ( localOrientationTarget == OT_Camera )
  2634. {
  2635. headBoneIdx = GetHeadBoneIndex();
  2636. if ( headBoneIdx >= 0 )
  2637. {
  2638. lookAtTarget = MatrixGetTranslation( GetBoneWorldMatrixByIndex( headBoneIdx ) );
  2639. }
  2640. else
  2641. {
  2642. lookAtTarget = GetWorldPosition();
  2643. lookAtTarget.Z += 1.6f; // fake head?
  2644. }
  2645. lookAtTarget += theCamera.GetCameraDirection() * 100.f;
  2646. lookAtActive = 1.0f;
  2647. }
  2648. else if ( localOrientationTarget == OT_CameraOffset )
  2649. {
  2650. /*lookAtTarget = GetWorldPosition();
  2651. lookAtTarget.Z += 1.6f; // fake head?
  2652. camDir = theCamera.GetCameraDirection();
  2653. camZ = camDir.Z;// + 0.1;
  2654. camDir = VecFromHeading( VecHeading( theCamera.GetCameraDirection() ) - oTCameraOffset ) * VecLength2D( camDir );
  2655. camDir.Z = camZ;*/
  2656.  
  2657. dir = theCamera.GetCameraDirection();
  2658. angles = VecToRotation( dir );
  2659. angles.Pitch = -angles.Pitch + oTCameraPitchOffset;
  2660. angles.Yaw -= oTCameraOffset;
  2661. dir = RotForward( angles );
  2662.  
  2663. lookAtTarget = dir * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2664. lookAtTarget.Z += 1.6f;
  2665. lookAtActive = 1.0f;
  2666. }
  2667. else if ( localOrientationTarget == OT_Actor )
  2668. {
  2669. if ( IsInCombatAction() )
  2670. {
  2671. if ( ( ( ( W3PlayerWitcher )this ).GetCurrentlyCastSign() != ST_None && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign )
  2672. || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_ItemThrow )
  2673. //|| GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Crossbow )
  2674. useTorsoBone = true;
  2675. }
  2676.  
  2677. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  2678. useTorsoBone = true;
  2679.  
  2680. if ( tempLookAtTarget && (CActor)(tempLookAtTarget) )
  2681. {
  2682. lookAtTarget = ProcessLookAtTargetPosition( tempLookAtTarget, useTorsoBone );
  2683. lookAtActive = 1.0f;
  2684. }
  2685.  
  2686. if ( GetDisplayTarget() && IsDisplayTargetTargetable() )
  2687. {
  2688. lookAtTarget = ProcessLookAtTargetPosition( GetDisplayTarget(), useTorsoBone );
  2689. lookAtActive = 1.0f;
  2690. }
  2691. else
  2692. {
  2693. //FAIL SAFE in case the displayTarget disappears for some reason
  2694.  
  2695. if ( slideTarget )
  2696. {
  2697. lookAtTarget = ProcessLookAtTargetPosition( slideTarget, useTorsoBone );
  2698. }
  2699. else
  2700. {
  2701. target = GetTarget();
  2702. if ( target )
  2703. {
  2704. lookAtTarget = ProcessLookAtTargetPosition( target, useTorsoBone );
  2705. }
  2706. }
  2707.  
  2708. lookAtActive = 1.0f;
  2709. }
  2710.  
  2711. if ( !slideTarget && !IsUsingVehicle() )
  2712. {
  2713. // TODO maybe just get axis from head?
  2714. playerRot = GetWorldRotation();
  2715. lookAtTarget = GetWorldPosition() + VecFromHeading( playerRot.Yaw ) * 100.0f;
  2716. lookAtActive = 0.0f;
  2717. }
  2718.  
  2719. if ( useTorsoBone )
  2720. lookAtTarget.Z += 0.2f;
  2721. }
  2722.  
  2723.  
  2724. //lookAtTarget = player.GetHeadingVector() * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2725. //lookAtActive = 1.0f;
  2726. GetVisualDebug().AddSphere('lookAtTarget', 1.f, lookAtTarget, true, Color(255,0,0), 3.0f );
  2727. SetLookAtPosition( lookAtTarget );
  2728. UpdateLookAtVariables( lookAtActive, lookAtTarget );
  2729. }
  2730.  
  2731. private function ProcessLookAtTargetPosition( ent : CGameplayEntity, useTorsoBone : bool ) : Vector
  2732. {
  2733. var boneIdx : int;
  2734. var actor : CActor;
  2735. var lookAtTarget : Vector;
  2736. var tempComponent : CDrawableComponent;
  2737. var box : Box;
  2738. var entityHeight : float;
  2739. var entityPos : Vector;
  2740. var predictedPos : Vector;
  2741. var z : float;
  2742. var entMat : Matrix;
  2743.  
  2744. actor = (CActor)(ent);
  2745. entityPos = ent.GetWorldPosition();
  2746. lookAtTarget = entityPos;
  2747.  
  2748. if ( actor )
  2749. {
  2750. if ( useTorsoBone )
  2751. boneIdx = actor.GetTorsoBoneIndex();
  2752. else
  2753. boneIdx = actor.GetHeadBoneIndex();
  2754. }
  2755. else
  2756. boneIdx = -1;
  2757.  
  2758. if ( !( ent.aimVector.X == 0 && ent.aimVector.Y == 0 && ent.aimVector.Z == 0 ) )
  2759. {
  2760. entMat = ent.GetLocalToWorld();
  2761. lookAtTarget = VecTransform( entMat, ent.aimVector );
  2762. }
  2763. else if ( boneIdx >= 0 )
  2764. {
  2765. lookAtTarget = MatrixGetTranslation( ent.GetBoneWorldMatrixByIndex( boneIdx ) );
  2766. }
  2767. else
  2768. {
  2769. if ( actor )
  2770. lookAtTarget.Z += ( ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetCapsuleHeight() * 0.5 ); // fake head?
  2771. else
  2772. {
  2773. tempComponent = (CDrawableComponent)( ent.GetComponentByClassName('CDrawableComponent') );
  2774. if ( tempComponent.GetObjectBoundingVolume( box ) )
  2775. {
  2776. entityHeight = box.Max.Z - box.Min.Z;
  2777. lookAtTarget = lookAtTarget + Vector(0,0,entityHeight/2);
  2778. }
  2779. }
  2780. }
  2781. z = ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetCapsuleHeight();
  2782. if ( actor )
  2783. {
  2784. if ( PredictLookAtTargetPosition( actor, lookAtTarget.Z - entityPos.Z, predictedPos ) )
  2785. lookAtTarget = predictedPos;
  2786. }
  2787.  
  2788. return lookAtTarget;
  2789. }
  2790.  
  2791.  
  2792. private function PredictLookAtTargetPosition( targetActor : CActor, zOffSet : float, out predictedPos : Vector ) : bool
  2793. {
  2794. var virtualPos : Vector;
  2795. var i : int;
  2796. var dist : float;
  2797. var deltaTime : float;
  2798. var projSpeed : float;
  2799. var projSpeedInt : Vector;
  2800. var projAngle : float;
  2801.  
  2802. var e3Hack : bool;
  2803. var currentTimeInCurve : float;
  2804. e3Hack = false;
  2805.  
  2806. if ( rangedWeapon
  2807. && rangedWeapon.GetDeployedEntity()
  2808. && ( rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' || rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' ) )
  2809. {
  2810. projSpeed = rangedWeapon.GetDeployedEntity().projSpeed;
  2811.  
  2812. virtualPos = targetActor.GetWorldPosition();
  2813.  
  2814. if ( e3Hack && targetActor.HasTag( 'e3_griffin' ) )
  2815. {
  2816. for ( i = 0; i < 10; i += 1 )
  2817. {
  2818. dist = VecDistance( rangedWeapon.GetDeployedEntity().GetWorldPosition(), virtualPos );
  2819. deltaTime = dist/projSpeed;
  2820. virtualPos = targetActor.PredictWorldPosition( deltaTime );
  2821. }
  2822. }
  2823. else
  2824. return false;
  2825.  
  2826. virtualPos.Z += zOffSet;
  2827. predictedPos = virtualPos;
  2828. GetVisualDebug().AddSphere('CrossbowPredictedPos', 1.0f, virtualPos , true, Color(255,50,50), 5.0f );
  2829. return true;
  2830. }
  2831. return false;
  2832. }
  2833.  
  2834. public function SetLookAtPosition( vec : Vector )
  2835. {
  2836. lookAtPosition = vec;
  2837. }
  2838.  
  2839. public function GetLookAtPosition() : Vector
  2840. {
  2841. return lookAtPosition;
  2842. }
  2843.  
  2844. ////////////////////////////////////////////////////////////////////////////////////
  2845. // Scene
  2846. ////////////////////////////////////////////////////////////////////////////////////
  2847.  
  2848. event OnBlockingSceneEnded( optional output : CStorySceneOutput)
  2849. {
  2850. //hack for possible immortality from finishers
  2851. SetImmortalityMode( AIM_None, AIC_SyncedAnim );
  2852. super.OnBlockingSceneEnded(output);
  2853. }
  2854.  
  2855. ////////////////////////////////////////////////////////////////////////////////////
  2856. // New combat / exploration and weapon drawing
  2857. ////////////////////////////////////////////////////////////////////////////////////
  2858.  
  2859. function GetCurrentMeleeWeaponName() : name
  2860. {
  2861. return weaponHolster.GetCurrentMeleeWeaponName();
  2862. }
  2863.  
  2864. public function GetCurrentMeleeWeaponType() : EPlayerWeapon
  2865. {
  2866. return weaponHolster.GetCurrentMeleeWeapon();
  2867. }
  2868.  
  2869. public function OnMeleeForceHolster(ignoreActionLock : bool)
  2870. {
  2871. weaponHolster.HolsterWeapon(ignoreActionLock, true);
  2872. }
  2873.  
  2874. event OnForcedHolsterWeapon()
  2875. {
  2876. weaponHolster.OnForcedHolsterWeapon();
  2877. }
  2878.  
  2879. event OnEquippedItem( category : name, slotName : name )
  2880. {
  2881. var weaponType : EPlayerWeapon;
  2882.  
  2883. if ( slotName == 'r_weapon' )
  2884. {
  2885. switch ( category )
  2886. {
  2887. case 'None' :
  2888. weaponType = PW_None;
  2889. break;
  2890. case 'fist' :
  2891. weaponType = PW_Fists;
  2892. break;
  2893. case 'steelsword' :
  2894. weaponType = PW_Steel;
  2895. break;
  2896. case 'silversword' :
  2897. weaponType = PW_Silver;
  2898. break;
  2899. default :
  2900. return true;
  2901. }
  2902.  
  2903. weaponHolster.OnEquippedMeleeWeapon( weaponType );
  2904. }
  2905. }
  2906.  
  2907. private var isHoldingDeadlySword : bool;
  2908. public function ProcessIsHoldingDeadlySword()
  2909. {
  2910. isHoldingDeadlySword = IsDeadlySwordHeld();
  2911. }
  2912.  
  2913. public function IsHoldingDeadlySword() : bool
  2914. {
  2915. return isHoldingDeadlySword;
  2916. }
  2917.  
  2918. event OnHolsteredItem( category : name, slotName : name )
  2919. {
  2920. var weaponType : EPlayerWeapon;
  2921.  
  2922. if ( slotName == 'r_weapon' )
  2923. {
  2924. weaponType = weaponHolster.GetCurrentMeleeWeapon();
  2925. switch ( category )
  2926. {
  2927. case 'fist' :
  2928. if ( weaponType == PW_Fists )
  2929. weaponHolster.OnEquippedMeleeWeapon( PW_None );
  2930. return true;
  2931. case 'steelsword' :
  2932. if ( weaponType == PW_Steel )
  2933. weaponHolster.OnEquippedMeleeWeapon( PW_None );
  2934. return true;
  2935. case 'silversword' :
  2936. if ( weaponType == PW_Silver )
  2937. weaponHolster.OnEquippedMeleeWeapon( PW_None );
  2938. return true;
  2939. default :
  2940. return true;
  2941. }
  2942. }
  2943. }
  2944.  
  2945. event OnEquipMeleeWeapon( weaponType : EPlayerWeapon, ignoreActionLock : bool, optional sheatheIfAlreadyEquipped : bool )
  2946. {
  2947. RemoveTimer( 'DelayedSheathSword' );
  2948.  
  2949. weaponHolster.OnEquipMeleeWeapon( weaponType, ignoreActionLock, sheatheIfAlreadyEquipped );
  2950.  
  2951. /*// Check if we want to go to combat or exploration
  2952. if( weaponHolster.GetCurrentMeleeWeapon() == PW_None )
  2953. {
  2954. GoToExplorationIfNeeded( );
  2955. }
  2956. else
  2957. {
  2958. GoToCombatIfNeeded( );
  2959. }*/
  2960.  
  2961. m_RefreshWeaponFXType = true;
  2962. }
  2963.  
  2964. event OnHolsterLeftHandItem()
  2965. {
  2966. weaponHolster.OnHolsterLeftHandItem();
  2967. }
  2968.  
  2969. timer function DelayedSheathSword( dt: float, id : int )
  2970. {
  2971. if ( !IsCombatMusicEnabled() )
  2972. {
  2973. if ( IsInCombatAction() || !IsActionAllowed( EIAB_DrawWeapon ) )
  2974. {
  2975. LogChannel( 'OnCombatFinished', "DelayedSheathSword: Sheath pushed to buffer" );
  2976. PushCombatActionOnBuffer(EBAT_Sheathe_Sword,BS_Pressed);
  2977. }
  2978. else
  2979. {
  2980. LogChannel( 'OnCombatFinished', "DelayedSheathSword: Sheath successful" );
  2981. OnEquipMeleeWeapon( PW_None, false );
  2982. }
  2983. }
  2984. }
  2985.  
  2986. protected function ShouldAutoSheathSwordInstantly() : bool
  2987. {
  2988. var enemies : array<CActor>;
  2989. var i : int;
  2990.  
  2991. GetEnemiesInRange( enemies );
  2992.  
  2993. for ( i = 0; i < enemies.Size(); i += 1 )
  2994. {
  2995. if ( IsThreat( enemies[i] ) &&
  2996. VecDistance( enemies[i].GetWorldPosition(), this.GetWorldPosition() ) <= findMoveTargetDist )
  2997. {
  2998. return false;
  2999. }
  3000. }
  3001.  
  3002. return true;
  3003. }
  3004.  
  3005. public function PrepareToAttack( optional target : CActor, optional action : EBufferActionType )
  3006. {
  3007. var weaponType : EPlayerWeapon;
  3008.  
  3009. if( IsInAir() || !GetBIsCombatActionAllowed() )
  3010. {
  3011. return ;
  3012. }
  3013.  
  3014. if( !target )
  3015. {
  3016. target = (CActor)displayTarget;
  3017. }
  3018. if( !target && IsCombatMusicEnabled() )
  3019. {
  3020. target = moveTarget;
  3021. }
  3022. if( !target )
  3023. {
  3024. if ( this.GetCurrentStateName() == 'Exploration' )
  3025. {
  3026. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  3027. thePlayer.CanAttackWhenNotInCombat( action, false, target );
  3028. }
  3029. }
  3030.  
  3031. weaponHolster.TryToPrepareMeleeWeaponToAttack();
  3032.  
  3033. //if ( this.GetCurrentStateName() == 'Exploration' ) //PF - commenting this because Geralt won't switch to proper state when you sheathe sword while mashing attack
  3034. {
  3035. weaponType = GetCurrentMeleeWeaponType();
  3036.  
  3037. if ( weaponType == PW_None )
  3038. {
  3039. // Get the weapon we have to use
  3040. weaponType = GetMostConvenientMeleeWeapon( target );
  3041. }
  3042.  
  3043. // Can't go to combat if we are in not a proper state
  3044. if( !OnStateCanGoToCombat() )
  3045. {
  3046. return;
  3047. }
  3048.  
  3049. GoToCombat( weaponType );
  3050. }
  3051. }
  3052.  
  3053. public function DisplayCannotAttackMessage( actor : CActor ) : bool
  3054. {
  3055. if ( actor && ( actor.GetMovingAgentComponent().GetName() == "child_base" || ((CNewNPC)actor).GetNPCType() == ENGT_Quest ) )
  3056. {
  3057. DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_cant_attack_this_target"));
  3058. return true;
  3059. }
  3060.  
  3061. return false;
  3062. }
  3063.  
  3064. public function GetMostConvenientMeleeWeapon( targetToDrawAgainst : CActor, optional ignoreActionLock : bool ) : EPlayerWeapon
  3065. {
  3066. return weaponHolster.GetMostConvenientMeleeWeapon( targetToDrawAgainst, ignoreActionLock );
  3067. }
  3068.  
  3069. private var reevaluateCurrentWeapon : bool;
  3070.  
  3071. event OnTargetWeaponDrawn()
  3072. {
  3073. var weaponType : EPlayerWeapon = this.GetCurrentMeleeWeaponType();
  3074. if ( weaponType == PW_Fists )
  3075. reevaluateCurrentWeapon = true;
  3076. }
  3077.  
  3078. public function GoToCombatIfNeeded( optional enemy : CActor ) : bool
  3079. {
  3080. var weaponType : EPlayerWeapon;
  3081. var target : CActor;
  3082.  
  3083. if( !enemy && IsInCombat() )
  3084. {
  3085. target = GetTarget();
  3086.  
  3087. if ( target )
  3088. enemy = target;
  3089. else
  3090. enemy = moveTarget;
  3091. }
  3092.  
  3093. // Should we fight
  3094. if( !ShouldGoToCombat( enemy ) )
  3095. {
  3096. return false;
  3097. }
  3098.  
  3099. weaponType = this.GetCurrentMeleeWeaponType();
  3100.  
  3101. if ( weaponType == PW_None || ( reevaluateCurrentWeapon && weaponType == PW_Fists ) || ( !IsInCombat() && weaponHolster.IsOnTheMiddleOfHolstering() ) )
  3102. {
  3103. // Get the weapon we have to use
  3104. weaponType = weaponHolster.GetMostConvenientMeleeWeapon( enemy );
  3105. reevaluateCurrentWeapon = false;
  3106. }
  3107.  
  3108. // Change the state+
  3109. GoToCombat( weaponType );
  3110.  
  3111.  
  3112. return true;
  3113. }
  3114.  
  3115. public function GoToCombatIfWanted( ) : bool
  3116. {
  3117. var weaponType : EPlayerWeapon;
  3118. var target : CActor;
  3119. var enemy : CActor;
  3120.  
  3121.  
  3122. if( !IsInCombat() )
  3123. {
  3124. return false;
  3125. }
  3126.  
  3127. target = GetTarget();
  3128.  
  3129. if ( target )
  3130. enemy = target;
  3131. else
  3132. enemy = moveTarget;
  3133.  
  3134. weaponType = this.GetCurrentMeleeWeaponType();
  3135.  
  3136. if ( weaponType == PW_None || ( !IsInCombat() && weaponHolster.IsOnTheMiddleOfHolstering() ) )
  3137. {
  3138. // Get the weapon we have to use
  3139. weaponType = weaponHolster.GetMostConvenientMeleeWeapon( enemy );
  3140. }
  3141.  
  3142. // Change the state+
  3143. GoToCombat( weaponType );
  3144.  
  3145.  
  3146. return true;
  3147. }
  3148.  
  3149. public function GoToExplorationIfNeeded() : bool
  3150. {
  3151. /*
  3152. if( GetCurrentStateName() == 'Exploration' )
  3153. {
  3154. return false;
  3155. }
  3156. */
  3157.  
  3158. if( ! IsInCombatState() )
  3159. {
  3160. return false;
  3161. }
  3162.  
  3163. if( !ShouldGoToExploration() )
  3164. {
  3165. return false;
  3166. }
  3167.  
  3168. // Change fists weapon to none
  3169. weaponHolster.EndedCombat();
  3170.  
  3171. // Change the state
  3172. GotoState( 'Exploration' );
  3173. return true;
  3174. }
  3175.  
  3176. event OnStateCanGoToCombat()
  3177. {
  3178. return false;
  3179. }
  3180.  
  3181. event OnStateCanUpdateExplorationSubstates()
  3182. {
  3183. return false;
  3184. }
  3185.  
  3186. private function ShouldGoToCombat( optional enemy : CActor ) : bool
  3187. {
  3188. // TODO If we don't have a specific enemy, let's just check if there are hostiles to fight
  3189. if ( !enemy )
  3190. {
  3191. //return isFightingHostiles;
  3192. return false;
  3193. }
  3194.  
  3195. // Can't go to combat if we are in not a proper state
  3196. if( !OnStateCanGoToCombat() )
  3197. {
  3198. return false;
  3199. }
  3200.  
  3201. // See if we should be fighting this enemy
  3202. /*if ( !IsEnemyVisible( enemy ) )
  3203. {
  3204. return false;
  3205. }*/
  3206. /*if ( !WasVisibleInScaledFrame( enemy, 1.f, 1.f ) )
  3207. {
  3208. return false;
  3209. }*/
  3210.  
  3211. if ( this.GetCurrentStateName() == 'AimThrow' )
  3212. {
  3213. return false;
  3214. }
  3215.  
  3216. if ( this.GetCurrentStateName() == 'Swimming' )
  3217. {
  3218. return false;
  3219. }
  3220.  
  3221. if ( this.GetCurrentStateName() == 'TraverseExploration' )
  3222. {
  3223. return false;
  3224. }
  3225.  
  3226.  
  3227. // Temporaryly disabled cause it does not work on some terrain
  3228. /*
  3229. if ( !theGame.GetWorld().NavigationLineTest( GetWorldPosition(), enemy.GetWorldPosition(), 0.4 ) )
  3230.  
  3231. {
  3232. return false;
  3233. }
  3234. */
  3235.  
  3236. return true;
  3237. }
  3238.  
  3239. private function ShouldGoToExploration() : bool
  3240. {
  3241. if ( IsInCombat() )//moveTarget && IsThreat( moveTarget ) )
  3242. {
  3243. return false;
  3244. }
  3245. /*if( IsGuarded() )
  3246. {
  3247. return false;
  3248. }*/
  3249. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  3250. {
  3251. return false;
  3252. }
  3253. if( IsFistFightMinigameEnabled() )
  3254. {
  3255. return false;
  3256. }
  3257. if( IsKnockedUnconscious() )
  3258. {
  3259. return false;
  3260. }
  3261. if( IsInCombatAction() )
  3262. {
  3263. return false;
  3264. }
  3265. if( GetCriticalBuffsCount() > 0 )
  3266. {
  3267. return false;
  3268. }
  3269.  
  3270. return true;
  3271. }
  3272.  
  3273. private function GoToCombat( weaponType : EPlayerWeapon, optional initialAction : EInitialAction )
  3274. {
  3275. // Set up and change state
  3276. switch( weaponType )
  3277. {
  3278. case PW_Silver:
  3279. ((W3PlayerWitcherStateCombatSilver) GetState('CombatSilver')).SetupState( initialAction );
  3280. GoToStateIfNew( 'CombatSilver' );
  3281. break;
  3282. case PW_Steel:
  3283. ((W3PlayerWitcherStateCombatSteel) GetState('CombatSteel')).SetupState( initialAction );
  3284. GoToStateIfNew( 'CombatSteel' );
  3285. break;
  3286. case PW_Fists:
  3287. case PW_None:
  3288. default :
  3289. ((W3PlayerWitcherStateCombatFists) GetState('CombatFists')).SetupState( initialAction );
  3290. GoToStateIfNew( 'CombatFists' );
  3291. break;
  3292. }
  3293. }
  3294.  
  3295. public function GoToStateIfNew( newState : name, optional keepStack : bool, optional forceEvents : bool )
  3296. {
  3297. if( newState != GetCurrentStateName() )
  3298. {
  3299. GotoState( newState, keepStack, forceEvents );
  3300. }
  3301. }
  3302.  
  3303. // So we can debug and control what is changing the state
  3304. public function GotoState( newState : name, optional keepStack : bool, optional forceEvents : bool )
  3305. {
  3306. /*if( newState == 'Exploration' )
  3307. {
  3308. newState = newState;
  3309. }*/
  3310.  
  3311. super.GotoState( newState, keepStack, forceEvents );
  3312. //PushState( newState );
  3313. }
  3314. /*
  3315. public function PushState( newState : name )
  3316. {
  3317. if( newState == 'Exploration' )
  3318. {
  3319. newState = newState;
  3320. }
  3321. super.PushState( newState );
  3322. }
  3323.  
  3324. public function PopState( optional popAll : bool )
  3325. {
  3326. super.PopState( popAll );
  3327. }
  3328. */
  3329. public function IsThisACombatSuperState( stateName : name ) : bool
  3330. {
  3331. return stateName == 'Combat' || stateName == 'CombatSteel' || stateName == 'CombatSilver' || stateName == 'CombatFists';
  3332. }
  3333.  
  3334. public function GetWeaponHolster() : WeaponHolster
  3335. {
  3336. return weaponHolster;
  3337. }
  3338.  
  3339. public function AbortSign()
  3340. {
  3341. var playerWitcher : W3PlayerWitcher;
  3342. var sign : W3SignEntity;
  3343.  
  3344. playerWitcher = (W3PlayerWitcher)this;
  3345.  
  3346. if(playerWitcher)
  3347. {
  3348. sign = (W3SignEntity)playerWitcher.GetCurrentSignEntity();
  3349. if (sign)
  3350. {
  3351. sign.OnSignAborted();
  3352. }
  3353. }
  3354. }
  3355.  
  3356. ///////////////////////////////////////////////////////////////////////////
  3357. // Animation event handlers
  3358. ///////////////////////////////////////////////////////////////////////////
  3359. protected var disableActionBlend : bool;
  3360.  
  3361. //KonradSuperDodgeHACK: To make dodge more responsive during NORMAL ATTACKS, dodge will fire immediately when hit animation can be played.
  3362. //When hit anim is disabled, then the action will be cached and will be processed at the END of DisallowHitAnim event.
  3363. //During all other actions, however, it will use the normal check of inputAllowed and combatActionAllowed. This is a super hack. And we will all go to hell for this.
  3364. event OnAnimEvent_DisallowHitAnim( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3365. {
  3366. if ( animEventType == AET_DurationEnd )
  3367. {
  3368. if ( ( BufferCombatAction == EBAT_Dodge || BufferCombatAction == EBAT_Roll )
  3369. && IsInCombatAction()
  3370. && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack )
  3371. {
  3372. //LogChannel('combatActionAllowed',"BufferCombatAction != EBAT_EMPTY");
  3373. ( (CR4Player)this ).ProcessCombatActionBuffer();
  3374. disableActionBlend = true;
  3375. }
  3376. }
  3377. else if ( IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge && animEventType == AET_DurationStart )
  3378. {
  3379. disableActionBlend = false;
  3380. }
  3381.  
  3382. super.OnAnimEvent_DisallowHitAnim( animEventName, animEventType, animInfo );
  3383. }
  3384.  
  3385.  
  3386. event OnAnimEvent_FadeOut( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3387. {
  3388. theGame.FadeOutAsync( 0.2, Color( 0, 0, 0, 1 ) );
  3389. }
  3390.  
  3391. event OnAnimEvent_FadeIn( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3392. {
  3393. theGame.FadeInAsync( 0.4 );
  3394. }
  3395.  
  3396. event OnAnimEvent_BloodTrailForced( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3397. {
  3398. var bloodTrailParam : CBloodTrailEffect;
  3399. var weaponId : SItemUniqueId;
  3400.  
  3401. if ( isInFinisher )
  3402. {
  3403. bloodTrailParam = (CBloodTrailEffect)(GetFinisherVictim()).GetGameplayEntityParam( 'CBloodTrailEffect' );
  3404. weaponId = this.inv.GetItemFromSlot('r_weapon');
  3405. if ( bloodTrailParam )
  3406. thePlayer.inv.PlayItemEffect( weaponId, bloodTrailParam.GetEffectName() );
  3407. }
  3408. }
  3409.  
  3410. event OnAnimEvent_SlowMo( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3411. {
  3412. if ( isInFinisher && DisableManualCameraControlStackHasSource( 'Finisher' ) )
  3413. {
  3414. if( animEventType != AET_DurationEnd )
  3415. theGame.SetTimeScale( 0.1f, 'AnimEventSlomoMo', 1000, true );
  3416. else
  3417. theGame.RemoveTimeScale( 'AnimEventSlomoMo' );
  3418. }
  3419. }
  3420.  
  3421. event OnAnimEvent_PlayFinisherBlood( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3422. {
  3423. if ( isInFinisher )
  3424. {
  3425. SpawnFinisherBlood();
  3426. }
  3427. }
  3428.  
  3429. event OnAnimEvent_OnWeaponDrawReady( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3430. {
  3431. weaponHolster.OnWeaponDrawReady();
  3432. }
  3433.  
  3434. event OnAnimEvent_OnWeaponHolsterReady( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3435. {
  3436. weaponHolster.OnWeaponHolsterReady();
  3437. }
  3438.  
  3439. event OnAnimEvent_ThrowHoldTest( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3440. {
  3441. var thrownEntity : CThrowable;
  3442.  
  3443. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  3444.  
  3445. if( IsThrowHold() )
  3446. {
  3447. SetBehaviorVariable( 'throwStage', (int)TS_Loop );
  3448. PushState( 'AimThrow' );
  3449. thrownEntity.StartAiming();
  3450. }
  3451. else
  3452. {
  3453. BombThrowRelease();
  3454. SetCombatIdleStance( 1.f );
  3455. }
  3456. }
  3457.  
  3458. event OnAnimEvent_AllowTempLookAt( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3459. {
  3460. if( animEventType == AET_DurationStart )
  3461. SetTempLookAtTarget( slideTarget );
  3462. else if( animEventType == AET_DurationEnd )
  3463. SetTempLookAtTarget( NULL );
  3464. }
  3465.  
  3466. protected var slideNPC : CNewNPC;
  3467. protected var minSlideDistance : float;
  3468. protected var slideTicket : SMovementAdjustmentRequestTicket;
  3469.  
  3470. event OnAnimEvent_SlideToTarget( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3471. {
  3472. var movementAdjustor : CMovementAdjustor;
  3473.  
  3474. if ( animEventType == AET_DurationStart )
  3475. slideNPC = (CNewNPC)slideTarget;
  3476.  
  3477. if(!slideNPC)
  3478. return false;
  3479.  
  3480. if ( animEventType == AET_DurationStart && slideNPC.GetGameplayVisibility() )
  3481. {
  3482. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3483. slideTicket = movementAdjustor.GetRequest( 'SlideToTarget' );
  3484. movementAdjustor.CancelByName( 'SlideToTarget' );
  3485. slideTicket = movementAdjustor.CreateNewRequest( 'SlideToTarget' );
  3486. movementAdjustor.BindToEventAnimInfo( slideTicket, animInfo );
  3487. //movementAdjustor.Continuous(slideTicket);
  3488. movementAdjustor.MaxLocationAdjustmentSpeed( slideTicket, 1000000 );
  3489. movementAdjustor.ScaleAnimation( slideTicket );
  3490. minSlideDistance = ((CMovingPhysicalAgentComponent)this.GetMovingAgentComponent()).GetCapsuleRadius()+((CMovingPhysicalAgentComponent)slideNPC.GetMovingAgentComponent()).GetCapsuleRadius();
  3491. movementAdjustor.SlideTowards( slideTicket, slideTarget, minSlideDistance, minSlideDistance );
  3492. }
  3493. else if ( !slideNPC.GetGameplayVisibility() )
  3494. {
  3495. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3496. movementAdjustor.CancelByName( 'SlideToTarget' );
  3497. slideNPC = NULL;
  3498. }
  3499. else
  3500. {
  3501. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3502. movementAdjustor.SlideTowards( slideTicket, slideTarget, minSlideDistance, minSlideDistance );
  3503. }
  3504. }
  3505.  
  3506. event OnAnimEvent_ActionBlend( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3507. {
  3508. }
  3509. /*
  3510. event OnAnimEvent_Throwable( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3511. {
  3512. var thrownEntity : CThrowable;
  3513.  
  3514. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  3515.  
  3516. if ( inv.IsItemCrossbow( inv.GetItemFromSlot('l_weapon') ) && rangedWeapon.OnProcessThrowEvent( animEventName ) )
  3517. {
  3518. return true;
  3519. }
  3520. else if( thrownEntity && IsThrowingItem() && thrownEntity.OnProcessThrowEvent( animEventName ) )
  3521. {
  3522. return true;
  3523. }
  3524. }*/
  3525.  
  3526. event OnAnimEvent_SubstateManager( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3527. {
  3528. // Notify the exploration manager
  3529. substateManager.OnAnimEvent( animEventName, animEventType, animInfo );
  3530. }
  3531.  
  3532. event OnAnimEvent_AllowFall( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3533. {
  3534. if ( !substateManager.m_OwnerMAC.IsOnGround() )
  3535. {
  3536. substateManager.m_SharedDataO.SetFallFromCritical( true );
  3537. substateManager.m_MoverO.SetVelocity( -6.0f * GetWorldForward() );
  3538. substateManager.QueueStateExternal( 'Jump' );
  3539. RemoveBuff( EET_Knockdown, true );
  3540. RemoveBuff( EET_HeavyKnockdown, true );
  3541. return true;
  3542. }
  3543. return false;
  3544. }
  3545.  
  3546. event OnAnimEvent_AllowFall2( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3547. {
  3548. if ( !substateManager.m_OwnerMAC.IsOnGround() )
  3549. {
  3550. //substateManager.m_SharedDataO.m_FromCriticalB = true;
  3551. //substateManager.m_MoverO.SetVelocity( -6.0f * GetWorldForward() );
  3552. substateManager.QueueStateExternal( 'Jump' );
  3553. RemoveBuff( EET_Knockdown, true );
  3554. RemoveBuff( EET_HeavyKnockdown, true );
  3555. }
  3556. if( substateManager.StateWantsAndCanEnter( 'Slide' ) )
  3557. {
  3558. substateManager.QueueStateExternal( 'Slide' );
  3559. }
  3560. }
  3561.  
  3562. event OnAnimEvent_DettachGround( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3563. {
  3564. //substateManager.m_MoverO.SetManualMovement( true );
  3565. }
  3566.  
  3567. //pad vibration for finishers
  3568. event OnAnimEvent_pad_vibration( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3569. {
  3570. var witcher : W3PlayerWitcher;
  3571.  
  3572. theGame.VibrateControllerHard();
  3573.  
  3574. //delayed FX for runeword 10 & 12
  3575. witcher = GetWitcherPlayer();
  3576. if(isInFinisher && witcher)
  3577. {
  3578. if(HasAbility('Runeword 10 _Stats', true) && !witcher.runeword10TriggerredOnFinisher && ((bool)theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'AutomaticFinishersEnabled')) == true)
  3579. {
  3580. witcher.Runeword10Triggerred();
  3581. witcher.runeword10TriggerredOnFinisher = true;
  3582. }
  3583. else if(HasAbility('Runeword 12 _Stats', true) && !witcher.runeword12TriggerredOnFinisher)
  3584. {
  3585. witcher.Runeword12Triggerred();
  3586. witcher.runeword12TriggerredOnFinisher = true;
  3587. }
  3588. }
  3589. }
  3590.  
  3591. //pad vibration light
  3592. event OnAnimEvent_pad_vibration_light( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3593. {
  3594. //theGame.VibrateControllerLight(); //draw & sheathe weapon
  3595. }
  3596.  
  3597. event OnAnimEvent_KillWithRagdoll( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3598. {
  3599. //thePlayer.SetKinematic( false );
  3600. //thePlayer.Kill();
  3601. }
  3602.  
  3603. event OnAnimEvent_RemoveBurning( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3604. {
  3605. thePlayer.AddBuffImmunity(EET_Burning, 'AnimEvent_RemoveBurning', true);
  3606. }
  3607.  
  3608. event OnAnimEvent_RemoveTangled( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3609. {
  3610. if ( this.HasBuff( EET_Tangled ) )
  3611. {
  3612. this.StopEffect('black_spider_web');
  3613. this.PlayEffectSingle('black_spider_web_break');
  3614. }
  3615. }
  3616. ///////////////////////////////////////////////////////////////////////////
  3617.  
  3618. event OnBehaviorGraphNotification( notificationName : name, stateName : name )
  3619. {
  3620. substateManager.OnBehaviorGraphNotification( notificationName, stateName );
  3621.  
  3622. if( notificationName == 'PlayerRunActivate' )
  3623. {
  3624. isInRunAnimation = true;
  3625. }
  3626. else if( notificationName == 'PlayerRunDeactivate' )
  3627. {
  3628. isInRunAnimation = false;
  3629. }
  3630. }
  3631.  
  3632. event OnEnumAnimEvent( animEventName : name, variant : SEnumVariant, animEventType : EAnimationEventType, animEventDuration : float, animInfo : SAnimationEventAnimInfo )
  3633. {
  3634. var movementAdjustor : CMovementAdjustor;
  3635. var ticket : SMovementAdjustmentRequestTicket;
  3636. var rotationRate : ERotationRate;
  3637.  
  3638. if ( animEventName == 'RotateToTarget' )
  3639. {
  3640. /**
  3641. * Rotate player to target
  3642. */
  3643. rotationRate = GetRotationRateFromAnimEvent( variant.enumValue );
  3644.  
  3645. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3646. if ( animEventType == AET_DurationStart || animEventType == AET_DurationStartInTheMiddle )
  3647. {
  3648. // when it starts (also in the middle - it may mean that we switch between events)
  3649. // create request if there isn't any and always setup rotation rate
  3650. if (! movementAdjustor.IsRequestActive( movementAdjustor.GetRequest( 'RotateToTarget' ) ) )
  3651. {
  3652. // start rotation adjustment
  3653. ticket = movementAdjustor.CreateNewRequest( 'RotateToTarget' );
  3654.  
  3655. // use adjustment duration only when RR_0 is selected, otherwise use continuous to match desired rotation as fast as possible
  3656. if ((int)rotationRate == 0)
  3657. movementAdjustor.AdjustmentDuration( ticket, animEventDuration );
  3658. else
  3659. {
  3660. movementAdjustor.Continuous( ticket );
  3661. movementAdjustor.BindToEvent( ticket, 'RotateToTarget' );
  3662. }
  3663.  
  3664. movementAdjustor.DontUseSourceAnimation( ticket ); // do not use source anim as it will use delta seconds from event
  3665. movementAdjustor.ReplaceRotation( ticket );
  3666. }
  3667. else
  3668. {
  3669. // get existing ticket to update rotation rate
  3670. ticket = movementAdjustor.GetRequest( 'RotateToTarget' );
  3671. }
  3672. MovAdjRotateToTarget( ticket );
  3673. // update rotationRate
  3674. if ((int)rotationRate > 0)
  3675. {
  3676. movementAdjustor.MaxRotationAdjustmentSpeed( ticket, (float)((int)rotationRate) );
  3677. }
  3678. }
  3679. else if ( animEventType == AET_DurationEnd )
  3680. {
  3681. // it will end if there's no event, but sometimes one event could end and be followed by another
  3682. // and we want to have that continuity kept, that's why we won't end request manually
  3683. }
  3684. else
  3685. {
  3686. // continuous update (makes more sense when there is no target and we want to rotate towards camera)
  3687. ticket = movementAdjustor.GetRequest( 'RotateToTarget' );
  3688. MovAdjRotateToTarget( ticket );
  3689. }
  3690. }
  3691. super.OnEnumAnimEvent(animEventName, variant, animEventType, animEventDuration, animInfo);
  3692. }
  3693.  
  3694. event OnTeleported()
  3695. {
  3696. if( substateManager )
  3697. {
  3698. substateManager.OnTeleported();
  3699. }
  3700. }
  3701.  
  3702. /*public function CaptureSafePosition()
  3703. {
  3704. lastSafePosition = GetWorldPosition();
  3705. lastSafeRotation = GetWorldRotation();
  3706. safePositionStored = true;
  3707. }*/
  3708.  
  3709. ///////////////////////////////////////////////////////////////////////////
  3710. // FISTFIGHT
  3711. ///////////////////////////////////////////////////////////////////////////
  3712. event OnStartFistfightMinigame()
  3713. {
  3714. super.OnStartFistfightMinigame();
  3715.  
  3716. //Goto state CombatFist
  3717. SetFistFightMinigameEnabled( true );
  3718. FistFightHealthChange( true );
  3719. thePlayer.GetPlayerMode().ForceCombatMode( FCMR_QuestFunction );
  3720. SetImmortalityMode(AIM_Unconscious, AIC_Fistfight);
  3721. thePlayer.SetBehaviorVariable( 'playerWeaponLatent', (int)PW_Fists );
  3722. GotoCombatStateWithAction( IA_None );
  3723. ((CMovingAgentComponent)this.GetMovingAgentComponent()).SnapToNavigableSpace( true );
  3724. EquipGeraltFistfightWeapon( true );
  3725. BlockAction( EIAB_RadialMenu, 'FistfightMinigame' ,,true);
  3726. BlockAction( EIAB_Signs, 'FistfightMinigame' ,,true);
  3727. BlockAction( EIAB_ThrowBomb, 'FistfightMinigame' ,,true);
  3728. BlockAction( EIAB_UsableItem, 'FistfightMinigame' ,,true);
  3729. BlockAction( EIAB_Crossbow, 'FistfightMinigame' ,,true);
  3730. BlockAction( EIAB_DrawWeapon, 'FistfightMinigame' ,,true);
  3731. BlockAction( EIAB_RunAndSprint, 'FistfightMinigame' ,,true);
  3732. BlockAction( EIAB_SwordAttack, 'FistfightMinigame' ,,true);
  3733. BlockAction( EIAB_CallHorse, 'FistfightMinigame' ,,true);
  3734. BlockAction( EIAB_Roll, 'FistfightMinigame' ,,true);
  3735. BlockAction( EIAB_Interactions, 'FistfightMinigame' ,,true);
  3736. BlockAction( EIAB_Explorations, 'FistfightMinigame' ,,true);
  3737. BlockAction( EIAB_OpenInventory, 'FistfightMinigame' ,,true);
  3738. BlockAction( EIAB_QuickSlots, 'FistfightMinigame' ,,true);
  3739. BlockAction( EIAB_OpenCharacterPanel, 'FistfightMinigame' ,,true);
  3740. }
  3741.  
  3742. event OnEndFistfightMinigame()
  3743. {
  3744. ((CMovingAgentComponent)this.GetMovingAgentComponent()).SnapToNavigableSpace( false );
  3745. FistFightHealthChange( false );
  3746. thePlayer.GetPlayerMode().ReleaseForceCombatMode( FCMR_QuestFunction );
  3747. EquipGeraltFistfightWeapon( false );
  3748. SetFistFightMinigameEnabled( false );
  3749. SetImmortalityMode(AIM_None, AIC_Fistfight);
  3750. BlockAllActions('FistfightMinigame',false);
  3751.  
  3752. super.OnEndFistfightMinigame();
  3753. }
  3754.  
  3755. public function GetFistFightFinisher( out masterAnimName, slaveAnimIndex : name )
  3756. {
  3757. var index : int;
  3758.  
  3759. index = RandRange(1);
  3760. switch ( index )
  3761. {
  3762. case 0 : masterAnimName = 'man_fistfight_finisher_1_win'; slaveAnimIndex = 'man_fistfight_finisher_1_looser';
  3763. }
  3764. }
  3765.  
  3766. public function SetFistFightMinigameEnabled( flag : bool )
  3767. {
  3768. fistFightMinigameEnabled = flag;
  3769. }
  3770.  
  3771. public function SetFistFightParams( toDeath : bool, endsWithBS : bool )
  3772. {
  3773. isFFMinigameToTheDeath = toDeath;
  3774. FFMinigameEndsithBS = endsWithBS;
  3775. }
  3776.  
  3777. public function IsFistFightMinigameEnabled() : bool
  3778. {
  3779. return fistFightMinigameEnabled;
  3780. }
  3781.  
  3782. public function IsFistFightMinigameToTheDeath() : bool
  3783. {
  3784. return isFFMinigameToTheDeath;
  3785. }
  3786.  
  3787. public function FistFightHealthChange( val : bool )
  3788. {
  3789. if( val == true )
  3790. {
  3791. GeraltMaxHealth = thePlayer.GetStatMax(BCS_Vitality);
  3792. ClampGeraltMaxHealth( 2000 );
  3793. SetHealthPerc( 100 );
  3794. }
  3795. else
  3796. {
  3797. ClampGeraltMaxHealth( GeraltMaxHealth );
  3798. SetHealthPerc( 100 );
  3799. }
  3800.  
  3801. }
  3802.  
  3803. function ClampGeraltMaxHealth( val : float )
  3804. {
  3805. thePlayer.abilityManager.SetStatPointMax( BCS_Vitality, val );
  3806. }
  3807.  
  3808. function EquipGeraltFistfightWeapon( val : bool )
  3809. {
  3810. if ( val )
  3811. {
  3812. fistsItems = thePlayer.GetInventory().AddAnItem( 'Geralt Fistfight Fists', 1, true, true );
  3813. thePlayer.GetInventory().MountItem( fistsItems[0] , true );
  3814. }
  3815. else
  3816. {
  3817. thePlayer.GetInventory().DropItem( fistsItems[0], true );
  3818. }
  3819. }
  3820.  
  3821. ///////////////////////////////////////////////////////////////////////////
  3822. // GWINT
  3823. ///////////////////////////////////////////////////////////////////////////
  3824. public function GetGwintAiDifficulty() : EGwintDifficultyMode
  3825. {
  3826. return gwintAiDifficulty;
  3827. }
  3828.  
  3829. public function SetGwintAiDifficulty( difficulty : EGwintDifficultyMode )
  3830. {
  3831. gwintAiDifficulty = difficulty;
  3832. }
  3833.  
  3834. public function GetGwintAiAggression() : EGwintAggressionMode
  3835. {
  3836. return gwintAiAggression;
  3837. }
  3838.  
  3839. public function SetGwintAiAggression( aggression : EGwintAggressionMode )
  3840. {
  3841. gwintAiAggression = aggression;
  3842. }
  3843.  
  3844. public function GetGwintMinigameState() : EMinigameState
  3845. {
  3846. return gwintMinigameState;
  3847. }
  3848.  
  3849. public function SetGwintMinigameState( minigameState : EMinigameState )
  3850. {
  3851. gwintMinigameState = minigameState;
  3852. }
  3853.  
  3854. public function OnGwintGameRequested( deckName : name )
  3855. {
  3856. var gwintManager:CR4GwintManager;
  3857. gwintManager = theGame.GetGwintManager();
  3858.  
  3859. gwintMinigameState = EMS_None;
  3860.  
  3861. gwintManager.SetEnemyDeckByName(deckName);
  3862.  
  3863. if (gwintManager.GetHasDoneTutorial() || !theGame.GetTutorialSystem().AreMessagesEnabled())
  3864. {
  3865. gwintManager.gameRequested = true;
  3866. theGame.RequestMenu( 'DeckBuilder' );
  3867. }
  3868. else
  3869. {
  3870. theGame.RequestMenu( 'GwintGame' );
  3871. }
  3872. }
  3873.  
  3874. private var gwintCardNumbersArray : array<int>;
  3875.  
  3876. public function InitGwintCardNumbersArray( arr : array<int> )
  3877. {
  3878. gwintCardNumbersArray.Clear();
  3879. gwintCardNumbersArray = arr;
  3880. }
  3881.  
  3882. public function GetCardNumbersArray() : array<int>
  3883. {
  3884. return gwintCardNumbersArray;
  3885. }
  3886. ///////////////////////////////////////////////////////////////////////////
  3887. // COMBAT CAMERA
  3888. ///////////////////////////////////////////////////////////////////////////
  3889.  
  3890. protected var customCameraStack : array<SCustomCameraParams>;
  3891.  
  3892. public function AddCustomCamToStack( customCameraParams : SCustomCameraParams ) : int
  3893. {
  3894. if( customCameraParams.useCustomCamera )
  3895. {
  3896. if ( customCameraParams.cameraParams.enums[0].enumType != 'ECustomCameraType' )
  3897. {
  3898. LogChannel( 'CustomCamera', "ERROR: Selected enum is not a custom camera!!!" );
  3899. return -1;
  3900. }
  3901. else
  3902. {
  3903. customCameraStack.PushBack( customCameraParams );
  3904. return ( customCameraStack.Size() - 1 );
  3905. }
  3906. }
  3907.  
  3908. return 0;
  3909. }
  3910.  
  3911. public function DisableCustomCamInStack( customCameraStackIndex : int )
  3912. {
  3913. if ( customCameraStackIndex != -1 )
  3914. customCameraStack[customCameraStackIndex].useCustomCamera = false;
  3915. else
  3916. LogChannel( 'CustomCamera', "ERROR: Custom camera to disable does not exist!!!" );
  3917. }
  3918.  
  3919. event OnInteriorStateChanged( inInterior : bool )
  3920. {
  3921. interiorCamera = inInterior;
  3922. }
  3923.  
  3924. event OnModifyPlayerSpeed( flag : bool )
  3925. {
  3926. modifyPlayerSpeed = flag;
  3927. SetBehaviorVariable( 'modifyPlayerSpeed', (float)modifyPlayerSpeed );
  3928. }
  3929.  
  3930. event OnGameCameraTick( out moveData : SCameraMovementData, dt : float )
  3931. {
  3932. var targetRotation : EulerAngles;
  3933. /*var dist : float;
  3934.  
  3935. // ImmersiveCam++
  3936. if( this.GetCurrentlyCastSign() == ST_Aard && GetBehaviorVariable( 'alternateSignCast' ) == 1 )
  3937. {
  3938. if( ic.critSloMoCam && thePlayer.IsInCombat() && ic.aardSlowMoFactor < 1.0 && !slowMoActive )
  3939. {
  3940. slowMoActive = true;
  3941. theGame.SetTimeScale( ic.aardSlowMoFactor, theGame.GetTimescaleSource(7), theGame.GetTimescalePriority(7), true);
  3942. AddTimer('OnStopTimeSlow',0.8, true);
  3943. }
  3944. }
  3945.  
  3946. if( this.GetCurrentlyCastSign() == ST_Igni && GetBehaviorVariable( 'alternateSignCast' ) == 1 )
  3947. {
  3948. if( ic.critSloMoCam && thePlayer.IsInCombat() && ic.igniSlowMoFactor < 1.0 && !slowMoActive )
  3949. {
  3950. slowMoActive = true;
  3951. theGame.SetTimeScale( ic.igniSlowMoFactor, theGame.GetTimescaleSource(7), theGame.GetTimescalePriority(7), true);
  3952. AddTimer('OnStopTimeSlow',0.8, true);
  3953. }
  3954. }
  3955.  
  3956. if( thePlayer.IsInCombat() )
  3957. {
  3958. dist = VecDistance2D( thePlayer.GetWorldPosition(), thePlayer.GetTarget().GetWorldPosition() );
  3959. thePlayer.GetVisualDebug().AddText( 'dbg', dist, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) );
  3960. if( theInput.IsActionPressed( 'CamOffsetIncrease' ) ) IncreaseComOffset();
  3961. if( theInput.IsActionPressed( 'CamOffsetDecrease' ) ) DecreaseComOffset();
  3962. if( theInput.IsActionPressed( 'CamDepthIncrease' ) ) IncreaseComDepth();
  3963. if( theInput.IsActionPressed( 'CamDepthDecrease' ) ) DecreaseComDepth();
  3964. if( theInput.IsActionPressed( 'CamHeightIncrease' ) ) IncreaseComHeight();
  3965. if( theInput.IsActionPressed( 'CamHeightDecrease' ) ) DecreaseComHeight();
  3966. }
  3967. else
  3968. {
  3969. if( theInput.IsActionPressed( 'CamOffsetIncrease' ) ) IncreaseOffset();
  3970. if( theInput.IsActionPressed( 'CamOffsetDecrease' ) ) DecreaseOffset();
  3971. if( theInput.IsActionPressed( 'CamDepthIncrease' ) ) IncreaseDepth();
  3972. if( theInput.IsActionPressed( 'CamDepthDecrease' ) ) DecreaseDepth();
  3973. if( theInput.IsActionPressed( 'CamHeightIncrease' ) ) IncreaseHeight();
  3974. if( theInput.IsActionPressed( 'CamHeightDecrease' ) ) DecreaseHeight();
  3975. // ImmersiveCam--
  3976.  
  3977. if ( isStartingFistFightMinigame )
  3978. {
  3979. moveData.pivotRotationValue = fistFightTeleportNode.GetWorldRotation();
  3980. isStartingFistFightMinigame = false;
  3981. }
  3982.  
  3983.  
  3984. /*
  3985. if( substateManager.UpdateCameraIfNeeded( moveData, dt ) )
  3986. {
  3987. //return true; //ImmersiveCam
  3988. }
  3989. */
  3990.  
  3991. // focusMode camera
  3992. if ( theGame.IsFocusModeActive() && ic.witcherSenseZoom && GetCurrentStateName() == 'Exploration' )
  3993. {
  3994. //restricted movement
  3995. if( ( movementLockType == PMLT_NoSprint || movementLockType == PMLT_NoRun ) && !ic.noInteriorCamChange )
  3996. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( ic.iWSOffset, ic.iWSDepth, ic.iWSHeight ), 0.5f, dt );
  3997. //normal
  3998.  
  3999. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( ic.eWSOffset + icOffsetAdj, ic.eWSDepth + icDepthAdj, ic.eWSHeight + icHeightAdj ), 0.5f, dt );
  4000. }
  4001. // combat camera
  4002.  
  4003. {
  4004. if ( IsCameraLockedToTarget() )
  4005. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( ic.hlOffset, ic.hlDepth, ic.hlHeight ), 0.60f, dt );
  4006. else
  4007. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( ic.comOffset + icComOffsetAdj, ic.comDepth + icComDepthAdj, ic.comHeight + icComHeightAdj ), 0.60f, dt );
  4008. }
  4009. // clue camera
  4010. else if( GetPlayerAction() == PEA_ExamineGround )
  4011. {
  4012. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( ic.clueOffset + icOffsetAdj, ic.clueDepth + icDepthAdj, ic.clueHeight + icHeightAdj ), 1.f, dt );
  4013. }
  4014. // exploration camera
  4015. else
  4016. {
  4017. //vanilla sprint came
  4018. if( GetIsSprinting() && ic.sprintMode == 2)
  4019. {
  4020. //do nothing - will use vanilla cam for sprint
  4021. }
  4022. //custom sprint cam
  4023. else if ( GetIsSprinting() && ic.sprintMode == 3 )
  4024. {
  4025. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( ic.sprintOffset, ic.sprintDepth, ic.sprintHeight ), 0.60f, dt );
  4026. }
  4027. //restricted movement
  4028. else if( ( movementLockType == PMLT_NoSprint || movementLockType == PMLT_NoRun ) && !ic.noInteriorCamChange )
  4029.  
  4030. {
  4031. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( ic.intOffset, ic.intDepth, ic.intHeight), 0.60f, dt );
  4032.  
  4033. }
  4034. //normal
  4035. else
  4036. {
  4037.  
  4038.  
  4039. }
  4040. // ImmersiveCam--
  4041.  
  4042. return false;
  4043. }
  4044.  
  4045. private var questCameraRequest : SQuestCameraRequest;
  4046. private var cameraRequestTimeStamp : float;
  4047.  
  4048. public function RequestQuestCamera( camera : SQuestCameraRequest )
  4049. {
  4050. questCameraRequest = camera;
  4051. questCameraRequest.requestTimeStamp = theGame.GetEngineTimeAsSeconds();
  4052. }
  4053.  
  4054. public function ResetQuestCameraRequest()
  4055. {
  4056. var cameraRequest : SQuestCameraRequest;
  4057.  
  4058. questCameraRequest = cameraRequest;
  4059. }
  4060.  
  4061. event OnGameCameraPostTick( out moveData : SCameraMovementData, dt : float )
  4062. {
  4063. var ent : CEntity;
  4064. var playerPos : Vector;
  4065. var angles : EulerAngles;
  4066.  
  4067. var distance : float;
  4068.  
  4069. /*if( thePlayer.IsInCombat() )
  4070. {
  4071. distance = VecDistance2D( thePlayer.GetWorldPosition(), thePlayer.GetTarget().GetWorldPosition() );
  4072. }
  4073.  
  4074. thePlayer.GetVisualDebug().AddText( 'Distance', "Distance form target: " + distance, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) );
  4075. */
  4076.  
  4077. if ( questCameraRequest.requestTimeStamp > 0 )
  4078. {
  4079. if ( questCameraRequest.duration > 0 && questCameraRequest.requestTimeStamp + questCameraRequest.duration < theGame.GetEngineTimeAsSeconds() )
  4080. {
  4081. ResetQuestCameraRequest();
  4082. return false;
  4083. }
  4084.  
  4085. if( questCameraRequest.lookAtTag )
  4086. {
  4087. ent = theGame.GetEntityByTag( questCameraRequest.lookAtTag );
  4088. playerPos = GetWorldPosition();
  4089. playerPos.Z += 1.8f;
  4090.  
  4091. angles = VecToRotation( ent.GetWorldPosition() - playerPos );
  4092.  
  4093. moveData.pivotRotationController.SetDesiredHeading( angles.Yaw );
  4094. moveData.pivotRotationController.SetDesiredPitch( -angles.Pitch );
  4095. }
  4096. else
  4097. {
  4098. if( questCameraRequest.requestYaw )
  4099. {
  4100. angles = GetWorldRotation();
  4101. moveData.pivotRotationController.SetDesiredHeading( angles.Yaw + questCameraRequest.yaw );
  4102. }
  4103.  
  4104. if( questCameraRequest.requestPitch )
  4105. {
  4106. moveData.pivotRotationController.SetDesiredPitch( questCameraRequest.pitch );
  4107. }
  4108. }
  4109. }
  4110.  
  4111. UpdateCameraSprint( moveData, dt ); //ImmersiveCam
  4112. }
  4113.  
  4114. var wasRunning : bool;
  4115. var vel : float;
  4116. var smoothTime : float;
  4117.  
  4118. var constDamper : ConstDamper;
  4119. var rotMultVel : float;
  4120.  
  4121. public function UpdateCameraInterior( out moveData : SCameraMovementData, timeDelta : float )
  4122. {
  4123. var camDist : float;
  4124. var camOffset : float;
  4125. var rotMultDest : float;
  4126. var rotMult : float;
  4127. var angles : EulerAngles;
  4128.  
  4129. theGame.GetGameCamera().ChangePivotRotationController( 'ExplorationInterior' );
  4130. theGame.GetGameCamera().ChangePivotDistanceController( 'Default' );
  4131. theGame.GetGameCamera().ChangePivotPositionController( 'Default' );
  4132.  
  4133. // HACK
  4134. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4135. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  4136. moveData.pivotPositionController = theGame.GetGameCamera().GetActivePivotPositionController();
  4137. // END HACK
  4138.  
  4139. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition(), 15.f );
  4140.  
  4141. if ( !constDamper )
  4142. {
  4143. constDamper = new ConstDamper in this;
  4144. constDamper.SetDamp( 0.35f );
  4145. }
  4146.  
  4147. if ( rawPlayerSpeed <= 0 || AbsF( AngleDistance( rawPlayerHeading, GetHeading() ) ) > 135 )
  4148. constDamper.Reset();
  4149. else if ( theGame.IsUberMovementEnabled() )
  4150. rotMult = 0.5f;
  4151. else
  4152. rotMult = 1.f;
  4153.  
  4154. rotMult = constDamper.UpdateAndGet( timeDelta, rotMult );
  4155.  
  4156. //DampFloatSpring( rotMult, rotMultVel, rotMultDest, 4.f, timeDelta );
  4157.  
  4158. if ( AbsF( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) ) < 135.f && rawPlayerSpeed > 0 )
  4159. moveData.pivotRotationController.SetDesiredHeading( GetHeading(), rotMult );
  4160. else
  4161. moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw );
  4162.  
  4163. //moveData.pivotDistanceController.SetDesiredDistance( 1.5f ); //ImmersiveCam
  4164.  
  4165. angles = VecToRotation( GetMovingAgentComponent().GetVelocity() );
  4166. if ( AbsF( angles.Pitch ) < 8.f || bLAxisReleased )
  4167. moveData.pivotRotationController.SetDesiredPitch( -10.f );
  4168. else
  4169. moveData.pivotRotationController.SetDesiredPitch( -angles.Pitch - 18.f );
  4170.  
  4171. if ( IsGuarded() )
  4172. moveData.pivotPositionController.offsetZ = 1.0f;
  4173. else
  4174. moveData.pivotPositionController.offsetZ = 1.3f;
  4175.  
  4176. //if ( movementLockType == PMLT_NoSprint )
  4177. //{
  4178. if ( playerMoveType >= PMT_Run )
  4179. {
  4180. //camDist = 0.3f;
  4181. camDist = -0.5f;
  4182. camOffset = 0.25;
  4183.  
  4184. if ( !wasRunning )
  4185. {
  4186. smoothTime = 1.f;
  4187. wasRunning = true;
  4188. }
  4189. DampFloatSpring( smoothTime, vel, 0.1, 0.5, timeDelta );
  4190. }
  4191. else
  4192. {
  4193. //camDist = -0.6f;
  4194. camDist = 0.f;
  4195. camOffset = 0.4f;
  4196. smoothTime = 0.2f;
  4197. wasRunning = false;
  4198. }
  4199.  
  4200. //camDist = theGame.GetGameplayConfigFloatValue( 'debugA' );
  4201.  
  4202. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.3f, camDist, 0.3f ), smoothTime, timeDelta );
  4203. //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5, camDist, camOffset ), smoothTime, timeDelta );
  4204. //}
  4205. //else
  4206. // DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( theGame.GetGameplayConfigFloatValue( 'debugA' ),theGame.GetGameplayConfigFloatValue( 'debugB' ),theGame.GetGameplayConfigFloatValue( 'debugC' ) ), 0.4f, timeDelta );
  4207. //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.7f, 0.f, 0.3 ), 0.4f, timeDelta );
  4208. }
  4209.  
  4210.  
  4211. var wasBRAxisPushed : bool;
  4212. protected function UpdateCameraChanneledSign( out moveData : SCameraMovementData, timeDelta : float ) : bool
  4213. {
  4214. var screenSpaceOffset : float;
  4215. var screenSpaceOffsetFwd : float;
  4216. var screenSpaceOffsetUp : float;
  4217. var heading : float;
  4218. var pitch : float;
  4219. var playerToTargetRot : EulerAngles;
  4220. var rightOffset : float = -20.f;
  4221. var leftOffset : float = 15.f;
  4222. var angles : EulerAngles;
  4223.  
  4224. var vec : Vector;
  4225.  
  4226. if( this.IsCurrentSignChanneled() && this.GetCurrentlyCastSign() != ST_Quen && this.GetCurrentlyCastSign() != ST_Yrden )
  4227. {
  4228. theGame.GetGameCamera().ChangePivotRotationController( 'SignChannel' );
  4229. theGame.GetGameCamera().ChangePivotDistanceController( 'SignChannel' );
  4230. // HACK
  4231. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4232. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  4233. // END HACK
  4234.  
  4235. if ( GetCurrentlyCastSign() == ST_Axii )
  4236. leftOffset = 32.f;
  4237.  
  4238. if ( oTCameraOffset != leftOffset && oTCameraOffset != rightOffset )
  4239. {
  4240. if( ( interiorCamera && !moveTarget )
  4241. || ( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) < 0 ) )
  4242. oTCameraOffset = leftOffset;
  4243. else
  4244. oTCameraOffset = rightOffset;
  4245. }
  4246.  
  4247. if ( oTCameraOffset == leftOffset )
  4248. {
  4249. // ImmersiveCam++
  4250. screenSpaceOffset = ic.fsOffset;
  4251. oTCameraPitchOffset = 13.f;
  4252.  
  4253. }
  4254. else if ( oTCameraOffset == rightOffset )
  4255. {
  4256. // ImmersiveCam++
  4257. screenSpaceOffset = -ic.fsOffset;
  4258. oTCameraPitchOffset = 13.f;
  4259.  
  4260. }
  4261.  
  4262. moveData.pivotPositionController.offsetZ = 1.3f;
  4263.  
  4264. if ( !delayCameraOrientationChange )
  4265. {
  4266. if ( GetOrientationTarget() == OT_Camera || GetOrientationTarget() == OT_CameraOffset )
  4267. {
  4268. if ( bRAxisReleased )
  4269. {
  4270. heading = moveData.pivotRotationValue.Yaw;
  4271. pitch = moveData.pivotRotationValue.Pitch;
  4272. }
  4273. else
  4274. {
  4275. heading = moveData.pivotRotationValue.Yaw + oTCameraOffset;
  4276. pitch = moveData.pivotRotationValue.Pitch; //+ oTCameraPitchOffset;
  4277. }
  4278. }
  4279. else if ( GetOrientationTarget() == OT_Actor )
  4280. {
  4281. if ( GetDisplayTarget() )
  4282. vec = GetDisplayTarget().GetWorldPosition() - GetWorldPosition();
  4283. else if ( slideTarget )
  4284. vec = slideTarget.GetWorldPosition() - GetWorldPosition();
  4285. else if ( GetTarget() )
  4286. vec = GetTarget().GetWorldPosition() - GetWorldPosition();
  4287. else
  4288. vec = GetHeadingVector();
  4289.  
  4290. angles = VecToRotation( vec );
  4291. heading = angles.Yaw + oTCameraOffset;
  4292. pitch = -angles.Pitch - oTCameraPitchOffset;//-angles.Pitch;
  4293. }
  4294. else
  4295. {
  4296. angles = VecToRotation( GetHeadingVector() );
  4297. heading = angles.Yaw + oTCameraOffset;
  4298. pitch = -angles.Pitch - oTCameraPitchOffset;//-angles.Pitch;
  4299. }
  4300.  
  4301. if ( !wasBRAxisPushed && ( !bRAxisReleased ) )//|| !lastAxisInputIsMovement ) )
  4302. wasBRAxisPushed = true;
  4303.  
  4304. moveData.pivotRotationController.SetDesiredHeading( heading , 2.f );
  4305. moveData.pivotRotationController.SetDesiredPitch( pitch );
  4306. }
  4307. else
  4308. {
  4309. moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw, 1.f );
  4310. moveData.pivotRotationController.SetDesiredPitch( -oTCameraPitchOffset );
  4311. }
  4312.  
  4313. if ( moveData.pivotRotationValue.Pitch <= 5.f && moveData.pivotRotationValue.Pitch >= -15.f )
  4314. {
  4315. // ImmersiveCam++
  4316. screenSpaceOffsetFwd = ic.fsDepth;
  4317. screenSpaceOffsetUp = ic.fsHeight;
  4318. // ImmersiveCam--
  4319. }
  4320. else if ( moveData.pivotRotationValue.Pitch > 0 )
  4321. {
  4322. // ImmersiveCam++
  4323. screenSpaceOffsetFwd = moveData.pivotRotationValue.Pitch*0.00727 + 1.275f;
  4324. screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, ic.fsDepth - 0.3, ic.fsDepth + 0.4 );
  4325.  
  4326. screenSpaceOffsetUp = -moveData.pivotRotationValue.Pitch*0.00727 + 0.4363f;
  4327. screenSpaceOffsetUp = ClampF( screenSpaceOffsetUp, ic.fsHeight - 0.4, ic.fsHeight - 0.1 );
  4328. // ImmersiveCam--
  4329. }
  4330. else
  4331. {
  4332. // ImmersiveCam++
  4333. if ( GetCurrentlyCastSign() == ST_Axii )
  4334. {
  4335. screenSpaceOffsetFwd = -moveData.pivotRotationValue.Pitch*0.0425 + 0.8625f;
  4336. screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, ic.fsDepth - 0.3, ic.fsDepth + 0.5 );
  4337. }
  4338. else
  4339. {
  4340. screenSpaceOffsetFwd = -moveData.pivotRotationValue.Pitch*0.035 + 0.75f;
  4341. screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, ic.fsDepth - 0.3, ic.fsDepth + 0.8 );
  4342. }
  4343. screenSpaceOffsetUp = -moveData.pivotRotationValue.Pitch*0.005 + 0.325f;
  4344. screenSpaceOffsetUp = ClampF( screenSpaceOffsetUp, ic.fsHeight, ic.fsHeight + 0.1 );
  4345. // ImmersiveCam--
  4346. }
  4347.  
  4348. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( screenSpaceOffset, screenSpaceOffsetFwd, screenSpaceOffsetUp ), 0.25f, timeDelta );//1.5,0.4
  4349. moveData.pivotDistanceController.SetDesiredDistance( 2.8f, 5.f );
  4350. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition() );
  4351.  
  4352. return true;
  4353. }
  4354. else
  4355. {
  4356. this.wasBRAxisPushed = false;
  4357.  
  4358. return false;
  4359. }
  4360. }
  4361.  
  4362. protected function UpdateCameraForSpecialAttack( out moveData : SCameraMovementData, timeDelta : float ) : bool
  4363. {
  4364. var screenSpaceOffset : float;
  4365. var tempHeading : float;
  4366. var cameraOffsetLeft : float;
  4367. var cameraOffsetRight : float;
  4368.  
  4369. if ( !specialAttackCamera )
  4370. return false;
  4371.  
  4372. theGame.GetGameCamera().ForceManualControlHorTimeout();
  4373. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4374. //if ( parent.delayCameraOrientationChange || parent.delayOrientationChange )
  4375. //{
  4376. cameraOffsetLeft = 30.f;
  4377. cameraOffsetRight = -30.f;
  4378. //}
  4379. //else
  4380. //{
  4381. // cameraOffsetLeft = 2.f;
  4382. // cameraOffsetRight = -2.f;
  4383. //}
  4384.  
  4385. theGame.GetGameCamera().ChangePivotRotationController( 'SignChannel' );
  4386. theGame.GetGameCamera().ChangePivotDistanceController( 'SignChannel' );
  4387. // HACK
  4388. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4389. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  4390.  
  4391. if ( slideTarget )
  4392. tempHeading = VecHeading( slideTarget.GetWorldPosition() - GetWorldPosition() );
  4393. else
  4394. tempHeading = GetHeading();
  4395.  
  4396. oTCameraPitchOffset = 0.f;
  4397.  
  4398. if( ( interiorCamera && !moveTarget )
  4399. || ( AngleDistance( tempHeading, moveData.pivotRotationValue.Yaw ) < 0 ) )
  4400. oTCameraOffset = cameraOffsetLeft;
  4401. else
  4402. oTCameraOffset = cameraOffsetRight;
  4403.  
  4404. if ( oTCameraOffset == cameraOffsetLeft )
  4405. {
  4406. if ( delayCameraOrientationChange || delayOrientationChange )
  4407. {
  4408. screenSpaceOffset = 0.75f;
  4409. moveData.pivotDistanceController.SetDesiredDistance( 1.6f, 3.f );
  4410. moveData.pivotPositionController.offsetZ = 1.4f;
  4411. moveData.pivotRotationController.SetDesiredPitch( -15.f );
  4412. }
  4413. else
  4414. {
  4415. screenSpaceOffset = 0.7f;
  4416. moveData.pivotDistanceController.SetDesiredDistance( 3.25f );
  4417. moveData.pivotPositionController.offsetZ = 1.2f;
  4418. moveData.pivotRotationController.SetDesiredPitch( -10.f );
  4419. }
  4420. }
  4421. else if ( oTCameraOffset == cameraOffsetRight )
  4422. {
  4423. if ( delayCameraOrientationChange || delayOrientationChange )
  4424. {
  4425. screenSpaceOffset = -0.85f;
  4426. moveData.pivotDistanceController.SetDesiredDistance( 1.6f, 3.f );
  4427. moveData.pivotPositionController.offsetZ = 1.4f;
  4428. moveData.pivotRotationController.SetDesiredPitch( -15.f );
  4429. }
  4430. else
  4431. {
  4432. screenSpaceOffset = -0.8f;
  4433. moveData.pivotDistanceController.SetDesiredDistance( 3.25f );
  4434. moveData.pivotPositionController.offsetZ = 1.2f;
  4435. moveData.pivotRotationController.SetDesiredPitch( -10.f );
  4436. }
  4437. }
  4438. else
  4439. {
  4440. moveData.pivotDistanceController.SetDesiredDistance( 1.25f, 3.f );
  4441. moveData.pivotPositionController.offsetZ = 1.3f;
  4442. moveData.pivotRotationController.SetDesiredPitch( -5.5f );
  4443. }
  4444.  
  4445. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( screenSpaceOffset, 0.f, 0.f ), 1.f, timeDelta );
  4446.  
  4447. if ( !delayCameraOrientationChange )
  4448. {
  4449. if ( moveTarget )
  4450. moveData.pivotRotationController.SetDesiredHeading( GetHeading() + oTCameraOffset, 0.5f );
  4451. else
  4452. moveData.pivotRotationController.SetDesiredHeading( GetHeading() + oTCameraOffset, 1.f );
  4453. }
  4454. else
  4455. moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw, 1.f );
  4456.  
  4457. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition() );
  4458.  
  4459. return true;
  4460. }
  4461.  
  4462.  
  4463. private var fovVel : float;
  4464. private var sprintOffset : Vector;
  4465. private var previousOffset : bool;
  4466. private var previousRotationVelocity : float;
  4467. private var pivotRotationTimeStamp : float;
  4468. protected function UpdateCameraSprint( out moveData : SCameraMovementData, timeDelta : float )
  4469. {
  4470. var angleDiff : float;
  4471. var camOffsetVector : Vector;
  4472. var smoothSpeed : float;
  4473. var camera : CCustomCamera;
  4474. var camAngularSpeed : float;
  4475.  
  4476. var playerToCamAngle : float;
  4477. var useExplorationSprintCam : bool;
  4478.  
  4479. camera = theGame.GetGameCamera();
  4480. if( camera )
  4481. {
  4482. if ( sprintingCamera )
  4483. {
  4484. //theGame.GetGameCamera().ForceManualControlHorTimeout();
  4485. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4486.  
  4487. playerToCamAngle = AbsF( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) );
  4488.  
  4489. /*if ( theGame.GetGameplayConfigFloatValue( 'debugE' ) > 0.1f )
  4490. useExplorationSprintCam = !IsInCombat() || ( moveTarget && VecDistance( moveTarget.GetWorldPosition(), GetWorldPosition() ) > findMoveTargetDistMax );
  4491. else*/
  4492. useExplorationSprintCam = false;// !IsInCombat() || ( moveTarget && VecDistance( moveTarget.GetWorldPosition(), GetWorldPosition() ) > findMoveTargetDistMax );
  4493.  
  4494. if ( useExplorationSprintCam )
  4495. {
  4496. if ( playerToCamAngle <= 45 )
  4497. {
  4498. theGame.GetGameCamera().ChangePivotRotationController( 'Sprint' );
  4499. // HACK
  4500. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4501.  
  4502. moveData.pivotRotationController.SetDesiredHeading( GetHeading(), 0.25f );
  4503. moveData.pivotRotationController.SetDesiredPitch( -3.5f, 0.5f );
  4504. thePlayer.EnableManualCameraControl( true, 'Sprint' );
  4505. }
  4506. else
  4507. {
  4508. thePlayer.EnableManualCameraControl( false, 'Sprint' );
  4509. }
  4510. }
  4511. else
  4512. {
  4513. if ( theGame.IsUberMovementEnabled() )
  4514. moveData.pivotRotationController.SetDesiredHeading( GetHeading(), 0.35f );
  4515.  
  4516. thePlayer.EnableManualCameraControl( true, 'Sprint' );
  4517. }
  4518.  
  4519. if ( bRAxisReleased )
  4520. {
  4521. if ( AbsF( rawLeftJoyRot ) > 25 )
  4522. angleDiff = AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw );
  4523.  
  4524. pivotRotationTimeStamp = theGame.GetEngineTimeAsSeconds();
  4525. previousRotationVelocity = 0.f;
  4526. }
  4527. else
  4528. {
  4529. if ( previousRotationVelocity <= 0 && AbsF( moveData.pivotRotationVelocity.Yaw ) > 250 )
  4530. {
  4531. pivotRotationTimeStamp = theGame.GetEngineTimeAsSeconds();
  4532. previousRotationVelocity = AbsF( moveData.pivotRotationVelocity.Yaw );
  4533. }
  4534. }
  4535.  
  4536. if ( pivotRotationTimeStamp + 0.4f <= theGame.GetEngineTimeAsSeconds() && AbsF( moveData.pivotRotationVelocity.Yaw ) > 250 )
  4537. angleDiff = VecHeading( rawRightJoyVec );
  4538.  
  4539. if ( useExplorationSprintCam )
  4540. {
  4541. if ( playerToCamAngle > 90 )
  4542. {
  4543. camOffsetVector.X = 0.f;
  4544. smoothSpeed = 1.f;
  4545. }
  4546. else if ( angleDiff > 15.f )
  4547. {
  4548. camOffsetVector.X = -0.8;
  4549. smoothSpeed = 1.f;
  4550. previousOffset = true;
  4551. }
  4552. else if ( angleDiff < -15.f )
  4553. {
  4554. camOffsetVector.X = 0.475f;
  4555. smoothSpeed = 1.5f;
  4556. previousOffset = false;
  4557. }
  4558. else
  4559. {
  4560. if ( previousOffset )
  4561. {
  4562. camOffsetVector.X = -0.8;
  4563. smoothSpeed = 1.5f;
  4564. }
  4565. else
  4566. {
  4567. camOffsetVector.X = 0.475f;
  4568. smoothSpeed = 1.5f;
  4569. }
  4570. }
  4571.  
  4572. camOffsetVector.Y = 1.4f;
  4573. camOffsetVector.Z = 0.275f;
  4574. }
  4575. else
  4576. {
  4577. /*camOffsetVector.X = 0.f;
  4578. camOffsetVector.Y = 0.4f;
  4579. camOffsetVector.Z = 0.2f;*/
  4580. smoothSpeed = 0.75f;
  4581.  
  4582. camOffsetVector.X = 0.f;
  4583. camOffsetVector.Y = 1.f;
  4584. camOffsetVector.Z = 0.2f;
  4585. moveData.pivotRotationController.SetDesiredPitch( -10.f, 0.5f );
  4586. }
  4587.  
  4588. DampVectorConst( sprintOffset, camOffsetVector, smoothSpeed, timeDelta );
  4589.  
  4590. moveData.cameraLocalSpaceOffset = sprintOffset;
  4591.  
  4592. DampFloatSpring( camera.fov, fovVel, ic.expFOV, 1.0, timeDelta ); //ImmersiveCam
  4593. }
  4594. else
  4595. {
  4596. sprintOffset = moveData.cameraLocalSpaceOffset;
  4597. DampFloatSpring( camera.fov, fovVel, ic.expFOV, 1.0, timeDelta ); //ImmersiveCam
  4598. previousOffset = false;
  4599. }
  4600. }
  4601. }
  4602.  
  4603. function EnableSprintingCamera( flag : bool )
  4604. {
  4605. //ImmersiveCam++
  4606. /*
  4607. if( !theGame.IsUberMovementEnabled() && !useSprintingCameraAnim )
  4608. {
  4609. return;
  4610. }
  4611. */
  4612. if( !useSprintingCameraAnim )
  4613. {
  4614. return;
  4615. }
  4616. //ImmersiveCam--
  4617.  
  4618. super.EnableSprintingCamera( flag );
  4619.  
  4620. if ( !flag )
  4621. {
  4622. thePlayer.EnableManualCameraControl( true, 'Sprint' );
  4623. }
  4624. }
  4625.  
  4626. protected function UpdateCameraCombatActionButNotInCombat( out moveData : SCameraMovementData, timeDelta : float )
  4627. {
  4628. var vel : Vector;
  4629. var heading : float;
  4630. var pitch : float;
  4631. var headingMult : float;
  4632. var pitchMult : float;
  4633. var camOffset : Vector;
  4634. var buff : CBaseGameplayEffect;
  4635. var runningAndAlertNear : bool;
  4636. var desiredDist : float;
  4637.  
  4638. if ( ( !IsCurrentSignChanneled() || GetCurrentlyCastSign() == ST_Quen || GetCurrentlyCastSign() == ST_Yrden ) && !specialAttackCamera && !IsInCombatActionFriendly() )
  4639. {
  4640. // ImmersiveCam++
  4641. /*
  4642. buff = GetCurrentlyAnimatedCS();
  4643. runningAndAlertNear = GetPlayerCombatStance() == PCS_AlertNear && playerMoveType == PMT_Run && !GetDisplayTarget();
  4644. if ( runningAndAlertNear ||
  4645. ( GetPlayerCombatStance() == PCS_AlertFar && !IsInCombatAction() && !buff ) )
  4646. {
  4647. camOffset.X = 0.f;
  4648. camOffset.Y = 0.f;
  4649. camOffset.Z = -0.1f;
  4650.  
  4651. if ( runningAndAlertNear )
  4652. {
  4653. moveData.pivotDistanceController.SetDesiredDistance( 4.f );
  4654. moveData.pivotPositionController.offsetZ = 1.5f;
  4655. }
  4656. }
  4657. else
  4658. {
  4659. camOffset.X = 0.f;
  4660. camOffset.Y = -1.5f;
  4661. camOffset.Z = -0.2f;
  4662. }
  4663.  
  4664. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( camOffset.X, camOffset.Y, camOffset.Z ), 0.4f, timeDelta );
  4665. sprintOffset = moveData.cameraLocalSpaceOffset;
  4666. */
  4667. // ImmersiveCam--
  4668. if( ic.expAutoRot )
  4669. {
  4670. heading = moveData.pivotRotationValue.Yaw;
  4671.  
  4672. if ( GetOrientationTarget() == OT_Camera || GetOrientationTarget() == OT_CameraOffset )
  4673. pitch = moveData.pivotRotationValue.Pitch;
  4674. else if ( lastAxisInputIsMovement
  4675. || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack
  4676. || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_SpecialAttack
  4677. || ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign && !IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Quen ) )
  4678. {
  4679. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4680. pitch = -20.f;
  4681. }
  4682. else
  4683. pitch = moveData.pivotRotationValue.Pitch;
  4684.  
  4685. headingMult = 1.f;
  4686. pitchMult = 1.f;
  4687.  
  4688.  
  4689. if( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign
  4690. && ( GetEquippedSign() == ST_Aard || GetEquippedSign() == ST_Yrden )
  4691. && GetBehaviorVariable( 'alternateSignCast' ) == 1 )
  4692. {
  4693.  
  4694. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4695. pitch = -20.f;
  4696.  
  4697.  
  4698. }
  4699.  
  4700.  
  4701.  
  4702.  
  4703.  
  4704.  
  4705. headingMult = 0.5f;*/
  4706. //}
  4707.  
  4708. if ( IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Quen )
  4709. {
  4710. pitch = moveData.pivotRotationValue.Pitch;
  4711. }
  4712.  
  4713. moveData.pivotRotationController.SetDesiredHeading( heading, );
  4714. moveData.pivotRotationController.SetDesiredPitch( pitch );
  4715. }
  4716. }
  4717. }
  4718.  
  4719. /*public function UpdateCameraForSpecialAttack( out moveData : SCameraMovementData, timeDelta : float ) : bool
  4720. {
  4721. return false;
  4722. }*/
  4723. //------------------------------------------------------------------------------------------------------------------
  4724. event OnGameCameraExplorationRotCtrlChange()
  4725. {
  4726. if( substateManager )
  4727. {
  4728. return substateManager.OnGameCameraExplorationRotCtrlChange( );
  4729. }
  4730.  
  4731. return false;
  4732. }
  4733.  
  4734. ///////////////////////////////////////////////////////////////////////////
  4735. // COMBAT MOVEMENT ORIENTATION
  4736. ///////////////////////////////////////////////////////////////////////////
  4737.  
  4738. //Rotation
  4739. function SetCustomRotation( customRotationName : name, rotHeading : float, rotSpeed : float, activeTime : float, rotateExistingDeltaLocation : bool )
  4740. {
  4741. var movementAdjustor : CMovementAdjustor;
  4742. var ticket : SMovementAdjustmentRequestTicket;
  4743.  
  4744. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4745. ticket = movementAdjustor.GetRequest( customRotationName );
  4746. movementAdjustor.Cancel( ticket );
  4747. ticket = movementAdjustor.CreateNewRequest( customRotationName );
  4748. movementAdjustor.Continuous( ticket );
  4749. movementAdjustor.ReplaceRotation( ticket );
  4750. movementAdjustor.RotateTo( ticket, rotHeading );
  4751. movementAdjustor.MaxRotationAdjustmentSpeed( ticket, rotSpeed );
  4752. if (rotSpeed == 0.0f)
  4753. {
  4754. movementAdjustor.AdjustmentDuration( ticket, activeTime );
  4755. }
  4756. movementAdjustor.KeepActiveFor( ticket, activeTime );
  4757. movementAdjustor.RotateExistingDeltaLocation( ticket, rotateExistingDeltaLocation );
  4758. }
  4759.  
  4760. function UpdateCustomRotationHeading( customRotationName : name, rotHeading : float )
  4761. {
  4762. var movementAdjustor : CMovementAdjustor;
  4763. var ticket : SMovementAdjustmentRequestTicket;
  4764.  
  4765. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4766. ticket = movementAdjustor.GetRequest( customRotationName );
  4767. movementAdjustor.RotateTo( ticket, rotHeading );
  4768. }
  4769.  
  4770. function SetCustomRotationTowards( customRotationName : name, target : CActor, rotSpeed : float, optional activeTime : float )
  4771. {
  4772. var movementAdjustor : CMovementAdjustor;
  4773. var ticket : SMovementAdjustmentRequestTicket;
  4774.  
  4775. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4776. ticket = movementAdjustor.GetRequest( customRotationName );
  4777. movementAdjustor.Cancel( ticket );
  4778. ticket = movementAdjustor.CreateNewRequest( customRotationName );
  4779. movementAdjustor.Continuous( ticket );
  4780. movementAdjustor.ReplaceRotation( ticket );
  4781. movementAdjustor.RotateTowards( ticket, target );
  4782. movementAdjustor.MaxRotationAdjustmentSpeed( ticket, rotSpeed );
  4783. if (activeTime > 0.0f)
  4784. {
  4785. movementAdjustor.KeepActiveFor( ticket, activeTime );
  4786. }
  4787. else
  4788. {
  4789. movementAdjustor.DontEnd( ticket );
  4790. }
  4791. }
  4792.  
  4793. //lock movement in dir
  4794. function CustomLockMovement( customMovementName : name, heading : float )
  4795. {
  4796. var movementAdjustor : CMovementAdjustor;
  4797. var ticket : SMovementAdjustmentRequestTicket;
  4798.  
  4799. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4800. ticket = movementAdjustor.GetRequest( customMovementName );
  4801. movementAdjustor.Cancel( ticket );
  4802. ticket = movementAdjustor.CreateNewRequest( customMovementName );
  4803. movementAdjustor.Continuous( ticket );
  4804. movementAdjustor.DontEnd( ticket );
  4805. movementAdjustor.LockMovementInDirection( ticket, heading );
  4806. }
  4807.  
  4808. function BindMovementAdjustmentToEvent( customRotationName : name, eventName : CName )
  4809. {
  4810. var movementAdjustor : CMovementAdjustor;
  4811. var ticket : SMovementAdjustmentRequestTicket;
  4812.  
  4813. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4814. ticket = movementAdjustor.GetRequest( customRotationName );
  4815. movementAdjustor.BindToEvent( ticket, eventName );
  4816. }
  4817.  
  4818. function UpdateCustomLockMovementHeading( customMovementName : name, heading : float )
  4819. {
  4820. var movementAdjustor : CMovementAdjustor;
  4821. var ticket : SMovementAdjustmentRequestTicket;
  4822.  
  4823. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4824. ticket = movementAdjustor.GetRequest( customMovementName );
  4825. movementAdjustor.LockMovementInDirection( ticket, heading );
  4826. }
  4827.  
  4828. function CustomLockDistance( customMovementName : name, maintainDistanceTo : CNode, minDist, maxDist : float )
  4829. {
  4830. var movementAdjustor : CMovementAdjustor;
  4831. var ticket : SMovementAdjustmentRequestTicket;
  4832.  
  4833. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4834. ticket = movementAdjustor.GetRequest( customMovementName );
  4835. movementAdjustor.Cancel( ticket );
  4836. ticket = movementAdjustor.CreateNewRequest( customMovementName );
  4837. movementAdjustor.Continuous( ticket );
  4838. movementAdjustor.SlideTowards( ticket, maintainDistanceTo, minDist, maxDist );
  4839. }
  4840.  
  4841. function UpdateCustomLockDistance( customMovementName : name, maintainDistanceTo : CNode, minDist, maxDist : float )
  4842. {
  4843. var movementAdjustor : CMovementAdjustor;
  4844. var ticket : SMovementAdjustmentRequestTicket;
  4845.  
  4846. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4847. ticket = movementAdjustor.GetRequest( customMovementName );
  4848. movementAdjustor.SlideTowards( ticket, maintainDistanceTo, minDist, maxDist );
  4849. }
  4850.  
  4851. private var disableManualCameraControlStack : array<name>;
  4852. public function EnableManualCameraControl( enable : bool, sourceName : name )
  4853. {
  4854. if ( !enable )
  4855. {
  4856. if ( !disableManualCameraControlStack.Contains( sourceName ) )
  4857. {
  4858. disableManualCameraControlStack.PushBack( sourceName );
  4859. }
  4860. }
  4861. else
  4862. {
  4863. disableManualCameraControlStack.Remove( sourceName );
  4864. }
  4865.  
  4866. if ( disableManualCameraControlStack.Size() > 0 )
  4867. theGame.GetGameCamera().EnableManualControl( false );
  4868. else
  4869. theGame.GetGameCamera().EnableManualControl( true );
  4870. }
  4871.  
  4872. public function IsCameraControlDisabled( optional disabledBySourceName : name ) : bool
  4873. {
  4874. if ( disabledBySourceName )
  4875. return disableManualCameraControlStack.Contains( disabledBySourceName );
  4876. else
  4877. return disableManualCameraControlStack.Size() > 0;
  4878. }
  4879.  
  4880. public function DisableManualCameraControlStackHasSource( sourceName : name ) : bool
  4881. {
  4882. return disableManualCameraControlStack.Contains( sourceName );
  4883. }
  4884.  
  4885. public function ClearDisableManualCameraControlStack()
  4886. {
  4887. disableManualCameraControlStack.Clear();
  4888. theGame.GetGameCamera().EnableManualControl( true );
  4889. }
  4890.  
  4891. function SetOrientationTarget( target : EOrientationTarget )
  4892. {
  4893. if ( IsPCModeEnabled() && target == OT_Player )
  4894. {
  4895. target = OT_Camera;
  4896. }
  4897.  
  4898. orientationTarget = target;
  4899. }
  4900.  
  4901. function GetOrientationTarget() : EOrientationTarget
  4902. {
  4903. return orientationTarget;
  4904. }
  4905.  
  4906. var customOrientationInfoStack : array<SCustomOrientationInfo>;
  4907. public function AddCustomOrientationTarget( orientationTarget : EOrientationTarget, sourceName : name )
  4908. {
  4909. var customOrientationInfo : SCustomOrientationInfo;
  4910. var i : int;
  4911.  
  4912. if ( customOrientationInfoStack.Size() > 0 )
  4913. {
  4914. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4915. {
  4916. if ( customOrientationInfoStack[i].sourceName == sourceName )
  4917. customOrientationInfoStack.Erase(i);
  4918. }
  4919. }
  4920.  
  4921. customOrientationInfo.sourceName = sourceName;
  4922. customOrientationInfo.orientationTarget = orientationTarget;
  4923. customOrientationInfoStack.PushBack( customOrientationInfo );
  4924. SetOrientationTarget( orientationTarget );
  4925. }
  4926.  
  4927. public function RemoveCustomOrientationTarget( sourceName : name )
  4928. {
  4929. var customOrientationInfo : SCustomOrientationInfo;
  4930. var i : int;
  4931.  
  4932. if ( customOrientationInfoStack.Size() > 0 )
  4933. {
  4934. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4935. {
  4936. if ( customOrientationInfoStack[i].sourceName == sourceName )
  4937. customOrientationInfoStack.Erase(i);
  4938. }
  4939. }
  4940. else
  4941. LogChannel( 'CustomOrienatation', "ERROR: Custom orientation cannot be removed, stack is already empty!!!" );
  4942. }
  4943.  
  4944. protected function ClearCustomOrientationInfoStack()
  4945. {
  4946. customOrientationInfoStack.Clear();
  4947. }
  4948.  
  4949. protected function GetCustomOrientationTarget( out infoStack : SCustomOrientationInfo ) : bool
  4950. {
  4951. var size : int;
  4952.  
  4953. size = customOrientationInfoStack.Size();
  4954.  
  4955. if ( size <= 0 )
  4956. return false;
  4957. else
  4958. {
  4959. infoStack = customOrientationInfoStack[ size - 1 ];
  4960. return true;
  4961. }
  4962. }
  4963.  
  4964. public function SetOrientationTargetCustomHeading( heading : float, sourceName : name ) : bool
  4965. {
  4966. var i : int;
  4967. if ( customOrientationInfoStack.Size() > 0 )
  4968. {
  4969. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4970. {
  4971. if ( customOrientationInfoStack[i].sourceName == sourceName )
  4972. {
  4973. customOrientationInfoStack[i].customHeading = heading;
  4974. return true;
  4975. }
  4976. }
  4977. }
  4978.  
  4979. LogChannel( 'SetOrientationTargetCustomHeading', "ERROR: Cannot set customHeading because stack is empty or sourceName is not found!!!" );
  4980. return false;
  4981. }
  4982.  
  4983. // returns the topmost OT_CustomHeading in stack
  4984. public function GetOrientationTargetCustomHeading() : float
  4985. {
  4986. var i : int;
  4987. if ( customOrientationInfoStack.Size() > 0 )
  4988. {
  4989. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4990. {
  4991. if ( customOrientationInfoStack[i].orientationTarget == OT_CustomHeading )
  4992. {
  4993. return customOrientationInfoStack[i].customHeading;
  4994. }
  4995. }
  4996. }
  4997.  
  4998. LogChannel( 'SetOrientationTargetCustomHeading', "ERROR: Cannot get customHeading because stack is empty or no OT_CustomHeading in stack!!!" );
  4999. return -1.f;
  5000. }
  5001.  
  5002. public function GetCombatActionOrientationTarget( combatActionType : ECombatActionType ) : EOrientationTarget
  5003. {
  5004. var newCustomOrientationTarget : EOrientationTarget;
  5005. var targetEnt : CGameplayEntity;
  5006. var targetActor : CActor;
  5007.  
  5008. if ( GetCurrentStateName() == 'AimThrow' )
  5009. newCustomOrientationTarget = OT_CameraOffset;
  5010. else
  5011. {
  5012. targetEnt = GetDisplayTarget();
  5013. targetActor = (CActor)targetEnt;
  5014.  
  5015. if ( targetEnt )
  5016. {
  5017. if ( targetActor )
  5018. {
  5019. if ( moveTarget )
  5020. newCustomOrientationTarget = OT_Actor;
  5021. else
  5022. {
  5023. if ( this.IsSwimming() )
  5024. newCustomOrientationTarget = OT_Camera;
  5025. else if ( lastAxisInputIsMovement )
  5026. newCustomOrientationTarget = OT_Player;
  5027. else
  5028. newCustomOrientationTarget = OT_Actor;
  5029. }
  5030. }
  5031. else
  5032. {
  5033. if ( combatActionType == CAT_Crossbow && targetEnt.HasTag( 'softLock_Bolt' ) )
  5034. newCustomOrientationTarget = OT_Actor;
  5035. else
  5036. {
  5037. if ( this.IsSwimming() )
  5038. newCustomOrientationTarget = OT_Camera;
  5039. else if ( lastAxisInputIsMovement )
  5040. newCustomOrientationTarget = OT_Player;
  5041. else
  5042. newCustomOrientationTarget = OT_Camera;
  5043.  
  5044. }
  5045. }
  5046. }
  5047. else
  5048. {
  5049. if ( IsUsingVehicle() )// || this.IsSwimming() )
  5050. newCustomOrientationTarget = OT_Camera;
  5051. else if ( lastAxisInputIsMovement )
  5052. {
  5053. if ( this.IsSwimming() )
  5054. {
  5055. //if ( !bRAxisReleased
  5056. // || ( GetOrientationTarget() == OT_Camera && ( this.rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' || this.rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' ) ) )
  5057. newCustomOrientationTarget = OT_Camera;
  5058. //else
  5059. // newCustomOrientationTarget = OT_CustomHeading;
  5060. }
  5061. else
  5062. newCustomOrientationTarget = OT_Player;
  5063.  
  5064. }
  5065. else
  5066. newCustomOrientationTarget = OT_Camera;
  5067. }
  5068. }
  5069.  
  5070. return newCustomOrientationTarget;
  5071. }
  5072.  
  5073. public function GetOrientationTargetHeading( orientationTarget : EOrientationTarget ) : float
  5074. {
  5075. var heading : float;
  5076.  
  5077. if( orientationTarget == OT_Camera )
  5078. heading = VecHeading( theCamera.GetCameraDirection() );
  5079. else if( orientationTarget == OT_CameraOffset )
  5080. heading = VecHeading( theCamera.GetCameraDirection() ) - oTCameraOffset;
  5081. else if( orientationTarget == OT_CustomHeading )
  5082. heading = GetOrientationTargetCustomHeading();
  5083. else if ( GetDisplayTarget() && orientationTarget == OT_Actor )
  5084. {
  5085. if ( (CActor)( GetDisplayTarget() ) )
  5086. {
  5087. //if ( GetPlayerCombatStance() == PCS_AlertNear )
  5088. heading = VecHeading( GetDisplayTarget().GetWorldPosition() - GetWorldPosition() );
  5089. //else
  5090. // heading = GetHeading();
  5091. }
  5092. else
  5093. {
  5094. if ( GetDisplayTarget().HasTag( 'softLock_Bolt' ) )
  5095. heading = VecHeading( GetDisplayTarget().GetWorldPosition() - GetWorldPosition() );
  5096. else
  5097. heading = GetHeading();
  5098. }
  5099. }
  5100. else
  5101. heading = GetHeading();
  5102.  
  5103. return heading;
  5104. }
  5105.  
  5106. event OnDelayOrientationChange()
  5107. {
  5108. var delayOrientation : bool;
  5109. var delayCameraRotation : bool;
  5110. var moveData : SCameraMovementData;
  5111. var time : float;
  5112.  
  5113. time = 0.01f;
  5114.  
  5115. if ( theInput.GetActionValue( 'CastSignHold' ) == 1.f )
  5116. {
  5117. actionType = 0;
  5118. if ( moveTarget )
  5119. delayOrientation = true;
  5120. else
  5121. {
  5122. if ( !GetBIsCombatActionAllowed() )
  5123. delayOrientation = true;
  5124. }
  5125.  
  5126.  
  5127. }
  5128. else if ( theInput.GetActionValue( 'ThrowItemHold' ) == 1.f )
  5129. {
  5130. actionType = 3;
  5131. delayOrientation = true;
  5132. }
  5133. else if ( theInput.GetActionValue( 'SpecialAttackHeavy' ) == 1.f )
  5134. {
  5135. actionType = 2;
  5136. if ( !slideTarget )
  5137. delayOrientation = true;
  5138. else
  5139. delayOrientation = true;
  5140. }
  5141. else if ( IsGuarded() && !moveTarget )
  5142. {
  5143. actionType = 1;
  5144. delayOrientation = true;
  5145. }
  5146.  
  5147. if ( delayOrientation )
  5148. {
  5149. delayOrientationChange = true;
  5150. theGame.GetGameCamera().ForceManualControlHorTimeout();
  5151. theGame.GetGameCamera().ForceManualControlVerTimeout();
  5152. AddTimer( 'DelayOrientationChangeTimer', time, true );
  5153. }
  5154.  
  5155. if ( delayCameraRotation )
  5156. {
  5157. delayCameraOrientationChange = true;
  5158. theGame.GetGameCamera().ForceManualControlHorTimeout();
  5159. theGame.GetGameCamera().ForceManualControlVerTimeout();
  5160. AddTimer( 'DelayOrientationChangeTimer', time, true );
  5161. }
  5162. }
  5163.  
  5164. //This is also called from behgraph (e.g. SpecialHeavyAttack)
  5165. event OnDelayOrientationChangeOff()
  5166. {
  5167. delayOrientationChange = false;
  5168. delayCameraOrientationChange = false;
  5169. RemoveTimer( 'DelayOrientationChangeTimer' );
  5170.  
  5171. //if ( !IsCameraLockedToTarget() )
  5172. // theGame.GetGameCamera().EnableManualControl( true );
  5173. }
  5174.  
  5175. timer function DelayOrientationChangeTimer( time : float , id : int)
  5176. {
  5177. if ( ( actionType == 0 && theInput.GetActionValue( 'CastSignHold' ) == 0.f )
  5178. || ( actionType == 2 && theInput.GetActionValue( 'SpecialAttackHeavy' ) == 0.f )
  5179. || ( actionType == 3 && theInput.GetActionValue( 'ThrowItemHold' ) == 0.f )
  5180. || ( actionType == 1 && !IsGuarded() )
  5181. || ( VecLength( rawRightJoyVec ) > 0.f ) )//&& !( slideTarget && IsInCombatAction() && GetBehaviorVariable( 'combatActionType') == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Axii ) ) )
  5182. {
  5183. OnDelayOrientationChangeOff();
  5184. }
  5185. }
  5186.  
  5187. public function SetCombatActionHeading( heading : float )
  5188. {
  5189. combatActionHeading = heading;
  5190. }
  5191.  
  5192. public function GetCombatActionHeading() : float
  5193. {
  5194. return combatActionHeading;
  5195. }
  5196.  
  5197. protected function EnableCloseCombatCharacterRadius( flag : bool )
  5198. {
  5199. var actor : CActor;
  5200.  
  5201. actor = (CActor)slideTarget;
  5202. if ( flag )
  5203. {
  5204. this.GetMovingAgentComponent().SetVirtualRadius( 'CloseCombatCharacterRadius' );
  5205. if(actor)
  5206. actor.GetMovingAgentComponent().SetVirtualRadius( 'CloseCombatCharacterRadius' );
  5207. }
  5208. else
  5209. {
  5210. if ( this.IsInCombat() )
  5211. {
  5212. GetMovingAgentComponent().SetVirtualRadius( 'CombatCharacterRadius' );
  5213. if(actor)
  5214. actor.GetMovingAgentComponent().SetVirtualRadius( 'CombatCharacterRadius' );
  5215. }
  5216. else
  5217. {
  5218. this.GetMovingAgentComponent().ResetVirtualRadius();
  5219. if(actor)
  5220. actor.GetMovingAgentComponent().ResetVirtualRadius();
  5221. }
  5222. }
  5223. }
  5224.  
  5225. ///////////////////////////////////////////////////////////////////////////
  5226. // Soft Lock Logic
  5227.  
  5228.  
  5229.  
  5230. private var isSnappedToNavMesh : bool;
  5231. private var snapToNavMeshCachedFlag : bool;
  5232. public function SnapToNavMesh( flag : bool )
  5233. {
  5234. var comp : CMovingAgentComponent;
  5235.  
  5236. comp = (CMovingAgentComponent)this.GetMovingAgentComponent();
  5237.  
  5238. if ( comp )
  5239. {
  5240. comp.SnapToNavigableSpace( flag );
  5241. isSnappedToNavMesh = flag;
  5242. }
  5243. else
  5244. {
  5245. snapToNavMeshCachedFlag = flag;
  5246. AddTimer( 'DelayedSnapToNavMesh', 0.2f );
  5247. }
  5248. }
  5249.  
  5250. public final function PlayRuneword4FX(optional weaponType : EPlayerWeapon)
  5251. {
  5252. var hasSwordDrawn : bool;
  5253. var sword : SItemUniqueId;
  5254.  
  5255. //we show fx only if overheal is greater than 1% - otherwise if we have a DoT and regen at the same time the health
  5256. //jumps back and forth between 100% and 99.99% stating and stopping the fx over and over
  5257. //needs to have sword drawn
  5258. if(abilityManager.GetOverhealBonus() > (0.005 * GetStatMax(BCS_Vitality)))
  5259. {
  5260. hasSwordDrawn = HasAbility('Runeword 4 _Stats', true);
  5261.  
  5262. if(!hasSwordDrawn && GetWitcherPlayer())
  5263. {
  5264. if(weaponType == PW_Steel)
  5265. {
  5266. if(GetWitcherPlayer().GetItemEquippedOnSlot(EES_SteelSword, sword))
  5267. hasSwordDrawn = inv.ItemHasAbility(sword, 'Runeword 4 _Stats');
  5268. }
  5269. else if(weaponType == PW_Silver)
  5270. {
  5271. if(GetWitcherPlayer().GetItemEquippedOnSlot(EES_SilverSword, sword))
  5272. hasSwordDrawn = inv.ItemHasAbility(sword, 'Runeword 4 _Stats');
  5273. }
  5274. }
  5275.  
  5276. if(hasSwordDrawn)
  5277. {
  5278. if(!IsEffectActive('runeword_4', true))
  5279. PlayEffect('runeword_4');
  5280. }
  5281. }
  5282. }
  5283.  
  5284. timer function DelayedSnapToNavMesh( dt : float, id : int)
  5285. {
  5286. SnapToNavMesh( snapToNavMeshCachedFlag );
  5287. }
  5288.  
  5289. saved var navMeshSnapInfoStack : array<name>;
  5290. public function EnableSnapToNavMesh( source : name, enable : bool )
  5291. {
  5292. if ( enable )
  5293. {
  5294. if ( !navMeshSnapInfoStack.Contains( source ) )
  5295. navMeshSnapInfoStack.PushBack( source );
  5296. }
  5297. else
  5298. {
  5299. if ( navMeshSnapInfoStack.Contains( source ) )
  5300. navMeshSnapInfoStack.Remove( source );
  5301. }
  5302.  
  5303. if ( navMeshSnapInfoStack.Size() > 0 )
  5304. SnapToNavMesh( true );
  5305. else
  5306. SnapToNavMesh( false );
  5307. }
  5308.  
  5309. public function ForceRemoveAllNavMeshSnaps()
  5310. {
  5311. navMeshSnapInfoStack.Clear();
  5312. SnapToNavMesh( false );
  5313. }
  5314.  
  5315. public function CanSprint( speed : float ) : bool
  5316. {
  5317. if( speed <= 0.8f )
  5318. {
  5319. return false;
  5320. }
  5321.  
  5322. if ( thePlayer.GetIsSprintToggled() )
  5323. {
  5324. }
  5325. else if ( !sprintActionPressed )
  5326. {
  5327. return false;
  5328. }
  5329. else if( !theInput.IsActionPressed('Sprint') || ( theInput.LastUsedGamepad() && IsInsideInteraction() && GetHowLongSprintButtonWasPressed() < 0.12 ) )
  5330. {
  5331. return false;
  5332. }
  5333.  
  5334. if ( thePlayer.HasBuff( EET_OverEncumbered ) )
  5335. {
  5336. return false;
  5337. }
  5338. if ( !IsSwimming() )
  5339. {
  5340. if ( ShouldUseStaminaWhileSprinting() && !GetIsSprinting() && !IsInCombat() && GetStatPercents(BCS_Stamina) <= 0.9 )
  5341. {
  5342. return false;
  5343. }
  5344. if( ( !IsCombatMusicEnabled() || IsInFistFightMiniGame() ) && ( !IsActionAllowed(EIAB_RunAndSprint) || !IsActionAllowed(EIAB_Sprint) ) )
  5345. {
  5346. return false;
  5347. }
  5348. if( IsTerrainTooSteepToRunUp() )
  5349. {
  5350. return false;
  5351. }
  5352. if( IsInCombatAction() )
  5353. {
  5354. return false;
  5355. }
  5356. if( IsInAir() )
  5357. {
  5358. return false;
  5359. }
  5360. }
  5361. if( theGame.IsFocusModeActive() )
  5362. {
  5363. return false;
  5364. }
  5365.  
  5366. return true;
  5367. }
  5368.  
  5369.  
  5370. public function SetTerrainPitch( pitch : float )
  5371. {
  5372. terrainPitch = pitch;
  5373. }
  5374.  
  5375. public function IsTerrainTooSteepToRunUp() : bool
  5376. {
  5377. return terrainPitch <= disableSprintTerrainPitch;
  5378. }
  5379.  
  5380. public function SetTempLookAtTarget( actor : CGameplayEntity )
  5381. {
  5382. tempLookAtTarget = actor;
  5383. }
  5384.  
  5385. private var beingWarnedBy : array<CActor>;
  5386.  
  5387. event OnBeingWarnedStart( sender : CActor )
  5388. {
  5389. if ( !beingWarnedBy.Contains(sender) )
  5390. beingWarnedBy.PushBack(sender);
  5391. }
  5392. event OnBeingWarnedStop( sender : CActor )
  5393. {
  5394. beingWarnedBy.Remove(sender);
  5395. }
  5396.  
  5397. event OnCanFindPath( sender : CActor )
  5398. {
  5399. AddCanFindPathEnemyToList(sender,true);
  5400. }
  5401. event OnCannotFindPath( sender : CActor )
  5402. {
  5403. AddCanFindPathEnemyToList(sender,false);
  5404. }
  5405. event OnBecomeAwareAndCanAttack( sender : CActor )
  5406. {
  5407. AddEnemyToHostileEnemiesList( sender, true );
  5408. OnApproachAttack( sender );
  5409. }
  5410. event OnBecomeUnawareOrCannotAttack( sender : CActor )
  5411. {
  5412. AddEnemyToHostileEnemiesList( sender, false );
  5413. OnApproachAttackEnd( sender );
  5414. OnCannotFindPath(sender);
  5415. }
  5416. event OnApproachAttack( sender : CActor )
  5417. {
  5418. AddEnemyToHostileEnemiesList( sender, true );
  5419. super.OnApproachAttack( sender );
  5420. }
  5421. event OnApproachAttackEnd( sender : CActor )
  5422. {
  5423. AddEnemyToHostileEnemiesList( sender, false );
  5424. super.OnApproachAttackEnd( sender );
  5425. }
  5426. event OnAttack( sender : CActor )
  5427. {
  5428. super.OnAttack( sender );
  5429. }
  5430. event OnAttackEnd( sender : CActor )
  5431. {
  5432. super.OnAttackEnd( sender );
  5433. }
  5434.  
  5435. event OnHitCeiling()
  5436. {
  5437. substateManager.ReactOnHitCeiling();
  5438. }
  5439.  
  5440. protected var hostileEnemies : array<CActor>; //all enemies that are actively engaged in combat with the player (may or may not be visible by Geralt)
  5441. private var hostileMonsters : array<CActor>; // subgroup from hostileEnemies containing only monsters for sound system
  5442. function AddEnemyToHostileEnemiesList( actor : CActor, add : bool )
  5443. {
  5444. if ( add )
  5445. {
  5446. RemoveTimer( 'RemoveEnemyFromHostileEnemiesListTimer' );
  5447. if ( !hostileEnemies.Contains( actor ) )
  5448. {
  5449. hostileEnemies.PushBack( actor );
  5450.  
  5451. if( !actor.IsHuman() )
  5452. hostileMonsters.PushBack( actor );
  5453. }
  5454. }
  5455. else
  5456. {
  5457. if ( hostileEnemies.Size() == 1 )
  5458. {
  5459. if ( !actor.IsAlive() || actor.IsKnockedUnconscious() )
  5460. {
  5461. hostileEnemies.Remove( actor );
  5462. if( !actor.IsHuman() )
  5463. hostileMonsters.Remove( actor );
  5464. }
  5465. else
  5466. {
  5467. // If we already waiting to remove an entity
  5468. if( hostileEnemyToRemove )
  5469. {
  5470. hostileEnemies.Remove( hostileEnemyToRemove );
  5471. if( !hostileEnemyToRemove.IsHuman() )
  5472. hostileMonsters.Remove( hostileEnemyToRemove );
  5473. }
  5474. hostileEnemyToRemove = actor;
  5475. AddTimer( 'RemoveEnemyFromHostileEnemiesListTimer', 3.f );
  5476. }
  5477. }
  5478. else
  5479. {
  5480. hostileEnemies.Remove( actor );
  5481. if( !actor.IsHuman() )
  5482. hostileMonsters.Remove( actor );
  5483. }
  5484. }
  5485. }
  5486.  
  5487.  
  5488.  
  5489. public function ShouldEnableCombatMusic() : bool
  5490. {
  5491. var moveTargetNPC : CNewNPC;
  5492.  
  5493. if ( thePlayer.GetPlayerMode().GetForceCombatMode() )
  5494. return true;
  5495. else if ( !IsCombatMusicEnabled() )
  5496. {
  5497. if ( IsInCombat() )
  5498. return true;
  5499. else if ( IsThreatened() )
  5500. {
  5501. moveTargetNPC = (CNewNPC)moveTarget;
  5502. if ( moveTargetNPC.IsRanged() && hostileEnemies.Contains( moveTargetNPC ) )
  5503. return true;
  5504. else
  5505. return false;
  5506. }
  5507. else
  5508. return false;
  5509. }
  5510. else if ( ( thePlayer.IsThreatened() && ( hostileEnemies.Size() > 0 || thePlayer.GetPlayerCombatStance() == PCS_AlertNear ) )
  5511. || IsInCombat()
  5512. || finishableEnemiesList.Size() > 0
  5513. || isInFinisher )
  5514. return true;
  5515. else
  5516. return false;
  5517.  
  5518. }
  5519.  
  5520. public var canFindPathEnemiesList : array<CActor>;
  5521. public var disablecanFindPathEnemiesListUpdate : bool;
  5522. private var lastCanFindPathEnemy : CActor;
  5523. private var cachedMoveTarget : CActor;
  5524. private var reachabilityTestId : int;
  5525. private var reachabilityTestId2 : int;
  5526. function AddCanFindPathEnemyToList( actor : CActor, add : bool )
  5527. {
  5528. if ( disablecanFindPathEnemiesListUpdate )
  5529. return;
  5530.  
  5531. if ( add && !canFindPathEnemiesList.Contains( actor ) )
  5532. {
  5533. canFindPathEnemiesList.PushBack(actor);
  5534. }
  5535. else if ( !add )
  5536. {
  5537. canFindPathEnemiesList.Remove(actor);
  5538.  
  5539. if ( canFindPathEnemiesList.Size() <= 0 )
  5540. playerMode.UpdateCombatMode();
  5541. }
  5542. }
  5543.  
  5544. public function ClearCanFindPathEnemiesList( dt : float, id : int )
  5545. {
  5546. canFindPathEnemiesList.Clear();
  5547. }
  5548.  
  5549. public var finishableEnemiesList : array<CActor>;
  5550. function AddToFinishableEnemyList( actor : CActor, add : bool )
  5551. {
  5552. if ( add && !finishableEnemiesList.Contains( actor ) )
  5553. {
  5554. finishableEnemiesList.PushBack(actor);
  5555. }
  5556. else if ( !add )
  5557. {
  5558. finishableEnemiesList.Remove(actor);
  5559. }
  5560. }
  5561.  
  5562. private function UpdateFinishableEnemyList()
  5563. {
  5564. var i : int;
  5565. i = 0;
  5566. while ( i < finishableEnemiesList.Size() )
  5567. {
  5568. if ( !finishableEnemiesList[ i ] )
  5569. {
  5570. finishableEnemiesList.EraseFast( i );
  5571. }
  5572. else
  5573. {
  5574. i += 1;
  5575. }
  5576. }
  5577. }
  5578.  
  5579. private timer function ClearFinishableEnemyList( dt : float, id : int )
  5580. {
  5581. finishableEnemiesList.Clear();
  5582. }
  5583.  
  5584. private var hostileEnemyToRemove : CActor;
  5585. private timer function RemoveEnemyFromHostileEnemiesListTimer( time : float , id : int)
  5586. {
  5587. hostileEnemies.Remove( hostileEnemyToRemove );
  5588.  
  5589. if( hostileEnemyToRemove.IsMonster() )
  5590. hostileMonsters.Remove( hostileEnemyToRemove );
  5591.  
  5592. hostileEnemyToRemove = NULL;
  5593. }
  5594.  
  5595. private function ClearHostileEnemiesList()
  5596. {
  5597. hostileEnemies.Clear();
  5598. hostileMonsters.Clear();
  5599. canFindPathEnemiesList.Clear();
  5600. }
  5601.  
  5602. private var moveTargets : array<CActor>; //all hostileEnemies that Geralt is aware of.
  5603. public function GetMoveTargets() : array<CActor> { return moveTargets; }
  5604. public function GetNumberOfMoveTargets() : int { return moveTargets.Size(); }
  5605.  
  5606. protected var enableStrafe : bool;
  5607.  
  5608.  
  5609. public function FindMoveTarget()
  5610. {
  5611. var moveTargetDists : array<float>;
  5612. var moveTargetCanPathFinds : array<bool>;
  5613. var aPotentialMoveTargetCanFindPath : bool;
  5614.  
  5615. var newMoveTarget : CActor;
  5616. var actors : array<CActor>;
  5617. var currentHeading : float;
  5618. var size, i : int;
  5619. var playerToNewMoveTargetDist : float;
  5620. var playerToMoveTargetDist : float;
  5621. var confirmEmptyMoveTarget : bool;
  5622. var newEmptyMoveTargetTimer : float;
  5623. var wasVisibleInFullFrame : bool;
  5624. var setIsThreatened : bool;
  5625.  
  5626. var enemysTarget : CActor;
  5627. var isEnemyInCombat : bool;
  5628. var potentialMoveTargets : array<CActor>;
  5629. var onlyThreatTargets : bool;
  5630.  
  5631. thePlayer.SetupEnemiesCollection( enemyCollectionDist, enemyCollectionDist, 10, 'None', FLAG_Attitude_Neutral + FLAG_Attitude_Hostile + FLAG_Attitude_Friendly + FLAG_OnlyAliveActors );
  5632.  
  5633. //if ( moveTarget )
  5634. // cachedMoveTarget = moveTarget;
  5635.  
  5636. if ( GetCurrentStateName() != 'PlayerDialogScene' && IsAlive() )//&& !IsInCombatAction() )//GetBIsCombatActionAllowed() )
  5637. {
  5638. GetVisibleEnemies( actors );
  5639.  
  5640. //Include enemies that geralt cannot see, but is hostile to him
  5641. if ( hostileEnemies.Size() > 0 )
  5642. {
  5643. for( i=0; i < hostileEnemies.Size() ; i+=1 )
  5644. {
  5645. if ( !actors.Contains( hostileEnemies[i] ) )
  5646. actors.PushBack( hostileEnemies[i] );
  5647. }
  5648. }
  5649.  
  5650. //Include enemies that are technically dead, but can be finished off
  5651. if ( finishableEnemiesList.Size() > 0 )
  5652. {
  5653. for( i=0; i < finishableEnemiesList.Size() ; i+=1 )
  5654. {
  5655. if ( !actors.Contains( finishableEnemiesList[i] ) )
  5656. actors.PushBack( finishableEnemiesList[i] );
  5657. }
  5658. }
  5659.  
  5660. //Check the last moveTarget for situation where enemy targets an ally when you round a corner
  5661. if ( moveTarget && !actors.Contains( moveTarget ) )
  5662. actors.PushBack( moveTarget );
  5663.  
  5664. FilterActors( actors, onlyThreatTargets, false );
  5665.  
  5666. //Determine whether Player should be threatened
  5667. if ( actors.Size() > 0 )
  5668. {
  5669. setIsThreatened = false;
  5670.  
  5671. if ( onlyThreatTargets )
  5672. {
  5673. setIsThreatened = true;
  5674. }
  5675. else
  5676. {
  5677. for( i=0; i < actors.Size() ; i+=1 )
  5678. {
  5679. if ( IsThreat( actors[i] ) )
  5680. {
  5681. setIsThreatened = true;
  5682. break;
  5683. }
  5684. else
  5685. {
  5686. enemysTarget = actors[i].GetTarget();
  5687. isEnemyInCombat = actors[i].IsInCombat();
  5688. if ( isEnemyInCombat && enemysTarget && GetAttitudeBetween( enemysTarget, this ) == AIA_Friendly && enemysTarget.isPlayerFollower )
  5689. {
  5690. setIsThreatened = true;
  5691. break;
  5692. }
  5693. }
  5694. }
  5695. }
  5696.  
  5697. //After filtering you will only have either all hostile or all neutral npcs
  5698. for( i = actors.Size()-1; i>=0; i-=1 )
  5699. {
  5700. if ( ( !actors[i].IsAlive() && !finishableEnemiesList.Contains( actors[i] ) )
  5701. || actors[i].IsKnockedUnconscious()
  5702. || this.GetUsedVehicle() == actors[i]
  5703. || !actors[i].CanBeTargeted() )
  5704. {
  5705. actors.EraseFast(i);
  5706. }
  5707. else if ( !IsThreatened() )
  5708. {
  5709. if ( !WasVisibleInScaledFrame( actors[i], 1.f, 1.f ) )
  5710. actors.EraseFast(i);
  5711. }
  5712. }
  5713. }
  5714. else if ( moveTarget && IsThreat( moveTarget ) )
  5715. setIsThreatened = true;
  5716. //SetIsThreatened( true );
  5717. else
  5718. setIsThreatened = false;
  5719. //SetIsThreatened( false );
  5720.  
  5721. if ( setIsThreatened )
  5722. {
  5723. enemyCollectionDist = 50.f;
  5724. SetIsThreatened( true );
  5725. }
  5726. else
  5727. {
  5728. if ( IsThreatened() )
  5729. AddTimer( 'finishableEnemiesList', 1.f );
  5730.  
  5731. enemyCollectionDist = findMoveTargetDistMax;
  5732. SetIsThreatened( false );
  5733. }
  5734.  
  5735. moveTargets = actors;
  5736. potentialMoveTargets = moveTargets;
  5737.  
  5738. //MS: By default Geralt will not play PCS_AlertNear unless there is one guy among the hostile npcs that canBeStrafed
  5739. if ( !moveTarget )
  5740. enableStrafe = false;
  5741.  
  5742. if ( potentialMoveTargets.Size() > 0 )
  5743. {
  5744. for ( i = 0; i < potentialMoveTargets.Size(); i += 1 )
  5745. {
  5746. if ( potentialMoveTargets[i].CanBeStrafed() )
  5747. enableStrafe = true;
  5748.  
  5749. if ( !potentialMoveTargets[i].GetGameplayVisibility() )
  5750. moveTargetDists.PushBack( 100.f ); //Put invisible enemies as the last choice for moveTarget
  5751. else
  5752. moveTargetDists.PushBack( VecDistance( potentialMoveTargets[i].GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() ) );
  5753.  
  5754. if ( canFindPathEnemiesList.Contains( potentialMoveTargets[i] ) )
  5755. {
  5756. moveTargetCanPathFinds.PushBack( true );
  5757. aPotentialMoveTargetCanFindPath = true;
  5758. }
  5759. else
  5760. {
  5761. moveTargetCanPathFinds.PushBack( false );
  5762. }
  5763. }
  5764.  
  5765. if ( aPotentialMoveTargetCanFindPath )
  5766. {
  5767. for ( i = moveTargetCanPathFinds.Size()-1 ; i >= 0; i-=1 )
  5768. {
  5769. if ( !moveTargetCanPathFinds[i] )
  5770. {
  5771. moveTargetCanPathFinds.EraseFast(i);
  5772. potentialMoveTargets.EraseFast(i);
  5773. moveTargetDists.EraseFast(i);
  5774. }
  5775. }
  5776. }
  5777.  
  5778. if ( moveTargetDists.Size() > 0 )
  5779. newMoveTarget = potentialMoveTargets[ ArrayFindMinF( moveTargetDists ) ];
  5780. }
  5781.  
  5782. if ( newMoveTarget && newMoveTarget != moveTarget )
  5783. {
  5784. if ( moveTarget )
  5785. {
  5786. playerToNewMoveTargetDist = VecDistance( newMoveTarget.GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() );
  5787. playerToMoveTargetDist = VecDistance( moveTarget.GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() );
  5788. wasVisibleInFullFrame = WasVisibleInScaledFrame( moveTarget, 1.f, 1.f ) ;
  5789.  
  5790. if ( !IsThreat( moveTarget )
  5791. || !wasVisibleInFullFrame
  5792. || !IsEnemyVisible( moveTarget )
  5793. || ( !moveTarget.IsAlive() && !finishableEnemiesList.Contains( moveTarget ) )
  5794. || !moveTarget.GetGameplayVisibility()
  5795. || ( moveTarget.IsAlive() && moveTarget.IsKnockedUnconscious() )
  5796. || ( wasVisibleInFullFrame && IsEnemyVisible( moveTarget ) && playerToNewMoveTargetDist < playerToMoveTargetDist - 0.25f ) )
  5797. {
  5798. SetMoveTarget( newMoveTarget );
  5799. }
  5800. }
  5801. else
  5802. SetMoveTarget( newMoveTarget );
  5803. }
  5804.  
  5805.  
  5806. if ( !IsThreatened() )
  5807. {
  5808. if ( moveTarget
  5809. && ( ( !moveTarget.IsAlive() && !finishableEnemiesList.Contains( moveTarget ) ) || !WasVisibleInScaledFrame( moveTarget, 0.8f, 1.f ) || VecDistance( moveTarget.GetWorldPosition(), this.GetWorldPosition() ) > theGame.params.MAX_THROW_RANGE ) )
  5810. {
  5811. confirmEmptyMoveTarget = true;
  5812. newEmptyMoveTargetTimer = 0.f;
  5813. }
  5814. }
  5815. /*else if ( moveTarget
  5816. && ( moveTarget.IsAlive() || finishableEnemiesList.Contains( moveTarget ) )
  5817. //&& moveTarget.GetGameplayVisibility()
  5818. && hostileEnemies.Contains( moveTarget ) )
  5819. */
  5820. else if ( moveTarget && ( IsThreat( moveTarget ) || finishableEnemiesList.Contains( moveTarget ) ) )
  5821. {
  5822. if ( !IsEnemyVisible( moveTarget ) )
  5823. {
  5824. confirmEmptyMoveTarget = true;
  5825. newEmptyMoveTargetTimer = 5.f;
  5826. }
  5827. else
  5828. SetMoveTarget( moveTarget );
  5829. }
  5830. else if ( IsInCombat() )
  5831. {
  5832. confirmEmptyMoveTarget = true;
  5833. newEmptyMoveTargetTimer = 1.0f;
  5834. }
  5835.  
  5836. if ( confirmEmptyMoveTarget )
  5837. {
  5838. if ( newEmptyMoveTargetTimer < emptyMoveTargetTimer )
  5839. {
  5840. bIsConfirmingEmptyTarget = false;
  5841. emptyMoveTargetTimer = newEmptyMoveTargetTimer;
  5842. }
  5843.  
  5844. ConfirmEmptyMoveTarget( newEmptyMoveTargetTimer );
  5845. }
  5846. }
  5847. else
  5848. SetIsThreatened( false );
  5849.  
  5850. //reactionsSystem
  5851. if ( IsThreatened() && !IsInFistFightMiniGame() )
  5852. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'CombatNearbyAction', 5.0, 18.0f, -1.f, -1, true ); //reactionSystemSearch
  5853. else
  5854. theGame.GetBehTreeReactionManager().RemoveReactionEvent( this, 'CombatNearbyAction'); //reactionSystemSearch
  5855.  
  5856. // sending nearby monsters count as parameter to sound system
  5857. theSound.SoundParameter( "monster_count", hostileMonsters.Size() );
  5858. }
  5859.  
  5860. private function ConfirmEmptyMoveTarget( timeDelta : float )
  5861. {
  5862. if ( !bIsConfirmingEmptyTarget )
  5863. {
  5864. bIsConfirmingEmptyTarget = true;
  5865. AddTimer( 'ConfirmEmptyTargetTimer', timeDelta );
  5866. }
  5867. }
  5868.  
  5869. private timer function ConfirmEmptyTargetTimer( time : float , id : int)
  5870. {
  5871. SetMoveTarget( NULL );
  5872. }
  5873.  
  5874.  
  5875. var isInCombatReason : int;
  5876. var canFindPathToEnemy : bool;
  5877. var combatModeEnt : CEntity;
  5878. var navDist : float;
  5879. var directDist : float;
  5880. var reachableEnemyWasTooFar : bool;
  5881. var reachableEnemyWasTooFarTimeStamp : float;
  5882. var reachablilityFailed : bool;
  5883. var reachablilityFailedTimeStamp : float;
  5884. public function ShouldEnableCombat( out unableToPathFind : bool, forceCombatMode : bool ) : bool
  5885. {
  5886. var shouldFindPathToNPCs : bool;
  5887. var playerToTargetDist : float;
  5888. var canFindPathToTarget : bool;
  5889. var moveTargetNPC : CNewNPC;
  5890. var currentTime : float;
  5891. var currentTime2 : float;
  5892. var isReachableEnemyTooFar : bool;
  5893. var reachableEnemyWasTooFarTimeStampDelta : float;
  5894. var reachablilityFailedTimeStampDelta : float;
  5895. var currentTimeTemp : float;
  5896.  
  5897. /*if ( GetIsSprinting() )
  5898. {
  5899. unableToPathFind = true;
  5900. isInCombatReason = 0;
  5901. return false;
  5902. }*/
  5903.  
  5904. if ( forceCombatMode && isSnappedToNavMesh )
  5905. return true;
  5906.  
  5907. if ( !IsThreatened() )
  5908. {
  5909. reachableEnemyWasTooFar = false;
  5910. reachablilityFailed = false;
  5911. isInCombatReason = 0;
  5912. return false;
  5913. }
  5914.  
  5915. if( thePlayer.substateManager.GetStateCur() != 'CombatExploration' && !thePlayer.substateManager.CanChangeToState( 'CombatExploration' )
  5916. && thePlayer.substateManager.GetStateCur() != 'Ragdoll' ) //&& !thePlayer.substateManager.CanChangeToState( 'Ragdoll' ) ) )
  5917. {
  5918. reachableEnemyWasTooFar = false;
  5919. reachablilityFailed = false;
  5920. isInCombatReason = 0;
  5921. return false;
  5922. }
  5923.  
  5924. if ( moveTarget )
  5925. {
  5926. canFindPathToEnemy = CanFindPathToTarget( unableToPathFind );
  5927. currentTimeTemp = EngineTimeToFloat( theGame.GetEngineTime() );
  5928.  
  5929. if ( canFindPathToEnemy )
  5930. isReachableEnemyTooFar = IsReachableEnemyTooFar();
  5931.  
  5932. if ( IsInCombat() )
  5933. {
  5934. if ( canFindPathToEnemy )
  5935. {
  5936. if ( forceCombatMode )
  5937. return true;
  5938.  
  5939. reachablilityFailed = false;
  5940. reachablilityFailedTimeStamp = currentTimeTemp;
  5941.  
  5942. if ( reachableEnemyWasTooFar )
  5943. {
  5944. if ( isReachableEnemyTooFar )
  5945. {
  5946. currentTime = currentTimeTemp;
  5947.  
  5948. if ( GetIsSprinting() )
  5949. reachableEnemyWasTooFarTimeStampDelta = 0.f;
  5950. else
  5951. reachableEnemyWasTooFarTimeStampDelta = 3.f;
  5952.  
  5953. if ( currentTime > reachableEnemyWasTooFarTimeStamp + reachableEnemyWasTooFarTimeStampDelta )
  5954. {
  5955. isInCombatReason = 0;
  5956. unableToPathFind = true;
  5957. return false;
  5958. }
  5959. }
  5960. else
  5961. reachableEnemyWasTooFar = false;
  5962. }
  5963. else
  5964. {
  5965. if ( isReachableEnemyTooFar )
  5966. {
  5967. reachableEnemyWasTooFar = true;
  5968. reachableEnemyWasTooFarTimeStamp = currentTimeTemp;
  5969. }
  5970. else
  5971. reachableEnemyWasTooFar = false;
  5972. }
  5973.  
  5974. return true;
  5975. }
  5976. else
  5977. {
  5978. reachableEnemyWasTooFar = false;
  5979. reachableEnemyWasTooFarTimeStamp = currentTimeTemp;
  5980.  
  5981. if ( reachablilityFailed )
  5982. {
  5983. if ( IsEnemyTooHighToReach() )
  5984. reachablilityFailedTimeStampDelta = 1.f;
  5985. else
  5986. reachablilityFailedTimeStampDelta = 5.f;
  5987.  
  5988. currentTime2 = currentTimeTemp;
  5989. if ( currentTime2 > reachablilityFailedTimeStamp + reachablilityFailedTimeStampDelta )
  5990. {
  5991. unableToPathFind = true;
  5992. return false;
  5993. }
  5994. }
  5995. else
  5996. {
  5997. reachablilityFailed = true;
  5998. reachablilityFailedTimeStamp = currentTimeTemp;
  5999. }
  6000.  
  6001. return true;
  6002. }
  6003. }
  6004. else if ( canFindPathToEnemy )
  6005. {
  6006. if ( forceCombatMode )
  6007. {
  6008. reachableEnemyWasTooFar = false;
  6009. return true;
  6010. }
  6011.  
  6012. reachablilityFailed = false;
  6013. reachablilityFailedTimeStamp = currentTimeTemp;
  6014.  
  6015. moveTargetNPC = (CNewNPC)moveTarget;
  6016. playerToTargetDist = VecDistance( moveTarget.GetWorldPosition(), this.GetWorldPosition() );
  6017.  
  6018. /*if ( !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), moveTarget.GetWorldPosition(), 0.4f ) )
  6019. {
  6020. isInCombatReason = 0;
  6021. return false;
  6022. }
  6023. else*/ if ( reachableEnemyWasTooFar
  6024. && ( isReachableEnemyTooFar || !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), moveTarget.GetWorldPosition(), 0.4f ) ) )
  6025. {
  6026. isInCombatReason = 0;
  6027. return false;
  6028. }
  6029. else if ( playerToTargetDist <= findMoveTargetDistMin )
  6030. isInCombatReason = 1;
  6031. else if ( ( moveTargetNPC.GetCurrentStance() == NS_Fly || moveTargetNPC.IsRanged() ) && hostileEnemies.Contains( moveTarget ) )
  6032. isInCombatReason = 2;
  6033. else
  6034. {
  6035. isInCombatReason = 0;
  6036. return false;
  6037. }
  6038.  
  6039. reachableEnemyWasTooFar = false;
  6040. return true;
  6041. }
  6042. }
  6043. else
  6044. {
  6045. reachableEnemyWasTooFar = false;
  6046. reachablilityFailed = false;
  6047. }
  6048.  
  6049. isInCombatReason = 0;
  6050. return false;
  6051. }
  6052.  
  6053. private function CanFindPathToTarget( out unableToPathFind : bool, optional forcedTarget : CNewNPC ) : bool
  6054. {
  6055. var moveTargetNPC : CNewNPC;
  6056. var moveTargetsTemp : array<CActor>;
  6057. var i : int;
  6058. var safeSpotTolerance : float;
  6059. var ent : CEntity;
  6060.  
  6061. moveTargetsTemp = moveTargets;
  6062.  
  6063. for ( i = 0; i < moveTargetsTemp.Size(); i += 1 )
  6064. {
  6065. moveTargetNPC = (CNewNPC)moveTargetsTemp[i];
  6066.  
  6067. if ( moveTargetNPC && moveTargetNPC.GetCurrentStance() == NS_Fly )
  6068. {
  6069. isInCombatReason = 2;
  6070. return true;
  6071. }
  6072. }
  6073.  
  6074. switch ( navQuery.GetLastOutput( 0.4 ) )
  6075. {
  6076. case EAsyncTastResult_Failure:
  6077. {
  6078. isInCombatReason = 0;
  6079. return false;
  6080. }
  6081. case EAsyncTastResult_Success:
  6082. {
  6083. ent = navQuery.GetOutputClosestEntity();
  6084.  
  6085. if ( ent )
  6086. combatModeEnt = moveTarget;
  6087.  
  6088. navDist = navQuery.GetOutputClosestDistance();
  6089.  
  6090. isInCombatReason = 1;
  6091. return true;
  6092. }
  6093. case EAsyncTastResult_Pending:
  6094. {
  6095. return canFindPathToEnemy;
  6096. }
  6097. case EAsyncTastResult_Invalidated:
  6098. {
  6099. if ( IsInCombat() )
  6100. {
  6101. if ( IsEnemyTooHighToReach() )
  6102. safeSpotTolerance = 0.f;
  6103. else
  6104. safeSpotTolerance = 3.f;
  6105. }
  6106. else
  6107. safeSpotTolerance = 0.f;
  6108.  
  6109. switch( navQuery.TestActorsList( ENavigationReachability_Any, this, moveTargetsTemp, safeSpotTolerance, 75.0 ) )
  6110. {
  6111. case EAsyncTastResult_Failure:
  6112. {
  6113. isInCombatReason = 0;
  6114. return false;
  6115. }
  6116. case EAsyncTastResult_Success:
  6117. {
  6118. ent = navQuery.GetOutputClosestEntity();
  6119.  
  6120. if ( ent )
  6121. combatModeEnt = moveTarget;
  6122.  
  6123. navDist = navQuery.GetOutputClosestDistance();
  6124.  
  6125. isInCombatReason = 1;
  6126. return true;
  6127. }
  6128. case EAsyncTastResult_Pending:
  6129. {
  6130. return canFindPathToEnemy;
  6131. }
  6132. case EAsyncTastResult_Invalidated:
  6133. {
  6134. if ( IsInCombat() )
  6135. return true;
  6136. else
  6137. return false;
  6138. }
  6139. }
  6140. }
  6141. }
  6142. }
  6143.  
  6144. private function IsReachableEnemyTooFar() : bool
  6145. {
  6146. //var navDistFailMax : float = 100.f;
  6147. var navDistLimit : float = findMoveTargetDist; //25.f;
  6148. var navDistDivisor : float = 2.f;
  6149. var playerToTargetVector : Vector;
  6150.  
  6151. directDist = VecDistance( combatModeEnt.GetWorldPosition(), thePlayer.GetWorldPosition() );
  6152. playerToTargetVector = this.GetWorldPosition() - combatModeEnt.GetWorldPosition();
  6153.  
  6154. if ( playerMode.GetForceCombatMode() || isInCombatReason == 2 )
  6155. return false;
  6156.  
  6157. if ( ( playerToTargetVector.Z < 0.5 && navDist > navDistLimit && directDist < navDist/navDistDivisor ) )
  6158. return true;
  6159. else
  6160. return false;
  6161. }
  6162.  
  6163. private function IsEnemyTooHighToReach() : bool
  6164. {
  6165. var playerToTargetVector : Vector;
  6166.  
  6167. playerToTargetVector = this.GetWorldPosition() - combatModeEnt.GetWorldPosition();
  6168.  
  6169. if ( playerToTargetVector.Z < -0.5f && !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), combatModeEnt.GetWorldPosition(), 0.4f ) )
  6170. return true;
  6171. else
  6172. return false;
  6173. }
  6174.  
  6175. //Force Geralt to face an enemy for a moment before changing to another enemy
  6176. public function LockToMoveTarget( lockTime : float )
  6177. {
  6178. /*if ( IsMoveTargetChangeAllowed() )
  6179. {
  6180. bMoveTargetChangeAllowed = false;
  6181. AddTimer( 'DisableLockToMoveTargetTimer', lockTime );
  6182. }*/
  6183. }
  6184.  
  6185. private timer function DisableLockToMoveTargetTimer( time : float , id : int)
  6186. {
  6187. if ( !this.IsActorLockedToTarget() )
  6188. {
  6189. SetMoveTargetChangeAllowed( true );
  6190. }
  6191. }
  6192.  
  6193. public function SetMoveTargetChangeAllowed( flag : bool )
  6194. {
  6195. //bMoveTargetChangeAllowed = flag;
  6196. }
  6197.  
  6198. public function IsMoveTargetChangeAllowed() : bool
  6199. {
  6200. return bMoveTargetChangeAllowed;
  6201. }
  6202.  
  6203. public function SetMoveTarget( actor : CActor )
  6204. {
  6205. if ( !actor && ForceCombatModeOverride() )
  6206. return;
  6207.  
  6208. if ( IsMoveTargetChangeAllowed()
  6209. && moveTarget != actor )
  6210. {
  6211. moveTarget = actor;
  6212. bIsConfirmingEmptyTarget = false;
  6213. RemoveTimer( 'ConfirmEmptyTargetTimer' );
  6214.  
  6215. if ( !moveTarget )
  6216. SetScriptMoveTarget( moveTarget );
  6217. }
  6218. }
  6219.  
  6220. private var isThreatened : bool;
  6221. protected function SetIsThreatened( flag : bool )
  6222. {
  6223. var allowSetIsThreatened : bool;
  6224.  
  6225. allowSetIsThreatened = true;
  6226. if ( ForceCombatModeOverride() )
  6227. {
  6228. if ( flag || !moveTarget )
  6229. allowSetIsThreatened = true;
  6230. else
  6231. allowSetIsThreatened = false;
  6232. }
  6233.  
  6234. if ( allowSetIsThreatened )
  6235. {
  6236. isThreatened = flag;
  6237. }
  6238. }
  6239.  
  6240. public function ForceCombatModeOverride() : bool
  6241. {
  6242. if( this.GetPlayerMode().GetForceCombatMode()
  6243. && canFindPathToEnemy
  6244. && theGame.GetGlobalAttitude( GetBaseAttitudeGroup(), moveTarget.GetBaseAttitudeGroup() ) == AIA_Hostile )
  6245. return true;
  6246. else
  6247. return false;
  6248. }
  6249.  
  6250. public function IsThreatened() : bool { return isThreatened; }
  6251.  
  6252. public function EnableFindTarget( flag : bool )
  6253. {
  6254. var target : CActor;
  6255.  
  6256. if( IsActorLockedToTarget() )
  6257. {
  6258. target = GetTarget();
  6259.  
  6260. if ( target && target.IsAlive() )
  6261. bCanFindTarget = flag;
  6262. else
  6263. bCanFindTarget = true;
  6264. }
  6265. else
  6266. bCanFindTarget = flag;
  6267. }
  6268.  
  6269. public function UpdateDisplayTarget( optional forceUpdate : bool, optional forceNullActor : bool )
  6270. {
  6271. var hud : CR4ScriptedHud;
  6272. var tempTarget : CGameplayEntity;
  6273. var angleDist1 : float;
  6274. var angleDist2 : float;
  6275. var nonActorTargetMult : float;
  6276. var combatActionType : int;
  6277. var currTarget : CActor;
  6278. var interactionTarget : CInteractionComponent;
  6279.  
  6280. var heading : float;
  6281.  
  6282. if(theGame.IsDialogOrCutscenePlaying())
  6283. {
  6284. currentSelectedDisplayTarget = NULL;
  6285.  
  6286. if ( displayTarget )
  6287. ConfirmDisplayTarget( NULL );
  6288.  
  6289. return;
  6290. }
  6291.  
  6292. if ( forceNullActor )
  6293. currTarget = NULL;
  6294. else
  6295. currTarget = GetTarget();
  6296.  
  6297. currentSelectedDisplayTarget = currTarget;
  6298.  
  6299. if ( currTarget && !currTarget.IsTargetableByPlayer() )
  6300. {
  6301. currentSelectedDisplayTarget = NULL;
  6302. ConfirmDisplayTarget( currentSelectedDisplayTarget );
  6303. return;
  6304. }
  6305. //Setting multiplier that increases non actor target priority
  6306. nonActorTargetMult = 1.25;
  6307.  
  6308. //Update the interaction icon
  6309. hud = (CR4ScriptedHud)theGame.GetHud();
  6310.  
  6311. if ( !IsThreatened() )
  6312. {
  6313. if ( !bLAxisReleased || lastAxisInputIsMovement )
  6314. {
  6315. if ( currTarget )
  6316. angleDist1 = AbsF( AngleDistance( this.GetHeading(), VecHeading( currTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6317. else
  6318. angleDist1 = 360;
  6319.  
  6320. if ( nonActorTarget )
  6321. angleDist2 = AbsF( AngleDistance( this.GetHeading(), VecHeading( nonActorTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6322. else
  6323. angleDist2 = 360;
  6324. }
  6325. else
  6326. {
  6327. if ( currTarget )
  6328. angleDist1 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( currTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6329. else
  6330. angleDist1 = 360;
  6331.  
  6332. if ( nonActorTarget )
  6333. angleDist2 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( nonActorTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6334. else
  6335. angleDist2 = 360;
  6336. }
  6337. }
  6338.  
  6339. else
  6340. {
  6341. if ( !bLAxisReleased )
  6342. {
  6343. if ( ShouldUsePCModeTargeting() )
  6344. {
  6345. if ( currTarget )
  6346. angleDist1 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( currTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6347. else
  6348. angleDist1 = 360;
  6349.  
  6350. if ( nonActorTarget && IsInCombatAction() )
  6351. {
  6352. angleDist2 = nonActorTargetMult * AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( nonActorTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6353. }
  6354. else
  6355. angleDist2 = 360;
  6356. }
  6357. else
  6358. {
  6359. if ( currTarget )
  6360. angleDist1 = AbsF( AngleDistance( rawPlayerHeading, VecHeading( currTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6361. else
  6362. angleDist1 = 360;
  6363.  
  6364. if ( nonActorTarget && IsInCombatAction() )
  6365. {
  6366. angleDist2 = nonActorTargetMult * AbsF( AngleDistance( rawPlayerHeading, VecHeading( nonActorTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6367. }
  6368. else
  6369. angleDist2 = 360;
  6370. }
  6371. }
  6372. else
  6373. {
  6374. angleDist1 = 0;
  6375. angleDist2 = 360;
  6376. }
  6377. }
  6378.  
  6379.  
  6380. if ( angleDist1 < angleDist2 )
  6381. tempTarget = currTarget;
  6382. else
  6383. tempTarget = nonActorTarget;
  6384.  
  6385.  
  6386. if ( slideTarget && IsInCombatAction() )
  6387. {
  6388. combatActionType = (int)this.GetBehaviorVariable( 'combatActionType' );
  6389. if ( combatActionType == (int)CAT_Attack
  6390. || ( combatActionType == (int)CAT_SpecialAttack && this.GetBehaviorVariable( 'playerAttackType' ) == 1.f )
  6391. || ( combatActionType == (int)CAT_ItemThrow )
  6392. || ( combatActionType == (int)CAT_CastSign && !IsCurrentSignChanneled() )
  6393. || ( combatActionType == (int)CAT_CastSign && IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Axii )
  6394. || ( combatActionType == (int)CAT_CastSign && IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Igni )
  6395. || combatActionType == (int)CAT_Dodge
  6396. || combatActionType == (int)CAT_Roll )
  6397. {
  6398. if ( combatActionType == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Igni && !IsCombatMusicEnabled() )
  6399. currentSelectedDisplayTarget = tempTarget;
  6400. else
  6401. currentSelectedDisplayTarget = slideTarget;
  6402. }
  6403. else
  6404. currentSelectedDisplayTarget = tempTarget;
  6405. }
  6406. else if ( slideTarget
  6407. && this.rangedWeapon
  6408. && this.rangedWeapon.GetCurrentStateName() != 'State_WeaponWait'
  6409. && this.playerAiming.GetCurrentStateName() == 'Waiting' ) //( this.rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' || this.rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' ) )
  6410. currentSelectedDisplayTarget = slideTarget;
  6411. else
  6412. currentSelectedDisplayTarget = tempTarget;
  6413.  
  6414. interactionTarget = theGame.GetInteractionsManager().GetActiveInteraction();
  6415. if ( interactionTarget && !IsThreatened() && !( this.IsCastingSign() && this.IsCurrentSignChanneled() ) )
  6416. {
  6417. tempTarget = (CGameplayEntity)interactionTarget.GetEntity();
  6418. if ( tempTarget && tempTarget != this.GetUsedVehicle() )
  6419. {
  6420. currentSelectedDisplayTarget = tempTarget;
  6421. SetDisplayTarget( currentSelectedDisplayTarget );
  6422. }
  6423. }
  6424.  
  6425. // disabling display for invisible targets
  6426. if ( (CActor)currentSelectedDisplayTarget && !((CActor)currentSelectedDisplayTarget).GetGameplayVisibility() )
  6427. {
  6428. currentSelectedDisplayTarget = NULL;
  6429. }
  6430.  
  6431. if ( displayTarget != currentSelectedDisplayTarget )
  6432. {
  6433. if ( forceUpdate )
  6434. SetDisplayTarget( currentSelectedDisplayTarget );
  6435. else
  6436. ConfirmDisplayTarget( currentSelectedDisplayTarget );
  6437. }
  6438. }
  6439.  
  6440. private var bConfirmDisplayTargetTimerEnabled : bool;
  6441. private var displayTargetToConfirm : CGameplayEntity;
  6442. private var currentSelectedDisplayTarget : CGameplayEntity;
  6443.  
  6444. private function ConfirmDisplayTarget( targetToConfirm : CGameplayEntity )
  6445. {
  6446. if ( targetToConfirm != displayTarget )
  6447. {
  6448. displayTargetToConfirm = targetToConfirm;
  6449. if( !bConfirmDisplayTargetTimerEnabled )
  6450. {
  6451. bConfirmDisplayTargetTimerEnabled = true;
  6452.  
  6453. if ( targetToConfirm )
  6454. AddTimer( 'ConfirmDisplayTargetTimer', 0.1f );
  6455. else
  6456. AddTimer( 'ConfirmDisplayTargetTimer', 0.f );
  6457. }
  6458. }
  6459. }
  6460.  
  6461. private timer function ConfirmDisplayTargetTimer( time : float, optional id : int)
  6462. {
  6463. if ( displayTargetToConfirm == currentSelectedDisplayTarget )
  6464. SetDisplayTarget( displayTargetToConfirm );
  6465.  
  6466. bConfirmDisplayTargetTimerEnabled = false;
  6467. }
  6468.  
  6469.  
  6470. protected function SetDisplayTarget( e : CGameplayEntity )
  6471. {
  6472. var displayTargetActor : CActor;
  6473.  
  6474. if ( e != displayTarget )
  6475. {
  6476. displayTarget = e;
  6477. displayTargetActor = (CActor)displayTarget;
  6478. SetPlayerCombatTarget( displayTargetActor );
  6479.  
  6480. if ( displayTargetActor && !displayTargetActor.IsTargetableByPlayer())
  6481. {
  6482. isDisplayTargetTargetable = false;
  6483. }
  6484. else if ( !displayTargetActor && displayTarget != nonActorTarget )
  6485. {
  6486. isDisplayTargetTargetable = false;
  6487. }
  6488. else
  6489. {
  6490. isDisplayTargetTargetable = true;
  6491. }
  6492. }
  6493. }
  6494.  
  6495. public function GetDisplayTarget() : CGameplayEntity { return displayTarget; }
  6496.  
  6497. private var isDisplayTargetTargetable : bool;
  6498. public function IsDisplayTargetTargetable() : bool
  6499. {
  6500. return isDisplayTargetTargetable;
  6501. }
  6502.  
  6503. public var radialSlots : array<name>;
  6504. public function EnableRadialSlots( enable : bool, slotNames : array<name> )
  6505. {
  6506. var hud : CR4ScriptedHud;
  6507. var module : CR4HudModuleRadialMenu;
  6508. var i : int;
  6509.  
  6510. hud = (CR4ScriptedHud)theGame.GetHud();
  6511. module = (CR4HudModuleRadialMenu)hud.GetHudModule("RadialMenuModule");
  6512.  
  6513. for(i=0; i<slotNames.Size(); i+=1)
  6514. {
  6515. module.SetDesaturated( !enable, slotNames[i] );
  6516. }
  6517. }
  6518.  
  6519. public function IsEnemyInCone( source : CActor, coneHeading : Vector, coneDist, coneAngle : float, out newLockTarget : CActor ) : bool
  6520. {
  6521. var targets : array<CActor>;
  6522. var sourceToTargetDists : array<float>;
  6523. var i : int;
  6524. var targetingInfo : STargetingInfo;
  6525.  
  6526. //GetVisibleEnemies( targets );
  6527. //targets = FilterActors( targets );
  6528. targets = GetMoveTargets();
  6529.  
  6530. if ( targets.Size() > 0 )
  6531. {
  6532. targetingInfo.source = this;
  6533. targetingInfo.canBeTargetedCheck = true;
  6534. targetingInfo.coneCheck = true;
  6535. targetingInfo.coneHalfAngleCos = CosF( Deg2Rad( coneAngle * 0.5f ) );
  6536. targetingInfo.coneDist = coneDist;
  6537. targetingInfo.coneHeadingVector = coneHeading;
  6538. targetingInfo.distCheck = true;
  6539. targetingInfo.invisibleCheck = true;
  6540. targetingInfo.navMeshCheck = true;
  6541. targetingInfo.inFrameCheck = false;
  6542. targetingInfo.frameScaleX = 1.f;
  6543. targetingInfo.frameScaleY = 1.f;
  6544. targetingInfo.knockDownCheck = false;
  6545. targetingInfo.knockDownCheckDist = 1.5f;
  6546. targetingInfo.rsHeadingCheck = false;
  6547. targetingInfo.rsHeadingLimitCos = 1.0f;
  6548.  
  6549. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  6550. {
  6551. targetingInfo.targetEntity = targets[i];
  6552. if ( !IsEntityTargetable( targetingInfo ) )
  6553. targets.Erase( i );
  6554. }
  6555.  
  6556. for ( i = 0; i < targets.Size(); i += 1 )
  6557. sourceToTargetDists.PushBack( VecDistance( source.GetWorldPosition(), targets[i].GetWorldPosition() ) );
  6558.  
  6559. if(sourceToTargetDists.Size() > 0)
  6560. newLockTarget = targets[ ArrayFindMinF( sourceToTargetDists ) ];
  6561. else
  6562. newLockTarget = NULL;
  6563. }
  6564.  
  6565. return targets.Size() > 0;
  6566. }
  6567.  
  6568. public function GetScreenSpaceLockTarget( sourceEnt : CGameplayEntity, coneAngle, coneDist, coneHeading : float, optional inFrameCheck : bool ) : CActor
  6569. {
  6570. var source : CActor;
  6571. var sourcePos, targetPos : Vector;
  6572. var targets : array<CActor>;
  6573. var sourceToTargetDists : array<float>;
  6574. var sourceCoord : Vector;
  6575. var targetCoord : Vector;
  6576. var i : int;
  6577. var angleDiff : float;
  6578. var sourceToTargetHeading : float;
  6579. var sourceToTargetDist : float;
  6580. var size : float;
  6581. var targetingDist : float;
  6582. var targetingInfo : STargetingInfo;
  6583.  
  6584. var temp : int;
  6585.  
  6586. // MAREK TODO : Need to use cached values of screenspace coords instead of calculating again
  6587. //GetVisibleEnemies( targets );
  6588. //targets = FilterActors( targets );
  6589. source = (CActor)sourceEnt;
  6590.  
  6591. targets = GetMoveTargets();
  6592.  
  6593. if ( this.IsPCModeEnabled() )
  6594. {
  6595. if ( ( coneHeading > -45.f && coneHeading < 45.f )
  6596. || coneHeading > 135.f
  6597. || coneHeading < -135.f )
  6598. {
  6599. if ( coneHeading > 0 )
  6600. coneHeading = 180 - coneHeading;
  6601. else
  6602. coneHeading = 180 + coneHeading;
  6603. }
  6604. }
  6605.  
  6606. /*if ( IsCombatMusicEnabled() || hostileEnemies.Size() > 0 )
  6607. {
  6608. if ( targets[0] && !IsThreat( targets[0] ) )
  6609. targets.Clear();
  6610. }*/
  6611.  
  6612. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  6613. {
  6614. if ( ( !targets[i].GetGameplayVisibility() || !IsThreat( targets[i] ) || !IsEnemyVisible( targets[i] ) || !this.CanBeTargetedIfSwimming( targets[i] ) )
  6615. && ( !IsCastingSign() || GetCurrentlyCastSign() != ST_Axii ) )
  6616. targets.Erase(i);
  6617. }
  6618.  
  6619. if ( source )
  6620. {
  6621. temp = source.GetTorsoBoneIndex();
  6622.  
  6623. if ( temp < 0 )
  6624. sourcePos = source.GetWorldPosition();
  6625. else
  6626. sourcePos = MatrixGetTranslation( source.GetBoneWorldMatrixByIndex( source.GetTorsoBoneIndex() ) );
  6627. }
  6628. else
  6629. sourcePos = sourceEnt.GetWorldPosition();
  6630.  
  6631. theCamera.WorldVectorToViewRatio( sourcePos, sourceCoord.X , sourceCoord.Y );
  6632.  
  6633. /*if ( !IsUsingVehicle() )
  6634. targetingDist = softLockDist;
  6635. else*/
  6636. targetingDist = softLockDistVehicle;
  6637.  
  6638. if ( targets.Size() > 0 )
  6639. {
  6640. targetingInfo.source = this;
  6641. targetingInfo.canBeTargetedCheck = true;
  6642. targetingInfo.coneCheck = false;
  6643. targetingInfo.coneHalfAngleCos = 0.86602540378f; // = CosF( Deg2Rad( 60.0f * 0.5f ) )
  6644. targetingInfo.coneDist = targetingDist;
  6645. targetingInfo.coneHeadingVector = Vector( 0.0f, 1.0f, 0.0f );
  6646. targetingInfo.distCheck = true;
  6647. targetingInfo.invisibleCheck = true;
  6648. targetingInfo.navMeshCheck = false;
  6649.  
  6650. if ( inFrameCheck )
  6651. targetingInfo.inFrameCheck = true;
  6652. else
  6653. targetingInfo.inFrameCheck = false;
  6654.  
  6655. targetingInfo.frameScaleX = 1.f;
  6656. targetingInfo.frameScaleY = 1.f;
  6657. targetingInfo.knockDownCheck = false;
  6658. targetingInfo.knockDownCheckDist = softLockDist;
  6659. if ( bRAxisReleased )
  6660. targetingInfo.rsHeadingCheck = false;
  6661. else
  6662. targetingInfo.rsHeadingCheck = true;
  6663. targetingInfo.rsHeadingLimitCos = -0.5f; // = CosF( Deg2Rad( 120.0f ) );
  6664.  
  6665. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  6666. {
  6667. temp = targets[i].GetTorsoBoneIndex();
  6668.  
  6669. if ( temp < 0 )
  6670. targetPos = targets[i].GetWorldPosition();
  6671. else
  6672. targetPos = MatrixGetTranslation( targets[i].GetBoneWorldMatrixByIndex( targets[i].GetTorsoBoneIndex() ) );
  6673.  
  6674. theCamera.WorldVectorToViewRatio( targetPos, targetCoord.X, targetCoord.Y );
  6675. sourceToTargetHeading = VecHeading( targetCoord - sourceCoord );
  6676. angleDiff = AbsF( AngleDistance( coneHeading, sourceToTargetHeading ) );
  6677.  
  6678. targetingInfo.targetEntity = targets[i];
  6679. if ( !IsEntityTargetable( targetingInfo ) )
  6680. targets.Erase( i );
  6681. else if ( !bRAxisReleased && angleDiff > ( coneAngle * 0.5 ) )
  6682. targets.Erase( i );
  6683. else if ( targets[i] == sourceEnt )
  6684. targets.Erase( i );
  6685.  
  6686. /*if ( GetDisplayTarget() && IsInCombatAction() && GetBehaviorVariable( 'combatActionType') == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Igni )
  6687. {
  6688.  
  6689. }
  6690. else
  6691. {
  6692. targetingInfo.rsHeadingCheck = false;
  6693. if ( !IsEntityTargetable( targetingInfo )
  6694. || angleDiff > ( coneAngle * 0.5 )
  6695. || targets[i] == sourceEnt )
  6696. targets.Erase( i );
  6697. }*/
  6698. }
  6699. }
  6700.  
  6701. size = targets.Size();
  6702. if ( size > 0 )
  6703. {
  6704. for ( i = 0; i < targets.Size(); i += 1 )
  6705. {
  6706. temp = targets[i].GetTorsoBoneIndex();
  6707.  
  6708. if ( temp < 0 )
  6709. targetPos = targets[i].GetWorldPosition();
  6710. else
  6711. targetPos = MatrixGetTranslation( targets[i].GetBoneWorldMatrixByIndex( targets[i].GetTorsoBoneIndex() ) );
  6712.  
  6713. theCamera.WorldVectorToViewRatio( targetPos, targetCoord.X, targetCoord.Y );
  6714. sourceToTargetHeading = AbsF( VecHeading( targetCoord - sourceCoord ) );
  6715. angleDiff = AngleDistance( 180, sourceToTargetHeading );
  6716. sourceToTargetDist = VecDistance2D( sourceCoord, targetCoord );
  6717.  
  6718. sourceToTargetDists.PushBack( SinF( Deg2Rad( angleDiff ) ) * sourceToTargetDist );
  6719. }
  6720. }
  6721.  
  6722. if ( targets.Size() > 0 )//GetDisplayTarget() )
  6723. return targets[ ArrayFindMinF( sourceToTargetDists ) ];
  6724. else
  6725. return NULL;
  6726. }
  6727.  
  6728. public function IsEntityTargetable( out info : STargetingInfo, optional usePrecalcs : bool ) : bool
  6729. {
  6730. var playerHasBlockingBuffs : bool;
  6731. var sourceActor : CActor;
  6732. var targetEntity : CEntity;
  6733. var targetActor : CActor;
  6734. var targetNPC : CNewNPC;
  6735. var sourcePosition : Vector;
  6736. var targetPosition : Vector;
  6737. var direction : Vector;
  6738. var sourceToTargetDist : float;
  6739. var sourceCapsuleRadius : float;
  6740. var mpac : CMovingPhysicalAgentComponent;
  6741.  
  6742. var coneDistSq : float;
  6743. var knockDownCheckDistSq : float;
  6744. var sourceToTargetAngleDist : float;
  6745. var b : bool;
  6746. var infoSourceWorldPos : Vector;
  6747. var infoTargetWorldPos : Vector;
  6748. var finishEnabled : bool;
  6749.  
  6750. if ( usePrecalcs )
  6751. {
  6752. playerHasBlockingBuffs = targetingIn.playerHasBlockingBuffs;
  6753. }
  6754. else
  6755. {
  6756. playerHasBlockingBuffs = thePlayer.HasBuff( EET_Confusion ) || thePlayer.HasBuff( EET_Hypnotized ) || thePlayer.HasBuff( EET_Blindness ) || thePlayer.HasBuff( EET_WraithBlindness );
  6757. }
  6758. if ( playerHasBlockingBuffs )
  6759. {
  6760. return false;
  6761. }
  6762.  
  6763. sourceActor = info.source;
  6764. targetEntity = info.targetEntity;
  6765. if ( !sourceActor || !targetEntity )
  6766. {
  6767. return false;
  6768. }
  6769.  
  6770. targetActor = (CActor)targetEntity;
  6771.  
  6772. // "can be targeted" check
  6773. if ( info.canBeTargetedCheck && !targetActor.CanBeTargeted() )
  6774. {
  6775. return false;
  6776. }
  6777.  
  6778. // visibility check
  6779. if ( info.invisibleCheck && !targetActor.GetGameplayVisibility() )
  6780. {
  6781. return false;
  6782. }
  6783.  
  6784. sourcePosition = sourceActor.GetWorldPosition();
  6785. targetPosition = targetEntity.GetWorldPosition();
  6786.  
  6787. if ( targetActor )
  6788. {
  6789. { // do not target mounted horses
  6790. targetNPC = (CNewNPC)targetActor;
  6791. if ( targetNPC )
  6792. {
  6793. if ( targetNPC.IsHorse() && !targetNPC.GetHorseComponent().IsDismounted() )
  6794. {
  6795. return false;
  6796. }
  6797. }
  6798. }
  6799. }
  6800.  
  6801. if ( info.distCheck || info.knockDownCheck )
  6802. {
  6803. if ( usePrecalcs )
  6804. {
  6805. if ( targetActor )
  6806. {
  6807. // radius is taken form the first actor
  6808. sourceToTargetDist = Distance2DBetweenCapsuleAndPoint( targetActor, sourceActor ) - targetingPrecalcs.playerRadius;
  6809. }
  6810. else
  6811. {
  6812. sourceToTargetDist = VecDistance2D( sourcePosition, targetPosition ) - targetingPrecalcs.playerRadius;
  6813. }
  6814. }
  6815. else
  6816. {
  6817. if ( targetActor )
  6818. {
  6819. sourceToTargetDist = Distance2DBetweenCapsules( sourceActor, targetActor );
  6820. }
  6821. else
  6822. {
  6823. sourceToTargetDist = Distance2DBetweenCapsuleAndPoint( sourceActor, targetEntity );
  6824. }
  6825. }
  6826. }
  6827.  
  6828. // distance check
  6829. if ( info.distCheck )
  6830. {
  6831. if ( sourceToTargetDist >= info.coneDist )
  6832. {
  6833. return false;
  6834. }
  6835. }
  6836.  
  6837. // prepare source to target direction if needed
  6838. if ( info.coneCheck || info.rsHeadingCheck )
  6839. {
  6840. direction = VecNormalize2D( targetPosition - sourcePosition );
  6841. }
  6842.  
  6843. // cone check
  6844. if ( info.coneCheck )
  6845. {
  6846. if ( VecDot2D( direction, info.coneHeadingVector ) < info.coneHalfAngleCos )
  6847. {
  6848. return false;
  6849. }
  6850. }
  6851.  
  6852. // heading cone check
  6853. if ( info.rsHeadingCheck )
  6854. {
  6855. if ( usePrecalcs )
  6856. {
  6857. if ( VecDot2D( direction, targetingIn.lookAtDirection ) < info.rsHeadingLimitCos )
  6858. {
  6859. return false;
  6860. }
  6861. }
  6862. else
  6863. {
  6864. if ( VecDot2D( direction, VecNormalize2D( GetLookAtPosition() - sourcePosition ) ) < info.rsHeadingLimitCos )
  6865. {
  6866. return false;
  6867. }
  6868. }
  6869. }
  6870.  
  6871. // "in frame" check
  6872. if ( info.inFrameCheck && !WasVisibleInScaledFrame( targetEntity, info.frameScaleX, info.frameScaleY ) )
  6873. {
  6874. return false;
  6875. }
  6876.  
  6877. // navmesh check
  6878. if ( info.navMeshCheck && !IsSwimming() )
  6879. {
  6880. sourceCapsuleRadius = 0.1f;
  6881. if ( usePrecalcs )
  6882. {
  6883. sourceCapsuleRadius = targetingPrecalcs.playerRadius;
  6884. }
  6885. else
  6886. {
  6887. mpac = (CMovingPhysicalAgentComponent)sourceActor.GetMovingAgentComponent();
  6888. if ( mpac )
  6889. {
  6890. sourceCapsuleRadius = mpac.GetCapsuleRadius();
  6891. }
  6892. }
  6893. if ( !theGame.GetWorld().NavigationLineTest( sourcePosition, targetPosition, sourceCapsuleRadius ) )
  6894. {
  6895. return false;
  6896. }
  6897. }
  6898.  
  6899. // knockdown check
  6900. if ( info.knockDownCheck )
  6901. {
  6902. // if actor is not alive
  6903. if ( targetActor && !targetActor.IsAlive() )
  6904. {
  6905. // and contains enabled "Finish" interaction
  6906. finishEnabled = targetActor.GetComponent( 'Finish' ).IsEnabled();
  6907. if ( finishEnabled )
  6908. {
  6909. // and is contained in finishable enemies list
  6910. if ( finishableEnemiesList.Contains( targetActor ) )
  6911. {
  6912. // and is too far to "finish" -> we cannot target it
  6913. if ( sourceToTargetDist >= info.knockDownCheckDist )
  6914. {
  6915. return false;
  6916. }
  6917. }
  6918. }
  6919. }
  6920. }
  6921.  
  6922. return true;
  6923. }
  6924.  
  6925. public function CanBeTargetedIfSwimming( actor : CActor, optional usePrecalcs : bool ) : bool
  6926. {
  6927. var subDepth : float;
  6928. var isDiving : bool;
  6929.  
  6930. if ( !actor )
  6931. {
  6932. return false;
  6933. }
  6934.  
  6935. if ( usePrecalcs )
  6936. {
  6937. isDiving = targetingIn.isDiving;
  6938. }
  6939. else
  6940. {
  6941. isDiving = IsSwimming() && OnCheckDiving();
  6942. }
  6943.  
  6944. subDepth = ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetSubmergeDepth();
  6945.  
  6946. if ( isDiving )
  6947. {
  6948. return ( subDepth < -1.0f );
  6949. }
  6950. else
  6951. {
  6952. return ( subDepth >= -1.0f );
  6953. }
  6954. }
  6955.  
  6956. /*
  6957. public function IsEntityTargetable( source : CActor, targetEntity : CGameplayEntity, coneCheck : bool, coneAngle, coneDist, coneHeading : float, distCheck, invisibleCheck, navMeshCheck : bool, inFrameCheck : bool, frameScaleX : float, frameScaleY : float, knockDownCheck : bool, knockDownCheckDist : float, rsHeadingCheck : bool, rsHeading : float, rsHeadingLimit : float) : bool
  6958. {
  6959. var targetActor : CActor;
  6960. var targetNPC : CNewNPC;
  6961. var direction : Vector;
  6962. var sourceToTargetDist : float;
  6963. var coneDistSq : float;
  6964. var sourceCapsuleRadius : float;
  6965. var knockDownCheckDistSq : float;
  6966. var sourceToTargetAngleDist : float;
  6967. var b : bool;
  6968. var targetsHorse : W3HorseComponent;
  6969.  
  6970. direction = VecNormalize2D( targetEntity.GetWorldPosition() - source.GetWorldPosition() );
  6971. targetActor = (CActor)targetEntity;
  6972.  
  6973. if ( distCheck )
  6974. {
  6975. if ( targetActor )
  6976. sourceToTargetDist = VecDistanceSquared( source.GetWorldPosition(), targetActor.GetNearestPointInBothPersonalSpaces( source.GetWorldPosition() ) );
  6977. else
  6978. sourceToTargetDist = VecDistanceSquared( source.GetWorldPosition(), targetEntity.GetWorldPosition() );
  6979.  
  6980. coneDistSq = coneDist * coneDist;
  6981. }
  6982.  
  6983. if ( knockDownCheck && targetActor )
  6984. knockDownCheckDistSq = knockDownCheckDist * knockDownCheckDist;
  6985.  
  6986. if ( navMeshCheck && targetActor )
  6987. sourceCapsuleRadius = ((CMovingPhysicalAgentComponent)source.GetMovingAgentComponent()).GetCapsuleRadius();
  6988.  
  6989. if ( rsHeadingCheck )
  6990. sourceToTargetAngleDist = AngleDistance( VecHeading( GetLookAtPosition() - source.GetWorldPosition() ), VecHeading( targetEntity.GetWorldPosition() - source.GetWorldPosition() ) );
  6991.  
  6992. // do not target mounted horses
  6993. if(targetActor)
  6994. {
  6995. targetNPC = (CNewNPC)targetActor;
  6996. if(targetNPC)
  6997. {
  6998. targetsHorse = (W3HorseComponent)targetNPC.GetHorseComponent();
  6999. if(targetsHorse && targetsHorse.IsNotBeingUsed() )
  7000. return false;
  7001. }
  7002. }
  7003.  
  7004. b = !coneCheck || AbsF( AngleDistance( coneHeading, VecHeading( direction ) ) ) < ( coneAngle * 0.5 );
  7005. b = b && ( !distCheck || sourceToTargetDist < coneDistSq );
  7006. b = b && ( !invisibleCheck || targetActor.GetGameplayVisibility() );
  7007. b = b && ( !navMeshCheck || (!IsSwimming() && theGame.GetWorld().NavigationLineTest( source.GetWorldPosition(), targetActor.GetWorldPosition(), sourceCapsuleRadius ) ) );
  7008. b = b && ( !inFrameCheck || WasVisibleInScaledFrame( targetEntity, frameScaleX, frameScaleY ) );
  7009. b = b && ( !rsHeadingCheck || ( rsHeading >= 0 && sourceToTargetAngleDist < 0 && sourceToTargetAngleDist >= ( rsHeadingLimit * -1 ) ) || ( rsHeading < 0 && sourceToTargetAngleDist >= 0 && sourceToTargetAngleDist <= rsHeadingLimit ) );
  7010. b = b && ( !knockDownCheck || !targetActor.GetComponent( 'Finish' ).IsEnabled() || ( targetActor.GetComponent( 'Finish' ).IsEnabled() && sourceToTargetDist < knockDownCheckDistSq ) );
  7011.  
  7012. if ( b )
  7013. return true;
  7014. else
  7015. return false;
  7016. }
  7017. */
  7018. private function FilterActors( out targets : array<CActor>, out onlyThreatsReturned : bool, optional usePrecalcs : bool )
  7019. {
  7020. var i : int;
  7021. var size : int;
  7022. var foundThreat : bool;
  7023. var foundNonThreat : bool;
  7024. var threatsCount : int;
  7025. var tmpActor : CActor;
  7026.  
  7027. foundThreat = false;
  7028. foundNonThreat = false;
  7029.  
  7030. size = targets.Size();
  7031. i = 0;
  7032. threatsCount = 0;
  7033.  
  7034. // after that loop first "threatsCount" targets will be "threat"
  7035. for ( i = 0; i < size; i+=1 )
  7036. {
  7037. if( IsThreat( targets[ i ], usePrecalcs ) )
  7038. {
  7039. foundThreat = true;
  7040. if ( i != threatsCount )
  7041. {
  7042. tmpActor = targets[ i ];
  7043. targets[ i ] = targets[ threatsCount ];
  7044. targets[ threatsCount ] = tmpActor;
  7045. }
  7046. threatsCount += 1;
  7047. }
  7048. else
  7049. {
  7050. foundNonThreat = true;
  7051. }
  7052. }
  7053.  
  7054. if ( foundThreat )
  7055. {
  7056. onlyThreatsReturned = true;
  7057. if ( foundNonThreat )
  7058. {
  7059. targets.Resize( threatsCount );
  7060. }
  7061. }
  7062. }
  7063.  
  7064. private function InternalFindTargetsInCone( out targets : array< CActor >, out outHeadingVector : Vector, optional usePrecalcs : bool )
  7065. {
  7066. var size, i : int;
  7067. var coneHalfAngleDot : float;
  7068. var coneHeading : float;
  7069. var coneHeadingVector : Vector;
  7070. var position : Vector;
  7071. var direction : Vector;
  7072. var onlyThreatTargetsFound : bool;
  7073.  
  7074. targets.Clear();
  7075. GetVisibleEnemies( targets );
  7076.  
  7077. //Include enemies that are technically dead, but can be finished off
  7078. for( i = 0; i < finishableEnemiesList.Size() ; i+=1 )
  7079. {
  7080. if ( !targets.Contains( finishableEnemiesList[i] ) )
  7081. {
  7082. targets.PushBack( finishableEnemiesList[i] );
  7083. }
  7084. }
  7085.  
  7086. onlyThreatTargetsFound = false;
  7087. FilterActors( targets, onlyThreatTargetsFound, true );
  7088.  
  7089. if ( IsCombatMusicEnabled() && targets.Size() > 0 && !onlyThreatTargetsFound && !IsThreat( targets[0], usePrecalcs ) )
  7090. {
  7091. targets.Clear();
  7092. }
  7093.  
  7094. coneHeading = 0.0f;
  7095. coneHalfAngleDot = 0.0f;
  7096. if ( ( orientationTarget == OT_Camera ) || ( orientationTarget == OT_CameraOffset ) )
  7097. {
  7098. if ( usePrecalcs )
  7099. {
  7100. coneHeading = targetingPrecalcs.cameraHeading;
  7101. }
  7102. else
  7103. {
  7104. coneHeading = theGame.GetGameCamera().GetHeading();
  7105. }
  7106. coneHalfAngleDot = 0.5f; // = CosF( Deg2Rad( 120.f * 0.5f ) ); - Just use calculator... why not? this is constant.
  7107. }
  7108. else
  7109. {
  7110. if ( IsSwimming() )
  7111. {
  7112. if ( usePrecalcs )
  7113. {
  7114. coneHeading = targetingPrecalcs.cameraHeading;
  7115. }
  7116. else
  7117. {
  7118. coneHeading = theGame.GetGameCamera().GetHeading();
  7119. }
  7120. coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) );
  7121. }
  7122. else if ( bLAxisReleased )
  7123. {
  7124. if( IsInCombatAction() )
  7125. {
  7126. coneHeading = GetCombatActionHeading();
  7127. }
  7128. else
  7129. {
  7130. if ( ShouldUsePCModeTargeting() )
  7131. coneHeading = theGame.GetGameCamera().GetHeading();
  7132. else
  7133. coneHeading = cachedRawPlayerHeading;
  7134. }
  7135.  
  7136. if ( IsInCombat() )
  7137. {
  7138. if ( ShouldUsePCModeTargeting() )
  7139. coneHalfAngleDot = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) )
  7140. else
  7141. coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) );
  7142. }
  7143. else
  7144. {
  7145. coneHalfAngleDot = -1.0f;
  7146. }
  7147. }
  7148. else
  7149. {
  7150. if( IsInCombatAction() )
  7151. {
  7152. coneHeading = GetCombatActionHeading();
  7153. }
  7154. else
  7155. {
  7156. if ( ShouldUsePCModeTargeting() )
  7157. coneHeading = theGame.GetGameCamera().GetHeading();
  7158. else
  7159. coneHeading = cachedRawPlayerHeading;
  7160. }
  7161.  
  7162. if ( ShouldUsePCModeTargeting() )
  7163. coneHalfAngleDot = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) )
  7164. else
  7165. coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) );
  7166. }
  7167.  
  7168. coneHeadingVector = VecFromHeading( coneHeading );
  7169. position = this.GetWorldPosition();
  7170.  
  7171. for ( i = targets.Size() - 1; i >= 0; i -= 1 )
  7172. {
  7173. if ( !targets[i] )
  7174. {
  7175. targets.EraseFast(i);
  7176. continue;
  7177. }
  7178.  
  7179. direction = VecNormalize2D( targets[i].GetWorldPosition() - position );
  7180.  
  7181. if ( VecDot2D( coneHeadingVector, direction ) < coneHalfAngleDot )
  7182. {
  7183. targets.EraseFast( i );
  7184. }
  7185. }
  7186. }
  7187.  
  7188. outHeadingVector = coneHeadingVector;
  7189. }
  7190.  
  7191. ///////////////////////////////////////////////////////////////////////////
  7192. // (new) targeting
  7193.  
  7194. function InitTargeting()
  7195. {
  7196. var consts : SR4PlayerTargetingConsts;
  7197.  
  7198. if ( !targeting )
  7199. {
  7200. targeting = new CR4PlayerTargeting in this;
  7201. }
  7202. if ( targeting )
  7203. {
  7204. consts.softLockDistance = this.softLockDist;
  7205. consts.softLockFrameSize = this.softLockFrameSize;
  7206. targeting.SetConsts( consts );
  7207. }
  7208. }
  7209.  
  7210. function PrepareTargetingIn( actionCheck : bool, bufferActionType : EBufferActionType, actionInput : bool )
  7211. {
  7212. var coneDist : float;
  7213.  
  7214. if ( actionCheck && bufferActionType == EBAT_ItemUse )
  7215. {
  7216. coneDist = findMoveTargetDist;
  7217. }
  7218. else if ( IsSwimming() )
  7219. {
  7220. coneDist = theGame.params.MAX_THROW_RANGE;
  7221. }
  7222. else if ( ( GetPlayerCombatStance() == PCS_AlertNear ) && ( ( playerMoveType == PMT_Walk ) || ( playerMoveType == PMT_Idle ) ) )
  7223. {
  7224. coneDist = softLockDist;
  7225. }
  7226. else
  7227. {
  7228. coneDist = findMoveTargetDist;
  7229. }
  7230.  
  7231. targetingIn.canFindTarget = this.bCanFindTarget;
  7232. targetingIn.playerHasBlockingBuffs = thePlayer.HasBuff( EET_Confusion ) || thePlayer.HasBuff( EET_Hypnotized ) || thePlayer.HasBuff( EET_Blindness ) || thePlayer.HasBuff( EET_WraithBlindness );
  7233. targetingIn.isHardLockedToTarget = this.IsHardLockEnabled();
  7234. targetingIn.isActorLockedToTarget = this.IsActorLockedToTarget();
  7235. targetingIn.isCameraLockedToTarget = this.IsCameraLockedToTarget();
  7236. targetingIn.actionCheck = actionCheck;
  7237. targetingIn.actionInput = actionInput;
  7238. targetingIn.isInCombatAction = this.IsInCombatAction();
  7239. targetingIn.isLAxisReleased = this.bLAxisReleased;
  7240. targetingIn.isLAxisReleasedAfterCounter = this.lAxisReleasedAfterCounter;
  7241. targetingIn.isLAxisReleasedAfterCounterNoCA = this.lAxisReleasedAfterCounterNoCA;
  7242. targetingIn.lastAxisInputIsMovement = this.lastAxisInputIsMovement;
  7243. targetingIn.isAiming = this.playerAiming.GetCurrentStateName() == 'Aiming';
  7244. targetingIn.isSwimming = this.IsSwimming();
  7245. targetingIn.isDiving = this.IsSwimming() && OnCheckDiving();
  7246. targetingIn.isThreatened = this.IsThreatened();
  7247. targetingIn.isCombatMusicEnabled = this.IsCombatMusicEnabled();
  7248. targetingIn.isPcModeEnabled = this.IsPCModeEnabled();
  7249. targetingIn.isInParryOrCounter = this.isInParryOrCounter;
  7250. targetingIn.shouldUsePcModeTargeting = this.ShouldUsePCModeTargeting();
  7251. targetingIn.bufferActionType = bufferActionType;
  7252. targetingIn.orientationTarget = this.GetOrientationTarget();
  7253. targetingIn.coneDist = coneDist; // computed few lines above
  7254. targetingIn.findMoveTargetDist = this.findMoveTargetDist;
  7255. targetingIn.cachedRawPlayerHeading = this.cachedRawPlayerHeading;
  7256. targetingIn.combatActionHeading = this.GetCombatActionHeading();
  7257. targetingIn.rawPlayerHeadingVector = VecFromHeading( this.rawPlayerHeading );
  7258. targetingIn.lookAtDirection = VecNormalize2D( this.GetLookAtPosition() - GetWorldPosition() );
  7259. targetingIn.moveTarget = this.moveTarget;
  7260. targetingIn.aimingTarget = this.playerAiming.GetAimedTarget();
  7261. targetingIn.displayTarget = (CActor)this.displayTarget;
  7262. targetingIn.finishableEnemies = this.finishableEnemiesList;
  7263. targetingIn.hostileEnemies = this.hostileEnemies;
  7264. targetingIn.defaultSelectionWeights = ProcessSelectionWeights();
  7265. }
  7266.  
  7267. function ResetTargetingOut()
  7268. {
  7269. targetingOut.target = NULL;
  7270. targetingOut.result = false;
  7271. targetingOut.confirmNewTarget = false;
  7272. targetingOut.forceDisableUpdatePosition = false;
  7273. }
  7274.  
  7275. function MakeFindTargetPrecalcs()
  7276. {
  7277. var mpac : CMovingPhysicalAgentComponent;
  7278.  
  7279. targetingPrecalcs.playerPosition = thePlayer.GetWorldPosition();
  7280. targetingPrecalcs.playerHeading = thePlayer.GetHeading();
  7281. targetingPrecalcs.playerHeadingVector = thePlayer.GetHeadingVector();
  7282. targetingPrecalcs.playerHeadingVector.Z = 0;
  7283. targetingPrecalcs.playerHeadingVector = VecNormalize2D( targetingPrecalcs.playerHeadingVector );
  7284.  
  7285. targetingPrecalcs.playerRadius = 0.5f;
  7286. mpac = (CMovingPhysicalAgentComponent)thePlayer.GetMovingAgentComponent();
  7287. if ( mpac )
  7288. {
  7289. targetingPrecalcs.playerRadius = mpac.GetCapsuleRadius();
  7290. }
  7291.  
  7292. targetingPrecalcs.cameraPosition = theCamera.GetCameraPosition();
  7293. targetingPrecalcs.cameraDirection = theCamera.GetCameraDirection();
  7294. targetingPrecalcs.cameraHeadingVector = targetingPrecalcs.cameraDirection;
  7295. targetingPrecalcs.cameraHeadingVector.Z = 0;
  7296. targetingPrecalcs.cameraHeadingVector = VecNormalize2D( targetingPrecalcs.cameraHeadingVector );
  7297. targetingPrecalcs.cameraHeading = VecHeading( targetingPrecalcs.cameraHeadingVector );
  7298. }
  7299.  
  7300. public function GetForceDisableUpdatePosition() : bool
  7301. {
  7302. return targetingOut.forceDisableUpdatePosition;
  7303. }
  7304.  
  7305. public function SetUseNativeTargeting( use : bool )
  7306. {
  7307. useNativeTargeting = use;
  7308. }
  7309.  
  7310. protected function FindTarget( optional actionCheck : bool, optional action : EBufferActionType, optional actionInput : bool ) : CActor
  7311. {
  7312. if ( IsCombatMusicEnabled() && !IsInCombat() && reachableEnemyWasTooFar )
  7313. {
  7314. playerMode.UpdateCombatMode();
  7315. }
  7316.  
  7317. PrepareTargetingIn( actionCheck, action, actionInput );
  7318. if ( useNativeTargeting )
  7319. {
  7320. targeting.BeginFindTarget( targetingIn );
  7321. targeting.FindTarget();
  7322. targeting.EndFindTarget( targetingOut );
  7323. }
  7324. else
  7325. {
  7326. UpdateVisibleActors();
  7327. MakeFindTargetPrecalcs();
  7328. ResetTargetingOut();
  7329. FindTarget_Scripted();
  7330. }
  7331. if ( targetingOut.result )
  7332. {
  7333. if ( targetingOut.confirmNewTarget )
  7334. {
  7335. ConfirmNewTarget( targetingOut.target );
  7336. }
  7337. return targetingOut.target;
  7338. }
  7339. return NULL;
  7340. }
  7341.  
  7342. protected function FindTarget_Scripted()
  7343. {
  7344. var currentTarget : CActor;
  7345. var newTarget : CActor;
  7346. var selectedTarget : CActor;
  7347. var displayTargetActor : CActor;
  7348. var playerPosition : Vector;
  7349. var playerHeadingVector : Vector;
  7350. var cameraPosition : Vector;
  7351. var cameraHeadingVector : Vector;
  7352. var selectionHeadingVector : Vector;
  7353. var targetingInfo : STargetingInfo;
  7354. var selectionWeights : STargetSelectionWeights;
  7355. var targets : array< CActor >;
  7356. var isMoveTargetTargetable : bool;
  7357. var targetChangeFromActionInput : bool;
  7358. var retainCurrentTarget : bool;
  7359.  
  7360. // caching data
  7361.  
  7362. playerPosition = this.GetWorldPosition();
  7363. playerHeadingVector = targetingPrecalcs.playerHeadingVector;
  7364. cameraPosition = theCamera.GetCameraPosition();
  7365. cameraHeadingVector = targetingPrecalcs.cameraHeadingVector;
  7366.  
  7367. currentTarget = GetTarget();
  7368. if ( currentTarget )
  7369. {
  7370. if ( IsHardLockEnabled() && currentTarget.IsAlive() && !currentTarget.IsKnockedUnconscious() )
  7371. {
  7372. if ( VecDistanceSquared( playerPosition, currentTarget.GetWorldPosition() ) > 50.f * 50.0f )
  7373. {
  7374. HardLockToTarget( false );
  7375. }
  7376. else
  7377. {
  7378. targetingOut.target = currentTarget;
  7379. targetingOut.result = true;
  7380. return;
  7381. }
  7382. }
  7383. GetVisualDebug().AddSphere('target', 1.0f, currentTarget.GetWorldPosition(), true, Color( 255, 255, 0 ), 1.0f );
  7384. }
  7385.  
  7386. if ( bCanFindTarget && !IsActorLockedToTarget() )
  7387. {
  7388. if ( !targetingIn.playerHasBlockingBuffs )
  7389. {
  7390. InternalFindTargetsInCone( targets, selectionHeadingVector, true );
  7391. }
  7392.  
  7393. targetingInfo.source = this;
  7394. targetingInfo.canBeTargetedCheck = true;
  7395. targetingInfo.coneCheck = false;
  7396. targetingInfo.coneHalfAngleCos = 1.0f;
  7397. targetingInfo.coneDist = targetingIn.coneDist;
  7398. targetingInfo.distCheck = true;
  7399. targetingInfo.invisibleCheck = true;
  7400. targetingInfo.navMeshCheck = false; //true;
  7401.  
  7402. if ( ShouldUsePCModeTargeting() )
  7403. targetingInfo.inFrameCheck = false;
  7404. else
  7405. targetingInfo.inFrameCheck = true;
  7406.  
  7407. targetingInfo.frameScaleX = 1.0f;
  7408. targetingInfo.frameScaleY = 1.0f;
  7409. targetingInfo.knockDownCheck = false;
  7410. targetingInfo.knockDownCheckDist = 1.5f;
  7411. targetingInfo.rsHeadingCheck = false;
  7412. targetingInfo.rsHeadingLimitCos = 1.0f;
  7413.  
  7414. if ( currentTarget )
  7415. {
  7416. targetingInfo.targetEntity = currentTarget;
  7417. if ( !IsEntityTargetable( targetingInfo, true ) )
  7418. {
  7419. currentTarget = NULL;
  7420. }
  7421. if ( currentTarget && !CanBeTargetedIfSwimming( currentTarget, true ) )
  7422. {
  7423. currentTarget = NULL;
  7424. }
  7425. }
  7426.  
  7427. isMoveTargetTargetable = false;
  7428. if ( moveTarget )
  7429. {
  7430. if ( CanBeTargetedIfSwimming( moveTarget, true ) )
  7431. {
  7432. targetingInfo.targetEntity = moveTarget;
  7433. targetingInfo.coneDist = findMoveTargetDist;
  7434. targetingInfo.inFrameCheck = false;
  7435. if ( IsEntityTargetable( targetingInfo, true ) )
  7436. {
  7437. isMoveTargetTargetable = true;
  7438. }
  7439. }
  7440. }
  7441.  
  7442. // checking "standard" cone dist again
  7443. targetingInfo.coneDist = targetingIn.coneDist;
  7444.  
  7445. if ( !targetingIn.playerHasBlockingBuffs )
  7446. {
  7447. RemoveNonTargetable( targets, targetingInfo, selectionHeadingVector );
  7448. }
  7449.  
  7450. newTarget = NULL;
  7451. if ( this.playerAiming.GetCurrentStateName() == 'Aiming' )
  7452. {
  7453. newTarget = this.playerAiming.GetAimedTarget();
  7454. if ( !newTarget )
  7455. {
  7456. selectionWeights.angleWeight = 1.f;
  7457. selectionWeights.distanceWeight = 0.f;
  7458. selectionWeights.distanceRingWeight = 0.f;
  7459.  
  7460. selectedTarget = SelectTarget( targets, false, cameraPosition, cameraHeadingVector, selectionWeights, true );
  7461. newTarget = selectedTarget;
  7462. }
  7463. }
  7464. else if ( IsSwimming() )
  7465. {
  7466. selectionWeights.angleWeight = 0.9f;
  7467. selectionWeights.distanceWeight = 0.1f;
  7468. selectionWeights.distanceRingWeight = 0.f;
  7469.  
  7470. selectedTarget = SelectTarget( targets, true, cameraPosition, cameraHeadingVector, selectionWeights, true );
  7471. newTarget = selectedTarget;
  7472. }
  7473. else if ( IsThreatened() )
  7474. {
  7475. // Change locked enemy when the current one becomes invisible
  7476. if ( IsCameraLockedToTarget() )
  7477. {
  7478. if ( currentTarget && !currentTarget.GetGameplayVisibility() )
  7479. {
  7480. ForceSelectLockTarget();
  7481. }
  7482. }
  7483.  
  7484. displayTargetActor = (CActor)displayTarget;
  7485. selectedTarget = SelectTarget( targets, true, playerPosition, selectionHeadingVector, targetingIn.defaultSelectionWeights, true );
  7486.  
  7487. if ( !selectedTarget )
  7488. {
  7489. targetingOut.forceDisableUpdatePosition = true;
  7490. }
  7491.  
  7492. targetChangeFromActionInput = targetingIn.actionInput && !lAxisReleasedAfterCounter;
  7493. if ( selectedTarget &&
  7494. ( !IsThreat( currentTarget, true ) || ShouldUsePCModeTargeting() || ( !IsInCombatAction() && !lAxisReleasedAfterCounterNoCA ) || targetChangeFromActionInput ) )
  7495. {
  7496. newTarget = selectedTarget;
  7497. }
  7498. else if ( displayTargetActor &&
  7499. ( ( bLAxisReleased && !ShouldUsePCModeTargeting() )|| IsInCombatAction() ) &&
  7500. ( displayTargetActor.IsAlive() || finishableEnemiesList.Contains( displayTargetActor ) ) &&
  7501. displayTargetActor.GetGameplayVisibility() &&
  7502. ( IsEnemyVisible( displayTargetActor ) || finishableEnemiesList.Contains( displayTargetActor ) ) &&
  7503. this.CanBeTargetedIfSwimming( displayTargetActor, true ) &&
  7504. IsThreat( displayTargetActor, true ) &&
  7505. WasVisibleInScaledFrame( displayTargetActor, 1.f, 1.f ) )
  7506. {
  7507. newTarget = displayTargetActor;
  7508. }
  7509. // target closest enemy immediately when transitioning from running/sprint to walk/idle,
  7510. // but when you are already in walk/idle player should hit air after he kills his target, he should only target closest enemy when that enmy is within his field of vision
  7511. else if ( moveTarget &&
  7512. isMoveTargetTargetable &&
  7513. ( !IsInCombatAction() || isInParryOrCounter || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Roll ) )
  7514. {
  7515. newTarget = moveTarget;
  7516. }
  7517. else
  7518. {
  7519. newTarget = NULL;
  7520. }
  7521. }
  7522. else
  7523. {
  7524. retainCurrentTarget = false;
  7525. if ( lAxisReleasedAfterCounterNoCA )
  7526. {
  7527. if ( lastAxisInputIsMovement && !this.IsSwimming())
  7528. {
  7529. selectionWeights.angleWeight = 0.375f;
  7530. selectionWeights.distanceWeight = 0.275f;
  7531. selectionWeights.distanceRingWeight = 0.35f;
  7532. selectedTarget = SelectTarget( targets, false, playerPosition, playerHeadingVector, selectionWeights, true );
  7533.  
  7534. if ( currentTarget != selectedTarget )
  7535. {
  7536. targetingInfo.targetEntity = currentTarget;
  7537. if ( IsEntityTargetable( targetingInfo, true ) && currentTarget.IsAlive() )
  7538. {
  7539. retainCurrentTarget = true;
  7540. }
  7541. }
  7542. }
  7543. else
  7544. {
  7545. selectionWeights.angleWeight = 0.75f;
  7546. selectionWeights.distanceWeight = 0.125f;
  7547. selectionWeights.distanceRingWeight = 0.125f;
  7548. selectedTarget = SelectTarget( targets, false, cameraPosition, cameraHeadingVector, selectionWeights, true );
  7549. }
  7550. }
  7551. else
  7552. {
  7553. selectionWeights.angleWeight = 0.6f;
  7554. selectionWeights.distanceWeight = 0.4f;
  7555. selectionWeights.distanceRingWeight = 0.f;
  7556. selectedTarget = SelectTarget( targets, true, playerPosition, targetingIn.rawPlayerHeadingVector, selectionWeights, true );
  7557. }
  7558.  
  7559. if ( retainCurrentTarget )
  7560. {
  7561. newTarget = currentTarget;
  7562. }
  7563. else if ( IsInCombatAction() && GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.0f )
  7564. {
  7565. newTarget = moveTarget;
  7566. }
  7567. else if ( selectedTarget )
  7568. {
  7569. newTarget = selectedTarget;
  7570. }
  7571. else
  7572. {
  7573. newTarget = NULL;
  7574. }
  7575. }
  7576.  
  7577. targetingOut.confirmNewTarget = true;
  7578. }
  7579. else
  7580. {
  7581. newTarget = NULL;
  7582. }
  7583.  
  7584. targetingOut.result = true;
  7585. targetingOut.target = newTarget;
  7586. }
  7587.  
  7588. function UpdateVisibleActors()
  7589. {
  7590. var i : int;
  7591. var now : float;
  7592.  
  7593. now = theGame.GetEngineTimeAsSeconds();
  7594. for ( i = visibleActors.Size() - 1; i >= 0; i-=1 )
  7595. {
  7596. // wasn't visible for more than 1 second
  7597. if ( ( now - visibleActorsTime[i] ) > 1.0f )
  7598. {
  7599. visibleActors.EraseFast( i );
  7600. visibleActorsTime.EraseFast( i );
  7601. }
  7602. }
  7603. }
  7604.  
  7605. function RemoveNonTargetable( out targets : array< CActor >, out info : STargetingInfo, selectionHeadingVector : Vector )
  7606. {
  7607. var i : int;
  7608. var cameraPosition : Vector;
  7609. var cameraDirection : Vector;
  7610. var nonCombatCheck : bool;
  7611. var playerToCamPlaneDist : float;
  7612. var targetToCamPlaneDist : float;
  7613.  
  7614. if ( targets.Size() == 0 )
  7615. {
  7616. return;
  7617. }
  7618.  
  7619. nonCombatCheck = bLAxisReleased && !IsInCombat();
  7620.  
  7621. // first, let's prepare targeting info (so that we don't need to do it in each loop step)
  7622. if ( nonCombatCheck )
  7623. {
  7624. info.coneHeadingVector = targetingPrecalcs.playerHeadingVector;
  7625. if ( lastAxisInputIsMovement )
  7626. {
  7627. info.coneHeadingVector = selectionHeadingVector;
  7628. info.invisibleCheck = false;
  7629. info.coneCheck = true;
  7630. info.coneHalfAngleCos = 0.76604444311f; // = CosF( Deg2Rad( 80.0f * 0.5f ) )
  7631. }
  7632. else
  7633. {
  7634. info.invisibleCheck = false;
  7635. info.frameScaleX = 0.9f;
  7636. info.frameScaleY = 0.9f;
  7637. }
  7638. }
  7639. else
  7640. {
  7641. info.coneHeadingVector = Vector( 0.0f, 0.0f, 0.0f );
  7642.  
  7643. //MS: ConeCheck is false because it's already been filtered by InternalFindTargetsInCone
  7644. if ( IsInCombat() )
  7645. {
  7646. info.inFrameCheck = false;
  7647. }
  7648. else
  7649. {
  7650. if ( !bLAxisReleased )
  7651. {
  7652. info.coneCheck = true;
  7653.  
  7654. if ( this.IsSwimming() )
  7655. info.coneHalfAngleCos = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) )
  7656. else
  7657. info.coneHalfAngleCos = 0.86602540378f; // = CosF( Deg2Rad( 60.0f * 0.5f ) )
  7658.  
  7659. info.coneHeadingVector = targetingIn.rawPlayerHeadingVector;
  7660. }
  7661. }
  7662. }
  7663.  
  7664. cameraPosition = theCamera.GetCameraPosition();
  7665. cameraDirection = targetingPrecalcs.cameraDirection;
  7666. playerToCamPlaneDist = VecDot2D( cameraDirection, this.GetWorldPosition() - cameraPosition );
  7667.  
  7668. // then, using prepared info let's filter out invalid targets
  7669. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  7670. {
  7671. info.targetEntity = targets[i];
  7672.  
  7673. if ( !CanBeTargetedIfSwimming( targets[i], true ) )
  7674. {
  7675. targets.EraseFast( i );
  7676. }
  7677. else if ( !IsEntityTargetable( info, true ) )
  7678. {
  7679. targets.EraseFast( i );
  7680. }
  7681. else
  7682. {
  7683. if ( nonCombatCheck && !lastAxisInputIsMovement )
  7684. {
  7685. // removing targets between camera and player
  7686. targetToCamPlaneDist = VecDot2D( cameraDirection, targets[i].GetWorldPosition() - cameraPosition );
  7687. if ( targetToCamPlaneDist < playerToCamPlaneDist )
  7688. {
  7689. targets.EraseFast( i );
  7690. }
  7691. }
  7692. }
  7693. }
  7694. }
  7695.  
  7696. var combatModeColor : Color;
  7697. public function CombatModeDebug()
  7698. {
  7699. var visualDebug : CVisualDebug = GetVisualDebug();
  7700.  
  7701. var naviQueryMsg : string;
  7702. var naviQueryMsg1 : string;
  7703. var naviQueryMsg2 : string;
  7704.  
  7705. var navSnapMsg : string;
  7706. var i : int;
  7707.  
  7708. if ( IsCombatMusicEnabled() )
  7709. visualDebug.AddText( 'CombatMusic', "CombatMusic : On", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.7f ), true, , Color( 255, 255, 255 ) );
  7710. else
  7711. visualDebug.AddText( 'CombatMusic', "CombatMusic : Off", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.7f ), true, , Color( 0, 0, 0 ) );
  7712.  
  7713. if ( GetPlayerMode().GetForceCombatMode() )
  7714. visualDebug.AddText( 'ForcedCombatMode', "ForcedCombatMode : TRUE", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.6f ), true, , Color( 255, 255, 255 ) );
  7715. else
  7716. visualDebug.AddText( 'ForcedCombatMode', "ForcedCombatMode : FALSE", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.6f ), true, , Color( 0, 0, 0 ) );
  7717.  
  7718.  
  7719. if ( IsThreatened() )
  7720. {
  7721. if ( IsInCombat() )
  7722. visualDebug.AddText( 'CombatMode', "CombatMode : AlertNear/Far", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 255, 0, 0 ) );
  7723. else
  7724. visualDebug.AddText( 'CombatMode', "CombatMode : CombatExploration", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 255, 255, 0 ) );
  7725. }
  7726. else
  7727. visualDebug.AddText( 'CombatMode', "CombatMode : NormalExploration", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 0, 255, 0 ) );
  7728.  
  7729. visualDebug.AddText( 'NaviQuery', naviQueryMsg, combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7730. visualDebug.AddText( 'NaviQuery1', naviQueryMsg1, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7731. visualDebug.AddText( 'NaviQuery2', naviQueryMsg2, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7732.  
  7733. if ( isInCombatReason == 0 )
  7734. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : ", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 125, 125, 125 ) );
  7735. else if ( isInCombatReason == 1 )
  7736. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : Geralt CAN pathfind to NPC", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) );
  7737. else if ( isInCombatReason == 2 )
  7738. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : An NPC is flying or ranged", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) );
  7739. else if ( isInCombatReason == 2 )
  7740. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : Forced Combat Mode", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) );
  7741.  
  7742. if ( reachableEnemyWasTooFar )
  7743. {
  7744. combatModeColor.Red = 255;
  7745. combatModeColor.Green = 255;
  7746. combatModeColor.Blue = 0;
  7747. }
  7748. else
  7749. {
  7750. combatModeColor.Red = 0;
  7751. combatModeColor.Green = 255;
  7752. combatModeColor.Blue = 0;
  7753. }
  7754.  
  7755. if ( IsThreatened() )
  7756. {
  7757. switch ( navQuery.GetLastOutput( 2.0 ) )
  7758. {
  7759. case EAsyncTastResult_Failure:
  7760. {
  7761. if ( this.playerMode.GetForceCombatMode() )
  7762. {
  7763. if ( isSnappedToNavMesh )
  7764. {
  7765. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7766. visualDebug.AddText( 'NaviQuery1', "Naviquery : Snapped So no need for query", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7767. visualDebug.AddText( 'NaviQuery2', "Naviquery : Snapped So no need for query", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7768. }
  7769. else
  7770. {
  7771. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7772. visualDebug.AddText( 'NaviQuery1', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7773. visualDebug.AddText( 'NaviQuery2', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7774. }
  7775. }
  7776. else
  7777. {
  7778. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7779. visualDebug.AddText( 'NaviQuery1', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7780. visualDebug.AddText( 'NaviQuery2', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7781. }
  7782. break;
  7783. }
  7784. case EAsyncTastResult_Success:
  7785. {
  7786. visualDebug.AddText( 'NaviQuery', combatModeEnt.GetName(), combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7787. visualDebug.AddText( 'NaviQuery1', "Naviquery : Success (navDist: " + navDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7788. visualDebug.AddText( 'NaviQuery2', "Naviquery : Success (directDist: " + directDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7789. break;
  7790. }
  7791. case EAsyncTastResult_Pending:
  7792. {
  7793. visualDebug.AddText( 'NaviQuery', combatModeEnt.GetName(), combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7794. visualDebug.AddText( 'NaviQuery1', "Naviquery : Pending (navDist: " + navDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7795. visualDebug.AddText( 'NaviQuery2', "Naviquery : Pending (directDist: " + directDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7796. break;
  7797. }
  7798. case EAsyncTastResult_Invalidated:
  7799. {
  7800. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7801. visualDebug.AddText( 'NaviQuery1', "Naviquery : Invalidated", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7802. visualDebug.AddText( 'NaviQuery2', "Naviquery : Invalidated", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7803. break;
  7804. }
  7805. }
  7806. }
  7807. else
  7808. {
  7809. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7810. visualDebug.AddText( 'NaviQuery1', "", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7811. visualDebug.AddText( 'NaviQuery2', "", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7812. }
  7813.  
  7814. if ( navMeshSnapInfoStack.Size() > 0 )
  7815. {
  7816. for ( i = navMeshSnapInfoStack.Size()-1; i >= 0; i -= 1 )
  7817. {
  7818. navSnapMsg = navSnapMsg + navMeshSnapInfoStack[i] + " ";
  7819. }
  7820.  
  7821. visualDebug.AddText( 'NavMeshSnap', "NavMeshSnap: Enabled, Sources : " + navSnapMsg, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.1f ), true, , Color( 255, 255, 255 ) );
  7822. }
  7823. else
  7824. visualDebug.AddText( 'NavMeshSnap', "NavMeshSnap: Disabled" , thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.1f ), true, , Color( 0, 0, 0 ) );
  7825.  
  7826. }
  7827.  
  7828. function IsCombatMusicEnabled() : bool
  7829. {
  7830. if ( theSound.GetCurrentGameState() == ESGS_UnderwaterCombat
  7831. || theSound.GetCurrentGameState() == ESGS_Combat
  7832. || theSound.GetCurrentGameState() == ESGS_CombatMonsterHunt
  7833. || theSound.GetCurrentGameState() == ESGS_FocusUnderwaterCombat )
  7834. return true;
  7835. else
  7836. return false;
  7837. }
  7838.  
  7839. function IsSoundStateCombatMusic( gameState : ESoundGameState ) : bool
  7840. {
  7841. if ( gameState == ESGS_UnderwaterCombat
  7842. || gameState == ESGS_Combat
  7843. || gameState == ESGS_CombatMonsterHunt
  7844. || gameState == ESGS_FocusUnderwaterCombat )
  7845. return true;
  7846. else
  7847. return false;
  7848. }
  7849.  
  7850. private function ConfirmNewTarget( actorToConfirm : CActor )
  7851. {
  7852. var leftJoyRotLimit : float = 1.f;
  7853.  
  7854. var target : CActor;
  7855.  
  7856. target = GetTarget();
  7857.  
  7858. //MS: When Player pushes stick in npcs direction, he needs to push the stick beyond leftJoyRotLimit in order to change targets
  7859. if ( !target
  7860. || !moveTarget
  7861. || ( target && ( !IsThreat( target ) || !target.IsAlive() ) )
  7862. || VecLength( rawLeftJoyVec ) < 0.7f
  7863. || ( IsInCombatAction() && ( ( GetBehaviorVariable( 'combatActionType') == (int)CAT_Dodge ) || ( VecLength( rawLeftJoyVec ) >= 0.7f && ( prevRawLeftJoyRot >= ( rawLeftJoyRot + leftJoyRotLimit ) || prevRawLeftJoyRot <= ( rawLeftJoyRot - leftJoyRotLimit ) || AbsF( AngleDistance( cachedRawPlayerHeading, VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() ) ) ) > 60 ) ) ) )
  7864. || ( !IsInCombatAction() && ( !rangedWeapon || ( rangedWeapon.GetCurrentStateName() != 'State_WeaponHolster' ) ) ))//&& rangedWeapon.GetCurrentStateName() != 'State_WeaponShoot' ) && rangedWeapon.GetCurrentStateName() != 'State_WeaponAim' ) )
  7865. {
  7866. SetPrevRawLeftJoyRot();
  7867.  
  7868. if ( actorToConfirm != target )
  7869. {
  7870. SetTarget( actorToConfirm );
  7871. }
  7872. }
  7873. }
  7874.  
  7875. protected function SelectTarget( targets : array< CActor >, useVisibilityCheck : bool, sourcePosition : Vector, headingVector : Vector, selectionWeights : STargetSelectionWeights, optional usePrecalcs : bool ) : CActor
  7876. {
  7877. var i : int;
  7878. var target : CActor;
  7879. var selectedTarget : CActor;
  7880. var currentTarget : CActor;
  7881. var playerPosition : Vector;
  7882. var distanceToPlayer : float;
  7883. var priority : float;
  7884. var maxPriority : float;
  7885. var now : float;
  7886. var remove : bool;
  7887. var visibleActorIndex : int;
  7888.  
  7889. if ( useVisibilityCheck )
  7890. {
  7891. currentTarget = this.GetTarget();
  7892. playerPosition = this.GetWorldPosition();
  7893. now = theGame.GetEngineTimeAsSeconds();
  7894.  
  7895. for ( i = targets.Size() - 1; i >= 0; i-=1 )
  7896. {
  7897. target = targets[ i ];
  7898. if ( target != currentTarget && ( !IsPCModeEnabled() && !WasVisibleInScaledFrame( target, softLockFrameSize, softLockFrameSize ) ) )
  7899. {
  7900. remove = true;
  7901. visibleActorIndex = visibleActors.FindFirst( target );
  7902. if ( visibleActorIndex != -1 )
  7903. {
  7904. if ( usePrecalcs )
  7905. {
  7906. distanceToPlayer = Distance2DBetweenCapsuleAndPoint( target, this ) - targetingPrecalcs.playerRadius;
  7907. }
  7908. else
  7909. {
  7910. distanceToPlayer = Distance2DBetweenCapsules( this, target );
  7911. }
  7912. // if within soft lock distance and soft lock visibility duration -> don't remove yet
  7913. if ( distanceToPlayer < this.softLockDist && ( now - visibleActorsTime[ i ] ) < 1.0f )
  7914. {
  7915. remove = false;
  7916. }
  7917. }
  7918. if ( remove )
  7919. {
  7920. targets.EraseFast( i );
  7921. }
  7922. }
  7923. else
  7924. {
  7925. visibleActorIndex = visibleActors.FindFirst( target );
  7926. if ( visibleActorIndex == -1 )
  7927. {
  7928. visibleActors.PushBack( target );
  7929. visibleActorsTime.PushBack( now );
  7930. }
  7931. else
  7932. {
  7933. visibleActorsTime[ visibleActorIndex ] = now;
  7934. }
  7935. }
  7936. }
  7937. }
  7938.  
  7939. selectedTarget = NULL;
  7940. maxPriority = -1.0f;
  7941. for( i = targets.Size() - 1; i >= 0; i-=1 )
  7942. {
  7943. priority = CalcSelectionPriority( targets[ i ], selectionWeights, sourcePosition, headingVector );
  7944. if ( priority > maxPriority )
  7945. {
  7946. maxPriority = priority;
  7947. selectedTarget = targets[ i ];
  7948. }
  7949. }
  7950.  
  7951. //LogChannel( 'selectedTarget', selectedTarget );
  7952. return selectedTarget;
  7953. }
  7954.  
  7955. function Distance2DBetweenCapsuleAndPoint( actor : CActor, entity : CEntity ) : float
  7956. {
  7957. var distance : float;
  7958. var mpac : CMovingPhysicalAgentComponent;
  7959.  
  7960. distance = VecDistance2D( actor.GetWorldPosition(), entity.GetWorldPosition() );
  7961.  
  7962. mpac = (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent();
  7963. if ( mpac )
  7964. {
  7965. distance -= mpac.GetCapsuleRadius();
  7966. }
  7967.  
  7968. return distance;
  7969. }
  7970.  
  7971.  
  7972. function Distance2DBetweenCapsules( actor1 : CActor, actor2 : CActor ) : float
  7973. {
  7974. var distance : float;
  7975. var mpac : CMovingPhysicalAgentComponent;
  7976.  
  7977. distance = VecDistance2D( actor1.GetWorldPosition(), actor2.GetWorldPosition() );
  7978.  
  7979. mpac = (CMovingPhysicalAgentComponent)actor1.GetMovingAgentComponent();
  7980. if ( mpac )
  7981. {
  7982. distance -= mpac.GetCapsuleRadius();
  7983. }
  7984.  
  7985. mpac = (CMovingPhysicalAgentComponent)actor2.GetMovingAgentComponent();
  7986. if ( mpac )
  7987. {
  7988. distance -= mpac.GetCapsuleRadius();
  7989. }
  7990.  
  7991. return distance;
  7992. }
  7993.  
  7994. protected function ProcessSelectionWeights() : STargetSelectionWeights
  7995. {
  7996. var selectionWeights : STargetSelectionWeights;
  7997.  
  7998. if ( ShouldUsePCModeTargeting() )
  7999. {
  8000. selectionWeights.angleWeight = 0.75f;
  8001. selectionWeights.distanceWeight = 0.25f;
  8002. selectionWeights.distanceRingWeight = 0.f;
  8003. return selectionWeights;
  8004. }
  8005.  
  8006. if ( IsInCombatAction() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Roll ) )
  8007. {
  8008. selectionWeights.angleWeight = 0.575f;
  8009. selectionWeights.distanceWeight = 0.175f;
  8010. selectionWeights.distanceRingWeight = 0.25f;
  8011. }
  8012. if ( !lAxisReleasedAfterCounter || IsInCombatAction() ) // !bLAxisReleased ||
  8013. {
  8014. if ( theInput.GetActionValue( 'ThrowItem' ) == 1.f || ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) )
  8015. {
  8016. selectionWeights.angleWeight = 1.f;
  8017. selectionWeights.distanceWeight = 0.f;
  8018. selectionWeights.distanceRingWeight = 0.f;
  8019. }
  8020. else if ( !lAxisReleasedAfterCounter ) // !bLAxisReleased )
  8021. {
  8022. selectionWeights.angleWeight = 0.55f;//0.75f;
  8023. selectionWeights.distanceWeight = 0.45f;//0.25f;
  8024. selectionWeights.distanceRingWeight = 0.f;//0.3f;
  8025. }
  8026. else
  8027. {
  8028. selectionWeights.angleWeight = 0.75f;
  8029. selectionWeights.distanceWeight = 0.25f;
  8030. selectionWeights.distanceRingWeight = 0.f;//0.3f;
  8031. }
  8032. }
  8033. else if( !IsCurrentSignChanneled() )
  8034. {
  8035. selectionWeights.angleWeight = 0.35f;
  8036. selectionWeights.distanceWeight = 0.65f;
  8037. selectionWeights.distanceRingWeight = 0.f;
  8038. }
  8039. else
  8040. {
  8041. selectionWeights.angleWeight = 0.275f;
  8042. selectionWeights.distanceWeight = 0.375f;
  8043. selectionWeights.distanceRingWeight = 0.35f;
  8044. }
  8045.  
  8046. return selectionWeights;
  8047. }
  8048.  
  8049. protected function CalcSelectionPriority( target : CEntity, selectionWeights : STargetSelectionWeights, sourcePosition : Vector, headingVector : Vector ) : float
  8050. {
  8051. var sourceToTarget : Vector;
  8052. var sourceToTargetDist : float;
  8053. var sourceToTargetAngleDiff : float;
  8054. var selectionPriority : float;
  8055.  
  8056. sourceToTarget = target.GetWorldPosition() - sourcePosition;
  8057. sourceToTargetDist = VecLength2D( sourceToTarget );
  8058. // normalize2D sourcetoTarget
  8059. if ( sourceToTargetDist < 0.0001f )
  8060. {
  8061. sourceToTarget = Vector( 0.0f, 0.0f, 0.0f );
  8062. }
  8063. else
  8064. {
  8065. sourceToTarget *= ( 1.0f / sourceToTargetDist );
  8066. }
  8067. sourceToTargetAngleDiff = AbsF( Rad2Deg( AcosF( VecDot2D( sourceToTarget, headingVector ) ) ) );
  8068.  
  8069. selectionPriority = ( selectionWeights.angleWeight * ( ( 180 - sourceToTargetAngleDiff ) / 180 ) );
  8070. selectionPriority += selectionWeights.distanceWeight * ( ( softLockDist - sourceToTargetDist ) / softLockDist );
  8071.  
  8072. if ( sourceToTargetDist > 0.f && sourceToTargetDist <= 6.f )
  8073. {
  8074. selectionPriority += selectionWeights.distanceRingWeight * 1.0f;
  8075. }
  8076. else if ( sourceToTargetDist > 6.f && sourceToTargetDist <= softLockDist )
  8077. {
  8078. selectionPriority += selectionWeights.distanceRingWeight * 0.4f;
  8079. }
  8080.  
  8081. return selectionPriority;
  8082. }
  8083.  
  8084. protected function SetTarget( targetActor : CActor, optional forceSetTarget : bool )
  8085. {
  8086. var playerToTargetDistance : float;
  8087. var target : CActor;
  8088. var allow : bool;
  8089.  
  8090. target = GetTarget();
  8091.  
  8092. if ( !IsInNonGameplayCutscene() )
  8093. allow = true;
  8094.  
  8095. if ( allow )
  8096. {
  8097. if ( targetActor )
  8098. {
  8099. if ( ( targetActor.IsAlive() && !targetActor.IsKnockedUnconscious() ) || finishableEnemiesList.Contains( targetActor ) )
  8100. allow = true;
  8101. else
  8102. allow = false;
  8103. }
  8104. else
  8105. allow = true;
  8106. }
  8107.  
  8108. if ( forceSetTarget )
  8109. allow = true;
  8110.  
  8111. if ( allow && target != targetActor )
  8112. allow = true;
  8113. else
  8114. allow = false;
  8115.  
  8116. if ( allow )
  8117. {
  8118. SetPlayerTarget( targetActor );
  8119.  
  8120. //playerToTargetDistance = VecDistance( GetWorldPosition(), targetActor.GetNearestPointInBothPersonalSpaces( GetWorldPosition() ) );
  8121. //LogChannel( 'Targeting', "selection " + playerToTargetDistance );
  8122. }
  8123. }
  8124.  
  8125. /*
  8126. protected function SetTarget( targetActor : CActor, optional forceSetTarget : bool )
  8127. {
  8128. var playerToTargetDistance : float;
  8129. var target : CActor;
  8130. //var gec : CGameplayEffectsComponent;
  8131.  
  8132.  
  8133. if ( !IsInNonGameplayCutscene()
  8134. && ( ( ( !targetActor || ( ( targetActor.IsAlive() || finishableEnemiesList.Contains( targetActor ) ) && !targetActor.IsKnockedUnconscious() ) ) && !IsActorLockedToTarget() ) || forceSetTarget ) )
  8135. {
  8136. target = GetTarget();
  8137.  
  8138. if ( target != targetActor )
  8139. {
  8140. if( target )
  8141. {
  8142. target.StopEffect( 'select_character' );
  8143. //gec = GetGameplayEffectsComponent( target );
  8144. //if(gec)
  8145. // gec.SetGameplayEffectFlag( EGEF_OutlineTarget, 0 );
  8146. }
  8147.  
  8148. SetPlayerTarget( targetActor );
  8149. target = targetActor;
  8150.  
  8151. if(target)
  8152. {
  8153. playerToTargetDistance = VecDistance( GetWorldPosition(), target.GetNearestPointInBothPersonalSpaces( GetWorldPosition() ) );
  8154. }
  8155.  
  8156. //LogChannel( 'Targeting', "selection " + playerToTargetDistance );
  8157. }
  8158. }
  8159. }
  8160. */
  8161. public function SetSlideTarget( actor : CGameplayEntity )
  8162. {
  8163. //if ( slideTarget != actor && slideTarget )
  8164. // EnableCloseCombatCharacterRadius( false );
  8165.  
  8166. slideTarget = actor;
  8167.  
  8168. if ( slideTarget )
  8169. SetPlayerCombatTarget((CActor)slideTarget);
  8170. else
  8171. Log( "slideTarget = NULL" );
  8172.  
  8173. if ( slideTarget == nonActorTarget )
  8174. UpdateDisplayTarget( true, true );
  8175. else
  8176. UpdateDisplayTarget();
  8177.  
  8178. ConfirmDisplayTargetTimer(0.f);
  8179. }
  8180.  
  8181. event OnForceSelectLockTarget()
  8182. {
  8183. ForceSelectLockTarget();
  8184. }
  8185.  
  8186. private function ForceSelectLockTarget()
  8187. {
  8188. var newMoveTarget : CActor;
  8189. var target : CActor;
  8190.  
  8191. newMoveTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, 90 );
  8192.  
  8193. if ( !newMoveTarget )
  8194. newMoveTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, -90 );
  8195.  
  8196. if ( newMoveTarget )
  8197. {
  8198. thePlayer.ProcessLockTarget( newMoveTarget );
  8199.  
  8200. target = GetTarget();
  8201. if ( target )
  8202. {
  8203. thePlayer.SetSlideTarget( target );
  8204.  
  8205. if ( IsHardLockEnabled() )
  8206. thePlayer.HardLockToTarget( true );
  8207. }
  8208. }
  8209. else
  8210. {
  8211. thePlayer.HardLockToTarget( false );
  8212. }
  8213. }
  8214.  
  8215. public function SetFinisherVictim( actor : CActor )
  8216. {
  8217. finisherVictim = actor;
  8218. }
  8219.  
  8220. public function GetFinisherVictim() : CActor
  8221. {
  8222. return finisherVictim;
  8223. }
  8224.  
  8225. protected function SetNonActorTarget( actor : CGameplayEntity )
  8226. {
  8227. if ( nonActorTarget != actor )
  8228. nonActorTarget = actor;
  8229. }
  8230.  
  8231. timer function DisableTargetHighlightTimer( time : float , id : int)
  8232. {
  8233. var target : CActor;
  8234. target = GetTarget();
  8235.  
  8236. if( target )
  8237. {
  8238. target.StopEffect( 'select_character' );
  8239. }
  8240. }
  8241.  
  8242. public function WasVisibleInScaledFrame( entity : CEntity, frameSizeX : float, frameSizeY : float ) : bool
  8243. {
  8244. var position : Vector;
  8245. var positionFound : bool;
  8246. var inFront : bool;
  8247. var x, y : float;
  8248. var boneIndex : int;
  8249. var actor : CActor;
  8250. var gameplayEntity : CGameplayEntity;
  8251. var gameplayEntityMatrix : Matrix;
  8252. var drawableComp : CDrawableComponent;
  8253. var box : Box;
  8254. var ok : bool;
  8255.  
  8256. if ( !entity )
  8257. {
  8258. return false;
  8259. }
  8260. if ( frameSizeX <= 0.0f && frameSizeY <= 0.0f )
  8261. {
  8262. LogChannel( 'WasVisibleInScaledFrame', "ERROR: WasVisibleInScaledFrame: frameSizeX && frameSizeY are both negative!!!" );
  8263. return false;
  8264. }
  8265.  
  8266. if ( useNativeTargeting )
  8267. {
  8268. return targeting.WasVisibleInScaledFrame( entity, frameSizeX, frameSizeY );
  8269. }
  8270.  
  8271. position = entity.GetWorldPosition();
  8272.  
  8273. actor = (CActor)entity;
  8274. if ( actor )
  8275. {
  8276. boneIndex = entity.GetBoneIndex( 'pelvis' );
  8277. if ( boneIndex == -1 )
  8278. {
  8279. boneIndex = entity.GetBoneIndex( 'k_pelvis_g' ); // not hack at all. DONE !*100000000000000000000
  8280. }
  8281.  
  8282. if ( boneIndex != -1 )
  8283. {
  8284. position = MatrixGetTranslation( entity.GetBoneWorldMatrixByIndex( boneIndex ) );
  8285. }
  8286. else
  8287. {
  8288. position = entity.GetWorldPosition();
  8289. position.Z += ( (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent() ).GetCapsuleHeight() * 0.5;
  8290. }
  8291. positionFound = true;
  8292. }
  8293. else
  8294. {
  8295. gameplayEntity = (CGameplayEntity)entity;
  8296. if ( gameplayEntity && !( gameplayEntity.aimVector.X == 0 && gameplayEntity.aimVector.Y == 0 && gameplayEntity.aimVector.Z == 0 ) )
  8297. {
  8298. gameplayEntityMatrix = gameplayEntity.GetLocalToWorld();
  8299. position = VecTransform( gameplayEntityMatrix, gameplayEntity.aimVector );
  8300. positionFound = true;
  8301. }
  8302. }
  8303.  
  8304. // if still not found proper position for test
  8305. if ( !positionFound )
  8306. {
  8307. drawableComp = (CDrawableComponent)entity.GetComponentByClassName( 'CDrawableComponent' );
  8308. if ( drawableComp && drawableComp.GetObjectBoundingVolume( box ) )
  8309. {
  8310. position.Z += ( ( box.Max.Z - box.Min.Z ) * 0.66f );
  8311. }
  8312. }
  8313.  
  8314. inFront = theCamera.WorldVectorToViewRatio( position, x, y );
  8315. if ( !inFront )
  8316. {
  8317. return false;
  8318. }
  8319. x = AbsF( x );
  8320. y = AbsF( y );
  8321.  
  8322. ok = true;
  8323. ok = ok && ( frameSizeX <= 0.0f || x < frameSizeX );
  8324. ok = ok && ( frameSizeY <= 0.0f || y < frameSizeY );
  8325.  
  8326. return ok;
  8327. }
  8328.  
  8329. public function HardLockToTarget( flag : bool )
  8330. {
  8331. EnableHardLock( flag );
  8332. LockToTarget( flag );
  8333. }
  8334.  
  8335. public function LockToTarget( flag : bool )
  8336. {
  8337. if ( IsHardLockEnabled() && !flag )
  8338. return;
  8339.  
  8340. LockCameraToTarget( flag );
  8341. LockActorToTarget( flag );
  8342. }
  8343.  
  8344. public function LockCameraToTarget( flag : bool )
  8345. {
  8346. if ( flag && !IsCameraLockedToTarget() )
  8347. {
  8348. thePlayer.EnableManualCameraControl( false, 'LockCameraToTarget' );
  8349. //((CCustomCamera)theCamera.GetTopmostCameraObject()).EnableManualControl( false );
  8350. SetIsCameraLockedToTarget( flag );
  8351. }
  8352. else if ( !flag && IsCameraLockedToTarget() )
  8353. {
  8354. thePlayer.EnableManualCameraControl( true, 'LockCameraToTarget' );
  8355. //((CCustomCamera)theCamera.GetTopmostCameraObject()).EnableManualControl( true );
  8356. SetIsCameraLockedToTarget( flag );
  8357. }
  8358. }
  8359.  
  8360. public function LockActorToTarget( flag : bool, optional withoutIcon : bool )
  8361. {
  8362. var displayTargetActor : CActor;
  8363.  
  8364. if ( flag )
  8365. {
  8366. if ( !IsActorLockedToTarget() )
  8367. {
  8368. //SetSlideTarget( target );
  8369. SetIsActorLockedToTarget( flag );
  8370. SetMoveTargetChangeAllowed( true );
  8371. SetMoveTarget( GetTarget() );
  8372. SetMoveTargetChangeAllowed( false );
  8373. SetTarget( GetTarget() );
  8374. SetSlideTarget( GetTarget() );
  8375. AddTimer( 'CheckLockTargetIsAlive', 0.5, true );
  8376. }
  8377.  
  8378. if ( IsActorLockedToTarget() )
  8379. {
  8380. displayTargetActor = (CActor)( GetDisplayTarget() );
  8381.  
  8382. if ( displayTargetActor && IsThreat( displayTargetActor ) && !withoutIcon )
  8383. EnableHardLockIcon( flag );
  8384. }
  8385. }
  8386. else if ( !flag && IsActorLockedToTarget() )
  8387. {
  8388. SetIsActorLockedToTarget( flag );
  8389. SetMoveTargetChangeAllowed( true );
  8390. RemoveTimer( 'CheckLockTargetIsAlive' );
  8391. EnableHardLockIcon( flag );
  8392. }
  8393. }
  8394.  
  8395. private function EnableHardLockIcon( flag : bool )
  8396. {
  8397. var hud : CR4ScriptedHud;
  8398. var module : CR4HudModuleEnemyFocus;
  8399.  
  8400. if( GetTarget().HasTag( 'NoHardLockIcon' ) )
  8401. return;
  8402.  
  8403. hud = (CR4ScriptedHud)theGame.GetHud();
  8404. module = (CR4HudModuleEnemyFocus)hud.GetHudModule("EnemyFocusModule");
  8405. module.SetShowHardLock( flag );
  8406. }
  8407.  
  8408. private timer function CheckLockTargetIsAlive( time : float , id : int)
  8409. {
  8410. var vitality : float;
  8411. var essence : float;
  8412. var actor : CActor;
  8413. var target : CActor;
  8414.  
  8415. target = (CActor)GetDisplayTarget();
  8416.  
  8417. if( !target
  8418. || !target.IsAlive()
  8419. || ( !target.GetGameplayVisibility() )
  8420. || !CanBeTargetedIfSwimming( target )
  8421. || (!target.UsesVitality() && !target.UsesEssence()))
  8422. {
  8423. if ( !ProcessLockTarget() )
  8424. HardLockToTarget( false );
  8425. }
  8426. }
  8427.  
  8428. //////////////////////////////////////////////////////////////////////////////////////////
  8429. //
  8430. // @Damage
  8431. //
  8432. //////////////////////////////////////////////////////////////////////////////////////////
  8433. protected function PlayHitAnimation(damageAction : W3DamageAction, animType : EHitReactionType)
  8434. {
  8435. var hitRotation : float;
  8436.  
  8437. if( damageAction.HasAnyCriticalEffect() )
  8438. return;
  8439.  
  8440. if( !substateManager.ReactOnBeingHit() && !IsUsingVehicle() )
  8441. {
  8442. return;
  8443. }
  8444.  
  8445. if ( damageAction.GetHitReactionType() == EHRT_Reflect )
  8446. SetBehaviorVariable( 'isAttackReflected', 1.f );
  8447. else
  8448. SetBehaviorVariable( 'isAttackReflected', 0.f );
  8449. SetBehaviorVariable( 'HitReactionType',(int)animType);
  8450. SetBehaviorVariable( 'HitReactionWeapon', ProcessSwordOrFistHitReaction( this, (CActor)damageAction.attacker ) );
  8451.  
  8452. if (damageAction.attacker)
  8453. {
  8454. SetHitReactionDirection(damageAction.attacker);
  8455. SetDetailedHitReaction(damageAction.GetSwingType(), damageAction.GetSwingDirection());
  8456. }
  8457.  
  8458. RaiseForceEvent( 'Hit' );
  8459.  
  8460. if ( IsUsingBoat() )
  8461. {
  8462. SoundEvent("cmb_play_hit_light");
  8463. return;
  8464. }
  8465.  
  8466. if ( IsUsingVehicle() )
  8467. return;
  8468.  
  8469. if(damageAction.attacker)
  8470. {
  8471. hitRotation = VecHeading( damageAction.attacker.GetWorldPosition() - GetWorldPosition() );
  8472. if ( this.GetBehaviorVariable( 'HitReactionDirection' ) == (float)( (int)EHRD_Back ) )
  8473. hitRotation += 180.f;
  8474.  
  8475. //GetVisualDebug().AddArrow( 'temp', GetWorldPosition(), GetWorldPosition() + VecFromHeading( hitRotation )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f );
  8476. SetCustomRotation( 'Hit', hitRotation, 1080.f, 0.1f, false );
  8477. }
  8478.  
  8479. CriticalEffectAnimationInterrupted("PlayHitAnimation");
  8480. }
  8481.  
  8482. public function ReduceDamage( out damageData : W3DamageAction)
  8483. {
  8484. super.ReduceDamage(damageData);
  8485.  
  8486. //halve damage if from your own bomb
  8487. if(damageData.attacker == this && (damageData.GetBuffSourceName() == "petard" || (W3Petard)damageData.causer) )
  8488. {
  8489. if ( theGame.CanLog() )
  8490. {
  8491. LogDMHits("CR4Player.ReduceDamage: hitting self with own bomb - damage reduced by 50%", damageData );
  8492. }
  8493. damageData.processedDmg.vitalityDamage = damageData.processedDmg.vitalityDamage / 2;
  8494. damageData.processedDmg.essenceDamage = damageData.processedDmg.essenceDamage / 2;
  8495. }
  8496. }
  8497.  
  8498. //crit hit chance 0-1
  8499. public function GetCriticalHitChance(isHeavyAttack : bool, target : CActor, victimMonsterCategory : EMonsterCategory) : float
  8500. {
  8501. var critChance : float;
  8502. var oilChanceAttribute : name;
  8503.  
  8504. critChance = 0;
  8505.  
  8506. //cheats
  8507. if(FactsQuerySum('debug_fact_critical_boy') > 0)
  8508. {
  8509. critChance += 1;
  8510. }
  8511.  
  8512. if( IsInState( 'HorseRiding' ) && ((CActor)GetUsedVehicle()).GetMovingAgentComponent().GetRelativeMoveSpeed() >= 4.0 )
  8513. {
  8514. critChance += 1;
  8515. }
  8516.  
  8517. //normal case
  8518. critChance += CalculateAttributeValue(GetAttributeValue(theGame.params.CRITICAL_HIT_CHANCE));
  8519.  
  8520. //active skills bonus
  8521. if(isHeavyAttack && CanUseSkill(S_Sword_s08))
  8522. critChance += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s08, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s08);
  8523. else if (!isHeavyAttack && CanUseSkill(S_Sword_s17))
  8524. critChance += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s17, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s17);
  8525.  
  8526. if(target && target.HasBuff(EET_Confusion))
  8527. {
  8528. critChance += ((W3ConfuseEffect)target.GetBuff(EET_Confusion)).GetCriticalHitChanceBonus();
  8529. }
  8530.  
  8531. //oils
  8532. oilChanceAttribute = MonsterCategoryToCriticalChanceBonus(victimMonsterCategory);
  8533. if(IsNameValid(oilChanceAttribute))
  8534. critChance += CalculateAttributeValue(GetAttributeValue(oilChanceAttribute));
  8535.  
  8536. return critChance;
  8537. }
  8538.  
  8539. //gets damage bonus for critical hit
  8540. public function GetCriticalHitDamageBonus(weaponId : SItemUniqueId, victimMonsterCategory : EMonsterCategory, isStrikeAtBack : bool) : SAbilityAttributeValue
  8541. {
  8542. var bonus, oilBonus : SAbilityAttributeValue;
  8543. var vsAttributeName : name;
  8544.  
  8545. bonus = super.GetCriticalHitDamageBonus(weaponId, victimMonsterCategory, isStrikeAtBack);
  8546.  
  8547. //oil bonus
  8548. if(inv.ItemHasOilApplied(weaponId))
  8549. {
  8550. vsAttributeName = MonsterCategoryToCriticalDamageBonus(victimMonsterCategory);
  8551. oilBonus = inv.GetItemAttributeValue(weaponId, vsAttributeName);
  8552. bonus += oilBonus;
  8553. }
  8554.  
  8555. return bonus;
  8556. }
  8557.  
  8558. /**
  8559. Called when we want to play hit animation
  8560. */
  8561. public function ReactToBeingHit(damageAction : W3DamageAction, optional buffNotApplied : bool) : bool
  8562. {
  8563. var strength : float;
  8564. var animType : EHitReactionType;
  8565. var sup : bool;
  8566. var boat : CBoatComponent;
  8567. var combatActionType : int;
  8568. var attackAction : W3Action_Attack;
  8569. var npc : CNewNPC;
  8570. var shakeCam : bool;
  8571.  
  8572. attackAction = (W3Action_Attack)damageAction;
  8573. //not parried, not countered, not dot, not dodged
  8574. if(!damageAction.IsDoTDamage() && (!attackAction || (!attackAction.IsParried() && !attackAction.IsCountered() && !attackAction.WasDodged()) ) )
  8575. {
  8576. npc = (CNewNPC)attackAction.attacker;
  8577. if(npc && npc.IsHeavyAttack(attackAction.GetAttackName()))
  8578. theGame.VibrateControllerVeryHard();//player got heavy hit
  8579. else
  8580. theGame.VibrateControllerHard();//player got hit
  8581. }
  8582.  
  8583. if ( (CActor)GetUsedVehicle() && this.playerAiming.GetCurrentStateName() == 'Aiming' )
  8584. {
  8585. OnRangedForceHolster( true, true );
  8586. }
  8587.  
  8588. combatActionType = (int)GetBehaviorVariable( 'combatActionType' );
  8589.  
  8590. if ( thePlayer.IsCurrentlyDodging() && ( combatActionType == (int)CAT_Roll || combatActionType == (int)CAT_CiriDodge ) )
  8591. sup = false;
  8592. else if ( this.GetCurrentStateName() == 'DismountHorse' )
  8593. sup = false;
  8594. else
  8595. sup = super.ReactToBeingHit(damageAction, buffNotApplied);
  8596. sup = false;
  8597. //telemetry
  8598. if(damageAction.attacker)
  8599. theTelemetry.LogWithLabelAndValue( TE_FIGHT_HERO_GETS_HIT, damageAction.attacker.ToString(), (int)damageAction.processedDmg.vitalityDamage );
  8600.  
  8601. //camera shake
  8602. if(damageAction.DealsAnyDamage())
  8603. {
  8604. if( ((W3PlayerWitcher)this) && GetWitcherPlayer().IsAnyQuenActive() && damageAction.IsDoTDamage())
  8605. {
  8606. shakeCam = false;
  8607. }
  8608. else
  8609. {
  8610. shakeCam = true;
  8611. }
  8612.  
  8613. if(shakeCam)
  8614. {
  8615. animType = ModifyHitSeverityReaction(this, damageAction.GetHitReactionType());
  8616.  
  8617. if(animType == EHRT_Light || animType == EHRT_LightClose)
  8618. strength = 0.1;
  8619. else if(animType == EHRT_Heavy || animType == EHRT_Igni)
  8620. strength = 0.2;
  8621.  
  8622. GCameraShakeLight(strength, false, GetWorldPosition(), 10.0);
  8623. }
  8624.  
  8625. this.HitReactionEffect( 0.25 );
  8626.  
  8627. //reset uninterrupted hits
  8628. ResetUninterruptedHitsCount();
  8629. }
  8630.  
  8631. //pause health regen
  8632. if(!damageAction.IsDoTDamage() && IsThreatened() && ShouldPauseHealthRegenOnHit() && damageAction.DealsAnyDamage() && !damageAction.WasDodged() && attackAction.CanBeParried() && !attackAction.IsParried())
  8633. {
  8634. PauseHPRegenEffects('being_hit', theGame.params.ON_HIT_HP_REGEN_DELAY);
  8635. }
  8636.  
  8637. //if player is on a boat and not moving then force dismount
  8638. /*if(usedVehicle)
  8639. {
  8640. boat = (CBoatComponent) usedVehicle.GetComponentByClassName('CBoatComponent');
  8641. if(boat && boat.GetLinearVelocityXY() < boat.IDLE_SPEED_THRESHOLD)
  8642. {
  8643. boat.StopAndDismountBoat();
  8644. }
  8645. }*/
  8646.  
  8647. //finesse achievement fail
  8648. if(damageAction.processedDmg.vitalityDamage > 0 && !((W3Effect_Toxicity)damageAction.causer))
  8649. ReceivedCombatDamage();
  8650.  
  8651. //tutorial
  8652. if(FactsQuerySum("tut_fight_use_slomo") > 0)
  8653. {
  8654. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) );
  8655. FactsRemove("tut_fight_slomo_ON");
  8656. }
  8657.  
  8658. // State
  8659. if( !substateManager.ReactOnBeingHit( damageAction ) )
  8660. {
  8661. GoToCombatIfNeeded();
  8662. //PushState( 'CombatFists' );
  8663. }
  8664.  
  8665. return sup;
  8666. }
  8667.  
  8668. protected function ShouldPauseHealthRegenOnHit() : bool
  8669. {
  8670. return true;
  8671. }
  8672.  
  8673. public function PlayHitEffect(damageAction : W3DamageAction)
  8674. {
  8675. super.PlayHitEffect(damageAction);
  8676.  
  8677. //fullscreen hit fx
  8678. if(damageAction.DealsAnyDamage() && !damageAction.IsDoTDamage())
  8679. PlayEffect('hit_screen');
  8680. }
  8681.  
  8682. function HitReactionEffect( interval : float )
  8683. {
  8684. if ( hitReactionEffect )
  8685. {
  8686. PlayEffect( 'radial_blur' );
  8687. hitReactionEffect = false;
  8688. }
  8689. else
  8690. {
  8691. AddTimer( 'HitReactionEffectCooldown', interval, false );
  8692. }
  8693. }
  8694.  
  8695. timer function HitReactionEffectCooldown( td : float , id : int)
  8696. {
  8697. hitReactionEffect = true;
  8698. }
  8699. //////////////////////////////////////////////////////////////////////////////////////////
  8700. //
  8701. // @Parry
  8702. //
  8703. //////////////////////////////////////////////////////////////////////////////////////////
  8704.  
  8705. function PerformParryCheck( parryInfo : SParryInfo) : bool
  8706. {
  8707. var mult : float;
  8708. var parryType : EParryType;
  8709. var parryDir : EPlayerParryDirection;
  8710. var parryHeading : float;
  8711. var fistFightParry : bool;
  8712. var action : W3DamageAction;
  8713. var xmlStaminaDamage : float;
  8714. var xmlStaminaDamageName : name = 'stamina_damage' ;
  8715.  
  8716. // if ( !parryInfo.canBeParried )
  8717. // return false;
  8718.  
  8719. if(CanParryAttack() && /*parryInfo.targetToAttackerAngleAbs < theGame.params.PARRY_HALF_ANGLE &&*/ FistFightCheck( parryInfo.target, parryInfo.attacker, fistFightParry ) )
  8720. {
  8721. parryHeading = GetParryHeading( parryInfo, parryDir ) ;
  8722. //GetVisualDebug().AddArrow( 'CombatActionHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( GetParryHeading( parryInfo, parryDir ) )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f );
  8723. SetBehaviorVariable( 'parryDirection', (float)( (int)( parryDir ) ) );
  8724. SetBehaviorVariable( 'parryDirectionOverlay', (float)( (int)( parryDir ) ) );
  8725. SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) );
  8726.  
  8727. if ( IsInCombatActionFriendly() )
  8728. RaiseEvent('CombatActionFriendlyEnd');
  8729.  
  8730. if ( HasStaminaToParry(parryInfo.attackActionName) )
  8731. {
  8732. this.SetBehaviorVariable( 'combatActionType', (int)CAT_Parry );
  8733.  
  8734. if ( parryInfo.targetToAttackerDist > 3.f && !bLAxisReleased && !thePlayer.IsCiri() )
  8735. {
  8736. if ( !RaiseForceEvent( 'PerformParryOverlay' ) )
  8737. return false;
  8738. else
  8739. ClearCustomOrientationInfoStack();
  8740. }
  8741. else
  8742. {
  8743. if ( RaiseForceEvent( 'PerformParry' ) )
  8744. {
  8745. OnCombatActionStart();
  8746. ClearCustomOrientationInfoStack();
  8747. SetSlideTarget( parryInfo.attacker );
  8748. SetCustomRotation( 'Parry', parryHeading, 1080.f, 0.1f, false );
  8749. }
  8750. else
  8751. return false;
  8752. }
  8753. }
  8754. else
  8755. {
  8756. AddEffectDefault(EET_Stagger, parryInfo.attacker, "Parry");
  8757. return true;
  8758. }
  8759.  
  8760. //parryTarget := this
  8761. if ( parryInfo.attacker.IsWeaponHeld( 'fist' ) && !parryInfo.target.IsWeaponHeld( 'fist' ) )
  8762. {
  8763. parryInfo.attacker.ReactToReflectedAttack(parryInfo.target);
  8764. }
  8765. else
  8766. {
  8767. if ( this.IsInFistFightMiniGame() && fistFightParry )
  8768. {
  8769. if ( IsNameValid(xmlStaminaDamageName) )
  8770. {
  8771. xmlStaminaDamage = CalculateAttributeValue(parryInfo.attacker.GetAttributeValue( xmlStaminaDamageName ));
  8772. DrainStamina(ESAT_FixedValue, xmlStaminaDamage);
  8773. }
  8774. }
  8775. else
  8776. {
  8777. DrainStamina(ESAT_Parry, 0, 0, '', 0, mult);
  8778. }
  8779. if(IsLightAttack(parryInfo.attackActionName))
  8780. parryInfo.target.PlayEffectOnHeldWeapon('light_block');
  8781. else
  8782. parryInfo.target.PlayEffectOnHeldWeapon('heavy_block');
  8783. }
  8784. return true;
  8785. }
  8786.  
  8787. return false;
  8788. }
  8789.  
  8790. protected function GetParryHeading( parryInfo : SParryInfo, out parryDir : EPlayerParryDirection ) : float
  8791. {
  8792. var targetToAttackerHeading : float;
  8793. var currToTargetAttackerAngleDiff : float;
  8794.  
  8795. targetToAttackerHeading = VecHeading( parryInfo.attacker.GetWorldPosition() - parryInfo.target.GetWorldPosition() );
  8796. currToTargetAttackerAngleDiff = AngleDistance( VecHeading( parryInfo.target.GetHeadingVector() ), targetToAttackerHeading );
  8797.  
  8798. if ( !parryInfo.target.IsWeaponHeld( 'fist' ) )
  8799. {
  8800. if( currToTargetAttackerAngleDiff > -45 && currToTargetAttackerAngleDiff < 45 )
  8801. {
  8802. parryDir = PPD_Forward;
  8803. return targetToAttackerHeading;
  8804. }
  8805. else if( currToTargetAttackerAngleDiff >= 45 && currToTargetAttackerAngleDiff < 135 )
  8806. {
  8807. parryDir = PPD_Right;
  8808. //return targetToAttackerHeading;
  8809. return targetToAttackerHeading + 90;
  8810. }
  8811. else if( currToTargetAttackerAngleDiff <= -45 && currToTargetAttackerAngleDiff > -135 )
  8812. {
  8813. parryDir = PPD_Left;
  8814. //return targetToAttackerHeading;
  8815. return targetToAttackerHeading - 90;
  8816. }
  8817. else
  8818. {
  8819. parryDir = PPD_Back;
  8820. //return targetToAttackerHeading;
  8821. return targetToAttackerHeading + 180;
  8822. }
  8823. }
  8824. else
  8825. {
  8826. if( currToTargetAttackerAngleDiff > -45 && currToTargetAttackerAngleDiff < 45 )
  8827. {
  8828. parryDir = PPD_Forward;
  8829. return targetToAttackerHeading;
  8830. }
  8831. else if( currToTargetAttackerAngleDiff >= 45 && currToTargetAttackerAngleDiff < 180 )
  8832. {
  8833. parryDir = PPD_Right;
  8834. return targetToAttackerHeading + 90;
  8835. }
  8836. else if( currToTargetAttackerAngleDiff <= -45 && currToTargetAttackerAngleDiff >= -180 )
  8837. {
  8838. parryDir = PPD_Left;
  8839. return targetToAttackerHeading - 90;
  8840. }
  8841. else
  8842. {
  8843. parryDir = PPD_Back;
  8844. return targetToAttackerHeading + 180;
  8845. }
  8846. }
  8847. }
  8848.  
  8849. function ProcessLockTarget( optional newLockTarget : CActor, optional checkLeftStickHeading : bool ) : bool
  8850. {
  8851. var attackerNearestPoint : Vector;
  8852. var playerNearestPoint : Vector;
  8853. var incomingAttacker : CActor;
  8854. var tempLockTarget : CActor;
  8855. var target : CActor;
  8856. var useIncomingAttacker : bool;
  8857.  
  8858. if ( newLockTarget )
  8859. tempLockTarget = newLockTarget;
  8860. else
  8861. {
  8862. incomingAttacker = GetClosestIncomingAttacker();
  8863. if ( incomingAttacker && incomingAttacker.IsAlive() && IsUsingVehicle() )
  8864. {
  8865. tempLockTarget = incomingAttacker;
  8866. useIncomingAttacker = false;
  8867. }
  8868.  
  8869. if ( !useIncomingAttacker )
  8870. {
  8871. target = GetTarget();
  8872. if ( target && target.IsAlive() && target.GetGameplayVisibility() && IsEnemyVisible( target ) && IsThreat( target ) && CanBeTargetedIfSwimming( target ) )
  8873. tempLockTarget = FindTarget();
  8874. else
  8875. {
  8876. tempLockTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, 0.f );
  8877. }
  8878. }
  8879. }
  8880.  
  8881. if ( tempLockTarget )
  8882. {
  8883. if ( IsCombatMusicEnabled() || hostileEnemies.Size() > 0 )
  8884. {
  8885. if ( !IsThreat( tempLockTarget ) )
  8886. tempLockTarget = NULL;
  8887. }
  8888. }
  8889.  
  8890. SetTarget( tempLockTarget, true );
  8891. SetMoveTargetChangeAllowed( true );
  8892. SetMoveTarget( tempLockTarget );
  8893. SetMoveTargetChangeAllowed( false );
  8894. SetSlideTarget( tempLockTarget );
  8895.  
  8896. if ( tempLockTarget )
  8897. {
  8898. if ( this.IsActorLockedToTarget() )
  8899. EnableHardLockIcon( true );
  8900.  
  8901. return true;
  8902. }
  8903. else
  8904. return false;
  8905. }
  8906.  
  8907. //////////////////////////////////////////////////////////////////////////////////////////
  8908. //////////////////////// @COMBAT ///////////////////////////////////////////////////////
  8909. //////////////////////////////////////////////////////////////////////////////////////////
  8910.  
  8911. //checks if player is doing special attack light/heavy
  8912. public function IsDoingSpecialAttack(heavy : bool) : bool
  8913. {
  8914. var pat : EPlayerAttackType;
  8915.  
  8916. if(IsInCombatAction() && ( (int)GetBehaviorVariable('combatActionType')) == CAT_SpecialAttack)
  8917. {
  8918. pat = (int)GetBehaviorVariable('playerAttackType');
  8919.  
  8920. if(heavy && pat == PAT_Heavy)
  8921. {
  8922. return true;
  8923. }
  8924. else if(!heavy && pat == PAT_Light)
  8925. {
  8926. return true;
  8927. }
  8928. }
  8929.  
  8930. return false;
  8931. }
  8932.  
  8933. public function SetIsCurrentlyDodging(enable : bool, optional isRolling : bool)
  8934. {
  8935. super.SetIsCurrentlyDodging(enable, isRolling);
  8936.  
  8937. if ( isRolling )
  8938. {
  8939. SetCanPlayHitAnim( false );
  8940. this.AddBuffImmunity( EET_KnockdownTypeApplicator, 'Roll', false );
  8941. this.AddBuffImmunity( EET_Knockdown, 'Roll', false );
  8942. this.AddBuffImmunity( EET_HeavyKnockdown, 'Roll', false );
  8943. this.AddBuffImmunity( EET_Stagger, 'Roll', false );
  8944. }
  8945. else
  8946. {
  8947. SetCanPlayHitAnim( true );
  8948. this.RemoveBuffImmunity( EET_KnockdownTypeApplicator, 'Roll' );
  8949. this.RemoveBuffImmunity( EET_Knockdown, 'Roll' );
  8950. this.RemoveBuffImmunity( EET_HeavyKnockdown, 'Roll' );
  8951. this.RemoveBuffImmunity( EET_Stagger, 'Roll' );
  8952. }
  8953. }
  8954.  
  8955. public function EnableHardLock( flag : bool )
  8956. {
  8957. super.EnableHardLock(flag);
  8958.  
  8959. if(flag && ShouldProcessTutorial('TutorialTargettingWaiting'))
  8960. {
  8961. FactsAdd("tut_hardlocked");
  8962. }
  8963. }
  8964.  
  8965. protected function TestParryAndCounter(data : CPreAttackEventData, weaponId : SItemUniqueId, out parried : bool, out countered : bool) : array<CActor>
  8966. {
  8967. var ret : array<CActor>;
  8968.  
  8969. //cheat for QA tests - NPCs won't parry/counter
  8970. if(FactsQuerySum('player_is_the_boss') > 0)
  8971. {
  8972. //---------------- DEBUG
  8973. //draw debug AR
  8974. SetDebugAttackRange(data.rangeName);
  8975. RemoveTimer('PostAttackDebugRangeClear'); //disable AR clearing since we've just set a new one
  8976.  
  8977. return ret;
  8978. }
  8979.  
  8980. ret = super.TestParryAndCounter(data, weaponId, parried, countered);
  8981.  
  8982. //achievement
  8983. if(parried)
  8984. theGame.GetGamerProfile().ResetStat(ES_CounterattackChain);
  8985.  
  8986. return ret;
  8987. }
  8988.  
  8989. public function SetSpecialAttackTimeRatio(f : float)
  8990. {
  8991. LogSpecialHeavy(f);
  8992. specialAttackTimeRatio = f;
  8993. }
  8994.  
  8995. public function GetSpecialAttackTimeRatio() : float
  8996. {
  8997. return specialAttackTimeRatio;
  8998. }
  8999.  
  9000. //called when we processed special heavy attack action - either from hit or from CombatActionEnd()
  9001. public function OnSpecialAttackHeavyActionProcess()
  9002. {
  9003. //clear ration after attack performed
  9004. SetSpecialAttackTimeRatio(0.f);
  9005. }
  9006.  
  9007. protected function DoAttack(animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array<CActor>, attackAnimationName : name, hitTime : float)
  9008. {
  9009. var shakeStr : float;
  9010. var weapon : EPlayerWeapon;
  9011. var targetActor : CActor;
  9012.  
  9013. //cam shake for player's heavy attacks
  9014. if ( animData.attackName == 'attack_heavy_special' )
  9015. {
  9016. if( specialAttackTimeRatio != 1 )
  9017. shakeStr = (specialAttackTimeRatio / 3.333) + 0.2;
  9018. else
  9019. shakeStr = 0.5;
  9020.  
  9021. GCameraShake( shakeStr, false, GetWorldPosition(), 10);
  9022. }
  9023. else if ( IsHeavyAttack(attackActionName) )
  9024. {
  9025. if(parriedBy.Size() > 0)
  9026. shakeStr = 0.2;
  9027. else
  9028. shakeStr = 0.1;
  9029.  
  9030. GCameraShake(shakeStr, false, GetWorldPosition(), 10);
  9031. }
  9032.  
  9033. targetActor = (CActor)slideTarget;
  9034. if ( targetActor && hitTargets.Contains(targetActor) )
  9035. {
  9036. weapon = this.GetMostConvenientMeleeWeapon(targetActor,true);
  9037. if ( this.GetCurrentMeleeWeaponType() != PW_Fists && weapon != this.GetCurrentMeleeWeaponType() )
  9038. {
  9039. if ( weapon == PW_Steel )
  9040. {
  9041. thePlayer.OnEquipMeleeWeapon(PW_Steel,true);
  9042. }
  9043. else if ( weapon == PW_Silver )
  9044. {
  9045. thePlayer.OnEquipMeleeWeapon(PW_Silver,true);
  9046. }
  9047.  
  9048. }
  9049. }
  9050.  
  9051. super.DoAttack(animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime);
  9052. }
  9053.  
  9054. //var delayCombatStanceTimeStamp : float;
  9055.  
  9056. private var confirmCombatStanceTimeStamp : float;
  9057. private var isConfirmingCombatStance : bool;
  9058. final function SetPlayerCombatStance(stance : EPlayerCombatStance, optional force : bool )
  9059. {
  9060. var stanceInt : int;
  9061.  
  9062. if ( !CanChangeCombatStance( stance, force ) )
  9063. return;
  9064.  
  9065. combatStance = stance;
  9066. stanceInt = (int)stance;
  9067.  
  9068. SetBehaviorVariable( 'playerCombatStance' , (float)stanceInt);
  9069. SetBehaviorVariable( 'playerCombatStanceForOverlay' , (float)stanceInt);
  9070. if ( force )
  9071. SetBehaviorVariable( 'forceCombatStance' , 1.f);
  9072. else
  9073. SetBehaviorVariable( 'forceCombatStance' , 0.f);
  9074. }
  9075.  
  9076. private function CanChangeCombatStance( stance : EPlayerCombatStance, optional force : bool ) : bool
  9077. {
  9078. var currTime : float;
  9079.  
  9080. if ( force )
  9081. return true;
  9082.  
  9083. if ( IsInFistFightMiniGame() )
  9084. return true;
  9085.  
  9086. if ( isInHolsterAnim )
  9087. return false;
  9088.  
  9089. if ( ( combatStance == PCS_Normal || combatStance == PCS_AlertFar )
  9090. && stance == PCS_AlertNear )
  9091. {
  9092. currTime = theGame.GetEngineTimeAsSeconds();
  9093. if ( !isConfirmingCombatStance )
  9094. {
  9095. isConfirmingCombatStance = true;
  9096. confirmCombatStanceTimeStamp = currTime;
  9097.  
  9098. if ( this.playerMoveType == PMT_Idle )
  9099. this.SetBehaviorVariable('isInCombatForOverlay',0.f);
  9100. else
  9101. this.SetBehaviorVariable('isInCombatForOverlay',1.f);
  9102.  
  9103. return false;
  9104. }
  9105. else if ( currTime < confirmCombatStanceTimeStamp + 1.f )
  9106. {
  9107. if ( stance == PCS_AlertNear )
  9108. return false;
  9109. }
  9110. else
  9111. isConfirmingCombatStance = false;
  9112. }
  9113. else
  9114. isConfirmingCombatStance = false;
  9115.  
  9116. return true;
  9117. }
  9118.  
  9119. private var isInHolsterAnim : bool;
  9120. event OnHolsterWeaponStart()
  9121. {
  9122. isInHolsterAnim = true;
  9123. }
  9124.  
  9125. event OnHolsterWeaponEnd()
  9126. {
  9127. isInHolsterAnim = false;
  9128. }
  9129.  
  9130. final function GetPlayerCombatStance() : EPlayerCombatStance
  9131. {
  9132. return combatStance;
  9133. }
  9134.  
  9135. timer function DelayedDisableFindTarget( time : float , id : int)
  9136. {
  9137. if ( GetTarget().IsAlive() )
  9138. {
  9139. EnableFindTarget( false );
  9140. }
  9141. else
  9142. {
  9143. EnableFindTarget( true );
  9144. }
  9145. }
  9146.  
  9147. ///////////////////////////////////////////////////////////////////////////
  9148. // @BUFFER @COMBATACTIONBUFFER
  9149. ///////////////////////////////////////////////////////////////////////////
  9150.  
  9151. private var dodgeTimerRunning : bool;
  9152.  
  9153. function StartDodgeTimer()
  9154. {
  9155. dodgeTimerRunning = true;
  9156. thePlayer.AddTimer('DodgeTimer',0.2,false);
  9157. }
  9158.  
  9159. function StopDodgeTimer()
  9160. {
  9161. this.RemoveTimer('DodgeTimer');
  9162. dodgeTimerRunning = false;
  9163. }
  9164.  
  9165. function IsDodgeTimerRunning() : bool
  9166. {
  9167. return dodgeTimerRunning;
  9168. }
  9169.  
  9170. timer function DodgeTimer( dt : float, id : int )
  9171. {
  9172. dodgeTimerRunning = false;
  9173. }
  9174.  
  9175. public function EvadePressed( bufferAction : EBufferActionType )
  9176. {
  9177. }
  9178.  
  9179. public function PerformingCombatAction() : EBufferActionType
  9180. {
  9181. return BufferCombatAction;
  9182. }
  9183.  
  9184. public function PushCombatActionOnBuffer( action : EBufferActionType, stage : EButtonStage, optional allSteps : bool )
  9185. {
  9186. BufferButtonStage = stage;
  9187. BufferCombatAction = action;
  9188. BufferAllSteps = allSteps;
  9189. }
  9190.  
  9191. protected function ProcessCombatActionHeading( action : EBufferActionType ) : float
  9192. {
  9193. var processedActionHeading : float;
  9194.  
  9195. HandleMovement( 0.f );
  9196.  
  9197. if ( ShouldUsePCModeTargeting() )
  9198. return theGame.GetGameCamera().GetHeading();
  9199.  
  9200. if ( lAxisReleasedAfterCounter ) // && IsInCombatAction() )
  9201. ResetCachedRawPlayerHeading();
  9202.  
  9203. processedActionHeading = cachedRawPlayerHeading;
  9204.  
  9205. return processedActionHeading;
  9206. }
  9207. /*
  9208. private function ProcessCombatActionHeading( action : EBufferActionType ) : float
  9209. {
  9210. var processedActionHeading : float;
  9211. var unusedActor : CActor; //MS: placeholder variable to fix memory error
  9212.  
  9213. if ( IsUsingVehicle() )
  9214. {
  9215. processedActionHeading = theGame.GetGameCamera().GetHeading();
  9216. return processedActionHeading;
  9217. }
  9218.  
  9219. if ( !bLAxisReleased || lAxisPushedTimeStamp + 0.5f > theGame.GetEngineTimeAsSeconds() )
  9220. processedActionHeading = cachedRawPlayerHeading;
  9221. else
  9222. {
  9223. if ( GetDisplayTarget() )
  9224. {
  9225. if ( cachedCombatActionHeading == cachedRawPlayerHeading )
  9226. ResetCachedRawPlayerHeading();
  9227. else
  9228. {
  9229. cachedRawPlayerHeading = cachedCombatActionHeading;
  9230. canResetCachedCombatActionHeading = true;
  9231. }
  9232.  
  9233. processedActionHeading = cachedRawPlayerHeading;
  9234. }
  9235. else
  9236. {
  9237. if ( lAxisReleasedAfterCounterNoCA )
  9238. ResetRawPlayerHeading();
  9239.  
  9240. cachedRawPlayerHeading = rawPlayerHeading;
  9241.  
  9242. if ( lAxisReleasedAfterCounterNoCA )
  9243. processedActionHeading = GetHeading();
  9244. else
  9245. processedActionHeading = cachedRawPlayerHeading;
  9246. }
  9247. }
  9248.  
  9249. if ( this.IsCameraLockedToTarget() && this.IsActorLockedToTarget() && action != EBAT_Dodge && action != EBAT_Roll )
  9250. processedActionHeading = theGame.GetGameCamera().GetHeading();
  9251.  
  9252. if ( lAxisReleasedAfterCounterNoCA )
  9253. {
  9254. if ( action == EBAT_Dodge || action == EBAT_Roll )
  9255. {
  9256. if ( ( !IsEnemyInCone( this, GetHeadingVector(), softLockDist, 60.f, unusedActor ) || !IsEnemyInCone( this, GetHeadingVector() + 180, softLockDist, 60.f, unusedActor ) ) && moveTarget )
  9257. processedActionHeading = VecHeading( moveTarget.GetWorldPosition() - GetWorldPosition() ) + 180;
  9258. else
  9259. processedActionHeading = GetHeading() + 180;
  9260. }
  9261. }
  9262.  
  9263. //GetVisualDebug().AddArrow( 'cachedRawPlayerHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( cachedRawPlayerHeading ), 1.f, 0.2f, 0.2f, true, Color(0,255,128), true, 5.f );
  9264. //GetVisualDebug().AddArrow( 'CombatActionHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( GetCombatActionHeading() )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f );
  9265.  
  9266. return processedActionHeading;
  9267. }*/
  9268.  
  9269. function ResetRawPlayerHeading()
  9270. {
  9271. if ( GetDisplayTarget() )
  9272. rawPlayerHeading = VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() );
  9273. else
  9274. rawPlayerHeading = GetHeading();
  9275.  
  9276. //LogChannel('ResetRawPlayerHeading',"ResetRawPlayerHeading" );
  9277. }
  9278.  
  9279. function ResetCachedRawPlayerHeading()
  9280. {
  9281. cachedRawPlayerHeading = rawPlayerHeading;
  9282. if ( GetDisplayTarget() && IsDisplayTargetTargetable() && AbsF( AngleDistance( VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() ), this.GetHeading() ) ) < 90.f )
  9283. cachedRawPlayerHeading = VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() );
  9284. else
  9285. cachedRawPlayerHeading = this.GetHeading();
  9286.  
  9287. if ( canResetCachedCombatActionHeading )
  9288. cachedCombatActionHeading = cachedRawPlayerHeading;
  9289. }
  9290.  
  9291. public function GetCombatActionTarget( action : EBufferActionType ) : CGameplayEntity
  9292. {
  9293. var selectedTargetableEntity : CGameplayEntity;
  9294.  
  9295. if ( !this.IsUsingVehicle() )
  9296. selectedTargetableEntity = FindNonActorTarget( true, action );
  9297.  
  9298. if ( selectedTargetableEntity )
  9299. {
  9300. return selectedTargetableEntity;
  9301. }
  9302. else
  9303. {
  9304. /*if ( !IsCombatMusicEnabled() && displayTarget )
  9305. {
  9306. if ( !( (CActor)displayTarget ) )
  9307. return NULL;
  9308. else
  9309. return displayTarget;
  9310. }*/
  9311.  
  9312. if ( !this.IsUsingVehicle() )
  9313. FindTarget( true, action, true );
  9314. else
  9315. ((CR4PlayerStateUseGenericVehicle)this.GetState( 'UseGenericVehicle' )).FindTarget();
  9316.  
  9317. return GetTarget();
  9318. }
  9319. }
  9320.  
  9321. //MS: FindNonActorTarget may or may not have an interaction component, which is why it is separate from ProcessInteraction
  9322. private function FindNonActorTarget( actionCheck : bool, optional action : EBufferActionType ) : CGameplayEntity
  9323. {
  9324. var targetableEntities : array<CGameplayEntity>;
  9325. var selectedTargetableEntity : CGameplayEntity;
  9326. var selectionPriority : array< float >;
  9327. var selectionWeights : STargetSelectionWeights;
  9328. var findEntityDist : float;
  9329. var i, size : int;
  9330. var playerHeading : float;
  9331. var playerInventory : CInventoryComponent;
  9332. var castSignType : ESignType;
  9333. var targetingInfo : STargetingInfo;
  9334. var playerPosition : Vector;
  9335. var cameraPosition : Vector;
  9336. var playerHeadingVector : Vector;
  9337. var rawPlayerHeadingVector : Vector;
  9338.  
  9339. playerPosition = this.GetWorldPosition();
  9340. cameraPosition = theCamera.GetCameraPosition();
  9341. rawPlayerHeadingVector = VecFromHeading( rawPlayerHeading );
  9342.  
  9343. if ( bCanFindTarget && !IsHardLockEnabled() )
  9344. {
  9345. if ( actionCheck && IsInCombat() && action == EBAT_CastSign )
  9346. {
  9347. findEntityDist = 6.f;
  9348. selectionWeights.angleWeight = 0.375f;
  9349. selectionWeights.distanceWeight = 0.275f;
  9350. selectionWeights.distanceRingWeight = 0.35f;
  9351. }
  9352. else if ( !IsInCombat() && lastAxisInputIsMovement )
  9353. {
  9354. findEntityDist = softLockDist;
  9355. selectionWeights.angleWeight = 0.375f;
  9356. selectionWeights.distanceWeight = 0.275f;
  9357. selectionWeights.distanceRingWeight = 0.35f;
  9358. }
  9359. else
  9360. {
  9361. findEntityDist = softLockDist;
  9362. selectionWeights.angleWeight = 0.75f;
  9363. selectionWeights.distanceWeight = 0.125f;
  9364. selectionWeights.distanceRingWeight = 0.125f;
  9365. }
  9366.  
  9367. //MSTODO : Ask programmers for filter for interactive entities
  9368. if ( !IsInCombat() || !bLAxisReleased )
  9369. {
  9370. FindGameplayEntitiesInRange( targetableEntities, this, findEntityDist, 10, theGame.params.TAG_SOFT_LOCK );
  9371. }
  9372.  
  9373. if ( targetableEntities.Size() > 0 )
  9374. {
  9375. playerInventory = this.GetInventory();
  9376. castSignType = this.GetEquippedSign();
  9377.  
  9378. if ( !bLAxisReleased )
  9379. {
  9380. targetingInfo.source = this;
  9381. targetingInfo.canBeTargetedCheck = false;
  9382. targetingInfo.coneCheck = true;
  9383. targetingInfo.coneHalfAngleCos = 0.5f; // = CosF( Deg2Rad( 120.0f * 0.5f ) )
  9384. targetingInfo.coneDist = softLockDist;
  9385. targetingInfo.coneHeadingVector = rawPlayerHeadingVector;
  9386. targetingInfo.distCheck = true;
  9387. targetingInfo.invisibleCheck = false;
  9388. targetingInfo.navMeshCheck = false;
  9389. targetingInfo.frameScaleX = 1.0f;
  9390. targetingInfo.frameScaleY = 1.0f;
  9391. targetingInfo.knockDownCheck = false;
  9392. targetingInfo.knockDownCheckDist = 0.0f;
  9393. targetingInfo.rsHeadingCheck = false;
  9394. targetingInfo.rsHeadingLimitCos = 1.0f;
  9395. }
  9396.  
  9397. for( i = targetableEntities.Size()-1; i>=0; i-=1 )
  9398. {
  9399. if ( bLAxisReleased )
  9400. {
  9401. if ( !lastAxisInputIsMovement )
  9402. {
  9403. if ( !WasVisibleInScaledFrame( targetableEntities[i], 0.9f, 0.9f ) )
  9404. {
  9405. targetableEntities.Erase(i);
  9406. continue;
  9407. }
  9408. }
  9409. else if ( !WasVisibleInScaledFrame( targetableEntities[i], 1.f, 1.f ) )
  9410. {
  9411. targetableEntities.Erase(i);
  9412. continue;
  9413. }
  9414. }
  9415. else
  9416. {
  9417. targetingInfo.targetEntity = targetableEntities[i];
  9418. if ( actionCheck && moveTarget )
  9419. {
  9420. targetingInfo.inFrameCheck = false;
  9421. if ( !IsEntityTargetable( targetingInfo ) )
  9422. {
  9423. targetableEntities.Erase(i);
  9424. continue;
  9425. }
  9426. }
  9427. else
  9428. {
  9429. targetingInfo.inFrameCheck = true;
  9430. if ( !IsEntityTargetable( targetingInfo ) )
  9431. {
  9432. targetableEntities.Erase(i);
  9433. continue;
  9434. }
  9435. }
  9436. }
  9437.  
  9438. if ( actionCheck )
  9439. {
  9440. if ( action == EBAT_ItemUse )
  9441. {
  9442. if ( ( playerInventory.IsItemBomb( this.GetSelectedItemId() ) && !targetableEntities[i].HasTag( 'softLock_Bomb' ) )
  9443. || ( playerInventory.IsItemCrossbow( this.GetSelectedItemId() ) && !targetableEntities[i].HasTag( 'softLock_Bolt' ) ) )
  9444. {
  9445. targetableEntities.Erase(i);
  9446. continue;
  9447. }
  9448. }
  9449. else if ( action == EBAT_CastSign )
  9450. {
  9451. if ( ( castSignType == ST_Aard && !targetableEntities[i].HasTag( 'softLock_Aard' ) )
  9452. || ( castSignType == ST_Igni && !targetableEntities[i].HasTag( 'softLock_Igni' ) )
  9453. || ( castSignType == ST_Axii && !targetableEntities[i].HasTag( 'softLock_Axii' ) )
  9454. || castSignType == ST_Yrden
  9455. || castSignType == ST_Quen )
  9456. {
  9457. targetableEntities.Erase(i);
  9458. continue;
  9459. }
  9460. }
  9461. else if ( action == EBAT_LightAttack || action == EBAT_HeavyAttack || action == EBAT_SpecialAttack_Heavy )
  9462. {
  9463. if ( ( IsWeaponHeld( 'fist' ) && !targetableEntities[i].HasTag( 'softLock_Fist' ) ) || ( !IsWeaponHeld( 'fist' ) && !targetableEntities[i].HasTag( 'softLock_Weapon' ) ) )
  9464. {
  9465. targetableEntities.Erase(i);
  9466. continue;
  9467. }
  9468. }
  9469. else
  9470. {
  9471. targetableEntities.Erase(i);
  9472. continue;
  9473. }
  9474. }
  9475. }
  9476. }
  9477.  
  9478. if ( targetableEntities.Size() > 0)
  9479. {
  9480. playerHeading = this.GetHeading();
  9481. playerHeadingVector = this.GetHeadingVector();
  9482. if ( IsInCombat() )
  9483. {
  9484. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9485. {
  9486. if ( bLAxisReleased )
  9487. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, cameraPosition, rawPlayerHeadingVector ) );
  9488. else
  9489. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, rawPlayerHeadingVector ) );
  9490. }
  9491.  
  9492. if ( selectionPriority.Size() > 0 )
  9493. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9494. }
  9495. else
  9496. {
  9497. if ( bLAxisReleased )
  9498. {
  9499. if ( !lastAxisInputIsMovement )
  9500. {
  9501. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9502. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, cameraPosition, rawPlayerHeadingVector ) );
  9503.  
  9504. if ( selectionPriority.Size() > 0 )
  9505. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9506. }
  9507. else
  9508. {
  9509. if ( IsInCombatAction() )
  9510. selectedTargetableEntity = nonActorTarget;
  9511. else
  9512. {
  9513. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9514. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, playerHeadingVector ) );
  9515.  
  9516. if ( selectionPriority.Size() > 0 )
  9517. {
  9518. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9519.  
  9520. targetingInfo.source = this;
  9521. targetingInfo.targetEntity = selectedTargetableEntity;
  9522. targetingInfo.canBeTargetedCheck = false;
  9523. targetingInfo.coneCheck = true;
  9524. targetingInfo.coneHalfAngleCos = 0.0f; // = CosF( Deg2Rad( 180.0f * 0.5f ) )
  9525. targetingInfo.coneDist = softLockDist;
  9526. targetingInfo.coneHeadingVector = this.GetHeadingVector();
  9527. targetingInfo.distCheck = true;
  9528. targetingInfo.invisibleCheck = false;
  9529. targetingInfo.navMeshCheck = false;
  9530. targetingInfo.inFrameCheck = false;
  9531. targetingInfo.frameScaleX = 1.0f;
  9532. targetingInfo.frameScaleY = 1.0f;
  9533. targetingInfo.knockDownCheck = false;
  9534. targetingInfo.knockDownCheckDist = 0.0f;
  9535. targetingInfo.rsHeadingCheck = false;
  9536. targetingInfo.rsHeadingLimitCos = 1.0f;
  9537.  
  9538. if ( !IsEntityTargetable( targetingInfo ) )
  9539. selectedTargetableEntity = NULL;
  9540. }
  9541. }
  9542. }
  9543. }
  9544. else
  9545. {
  9546. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9547. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, rawPlayerHeadingVector ) );
  9548.  
  9549. if ( selectionPriority.Size() > 0 )
  9550. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9551. }
  9552. }
  9553. }
  9554. else
  9555. selectedTargetableEntity = NULL;
  9556. }
  9557.  
  9558. SetNonActorTarget( selectedTargetableEntity );
  9559. return selectedTargetableEntity;
  9560. }
  9561. /*
  9562. timer function IsItemUseInputHeld ( time : float , id : int)
  9563. {
  9564. if ( GetBIsInputAllowed()
  9565. && GetBIsCombatActionAllowed()
  9566. && IsActionAllowed( EIAB_Crossbow )
  9567. && inv.IsIdValid( GetSelectedItemId() )
  9568. && inv.IsItemCrossbow( GetSelectedItemId()En )
  9569. && rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' )
  9570. {
  9571. SetIsAimingCrossbow( true );
  9572. PushCombatActionOnBuffer( EBAT_ItemUse, BS_Pressed );
  9573. ProcessCombatActionBuffer();
  9574. }
  9575.  
  9576. if ( theInput.GetActionValue( 'ThrowItem' ) == 0.f )
  9577. {
  9578. if ( GetBIsCombatActionAllowed() )
  9579. {
  9580. PushCombatActionOnBuffer( EBAT_ItemUse, BS_Pressed );
  9581. ProcessCombatActionBuffer();
  9582. }
  9583.  
  9584. SetIsAimingCrossbow( false );
  9585. RemoveTimer( 'IsItemUseInputHeld' );
  9586. }
  9587. }*/
  9588.  
  9589. public function SetupCombatAction( action : EBufferActionType, stage : EButtonStage )
  9590. {
  9591. var weaponType : EPlayerWeapon;
  9592. var canAttackTarget : CGameplayEntity;
  9593. var target : CActor;
  9594.  
  9595. /*if( thePlayer.substateManager.GetStateCur() == 'Slide' )
  9596. {
  9597. return;
  9598. }*/
  9599. if ( !IsCombatMusicEnabled() )
  9600. {
  9601. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  9602. FindTarget();
  9603. UpdateDisplayTarget( true );
  9604. }
  9605.  
  9606. if ( displayTarget && IsDisplayTargetTargetable() )
  9607. canAttackTarget = displayTarget;
  9608. else if ( GetTarget() )
  9609. canAttackTarget = GetTarget();
  9610. else if( !target && IsCombatMusicEnabled() )
  9611. canAttackTarget = moveTarget;
  9612.  
  9613. target = (CActor)canAttackTarget;
  9614.  
  9615. if ( !AllowAttack( target, action ) )
  9616. return;
  9617.  
  9618. if( ( action != EBAT_ItemUse ) && ( action != EBAT_CastSign ) )
  9619. {
  9620. weaponType = weaponHolster.GetCurrentMeleeWeapon();
  9621. PrepareToAttack( target, action );
  9622.  
  9623. //Do not automatically attack when drawing sword
  9624. if ( weaponType != weaponHolster.GetCurrentMeleeWeapon() )
  9625. {
  9626. //Check if switching from PW_None to PW_Fists. If so, allow the attack
  9627. if ( !( weaponType == PW_None && weaponHolster.GetCurrentMeleeWeapon() == PW_Fists ) )
  9628. return;
  9629. }
  9630. }
  9631.  
  9632. //geralt's special attack heavy
  9633. if(action == EBAT_SpecialAttack_Heavy && !((W3ReplacerCiri)this) )
  9634. thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s02));
  9635.  
  9636. CriticalEffectAnimationInterrupted("SetupCombatAction " + action);
  9637. PushCombatActionOnBuffer( action, stage );
  9638.  
  9639. if( GetBIsCombatActionAllowed() )
  9640. {
  9641. ProcessCombatActionBuffer();
  9642. }
  9643. }
  9644.  
  9645. public function AllowAttack( target : CActor, action : EBufferActionType ) : bool
  9646. {
  9647. var newTarget : CActor;
  9648. var canAttackWhenNotInCombat : bool;
  9649. var messageDisplayed : bool;
  9650.  
  9651. var itemId : SItemUniqueId;
  9652. var isShootingCrossbow : bool;
  9653.  
  9654. var isInCorrectState : bool;
  9655.  
  9656. if ( target )
  9657. {
  9658. if ( target.IsTargetableByPlayer())
  9659. {
  9660. if ( !target.IsAttackableByPlayer() )
  9661. {
  9662. DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_cant_attack_this_target"));
  9663. return false;
  9664. }
  9665. }
  9666. }
  9667.  
  9668. if ( this.GetCurrentStateName() == 'Exploration' )
  9669. isInCorrectState = true;
  9670.  
  9671. if ( action == EBAT_ItemUse )
  9672. {
  9673. itemId = thePlayer.GetSelectedItemId();
  9674. if ( inv.IsIdValid(itemId) && inv.IsItemCrossbow(itemId) )
  9675. isShootingCrossbow = true;
  9676.  
  9677. if ( !isInCorrectState )
  9678. {
  9679. if ( this.GetCurrentStateName() == 'AimThrow' && !isShootingCrossbow )
  9680. {
  9681. isInCorrectState = true;
  9682. }
  9683. }
  9684. }
  9685.  
  9686. if ( isInCorrectState )
  9687. canAttackWhenNotInCombat = thePlayer.CanAttackWhenNotInCombat( action, false, newTarget, target );
  9688.  
  9689. if( !target )
  9690. {
  9691. if ( isInCorrectState )
  9692. {
  9693. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  9694. target = newTarget;
  9695. }
  9696. }
  9697.  
  9698. if ( isInCorrectState )
  9699. {
  9700. if ( !canAttackWhenNotInCombat )
  9701. {
  9702. if ( DisplayCannotAttackMessage( target ) )
  9703. messageDisplayed = true;
  9704. else if ( ( action == EBAT_LightAttack || action == EBAT_HeavyAttack )
  9705. && !RaiseAttackFriendlyEvent( target ) )
  9706. messageDisplayed = true;
  9707. else
  9708. {
  9709. if ( !CanRaiseCombatActionFriendlyEvent( isShootingCrossbow ) )
  9710. messageDisplayed = true;
  9711. }
  9712. }
  9713.  
  9714. if ( messageDisplayed )
  9715. {
  9716. theInput.ForceDeactivateAction('ThrowItem');
  9717. theInput.ForceDeactivateAction('ThrowItemHold');
  9718. return false;
  9719. }
  9720. }
  9721.  
  9722. return true;
  9723. }
  9724.  
  9725.  
  9726. //returns true if processed
  9727. public function ProcessCombatActionBuffer() : bool
  9728. {
  9729. var actionResult : bool;
  9730. var action : EBufferActionType = this.BufferCombatAction;
  9731. var stage : EButtonStage = this.BufferButtonStage;
  9732. var s : SNotWorkingOutFunctionParametersHackStruct1;
  9733. var allSteps : bool = this.BufferAllSteps;
  9734.  
  9735. if ( IsInCombatActionFriendly() )
  9736. {
  9737. RaiseEvent('CombatActionFriendlyEnd');
  9738. }
  9739.  
  9740. //Disable any npcs that are set to unpushable when Player performs another combat action
  9741. if ( ( action != EBAT_SpecialAttack_Heavy && action != EBAT_ItemUse )
  9742. || ( action == EBAT_SpecialAttack_Heavy && stage == BS_Pressed )
  9743. || ( action == EBAT_ItemUse && stage != BS_Released ) )
  9744. {
  9745. GetMovingAgentComponent().GetMovementAdjustor().CancelAll();
  9746. SetUnpushableTarget( NULL );
  9747. }
  9748.  
  9749. //if ( !( action == EBAT_Dodge && stage == BS_Pressed && IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge ) )
  9750. if ( !( action == EBAT_Dodge || action == EBAT_Roll ) )
  9751. SetIsCurrentlyDodging(false);
  9752.  
  9753. //-- init
  9754. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  9755.  
  9756. //theGame.GetSyncAnimManager().OnRemoveFinisherCameraAnimation();
  9757.  
  9758. if ( action == EBAT_ItemUse && GetInventory().IsItemCrossbow( selectedItemId ) )
  9759. {
  9760. //stage == BS_Pressed &&
  9761. if ( rangedWeapon
  9762. && ( ( rangedWeapon.GetCurrentStateName() != 'State_WeaponShoot' && rangedWeapon.GetCurrentStateName() != 'State_WeaponAim' ) || GetIsShootingFriendly() ) )
  9763. {
  9764. SetSlideTarget( GetCombatActionTarget( action ) );
  9765. }
  9766. }
  9767. else if ( !( ( action == EBAT_SpecialAttack_Heavy && stage == BS_Released ) || GetCurrentStateName() == 'AimThrow' ) )
  9768. {
  9769. SetSlideTarget( GetCombatActionTarget( action ) );
  9770. }
  9771.  
  9772. if( !slideTarget )
  9773. LogChannel( 'Targeting', "NO SLIDE TARGET" );
  9774.  
  9775. //-- process
  9776. actionResult = true;
  9777.  
  9778. switch ( action )
  9779. {
  9780. case EBAT_EMPTY :
  9781. {
  9782. this.BufferAllSteps = false;
  9783. return true;
  9784. } break;
  9785.  
  9786. case EBAT_LightAttack :
  9787. {
  9788. if ( IsCiri() )
  9789. return false;
  9790.  
  9791. switch ( stage )
  9792. {
  9793. case BS_Pressed ://BS_Released :
  9794. {
  9795. // early out, stamina drain etc
  9796. //if( HasStaminaToUseAction(ESAT_LightAttack) )
  9797. //{
  9798.  
  9799. // replacing stamina lock with stamina drain - change in design
  9800. /*
  9801. s = LockStamina(ESAT_LightAttack);
  9802. if(s.retValue)
  9803. {
  9804. AddCombatActionStaminaLock(s.outValue);
  9805. }
  9806. */
  9807. DrainStamina(ESAT_LightAttack);
  9808. //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack );
  9809.  
  9810. thePlayer.BreakPheromoneEffect();
  9811. actionResult = OnPerformAttack(theGame.params.ATTACK_NAME_LIGHT);
  9812. //}
  9813. } break;
  9814.  
  9815. default :
  9816. {
  9817. actionResult = false;
  9818. }break;
  9819. }
  9820. }break;
  9821.  
  9822. case EBAT_HeavyAttack :
  9823. {
  9824. if ( IsCiri() )
  9825. return false;
  9826.  
  9827. switch ( stage )
  9828. {
  9829. case BS_Released :
  9830. {
  9831. // early out, stamina drain etc
  9832. //if( HasStaminaToUseAction(ESAT_HeavyAttack) )
  9833. //{
  9834. // replacing stamina lock with stamina drain - change in design
  9835. /*
  9836. s = LockStamina(ESAT_HeavyAttack);
  9837. if(s.retValue)
  9838. {
  9839. AddCombatActionStaminaLock(s.outValue);
  9840. }
  9841. */
  9842. DrainStamina(ESAT_HeavyAttack);
  9843.  
  9844. //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack );
  9845.  
  9846. thePlayer.BreakPheromoneEffect();
  9847. actionResult = this.OnPerformAttack(theGame.params.ATTACK_NAME_HEAVY);
  9848. //}
  9849. } break;
  9850.  
  9851. case BS_Pressed :
  9852. {
  9853. if ( this.GetCurrentStateName() == 'CombatFists' )
  9854. {
  9855. // early out, stamina drain etc
  9856. //if( HasStaminaToUseAction(ESAT_HeavyAttack) )
  9857. //{
  9858. // replacing stamina lock with stamina drain - change in design
  9859. /*
  9860. s = LockStamina(ESAT_HeavyAttack);
  9861. if(s.retValue)
  9862. {
  9863. AddCombatActionStaminaLock(s.outValue);
  9864. }
  9865. */
  9866. DrainStamina(ESAT_HeavyAttack);
  9867.  
  9868. //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack );
  9869.  
  9870. thePlayer.BreakPheromoneEffect();
  9871. actionResult = this.OnPerformAttack(theGame.params.ATTACK_NAME_HEAVY);
  9872. //}
  9873. }
  9874. } break;
  9875.  
  9876. default :
  9877. {
  9878. actionResult = false;
  9879.  
  9880. } break;
  9881. }
  9882. } break;
  9883.  
  9884. case EBAT_ItemUse : //this gets called only for bombs. No usable items use this!
  9885. {
  9886. switch ( stage )
  9887. {
  9888. case BS_Pressed :
  9889. {
  9890. if ( !( (W3PlayerWitcher)this ) ||
  9891. ( !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) ) ) )
  9892. //( !IsCastingSign() && !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) ) )
  9893. {
  9894. if ( inv.IsItemCrossbow( selectedItemId ) )
  9895. {
  9896. rangedWeapon = ( Crossbow )( inv.GetItemEntityUnsafe( selectedItemId ) );
  9897. rangedWeapon.OnRangedWeaponPress();
  9898. GetTarget().SignalGameplayEvent( 'Approach' );
  9899. }
  9900. else if(inv.IsItemBomb(selectedItemId) && this.inv.SingletonItemGetAmmo(selectedItemId) > 0 )
  9901. {
  9902. BombThrowStart();
  9903. GetTarget().SignalGameplayEvent( 'Approach' );
  9904. }
  9905. else
  9906. {
  9907. DrainStamina(ESAT_UsableItem);
  9908. UsableItemStart();
  9909. }
  9910. }
  9911.  
  9912. } if (!allSteps) break;
  9913.  
  9914. case BS_Released:
  9915. {
  9916. if ( !( (W3PlayerWitcher)this ) ||
  9917. ( !IsInCombatActionFriendly() && ( GetBIsCombatActionAllowed() || !( !GetBIsCombatActionAllowed() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) ) ) ) )
  9918. //( !IsCastingSign() && !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) ) )
  9919. {
  9920. if ( inv.IsItemCrossbow( selectedItemId ) )
  9921. {
  9922. /*if ( rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' )
  9923. {
  9924. rangedWeapon = ( Crossbow )( inv.GetItemEntityUnsafe( selectedItemId ) );
  9925. rangedWeapon.OnRangedWeaponPress();
  9926. }*/
  9927. rangedWeapon.OnRangedWeaponRelease();
  9928. }
  9929. else if(inv.IsItemBomb(selectedItemId))
  9930. {
  9931. BombThrowRelease();
  9932. }
  9933. else
  9934. {
  9935. UsableItemRelease();
  9936. }
  9937. }
  9938. } break;
  9939.  
  9940. default :
  9941. {
  9942. actionResult = false;
  9943. break;
  9944. }
  9945. }
  9946. } break;
  9947.  
  9948. case EBAT_Dodge :
  9949. {
  9950. switch ( stage )
  9951. {
  9952. case BS_Released :
  9953. {
  9954. theGame.GetBehTreeReactionManager().CreateReactionEvent( this, 'PlayerEvade', 1.0f, 10.0f, -1.0f, -1 );
  9955. thePlayer.BreakPheromoneEffect();
  9956. actionResult = this.OnPerformEvade( PET_Dodge );
  9957. } break;
  9958.  
  9959. /*case BS_Pressed :
  9960. {
  9961. actionResult = this.OnPerformEvade( PET_Roll );
  9962. } break;*/
  9963.  
  9964. default :
  9965. {
  9966. actionResult = false;
  9967. } break;
  9968. }
  9969. } break;
  9970.  
  9971. case EBAT_Roll :
  9972. {
  9973. if ( IsCiri() )
  9974. return false;
  9975.  
  9976. switch ( stage )
  9977. {
  9978. case BS_Released :
  9979. {
  9980. theGame.GetBehTreeReactionManager().CreateReactionEvent( this, 'PlayerEvade', 1.0f, 10.0f, -1.0f, -1 );
  9981. thePlayer.BreakPheromoneEffect();
  9982. actionResult = this.OnPerformEvade( PET_Roll );
  9983. } break;
  9984.  
  9985. case BS_Pressed :
  9986. {
  9987. if ( this.GetBehaviorVariable( 'combatActionType' ) == 2.f )
  9988. {
  9989. if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' )
  9990. actionResult = this.OnPerformEvade( PET_Pirouette );
  9991. else
  9992. actionResult = this.OnPerformEvade( PET_Roll );
  9993. }
  9994. else
  9995. {
  9996. if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' )
  9997. {
  9998. actionResult = this.OnPerformEvade( PET_Dodge );
  9999. actionResult = this.OnPerformEvade( PET_Pirouette );
  10000. }
  10001. else
  10002. {
  10003. actionResult = this.OnPerformEvade( PET_Dodge );
  10004. actionResult = this.OnPerformEvade( PET_Roll );
  10005. }
  10006. }
  10007.  
  10008.  
  10009. } break;
  10010.  
  10011. default :
  10012. {
  10013. actionResult = false;
  10014. } break;
  10015. }
  10016. } break;
  10017.  
  10018. case EBAT_Draw_Steel :
  10019. {
  10020. switch ( stage )
  10021. {
  10022. case BS_Pressed :
  10023. {
  10024. if( !IsActionAllowed(EIAB_DrawWeapon) )
  10025. {
  10026. thePlayer.DisplayActionDisallowedHudMessage(EIAB_DrawWeapon);
  10027. actionResult = false;
  10028. break;
  10029. }
  10030. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'steelsword' ) )
  10031. {
  10032. OnEquipMeleeWeapon( PW_Steel, false, true );
  10033. }
  10034.  
  10035. actionResult = false;
  10036.  
  10037. } break;
  10038.  
  10039. default :
  10040. {
  10041. actionResult = false;
  10042. } break;
  10043. }
  10044. } break;
  10045.  
  10046. case EBAT_Draw_Silver :
  10047. {
  10048. switch ( stage )
  10049. {
  10050. case BS_Pressed :
  10051. {
  10052. if( !IsActionAllowed(EIAB_DrawWeapon) )
  10053. {
  10054. thePlayer.DisplayActionDisallowedHudMessage(EIAB_DrawWeapon);
  10055. actionResult = false;
  10056. break;
  10057. }
  10058. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'silversword' ) )
  10059. {
  10060. OnEquipMeleeWeapon( PW_Silver, false, true );
  10061. }
  10062.  
  10063. actionResult = false;
  10064.  
  10065. } break;
  10066.  
  10067. default :
  10068. {
  10069. actionResult = false;
  10070. } break;
  10071. }
  10072. } break;
  10073.  
  10074. case EBAT_Sheathe_Sword :
  10075. {
  10076. switch ( stage )
  10077. {
  10078. case BS_Pressed :
  10079. {
  10080. if( GetCurrentMeleeWeaponType() == PW_Silver )
  10081. {
  10082. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'silversword' ) )
  10083. {
  10084. OnEquipMeleeWeapon( PW_Silver, false, true );
  10085. }
  10086. }
  10087. else if( GetCurrentMeleeWeaponType() == PW_Steel )
  10088. {
  10089. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'steelsword' ) )
  10090. {
  10091. OnEquipMeleeWeapon( PW_Steel, false, true );
  10092. }
  10093. }
  10094.  
  10095. actionResult = false;
  10096.  
  10097. } break;
  10098.  
  10099. default :
  10100. {
  10101. actionResult = false;
  10102. } break;
  10103. }
  10104. } break;
  10105.  
  10106. default:
  10107. return false; //not processed
  10108. }
  10109.  
  10110. //if here then buffer was processed
  10111. CleanCombatActionBuffer();
  10112.  
  10113. if (actionResult)
  10114. {
  10115. SetCombatAction( action ) ;
  10116.  
  10117. if(GetWitcherPlayer().IsInFrenzy())
  10118. GetWitcherPlayer().SkillFrenzyFinish(0);
  10119. }
  10120.  
  10121. return true;
  10122. }
  10123.  
  10124. public function CleanCombatActionBuffer()
  10125. {
  10126. BufferCombatAction = EBAT_EMPTY;
  10127. BufferAllSteps = false;
  10128. }
  10129.  
  10130. public function CancelHoldAttacks()
  10131. {
  10132. thePlayer.RemoveTimer( 'IsSpecialLightAttackInputHeld' );
  10133. thePlayer.RemoveTimer( 'IsSpecialHeavyAttackInputHeld' );
  10134. thePlayer.RemoveTimer( 'SpecialAttackLightSustainCost' );
  10135. thePlayer.RemoveTimer( 'SpecialAttackHeavySustainCost' );
  10136. thePlayer.RemoveTimer( 'UpdateSpecialAttackLightHeading' );
  10137. thePlayer.UnblockAction( EIAB_Crossbow, 'SpecialAttack' );
  10138.  
  10139. if ( thePlayer.GetBehaviorVariable( 'combatActionType' ) == (int)CAT_SpecialAttack )
  10140. {
  10141. if( thePlayer.GetBehaviorVariable( 'playerAttackType' ) == (int)PAT_Light
  10142. && thePlayer.GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.f )
  10143. {
  10144. thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s01));
  10145. thePlayer.PushCombatActionOnBuffer( EBAT_SpecialAttack_Light, BS_Released );
  10146. thePlayer.ProcessCombatActionBuffer();
  10147. //thePlayer.SetupCombatAction( EBAT_SpecialAttack_Light, BS_Released );
  10148. ((W3PlayerWitcherStateCombatFists) GetState('Combat')).ResetTimeToEndCombat();
  10149.  
  10150. }
  10151. else if( thePlayer.GetBehaviorVariable( 'playerAttackType' ) == (int)PAT_Heavy
  10152. && thePlayer.GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.f )
  10153. {
  10154. thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s02));
  10155. thePlayer.PushCombatActionOnBuffer( EBAT_SpecialAttack_Heavy, BS_Released );
  10156. thePlayer.ProcessCombatActionBuffer();
  10157. //thePlayer.SetupCombatAction( EBAT_SpecialAttack_Heavy, BS_Released );
  10158. }
  10159. }
  10160. }
  10161.  
  10162. public function RaiseAttackFriendlyEvent( actor : CActor ) : bool
  10163. {
  10164. var playerToTargetHeading : float;
  10165.  
  10166. if ( actor && RaiseCombatActionFriendlyEvent() )
  10167. {
  10168. SetBehaviorVariable( 'tauntTypeForOverlay', 0.f );
  10169. SetBehaviorVariable( 'combatActionTypeForOverlay', (int)CAT_Attack );
  10170.  
  10171. if ( actor )
  10172. actor.SignalGameplayEvent('PersonalTauntAction');
  10173. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'TauntAction', -1.0, 4.5f, -1, 9999, true ); //reactionSystemSearch
  10174.  
  10175. OnCombatActionStart();
  10176.  
  10177. playerToTargetHeading = VecHeading( actor.GetWorldPosition() - GetWorldPosition() );
  10178.  
  10179. SetCustomRotation( 'Attack', playerToTargetHeading, 0.0f, 0.3f, false );
  10180.  
  10181. return true;
  10182. }
  10183.  
  10184. return false;
  10185. }
  10186.  
  10187. public function SendAttackReactionEvent()
  10188. {
  10189. var reactionName : name;
  10190.  
  10191. /*switch ( action )
  10192. {
  10193. case EBAT_LightAttack :
  10194. reactionName = 'AttackAction';
  10195. break;
  10196. case EBAT_HeavyAttack :
  10197. reactionName = 'AttackAction';
  10198. break;
  10199. case EBAT_SpecialAttack_Light :
  10200. reactionName = 'AttackAction';
  10201. break;
  10202. case EBAT_SpecialAttack_Heavy :
  10203. reactionName = 'AttackAction';
  10204. break;
  10205. case EBAT_Ciri_SpecialAttack :
  10206. reactionName = 'AttackAction';
  10207. break;
  10208. default:
  10209. return;
  10210. }*/
  10211.  
  10212. reactionName = 'AttackAction';
  10213.  
  10214. if ( IsNameValid(reactionName) )
  10215. {
  10216. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, reactionName, -1.0, 8.0f, -1, 5, true ); //reactionSystemSearch
  10217. }
  10218.  
  10219. // event for horse - trigger running away
  10220. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'outOfMyWay', -1.0, 2.0f, -1, 5, true ); //reactionSystemSearch
  10221. }
  10222.  
  10223. var forceCanAttackWhenNotInCombat : int; // 0 = NoForce, 1 = ForceWhenNoDisplayTarget 2 = ForceEvenWithDisplayTarget
  10224. public function SetForceCanAttackWhenNotInCombat( forceMode : int )
  10225. {
  10226. forceCanAttackWhenNotInCombat = forceMode;
  10227. }
  10228.  
  10229. public function CanAttackWhenNotInCombat( actionType : EBufferActionType, altCast : bool, out newTarget : CActor, optional target : CGameplayEntity ) : bool
  10230. {
  10231. var localTargets : array<CActor>;
  10232. var i, size : int;
  10233. var inputHeading : float;
  10234. var clearanceMin, clearanceMax : float;
  10235. var attackLength : float;
  10236. var attackAngle : float;
  10237. var npc : CNewNPC;
  10238. var canAttackTarget : CGameplayEntity;
  10239. var canAttackTargetActor : CActor;
  10240.  
  10241. if ( target )
  10242. canAttackTarget = target;
  10243. else if ( displayTarget && IsDisplayTargetTargetable() )
  10244. canAttackTarget = displayTarget;
  10245. else
  10246. canAttackTarget = slideTarget;
  10247.  
  10248. canAttackTargetActor = (CActor)canAttackTarget;
  10249.  
  10250. if ( forceCanAttackWhenNotInCombat == 2 )
  10251. return true;
  10252. else if ( forceCanAttackWhenNotInCombat == 1 && ( !canAttackTarget || !canAttackTargetActor.IsHuman() ) )
  10253. return true;
  10254.  
  10255. if ( actionType == EBAT_CastSign )
  10256. {
  10257. if ( thePlayer.GetEquippedSign() != ST_Quen && thePlayer.GetEquippedSign() != ST_Axii )
  10258. {
  10259. if ( CanUseSkill( S_Magic_s20 ) )
  10260. {
  10261. if ( thePlayer.GetEquippedSign() == ST_Aard )
  10262. attackLength = 6.f;
  10263. else if ( thePlayer.GetEquippedSign() == ST_Igni )
  10264. attackLength = 4.f;
  10265. else
  10266. attackLength = 6.f;
  10267. }
  10268. else
  10269. {
  10270. if ( thePlayer.GetEquippedSign() == ST_Aard )
  10271. attackLength = 9.f;
  10272. else if ( thePlayer.GetEquippedSign() == ST_Igni )
  10273. attackLength = 6.f;
  10274. else
  10275. attackLength = 6.f;
  10276. }
  10277.  
  10278. if ( altCast )
  10279. attackAngle = 180.f;
  10280. else
  10281. // sign cone angle / 2 with a bonus for safetey
  10282. attackAngle = 90.f;
  10283.  
  10284. if ( !lastAxisInputIsMovement )
  10285. inputHeading = VecHeading( theCamera.GetCameraDirection() );
  10286. else if ( lAxisReleasedAfterCounter )
  10287. inputHeading = GetHeading();
  10288. else
  10289. inputHeading = GetCombatActionHeading();
  10290.  
  10291. clearanceMin = 1.f;
  10292. clearanceMax = attackLength + 1.f;
  10293. }
  10294. else if ( thePlayer.GetEquippedSign() == ST_Axii )
  10295. {
  10296. npc = (CNewNPC)canAttackTarget;
  10297. if ( npc && npc.GetNPCType() == ENGT_Quest && !npc.HasTag(theGame.params.TAG_AXIIABLE_LOWER_CASE) && !npc.HasTag(theGame.params.TAG_AXIIABLE))
  10298. return false;
  10299. else if ( npc && npc.IsUsingHorse() )
  10300. return false;
  10301. else
  10302. return true;
  10303. }
  10304. else
  10305. return true;
  10306. }
  10307. else if ( actionType == EBAT_ItemUse )
  10308. {
  10309. attackLength = theGame.params.MAX_THROW_RANGE;
  10310. attackAngle = 90.f;
  10311.  
  10312. if ( thePlayer.lastAxisInputIsMovement )
  10313. inputHeading = GetCombatActionHeading();
  10314. else
  10315. inputHeading = VecHeading( theCamera.GetCameraDirection() );
  10316.  
  10317. clearanceMin = 0.8f;
  10318. clearanceMax = attackLength + 3.f;
  10319. }
  10320. else
  10321. {
  10322. if ( actionType == EBAT_SpecialAttack_Light || actionType == EBAT_SpecialAttack_Heavy )
  10323. {
  10324. attackLength = 1.9f;
  10325. attackAngle = 90.f;
  10326. }
  10327. else
  10328. {
  10329. if( thePlayer.GetCurrentMeleeWeaponType() == PW_Fists || thePlayer.GetCurrentMeleeWeaponType() == PW_None )
  10330. attackLength = 1.2f;
  10331. else
  10332. attackLength = 1.9f;
  10333.  
  10334. attackAngle = 90.f;
  10335. }
  10336.  
  10337. if ( lastAxisInputIsMovement )
  10338. inputHeading = GetCombatActionHeading();
  10339. else
  10340. inputHeading = VecHeading( theCamera.GetCameraDirection() );
  10341.  
  10342. clearanceMin = attackLength / 2.f;
  10343. clearanceMax = attackLength + 3.f;
  10344. }
  10345.  
  10346. //Use slideTarget first if it's NULL, then we try other npcs in the area
  10347. if ( canAttackTarget )
  10348. {
  10349. if ( ( canAttackTargetActor && canAttackTargetActor.IsHuman() ) || canAttackTargetActor.HasTag( 'softLock_Friendly' ) )
  10350. {
  10351. if ( ShouldPerformFriendlyAction( canAttackTargetActor, inputHeading, attackAngle, clearanceMin, clearanceMax ) )
  10352. {
  10353. SetSlideTarget( canAttackTargetActor );
  10354. newTarget = canAttackTargetActor;
  10355. return false;
  10356. }
  10357. }
  10358.  
  10359. //return true;
  10360. }
  10361.  
  10362. return true;
  10363.  
  10364. thePlayer.GetVisibleEnemies( localTargets );
  10365. size = localTargets.Size();
  10366.  
  10367. if ( size > 0 )
  10368. {
  10369. for ( i = size-1; i>=0; i-=1 )
  10370. {
  10371. /*
  10372. Andrzej: Geralt's friendly combat action - taunting actors with a sword or playing with Signs is set to work only for humans.
  10373. We don't want it to work against all non-humans, so I've added an exception that works similar to targeting non actor objects.
  10374. If you want Geralt to play friendly combat action when targeting monsters, add tag softLock_Friendly to monster's entity.
  10375. */
  10376. if ( !localTargets[i].IsHuman() && !localTargets[i].HasTag( 'softLock_Friendly' ) )
  10377. localTargets.Erase(i);
  10378. }
  10379. }
  10380.  
  10381. size = localTargets.Size();
  10382. if ( size > 0 )
  10383. {
  10384. for ( i = 0; i < localTargets.Size(); i += 1 )
  10385. {
  10386. if ( ShouldPerformFriendlyAction( localTargets[i], inputHeading, attackAngle, clearanceMin, clearanceMax ) )
  10387. {
  10388. SetSlideTarget( localTargets[i] );
  10389. newTarget = localTargets[i];
  10390. return false;
  10391. }
  10392. }
  10393. }
  10394.  
  10395. newTarget = NULL;
  10396.  
  10397. return true;
  10398. }
  10399.  
  10400. private function ShouldPerformFriendlyAction( actor : CActor, inputHeading, attackAngle, clearanceMin, clearanceMax : float ) : bool
  10401. {
  10402. var npc : CNewNPC;
  10403. var argh : float;
  10404. var playerToTargetDist : float;
  10405.  
  10406. npc = (CNewNPC)actor;
  10407.  
  10408. if ( npc &&
  10409. ( GetAttitudeBetween(thePlayer, npc) == AIA_Hostile || ( GetAttitudeBetween(thePlayer, npc) == AIA_Neutral && npc.GetNPCType() != ENGT_Guard ) ) )
  10410. {
  10411. }
  10412. else
  10413. {
  10414. playerToTargetDist = VecDistance( this.GetWorldPosition(), actor.PredictWorldPosition( 0.5f ) ); //actor.GetNearestPointInPersonalSpace( this.GetWorldPosition() ) );
  10415.  
  10416. argh = AbsF( AngleDistance( inputHeading, VecHeading( actor.GetWorldPosition() - thePlayer.GetWorldPosition() ) ) );
  10417.  
  10418. if ( AbsF( AngleDistance( inputHeading, VecHeading( actor.GetWorldPosition() - thePlayer.GetWorldPosition() ) ) ) < attackAngle )
  10419. {
  10420. if ( playerToTargetDist < clearanceMax )
  10421. {
  10422. return true;
  10423. }
  10424. }
  10425. else
  10426. {
  10427. if ( playerToTargetDist < clearanceMin )
  10428. {
  10429. return true;
  10430. }
  10431. }
  10432. }
  10433.  
  10434. return false;
  10435. }
  10436.  
  10437. ///////////////////////////////////////////////////////////////////////////
  10438. // HUD //#B
  10439. ///////////////////////////////////////////////////////////////////////////
  10440.  
  10441. public function GetHudMessagesSize() : int
  10442. {
  10443. return HudMessages.Size();
  10444. }
  10445.  
  10446. public function GetHudPendingMessage() : string
  10447. {
  10448. return HudMessages[0];
  10449. }
  10450.  
  10451. public function DisplayHudMessage( value : string ) : void
  10452. {
  10453. if (value == "")
  10454. {
  10455. return;
  10456. }
  10457.  
  10458. if( GetHudMessagesSize() > 0 )
  10459. {
  10460. if( HudMessages[HudMessages.Size()-1] == value )
  10461. {
  10462. return;
  10463. }
  10464. }
  10465. HudMessages.PushBack(value);
  10466. }
  10467.  
  10468. //hacks for review requests
  10469. private final function DisallowedActionDontShowHack(action : EInputActionBlock) : bool
  10470. {
  10471. var locks : array< SInputActionLock >;
  10472. var i : int;
  10473.  
  10474. //no info if we're trying to attack while staggered
  10475. if((action == EIAB_Fists || action == EIAB_SwordAttack || action == EIAB_Signs || action == EIAB_LightAttacks || action == EIAB_HeavyAttacks || action == EIAB_SpecialAttackLight || action == EIAB_SpecialAttackHeavy) && (HasBuff(EET_Stagger) || HasBuff(EET_LongStagger)) )
  10476. {
  10477. return true;
  10478. }
  10479.  
  10480. //always show meditation message
  10481. if(action == EIAB_OpenMeditation)
  10482. return false;
  10483.  
  10484. //if there's at least one lock from quest or from location fine
  10485. locks = GetActionLocks(action);
  10486. for(i=0; i<locks.Size(); i+=1)
  10487. {
  10488. if(locks[i].isFromQuest || locks[i].isFromPlace)
  10489. return false;
  10490. }
  10491.  
  10492. if ( this.IsCurrentlyUsingItemL() )
  10493. {
  10494. if ( action == EIAB_HeavyAttacks || action == EIAB_Parry )
  10495. return false;
  10496. }
  10497.  
  10498. //otherwise we don't display locks
  10499. return true;
  10500. }
  10501.  
  10502. public final function DisplayActionDisallowedHudMessage(action : EInputActionBlock, optional isCombatLock : bool, optional isPlaceLock : bool, optional isTimeLock : bool, optional isDangerous : bool)
  10503. {
  10504. var lockType : name;
  10505.  
  10506. if(action != EIAB_Undefined && DisallowedActionDontShowHack(action))
  10507. return;
  10508.  
  10509. //combat lock is strongest - overrides all
  10510. if(IsInCombat() && !IsActionCombat(action))
  10511. isCombatLock = true;
  10512.  
  10513. //if no specific lock set, check based on action
  10514. if(!isCombatLock && !isPlaceLock && ! isTimeLock && action != EIAB_Undefined)
  10515. {
  10516. lockType = inputHandler.GetActionBlockedHudLockType(action);
  10517.  
  10518. if(lockType == 'combat')
  10519. isCombatLock = true;
  10520. else if(lockType == 'place')
  10521. isPlaceLock = true;
  10522. else if(lockType == 'time')
  10523. isTimeLock = true;
  10524. }
  10525.  
  10526. if(isDangerous)
  10527. {
  10528. DisplayHudMessage(GetLocStringByKeyExt( "message_meditation_too_dangerous" ));
  10529. }
  10530. else if(isCombatLock)
  10531. {
  10532. DisplayHudMessage(GetLocStringByKeyExt( "panel_hud_message_actionnotallowed_combat" ));
  10533. }
  10534. else if(isPlaceLock)
  10535. {
  10536. DisplayHudMessage(GetLocStringByKeyExt( "menu_cannot_perform_action_here" ));
  10537. }
  10538. else if(isTimeLock)
  10539. {
  10540. DisplayHudMessage(GetLocStringByKeyExt( "menu_cannot_perform_action_now" ));
  10541. }
  10542. }
  10543.  
  10544. //removes first or all instances of given message
  10545. public function RemoveHudMessageByString(msg : string, optional allQueuedInstances : bool)
  10546. {
  10547. var i, j : int;
  10548.  
  10549. for(i=0; i<HudMessages.Size(); i+=1)
  10550. {
  10551. if(HudMessages[i] == msg)
  10552. {
  10553. HudMessages.EraseFast(i);
  10554.  
  10555. if(!allQueuedInstances)
  10556. return;
  10557.  
  10558. break;
  10559. }
  10560. }
  10561.  
  10562. //if here then we want all remaining instances as well
  10563. for(j=HudMessages.Size()-1; j >= i; j-=1)
  10564. {
  10565. if(HudMessages[i] == msg)
  10566. {
  10567. HudMessages.EraseFast(i);
  10568. }
  10569. }
  10570. }
  10571.  
  10572. public function RemoveHudMessageByIndex(idx : int)
  10573. {
  10574. if(idx >= 0 && idx < HudMessages.Size())
  10575. HudMessages.Erase(idx);
  10576. }
  10577.  
  10578. function SetSettlementBlockCanter( valueAdd : int ) // #B
  10579. {
  10580. m_SettlementBlockCanter += valueAdd;
  10581. }
  10582.  
  10583. var countDownToStart : int;
  10584. default countDownToStart = 0;
  10585.  
  10586. function DisplayRaceStart( countDownSecondsNumber : int ) // #B
  10587. {
  10588. var i : int;
  10589. countDownToStart = countDownSecondsNumber;
  10590. for( i = countDownSecondsNumber; i > 0; i -= 1 )
  10591. {
  10592. DisplayHudMessage(IntToString(i));
  10593. }
  10594. DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_race_start"));
  10595. AddTimer('RaceCountdown',1,true);
  10596. }
  10597.  
  10598. timer function RaceCountdown(dt : float, id : int) // #B
  10599. {
  10600. var hud : CR4ScriptedHud;
  10601. var messageModule : CR4HudModuleMessage;
  10602.  
  10603. countDownToStart -= 1;
  10604. hud = (CR4ScriptedHud)theGame.GetHud();
  10605.  
  10606. if( hud )
  10607. {
  10608. messageModule = (CR4HudModuleMessage)hud.GetHudModule("MessageModule");
  10609. if( messageModule )
  10610. {
  10611. messageModule.OnMessageHidden(); // to force show next messeage
  10612. }
  10613. }
  10614.  
  10615. if( countDownToStart <= 0 )
  10616. {
  10617. RemoveTimer('RaceCountdown');
  10618. }
  10619. }
  10620.  
  10621. public function GetCountDownToStart() : int // #B
  10622. {
  10623. return countDownToStart;
  10624. }
  10625.  
  10626. public function HAXE3GetContainer() : W3Container //#B temp for E3
  10627. {
  10628. return HAXE3Container;
  10629. }
  10630.  
  10631. public function HAXE3SetContainer( container : W3Container) : void //#B temp for E3
  10632. {
  10633. HAXE3Container = container;
  10634. }
  10635.  
  10636. public function HAXE3GetAutoLoot() : bool //#B temp for E3
  10637. {
  10638. return HAXE3bAutoLoot;
  10639. }
  10640.  
  10641. public function HAXE3SetAutoLoot( value : bool ) : void //#B temp for E3
  10642. {
  10643. HAXE3bAutoLoot = value;
  10644. }
  10645.  
  10646. public function GetShowHud() : bool
  10647. {
  10648. return bShowHud;
  10649. }
  10650.  
  10651. public function SetShowHud( value : bool ) : void
  10652. {
  10653. bShowHud = value;
  10654. }
  10655.  
  10656. public function DisplayItemRewardNotification( itemName : name, optional quantity : int ) : void
  10657. {
  10658. var hud : CR4ScriptedHud;
  10659. hud = (CR4ScriptedHud)theGame.GetHud();
  10660. hud.OnItemRecivedDuringScene(itemName, quantity); // #B because our default currency are Crowns !!!
  10661. }
  10662.  
  10663. function IsNewQuest( questGuid : CGUID ) : bool // #B
  10664. {
  10665. var i : int;
  10666. for(i = 0; i < displayedQuestsGUID.Size(); i += 1 )
  10667. {
  10668. if( displayedQuestsGUID[i] == questGuid )
  10669. {
  10670. return false;
  10671. }
  10672. }
  10673. displayedQuestsGUID.PushBack(questGuid);
  10674. return true;
  10675. }
  10676.  
  10677. function GetRewardMultiplier( rewardName : name ) : float // #B
  10678. {
  10679. var i : int;
  10680. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10681. {
  10682. if( rewardsMultiplier[i].rewardName == rewardName )
  10683. {
  10684. return rewardsMultiplier[i].rewardMultiplier;
  10685. }
  10686. }
  10687. return 1.0;
  10688. }
  10689.  
  10690. function GetRewardMultiplierExists( rewardName : name ) : bool // #B
  10691. {
  10692. var i : int;
  10693. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10694. {
  10695. if( rewardsMultiplier[i].rewardName == rewardName )
  10696. {
  10697. return true;
  10698. }
  10699. }
  10700. return false;
  10701. }
  10702.  
  10703. function SetRewardMultiplier( rewardName : name, value : float ) : void // #B
  10704. {
  10705. var i : int;
  10706. var rewardMultiplier : SRewardMultiplier;
  10707.  
  10708. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10709. {
  10710. if( rewardsMultiplier[i].rewardName == rewardName )
  10711. {
  10712. rewardsMultiplier[i].rewardMultiplier = value;
  10713. return;
  10714. }
  10715. }
  10716.  
  10717. rewardMultiplier.rewardName = rewardName;
  10718. rewardMultiplier.rewardMultiplier = value;
  10719.  
  10720. rewardsMultiplier.PushBack(rewardMultiplier);
  10721. }
  10722.  
  10723. function RemoveRewardMultiplier( rewardName : name ) : void // #B
  10724. {
  10725. var i : int;
  10726. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10727. {
  10728. if( rewardsMultiplier[i].rewardName == rewardName )
  10729. {
  10730. rewardsMultiplier.Erase(i);
  10731. return;
  10732. }
  10733. }
  10734. }
  10735.  
  10736. ////////////////////////////////////////////////////////////////////////////////
  10737. /////////////////////////// @OILS ////////////////////////////////////////////
  10738. ////////////////////////////////////////////////////////////////////////////////
  10739.  
  10740. public final function GetCurrentOilAmmo(id : SItemUniqueId) : int
  10741.  
  10742.  
  10743.  
  10744. {
  10745. return inv.GetItemModifierInt(id, 'oil_charges');
  10746. }
  10747.  
  10748. public final function GetMaxOilAmmo(id : SItemUniqueId) : int
  10749. {
  10750. return inv.GetItemModifierInt(id, 'oil_max_charges');
  10751. }
  10752.  
  10753.  
  10754. {
  10755. var currentAmmo : int;
  10756.  
  10757. if(ammo == 0)
  10758. ammo = 1;
  10759.  
  10760. currentAmmo = GetCurrentOilAmmo(id);
  10761. if(currentAmmo > 0)
  10762. {
  10763. currentAmmo = Max(currentAmmo - ammo, 0);
  10764. inv.SetItemModifierInt(id, 'oil_charges', currentAmmo);
  10765.  
  10766. if(currentAmmo == 0)
  10767.  
  10768. {
  10769. RemoveItemOil(id);
  10770.  
  10771. //count alchemy usage but only after nightmare
  10772. if(ShouldProcessTutorial('TutorialAlchemyRefill') && FactsQuerySum("q001_nightmare_ended") > 0 && GetWitcherPlayer())
  10773. FactsAdd('tut_alch_refill', 1);
  10774. }
  10775. }
  10776.  
  10777. theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnOilApplied );
  10778. }
  10779.  
  10780. //removes oil from given item
  10781. public function RemoveItemOil(id : SItemUniqueId)
  10782. {
  10783. var i : int;
  10784. var dm : CDefinitionsManagerAccessor;
  10785. var abilities : array<name>;
  10786. var sword : CWitcherSword;
  10787.  
  10788. dm = theGame.GetDefinitionsManager();
  10789. inv.GetItemAbilities(id, abilities);
  10790.  
  10791. for(i=0; i<abilities.Size(); i+=1)
  10792. if(dm.AbilityHasTag(abilities[i], theGame.params.OIL_ABILITY_TAG))
  10793. inv.RemoveItemCraftedAbility(id, abilities[i]);
  10794.  
  10795. inv.SetItemModifierInt(id, 'oil_charges', -1);
  10796. inv.SetItemModifierInt(id, 'oil_max_charges', -1);
  10797. sword = (CWitcherSword) inv.GetItemEntityUnsafe(id);
  10798. sword.RemoveOil( inv );
  10799.  
  10800. theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnOilApplied );
  10801. }
  10802. ////////////////////////////////////////////////////////////////////////////////
  10803. //
  10804. // @Items
  10805. //
  10806. ////////////////////////////////////////////////////////////////////////////////
  10807.  
  10808. public final function HasRequiredLevelToEquipItem(item : SItemUniqueId) : bool
  10809. {
  10810. /* modRemoveItemLevelReqs
  10811. */
  10812. return true;
  10813. }
  10814.  
  10815. public function SkillReduceBombAmmoBonus()
  10816. {
  10817. var i, ammo, maxAmmo : int;
  10818. var items : array<SItemUniqueId>;
  10819.  
  10820. items = inv.GetSingletonItems();
  10821.  
  10822. for(i=0; i<items.Size(); i+=1)
  10823. {
  10824. ammo = inv.GetItemModifierInt(items[i], 'ammo_current');
  10825.  
  10826. //if doesn't have infinite ammo
  10827. if(ammo > 0)
  10828. {
  10829. maxAmmo = inv.SingletonItemGetMaxAmmo(items[i]);
  10830.  
  10831. //if current ammo > max ammo, set current ammo to max ammo
  10832. if(ammo > maxAmmo)
  10833. {
  10834. inv.SetItemModifierInt(items[i], 'ammo_current', maxAmmo);
  10835. }
  10836. }
  10837. }
  10838. theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnAmmoChanged );
  10839. }
  10840.  
  10841. public function ConsumeItem( itemId : SItemUniqueId ) : bool
  10842. {
  10843. var params : SCustomEffectParams;
  10844. var buffs : array<SEffectInfo>;
  10845. var i : int;
  10846. var category : name;
  10847. var potionToxicity : float;
  10848.  
  10849. if(!inv.IsIdValid(itemId))
  10850. return false;
  10851.  
  10852. //apply buff
  10853. category = inv.GetItemCategory(itemId);
  10854. if(category == 'edibles' || inv.ItemHasTag(itemId, 'Drinks') || ( category == 'alchemy_ingredient' && inv.ItemHasTag(itemId, 'Alcohol')) )
  10855. {
  10856. //cannot eat in fistfights
  10857. if(IsFistFightMinigameEnabled())
  10858. {
  10859. DisplayActionDisallowedHudMessage(EIAB_Undefined, false, false, true);
  10860. return false;
  10861. }
  10862.  
  10863. //edible buff
  10864. inv.GetItemBuffs(itemId, buffs);
  10865.  
  10866. for(i=0; i<buffs.Size(); i+=1)
  10867. {
  10868. params.effectType = buffs[i].effectType;
  10869. params.creator = this;
  10870. params.sourceName = "edible";
  10871. params.customAbilityName = buffs[i].effectAbilityName;
  10872. AddEffectCustom(params);
  10873. }
  10874.  
  10875. //custom hack
  10876. if ( inv.ItemHasTag(itemId, 'Alcohol') )
  10877. {
  10878. potionToxicity = CalculateAttributeValue(inv.GetItemAttributeValue(itemId, 'toxicity'));
  10879. abilityManager.GainStat(BCS_Toxicity, potionToxicity );
  10880. AddEffectDefault(EET_Drunkenness, NULL, inv.GetItemName(itemId));
  10881. }
  10882. PlayItemConsumeSound( itemId );
  10883. }
  10884.  
  10885. if(inv.IsItemFood(itemId))
  10886. FactsAdd("consumed_food_cnt");
  10887.  
  10888. //remove item
  10889. if(!inv.ItemHasTag(itemId, theGame.params.TAG_INFINITE_USE) && !inv.RemoveItem(itemId))
  10890. {
  10891. LogAssert(false,"Failed to remove consumable item from player inventory!" + inv.GetItemName( itemId ) );
  10892. return false;
  10893. }
  10894.  
  10895. return true;
  10896. }
  10897.  
  10898. public function MountVehicle( vehicleEntity : CEntity, mountType : EVehicleMountType, optional vehicleSlot : EVehicleSlot )
  10899. {
  10900. var vehicle : CVehicleComponent;
  10901. vehicle = (CVehicleComponent)(vehicleEntity.GetComponentByClassName('CVehicleComponent'));
  10902.  
  10903. if ( vehicle )
  10904. vehicle.Mount( this, mountType, vehicleSlot );
  10905. }
  10906.  
  10907. public function DismountVehicle( vehicleEntity : CEntity, dismountType : EDismountType )
  10908. {
  10909. var vehicle : CVehicleComponent;
  10910. vehicle = (CVehicleComponent)(vehicleEntity.GetComponentByClassName('CVehicleComponent'));
  10911.  
  10912. if ( vehicle )
  10913. vehicle.IssueCommandToDismount( dismountType );
  10914. }
  10915.  
  10916. ////////////////
  10917. // @stamina @stats
  10918. ////////////////
  10919.  
  10920. //Returns true if actor has enough stamina to perform given action type (refer to DrainStamina for more info).
  10921. //If there is not enough stamina and actor is a player character then a insufficient stamina indication is shown on HUD
  10922. public function HasStaminaToUseAction(action : EStaminaActionType, optional abilityName : name, optional dt :float, optional multiplier : float) : bool
  10923. {
  10924. var cost : float;
  10925. var ret : bool;
  10926.  
  10927. ret = super.HasStaminaToUseAction(action, abilityName, dt, multiplier);
  10928.  
  10929. if(!ret)
  10930. {
  10931. SetCombatActionHeading( GetHeading() );
  10932.  
  10933. if(multiplier == 0)
  10934. multiplier = 1;
  10935.  
  10936. cost = multiplier * GetStaminaActionCost(action, abilityName, dt);
  10937. SetShowToLowStaminaIndication(cost);
  10938. }
  10939.  
  10940. return ret;
  10941. }
  10942.  
  10943. //since we cannot add timer on abilityManager...
  10944. timer function AbilityManager_FloorStaminaSegment(dt : float, id : int)
  10945. {
  10946. ((W3PlayerAbilityManager)abilityManager).FloorStaminaSegment();
  10947. }
  10948.  
  10949. public function DrainToxicity(amount : float )
  10950. {
  10951. if(abilityManager && abilityManager.IsInitialized() && IsAlive())
  10952. abilityManager.DrainToxicity(amount);
  10953. }
  10954.  
  10955. public function DrainFocus(amount : float )
  10956. {
  10957. if(abilityManager && abilityManager.IsInitialized() && IsAlive())
  10958. abilityManager.DrainFocus(amount);
  10959. }
  10960.  
  10961. public function GetOffenseStat():int
  10962. {
  10963. if(abilityManager && abilityManager.IsInitialized())
  10964. return ((W3PlayerAbilityManager)abilityManager).GetOffenseStat();
  10965.  
  10966. return 0;
  10967. }
  10968.  
  10969. public function GetDefenseStat():int
  10970. {
  10971. if(abilityManager && abilityManager.IsInitialized())
  10972. return ((W3PlayerAbilityManager)abilityManager).GetDefenseStat();
  10973.  
  10974. return 0;
  10975. }
  10976.  
  10977. public function GetSignsStat():float
  10978. {
  10979. if(abilityManager && abilityManager.IsInitialized())
  10980. return ((W3PlayerAbilityManager)abilityManager).GetSignsStat();
  10981.  
  10982. return 0;
  10983. }
  10984.  
  10985. ////////////////
  10986. // water
  10987. ////////////////
  10988.  
  10989. private var inWaterTrigger : bool;
  10990.  
  10991. event OnOceanTriggerEnter()
  10992. {
  10993. inWaterTrigger = true;
  10994. }
  10995.  
  10996. event OnOceanTriggerLeave()
  10997. {
  10998. inWaterTrigger = false;
  10999. }
  11000.  
  11001. public function IsInWaterTrigger() : bool
  11002. {
  11003. return inWaterTrigger;
  11004. }
  11005.  
  11006. //////////////////////////////////////////////////////////////////////////////////////////
  11007. // @Skills @Perks
  11008. //////////////////////////////////////////////////////////////////////////////////////////
  11009.  
  11010. public function GetSkillColor(skill : ESkill) : ESkillColor
  11011. {
  11012. if(abilityManager && abilityManager.IsInitialized())
  11013. return ((W3PlayerAbilityManager)abilityManager).GetSkillColor(skill);
  11014.  
  11015. return SC_None;
  11016. }
  11017.  
  11018. public function GetSkillSlotIndexFromSkill(skill : ESkill) : int
  11019. {
  11020. if(abilityManager && abilityManager.IsInitialized())
  11021. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIndexFromSkill(skill);
  11022.  
  11023. return -1;
  11024. }
  11025.  
  11026. public final function GetSkillSlotIndex(slotID : int, checkIfUnlocked : bool) : int
  11027. {
  11028. if(abilityManager && abilityManager.IsInitialized())
  11029. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIndex(slotID, checkIfUnlocked);
  11030.  
  11031. return -1;
  11032. }
  11033.  
  11034. public final function GetSkillSlotIDFromIndex(skillSlotIndex : int) : int
  11035. {
  11036. if(abilityManager && abilityManager.IsInitialized())
  11037. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIDFromIndex(skillSlotIndex);
  11038.  
  11039. return -1;
  11040. }
  11041.  
  11042. public function GetSkillSlotID(skill : ESkill) : int
  11043. {
  11044. if(abilityManager && abilityManager.IsInitialized())
  11045. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotID(skill);
  11046.  
  11047. return -1;
  11048. }
  11049.  
  11050. public function GetSkillGroupBonus(groupID : int) : name
  11051. {
  11052. if(abilityManager && abilityManager.IsInitialized())
  11053. return ((W3PlayerAbilityManager)abilityManager).GetGroupBonus(groupID);
  11054.  
  11055. return '';
  11056. }
  11057.  
  11058. public function GetGroupBonusCount(commonColor : ESkillColor,groupID : int) : int
  11059. {
  11060. if(abilityManager && abilityManager.IsInitialized())
  11061. return ((W3PlayerAbilityManager)abilityManager).GetGroupBonusCount(commonColor, groupID);
  11062.  
  11063. return 0;
  11064. }
  11065.  
  11066. public function GetMutagenSlotIDFromGroupID(groupID : int) : int
  11067. {
  11068. if(abilityManager && abilityManager.IsInitialized())
  11069. return ((W3PlayerAbilityManager)abilityManager).GetMutagenSlotIDFromGroupID(groupID);
  11070.  
  11071. return -1;
  11072. }
  11073.  
  11074. public function GetSkillLevel(skill : ESkill) : int
  11075. {
  11076. if(abilityManager && abilityManager.IsInitialized())
  11077. return ((W3PlayerAbilityManager)abilityManager).GetSkillLevel(skill);
  11078.  
  11079. return -1;
  11080. }
  11081.  
  11082. public function GetBoughtSkillLevel(skill : ESkill) : int
  11083. {
  11084. if(abilityManager && abilityManager.IsInitialized())
  11085. return ((W3PlayerAbilityManager)abilityManager).GetBoughtSkillLevel(skill);
  11086.  
  11087. return -1;
  11088. }
  11089.  
  11090. public function AddSkill(skill : ESkill, optional isTemporary : bool)
  11091. {
  11092. if(abilityManager && abilityManager.IsInitialized())
  11093. ((W3PlayerAbilityManager)abilityManager).AddSkill(skill, isTemporary);
  11094. }
  11095.  
  11096. public function AddMultipleSkills(skill : ESkill, optional number : int, optional isTemporary : bool)
  11097. {
  11098. var i : int;
  11099.  
  11100. if(number)
  11101. {
  11102. for( i=0; i<number; i+=1)
  11103. {
  11104. AddSkill(skill,isTemporary);
  11105. }
  11106. }
  11107. else
  11108. {
  11109. AddSkill(skill,isTemporary);
  11110. }
  11111. }
  11112.  
  11113. public function GetSkillAbilityName(skill : ESkill) : name
  11114. {
  11115. if(abilityManager && abilityManager.IsInitialized())
  11116. return ((W3PlayerAbilityManager)abilityManager).GetSkillAbilityName(skill);
  11117.  
  11118. return '';
  11119. }
  11120.  
  11121. public function HasStaminaToUseSkill(skill : ESkill, optional perSec : bool, optional signHack : bool) : bool
  11122. {
  11123. var ret : bool;
  11124. var cost : float;
  11125.  
  11126. cost = GetSkillStaminaUseCost(skill, perSec);
  11127.  
  11128. ret = ( CanUseSkill(skill) && (abilityManager.GetStat(BCS_Stamina, signHack) >= cost) );
  11129.  
  11130. //perk, using adrenaline instead of stamina when out of stamina
  11131. if(!ret && IsSkillSign(skill) && CanUseSkill(S_Perk_09) && GetStat(BCS_Focus) >= 1)
  11132. ret = true;
  11133.  
  11134. if(!ret)
  11135. {
  11136. SetCombatActionHeading( GetHeading() );
  11137. SetShowToLowStaminaIndication(cost);
  11138. }
  11139.  
  11140. return ret;
  11141. }
  11142.  
  11143. protected function GetSkillStaminaUseCost(skill : ESkill, optional perSec : bool) : float
  11144. {
  11145. if(abilityManager && abilityManager.IsInitialized())
  11146. return ((W3PlayerAbilityManager)abilityManager).GetSkillStaminaUseCost(skill, perSec);
  11147.  
  11148. return 0;
  11149. }
  11150.  
  11151. //works for perks and bookperks as well
  11152. public function GetSkillAttributeValue(skill : ESkill, attributeName : name, addBaseCharAttribute : bool, addSkillModsAttribute : bool) : SAbilityAttributeValue
  11153. {
  11154. var null : SAbilityAttributeValue;
  11155.  
  11156. if(abilityManager && abilityManager.IsInitialized())
  11157. return abilityManager.GetSkillAttributeValue(SkillEnumToName(skill), attributeName, addBaseCharAttribute, addSkillModsAttribute);
  11158.  
  11159. return null;
  11160. }
  11161.  
  11162. public function GetSkillLocalisationKeyName(skill : ESkill) : string // #B
  11163. {
  11164. if(abilityManager && abilityManager.IsInitialized())
  11165. return ((W3PlayerAbilityManager)abilityManager).GetSkillLocalisationKeyName(skill);
  11166.  
  11167. return "";
  11168. }
  11169.  
  11170. public function GetSkillLocalisationKeyDescription(skill : ESkill) : string // #B
  11171. {
  11172. if(abilityManager && abilityManager.IsInitialized())
  11173. return ((W3PlayerAbilityManager)abilityManager).GetSkillLocalisationKeyDescription(skill);
  11174.  
  11175. return "";
  11176. }
  11177.  
  11178. public function GetSkillIconPath(skill : ESkill) : string // #B
  11179. {
  11180. if(abilityManager && abilityManager.IsInitialized())
  11181. return ((W3PlayerAbilityManager)abilityManager).GetSkillIconPath(skill);
  11182.  
  11183. return "";
  11184. }
  11185.  
  11186. public function HasLearnedSkill(skill : ESkill) : bool
  11187. {
  11188. if(abilityManager && abilityManager.IsInitialized())
  11189. return ((W3PlayerAbilityManager)abilityManager).HasLearnedSkill(skill);
  11190.  
  11191. return false;
  11192. }
  11193.  
  11194. public function IsSkillEquipped(skill : ESkill) : bool
  11195. {
  11196. if(abilityManager && abilityManager.IsInitialized())
  11197. return ((W3PlayerAbilityManager)abilityManager).IsSkillEquipped(skill);
  11198.  
  11199. return false;
  11200. }
  11201.  
  11202. public function CanUseSkill(skill : ESkill) : bool
  11203. {
  11204. if(abilityManager && abilityManager.IsInitialized())
  11205. return ((W3PlayerAbilityManager)abilityManager).CanUseSkill(skill);
  11206.  
  11207. return false;
  11208. }
  11209.  
  11210. public function CanLearnSkill(skill : ESkill) : bool //#B
  11211. {
  11212. if(abilityManager && abilityManager.IsInitialized())
  11213. return ((W3PlayerAbilityManager)abilityManager).CanLearnSkill(skill);
  11214.  
  11215. return false;
  11216. }
  11217.  
  11218. public function HasSpentEnoughPoints(skill : ESkill) : bool //#J
  11219. {
  11220. if(abilityManager && abilityManager.IsInitialized())
  11221. return ((W3PlayerAbilityManager)abilityManager).HasSpentEnoughPoints(skill);
  11222.  
  11223. return false;
  11224. }
  11225.  
  11226. public function PathPointsForSkillsPath(skill : ESkill) : int //#J
  11227. {
  11228. if(abilityManager && abilityManager.IsInitialized())
  11229. return ((W3PlayerAbilityManager)abilityManager).PathPointsSpentInSkillPathOfSkill(skill);
  11230.  
  11231. return -1;
  11232. }
  11233.  
  11234. public function GetPlayerSkills() : array<SSkill> // #B
  11235. {
  11236. var null : array<SSkill>;
  11237.  
  11238. if(abilityManager && abilityManager.IsInitialized())
  11239. return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkills();
  11240.  
  11241. return null;
  11242. }
  11243.  
  11244. public function GetPlayerSkill(s : ESkill) : SSkill // #B
  11245. {
  11246. var null : SSkill;
  11247.  
  11248. if(abilityManager && abilityManager.IsInitialized())
  11249. return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkill(s);
  11250.  
  11251. return null;
  11252. }
  11253.  
  11254. public function GetSkillSubPathType(s : ESkill) : ESkillSubPath // #B
  11255. {
  11256. if(abilityManager && abilityManager.IsInitialized())
  11257. return ((W3PlayerAbilityManager)abilityManager).GetSkillSubPathType(s);
  11258.  
  11259. return ESSP_NotSet;
  11260. }
  11261.  
  11262. public function GetSkillSlotsCount() : int
  11263. {
  11264. if(abilityManager && abilityManager.IsInitialized())
  11265. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotsCount();
  11266.  
  11267. return 0;
  11268. }
  11269.  
  11270. public function GetSkillSlots() : array<SSkillSlot>
  11271. {
  11272. var null : array<SSkillSlot>;
  11273.  
  11274. if(abilityManager && abilityManager.IsInitialized())
  11275. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlots();
  11276.  
  11277. return null;
  11278. }
  11279.  
  11280. public function GetPlayerSkillMutagens() : array<SMutagenSlot>
  11281. {
  11282. var null : array<SMutagenSlot>;
  11283.  
  11284. if(abilityManager && abilityManager.IsInitialized())
  11285. return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkillMutagens();
  11286.  
  11287. return null;
  11288. }
  11289.  
  11290. // mutagens
  11291. //public function OnSkillMutagenEquipped()
  11292.  
  11293. public function BlockSkill(skill : ESkill, block : bool, optional cooldown : float) : bool
  11294. {
  11295. if(abilityManager && abilityManager.IsInitialized())
  11296. return ((W3PlayerAbilityManager)abilityManager).BlockSkill(skill, block, cooldown);
  11297.  
  11298. return false;
  11299. }
  11300.  
  11301. public function IsSkillBlocked(skill : ESkill) : bool
  11302. {
  11303. if(abilityManager && abilityManager.IsInitialized())
  11304. return ((W3PlayerAbilityManager)abilityManager).IsSkillBlocked(skill);
  11305.  
  11306. return false;
  11307. }
  11308.  
  11309. //returns true if succeeded
  11310. public function EquipSkill(skill : ESkill, slotID : int) : bool
  11311. {
  11312. var ret : bool;
  11313. var groupID : int;
  11314. var pam : W3PlayerAbilityManager;
  11315.  
  11316. if(abilityManager && abilityManager.IsInitialized())
  11317. {
  11318. pam = (W3PlayerAbilityManager)abilityManager;
  11319. ret = pam.EquipSkill(skill, slotID);
  11320. if(ret)
  11321. {
  11322. groupID = pam.GetSkillGroupIdFromSkillSlotId(slotID);
  11323. LogSkillColors("Equipped <<" + GetSkillColor(skill) + ">> skill <<" + skill + ">> to group <<" + groupID + ">>");
  11324. LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>");
  11325. LogSkillColors("");
  11326. }
  11327.  
  11328. return ret;
  11329. }
  11330.  
  11331. return false;
  11332. }
  11333.  
  11334. //returns true if succeeded
  11335. public function UnequipSkill(slotID : int) : bool
  11336. {
  11337. var ret : bool;
  11338. var groupID : int;
  11339. var skill : ESkill;
  11340. var pam : W3PlayerAbilityManager;
  11341.  
  11342. if(abilityManager && abilityManager.IsInitialized())
  11343. {
  11344. pam = (W3PlayerAbilityManager)abilityManager;
  11345. GetSkillOnSlot(slotID, skill);
  11346. ret = pam.UnequipSkill(slotID);
  11347. if(ret)
  11348. {
  11349. groupID = pam.GetSkillGroupIdFromSkillSlotId(slotID);
  11350. LogSkillColors("Unequipped <<" + GetSkillColor(skill) + ">> skill <<" + skill + ">> from group <<" + groupID + ">>");
  11351. LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>");
  11352. LogSkillColors("");
  11353. }
  11354. return ret;
  11355. }
  11356.  
  11357. return false;
  11358. }
  11359.  
  11360. //returns true if succeeded
  11361. public function GetSkillOnSlot(slotID : int, out skill : ESkill) : bool
  11362. {
  11363. if(abilityManager && abilityManager.IsInitialized())
  11364. return ((W3PlayerAbilityManager)abilityManager).GetSkillOnSlot(slotID, skill);
  11365.  
  11366. skill = S_SUndefined;
  11367. return false;
  11368. }
  11369.  
  11370. //returns random free skill slot (if any, otherwise -1)
  11371. public function GetFreeSkillSlot() : int
  11372. {
  11373. var i, size : int;
  11374. var skill : ESkill;
  11375.  
  11376. size = ((W3PlayerAbilityManager)abilityManager).GetSkillSlotsCount();
  11377. for(i=1; i<size; i+=1)
  11378. {
  11379. if(!GetSkillOnSlot(i, skill))
  11380. continue; //if slot locked
  11381.  
  11382. if(skill == S_SUndefined) //empty unlocked slot
  11383. return i;
  11384. }
  11385.  
  11386. return -1;
  11387. }
  11388.  
  11389. //////////////////
  11390. // @attacks
  11391. //////////////////
  11392.  
  11393. //performs an attack (mechanics wise) on given target and using given attack data
  11394. protected function Attack( hitTarget : CGameplayEntity, animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array<CActor>, attackAnimationName : name, hitTime : float, weaponEntity : CItemEntity)
  11395. {
  11396. var attackAction : W3Action_Attack;
  11397.  
  11398. if(!PrepareAttackAction(hitTarget, animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime, weaponEntity, attackAction))
  11399. return; //failed to create a valid attack action
  11400.  
  11401. if ( attackAction.IsParried() && ( ((CNewNPC)attackAction.victim).IsShielded(attackAction.attacker) || ((CNewNPC)attackAction.victim).SignalGameplayEventReturnInt('IsDefending',0) == 1 ) )
  11402. {
  11403. thePlayer.SetCanPlayHitAnim(true);
  11404. thePlayer.ReactToReflectedAttack(attackAction.victim);
  11405. }
  11406.  
  11407. theTelemetry.LogWithLabel( TE_FIGHT_PLAYER_ATTACKS, attackAction.GetAttackName() );
  11408.  
  11409. //process action
  11410. theGame.damageMgr.ProcessAction(attackAction);
  11411.  
  11412. delete attackAction;
  11413. }
  11414.  
  11415. public function IsHeavyAttack(attackName : name) : bool
  11416. {
  11417. var skill : ESkill;
  11418. var sup : bool;
  11419.  
  11420. sup = super.IsHeavyAttack(attackName);
  11421. if(sup)
  11422. return true;
  11423.  
  11424. if ( attackName == 'attack_heavy_special' )
  11425. return true;
  11426.  
  11427. skill = SkillNameToEnum(attackName);
  11428.  
  11429. return skill == S_Sword_2 || skill == S_Sword_s02;
  11430. }
  11431.  
  11432. public function IsLightAttack(attackName : name) : bool
  11433. {
  11434. var skill : ESkill;
  11435. var sup : bool;
  11436.  
  11437. sup = super.IsLightAttack(attackName);
  11438. if(sup)
  11439. return true;
  11440.  
  11441. skill = SkillNameToEnum(attackName);
  11442.  
  11443. return skill == S_Sword_1 || skill == S_Sword_s01;
  11444. }
  11445.  
  11446. public final function ProcessWeaponCollision()
  11447. {
  11448. var l_stateName : name;
  11449.  
  11450. var l_weaponPosition : Vector;
  11451. var l_weaponTipPos : Vector;
  11452. var l_collidingPosition : Vector;
  11453. var l_offset : Vector;
  11454. var l_normal : Vector;
  11455.  
  11456. var l_slotMatrix : Matrix;
  11457.  
  11458. var l_distance : float;
  11459.  
  11460. var l_materialName : name;
  11461. var l_hitComponent : CComponent;
  11462. var l_destructibleCmp : CDestructionSystemComponent;
  11463. var barrel : COilBarrelEntity;
  11464.  
  11465. //return;
  11466.  
  11467. if( isCurrentlyDodging )
  11468. return;
  11469.  
  11470. l_stateName = GetCurrentStateName();
  11471.  
  11472. if( !attackEventInProgress && l_stateName == 'CombatFists' )
  11473. return;
  11474.  
  11475. CalcEntitySlotMatrix('r_weapon', l_slotMatrix);
  11476.  
  11477. l_weaponPosition = MatrixGetTranslation( l_slotMatrix );
  11478.  
  11479. // Finding weapon's tip
  11480. switch( l_stateName )
  11481. {
  11482. case 'CombatFists':
  11483. l_offset = MatrixGetAxisX( l_slotMatrix );
  11484. l_offset = VecNormalize( l_offset ) * 0.25f;
  11485. break;
  11486. // sword
  11487. default:
  11488. l_offset = MatrixGetAxisZ( l_slotMatrix );
  11489. l_offset = VecNormalize( l_offset ) * 1.f;
  11490. break;
  11491. }
  11492.  
  11493. l_weaponTipPos = l_weaponPosition + l_offset;
  11494.  
  11495.  
  11496.  
  11497. if( !attackEventInProgress )
  11498. {
  11499. // If the weapon is not moving fast enough, do not play collision fx
  11500. if( m_LastWeaponTipPos == Vector ( 0, 0, 0 ) )
  11501. l_distance = 0;
  11502. else
  11503. l_distance = VecDistance( l_weaponTipPos, m_LastWeaponTipPos ) ;
  11504.  
  11505. //GetVisualDebug().AddText( 'LastWeaponTipText', "Last - dist: " + l_distance, m_LastWeaponTipPos, true, , Color( 249, 98, 158 ) );
  11506. //GetVisualDebug().AddArrow( 'OldDirectArrow', l_weaponPosition, m_LastWeaponTipPos , 0.8f, 0.1f, 0.2f, true, Color( 249, 98, 158 ) );
  11507.  
  11508. m_LastWeaponTipPos = l_weaponTipPos;
  11509. if( l_distance < 0.35f )
  11510. return;
  11511.  
  11512. }
  11513.  
  11514. /*GetVisualDebug().AddSphere( 'WeaponPosition', 0.1f, l_weaponPosition, true, Color( 249, 98, 158 ) );
  11515. GetVisualDebug().AddText( 'WeaponTipText', "Weapon Tip", l_weaponTipPos, true, , Color( 249, 98, 158 ) );
  11516. GetVisualDebug().AddArrow( 'CollisionArrow', l_weaponPosition, l_weaponTipPos , 0.8f, 0.1f, 0.2f, true, Color( 249, 98, 158 ) );*/
  11517.  
  11518. m_LastWeaponTipPos = l_weaponTipPos;
  11519.  
  11520. if ( !theGame.GetWorld().StaticTraceWithAdditionalInfo( l_weaponPosition, l_weaponTipPos, l_collidingPosition, l_normal, l_materialName, l_hitComponent, m_WeaponFXCollisionGroupNames ) )
  11521. {
  11522. // Test left fist
  11523. if( l_stateName == 'CombatFists' )
  11524. {
  11525. CalcEntitySlotMatrix('l_weapon', l_slotMatrix);
  11526. l_weaponPosition = MatrixGetTranslation( l_slotMatrix );
  11527. l_offset = MatrixGetAxisX( l_slotMatrix );
  11528. l_offset = VecNormalize( l_offset ) * 0.25f;
  11529. l_weaponTipPos = l_weaponPosition + l_offset;
  11530. if( !theGame.GetWorld().StaticTrace( l_weaponPosition, l_weaponTipPos, l_collidingPosition, l_normal, m_WeaponFXCollisionGroupNames ) )
  11531. {
  11532. return;
  11533. }
  11534. }
  11535. else
  11536. {
  11537. return;
  11538. }
  11539. }
  11540.  
  11541. if( !m_CollisionEffect )
  11542. {
  11543. m_CollisionEffect = theGame.CreateEntity( m_CollisionFxTemplate, l_collidingPosition, EulerAngles(0,0,0) );
  11544. }
  11545.  
  11546. m_CollisionEffect.Teleport( l_collidingPosition );
  11547.  
  11548. // Play hit effect
  11549. switch( l_stateName )
  11550. {
  11551. case 'CombatFists':
  11552. m_CollisionEffect.PlayEffect('fist');
  11553. break;
  11554. default:
  11555. // Optimisation because IsSwordWooden() is heavy (around 0.13 ms)
  11556. if( m_RefreshWeaponFXType )
  11557. {
  11558. m_PlayWoodenFX = IsSwordWooden();
  11559. m_RefreshWeaponFXType = false;
  11560. }
  11561.  
  11562. if( m_PlayWoodenFX )
  11563. {
  11564. m_CollisionEffect.PlayEffect('wood');
  11565. }
  11566. else
  11567. {
  11568. switch( l_materialName )
  11569. {
  11570. case 'wood_hollow':
  11571. case 'wood_debris':
  11572. case 'wood_solid':
  11573. m_CollisionEffect.PlayEffect('wood');
  11574. break;
  11575. case 'dirt_hard':
  11576. case 'dirt_soil':
  11577. case 'hay':
  11578. m_CollisionEffect.PlayEffect('fist');
  11579. break;
  11580. case 'stone_debris':
  11581. case 'stone_solid':
  11582. case 'clay_tile':
  11583. case 'gravel_large':
  11584. case 'gravel_small':
  11585. case 'metal':
  11586. case 'custom_sword':
  11587. m_CollisionEffect.PlayEffect('sparks');
  11588. break;
  11589. default:
  11590. m_CollisionEffect.PlayEffect('wood');
  11591. break;
  11592. }
  11593.  
  11594. }
  11595. break;
  11596. }
  11597.  
  11598. //don't ask...
  11599. if(l_hitComponent)
  11600. {
  11601. barrel = (COilBarrelEntity)l_hitComponent.GetEntity();
  11602. if(barrel)
  11603. {
  11604. barrel.OnFireHit(NULL); //sets barrel on fire so that it explodes in a few sec
  11605. return;
  11606. }
  11607. }
  11608.  
  11609. // Destroy destructibles
  11610. l_destructibleCmp = (CDestructionSystemComponent) l_hitComponent;
  11611. if( l_destructibleCmp && l_stateName != 'CombatFists' )
  11612. {
  11613. l_destructibleCmp.ApplyFracture();
  11614. }
  11615.  
  11616.  
  11617. //GetVisualDebug().AddText( 'collisionText', "Collision Here", l_collidingPosition, true, , Color( 249, 98, 158 ) );
  11618. }
  11619.  
  11620. public function ReactToReflectedAttack( target : CGameplayEntity)
  11621. {
  11622.  
  11623. var hp, dmg : float;
  11624. var action : W3DamageAction;
  11625.  
  11626. super.ReactToReflectedAttack(target);
  11627.  
  11628. if ( !((CNewNPC)target).IsShielded(this) )
  11629. {
  11630. action = new W3DamageAction in this;
  11631. action.Initialize(target,this,NULL,'',EHRT_Reflect,CPS_AttackPower,true,false,false,false);
  11632. action.AddEffectInfo(EET_Stagger);
  11633. action.SetProcessBuffsIfNoDamage(true);
  11634.  
  11635. theGame.damageMgr.ProcessAction( action );
  11636. delete action;
  11637. }
  11638.  
  11639. theGame.VibrateControllerLight();//player attack was reflected
  11640. }
  11641.  
  11642. //////////////////
  11643. // falling damage
  11644. //////////////////
  11645.  
  11646. //return false when not falling
  11647. function GetFallDist( out fallDist : float ) : bool
  11648. {
  11649. var fallDiff, jumpTotalDiff : float;
  11650.  
  11651. // Get the falling height
  11652. substateManager.m_SharedDataO.CalculateFallingHeights( fallDiff, jumpTotalDiff );
  11653.  
  11654. if ( fallDiff <= 0 )
  11655. return false;
  11656.  
  11657. fallDist = fallDiff;
  11658. return true;
  11659. }
  11660.  
  11661. function ApplyFallingDamage(heightDiff : float, optional reducing : bool) : float
  11662. {
  11663. var hpPerc : float;
  11664. var tut : STutorialMessage;
  11665.  
  11666. if ( IsSwimming() || FactsQuerySum("block_falling_damage") >= 1 )
  11667. return 0.0f;
  11668.  
  11669. hpPerc = super.ApplyFallingDamage( heightDiff, reducing );
  11670.  
  11671. if(hpPerc > 0)
  11672. {
  11673. theGame.VibrateControllerHard();//player falling damage
  11674.  
  11675. if(IsAlive())
  11676. {
  11677. if(ShouldProcessTutorial('TutorialFallingDamage'))
  11678. {
  11679. FactsAdd("tutorial_falling_damage");
  11680. }
  11681.  
  11682. if(FactsQuerySum("tutorial_falling_damage") > 1 && ShouldProcessTutorial('TutorialFallingRoll'))
  11683. {
  11684. //fill tutorial object data
  11685. tut.type = ETMT_Hint;
  11686. tut.tutorialScriptTag = 'TutorialFallingRoll';
  11687. tut.hintPositionType = ETHPT_DefaultGlobal;
  11688. tut.hintDurationType = ETHDT_Long;
  11689. tut.canBeShownInMenus = false;
  11690. tut.glossaryLink = false;
  11691. tut.markAsSeenOnShow = true;
  11692.  
  11693. //show tutorial
  11694. theGame.GetTutorialSystem().DisplayTutorial(tut);
  11695. }
  11696. }
  11697. }
  11698.  
  11699. return hpPerc;
  11700. }
  11701.  
  11702. //--------------------------------- STAMINA INDICATOR #B --------------------------------------
  11703.  
  11704. public function SetShowToLowStaminaIndication( value : float ) : void
  11705. {
  11706. fShowToLowStaminaIndication = value;
  11707. }
  11708.  
  11709. public function GetShowToLowStaminaIndication() : float
  11710. {
  11711. return fShowToLowStaminaIndication;
  11712. }
  11713.  
  11714. public final function IndicateTooLowAdrenaline()
  11715. {
  11716. SoundEvent("gui_no_adrenaline");
  11717. showTooLowAdrenaline = true;
  11718. }
  11719.  
  11720. /////////////////////////////////
  11721.  
  11722. protected function GotoCombatStateWithAction( initialAction : EInitialAction, optional initialBuff : CBaseGameplayEffect )
  11723. {
  11724. if ( this.GetCurrentActionType() == ActorAction_Exploration )
  11725. ActionCancelAll();
  11726.  
  11727. ((W3PlayerWitcherStateCombatFists)this.GetState('CombatFists')).SetupState( initialAction, initialBuff );
  11728. this.GotoState( 'CombatFists' );
  11729.  
  11730. }
  11731. ///////////////////////////////////////////////////////////////////////////////////////////
  11732. // COMBAT
  11733. public function IsThreat( actor : CActor, optional usePrecalcs : bool ) : bool
  11734. {
  11735. var npc : CNewNPC;
  11736. var dist : float;
  11737. var targetCapsuleHeight : float;
  11738. var isDistanceExpanded : bool;
  11739. var distanceToTarget : float;
  11740. var attitude : EAIAttitude;
  11741.  
  11742. if (!actor)
  11743. {
  11744. return false;
  11745. }
  11746.  
  11747. if ( finishableEnemiesList.Contains( actor ) )
  11748. {
  11749. return true;
  11750. }
  11751.  
  11752. if ( !actor.IsAlive() || actor.IsKnockedUnconscious() )
  11753. {
  11754. return false;
  11755. }
  11756.  
  11757. npc = (CNewNPC)actor;
  11758. if (npc && npc.IsHorse() )
  11759. {
  11760. return false;
  11761. }
  11762.  
  11763. if ( hostileEnemies.Contains( actor ) )
  11764. {
  11765. return true;
  11766. }
  11767.  
  11768. //MS: We add a tolerance to make geralt go to alertfar everytime he runs away from npc
  11769. if ( GetAttitudeBetween( this, actor ) == AIA_Hostile )
  11770. {
  11771. if ( usePrecalcs )
  11772. {
  11773. distanceToTarget = Distance2DBetweenCapsuleAndPoint( actor, this ) - targetingPrecalcs.playerRadius;
  11774. }
  11775. else
  11776. {
  11777. distanceToTarget = Distance2DBetweenCapsules( this, actor );
  11778. }
  11779.  
  11780. // shortDistance = findMoveTargetDist + 5.0f;
  11781. if ( distanceToTarget < findMoveTargetDist + 5.0f )
  11782. {
  11783. return true;
  11784. }
  11785.  
  11786. if ( actor.IsInCombat() || this.IsHardLockEnabled() )
  11787. {
  11788. targetCapsuleHeight = ( (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent() ).GetCapsuleHeight();
  11789. if ( targetCapsuleHeight >= 2.0f || npc.GetCurrentStance() == NS_Fly )
  11790. {
  11791. // expandedDistance = 40.f;
  11792. if ( distanceToTarget < 40.0f )
  11793. {
  11794. return true;
  11795. }
  11796. }
  11797. }
  11798. }
  11799.  
  11800. if ( actor.GetAttitudeGroup() == 'npc_charmed' )
  11801. {
  11802. if ( theGame.GetGlobalAttitude( GetBaseAttitudeGroup(), actor.GetBaseAttitudeGroup() ) == AIA_Hostile )
  11803. {
  11804. return true;
  11805. }
  11806. }
  11807.  
  11808. return false;
  11809. }
  11810.  
  11811. function SetBIsCombatActionAllowed ( flag : bool )
  11812. {
  11813. bIsCombatActionAllowed = flag;
  11814.  
  11815. if ( !flag )
  11816. {
  11817. SetBIsInCombatAction(true);
  11818. }
  11819. else
  11820. {
  11821. this.ProcessLAxisCaching();
  11822. //UnblockAction(EIAB_Interactions, 'InsideCombatAction' );
  11823. }
  11824.  
  11825. //LogChannel('combatActionAllowed', "Is SET TO: " + flag );
  11826. }
  11827.  
  11828. function GetBIsCombatActionAllowed() : bool
  11829. {
  11830. return bIsCombatActionAllowed;
  11831. }
  11832.  
  11833. function SetCombatAction( action : EBufferActionType )
  11834. {
  11835. currentCombatAction = action;
  11836. }
  11837.  
  11838. function GetCombatAction() : EBufferActionType
  11839. {
  11840. return currentCombatAction;
  11841. }
  11842.  
  11843. protected function WhenCombatActionIsFinished()
  11844. {
  11845. if(IsThrowingItem() || IsThrowingItemWithAim() )
  11846. {
  11847. if(inv.IsItemBomb(selectedItemId))
  11848. {
  11849. BombThrowAbort();
  11850. }
  11851. else
  11852. {
  11853. ThrowingAbort();
  11854. }
  11855. }
  11856.  
  11857. if ( this.GetCurrentStateName() != 'DismountHorse' )
  11858. OnRangedForceHolster( true );
  11859.  
  11860. //SetBehaviorVariable( 'combatActionType', (int)CAT_None2);
  11861. }
  11862.  
  11863. public function IsInCombatAction_Attack(): bool
  11864. {
  11865. if ( IsInCombatAction_NonSpecialAttack() || IsInCombatAction_SpecialAttack() )
  11866. return true;
  11867. else
  11868. return false;
  11869. }
  11870.  
  11871. public function IsInCombatAction_NonSpecialAttack(): bool
  11872. {
  11873. if ( IsInCombatAction() && ( GetCombatAction() == EBAT_LightAttack || GetCombatAction() == EBAT_HeavyAttack ) )
  11874. return true;
  11875. else
  11876. return false;
  11877. }
  11878.  
  11879. public function IsInSpecificCombatAction ( specificCombatAction : EBufferActionType ) : bool
  11880. {
  11881. if ( IsInCombatAction() && GetCombatAction() == specificCombatAction )
  11882. return true;
  11883. else
  11884. return false;
  11885. }
  11886.  
  11887. public function IsInRunAnimation() : bool
  11888. {
  11889. return isInRunAnimation;
  11890. }
  11891.  
  11892. //I need to call it after scene ends thats why it's public. PF
  11893. public function SetCombatIdleStance( stance : float )
  11894. {
  11895. SetBehaviorVariable( 'combatIdleStance', stance );
  11896. SetBehaviorVariable( 'CombatStanceForOverlay', stance );
  11897.  
  11898. if ( stance == 0.f )
  11899. LogChannel( 'ComboInput', "combatIdleStance = Left" );
  11900. else
  11901. LogChannel( 'ComboInput', "combatIdleStance = Right" );
  11902. }
  11903.  
  11904. public function GetCombatIdleStance() : float
  11905. {
  11906. // 0.f == Left
  11907. return GetBehaviorVariable( 'combatIdleStance' );
  11908. }
  11909.  
  11910. protected var isRotatingInPlace : bool;
  11911. event OnRotateInPlaceStart()
  11912. {
  11913. isRotatingInPlace = true;
  11914. }
  11915.  
  11916. event OnRotateInPlaceEnd()
  11917. {
  11918. isRotatingInPlace = false;
  11919. }
  11920.  
  11921. event OnFullyBlendedIdle()
  11922. {
  11923. if ( bLAxisReleased )
  11924. {
  11925. ResetRawPlayerHeading();
  11926. ResetCachedRawPlayerHeading();
  11927. defaultLocomotionController.ResetMoveDirection();
  11928. }
  11929. }
  11930.  
  11931. event OnRunLoopStart()
  11932. {
  11933. EnableRunCamera( true );
  11934. }
  11935.  
  11936. event OnRunLoopEnd()
  11937. {
  11938. EnableRunCamera( false );
  11939. }
  11940.  
  11941. event OnCombatActionStartBehgraph()
  11942. {
  11943. var buff : CBaseGameplayEffect;
  11944. var action : EBufferActionType;
  11945. var cost, delay : float;
  11946.  
  11947. // Block saves
  11948. //theGame.CreateNoSaveLock( noSaveLockCombatActionName, noSaveLockCombatAction, true );
  11949.  
  11950. OnCombatActionStart();
  11951.  
  11952. //Pause the stamina regen for as long as we're doing combat actions.
  11953. //Pause only once to avoid the pause counter from increasing with each lock
  11954. buff = GetBuff(EET_AutoStaminaRegen);
  11955.  
  11956. action = PerformingCombatAction();
  11957. switch ( action )
  11958. {
  11959. case EBAT_LightAttack :
  11960. {
  11961. abilityManager.GetStaminaActionCost(ESAT_LightAttack, cost, delay);
  11962. } break;
  11963. case EBAT_HeavyAttack :
  11964. {
  11965. abilityManager.GetStaminaActionCost(ESAT_HeavyAttack, cost, delay);
  11966. } break;
  11967. case EBAT_ItemUse :
  11968. {
  11969. abilityManager.GetStaminaActionCost(ESAT_UsableItem, cost, delay);
  11970. } break;
  11971. case EBAT_Parry :
  11972. {
  11973. abilityManager.GetStaminaActionCost(ESAT_Parry, cost, delay);
  11974. } break;
  11975. case EBAT_Dodge :
  11976. {
  11977. abilityManager.GetStaminaActionCost(ESAT_Dodge, cost, delay);
  11978. } break;
  11979. case EBAT_Roll :
  11980. abilityManager.GetStaminaActionCost(ESAT_Roll, cost, delay);
  11981. break;
  11982. case EBAT_SpecialAttack_Light :
  11983. {
  11984. abilityManager.GetStaminaActionCost(ESAT_Ability, cost, delay, 0,0, GetSkillAbilityName(S_Sword_s01));
  11985. } break;
  11986. case EBAT_SpecialAttack_Heavy :
  11987. {
  11988. abilityManager.GetStaminaActionCost(ESAT_Ability, cost, delay, 0,0, GetSkillAbilityName(S_Sword_s02));
  11989. } break;
  11990. case EBAT_Roll :
  11991. {
  11992. abilityManager.GetStaminaActionCost(ESAT_Evade, cost, delay);
  11993. } break;
  11994. /*
  11995. case EBAT_Ciri_SpecialAttack :
  11996. {
  11997. cost = GetStaminaActionCost();
  11998. } break;
  11999. */
  12000. default :
  12001. ;
  12002. }
  12003.  
  12004.  
  12005.  
  12006. }
  12007.  
  12008. public function HolsterUsableItem() : bool
  12009. {
  12010. return holsterUsableItem;
  12011. }
  12012.  
  12013. private var isInGuardedState : bool;
  12014. public function IsInGuardedState() : bool
  12015. {
  12016. return isInGuardedState;
  12017. }
  12018.  
  12019. event OnGuardedStart()
  12020. {
  12021. isInParryOrCounter = true;
  12022. isInGuardedState = true;
  12023. }
  12024.  
  12025. event OnGuardedEnd()
  12026. {
  12027. isInParryOrCounter = false;
  12028. isInGuardedState = false;
  12029. }
  12030.  
  12031. private var restoreUsableItem : bool;
  12032. private var holsterUsableItem : bool;
  12033. event OnCombatActionStart()
  12034. {
  12035. //Block Actions
  12036. //BlockAction( EIAB_DrawWeapon, 'OnCombatActionStart' );
  12037. BlockAction( EIAB_UsableItem, 'OnCombatActionStart' );
  12038. BlockAction( EIAB_CallHorse, 'OnCombatActionStart' );
  12039.  
  12040. /*if ( !IsGuarded() )
  12041. SetParryTarget( NULL );*/
  12042.  
  12043. LogChannel('combatActionAllowed',"FALSE OnCombatActionStart");
  12044. SetBIsCombatActionAllowed( false );
  12045. SetBIsInputAllowed( false, 'OnCombatActionStart' );
  12046. //lastAxisInputIsMovement = true;
  12047.  
  12048. ClearFinishableEnemyList( 0.f, 0 );
  12049.  
  12050. bIsInHitAnim = false;
  12051.  
  12052. //Holster Crossbow if it's held
  12053. //if ( inv.IsItemCrossbow( inv.GetItemFromSlot( 'l_weapon' ) ) )//&& GetBehaviorVariable( 'combatActionType' ) != (int)CAT_Crossbow )
  12054. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  12055. {
  12056. CleanCombatActionBuffer();
  12057. SetIsAimingCrossbow( false );
  12058. OnRangedForceHolster( false, true );
  12059. }
  12060.  
  12061. //Holster UsableItem if it's held
  12062. holsterUsableItem = false;
  12063. if ( thePlayer.IsHoldingItemInLHand() ) // && !thePlayer.IsUsableItemLBlocked() )
  12064. {
  12065. if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign )
  12066. holsterUsableItem = true;
  12067. else if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack )
  12068. {
  12069. if ( this.GetCurrentStateName() == 'CombatFists' )
  12070. holsterUsableItem = true;
  12071. }
  12072. }
  12073.  
  12074. if ( holsterUsableItem )
  12075. {
  12076. thePlayer.SetPlayerActionToRestore ( PATR_None );
  12077. thePlayer.OnUseSelectedItem( true );
  12078.  
  12079. restoreUsableItem = true;
  12080. }
  12081.  
  12082. //Stop Geralt from automatically attacking while in AttackApproach when Player performs a non-attack combat action
  12083. if ( GetBehaviorVariable( 'combatActionType' ) != (int)CAT_Attack && GetBehaviorVariable( 'combatActionType' ) != (int)CAT_PreAttack )
  12084. {
  12085. RemoveTimer( 'ProcessAttackTimer' );
  12086. RemoveTimer( 'AttackTimerEnd' );
  12087. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12088. }
  12089. else
  12090. {
  12091. //MS: Do not remove this!! The attack to idle transition states will not work correctly if you change weapon mid-attack.
  12092. BlockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12093. }
  12094.  
  12095. //GetMovingAgentComponent().SnapToNavigableSpace(true);
  12096. }
  12097.  
  12098. var isInParryOrCounter : bool;
  12099. event OnParryOrCounterStart()
  12100. {
  12101. isInParryOrCounter = true;
  12102. OnCombatActionStartBehgraph();
  12103. }
  12104.  
  12105. event OnParryOrCounterEnd()
  12106. {
  12107. isInParryOrCounter = false;
  12108. OnCombatActionEnd();
  12109. SetBIsInCombatAction( false );
  12110. }
  12111.  
  12112. //called when a combat action is completed (e.g. single hit in a combo sequence)
  12113. event OnCombatActionEnd()
  12114. {
  12115. var item : SItemUniqueId;
  12116. var combatActionType : float;
  12117.  
  12118. super.OnCombatActionEnd();
  12119.  
  12120.  
  12121. //Unblock Actions
  12122. BlockAllActions( 'OnCombatActionStart', false );
  12123.  
  12124. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12125.  
  12126. //why? this way after EACH attack you reset it - what's the point then?
  12127. //ResetUninterruptedHitsCount();
  12128.  
  12129. oTCameraOffset = 0.f;
  12130. oTCameraPitchOffset = 0.f;
  12131.  
  12132. //LogChannel('combatActionAllowed',"TRUE OnCombatActionEnd");
  12133. SetBIsCombatActionAllowed( true );
  12134. //reapply critical buff if any
  12135. //Z ReapplyCriticalBuff();
  12136. SetBIsInputAllowed( true, 'OnCombatActionEnd' );
  12137. SetCanPlayHitAnim( true );
  12138. EnableFindTarget( true );
  12139.  
  12140.  
  12141.  
  12142.  
  12143. SetFinisherVictim( NULL );
  12144.  
  12145. OnBlockAllCombatTickets( false );
  12146.  
  12147. LogStamina("CombatActionEnd");
  12148.  
  12149. //GetMovingAgentComponent().SnapToNavigableSpace(false);
  12150.  
  12151. SetAttackActionName('');
  12152. combatActionType = GetBehaviorVariable('combatActionType');
  12153.  
  12154. //clean-up after special attack heavy finishes
  12155. if(GetBehaviorVariable('combatActionType') == (int)CAT_SpecialAttack)
  12156. {
  12157. theGame.GetGameCamera().StopAnimation( 'camera_shake_loop_lvl1_1' );
  12158. OnSpecialAttackHeavyActionProcess();
  12159. }
  12160. // Do we need to interrupt?
  12161. substateManager.ReactToChanceToFallAndSlide();
  12162. }
  12163.  
  12164. event OnCombatActionFriendlyStart()
  12165. {
  12166. SetBIsInCombatActionFriendly(true);
  12167. OnCombatActionStart();
  12168. }
  12169.  
  12170. event OnCombatActionFriendlyEnd()
  12171. {
  12172. SetBIsInCombatActionFriendly(false);
  12173. OnCombatActionEnd();
  12174. SetBIsInCombatAction(false);
  12175. //RaiseForceEvent( 'ForceIdle' );
  12176. }
  12177.  
  12178. event OnHitStart()
  12179. {
  12180. var timeLeft : float;
  12181. var currentEffects : array<CBaseGameplayEffect>;
  12182. var none : SAbilityAttributeValue;
  12183.  
  12184. CancelHoldAttacks();
  12185. WhenCombatActionIsFinished();
  12186. if ( isInFinisher )
  12187. {
  12188. if ( finisherTarget )
  12189. ( (CNewNPC)finisherTarget ).SignalGameplayEvent( 'FinisherInterrupt' );
  12190. isInFinisher = false;
  12191. finisherTarget = NULL;
  12192. SetBIsCombatActionAllowed( true );
  12193. }
  12194.  
  12195. bIsInHitAnim = true;
  12196.  
  12197. OnCombatActionStart(); //"because it's needed"
  12198.  
  12199. //OnCombatActionStart pauses the regen and we don't want that
  12200. ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction');
  12201.  
  12202. if( GetHealthPercents() < 0.3f )
  12203. {
  12204. PlayBattleCry('BattleCryBadSituation', 0.10f, true );
  12205. }
  12206. else
  12207. {
  12208. PlayBattleCry('BattleCryBadSituation', 0.05f, true );
  12209. }
  12210. }
  12211.  
  12212. event OnHitStartSwimming()
  12213. {
  12214. OnRangedForceHolster( true, true, false );
  12215. }
  12216.  
  12217. private var finisherSaveLock : int;
  12218. event OnFinisherStart()
  12219. {
  12220. var currentEffects : array<CBaseGameplayEffect>;
  12221.  
  12222. theGame.CreateNoSaveLock("Finisher",finisherSaveLock,true,false);
  12223.  
  12224. isInFinisher = true;
  12225.  
  12226. finisherTarget = slideTarget;
  12227. OnCombatActionStart();
  12228.  
  12229. CancelHoldAttacks();
  12230.  
  12231. PlayFinisherCameraAnimation( theGame.GetSyncAnimManager().GetFinisherCameraAnimName() );
  12232. this.AddAnimEventCallback('SyncEvent','OnFinisherAnimEvent_SyncEvent');
  12233. SetImmortalityMode( AIM_Invulnerable, AIC_SyncedAnim );
  12234. }
  12235.  
  12236. public function IsPerformingFinisher() : bool
  12237. {
  12238. return isInFinisher;
  12239. }
  12240.  
  12241. private function PlayFinisherCameraAnimation( cameraAnimName : name )
  12242. {
  12243. var camera : CCustomCamera = theGame.GetGameCamera();
  12244. var animation : SCameraAnimationDefinition;
  12245.  
  12246. if (IsLastEnemyKilled() && theGame.GetWorld().NavigationCircleTest( this.GetWorldPosition(), 3.f ) )
  12247. {
  12248. camera.StopAnimation('camera_shake_hit_lvl3_1' );
  12249.  
  12250. animation.animation = cameraAnimName;
  12251. animation.priority = CAP_Highest;
  12252. animation.blendIn = 0.15f;
  12253. animation.blendOut = 1.0f;
  12254. animation.weight = 1.f;
  12255. animation.speed = 1.0f;
  12256. animation.reset = true;
  12257.  
  12258. camera.PlayAnimation( animation );
  12259. //thePlayer.AddTimer( 'RemoveFinisherCameraAnimationCheck', 0.01, true );
  12260.  
  12261. thePlayer.EnableManualCameraControl( false, 'Finisher' );
  12262. }
  12263. }
  12264.  
  12265. public function IsLastEnemyKilled() : bool
  12266. {
  12267. var tempMoveTargets : array<CActor>;
  12268.  
  12269. FindMoveTarget();
  12270. tempMoveTargets = GetMoveTargets();
  12271. if ( tempMoveTargets.Size() <= 0 || !thePlayer.IsThreat( tempMoveTargets[0] ) )
  12272. return true;
  12273.  
  12274. return false;
  12275. }
  12276.  
  12277. event OnFinisherAnimEvent_SyncEvent( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  12278. {
  12279. if ( finisherTarget )
  12280. ( (CNewNPC)finisherTarget ).SignalGameplayEvent('FinisherKill');
  12281. finisherTarget = NULL;
  12282. }
  12283.  
  12284. event OnFinisherEnd()
  12285. {
  12286. isInFinisher = false;
  12287. finisherTarget = NULL;
  12288.  
  12289. theGame.ReleaseNoSaveLock(finisherSaveLock);
  12290.  
  12291. this.RemoveAnimEventCallback('SyncEvent');
  12292.  
  12293. //SetIsPerformingPhaseChangeAnimation( false ); // for eredin fight
  12294. SetImmortalityMode( AIM_None, AIC_SyncedAnim );
  12295. theGame.RemoveTimeScale( 'AnimEventSlomoMo' );
  12296. AddTimer( 'FinisherEndEnableCamera', 0.5f );
  12297. //OnBlockAllCombatTickets( false );
  12298. OnCombatActionEnd();
  12299. OnCombatActionEndComplete();
  12300. }
  12301.  
  12302. private timer function FinisherEndEnableCamera( dt : float, id : int )
  12303. {
  12304. thePlayer.EnableManualCameraControl( true, 'Finisher' );
  12305. }
  12306.  
  12307. public function SpawnFinisherBlood()
  12308. {
  12309. var weaponEntity : CEntity;
  12310. var weaponSlotMatrix : Matrix;
  12311. var bloodFxPos : Vector;
  12312. var bloodFxRot : EulerAngles;
  12313. var tempEntity : CEntity;
  12314.  
  12315. weaponEntity = this.GetInventory().GetItemEntityUnsafe( GetInventory().GetItemFromSlot('r_weapon') );
  12316. weaponEntity.CalcEntitySlotMatrix( 'blood_fx_point', weaponSlotMatrix );
  12317. bloodFxPos = MatrixGetTranslation( weaponSlotMatrix );
  12318. bloodFxRot = this.GetWorldRotation();//MatrixGetRotation( weaponSlotMatrix );
  12319. tempEntity = theGame.CreateEntity( (CEntityTemplate)LoadResource('finisher_blood'), bloodFxPos, bloodFxRot);
  12320. tempEntity.PlayEffect('crawl_blood');
  12321. }
  12322.  
  12323. //called when all combat actions have ended (e.g. whole combo)
  12324. event OnCombatActionEndComplete()
  12325. {
  12326. var buff : CBaseGameplayEffect;
  12327.  
  12328. buff = ChooseCurrentCriticalBuffForAnim();
  12329. SetCombatAction( EBAT_EMPTY );
  12330.  
  12331. //Unblock Actions what you wann
  12332. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart' );
  12333. UnblockAction( EIAB_OpenInventory, 'OnCombatActionStart' );
  12334. UnblockAction( EIAB_UsableItem, 'OnCombatActionStart' );
  12335.  
  12336. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12337.  
  12338. SetUnpushableTarget( NULL );
  12339. SetBIsInCombatAction(false);
  12340. SetIsCurrentlyDodging(false);
  12341. SetMoveTargetChangeAllowed( true );
  12342. SetCanPlayHitAnim( true );
  12343.  
  12344. SetFinisherVictim( NULL );
  12345.  
  12346. this.RemoveBuffImmunity(EET_Burning, 'AnimEvent_RemoveBurning');
  12347.  
  12348. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' && !buff )
  12349. {
  12350. ClearCustomOrientationInfoStack();
  12351. SetSlideTarget( NULL );
  12352. }
  12353.  
  12354. UnblockAction( EIAB_Crossbow, 'OnForceHolster' );
  12355.  
  12356. specialAttackCamera = false;
  12357.  
  12358. bIsRollAllowed = false;
  12359.  
  12360. if ( bLAxisReleased )
  12361. {
  12362. ResetRawPlayerHeading();
  12363. ResetCachedRawPlayerHeading();
  12364. }
  12365.  
  12366. //reapply critical buff if any
  12367. ReapplyCriticalBuff();
  12368. SetBIsInputAllowed( true, 'OnCombatActionEndComplete' );
  12369.  
  12370. //stamina regen is paused as long as we are doing some combat actions
  12371. ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction');
  12372.  
  12373. bIsInHitAnim = false;
  12374.  
  12375. SetBIsCombatActionAllowed( true );
  12376.  
  12377. m_LastWeaponTipPos = Vector(0, 0, 0, 0 );
  12378.  
  12379. //free tickets
  12380. this.AddTimer('FreeTickets',3.f,false);
  12381.  
  12382. // remove save lock
  12383. //theGame.ReleaseNoSaveLockByName( noSaveLockCombatActionName );
  12384. }
  12385.  
  12386. event OnMovementFullyBlended()
  12387. {
  12388. SetBehaviorVariable( 'isPerformingSpecialAttack', 0.f );
  12389.  
  12390. if ( restoreUsableItem )
  12391. {
  12392. restoreUsableItem = false;
  12393. SetPlayerActionToRestore ( PATR_Default );
  12394. OnUseSelectedItem();
  12395. }
  12396. }
  12397.  
  12398. event OnCombatMovementStart()
  12399. {
  12400. SetCombatIdleStance( 1.f );
  12401. OnCombatActionEndComplete();
  12402. }
  12403.  
  12404. timer function FreeTickets( dt : float, id : int )
  12405. {
  12406. FreeTicketAtCombatTarget();
  12407. }
  12408.  
  12409.  
  12410. /*
  12411. These declarations are needed here only to call event with the same name inside combat state (there's no other way to call it!).
  12412. */
  12413. event OnGuardedReleased(){}
  12414. event OnPerformAttack( playerAttackType : name ){}
  12415. event OnPerformEvade( playerEvadeType : EPlayerEvadeType ){}
  12416. event OnInterruptAttack(){}
  12417. event OnPerformGuard(){}
  12418. event OnSpawnHorse(){}
  12419. event OnDismountActionScriptCallback(){}
  12420.  
  12421. event OnHorseSummonStart()
  12422. {
  12423. thePlayer.BlockAction(EIAB_CallHorse, 'HorseSummon');
  12424. thePlayer.BlockAction(EIAB_Signs, 'HorseSummon');
  12425. thePlayer.BlockAction(EIAB_Crossbow, 'HorseSummon');
  12426. thePlayer.BlockAction(EIAB_UsableItem, 'HorseSummon');
  12427. thePlayer.BlockAction(EIAB_ThrowBomb, 'HorseSummon');
  12428. thePlayer.BlockAction(EIAB_SwordAttack, 'HorseSummon');
  12429. thePlayer.BlockAction(EIAB_Jump, 'HorseSummon');
  12430. thePlayer.BlockAction(EIAB_Dodge, 'HorseSummon');
  12431. thePlayer.BlockAction(EIAB_LightAttacks, 'HorseSummon');
  12432. thePlayer.BlockAction(EIAB_HeavyAttacks, 'HorseSummon');
  12433. thePlayer.BlockAction(EIAB_SpecialAttackLight, 'HorseSummon');
  12434. thePlayer.BlockAction(EIAB_SpecialAttackHeavy, 'HorseSummon');
  12435.  
  12436. horseSummonTimeStamp = theGame.GetEngineTimeAsSeconds();
  12437. }
  12438.  
  12439. event OnHorseSummonStop()
  12440. {
  12441. thePlayer.BlockAllActions('HorseSummon',false);
  12442. }
  12443.  
  12444. /*
  12445. CombatAction events when on vehicles
  12446. */
  12447. event OnCombatActionStartVehicle( action : EVehicleCombatAction )
  12448. {
  12449. this.SetBIsCombatActionAllowed( false );
  12450.  
  12451. if ( action != EHCA_ShootCrossbow )
  12452. {
  12453. SetIsAimingCrossbow( false );
  12454. OnRangedForceHolster();
  12455. }
  12456. }
  12457.  
  12458. event OnCombatActionEndVehicle()
  12459. {
  12460. this.SetBIsCombatActionAllowed( true );
  12461. }
  12462.  
  12463. ////////////////////////////////////////////////////////////////////////////////////////////
  12464. /////////////////////////// @CRITICAL STATES /////////////////////////////////////////////
  12465. ////////////////////////////////////////////////////////////////////////////////////////////
  12466.  
  12467. protected function CriticalBuffInformBehavior(buff : CBaseGameplayEffect)
  12468. {
  12469. /*if ( this.GetCurrentStateName() == 'Exploration' || this.GetCurrentStateName() == 'AimThrow' )
  12470. GotoCombatStateWithAction( IA_CriticalState, buff );
  12471. else
  12472. {*/
  12473. if( !CanAnimationReactToCriticalState( buff ) )
  12474. {
  12475. return;
  12476. }
  12477.  
  12478. // if ( IsInCombatAction() )
  12479. // RaiseEvent('ForceBlendOut');
  12480.  
  12481. SetBehaviorVariable( 'CriticalStateType', (int)GetBuffCriticalType(buff) );
  12482. SetBehaviorVariable( 'bCriticalState', 1);
  12483.  
  12484. if(CriticalBuffUsesFullBodyAnim(buff))
  12485. RaiseEvent('CriticalState');
  12486.  
  12487. SetBehaviorVariable( 'IsInAir', (int)IsInAir());
  12488.  
  12489. LogCritical("Sending player critical state event for <<" + buff.GetEffectType() + ">>");
  12490.  
  12491. //}
  12492. }
  12493.  
  12494. private function CanAnimationReactToCriticalState( buff : CBaseGameplayEffect ) : bool
  12495. {
  12496. var buffCritical : W3CriticalEffect;
  12497. var buffCriticalDOT : W3CriticalDOTEffect;
  12498. var isHeavyCritical : bool;
  12499.  
  12500. isHeavyCritical = false;
  12501.  
  12502. // Find out if it is a heavy critical state
  12503. buffCritical = ( W3CriticalEffect ) buff;
  12504. if( buffCritical )
  12505. {
  12506. isHeavyCritical = buffCritical.explorationStateHandling == ECH_HandleNow;
  12507. }
  12508. else
  12509. {
  12510. buffCriticalDOT = ( W3CriticalDOTEffect ) buff;
  12511. if( buffCriticalDOT )
  12512. {
  12513. isHeavyCritical = buffCriticalDOT.explorationStateHandling == ECH_HandleNow;
  12514. }
  12515. }
  12516.  
  12517. // If it is not, we may skip it
  12518. if( !isHeavyCritical )
  12519. {
  12520. if( !CanReactToCriticalState() )
  12521. {
  12522. return false;
  12523. }
  12524. }
  12525.  
  12526. return true;
  12527. }
  12528.  
  12529. public function CanReactToCriticalState() : bool
  12530. {
  12531. return substateManager.CanReactToHardCriticalState();
  12532. }
  12533.  
  12534. event OnCriticalStateAnimStart()
  12535. {
  12536. var heading : float;
  12537. var newCritical : ECriticalStateType;
  12538. var newReqCS : CBaseGameplayEffect;
  12539.  
  12540. OnCombatActionEndComplete();
  12541.  
  12542. //abort throwing if super was processed properly
  12543. newReqCS = newRequestedCS;
  12544. if(super.OnCriticalStateAnimStart())
  12545. {
  12546. //WhenCombatActionIsFinished();
  12547. RemoveTimer( 'IsItemUseInputHeld' );
  12548. keepRequestingCriticalAnimStart = false;
  12549. CancelHoldAttacks();
  12550.  
  12551. //knockdown direction
  12552. // No knockdown when using a vehicule: the vehicule will handle the knock down logic
  12553. //PFTODO
  12554. //we need this for NPCs also (knockdown dir)
  12555. if(!IsUsingVehicle())
  12556. {
  12557. newCritical = GetBuffCriticalType(newReqCS);
  12558. if(newCritical == ECST_HeavyKnockdown
  12559. || newCritical == ECST_Knockdown
  12560. || newCritical == ECST_Stagger
  12561. || newCritical == ECST_Ragdoll
  12562. || newCritical == ECST_LongStagger )
  12563. {
  12564. if(newReqCS.GetCreator())
  12565. heading = VecHeading(newReqCS.GetCreator().GetWorldPosition() - GetWorldPosition());
  12566. else
  12567. heading = GetHeading();
  12568.  
  12569. //this.GetMovingAgentComponent().GetMovementAdjustor().CancelAll();
  12570. SetCustomRotation( 'Knockdown', heading, 2160.f, 0.1f, true );
  12571.  
  12572. if ( newCritical != ECST_Stagger && newCritical != ECST_LongStagger )
  12573. substateManager.ReactOnCriticalState( true );
  12574. }
  12575. }
  12576.  
  12577. return true;
  12578. }
  12579.  
  12580. //SetBehaviorVariable( 'bCriticalStopped', 1);
  12581. return false;
  12582. }
  12583.  
  12584. /*
  12585. Called when new critical effect has started
  12586. This will interrupt current critical state
  12587.  
  12588. returns true if the effect got fired properly
  12589. */
  12590. public function StartCSAnim(buff : CBaseGameplayEffect) : bool
  12591. {
  12592. SetBehaviorVariable( 'bCriticalStopped', 0 );
  12593.  
  12594. if(super.StartCSAnim(buff))
  12595. {
  12596. if(!CriticalBuffUsesFullBodyAnim(buff))
  12597. {
  12598. OnCriticalStateAnimStart();
  12599. }
  12600.  
  12601. ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction');
  12602.  
  12603. keepRequestingCriticalAnimStart = true;
  12604. AddTimer('RequestCriticalAnimStart', 0, true);
  12605. //RequestCriticalAnimStart(0);
  12606.  
  12607. return true;
  12608. }
  12609.  
  12610. return false;
  12611. }
  12612.  
  12613. public function CriticalEffectAnimationInterrupted(reason : string) : bool
  12614. {
  12615. var ret : bool; //for debug
  12616.  
  12617. LogCriticalPlayer("R4Player.CriticalEffectAnimationInterrupted() - because: " + reason);
  12618.  
  12619. ret = super.CriticalEffectAnimationInterrupted(reason);
  12620.  
  12621. if(ret)
  12622. {
  12623. keepRequestingCriticalAnimStart = false;
  12624. }
  12625.  
  12626. substateManager.ReactOnCriticalState( false );
  12627.  
  12628. return ret;
  12629. }
  12630.  
  12631. public function CriticalStateAnimStopped(forceRemoveBuff : bool)
  12632. {
  12633. LogCriticalPlayer("R4Player.CriticalStateAnimStopped() - forced: " + forceRemoveBuff);
  12634.  
  12635. super.CriticalStateAnimStopped(forceRemoveBuff);
  12636.  
  12637. substateManager.ReactOnCriticalState( false );
  12638. }
  12639.  
  12640. // keeps requesting (sending event) to enter critical states anim state in behavior
  12641. timer function RequestCriticalAnimStart(dt : float, id : int)
  12642. {
  12643. if(keepRequestingCriticalAnimStart)
  12644. {
  12645. if(newRequestedCS && newRequestedCS.GetDurationLeft() > 0)
  12646. {
  12647. CriticalBuffInformBehavior(newRequestedCS);
  12648. }
  12649. else
  12650. {
  12651. keepRequestingCriticalAnimStart = false;
  12652. RemoveTimer('RequestCriticalAnimStart');
  12653. }
  12654. }
  12655. else
  12656. {
  12657. RemoveTimer('RequestCriticalAnimStart');
  12658. }
  12659. }
  12660.  
  12661. event OnRagdollUpdate(progress : float)
  12662. {
  12663. //super.OnRagdollUpdate(progress);
  12664.  
  12665. SetIsInAir(progress == 0);
  12666. }
  12667.  
  12668. // getting from ragdoll after certain time has passed
  12669. event OnRagdollOnGround()
  12670. {
  12671. // try to getup immediately as currently when laying on ground we might be constantly switched between on ground and in air
  12672. TryToEndRagdollOnGround( 0.0f );
  12673. }
  12674.  
  12675. event OnRagdollInAir()
  12676. {
  12677. RemoveTimer('TryToEndRagdollOnGround');
  12678. }
  12679.  
  12680. event OnNoLongerInRagdoll()
  12681. {
  12682. RemoveTimer('TryToEndRagdollOnGround');
  12683. }
  12684.  
  12685. timer function TryToEndRagdollOnGround( td : float, optional id : int)
  12686. {
  12687. var critical : CBaseGameplayEffect;
  12688. var type : EEffectType;
  12689.  
  12690. critical = GetCurrentlyAnimatedCS();
  12691. if(critical)
  12692. {
  12693. type = critical.GetEffectType();
  12694. if(type == EET_Knockdown || type == EET_HeavyKnockdown || type == EET_Ragdoll)
  12695. {
  12696. // 2.5 seconds is not that long but this is not ragdoll simulator :)
  12697. if (critical.GetTimeActive() >= 2.5f)
  12698. {
  12699. SetIsInAir(false);
  12700. RequestCriticalAnimStop();
  12701. RemoveTimer('TryToEndRagdollOnGround');
  12702. }
  12703. else
  12704. {
  12705. AddTimer('TryToEndRagdollOnGround', 0.2f, true);
  12706. }
  12707. return;
  12708. }
  12709. }
  12710.  
  12711. // not in critical or type differs
  12712. RemoveTimer('TryToEndRagdollOnGround');
  12713. }
  12714.  
  12715. public function RequestCriticalAnimStop(optional dontSetCriticalToStopped : bool)
  12716. {
  12717. var buff : CBaseGameplayEffect;
  12718.  
  12719. buff = GetCurrentlyAnimatedCS();
  12720. if(buff && !CriticalBuffUsesFullBodyAnim(buff))
  12721. {
  12722. CriticalStateAnimStopped(false);
  12723. }
  12724.  
  12725. if(!buff || !CriticalBuffUsesFullBodyAnim(buff))
  12726. {
  12727. SetBehaviorVariable( 'bCriticalState', 0);
  12728. }
  12729.  
  12730. super.RequestCriticalAnimStop(dontSetCriticalToStopped);
  12731. }
  12732. ////////////////////////////////////////////////////////////////////////////////////////////
  12733. // @Buffs @Effects
  12734. ////////////////////////////////////////////////////////////////////////////////////////////
  12735.  
  12736. public function SimulateBuffTimePassing(simulatedTime : float)
  12737. {
  12738. effectManager.SimulateBuffTimePassing(simulatedTime);
  12739. }
  12740.  
  12741. public function AddEffectDefault(effectType : EEffectType, creat : CGameplayEntity, srcName : string, optional isSignEffect : bool) : EEffectInteract
  12742. {
  12743. var params : SCustomEffectParams;
  12744.  
  12745. /*
  12746. Welcome to the Ancient Pit. If you're here reading this then you're doomed...
  12747.  
  12748. You're probably asking why someone is overriding default effect durations with some custom arbitrary numbers...
  12749.  
  12750. The thuth is: noone remembers...
  12751.  
  12752. But we need this and you cannot remove it or shit will start falling apart.
  12753. */
  12754. if(effectType == EET_Stagger || effectType == EET_LongStagger || effectType == EET_Knockdown || effectType == EET_HeavyKnockdown)
  12755. {
  12756. params.effectType = effectType;
  12757. params.creator = creat;
  12758. params.sourceName = srcName;
  12759. params.isSignEffect = isSignEffect;
  12760.  
  12761. if ( effectType == EET_Stagger )
  12762. params.duration = 1.83;
  12763. else if ( effectType == EET_LongStagger )
  12764. params.duration = 4;
  12765. else if ( effectType == EET_Knockdown )
  12766. params.duration = 2.5;
  12767. else if ( effectType == EET_HeavyKnockdown )
  12768. params.duration = 4;
  12769.  
  12770. return super.AddEffectCustom(params);
  12771. }
  12772. else
  12773. {
  12774. return super.AddEffectDefault(effectType, creat, srcName, isSignEffect);
  12775. }
  12776. }
  12777.  
  12778.  
  12779. ////////////////////////////////////////////////////////////////////////////////////////////
  12780.  
  12781. //a cheat to ressurect player
  12782. public function CheatResurrect()
  12783. {
  12784. if(IsAlive())
  12785. return;
  12786.  
  12787.  
  12788. SetAlive(true);
  12789.  
  12790. SetKinematic(true);
  12791.  
  12792. delete abilityManager;
  12793. delete effectManager;
  12794.  
  12795. SetAbilityManager(); //defined in inheriting classes but must be called before setting any other managers - sets skills and stats
  12796. abilityManager.Init(this, GetCharacterStats(), false, theGame.GetDifficultyMode());
  12797.  
  12798. SetEffectManager();
  12799.  
  12800. abilityManager.PostInit(); //called after other managers are ready
  12801.  
  12802. EnableFindTarget( true );
  12803. SetBehaviorVariable( 'Ragdoll_Weight', 0.f );
  12804. RaiseForceEvent( 'RecoverFromRagdoll' );
  12805. SetCanPlayHitAnim( true );
  12806. SetBehaviorVariable( 'CriticalStateType', (int)ECST_None );
  12807. //if( GetCurrentStateName() != 'CombatSteel')
  12808. // PushState( 'CombatSteel' );
  12809. //else
  12810. GoToStateIfNew('Exploration');
  12811.  
  12812. ( (CDismembermentComponent)this.GetComponent( 'Dismemberment' ) ).ClearVisibleWound();
  12813.  
  12814. SetIsInAir(false); //might block getup from ragdol in knockdown
  12815.  
  12816. theInput.SetContext('Exploration');
  12817.  
  12818. ResetDeathType();
  12819.  
  12820. ForceUnlockAllInputActions(false);
  12821.  
  12822. theGame.CloseMenu('DeathScreenMenu');
  12823.  
  12824. //restore sounds
  12825. theSound.LeaveGameState(ESGS_Death);
  12826.  
  12827. theGame.ReleaseNoSaveLock(deathNoSaveLock);
  12828. }
  12829.  
  12830. ////////////////////////////////////////////////////////////////////////////////////////////
  12831.  
  12832. public function SetIsInsideInteraction(b : bool) {isInsideInteraction = b;}
  12833. public function IsInsideInteraction() : bool {return isInsideInteraction;}
  12834.  
  12835. public function SetIsInsideHorseInteraction( b : bool, horse : CEntity )
  12836. {
  12837. isInsideHorseInteraction = b;
  12838. horseInteractionSource = horse;
  12839. }
  12840. public function IsInsideHorseInteraction() : bool {return isInsideHorseInteraction;}
  12841.  
  12842.  
  12843. event OnInteractionActivationTest( interactionComponentName : string, activator : CEntity )
  12844. {
  12845. if ( interactionComponentName == "ClimbLadder" )
  12846. {
  12847. if( PlayerHasLadderExplorationReady() )
  12848. {
  12849. return true;
  12850. }
  12851. }
  12852.  
  12853. return false;
  12854. }
  12855.  
  12856. private function PlayerHasLadderExplorationReady() : bool
  12857. {
  12858. if( !substateManager.CanInteract() )
  12859. {
  12860. return false;
  12861. }
  12862.  
  12863. if( !substateManager.m_SharedDataO.HasValidLadderExploration() )
  12864. {
  12865. return false;
  12866. }
  12867.  
  12868. return true;
  12869. }
  12870.  
  12871. ////////////////////////////////////////////////////////////////////////////////////////////
  12872. ////////////////////////////// @COMBAT /////////////////////////////////////////////////
  12873. ////////////////////////////////////////////////////////////////////////////////////////////
  12874.  
  12875. public function SetGuarded(flag : bool)
  12876. {
  12877. super.SetGuarded(flag);
  12878.  
  12879. if(flag && FactsQuerySum("tut_fight_use_slomo") > 0)
  12880. {
  12881. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) );
  12882. FactsRemove("tut_fight_slomo_ON");
  12883. }
  12884. }
  12885.  
  12886.  
  12887. public function IsGuarded() : bool
  12888. {
  12889. return super.IsGuarded() && ( !rangedWeapon || rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' );
  12890. }
  12891. ////////////////////////////////////////////////////////////////////////////////////////////
  12892. ///////////////////// @THROWABLE @BOMBS @PETARDS @Usable ///////////////////////////////////
  12893. ////////////////////////////////////////////////////////////////////////////////////////////
  12894.  
  12895. public function GetSelectedItemId() : SItemUniqueId {return selectedItemId;}
  12896. public function ClearSelectedItemId() {selectedItemId = GetInvalidUniqueId();}
  12897.  
  12898. public function IsHoldingItemInLHand() : bool
  12899. {
  12900. return currentlyEquipedItemL != GetInvalidUniqueId();
  12901. }
  12902.  
  12903. public function GetCurrentlyUsedItemL () : W3UsableItem
  12904. {
  12905. return currentlyUsedItemL;
  12906. }
  12907.  
  12908. public function SetPlayerActionToRestore ( actionToRestoreType : EPlayerActionToRestore )
  12909. {
  12910. playerActionToRestore = actionToRestoreType;
  12911. }
  12912.  
  12913. public function IsCurrentlyUsingItemL () : bool
  12914. {
  12915. return currentlyUsingItem;
  12916. }
  12917.  
  12918. function BlockSlotsOnLItemUse ()
  12919. {
  12920. var slotsToBlock : array<name>;
  12921.  
  12922. slotsToBlock.PushBack( 'Slot1' );
  12923. slotsToBlock.PushBack( 'Slot2' );
  12924. slotsToBlock.PushBack( 'Slot3' );
  12925. slotsToBlock.PushBack( 'Slot4' );
  12926. slotsToBlock.PushBack( 'Slot5' );
  12927. slotsToBlock.PushBack( 'Yrden' );
  12928. slotsToBlock.PushBack( 'Quen' );
  12929. slotsToBlock.PushBack( 'Igni' );
  12930. slotsToBlock.PushBack( 'Axii' );
  12931. slotsToBlock.PushBack( 'Aard' );
  12932.  
  12933.  
  12934. EnableRadialSlotsWithSource ( false, slotsToBlock, 'usableItemL' );
  12935. }
  12936.  
  12937. function UnblockSlotsOnLItemUse ()
  12938. {
  12939. var slotsToBlock : array<name>;
  12940.  
  12941. slotsToBlock.PushBack( 'Slot1' );
  12942. slotsToBlock.PushBack( 'Slot2' );
  12943. slotsToBlock.PushBack( 'Slot3' );
  12944. slotsToBlock.PushBack( 'Slot4' );
  12945. slotsToBlock.PushBack( 'Slot5' );
  12946. slotsToBlock.PushBack( 'Yrden' );
  12947. slotsToBlock.PushBack( 'Quen' );
  12948. slotsToBlock.PushBack( 'Igni' );
  12949. slotsToBlock.PushBack( 'Axii' );
  12950. slotsToBlock.PushBack( 'Aard' );
  12951.  
  12952.  
  12953. EnableRadialSlotsWithSource ( true, slotsToBlock, 'usableItemL' );
  12954. }
  12955.  
  12956. function IsUsableItemLBlocked () : bool
  12957. {
  12958. return isUsableItemBlocked;
  12959. }
  12960. function HideUsableItem( optional force : bool )
  12961. {
  12962. if( currentlyEquipedItemL != GetInvalidUniqueId() )
  12963. {
  12964. if ( force )
  12965. {
  12966. if (!RaiseEvent( 'ItemEndL' ) )
  12967. {
  12968. OnUsingItemsReset();
  12969. }
  12970. return;
  12971.  
  12972. }
  12973. RaiseEvent( 'ItemUseL' );
  12974. }
  12975. }
  12976. function ProcessUsableItemsTransition ( actionToRestore : EPlayerActionToRestore )
  12977. {
  12978. var category : name;
  12979. var signSkill : ESkill;
  12980.  
  12981. category = inv.GetItemCategory ( selectedItemId );
  12982. signSkill = SignEnumToSkillEnum( GetEquippedSign());
  12983.  
  12984. switch ( actionToRestore )
  12985. {
  12986. case PATR_None:
  12987. if ( currentlyUsedItemL )
  12988. {
  12989. inv.UnmountItem( currentlyEquipedItemL, true );
  12990. }
  12991. currentlyEquipedItemL = GetInvalidUniqueId();
  12992. return;
  12993.  
  12994. case PATR_Default:
  12995. if ( IsSlotQuickslot( inv.GetSlotForItemId ( selectedItemId )) && category == 'usable' && currentlyEquipedItemL != selectedItemId )
  12996. {
  12997. if ( currentlyUsedItemL )
  12998. {
  12999. inv.UnmountItem( currentlyEquipedItemL, true );
  13000. }
  13001. currentlyEquipedItemL = GetInvalidUniqueId();
  13002. OnUseSelectedItem();
  13003. return;
  13004. }
  13005. break;
  13006. case PATR_Crossbow:
  13007. if ( inv.IsItemCrossbow ( selectedItemId ) )
  13008. {
  13009. if ( currentlyUsedItemL )
  13010. {
  13011. inv.UnmountItem( currentlyEquipedItemL, true );
  13012. }
  13013. currentlyEquipedItemL = GetInvalidUniqueId();
  13014. SetIsAimingCrossbow( true );
  13015.  
  13016. if ( theInput.IsActionPressed( 'ThrowItem' ) )
  13017. SetupCombatAction( EBAT_ItemUse, BS_Pressed );
  13018. else
  13019. {
  13020. SetupCombatAction( EBAT_ItemUse, BS_Pressed );
  13021. SetupCombatAction( EBAT_ItemUse, BS_Released );
  13022. }
  13023. return;
  13024. }
  13025. break;
  13026. case PATR_CastSign:
  13027. if( signSkill != S_SUndefined && playerActionToRestore == PATR_CastSign )
  13028. {
  13029. if ( currentlyUsedItemL )
  13030. {
  13031. inv.UnmountItem( currentlyEquipedItemL, true );
  13032. }
  13033. currentlyEquipedItemL = GetInvalidUniqueId();
  13034.  
  13035. if( HasStaminaToUseSkill( signSkill, false ) )
  13036. {
  13037. if( GetInvalidUniqueId() != inv.GetItemFromSlot( 'l_weapon' ) )
  13038. PushCombatActionOnBuffer( EBAT_CastSign, BS_Pressed );
  13039. else
  13040. SetupCombatAction( EBAT_CastSign, BS_Pressed );
  13041. }
  13042. else
  13043. {
  13044. thePlayer.SoundEvent("gui_no_stamina");
  13045. }
  13046. return;
  13047. }
  13048. break;
  13049. case PATR_ThrowBomb:
  13050. if ( inv.IsItemBomb ( selectedItemId ) )
  13051. {
  13052. if ( currentlyUsedItemL )
  13053. {
  13054. inv.UnmountItem( currentlyEquipedItemL, true );
  13055. }
  13056. currentlyEquipedItemL = GetInvalidUniqueId();
  13057. PrepareToAttack();
  13058. SetupCombatAction( EBAT_ItemUse, BS_Pressed );
  13059. return;
  13060. }
  13061. break;
  13062. case PATR_CallHorse:
  13063. theGame.OnSpawnPlayerHorse();
  13064. break;
  13065. default:
  13066. if ( currentlyUsedItemL )
  13067. {
  13068. inv.UnmountItem( currentlyEquipedItemL, true );
  13069. }
  13070. currentlyEquipedItemL = GetInvalidUniqueId();
  13071. return;
  13072. }
  13073. if ( currentlyUsedItemL )
  13074. {
  13075. inv.UnmountItem( currentlyEquipedItemL, true );
  13076. }
  13077. currentlyEquipedItemL = GetInvalidUniqueId();
  13078. }
  13079.  
  13080. function GetUsableItemLtransitionAllowed () : bool
  13081. {
  13082. return isUsableItemLtransitionAllowed;
  13083. }
  13084.  
  13085. function SetUsableItemLtransitionAllowed ( isAllowed : bool)
  13086. {
  13087. isUsableItemLtransitionAllowed = isAllowed;
  13088. }
  13089.  
  13090. event OnItemUseLUnBlocked ()
  13091. {
  13092. if ( isUsableItemBlocked )
  13093. {
  13094. isUsableItemBlocked = false;
  13095. UnblockSlotsOnLItemUse ();
  13096. }
  13097. }
  13098.  
  13099. event OnItemUseLBlocked ()
  13100. {
  13101. if ( !isUsableItemBlocked )
  13102. {
  13103. isUsableItemBlocked = true;
  13104. BlockSlotsOnLItemUse ();
  13105. }
  13106. }
  13107.  
  13108. event OnUsingItemsReset()
  13109. {
  13110. if ( currentlyUsingItem )
  13111. {
  13112. OnItemUseLUnBlocked ();
  13113. OnUsingItemsComplete();
  13114. }
  13115. }
  13116. event OnUsingItemsComplete ()
  13117. {
  13118. if ( isUsableItemBlocked )
  13119. {
  13120. OnItemUseLUnBlocked ();
  13121. }
  13122. currentlyUsingItem = false;
  13123. if ( GetUsableItemLtransitionAllowed () )
  13124. {
  13125. ProcessUsableItemsTransition( playerActionToRestore );
  13126. }
  13127. else
  13128. {
  13129. if ( currentlyUsedItemL )
  13130. {
  13131. inv.UnmountItem( currentlyEquipedItemL, true );
  13132. }
  13133. currentlyEquipedItemL = GetInvalidUniqueId();
  13134. }
  13135.  
  13136. SetPlayerActionToRestore ( PATR_Default );
  13137. }
  13138.  
  13139. event OnUseSelectedItem( optional force : bool )
  13140. {
  13141. var category : name;
  13142. var itemEntity : W3UsableItem;
  13143.  
  13144. if ( isUsableItemBlocked && !force )
  13145. {
  13146. return false;
  13147. }
  13148. if ( IsCastingSign() )
  13149. return false;
  13150.  
  13151. if ( currentlyEquipedItemL != GetInvalidUniqueId() )
  13152. {
  13153. SetBehaviorVariable( 'SelectedItemL', (int)GetUsableItemTypeById( currentlyEquipedItemL ) );
  13154. if ( force )
  13155. {
  13156. if ( RaiseEvent( 'ItemEndL' ) )
  13157. {
  13158. SetUsableItemLtransitionAllowed ( true );
  13159. return true;
  13160. }
  13161. }
  13162. else
  13163. {
  13164. if ( RaiseEvent( 'ItemUseL' ) )
  13165. {
  13166. SetUsableItemLtransitionAllowed ( true );
  13167. return true;
  13168. }
  13169. }
  13170. }
  13171. else
  13172. {
  13173. category = inv.GetItemCategory( selectedItemId );
  13174. if( category != 'usable' )
  13175. {
  13176. return false;
  13177. }
  13178. SetBehaviorVariable( 'SelectedItemL', (int)GetUsableItemTypeById( selectedItemId ) );
  13179. if( RaiseEvent( 'ItemUseL' ) )
  13180. {
  13181. currentlyEquipedItemL = selectedItemId;
  13182. SetUsableItemLtransitionAllowed ( false );
  13183. currentlyUsingItem = true;
  13184.  
  13185. return true;
  13186. }
  13187. inv.UnmountItem( selectedItemId, true );
  13188. }
  13189. }
  13190.  
  13191. protected saved var currentlyUsingItem : bool;
  13192.  
  13193. public function ProcessUseSelectedItem( itemEntity : W3UsableItem, optional shouldCallOnUsed : bool )
  13194. {
  13195. currentlyUsedItemL = itemEntity;
  13196. DrainStamina(ESAT_UsableItem);
  13197.  
  13198. if ( shouldCallOnUsed )
  13199. {
  13200. currentlyUsedItemL.OnUsed( thePlayer );
  13201. }
  13202. }
  13203.  
  13204. function GetUsableItemTypeById ( itemId : SItemUniqueId ) : EUsableItemType
  13205. {
  13206. var itemName : name;
  13207.  
  13208. itemName = inv.GetItemName ( itemId );
  13209.  
  13210. return theGame.GetDefinitionsManager().GetUsableItemType ( itemName );
  13211.  
  13212. }
  13213.  
  13214. // Starts the 'WaitForItemSpawnAndProccesTask' task
  13215. public function StartWaitForItemSpawnAndProccesTask()
  13216. {
  13217. AddTimer( 'WaitForItemSpawnAndProccesTask', 0.001f, true,,,,true );
  13218. }
  13219.  
  13220. // Kills the 'WaitForItemSpawnAndProccesTask' task
  13221. public function KillWaitForItemSpawnAndProccesTask()
  13222. {
  13223. RemoveTimer ( 'WaitForItemSpawnAndProccesTask' );
  13224. }
  13225.  
  13226. // Informs the 'WaitForItemSpawnAndProccesTask' task, that selected item should be used ASAP.
  13227. // Flag will be reset by the task itself
  13228. public function AllowUseSelectedItem()
  13229. {
  13230. m_useSelectedItemIfSpawned = true;
  13231. }
  13232.  
  13233. // Task waits for inventory to created selected item. Item will be used ASAP as the task is allowed to do so.
  13234. // Right after that - it kills itself.
  13235. timer function WaitForItemSpawnAndProccesTask( timeDelta : float , id : int )
  13236. {
  13237. var itemEntity : W3UsableItem;
  13238. var canTaskBeKilled : bool;
  13239. canTaskBeKilled = false;
  13240.  
  13241. if ( IsCastingSign() )
  13242. {
  13243. return;
  13244. }
  13245.  
  13246. // selectad item is wrong!
  13247. if ( selectedItemId == GetInvalidUniqueId() )
  13248. {
  13249. canTaskBeKilled = true;
  13250. }
  13251.  
  13252. itemEntity = (W3UsableItem)inv.GetItemEntityUnsafe( selectedItemId );
  13253. if ( itemEntity && m_useSelectedItemIfSpawned )
  13254. {
  13255. // we have selected item and we are allowed to use it, so to it and kill itself.
  13256. canTaskBeKilled = true;
  13257. m_useSelectedItemIfSpawned = false; // reset flag
  13258. ProcessUseSelectedItem( itemEntity, true );
  13259. }
  13260.  
  13261. if ( canTaskBeKilled )
  13262. {
  13263. KillWaitForItemSpawnAndProccesTask();
  13264. }
  13265. }
  13266.  
  13267. event OnBombProjectileReleased()
  13268. {
  13269. ResetRawPlayerHeading();
  13270. UnblockAction(EIAB_ThrowBomb, 'BombThrow');
  13271. UnblockAction(EIAB_Crossbow, 'BombThrow');
  13272.  
  13273. if(GetCurrentStateName() == 'AimThrow')
  13274. PopState();
  13275.  
  13276. FactsAdd("ach_bomb", 1, 4 );
  13277. theGame.GetGamerProfile().CheckLearningTheRopes();
  13278. }
  13279.  
  13280. public function SetIsThrowingItemWithAim(b : bool)
  13281. {
  13282. isThrowingItemWithAim = b;
  13283. }
  13284.  
  13285. public function SetIsThrowingItem( flag : bool ) {isThrowingItem = flag;}
  13286. public function IsThrowingItem() : bool {return isThrowingItem;}
  13287. public function IsThrowingItemWithAim() : bool {return isThrowingItemWithAim;}
  13288. public function SetThrowHold(b : bool) {isThrowHoldPressed = b;}
  13289. public function IsThrowHold() : bool {return isThrowHoldPressed;}
  13290. public function SetIsAimingCrossbow( flag : bool ) {isAimingCrossbow = flag;}
  13291. public function GetIsAimingCrossbow() : bool {return isAimingCrossbow;}
  13292.  
  13293. event OnThrowAnimLeave()
  13294. {
  13295. var throwStage : EThrowStage;
  13296. var thrownEntity : CThrowable;
  13297.  
  13298. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  13299.  
  13300. if(thrownEntity && !thrownEntity.WasThrown())
  13301. {
  13302. throwStage = (int)GetBehaviorVariable( 'throwStage', (int)TS_Stop);
  13303. if(inv.IsItemBomb(selectedItemId))
  13304. {
  13305. BombThrowCleanUp();
  13306. }
  13307. else
  13308. {
  13309. ThrowingAbort();
  13310. }
  13311. }
  13312.  
  13313. thrownEntity = NULL;
  13314. SetIsThrowingItem( false );
  13315. SetIsThrowingItemWithAim( false );
  13316.  
  13317. this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' );
  13318. UnblockAction(EIAB_ThrowBomb, 'BombThrow');
  13319. UnblockAction(EIAB_Crossbow, 'BombThrow');
  13320. }
  13321.  
  13322. //Called when bomb throwing has started - it is ensured that we CAN throw it. At this point we don't know yet if it's a quick throw or aimed throw
  13323. protected function BombThrowStart()
  13324. {
  13325. var slideTargetActor : CActor;
  13326.  
  13327. BlockAction( EIAB_ThrowBomb, 'BombThrow' );
  13328. BlockAction(EIAB_Crossbow, 'BombThrow');
  13329.  
  13330. SetBehaviorVariable( 'throwStage', (int)TS_Start );
  13331. SetBehaviorVariable( 'combatActionType', (int)CAT_ItemThrow );
  13332.  
  13333. if ( slideTarget )
  13334. {
  13335. AddCustomOrientationTarget( OT_Actor, 'BombThrow' );
  13336.  
  13337. slideTargetActor = (CActor)( slideTarget );
  13338.  
  13339. //AK BOMB: moved rotation from anim event to scripts to prevent rotation to friendly and neutral npcs.
  13340. // removed the check after commenting out ProcessCanAttackWhenNotInCombatBomb
  13341. //if( !slideTargetActor || ( slideTargetActor && GetAttitudeBetween(this, slideTarget) == AIA_Hostile ) )
  13342. // SetCustomRotation( 'Throw', VecHeading( slideTarget.GetWorldPosition() - GetWorldPosition() ), 0.0f, 0.3f, false );
  13343. }
  13344. else
  13345. {
  13346. if ( lastAxisInputIsMovement )
  13347. AddCustomOrientationTarget( OT_Actor, 'BombThrow' );
  13348. else
  13349. AddCustomOrientationTarget( OT_Camera, 'BombThrow' );
  13350. }
  13351.  
  13352. UpdateLookAtTarget();
  13353. SetCustomRotation( 'Throw', VecHeading( this.GetLookAtPosition() - GetWorldPosition() ), 0.0f, 0.3f, false );
  13354.  
  13355. SetBehaviorVariable( 'itemType', (int)IT_Petard );
  13356.  
  13357. ProcessCanAttackWhenNotInCombatBomb();
  13358.  
  13359. if ( RaiseForceEvent('CombatAction') )
  13360. OnCombatActionStart();
  13361.  
  13362. //FIXME might be aborted afterwards and no bomb would be thrown actually
  13363. theTelemetry.LogWithLabel(TE_FIGHT_HERO_THROWS_BOMB, inv.GetItemName( selectedItemId ));
  13364. }
  13365.  
  13366. //from animation
  13367. event OnThrowAnimStart()
  13368. {
  13369. var itemId : SItemUniqueId;
  13370. var thrownEntity : CThrowable;
  13371. //Disable slots on radial menu
  13372. this.radialSlots.Clear();
  13373. GetWitcherPlayer().GetItemEquippedOnSlot(EES_Petard1, itemId );
  13374.  
  13375. if( GetSelectedItemId() == itemId )
  13376. {
  13377. this.radialSlots.PushBack( 'Slot2' );
  13378. }
  13379. else
  13380. {
  13381. this.radialSlots.PushBack( 'Slot1' );
  13382. }
  13383. this.radialSlots.PushBack( 'Slot3' );
  13384. this.radialSlots.PushBack( 'Slot4' );
  13385. this.radialSlots.PushBack( 'Slot5' );
  13386. this.EnableRadialSlotsWithSource( false, this.radialSlots, 'throwBomb' );
  13387.  
  13388. thrownEntity = (CThrowable)inv.GetDeploymentItemEntity( selectedItemId,,,true );
  13389. thrownEntity.Initialize( this, selectedItemId );
  13390. EntityHandleSet( thrownEntityHandle, thrownEntity );
  13391. SetIsThrowingItem( true );
  13392. }
  13393.  
  13394. public function BombThrowAbort()
  13395. {
  13396. BombThrowCleanUp();
  13397. UnblockAction( EIAB_ThrowBomb, 'BombThrow' );
  13398. UnblockAction(EIAB_Crossbow, 'BombThrow');
  13399. }
  13400.  
  13401. private function BombThrowCleanUp()
  13402. {
  13403. var throwStage : EThrowStage;
  13404. var thrownEntity : CThrowable;
  13405. var vehicle : CVehicleComponent;
  13406.  
  13407. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  13408.  
  13409. this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' );
  13410. throwStage = (int)GetBehaviorVariable( 'throwStage', (int)TS_Stop);
  13411.  
  13412. SetBehaviorVariable( 'throwStage', (int)TS_Stop );
  13413.  
  13414. if( GetCurrentStateName() == 'AimThrow')
  13415. {
  13416. PopState();
  13417. thrownEntity.StopAiming( true );
  13418. }
  13419. else if ( this.IsUsingHorse() )
  13420. {
  13421. vehicle = (CVehicleComponent)(GetUsedVehicle().GetComponentByClassName('CVehicleComponent'));
  13422. vehicle.GetUserCombatManager().OnForceItemActionAbort();
  13423. }
  13424.  
  13425. //if bomb was not detached yet (is not flying)
  13426. if(thrownEntity && !thrownEntity.WasThrown())
  13427. {
  13428. thrownEntity.BreakAttachment();
  13429. thrownEntity.Destroy();
  13430. }
  13431.  
  13432. thrownEntity = NULL;
  13433. SetIsThrowingItem( false );
  13434. SetIsThrowingItemWithAim( false );
  13435. RemoveCustomOrientationTarget( 'BombThrow' );
  13436. }
  13437.  
  13438. public function ProcessCanAttackWhenNotInCombatBomb()
  13439. {
  13440. /* //AK BOMB: keeping it just in case we need to bring it back
  13441. var impactRange : float;
  13442. var entities : array<CGameplayEntity>;
  13443. var ent : CEntity;
  13444. var actor : CActor;
  13445. var petard : W3Petard;
  13446. var vehicle : CEntity;
  13447. var slotMatrix : Matrix;
  13448. var isShootingFriendly : bool;
  13449.  
  13450.  
  13451. if ( thrownEntity )
  13452. {
  13453. petard = (W3Petard)( thrownEntity );
  13454.  
  13455. if ( !IsThreatened() )
  13456. {
  13457. if ( this.playerAiming.GetCurrentStateName() == 'Aiming' )
  13458. ent = playerAiming.GetSweptFriendly();
  13459. else
  13460. actor = (CActor)GetDisplayTarget();
  13461.  
  13462. if( ent || ( actor && actor.IsHuman() && !IsThreat( actor ) ) )
  13463. SetIsShootingFriendly( true );
  13464. else
  13465. SetIsShootingFriendly( false );
  13466. }
  13467. else
  13468. SetIsShootingFriendly( false );
  13469. }
  13470. else
  13471. SetIsShootingFriendly( false );
  13472. */
  13473.  
  13474. SetIsShootingFriendly( false );
  13475. SetBehaviorVariable( 'isShootingFriendly', (float)( GetIsShootingFriendly() ) );
  13476. }
  13477.  
  13478. public function SetIsShootingFriendly( flag : bool )
  13479. {
  13480. isShootingFriendly = flag;
  13481. }
  13482.  
  13483. public function GetIsShootingFriendly() : bool
  13484. {
  13485. return isShootingFriendly;
  13486. }
  13487.  
  13488. //only for usable items
  13489. protected function UsableItemStart()
  13490. {
  13491. var thrownEntity : CThrowable;
  13492.  
  13493. //this seems like bullshit but it's because usable items use the same code as throwing bombs and shooting crossbow
  13494. thrownEntity = (CThrowable)inv.GetDeploymentItemEntity( selectedItemId,,,true );
  13495. thrownEntity.Initialize( this, selectedItemId );
  13496. EntityHandleSet( thrownEntityHandle, thrownEntity );
  13497. SetBehaviorVariable( 'throwStage', (int)TS_Start );
  13498. SetIsThrowingItem( true );
  13499. SetBehaviorVariable( 'combatActionType', (int)CAT_ItemThrow );
  13500.  
  13501. if ( slideTarget )
  13502. {
  13503. AddCustomOrientationTarget( OT_Actor, 'UsableItems' );
  13504. }
  13505. else
  13506. {
  13507. if ( lastAxisInputIsMovement )
  13508. AddCustomOrientationTarget( OT_Actor, 'UsableItems' );
  13509. else
  13510. AddCustomOrientationTarget( OT_Camera, 'UsableItems' );
  13511. }
  13512.  
  13513. SetBehaviorVariable( 'itemType', (int)(-1) );
  13514.  
  13515. if ( RaiseForceEvent('CombatAction') )
  13516. OnCombatActionStart();
  13517. }
  13518.  
  13519. protected function BombThrowRelease()
  13520. {
  13521. OnDelayOrientationChangeOff();
  13522.  
  13523. if ( GetIsShootingFriendly() )
  13524. BombThrowAbort();
  13525. else
  13526. {
  13527. SetBehaviorVariable( 'throwStage', (int)TS_End );
  13528.  
  13529. if ( playerAiming.GetCurrentStateName() == 'Aiming' )
  13530. SetCustomRotation( 'Throw', VecHeading( this.GetLookAtPosition() - GetWorldPosition() ), 0.0f, 0.2f, false );
  13531. }
  13532. }
  13533.  
  13534. protected function UsableItemRelease()
  13535. {
  13536. OnDelayOrientationChangeOff();
  13537. SetBehaviorVariable( 'throwStage', (int)TS_End );
  13538. RemoveCustomOrientationTarget( 'UsableItems' );
  13539. }
  13540.  
  13541. // Called when usable item use or crossbow shot was aborted (bombs use different function)
  13542. public function ThrowingAbort()
  13543. {
  13544. var thrownEntity : CThrowable;
  13545.  
  13546. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  13547.  
  13548. SetBehaviorVariable( 'throwStage', (int)TS_Stop );
  13549. RaiseEvent( 'actionStop' );
  13550.  
  13551. if( GetCurrentStateName() == 'AimThrow')
  13552. {
  13553. PopState();
  13554. thrownEntity.StopAiming( true );
  13555. }
  13556.  
  13557. //if bomb was not detached yet (is not flying)
  13558. if(thrownEntity && !thrownEntity.WasThrown())
  13559. {
  13560. thrownEntity.BreakAttachment();
  13561. thrownEntity.Destroy();
  13562. }
  13563. this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' );
  13564. }
  13565.  
  13566. public function CanSetupCombatAction_Throw() : bool
  13567. {
  13568. //if has item selected
  13569. if(!inv.IsIdValid( selectedItemId ))
  13570. return false;
  13571.  
  13572. //if not a throwable item
  13573. if(!inv.IsItemSingletonItem(selectedItemId))
  13574. return false;
  13575.  
  13576. //if input is not blocked
  13577. if(!GetBIsInputAllowed())
  13578. return false;
  13579.  
  13580. //if has ammo
  13581. if(inv.GetItemQuantity(GetSelectedItemId()) <= 0 && !inv.ItemHasTag(selectedItemId, theGame.params.TAG_INFINITE_AMMO))
  13582. return false;
  13583.  
  13584. //if action is not blocked or (HACK) we're in swimming
  13585. if(!inputHandler.IsActionAllowed(EIAB_ThrowBomb) && GetCurrentStateName() != 'Swimming')
  13586. return false;
  13587.  
  13588. return true;
  13589. }
  13590.  
  13591. public function GetThrownEntity() : CThrowable
  13592. {
  13593. return (CThrowable)EntityHandleGet( thrownEntityHandle );
  13594. }
  13595.  
  13596. // Crossbow events and functions
  13597. event OnWeaponWait() { rangedWeapon.OnWeaponWait(); }
  13598. event OnWeaponDrawStart() { rangedWeapon.OnWeaponDrawStart(); }
  13599. event OnWeaponReloadStart() { rangedWeapon.OnWeaponReloadStart(); }
  13600. event OnWeaponReloadEnd() { rangedWeapon.OnWeaponReloadEnd(); }
  13601. event OnWeaponAimStart() { rangedWeapon.OnWeaponAimStart(); }
  13602. event OnWeaponShootStart() { rangedWeapon.OnWeaponShootStart(); }
  13603. event OnWeaponShootEnd() { rangedWeapon.OnWeaponShootEnd(); }
  13604. event OnWeaponAimEnd() { rangedWeapon.OnWeaponAimEnd(); }
  13605. event OnWeaponHolsterStart() { rangedWeapon.OnWeaponHolsterStart(); }
  13606. event OnWeaponHolsterEnd() { rangedWeapon.OnWeaponHolsterEnd(); }
  13607. event OnWeaponToNormalTransStart() { rangedWeapon.OnWeaponToNormalTransStart(); }
  13608. event OnWeaponToNormalTransEnd() { rangedWeapon.OnWeaponToNormalTransEnd(); }
  13609.  
  13610. event OnEnableAimingMode( enable : bool )
  13611. {
  13612. if( !crossbowDontPopStateHack )
  13613. {
  13614. if ( enable )
  13615. PushState( 'AimThrow' );
  13616. else if ( GetCurrentStateName() == 'AimThrow' )
  13617. PopState();
  13618. }
  13619. }
  13620.  
  13621. event OnRangedForceHolster( optional forceUpperBodyAnim, instant, dropItem : bool )
  13622. {
  13623. if(rangedWeapon)
  13624. rangedWeapon.OnForceHolster( forceUpperBodyAnim, instant, dropItem );
  13625. }
  13626.  
  13627.  
  13628. public function IsCrossbowHeld() : bool
  13629. {
  13630. if (rangedWeapon)
  13631. return rangedWeapon.GetCurrentStateName() != 'State_WeaponWait';
  13632. return false;
  13633. }
  13634.  
  13635. // Tickets
  13636. event OnBlockAllCombatTickets( release : bool )
  13637. {
  13638. if (!release )
  13639. ((CR4PlayerStateCombat)GetState('Combat')).OnBlockAllCombatTickets(false);
  13640. }
  13641. event OnForceTicketUpdate() {}
  13642.  
  13643. ////////////////////////////////////////////////////////////////////////////////////////////
  13644. /////////////////////////// @ATTACKS /////////////////////////////////////////////
  13645. ////////////////////////////////////////////////////////////////////////////////////////////
  13646.  
  13647. /*script*/ event OnPocessActionPost(action : W3DamageAction)
  13648. {
  13649. var npc : CNewNPC;
  13650. var attackAction : W3Action_Attack;
  13651. var lifeLeech : float;
  13652.  
  13653. super.OnPocessActionPost(action);
  13654.  
  13655. attackAction = (W3Action_Attack)action;
  13656.  
  13657. if(attackAction)
  13658. {
  13659. npc = (CNewNPC)action.victim;
  13660.  
  13661. if(npc && npc.IsHuman() )
  13662. {
  13663. PlayBattleCry('BattleCryHumansHit', 0.05f );
  13664. }
  13665. else
  13666. {
  13667. PlayBattleCry('BattleCryMonstersHit', 0.05f );
  13668. }
  13669.  
  13670. if(attackAction.IsActionMelee())
  13671. {
  13672. //uninterrupted hits counting
  13673. IncreaseUninterruptedHitsCount();
  13674.  
  13675. //camera shake
  13676. if( IsLightAttack( attackAction.GetAttackName() ) )
  13677. {
  13678. GCameraShake(0.1, false, GetWorldPosition(), 10);
  13679. }
  13680.  
  13681. //Caretaker Shovel life steal
  13682. if(npc && inv.GetItemName(attackAction.GetWeaponId()) == 'PC Caretaker Shovel')
  13683. {
  13684. //inv.PlayItemEffect( items[i], 'stab_attack' );
  13685. lifeLeech = CalculateAttributeValue(inv.GetItemAttributeValue(attackAction.GetWeaponId() ,'lifesteal'));
  13686. if (npc.UsesVitality())
  13687. lifeLeech *= action.processedDmg.vitalityDamage;
  13688. else if (UsesEssence())
  13689. lifeLeech *= action.processedDmg.essenceDamage;
  13690. else
  13691. lifeLeech = 0;
  13692.  
  13693. if ( lifeLeech > 0 )
  13694. {
  13695. inv.PlayItemEffect( attackAction.GetWeaponId(), 'stab_attack' );
  13696. PlayEffect('drain_energy_caretaker_shovel');
  13697. GainStat(BCS_Vitality, lifeLeech);
  13698. }
  13699. }
  13700. }
  13701. }
  13702. }
  13703.  
  13704. public function SetHitReactTransScale(f : float) {hitReactTransScale = f;}
  13705. public function GetHitReactTransScale() : float
  13706. {
  13707. if ( ( (CNewNPC)slideTarget ).GetIsTranslationScaled() )
  13708. return hitReactTransScale;
  13709. else
  13710. return 1.f;
  13711. }
  13712.  
  13713. ////////////////////////////////////////////////////////////////////////////////////////////
  13714. /////////////////////////// @HORSE /////////////////////////////////////////////
  13715. ////////////////////////////////////////////////////////////////////////////////////////////
  13716.  
  13717. public function GetHorseWithInventory() : CNewNPC
  13718. {
  13719. return (CNewNPC)EntityHandleGet( horseWithInventory );
  13720. }
  13721. public function GetHorseCurrentlyMounted() : CNewNPC
  13722. {
  13723. return currentlyMountedHorse;
  13724. }
  13725. // Do not use outside of vehicle component
  13726. public function _SetHorseCurrentlyMounted( horse : CNewNPC )
  13727. {
  13728. currentlyMountedHorse = horse;
  13729. }
  13730.  
  13731. public function WasHorseRecentlySummoned() : bool
  13732. {
  13733. if ( horseSummonTimeStamp + 5.f > theGame.GetEngineTimeAsSeconds() )
  13734. return true;
  13735.  
  13736. return false;
  13737. }
  13738.  
  13739. private const var MOUNT_DISTANCE_CBT : float;
  13740. default MOUNT_DISTANCE_CBT = 3.0;
  13741.  
  13742. private const var MOUNT_ANGLE_CBT : float;
  13743. default MOUNT_ANGLE_CBT = 35.0;
  13744.  
  13745. private const var MOUNT_ANGLE_EXP : float;
  13746. default MOUNT_ANGLE_EXP = 45.0;
  13747.  
  13748. public function IsMountingHorseAllowed( optional alwaysAllowedInExploration : bool ) : bool
  13749. {
  13750. var angle : float;
  13751. var distance : float;
  13752.  
  13753. if( IsInsideHorseInteraction() )
  13754. {
  13755. angle = AngleDistance( thePlayer.rawPlayerHeading, VecHeading( thePlayer.horseInteractionSource.GetWorldPosition() - thePlayer.GetWorldPosition() ) );
  13756.  
  13757. if( thePlayer.IsInCombat() )
  13758. {
  13759. if( AbsF( angle ) < MOUNT_ANGLE_CBT )
  13760. {
  13761. distance = VecDistance( thePlayer.GetWorldPosition(), thePlayer.horseInteractionSource.GetWorldPosition() );
  13762.  
  13763. if( distance < MOUNT_DISTANCE_CBT )
  13764. {
  13765. return true;
  13766. }
  13767. else
  13768. {
  13769. return false;
  13770. }
  13771. }
  13772. else
  13773. {
  13774. return false;
  13775. }
  13776.  
  13777. }
  13778. else
  13779. {
  13780. if( alwaysAllowedInExploration )
  13781. {
  13782. return true;
  13783. }
  13784. else
  13785. {
  13786. if( AbsF( angle ) < MOUNT_ANGLE_EXP )
  13787. {
  13788. return true;
  13789. }
  13790. else
  13791. {
  13792. return false;
  13793. }
  13794. }
  13795. }
  13796. }
  13797. else
  13798. {
  13799. return false;
  13800. }
  13801. }
  13802.  
  13803. public function FollowActor( actor : CActor )
  13804. {
  13805. var l_aiTreeDecorator : CAIPlayerActionDecorator;
  13806. var l_aiTree_onFoot : CAIFollowSideBySideAction;
  13807. var l_aiTree_onHorse : CAIRiderFollowSideBySideAction;
  13808. var l_success : bool = false;
  13809.  
  13810. actor.AddTag( 'playerFollowing' );
  13811.  
  13812. if( thePlayer.IsUsingHorse() )
  13813. {
  13814. l_aiTree_onHorse = new CAIRiderFollowSideBySideAction in this;
  13815. l_aiTree_onHorse.OnCreated();
  13816.  
  13817. l_aiTree_onHorse.params.targetTag = 'playerFollowing';
  13818. }
  13819. else
  13820. {
  13821. l_aiTree_onFoot = new CAIFollowSideBySideAction in this;
  13822. l_aiTree_onFoot.OnCreated();
  13823.  
  13824. l_aiTree_onFoot.params.targetTag = 'playerFollowing';
  13825. }
  13826.  
  13827. l_aiTreeDecorator = new CAIPlayerActionDecorator in this;
  13828. l_aiTreeDecorator.OnCreated();
  13829. l_aiTreeDecorator.interruptOnInput = false;
  13830.  
  13831. if( thePlayer.IsUsingHorse() )
  13832. l_aiTreeDecorator.scriptedAction = l_aiTree_onHorse;
  13833. else
  13834. l_aiTreeDecorator.scriptedAction = l_aiTree_onFoot;
  13835.  
  13836. if( l_aiTreeDecorator )
  13837. l_success = ForceAIBehavior( l_aiTreeDecorator, BTAP_Emergency );
  13838. else if( thePlayer.IsUsingHorse() )
  13839. l_success = ForceAIBehavior( l_aiTree_onHorse, BTAP_Emergency );
  13840. else
  13841. l_success = ForceAIBehavior( l_aiTree_onFoot, BTAP_Emergency );
  13842.  
  13843. if ( l_success )
  13844. {
  13845. GetMovingAgentComponent().SetGameplayRelativeMoveSpeed( 0.0f );
  13846. }
  13847. }
  13848.  
  13849. public function SetCanFollowNpc( val : bool, actor : CActor ) { canFollowNpc = val; actorToFollow = actor; }
  13850. public function CanFollowNpc() : bool { return canFollowNpc; }
  13851. public function GetActorToFollow() : CActor { return actorToFollow; }
  13852.  
  13853. /*public function SetIsFollowing( val : bool )
  13854. {
  13855. isFollowing = val;
  13856.  
  13857. if( val )
  13858. followingStartTime = theGame.GetEngineTimeAsSeconds();
  13859. else
  13860. followingStartTime = 0.0;
  13861. }
  13862. public function GetFollowingStartTime() : float { return followingStartTime; }
  13863. public function IsFollowing() : bool { return isFollowing; }
  13864.  
  13865. timer function ResetIsFollowing( td : float, id : int )
  13866. {
  13867. isFollowing = false;
  13868. }*/
  13869.  
  13870. ////////////////////////////////////////////////////////////////////////////////////////////
  13871. ///////////////////// @SWIMMING ////////////////////////////////////////////////////////
  13872. ////////////////////////////////////////////////////////////////////////////////////////////
  13873.  
  13874. public function SetIsSwimming ( toggle : bool )
  13875. {
  13876. if( isSwimming != toggle )
  13877. {
  13878. thePlayer.substateManager.SetBehaviorParamBool( 'isSwimmingForOverlay', toggle );
  13879. isSwimming = toggle;
  13880. }
  13881. }
  13882. //public function IsSwimming () : bool { return isSwimming; }
  13883.  
  13884. ////////////////////////////////////////////////////////////////////////////////////////////
  13885. /////////////////////////// @DURABILITY //////////////////////////////////////////////////
  13886. ////////////////////////////////////////////////////////////////////////////////////////////
  13887.  
  13888. //returns true if repaired
  13889. public function RepairItemUsingConsumable(item, consumable : SItemUniqueId) : bool
  13890. {
  13891. inv.SetItemDurabilityScript(item, inv.GetItemMaxDurability(item));
  13892.  
  13893.  
  13894.  
  13895.  
  13896.  
  13897.  
  13898. if(HasBookPerk(S_Book_28))
  13899. max = max * (1 + (repairBonus + perkValue) /100);
  13900. */
  13901.  
  13902. return true;
  13903. }
  13904.  
  13905. ////////////////////////////////////////////////////////////////////////////////////////////
  13906. /////////////////////////// @PushingObject /////////////////////////////////////////////
  13907. ///////////////////////////////////////////////////////////////////////////////////////////
  13908. /*
  13909. event OnRigidBodyCollision( component : CComponent, actorIndex : int, shapeIndex : int )
  13910. {
  13911. pushableComponent = component;
  13912. if ( pushableComponent )
  13913. this.RaiseEvent('PushObject');
  13914.  
  13915. //component.ApplyForceAtPointToPhysicalObject
  13916. }
  13917.  
  13918. event OnRigidBodyExit( component : CComponent )
  13919. {
  13920. this.RaiseEvent('PushObjectEnd');
  13921. pushableComponent = NULL;
  13922. }
  13923.  
  13924. event OnPushObjectStart()
  13925. {
  13926. moveAdj = GetMovingAgentComponent().GetMovementAdjustor();
  13927. moveAdj.CancelAll();
  13928. pushRotTicket = moveAdj.CreateNewRequest( 'RotateToObject' );
  13929. moveAdj.MaxRotationAdjustmentSpeed(pushRotTicket,30);
  13930. moveAdj.Continuous(pushRotTicket);
  13931. moveAdj.DontEnd(pushRotTicket);
  13932. this.AddTimer('PushObjectUpdate',0.01,true, , , true);
  13933.  
  13934. }
  13935.  
  13936. event OnPushObjectStop()
  13937. {
  13938. this.RemoveTimer('PushObjectUpdate');
  13939. moveAdj.CancelByName('RotateToObject');
  13940. moveAdj = NULL;
  13941. }
  13942.  
  13943. timer function PushObjectUpdate( dt : float , id : int)
  13944. {
  13945. var impulse : Vector;
  13946. moveAdj.RotateTo( pushRotTicket, rawPlayerHeading );
  13947. impulse = this.GetHeadingVector()*10.0;
  13948. //impulse.Z += 0.5;
  13949. //pushableComponent.ApplyLocalImpulseToPhysicalObject(impulse);
  13950. }
  13951. */
  13952.  
  13953. ///////////////////////////////////////////////////////////////////////////////////////////
  13954. /////////////////////////// @DAY @NIGHT CYCLE CHECK /////////////////////////////////////
  13955. ///////////////////////////////////////////////////////////////////////////////////////////
  13956.  
  13957. private function CheckDayNightCycle()
  13958. {
  13959. var time : GameTime;
  13960. var isNight : bool;
  13961.  
  13962. //if changed
  13963. isNight = theGame.envMgr.IsNight();
  13964. if(prevDayNightIsNight != isNight)
  13965. {
  13966. if(isNight)
  13967. OnNightStarted();
  13968. else
  13969. OnDayStarted();
  13970.  
  13971. prevDayNightIsNight = isNight;
  13972. }
  13973.  
  13974. //schedule next call
  13975. if(isNight)
  13976. time = theGame.envMgr.GetGameTimeTillNextDay();
  13977. else
  13978. time = theGame.envMgr.GetGameTimeTillNextNight();
  13979.  
  13980. AddGameTimeTimer('DayNightCycle', time);
  13981. }
  13982.  
  13983. timer function DayNightCycle(dt : GameTime, id : int)
  13984. {
  13985. CheckDayNightCycle();
  13986. }
  13987.  
  13988. /*script*/ event OnNightStarted()
  13989. {
  13990. var pam : W3PlayerAbilityManager;
  13991.  
  13992. if(CanUseSkill(S_Perk_01))
  13993. {
  13994. pam = (W3PlayerAbilityManager)abilityManager;
  13995. pam.SetPerk01Abilities(false, true);
  13996. }
  13997. }
  13998.  
  13999. /*script*/ event OnDayStarted()
  14000. {
  14001. var pam : W3PlayerAbilityManager;
  14002.  
  14003. if(CanUseSkill(S_Perk_01))
  14004. {
  14005. pam = (W3PlayerAbilityManager)abilityManager;
  14006. pam.SetPerk01Abilities(true, false);
  14007. }
  14008. }
  14009.  
  14010. ///////////////////////////////////////////////////////////////////////////////////////////
  14011. /////////////////////////// @INPUT //////////////////////////////////////////////////////
  14012. ///////////////////////////////////////////////////////////////////////////////////////////
  14013.  
  14014. public function ForceUnlockAllInputActions(alsoQuestLocks : bool)
  14015. {
  14016. if ( inputHandler )
  14017. inputHandler.ForceUnlockAllInputActions(alsoQuestLocks);
  14018. }
  14019.  
  14020. public function SetPrevRawLeftJoyRot()
  14021. {
  14022. prevRawLeftJoyRot = rawLeftJoyRot;
  14023. }
  14024.  
  14025. public function GetPrevRawLeftJoyRot() : float
  14026. {
  14027. return prevRawLeftJoyRot;
  14028. }
  14029.  
  14030. public function GetExplorationInputContext() : name
  14031. {
  14032. return explorationInputContext;
  14033. }
  14034.  
  14035. public function GetCombatInputContext() : name
  14036. {
  14037. return combatInputContext;
  14038. }
  14039.  
  14040. ///////////////////////////////////////////////////////////////////////////////////////////
  14041. /////////////////////////// @EXPLORATION ////////////////////////////////////////////////
  14042. ///////////////////////////////////////////////////////////////////////////////////////////
  14043.  
  14044. public function SetIsOnBoat(b : bool)
  14045. {
  14046. isOnBoat = b;
  14047. }
  14048.  
  14049. public function IsOnBoat() : bool
  14050. {
  14051. return isOnBoat;
  14052. }
  14053.  
  14054. public function IsInShallowWater() : bool
  14055. {
  14056. return isInShallowWater;
  14057. }
  14058.  
  14059. event OnEnterShallowWater()
  14060. {
  14061. if ( isInShallowWater )
  14062. return false;
  14063.  
  14064. isInShallowWater = true;
  14065. BlockAction( EIAB_Dodge,'ShallowWater', false, false, true );
  14066. BlockAction( EIAB_Sprint,'ShallowWater', false, false, true );
  14067. BlockAction( EIAB_Crossbow,'ShallowWater', false, false, true );
  14068.  
  14069. //--===modJumpInShallowWater Begin===--
  14070. //BlockAction( EIAB_Jump,'ShallowWater', false, false, true );
  14071. //--===modJumpInShallowWater End===--
  14072. SetBehaviorVariable( 'shallowWater',1.0);
  14073. }
  14074. event OnExitShallowWater()
  14075. {
  14076. if ( !isInShallowWater )
  14077. return false;
  14078.  
  14079. isInShallowWater = false;
  14080. BlockAllActions('ShallowWater',false);
  14081. SetBehaviorVariable( 'shallowWater',0.0);
  14082. }
  14083.  
  14084. public function TestIsInSettlement() : bool
  14085. {
  14086. return IsInSettlement();
  14087. }
  14088.  
  14089. ///////////////////////////////////////////////////////////////////////////////////////////
  14090. /////////////////////////// GLOSSARY ////////////////////////////////////////////////
  14091. ///////////////////////////////////////////////////////////////////////////////////////////
  14092.  
  14093. //Processes glossary image filename and exchanges it with override if provided
  14094. public function ProcessGlossaryImageOverride( defaultImage : string, uniqueTag : name ) : string
  14095. {
  14096. var size : int;
  14097. var i : int;
  14098.  
  14099. size = glossaryImageOverride.Size();
  14100.  
  14101. if( size == 0 )
  14102. return defaultImage;
  14103.  
  14104. for( i = 0; i < size; i += 1 )
  14105. {
  14106. if( glossaryImageOverride[i].uniqueTag == uniqueTag )
  14107. return glossaryImageOverride[i].imageFileName;
  14108.  
  14109. }
  14110.  
  14111. return defaultImage;
  14112. }
  14113.  
  14114. //Adds glossary image override filename to array
  14115. public function EnableGlossaryImageOverride( uniqueTag : name, imageFileName : string, enable : bool )
  14116. {
  14117. var imageData : SGlossaryImageOverride;
  14118. var size : int;
  14119. var i : int;
  14120.  
  14121. for( i = 0; i < glossaryImageOverride.Size(); i += 1 )
  14122. {
  14123. if( glossaryImageOverride[i].uniqueTag == uniqueTag )
  14124. {
  14125. glossaryImageOverride.Remove(glossaryImageOverride[i]);
  14126. }
  14127. }
  14128.  
  14129. if( enable )
  14130. {
  14131. if( IsNameValid(uniqueTag) && imageFileName != "" )
  14132. {
  14133. glossaryImageOverride.PushBack( SGlossaryImageOverride( uniqueTag, imageFileName ) );
  14134. }
  14135. }
  14136. }
  14137. ///////////////////////////////////////////////////////////////////////////////////////////
  14138. /////////////////////////// MONSTER HUNT INVESTIGATION AREAS /////////////////////////////
  14139. ///////////////////////////////////////////////////////////////////////////////////////////
  14140.  
  14141. public function SetCurrentMonsterHuntInvestigationArea ( area : W3MonsterHuntInvestigationArea )
  14142. {
  14143. currentMonsterHuntInvestigationArea = area;
  14144. }
  14145.  
  14146.  
  14147. ///////////////////////////////////////////////////////////////////////////////////////////
  14148. /////////////////////////// BARBER SYSTEM CUSTOM HEAD /////////////////////////////
  14149. ///////////////////////////////////////////////////////////////////////////////////////////
  14150.  
  14151. public function RememberCustomHead( headName : name )
  14152. {
  14153. rememberedCustomHead = headName;
  14154. }
  14155.  
  14156. public function GetRememberedCustomHead() : name
  14157. {
  14158. return rememberedCustomHead;
  14159. }
  14160.  
  14161. public function ClearRememberedCustomHead()
  14162. {
  14163. rememberedCustomHead = '';
  14164. }
  14165.  
  14166. ///////////////////////////////////////////////////////////////////////////////////////////
  14167. /////////////////////////// @TUTORIAL ////////////////////////////////////////////////
  14168. ///////////////////////////////////////////////////////////////////////////////////////////
  14169.  
  14170. public function CreateTutorialInput()
  14171. {
  14172. var prevInputHandler : CPlayerInput;
  14173.  
  14174. prevInputHandler = inputHandler;
  14175. inputHandler = new W3PlayerTutorialInput in this;
  14176. inputHandler.Initialize(false, prevInputHandler);
  14177.  
  14178. if(prevInputHandler)
  14179. delete prevInputHandler;
  14180. }
  14181.  
  14182. public function CreateInput()
  14183. {
  14184. var oldInputHandler : CPlayerInput;
  14185.  
  14186. oldInputHandler = inputHandler;
  14187. inputHandler = new CPlayerInput in this;
  14188. inputHandler.Initialize(false, oldInputHandler);
  14189. }
  14190.  
  14191. timer function TutorialSilverCombat(dt : float, id : int)
  14192. {
  14193. var i : int;
  14194. var actors : array<CActor>;
  14195.  
  14196. if(IsInCombat())
  14197. {
  14198. actors = GetNPCsAndPlayersInRange(20, 1000000, ,FLAG_ExcludePlayer + FLAG_OnlyAliveActors);
  14199. for(i=0; i<actors.Size(); i+=1)
  14200. {
  14201. if(actors[i] && IsRequiredAttitudeBetween(this, actors[i], true) && actors[i].UsesEssence())
  14202. {
  14203. FactsAdd("TutorialShowSilver");
  14204.  
  14205. RemoveTimer('TutorialSilverCombat');
  14206. break;
  14207. }
  14208. }
  14209. }
  14210. }
  14211.  
  14212. private saved var m_bossTag : name;
  14213.  
  14214. public function GetBossTag() : name
  14215. {
  14216. return m_bossTag;
  14217. }
  14218.  
  14219. public function SetBossTag( bossTag : name )
  14220. {
  14221. m_bossTag = bossTag;
  14222. }
  14223.  
  14224. private saved var m_usingCoatOfArms : bool; default m_usingCoatOfArms = false;
  14225.  
  14226. public function IsUsingCoatOfArms() : bool
  14227. {
  14228. return m_usingCoatOfArms;
  14229. }
  14230.  
  14231. public function SetUsingCoatOfArms( using : bool)
  14232. {
  14233. m_usingCoatOfArms = using;
  14234. }
  14235.  
  14236. private saved var m_initialTimeOut : float;
  14237. private saved var m_currentTimeOut : float;
  14238.  
  14239. public function GetInitialTimeOut() : float
  14240. {
  14241. return m_initialTimeOut;
  14242. }
  14243.  
  14244. public function SetInitialTimeOut( timeOut : float )
  14245. {
  14246. m_initialTimeOut = timeOut;
  14247. }
  14248.  
  14249. public function GetCurrentTimeOut() : float
  14250. {
  14251. return m_currentTimeOut;
  14252. }
  14253.  
  14254. public function SetCurrentTimeOut( timeOut : float )
  14255. {
  14256. m_currentTimeOut = timeOut;
  14257. }
  14258.  
  14259.  
  14260. ///////////////////////////////////////////////////////////////////////////////////////////
  14261. /////////////////////////// @FINISHERS ////////////////////////////////////////////
  14262. ///////////////////////////////////////////////////////////////////////////////////////////
  14263.  
  14264. timer function DelayedFinisherInputTimer(dt : float, id : int)
  14265. {
  14266. //theGame.SetTimeScale( 0.1, theGame.GetTimescaleSource(ETS_FinisherInput), theGame.GetTimescalePriority(ETS_FinisherInput) );
  14267. //GetFinisherVictim().EnableFinishComponent( true );
  14268. }
  14269.  
  14270. timer function RemoveFinisherCameraAnimationCheck(dt : float, id : int)
  14271. {
  14272. if ( !isInFinisher && !bLAxisReleased )
  14273. {
  14274. theGame.GetSyncAnimManager().OnRemoveFinisherCameraAnimation();
  14275. RemoveTimer( 'RemoveFinisherCameraAnimationCheck' );
  14276. }
  14277. }
  14278.  
  14279. ///////////////////////////////////////////////////////////////////////////////////////////
  14280. /////////////////////////// @DEBUG @TIMERS ////////////////////////////////////////////
  14281. ///////////////////////////////////////////////////////////////////////////////////////////
  14282.  
  14283. timer function GameplayFactRemove(dt : float, timerId : int)
  14284. {
  14285. theGame.GameplayFactRemoveFromTimer(timerId);
  14286. }
  14287.  
  14288. //gives NORMAL starting inventory
  14289. timer function GiveStartingItems(dt : float, timerId : int)
  14290. {
  14291. var template : CEntityTemplate;
  14292. var invEntity : CInventoryComponent;
  14293. var entity : CEntity;
  14294. var items : array<SItemUniqueId>;
  14295. var id : SItemUniqueId;
  14296. var i : int;
  14297.  
  14298. //wait for inventory to init
  14299. if(inv)
  14300. {
  14301. inv.GetAllItems(items);
  14302. if(items.Size() <= 0)
  14303. {
  14304. return;
  14305. }
  14306. }
  14307. else
  14308. {
  14309. return;
  14310. }
  14311.  
  14312. //add items
  14313. template = (CEntityTemplate)LoadResource("geralt_inventory_release");
  14314. entity = theGame.CreateEntity(template, Vector(0,0,0));
  14315. invEntity = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent');
  14316.  
  14317. invEntity.GetAllItems(items);
  14318. for(i=0; i<items.Size(); i+=1)
  14319. {
  14320. id = invEntity.GiveItemTo(inv, items[i], 0, false, true);
  14321. if ( inv.ItemHasTag(id,'Scabbard') )
  14322. {
  14323. inv.MountItem(id);
  14324. }
  14325. else if(!inv.IsItemFists(id) && inv.GetItemName(id) != 'Cat 1') //hack for cat potion - don't equip!
  14326. {
  14327. EquipItem(id);
  14328. }
  14329. else if(inv.IsItemSingletonItem(id))
  14330. {
  14331. inv.SingletonItemSetAmmo(id, inv.SingletonItemGetMaxAmmo(id));
  14332. }
  14333. }
  14334.  
  14335. entity.Destroy();
  14336.  
  14337. //remove timer
  14338. RemoveTimer('GiveStartingItems');
  14339. }
  14340.  
  14341. //Adds items used for testing. Won't be called in final release. Items are added from geralt_inventory entity.
  14342. //Works as a timer since we need to wait for inventory to init and there is no such event.
  14343. timer function Debug_GiveTestingItems(dt : float, optional id : int)
  14344. {
  14345. var template : CEntityTemplate;
  14346. var invTesting : CInventoryComponent;
  14347. var entity : CEntity;
  14348. var items : array<SItemUniqueId>;
  14349. var i : int;
  14350. var slot : EEquipmentSlots;
  14351.  
  14352. //wait for inventory to init
  14353. if(inv)
  14354. {
  14355. inv.GetAllItems(items);
  14356. if(items.Size() <= 0)
  14357. {
  14358. return;
  14359. }
  14360. }
  14361. else
  14362. {
  14363. return;
  14364. }
  14365.  
  14366. template = (CEntityTemplate)LoadResource("geralt_inventory_internal");
  14367. entity = theGame.CreateEntity(template, Vector(0,0,0));
  14368. invTesting = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent');
  14369. invTesting.GiveAllItemsTo(inv, true);
  14370. entity.Destroy();
  14371.  
  14372. //once called remove the timer
  14373. RemoveTimer('Debug_GiveTestingItems');
  14374.  
  14375. //equip crossbow, bombs and bolts, select bolts
  14376. inv.GetAllItems(items);
  14377.  
  14378. for(i=0; i<items.Size(); i+=1)
  14379. {
  14380. if( inv.IsItemCrossbow(items[i]) || inv.IsItemBomb(items[i]) )
  14381. {
  14382. slot = inv.GetSlotForItemId(items[i]);
  14383. EquipItem(items[i], slot);
  14384.  
  14385. if( (W3PlayerWitcher)this && inv.IsItemCrossbow(items[i]) )
  14386. GetWitcherPlayer().SelectQuickslotItem(slot);
  14387. }
  14388. else if(inv.IsItemBolt(items[i]))
  14389. {
  14390. slot = inv.GetSlotForItemId(items[i]);
  14391. EquipItem(items[i], slot);
  14392. }
  14393.  
  14394. if(inv.IsItemSingletonItem(items[i]))
  14395. {
  14396. inv.SingletonItemSetAmmo(items[i], inv.SingletonItemGetMaxAmmo(items[i]));
  14397. }
  14398. }
  14399. }
  14400.  
  14401. //called in tutorial in not final version to remove testing items
  14402. timer function Debug_RemoveTestingItems(dt : float, id : int)
  14403. {
  14404. var template : CEntityTemplate;
  14405. var entity : CEntity;
  14406. var invTesting : CInventoryComponent;
  14407. var ids : array<SItemUniqueId>;
  14408. var i : int;
  14409.  
  14410. template = (CEntityTemplate)LoadResource("geralt_inventory_internal");
  14411. entity = theGame.CreateEntity(template, Vector(0,0,0));
  14412. invTesting = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent');
  14413. invTesting.GetAllItems(ids);
  14414.  
  14415. for(i=0; i<ids.Size(); i+=1)
  14416. inv.RemoveItemByName(invTesting.GetItemName(ids[i]), invTesting.GetItemQuantity(ids[i]));
  14417.  
  14418. entity.Destroy();
  14419. RemoveTimer('Debug_RemoveTestingItems');
  14420. }
  14421.  
  14422. timer function Debug_DelayedConsoleCommand(dt : float, id : int)
  14423. {
  14424. //inv.AddAnItem('Recipe for Mutagen 23');
  14425. inv.AddAnItem('Boots 2 schematic');
  14426. }
  14427.  
  14428. function DBG_SkillSlots()
  14429. {
  14430. ((W3PlayerAbilityManager)abilityManager).DBG_SkillSlots();
  14431. }
  14432.  
  14433. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14434. //////////////////////////////// @BACKLIGHT COLOR ////////////////////////////////////////////////////////////////////
  14435. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14436.  
  14437. public final function SetPadBacklightColor(r, g, b : int)
  14438. {
  14439. var padBacklightColor : Vector;
  14440.  
  14441. padBacklightColor.X = r / 255;
  14442. padBacklightColor.Y = g / 255;
  14443. padBacklightColor.Z = b / 255;
  14444.  
  14445. SetBacklightColor(padBacklightColor);
  14446. }
  14447.  
  14448. public final function SetPadBacklightColorFromSign(signType : ESignType)
  14449. {
  14450. LogPS4Light("SetPadBacklightColorFromSign... " + signType);
  14451.  
  14452. switch(signType)
  14453. {
  14454. case ST_Yrden: SetPadBacklightColor( 200 , 81 , 255 ); break; // Violet
  14455. case ST_Quen: SetPadBacklightColor( 255 , 205 , 68 ); break; // Yellow
  14456. case ST_Igni: SetPadBacklightColor( 255 , 79 , 10 ); break; // Orange
  14457. case ST_Axii: SetPadBacklightColor( 255 , 255 , 255 ); break; // White
  14458. case ST_Aard: SetPadBacklightColor( 158 , 214 , 255 ); break; // Blue
  14459. }
  14460. }
  14461.  
  14462. timer function ResetPadBacklightColorTimer(dt : float, id : int)
  14463. {
  14464. ResetPadBacklightColor();
  14465. }
  14466.  
  14467. public final function ResetPadBacklightColor(optional skipHeldWeapon : bool)
  14468. {
  14469. var weapons : array<SItemUniqueId>;
  14470. var sword : CWitcherSword;
  14471. var healthPercentage : float;
  14472. var tmpBacklight : Vector;
  14473.  
  14474. if(!skipHeldWeapon)
  14475. {
  14476. weapons = inv.GetHeldWeapons();
  14477.  
  14478. //if holding a sword the default backlight color matches the one set in sword entity
  14479. if(weapons.Size() > 0)
  14480. {
  14481. sword = (CWitcherSword)inv.GetItemEntityUnsafe(weapons[0]);
  14482. if(sword)
  14483. {
  14484. tmpBacklight.X = sword.padBacklightColor.X / 255.0f;
  14485. tmpBacklight.Y = sword.padBacklightColor.Y / 255.0f;
  14486. tmpBacklight.Z = sword.padBacklightColor.Z / 255.0f;
  14487. tmpBacklight.W = 1.0f;
  14488. SetBacklightColor( tmpBacklight );
  14489. LogPS4Light("Setting light from sword template: " + NoTrailZeros(sword.padBacklightColor.X) + ", " + NoTrailZeros(sword.padBacklightColor.Y) + ", " + NoTrailZeros(sword.padBacklightColor.Z) );
  14490. return;
  14491. }
  14492. }
  14493. }
  14494.  
  14495. healthPercentage = GetStatPercents( BCS_Vitality );
  14496. SetBacklightFromHealth( healthPercentage );
  14497. LogPS4Light("Setting light from health, " + NoTrailZeros(RoundMath(healthPercentage*100)) + "%");
  14498. }
  14499.  
  14500. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14501.  
  14502. event OnOpenningDoor()
  14503. {
  14504. if( !thePlayer.IsUsingHorse() )
  14505. RaiseEvent('OpenDoor');
  14506. }
  14507.  
  14508. public var loopingCameraShakeAnimName : name;
  14509. timer function RemoveQuestCameraShakeTimer( dt : float , id : int)
  14510. {
  14511. RemoveQuestCameraShake( loopingCameraShakeAnimName );
  14512. }
  14513.  
  14514. public function RemoveQuestCameraShake( animName : name )
  14515. {
  14516. var camera : CCustomCamera = theGame.GetGameCamera();
  14517. var animation : SCameraAnimationDefinition;
  14518.  
  14519. camera.StopAnimation( animName );
  14520. }
  14521.  
  14522. public function GetCameraPadding() : float
  14523. {
  14524. if( theGame.IsFocusModeActive() )
  14525. {
  14526. return 0.25; // Tweaked for [108933] Geralt is being clipped when using focus mode while running towards camera.
  14527. }
  14528. else
  14529. {
  14530. return 0.02f; // Tweaked for [114907] Player dissolving while aiming crossbow.
  14531. }
  14532. }
  14533.  
  14534. public function IsPerformingPhaseChangeAnimation() : bool { return isPerformingPhaseChangeAnimation; }
  14535. public function SetIsPerformingPhaseChangeAnimation( val : bool ) { isPerformingPhaseChangeAnimation = val; }
  14536.  
  14537. private function DealCounterDamageToOlgierd()
  14538. {
  14539. var damage : W3DamageAction;
  14540.  
  14541. damage = new W3DamageAction in this;
  14542.  
  14543. damage.Initialize( thePlayer.GetTarget(), thePlayer.GetTarget(), NULL, this, EHRT_None, CPS_Undefined, false, false, false, true );
  14544. damage.AddDamage( theGame.params.DAMAGE_NAME_DIRECT, thePlayer.GetTarget().GetStatMax( BCS_Vitality ) * 3 / 100 );
  14545. theGame.damageMgr.ProcessAction( damage );
  14546.  
  14547. delete damage;
  14548. }
  14549.  
  14550. timer function PlayDelayedCounterDamageEffect( dt : float, id : int )
  14551. {
  14552. thePlayer.GetTarget().PlayEffect( 'olgierd_energy_blast' );
  14553. }
  14554.  
  14555. // TEST
  14556. public function SetTestAdjustRequestedMovementDirection( val : bool )
  14557. {
  14558. testAdjustRequestedMovementDirection = val;
  14559. }
  14560.  
  14561. event OnVisualDebug( frame : CScriptedRenderFrame, flag : EShowFlags )
  14562. {
  14563. var boneFollow : int;
  14564. var bonePosition : Vector;
  14565. var yrdenEntity : W3YrdenEntity;
  14566.  
  14567. substateManager.OnVisualDebug( frame, flag );
  14568.  
  14569. boneFollow = thePlayer.GetBoneIndex( 'Reference' );
  14570. bonePosition = MatrixGetTranslation( thePlayer.GetBoneWorldMatrixByIndex( boneFollow ) );
  14571. frame.DrawText( "R", bonePosition, Color( 50, 200, 70 ) );
  14572. //frame.DrawText( "R", bonePositionCam, Color( 200, 50, 70 ) );
  14573.  
  14574. boneFollow = thePlayer.GetBoneIndex( 'Trajectory' );
  14575. bonePosition = MatrixGetTranslation( thePlayer.GetBoneWorldMatrixByIndex( boneFollow ) );
  14576. frame.DrawSphere( bonePosition, 0.1f, Color( 200, 50, 70 ) );
  14577. frame.DrawText( "T", bonePosition, Color( 200, 50, 70 ) );
  14578.  
  14579. //frame.DrawSphere( lastSafePosition, 1.0f, Color( 50, 200, 70 ) );
  14580. //frame.DrawText( "SavePos", lastSafePosition, Color( 50, 200, 70 ) );
  14581.  
  14582. yrdenEntity = (W3YrdenEntity)GetWitcherPlayer().GetSignEntity(ST_Yrden);
  14583. yrdenEntity.OnVisualDebug(frame, flag, false);
  14584.  
  14585. return true;
  14586. }
  14587.  
  14588. timer function PotDrinkTimer(dt : float, id : int)
  14589. {
  14590. inputHandler.PotDrinkTimer(false);
  14591. }
  14592.  
  14593. public function SetIsHorseRacing( val : bool )
  14594. {
  14595. isHorseRacing = val;
  14596. }
  14597.  
  14598. public function GetIsHorseRacing() : bool
  14599. {
  14600. return isHorseRacing;
  14601. }
  14602.  
  14603. public function SetHorseCombatSlowMo( val : bool )
  14604. {
  14605. horseCombatSlowMo = val;
  14606. }
  14607.  
  14608. public function GetHorseCombatSlowMo() : bool
  14609. {
  14610. return horseCombatSlowMo;
  14611. }
  14612.  
  14613. public function SetItemsPerLevelGiven( id : int )
  14614. {
  14615. itemsPerLevelGiven[id] = true;
  14616. }
  14617.  
  14618. private function AddItemPerLevelList()
  14619. {
  14620. var i : int;
  14621.  
  14622. itemsPerLevel.Clear();
  14623. itemsPerLevel.PushBack('O');
  14624. itemsPerLevel.PushBack('No Mans Land sword 2');
  14625. itemsPerLevel.PushBack('No Mans Land sword 3');
  14626. itemsPerLevel.PushBack('Silver sword 2');
  14627. itemsPerLevel.PushBack('Boots 01');
  14628. itemsPerLevel.PushBack('Novigraadan sword 2');
  14629. itemsPerLevel.PushBack('Light armor 01');
  14630. itemsPerLevel.PushBack('Heavy boots 01');
  14631. itemsPerLevel.PushBack('Nilfgaardian sword 3');
  14632. itemsPerLevel.PushBack('Silver sword 3');
  14633. itemsPerLevel.PushBack('Heavy gloves 01');
  14634. itemsPerLevel.PushBack('Skellige sword 2');
  14635. itemsPerLevel.PushBack('Heavy pants 01');
  14636. itemsPerLevel.PushBack('Silver sword 4');
  14637. itemsPerLevel.PushBack('No Mans Land sword 4');
  14638. itemsPerLevel.PushBack('Heavy armor 01');
  14639. itemsPerLevel.PushBack('Heavy boots 02');
  14640. itemsPerLevel.PushBack('Skellige sword 3');
  14641. itemsPerLevel.PushBack('Silver sword 5');
  14642. itemsPerLevel.PushBack('Heavy pants 02');
  14643. itemsPerLevel.PushBack('Heavy gloves 02');
  14644. itemsPerLevel.PushBack('Heavy gloves 02');
  14645. itemsPerLevel.PushBack('Heavy armor 02');
  14646. itemsPerLevel.PushBack('Scoiatael sword 1');
  14647.  
  14648. if ( itemsPerLevelGiven.Size() < 49 )
  14649. {
  14650. itemsPerLevelGiven.Clear();
  14651. for (i = 0; i < itemsPerLevel.Size(); i += 1) { itemsPerLevelGiven.PushBack( false ); }
  14652. }
  14653. }
  14654.  
  14655. // TEMP
  14656. public function DealDamageToBoat( dmg : float, index : int, optional globalHitPos : Vector )
  14657. {
  14658. var boat : CBoatDestructionComponent;
  14659.  
  14660. if(usedVehicle)
  14661. {
  14662. boat = (CBoatDestructionComponent) usedVehicle.GetComponentByClassName( 'CBoatDestructionComponent' );
  14663. if( boat )
  14664. {
  14665. boat.DealDamage( dmg, index, globalHitPos );
  14666. }
  14667. }
  14668. }
  14669.  
  14670. ////////////////////////////////////////////////////////////////////////////////
  14671. //
  14672. // PLAYABLE AREA
  14673. //
  14674. public function OnStartTeleportingPlayerToPlayableArea()
  14675. {
  14676. var FADEOUT_INTERVAL : float = 0.5;
  14677.  
  14678. // if we jumped on horse right before being teleported, we need to disable falling damage because height difference may kill us
  14679. if ( thePlayer.IsUsingHorse() )
  14680. {
  14681. if ( thePlayer.GetUsedHorseComponent().OnCheckHorseJump() )
  14682. {
  14683. thePlayer.GetUsedHorseComponent().SetCanTakeDamageFromFalling( false );
  14684. }
  14685. }
  14686.  
  14687. if ( thePlayer.IsActionAllowed( EIAB_FastTravel ) )
  14688. {
  14689. OnOpenMapToLetPlayerGoBackToPlayableArea();
  14690. }
  14691. else
  14692. {
  14693. theGame.FadeOutAsync( FADEOUT_INTERVAL );
  14694. thePlayer.AddTimer( 'BorderTeleportFadeOutTimer', FADEOUT_INTERVAL, false );
  14695. }
  14696. }
  14697.  
  14698. timer function BorderTeleportFadeOutTimer( dt : float, id : int )
  14699. {
  14700. OnTeleportPlayerToPlayableArea( false );
  14701. }
  14702.  
  14703. public function OnOpenMapToLetPlayerGoBackToPlayableArea()
  14704. {
  14705. var initData : W3MapInitData;
  14706.  
  14707. initData = new W3MapInitData in this;
  14708. initData.SetTriggeredExitEntity( true );
  14709. initData.ignoreSaveSystem = true;
  14710. initData.setDefaultState('FastTravel');
  14711. theGame.RequestMenuWithBackground( 'MapMenu', 'CommonMenu', initData );
  14712. }
  14713.  
  14714. public function OnTeleportPlayerToPlayableArea( afterClosingMap : bool )
  14715. {
  14716. var BLACKSCREEN_INTERVAL : float = 0.5;
  14717. var manager : CCommonMapManager = theGame.GetCommonMapManager();
  14718.  
  14719. theGame.FadeOutAsync( 0 );
  14720. thePlayer.TeleportWithRotation( manager.GetBorderTeleportPosition(), manager.GetBorderTeleportRotation() );
  14721. thePlayer.AddTimer( 'BorderTeleportFadeInTimer', BLACKSCREEN_INTERVAL, false );
  14722. }
  14723.  
  14724. timer function BorderTeleportFadeInTimer( dt : float, id : int )
  14725. {
  14726. var FADEIN_INTERVAL : float = 0.5;
  14727.  
  14728. theGame.FadeInAsync( FADEIN_INTERVAL );
  14729. }
  14730.  
  14731. public final function SetLastInstantKillTime(g : GameTime)
  14732. {
  14733. lastInstantKillTime = g;
  14734. }
  14735. //
  14736. //
  14737. //
  14738. ////////////////////////////////////////////////////////////////////////////////
  14739.  
  14740. timer function TestTimer(dt : float, id : int )
  14741. {
  14742. LogChannel('asdf', "asdf");
  14743. theGame.FadeOutAsync( 5 );
  14744. }
  14745.  
  14746. public final function Debug_ReleaseCriticalStateSaveLocks()
  14747. {
  14748. effectManager.Debug_ReleaseCriticalStateSaveLocks();
  14749. }
  14750.  
  14751. timer function Debug_SpamSpeed(dt : float, id : int)
  14752. {
  14753. if(currentlyMountedHorse)
  14754. {
  14755. LogSpeed("curr player's horse speed: " + NoTrailZeros(currentlyMountedHorse.GetMovingAgentComponent().GetSpeed())) ;
  14756. }
  14757. else
  14758. {
  14759. LogSpeed("curr player speed: " + NoTrailZeros(GetMovingAgentComponent().GetSpeed())) ;
  14760. }
  14761. }
  14762.  
  14763. timer function RemoveInstantKillSloMo(dt : float, id : int)
  14764. {
  14765. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_InstantKill) );
  14766. }
  14767.  
  14768. timer function RemoveForceFinisher(dt : float, id : int)
  14769. {
  14770. forceFinisher = false;
  14771. }
  14772.  
  14773. public final function Debug_ClearAllActionLocks(optional action : EInputActionBlock, optional all : bool)
  14774. {
  14775. inputHandler.Debug_ClearAllActionLocks(action, all);
  14776. }
  14777.  
  14778. function OnFocusedCameraBlendBegin() {}
  14779. function OnFocusedCameraBlendUpdate( progress : float ) {}
  14780. function OnFocusedCameraBlendEnd() {}
  14781.  
  14782. public function GetEtherealCount() : int { return etherealCount; }
  14783. public function IncrementEtherealCount()
  14784. {
  14785. etherealCount += 1;
  14786. if( etherealCount == 6 )
  14787. ResetEtherealCount();
  14788. }
  14789. public function ResetEtherealCount() { etherealCount = 0; }
  14790.  
  14791. // PHANTOM WEAPON
  14792. //------------------------------------------------------------------------------------------------------------------
  14793. public function InitPhantomWeaponMgr()
  14794. {
  14795. if( !phantomWeaponMgr )
  14796. {
  14797. phantomWeaponMgr = new CPhantomWeaponManager in this;
  14798. phantomWeaponMgr.Init( this.GetInventory() );
  14799. }
  14800. }
  14801.  
  14802. public function DestroyPhantomWeaponMgr()
  14803. {
  14804. if( phantomWeaponMgr )
  14805. {
  14806. delete phantomWeaponMgr;
  14807. }
  14808. }
  14809.  
  14810. public function GetPhantomWeaponMgr() : CPhantomWeaponManager
  14811. {
  14812. if( phantomWeaponMgr )
  14813. {
  14814. return phantomWeaponMgr;
  14815. }
  14816. else
  14817. {
  14818. return NULL;
  14819. }
  14820. }
  14821.  
  14822. public timer function DischargeWeaponAfter( td : float, id : int )
  14823. {
  14824. GetPhantomWeaponMgr().DischargeWeapon();
  14825. }
  14826. //------------------------------------------------------------------------------------------------------------------
  14827. }
  14828.  
  14829. exec function ttt
  14830. {
  14831. thePlayer.AddTimer( 'TestTimer', 5, false );
  14832. }
Add Comment
Please, Sign In to add comment