chingchong0

Untitled

Aug 25th, 2021
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 441.05 KB | None | 0 0
  1. statemachine abstract import class CR4Player extends CPlayer
  2. {
  3. // BEHAVIOR INITIALIZATION
  4. protected var pcGamePlayInitialized : bool; // MS: hack variable to fix Tpose when initially spawning Geralt (Consult Tomsin)
  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 bonePositionCam : Vector;
  196.  
  197. public function SetBonePositionCam( pos : Vector )
  198. {
  199. bonePositionCam = pos;
  200. }*/
  201.  
  202. function EnablePCMode( flag : bool )
  203. {
  204. pcMode = flag;
  205. }
  206.  
  207. public function IsPCModeEnabled() : bool
  208. {
  209. return pcMode && theInput.LastUsedPCInput();
  210. }
  211.  
  212. public function ShouldUsePCModeTargeting() : bool
  213. {
  214. return IsPCModeEnabled() && !lastAxisInputIsMovement;
  215. }
  216.  
  217. public function SetDodgeFeedbackTarget( target : CActor )
  218. {
  219. dodgeFeedbackTarget = target;
  220. }
  221.  
  222. public function GetDodgeFeedbackTarget() : CActor
  223. {
  224. return dodgeFeedbackTarget;
  225. }
  226.  
  227. public function SetSubmergeDepth( depth : float )
  228. {
  229. submergeDepth = depth;
  230. }
  231.  
  232. public function GetSubmergeDepth() : float
  233. {
  234. return submergeDepth;
  235. }
  236.  
  237. // ONELINERS
  238. editable var delayBetweenIllusionOneliners : float;
  239.  
  240. hint delayBetweenIllusionOneliners = "delay in secs between oneliners about illusionary objects";
  241.  
  242. default delayBetweenIllusionOneliners = 5;
  243.  
  244. // Battlecry
  245. private var battlecry_timeForNext : float;
  246. private var battlecry_delayMin : float; default battlecry_delayMin = 15;
  247. private var battlecry_delayMax : float; default battlecry_delayMax = 60;
  248. private var battlecry_lastTry : name;
  249.  
  250. // Weather
  251. private var previousWeather : name;
  252. private var previousRainStrength : float;
  253.  
  254. //OTHER
  255. protected var receivedDamageInCombat : bool; //set when you got hit
  256. protected var prevDayNightIsNight : bool; //Day-Night cycle check - value of previous check
  257. public var failedFundamentalsFirstAchievementCondition : bool; //achievement
  258.  
  259. private var spawnedTime : float;
  260.  
  261. public var currentMonsterHuntInvestigationArea : W3MonsterHuntInvestigationArea;
  262.  
  263. private var isPerformingPhaseChangeAnimation : bool; // flag for suppressing game camera update during synced animation in eredin fight
  264. default isPerformingPhaseChangeAnimation = false;
  265.  
  266. default receivedDamageInCombat = false;
  267.  
  268. // PLAYER MODE
  269. public var playerMode : W3PlayerMode;
  270.  
  271. // QUICKSLOTS
  272. protected saved var selectedItemId : SItemUniqueId; //id of item selected from quickslots
  273. protected saved var blockedRadialSlots : array < SRadialSlotDef >; // radial menu slots blocked by different sources
  274.  
  275. // SOFT LOCK TARGETING
  276. public var enemyCollectionDist : float;
  277. public var findMoveTargetDistMin : float; //distance from player to get softlocked targets
  278. public var findMoveTargetDistMax : float; //distance from player that target gets disengaged from soft lock
  279. private var findMoveTargetScaledFrame : float; //xaxis scale to find non-hostile targets when stationary
  280. public var interactDist : float; //distance from player to attack or interact with a non-hostile npc
  281. protected var bCanFindTarget : bool;
  282. private var bIsConfirmingEmptyTarget : bool;
  283. private var displayTarget : CGameplayEntity; //entity to show health bar on hud;
  284. private var isShootingFriendly : bool;
  285.  
  286. default findMoveTargetDistMax = 18.f;
  287. default findMoveTargetScaledFrame = 0.5f;
  288. default interactDist = 3.5f;
  289.  
  290. //Target Selection
  291. private var currentSelectedTarget : CActor;
  292. private var selectedTargetToConfirm : CActor;
  293. private var bConfirmTargetTimerIsEnabled : bool;
  294.  
  295. // THROWABLES
  296. public saved var thrownEntityHandle : EntityHandle; //entity of currently thrown item (in aiming)
  297. private var isThrowingItemWithAim : bool;
  298. private saved var isThrowingItem : bool; //used for aim mode to check if we're in throwing logic
  299. private var isThrowHoldPressed : bool;
  300.  
  301. // CROSSBOW
  302. private var isAimingCrossbow : bool;
  303.  
  304. default isThrowingItemWithAim = false;
  305.  
  306. // AIMING MODE
  307. public var playerAiming : PlayerAiming;
  308.  
  309. // DISMEMBERMENT
  310. public var forceDismember : bool;
  311. public var forceDismemberName : name;
  312. public var forceDismemberChance : int;
  313. public var forceDismemberExplosion : bool;
  314.  
  315. // FINISHER
  316. private var finisherVictim : CActor;
  317. public var forceFinisher : bool;
  318. public var forceFinisherAnimName : name;
  319. public var forceFinisherChance : int;
  320. public var forcedStance : bool;
  321.  
  322. // WEAPON COLLISION FX
  323. private var m_WeaponFXCollisionGroupNames : array <name>;
  324. private var m_CollisionEffect : CEntity;
  325. private var m_LastWeaponTipPos : Vector;
  326. private var m_CollisionFxTemplate : CEntityTemplate;
  327. private var m_RefreshWeaponFXType : bool;
  328. private var m_PlayWoodenFX : bool;
  329.  
  330. // POSTERS
  331. private var m_activePoster : W3Poster;
  332.  
  333. public function SetActivePoster ( poster : W3Poster )
  334. {
  335. m_activePoster = poster;
  336. }
  337.  
  338. public function RemoveActivePoster ()
  339. {
  340. m_activePoster = NULL;
  341. }
  342.  
  343. public function GetActivePoster () : W3Poster
  344. {
  345. return m_activePoster;
  346. }
  347. // SAVE / LOAD
  348. //private saved var safePositionStored: bool; default safePositionStored = false;
  349. //private saved var lastSafePosition : Vector;
  350. //private saved var lastSafeRotation : EulerAngles;
  351.  
  352. public var horseOnNavMesh : bool;
  353. default horseOnNavMesh = true;
  354.  
  355. public function SetHorseNav( val : bool ) { horseOnNavMesh = val; }
  356.  
  357. // TEST
  358. public var testAdjustRequestedMovementDirection : bool; // TEST
  359. default testAdjustRequestedMovementDirection = false;
  360.  
  361. // State
  362. default autoState = 'Exploration';
  363.  
  364. ///////////////////////////////////////////////////////////////////////////
  365. /////////////////// IMPORTED C++ FUNCTIONS //////////////////////////////
  366. ///////////////////////////////////////////////////////////////////////////
  367.  
  368. // All following functions give cached data from previous frame
  369. import final function GetEnemiesInRange( out enemies : array< CActor > );
  370. import final function GetVisibleEnemies( out enemies : array< CActor > );
  371. import final function IsEnemyVisible( enemy : CActor ) : bool;
  372.  
  373. // Set this up in order to use above functions and get the proper data
  374. import final function SetupEnemiesCollection( range, heightTolerance : float,
  375. maxEnemies : int,
  376. optional tag : name,
  377. optional flags : int ); // please combine EScriptQueryFlags - FLAG_ExcludePlayer is always on
  378.  
  379. import final function IsInInterior() : bool;
  380. import final function IsInSettlement() : bool;
  381. import final function EnterSettlement( isEntering : bool );
  382. import final function ActionDirectControl( controller : CR4LocomotionDirectController ) : bool;
  383. import final function SetPlayerTarget( target : CActor );
  384. import final function SetPlayerCombatTarget( target : CActor );
  385. import final function ObtainTicketFromCombatTarget( ticketName : CName, ticketsCount : int );
  386. import final function FreeTicketAtCombatTarget();
  387. import final function SetScriptMoveTarget( target : CActor );
  388. import final function GetRiderData() : CAIStorageRiderData;
  389. import final function SetIsInCombat( inCombat : bool );
  390. import final function SaveLastMountedHorse( mountedHorse : CActor );
  391.  
  392. import final function SetBacklightFromHealth( healthPercentage : float );
  393. import private final function SetBacklightColor( color : Vector );
  394.  
  395. import final function GetCombatDataComponent() : CCombatDataComponent;
  396.  
  397. import final function GetTemplatePathAndAppearance( out templatePath : string, out appearance : name );
  398.  
  399. import final function HACK_BoatDismountPositionCorrection( slotPos : Vector );
  400.  
  401. import final function HACK_ForceGetBonePosition( boneIndex : int ) : Vector;
  402.  
  403.  
  404. public function GetLevel() : int
  405. {
  406. return 0;
  407. }
  408.  
  409. ///////////////////////////////////////////////////////////////////////////
  410. // (new) targeting
  411.  
  412. var targeting : CR4PlayerTargeting;
  413. var targetingPrecalcs : SR4PlayerTargetingPrecalcs;
  414. var targetingIn : SR4PlayerTargetingIn;
  415. var targetingOut : SR4PlayerTargetingOut;
  416. var useNativeTargeting : bool;
  417. default useNativeTargeting = true;
  418.  
  419. var visibleActors : array< CActor >;
  420. var visibleActorsTime : array< float >;
  421.  
  422. ///////////////////////////////////////////////////////////////////////////
  423.  
  424. event OnSpawned( spawnData : SEntitySpawnData )
  425. {
  426. var atts : array<name>;
  427. var skill : ESkill;
  428. var i : int;
  429. var item : SItemUniqueId;
  430.  
  431. AddAnimEventCallback('ThrowHoldTest', 'OnAnimEvent_ThrowHoldTest');
  432. AddAnimEventCallback('OnWeaponDrawReady', 'OnAnimEvent_OnWeaponDrawReady');
  433. AddAnimEventCallback('OnWeaponHolsterReady', 'OnAnimEvent_OnWeaponHolsterReady');
  434. AddAnimEventCallback('AllowTempLookAt', 'OnAnimEvent_AllowTempLookAt');
  435. AddAnimEventCallback('SlideToTarget', 'OnAnimEvent_SlideToTarget');
  436. AddAnimEventCallback('PlayFinisherBlood', 'OnAnimEvent_PlayFinisherBlood');
  437. AddAnimEventCallback('SlowMo', 'OnAnimEvent_SlowMo');
  438. AddAnimEventCallback('BloodTrailForced', 'OnAnimEvent_BloodTrailForced');
  439. AddAnimEventCallback('FadeOut', 'OnAnimEvent_FadeOut');
  440. AddAnimEventCallback('FadeIn', 'OnAnimEvent_FadeIn');
  441. AddAnimEventCallback('DisallowHitAnim', 'OnAnimEvent_DisallowHitAnim');
  442. AddAnimEventCallback('AllowFall', 'OnAnimEvent_AllowFall');
  443. AddAnimEventCallback('AllowFall2', 'OnAnimEvent_AllowFall2');
  444. AddAnimEventCallback('DettachGround', 'OnAnimEvent_DettachGround');
  445. AddAnimEventCallback('KillWithRagdoll', 'OnAnimEvent_KillWithRagdoll');
  446. AddAnimEventCallback('pad_vibration', 'OnAnimEvent_pad_vibration');
  447. AddAnimEventCallback('pad_vibration_light', 'OnAnimEvent_pad_vibration_light');
  448. AddAnimEventCallback('RemoveBurning', 'OnAnimEvent_RemoveBurning');
  449. AddAnimEventCallback('RemoveTangled', 'OnAnimEvent_RemoveTangled');
  450.  
  451. AddItemPerLevelList();
  452.  
  453. enemyCollectionDist = findMoveTargetDistMax;
  454.  
  455. //give items
  456. if(!spawnData.restored && !((W3ReplacerCiri)this) )
  457. {
  458. AddTimer('GiveStartingItems', 0.00001, true, , , true);
  459.  
  460. if(!theGame.IsFinalBuild())
  461. {
  462. //unlock skills for testing purposes
  463. AddAbility('GeraltSkills_Testing');
  464. AddTimer('Debug_GiveTestingItems',0.0001,true);
  465. }
  466. }
  467.  
  468. InitTargeting();
  469.  
  470. // After load
  471. if( spawnData.restored )
  472. {
  473. // ED this line was not called before, because of extra if conditions regarding "safe position stored" but it was uncommented
  474. //OnUseSelectedItem();
  475. }
  476.  
  477.  
  478. // Create the sword holster (it is a saved property, there is no need of re-creating it when playing from save)
  479. if ( !weaponHolster )
  480. {
  481. weaponHolster = new WeaponHolster in this;
  482. }
  483. // temp workaround of not saving states:
  484. weaponHolster.Initialize( this, spawnData.restored );
  485.  
  486. if ( !interiorTracker )
  487. {
  488. interiorTracker = new CPlayerInteriorTracker in this;
  489. }
  490. interiorTracker.Init( spawnData.restored );
  491.  
  492.  
  493. super.OnSpawned( spawnData );
  494.  
  495. // Create medallion
  496. medallion = new W3MedallionFX in this;
  497.  
  498. playerMode = new W3PlayerMode in this;
  499. playerMode.Initialize( this );
  500.  
  501. // Initialize Aiming Mode
  502. playerAiming = new PlayerAiming in this;
  503. playerAiming.Initialize( this );
  504.  
  505. // Initialize reachability query
  506. navQuery = new CNavigationReachabilityQueryInterface in this;
  507.  
  508. // Start looking for soft-lock targets
  509. EnableFindTarget( true );
  510. AddTimer( 'CombatCheck', 0.2f, true );
  511.  
  512. // Get the exploration state manager component
  513. substateManager = ( CExplorationStateManager ) GetComponentByClassName( 'CExplorationStateManager' );
  514.  
  515. findMoveTargetDist = findMoveTargetDistMax;
  516.  
  517. SetupEnemiesCollection( enemyCollectionDist, findMoveTargetDist, 10, 'None', FLAG_Attitude_Neutral + FLAG_Attitude_Hostile + FLAG_Attitude_Friendly + FLAG_OnlyAliveActors );
  518.  
  519. //for geralt-replacer switching
  520. inputHandler.RemoveLocksOnSpawn();
  521.  
  522. // Player has the lowest push priority
  523. ((CActor) this ).SetInteractionPriority( IP_Prio_0 );
  524.  
  525. prevDayNightIsNight = theGame.envMgr.IsNight();
  526. CheckDayNightCycle();
  527.  
  528. // Debug
  529. EnableVisualDebug( SHOW_AI, true );
  530.  
  531. //oneliners delay
  532. FactsRemove("blocked_illusion_oneliner");
  533.  
  534. SetFailedFundamentalsFirstAchievementCondition(false);
  535. m_CollisionFxTemplate = (CEntityTemplate) LoadResource( 'sword_colision_fx' );
  536. if( m_WeaponFXCollisionGroupNames.Size() == 0 )
  537. {
  538. m_WeaponFXCollisionGroupNames.PushBack('Static');
  539. m_WeaponFXCollisionGroupNames.PushBack('Foliage');
  540. m_WeaponFXCollisionGroupNames.PushBack('Fence');
  541. m_WeaponFXCollisionGroupNames.PushBack('BoatSide');
  542. m_WeaponFXCollisionGroupNames.PushBack('Door');
  543. m_WeaponFXCollisionGroupNames.PushBack('RigidBody');
  544. m_WeaponFXCollisionGroupNames.PushBack('Dynamic');
  545. m_WeaponFXCollisionGroupNames.PushBack('Destructible');
  546. }
  547.  
  548. if ( counterCollisionGroupNames.Size() == 0 )
  549. {
  550. counterCollisionGroupNames.PushBack('Static');
  551. counterCollisionGroupNames.PushBack('Foliage');
  552. counterCollisionGroupNames.PushBack('Fence');
  553. counterCollisionGroupNames.PushBack('Terrain');
  554. counterCollisionGroupNames.PushBack('Door');
  555. counterCollisionGroupNames.PushBack('RigidBody');
  556. counterCollisionGroupNames.PushBack('Dynamic');
  557. counterCollisionGroupNames.PushBack('Destructible');
  558. }
  559.  
  560. //ps4 pad backlight color
  561. ResetPadBacklightColor();
  562.  
  563. if( spawnData.restored )
  564. {
  565. if (IsCurrentlyUsingItemL())
  566. {
  567. if (inv.HasItemById( currentlyEquipedItemL ))
  568. {
  569. OnUseSelectedItem();
  570. }
  571. else
  572. {
  573. HideUsableItem(true);
  574. }
  575. }
  576. if ( GetCurrentMeleeWeaponType() == PW_Steel || GetCurrentMeleeWeaponType() == PW_Silver )
  577. {
  578. OnEquipMeleeWeapon(GetCurrentMeleeWeaponType(), true, true);
  579. }
  580.  
  581. AddTimer( 'UnmountCrossbowTimer', 0.01, true );
  582.  
  583. ClearBlockedSlots();
  584. }
  585.  
  586. ((CR4PlayerStateSwimming)this.GetState('Swimming')).OnParentSpawned();
  587.  
  588. //hack for possible immortality from finishers
  589. SetImmortalityMode( AIM_None, AIC_SyncedAnim );
  590.  
  591. //disable Dimeritium Bomb skill locks after load
  592. theGame.GetDefinitionsManager().GetContainedAbilities('DwimeritiumBomb_3', atts);
  593. for(i=0; i<atts.Size(); i+=1)
  594. {
  595. skill = SkillNameToEnum(atts[i]);
  596. if(skill != S_SUndefined)
  597. BlockSkill(skill, false);
  598. }
  599.  
  600. // phantom weapon manager
  601. this.GetInventory().GetItemEquippedOnSlot( EES_SteelSword, item );
  602. if( this.GetInventory().ItemHasTag( item, 'PhantomWeapon' ) )
  603. {
  604. this.InitPhantomWeaponMgr();
  605. }
  606.  
  607. //retoractive fix
  608. if(FactsQuerySum("mq3036_fact_done") > 0)
  609. BlockAllActions('mq3036', false);
  610.  
  611. spawnedTime = theGame.GetEngineTimeAsSeconds();
  612.  
  613. if ( theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'EnableUberMovement' ) == "1" )
  614. theGame.EnableUberMovement( true );
  615. else
  616. theGame.EnableUberMovement( false );
  617.  
  618. // Initial level for Gwint Difficulty (Normal)
  619. if ( !FactsDoesExist("gwent_difficulty") )
  620. FactsAdd("gwent_difficulty", 2);
  621. }
  622.  
  623. public function GetTimeSinceSpawned() : float
  624. {
  625. return theGame.GetEngineTimeAsSeconds() - spawnedTime;
  626. }
  627.  
  628. timer function UnmountCrossbowTimer( dt : float, id : int )
  629. {
  630. var itemId : SItemUniqueId;
  631.  
  632. itemId = this.inv.GetItemFromSlot( 'l_weapon' );
  633. if ( inv.IsIdValid( itemId ) && inv.IsItemCrossbow( itemId ) )
  634. {
  635. rangedWeapon = (Crossbow)( inv.GetItemEntityUnsafe( itemId ) );
  636.  
  637. if (rangedWeapon)
  638. {
  639. rangedWeapon.Initialize( (CActor)( rangedWeapon.GetParentEntity() ) );
  640. OnRangedForceHolster( true, true );
  641. RemoveTimer( 'UnmountCrossbowTimer' );
  642. }
  643. }
  644. else
  645. RemoveTimer( 'UnmountCrossbowTimer' );
  646. }
  647.  
  648. event OnDestroyed()
  649. {
  650. playerAiming.RemoveAimingSloMo();
  651.  
  652. if(rangedWeapon)
  653. rangedWeapon.ClearDeployedEntity(true);
  654.  
  655. ResetPadBacklightColor();
  656.  
  657. //remove combat mode no-save lock
  658. theGame.ReleaseNoSaveLock( noSaveLock );
  659. }
  660.  
  661. /////////////////////////////////////////////////////////////////////
  662. ////////////////////////Radial Menu//////////////////////////////////
  663. ////////////////////////////////////////////////////////////////////
  664.  
  665. public function GetBlockedSlots () : array < SRadialSlotDef >
  666. {
  667. return blockedRadialSlots;
  668. }
  669.  
  670. public function ClearBlockedSlots()
  671. {
  672. var i : int;
  673. //var blockedSigns : array<ESignType>;
  674. //var playerWitcher : W3PlayerWitcher;
  675.  
  676. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  677. {
  678. if( !IsSwimming() )
  679. {
  680. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'swimming'))
  681. {
  682. i-=1;
  683. continue;
  684. }
  685. }
  686. if (!IsUsingVehicle())
  687. {
  688. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'useVehicle'))
  689. {
  690. i-=1;
  691. continue;
  692. }
  693. }
  694. if ( !IsCurrentlyUsingItemL() || !IsUsableItemLBlocked() )
  695. {
  696. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'usableItemL'))
  697. {
  698. i-=1;
  699. continue;
  700. }
  701. }
  702. if ( !IsThrowingItem() )
  703. {
  704. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'throwBomb'))
  705. {
  706. i-=1;
  707. continue;
  708. }
  709. }
  710. }
  711. // 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.
  712. /*playerWitcher = (W3PlayerWitcher)this;
  713.  
  714. if ( playerWitcher )
  715. {
  716. blockedSigns = playerWitcher.GetBlockedSigns();
  717.  
  718. i = 0;
  719. for ( i = 0; i < blockedSigns.Size(); i+=1 )
  720. {
  721. switch( blockedSigns[i] )
  722. {
  723. case ST_Aard :
  724. if ( !IsRadialSlotBlocked ( 'Aard') )
  725. {
  726. playerWitcher.BlockSignSelection(ST_Aard, false);
  727. }
  728. break;
  729. case ST_Axii :
  730. if ( !IsRadialSlotBlocked ( 'Axii') )
  731. {
  732. playerWitcher.BlockSignSelection(ST_Axii, false );
  733. }
  734. break;
  735. case ST_Igni :
  736. if ( !IsRadialSlotBlocked ( 'Igni') )
  737. {
  738. playerWitcher.BlockSignSelection(ST_Igni, false );
  739. }
  740. break;
  741. case ST_Quen :
  742. if ( !IsRadialSlotBlocked ( 'Quen') )
  743. {
  744. playerWitcher.BlockSignSelection(ST_Quen, false );
  745. }
  746. break;
  747. case ST_Yrden :
  748. if ( !IsRadialSlotBlocked ( 'Yrden') )
  749. {
  750. playerWitcher.BlockSignSelection(ST_Yrden, false );
  751. }
  752. break;
  753. default:
  754. break;
  755. }
  756. }
  757. }*/
  758.  
  759. }
  760.  
  761. public function RestoreBlockedSlots ()
  762. {
  763. var i : int;
  764. var slotsToBlock : array<name>;
  765.  
  766. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  767. {
  768. slotsToBlock.PushBack ( blockedRadialSlots[i].slotName );
  769. }
  770. if ( slotsToBlock.Size() > 0 )
  771. {
  772. EnableRadialSlots ( false, slotsToBlock );
  773. }
  774. }
  775. private function DisableRadialSlot ( slotName : name, sourceName : name ) : bool
  776. {
  777. var i : int;
  778. var k : int;
  779. var slotsToBlock : array<name>;
  780.  
  781. var blockedRadialSlotEntry : SRadialSlotDef;
  782.  
  783. slotsToBlock.PushBack ( slotName );
  784.  
  785. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  786. {
  787. if ( blockedRadialSlots[i].slotName == slotName )
  788. {
  789. if ( sourceName != '' )
  790. {
  791. for ( k = 0; k < blockedRadialSlots[i].disabledBySources.Size(); k += 1 )
  792. {
  793. if ( blockedRadialSlots[i].disabledBySources[k] == sourceName )
  794. {
  795. return false;
  796. }
  797. }
  798. blockedRadialSlots[i].disabledBySources.PushBack ( sourceName );
  799. return false;
  800. }
  801.  
  802. return false;
  803. }
  804. }
  805.  
  806. blockedRadialSlotEntry = InitBlockedRadialSlotEntry ( slotName );
  807.  
  808. if ( sourceName != '' )
  809. {
  810. blockedRadialSlotEntry.disabledBySources.PushBack ( sourceName );
  811. }
  812. blockedRadialSlots.PushBack ( blockedRadialSlotEntry );
  813. EnableRadialSlots ( false, slotsToBlock );
  814. return true;
  815. }
  816.  
  817. public function EnableRadialSlot ( slotName : name, sourceName : name ) : bool
  818. {
  819. var i : int;
  820. var k : int;
  821.  
  822. var slotsToBlock : array<name>;
  823.  
  824. slotsToBlock.PushBack ( slotName );
  825.  
  826. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  827. {
  828. if ( blockedRadialSlots[i].slotName == slotName )
  829. {
  830.  
  831. if ( sourceName != '' )
  832. {
  833. for ( k = 0; k < blockedRadialSlots[i].disabledBySources.Size(); k += 1 )
  834. {
  835. if ( blockedRadialSlots[i].disabledBySources[k] == sourceName )
  836. {
  837. blockedRadialSlots[i].disabledBySources.Remove ( blockedRadialSlots[i].disabledBySources[k] );
  838. }
  839. }
  840. }
  841. if ( blockedRadialSlots[i].disabledBySources.Size() <= 0 )
  842. {
  843. blockedRadialSlots.Remove( blockedRadialSlots[i] );
  844. EnableRadialSlots ( true, slotsToBlock );
  845. return true;
  846. }
  847. return false;
  848. }
  849. }
  850. return false;
  851.  
  852. }
  853.  
  854. private function InitBlockedRadialSlotEntry ( slotName : name ) : SRadialSlotDef
  855. {
  856. var blockedRadialSlotEntry : SRadialSlotDef;
  857.  
  858. blockedRadialSlotEntry.slotName = slotName;
  859.  
  860. return blockedRadialSlotEntry;
  861.  
  862. }
  863.  
  864. public function EnableRadialSlotsWithSource ( enable : bool, slotsToBlock : array < name >, sourceName : name )
  865. {
  866. var i : int;
  867.  
  868. for ( i = 0; i < slotsToBlock.Size(); i+=1 )
  869. {
  870. if ( enable )
  871. {
  872. EnableRadialSlot ( slotsToBlock[i], sourceName );
  873. }
  874. else
  875. {
  876. DisableRadialSlot ( slotsToBlock[i], sourceName );
  877. }
  878. }
  879. if ( blockedRadialSlots.Size() <= 0 )
  880. {
  881. blockedRadialSlots.Clear();
  882. }
  883. }
  884.  
  885. public function IsRadialSlotBlocked ( slotName : name ) : bool
  886. {
  887. var i : int;
  888.  
  889. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  890. {
  891. if ( blockedRadialSlots[i].slotName == slotName )
  892. {
  893. return true;
  894. }
  895. }
  896. return false;
  897. }
  898.  
  899.  
  900. /////////////////////////////////////////////////////////////////////
  901. ////////////////////////////////////////////////////////////////////
  902. /////////////////////// @Reapir Kits ////////////////////////////////////
  903. ////////////////////////////////////////////////////////////////////
  904. public function RepairItem ( rapairKitId : SItemUniqueId, usedOnItem : SItemUniqueId );
  905. public function HasRepairAbleGearEquiped () : bool;
  906. public function HasRepairAbleWaponEquiped () : bool;
  907. public function IsItemRepairAble ( item : SItemUniqueId ) : bool;
  908.  
  909. /////////////////////////////////////////////////////////////////////
  910. ////////////////////////////////////////////////////////////////////
  911. /////////////////////// @OILS ////////////////////////////////////
  912. ////////////////////////////////////////////////////////////////////
  913. public function ApplyOil( oilId : SItemUniqueId, usedOnItem : SItemUniqueId );
  914. public function IsEquippedSwordUpgradedWithOil(steel : bool, optional oilName : name) : bool;
  915. public function GetOilAppliedOnSword(steel : bool) : name;
  916.  
  917. public function CanApplyOilOnItem(oilId : SItemUniqueId, usedOnItem : SItemUniqueId) : bool
  918. {
  919. if(inv.ItemHasTag(oilId, theGame.params.TAG_STEEL_OIL) && inv.IsItemSteelSwordUsableByPlayer(usedOnItem))
  920. return true;
  921.  
  922. if(inv.ItemHasTag(oilId, theGame.params.TAG_SILVER_OIL) && inv.IsItemSilverSwordUsableByPlayer(usedOnItem))
  923. return true;
  924.  
  925. return false;
  926. }
  927. ////////////////////////////////////////////////////////////////////
  928.  
  929. public final function DidFailFundamentalsFirstAchievementCondition() : bool
  930. {
  931. return failedFundamentalsFirstAchievementCondition;
  932. }
  933.  
  934. public final function SetFailedFundamentalsFirstAchievementCondition(b : bool)
  935. {
  936. var i : int;
  937. var npc : CNewNPC;
  938.  
  939. failedFundamentalsFirstAchievementCondition = b;
  940.  
  941. //save info in enemy since we might run away from combat and return, triggering new combat encounter
  942. if(failedFundamentalsFirstAchievementCondition)
  943. {
  944. for(i=0; i<hostileEnemies.Size(); i+=1)
  945. {
  946. if(hostileEnemies[i].HasTag(theGame.params.MONSTER_HUNT_ACTOR_TAG))
  947. {
  948. npc = (CNewNPC)hostileEnemies[i];
  949. npc.AddTag('failedFundamentalsAchievement');
  950. npc.AddTimer('FundamentalsAchFailTimer', 30*60, , , , true, true);
  951. }
  952. }
  953. }
  954. }
  955.  
  956. public function IsInCombatFist() : bool
  957. {
  958. return this.GetCurrentStateName() == 'CombatFists';
  959. }
  960.  
  961. public function IsInitialized() : bool;
  962.  
  963. public function IsCiri() : bool
  964. {
  965. return ((W3ReplacerCiri)this);
  966. }
  967.  
  968. protected function WouldLikeToMove() : bool
  969. {
  970. var speedVec : Vector;
  971. var speed, speedMult : float;
  972.  
  973. // Get speed from input
  974. speedVec.X = theInput.GetActionValue( 'GI_AxisLeftX' ); //player.mainInput.aLeftJoyX;
  975. speedVec.Y = theInput.GetActionValue( 'GI_AxisLeftY' );//player.mainInput.aLeftJoyY;
  976. speed = VecLength2D( speedVec );
  977.  
  978. return speed > 0.1f;
  979. }
  980.  
  981. function HandleMovement( deltaTime : float )
  982. {
  983. // just to see if player would like to move if there would be possibility
  984. // example of use: movement is blocked when in critical state, but it can end earlier only if it would be desired by player
  985. // and this is nothing but desire to move
  986. // note: for some reason, when doing WouldLikeToMove()? 1.0f : 0.0f it just doesn't care and gives 0.0f
  987. if (WouldLikeToMove())
  988. SetBehaviorVariable( 'playerWouldLikeToMove', 1.0f);
  989. else
  990. SetBehaviorVariable( 'playerWouldLikeToMove', 0.0f);
  991.  
  992. super.HandleMovement( deltaTime );
  993. }
  994.  
  995. function BattleCryIsReady( ) : bool
  996. {
  997. var l_currentTime : float;
  998.  
  999. l_currentTime = theGame.GetEngineTimeAsSeconds();
  1000.  
  1001. if( l_currentTime >= battlecry_timeForNext )
  1002. {
  1003. return true;
  1004. }
  1005. return false;
  1006. }
  1007.  
  1008. function PlayBattleCry( _BattleCry : name , _Chance : float, optional _IgnoreDelay, ignoreRepeatCheck : bool )
  1009. {
  1010. var l_randValue : float;
  1011. var fact : int;
  1012.  
  1013. fact = FactsQuerySum("force_stance_normal");
  1014.  
  1015. if( IsSwimming()
  1016. || theGame.IsDialogOrCutscenePlaying()
  1017. || IsInNonGameplayCutscene()
  1018. || IsInGameplayScene()
  1019. || theGame.IsCurrentlyPlayingNonGameplayScene()
  1020. || theGame.IsFading()
  1021. || theGame.IsBlackscreen()
  1022. || FactsQuerySum("force_stance_normal") > 0 )
  1023. {
  1024. return;
  1025. }
  1026.  
  1027. // To avoid calling too often the same type of battle cry
  1028. if ( !ignoreRepeatCheck )
  1029. {
  1030. if( battlecry_lastTry == _BattleCry )
  1031. return;
  1032. }
  1033.  
  1034. battlecry_lastTry = _BattleCry;
  1035.  
  1036. l_randValue = RandF();
  1037.  
  1038. // Either use delay or chance
  1039. if( l_randValue < _Chance && ( _IgnoreDelay || BattleCryIsReady() ) )
  1040. {
  1041. thePlayer.PlayVoiceset( 90, _BattleCry );
  1042. // Restart counter
  1043. battlecry_timeForNext = theGame.GetEngineTimeAsSeconds() + RandRangeF( battlecry_delayMax, battlecry_delayMin );
  1044. }
  1045.  
  1046. }
  1047.  
  1048. public final function OnWeatherChanged()
  1049. {
  1050. if( IsInInterior()
  1051. || GetCurrentStateName() != 'Exploration'
  1052. || theGame.IsDialogOrCutscenePlaying()
  1053. || IsInNonGameplayCutscene()
  1054. || IsInGameplayScene()
  1055. || theGame.IsCurrentlyPlayingNonGameplayScene()
  1056. || theGame.IsFading()
  1057. || theGame.IsBlackscreen()
  1058. || GetTimeSinceSpawned() < 60 )
  1059. {
  1060. return;
  1061. }
  1062.  
  1063. AddTimer( 'CommentOnWeather', 1 );
  1064. }
  1065.  
  1066. public final timer function CommentOnWeather( _Delta : float, _Id : int )
  1067. {
  1068. var l_weather : name;
  1069. var l_currentArea : EAreaName;
  1070. var l_rand : float;
  1071.  
  1072. l_weather = GetWeatherConditionName();
  1073.  
  1074. l_currentArea = theGame.GetCommonMapManager().GetCurrentArea();
  1075.  
  1076. switch ( l_weather )
  1077. {
  1078. case 'WT_Clear':
  1079.  
  1080. l_rand = RandF();
  1081.  
  1082. if( l_rand > 0.66f && !AreaIsCold() && theGame.envMgr.IsDay() )
  1083. {
  1084. thePlayer.PlayVoiceset( 90, 'WeatherHot' );
  1085. }
  1086. else if ( l_rand > 0.33f )
  1087. {
  1088. thePlayer.PlayVoiceset( 90, 'WeatherClearingUp' );
  1089. }
  1090. break;
  1091.  
  1092. case 'WT_Rain_Storm':
  1093. thePlayer.PlayVoiceset( 90, 'WeatherStormy' );
  1094. break;
  1095.  
  1096. case 'WT_Light_Clouds':
  1097. if( previousRainStrength < GetRainStrength() )
  1098. {
  1099. thePlayer.PlayVoiceset( 90, 'WeatherLooksLikeRain' );
  1100. }
  1101. else if( AreaIsCold() && previousWeather == 'WT_Clear' )
  1102. {
  1103. thePlayer.PlayVoiceset( 90, 'WeatherCold' );
  1104. }
  1105. break;
  1106.  
  1107. case 'WT_Mid_Clouds':
  1108. if( previousRainStrength < GetRainStrength() )
  1109. {
  1110. thePlayer.PlayVoiceset( 90, 'WeatherRaining' );
  1111. }
  1112. else if( AreaIsCold() && previousWeather == 'WT_Clear' )
  1113. {
  1114. thePlayer.PlayVoiceset( 90, 'WeatherCold' );
  1115. }
  1116. break;
  1117.  
  1118. case 'WT_Mid_Clouds_Dark':
  1119. if( previousWeather != 'WT_Heavy_Clouds' && previousWeather != 'WT_Heavy_Clouds_Dark' )
  1120. thePlayer.PlayVoiceset( 90, 'WeatherWindy' );
  1121. break;
  1122.  
  1123. case 'WT_Heavy_Clouds':
  1124. if( previousWeather != 'WT_Mid_Clouds_Dark' && previousWeather != 'WT_Heavy_Clouds_Dark' )
  1125. thePlayer.PlayVoiceset( 90, 'WeatherWindy' );
  1126. break;
  1127.  
  1128. case 'WT_Heavy_Clouds_Dark':
  1129. if( thePlayer.IsOnBoat() )
  1130. {
  1131. thePlayer.PlayVoiceset( 90, 'WeatherSeaWillStorm' );
  1132. }
  1133. else if( previousRainStrength < GetRainStrength() )
  1134. {
  1135. thePlayer.PlayVoiceset( 90, 'WeatherLooksLikeRain' );
  1136. }
  1137. else
  1138. {
  1139. thePlayer.PlayVoiceset( 90, 'WeatherWindy' );
  1140. }
  1141. break;
  1142.  
  1143. case 'WT_Snow':
  1144. if( RandF() > 0.5f )
  1145. thePlayer.PlayVoiceset( 90, 'WeatherSnowy' );
  1146. else
  1147. thePlayer.PlayVoiceset( 90, 'WeatherCold' );
  1148. break;
  1149. }
  1150.  
  1151. previousRainStrength = GetRainStrength();
  1152. previousWeather = l_weather;
  1153. }
  1154.  
  1155. function CanUpdateMovement() : bool
  1156. {
  1157. if ( rangedWeapon
  1158. && GetBehaviorVariable( 'fullBodyAnimWeight' ) >= 1.f
  1159. && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  1160. return false;
  1161.  
  1162. return true;
  1163. }
  1164.  
  1165. public function SetDefaultLocomotionController()
  1166. {
  1167. if( !defaultLocomotionController )
  1168. {
  1169. defaultLocomotionController = new CR4LocomotionPlayerControllerScript in this;
  1170. }
  1171.  
  1172. ActionDirectControl( defaultLocomotionController );
  1173. }
  1174.  
  1175. event OnPlayerTickTimer( deltaTime : float )
  1176. {
  1177. var focusModeController : CFocusModeController;
  1178. var cnt : int;
  1179.  
  1180. super.OnPlayerTickTimer( deltaTime );
  1181.  
  1182. HandleMovement( deltaTime );
  1183.  
  1184. if ( playerAiming.GetCurrentStateName() == 'Aiming' )
  1185. {
  1186. FindTarget();
  1187. FindNonActorTarget( false );
  1188. UpdateDisplayTarget();
  1189. UpdateLookAtTarget();
  1190. }
  1191. else
  1192. {
  1193. if( playerTickTimerPhase == 0 )
  1194. {
  1195. FindTarget();
  1196. }
  1197. else if( playerTickTimerPhase == 1 )
  1198. {
  1199. FindNonActorTarget( false );
  1200. }
  1201. else if ( playerTickTimerPhase == 2 )
  1202. {
  1203. UpdateDisplayTarget();
  1204. UpdateLookAtTarget();
  1205. }
  1206. }
  1207.  
  1208. //CombatModeDebug();
  1209.  
  1210. playerTickTimerPhase = ( playerTickTimerPhase + 1 ) % 3;
  1211.  
  1212. focusModeController = theGame.GetFocusModeController();
  1213. focusModeController.UpdateFocusInteractions( deltaTime );
  1214.  
  1215. //some behavior hack for critical states, moved from effectsManager.PerformUpdate() since it does not tick continuously anymore
  1216. cnt = (int)( effectManager.GetCriticalBuffsCount() > 0 );
  1217. SetBehaviorVariable('hasCriticalBuff', cnt);
  1218. }
  1219.  
  1220. event OnDeath( damageAction : W3DamageAction )
  1221. {
  1222. super.OnDeath( damageAction );
  1223.  
  1224. RemoveTimer('RequestCriticalAnimStart');
  1225. //theInput.SetContext('Death');
  1226. EnableFindTarget( false );
  1227. BlockAllActions('Death', true);
  1228.  
  1229. EnableHardLock( false );
  1230.  
  1231. theGame.CreateNoSaveLock( 'player_death', deathNoSaveLock, false, false );
  1232. theGame.SetDeathSaveLockId( deathNoSaveLock );
  1233.  
  1234. ClearHostileEnemiesList();
  1235. RemoveReactions();
  1236. SetPlayerCombatTarget(NULL);
  1237. OnEnableAimingMode( false );
  1238. }
  1239.  
  1240. // Called when the actor gets out of unconscious state
  1241. function OnRevived()
  1242. {
  1243. super.OnRevived();
  1244. BlockAllActions('Death', false);
  1245.  
  1246. theGame.ReleaseNoSaveLock(deathNoSaveLock);
  1247.  
  1248. this.RestartReactionsIfNeeded();
  1249. }
  1250.  
  1251. public function CanStartTalk() : bool
  1252. {
  1253. if ( beingWarnedBy.Size() > 0 )
  1254. return false;
  1255.  
  1256. return super.CanStartTalk();
  1257. }
  1258.  
  1259. ///////////////////////////////////////////////////////////////////////////
  1260. // @Counters
  1261. ///////////////////////////////////////////////////////////////////////////
  1262.  
  1263. //caches timestamp of counter use (button press)
  1264. public function AddCounterTimeStamp(time : EngineTime) {counterTimestamps.PushBack(time);}
  1265.  
  1266. /*
  1267. This function checks if we have performed a counter
  1268. It checks timestamps of moments when we pressed the parry/counter button in order
  1269. to determine if the player was spamming the button. If so then this is not a counter.
  1270.  
  1271. Returns true if the counter is valid
  1272. */
  1273. public function CheckCounterSpamming(attacker : CActor) : bool
  1274. {
  1275. var counterWindowStartTime : EngineTime; //the time when the counter window (in anim) started
  1276. var i, spamCounter : int;
  1277. var reflexAction : bool;
  1278. var testEngineTime : EngineTime;
  1279.  
  1280. if(!attacker)
  1281. return false;
  1282.  
  1283. counterWindowStartTime = ((CNewNPC)attacker).GetCounterWindowStartTime();
  1284. spamCounter = 0;
  1285. reflexAction = false;
  1286.  
  1287. //if counterWindowStartTime was never set return false - PF
  1288. if ( counterWindowStartTime == testEngineTime )
  1289. {
  1290. return false;
  1291. }
  1292.  
  1293. for(i = counterTimestamps.Size() - 1; i>=0; i-=1)
  1294. {
  1295. //log number of button presses since 0.4 seconds before the counter timewindow
  1296. if(counterTimestamps[i] >= (counterWindowStartTime - EngineTimeFromFloat(0.4)) )
  1297. {
  1298. spamCounter += 1;
  1299. }
  1300. //and at the same time remove all outdated data on the fly
  1301. else
  1302. {
  1303. counterTimestamps.Remove(counterTimestamps[i]);
  1304. continue;
  1305. }
  1306.  
  1307. //set info that we have a potential parry if this press was after the counter timewindow started
  1308. if(!reflexAction && (counterTimestamps[i] >= counterWindowStartTime))
  1309. reflexAction = true;
  1310. }
  1311.  
  1312. /*
  1313. If reflexAction is set then we have at least 1 button press within the counter timewindow.
  1314.  
  1315. As for the spam counter:
  1316. 0 means no button was pressed - no counter
  1317. 1 means exactly one button press - a potential counter (if reflexAction is set as well)
  1318. >1 means spamming
  1319. */
  1320. if(spamCounter == 1 && reflexAction)
  1321. return true;
  1322.  
  1323. return false;
  1324. }
  1325.  
  1326. protected function PerformCounterCheck(parryInfo: SParryInfo) : bool
  1327. {
  1328. var mult : float;
  1329. var parryType : EParryType;
  1330. var validCounter, useKnockdown : bool;
  1331. var slideDistance, duration : float;
  1332. var playerToTargetRot : EulerAngles;
  1333. var zDifference : float;
  1334. var effectType : EEffectType;
  1335. var repelType : EPlayerRepelType = PRT_Random;
  1336. var params : SCustomEffectParams;
  1337. var thisPos, attackerPos : Vector;
  1338. var fistFightCheck : bool;
  1339. var fistFightCounter : bool;
  1340. var attackerInventory : CInventoryComponent;
  1341. var weaponId : SItemUniqueId;
  1342. var weaponTags : array<name>;
  1343. var playerToAttackerVector : Vector;
  1344. var tracePosStart : Vector;
  1345. var tracePosEnd : Vector;
  1346. var hitPos : Vector;
  1347. var hitNormal : Vector;
  1348.  
  1349. if(ShouldProcessTutorial('TutorialDodge') || ShouldProcessTutorial('TutorialCounter'))
  1350. {
  1351. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) );
  1352. FactsRemove("tut_fight_slomo_ON");
  1353. }
  1354.  
  1355. if ( !parryInfo.canBeParried || parryInfo.attacker.HasAbility( 'CannotBeCountered' ) )
  1356. return false;
  1357.  
  1358. fistFightCheck = FistFightCheck( parryInfo.target, parryInfo.attacker, fistFightCounter );
  1359.  
  1360. if( ParryCounterCheck() && parryInfo.targetToAttackerAngleAbs < theGame.params.PARRY_HALF_ANGLE && fistFightCheck )
  1361. {
  1362. //check if this is a valid counter
  1363. validCounter = CheckCounterSpamming(parryInfo.attacker);
  1364.  
  1365. if(validCounter)
  1366. {
  1367. if ( IsInCombatActionFriendly() )
  1368. RaiseEvent('CombatActionFriendlyEnd');
  1369.  
  1370. SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) );
  1371. SetBehaviorVariable( 'counter', (float)validCounter); //1/true when the parry is a counter/reflex_parry
  1372.  
  1373. //PPPP counter success sound
  1374. //SoundEvent("global_machines_lift_wood1_mechanism_stop" );
  1375. SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) );
  1376. SetBehaviorVariable( 'counter', (float)validCounter); //1/true when the parry is a counter/reflex_parry
  1377. this.SetBehaviorVariable( 'combatActionType', (int)CAT_Parry );
  1378.  
  1379.  
  1380. if ( !fistFightCounter )
  1381. {
  1382. attackerInventory = parryInfo.attacker.GetInventory();
  1383. weaponId = attackerInventory.GetItemFromSlot('r_weapon');
  1384. attackerInventory.GetItemTags( weaponId , weaponTags );
  1385.  
  1386. /*if( parryInfo.attacker.HasTag( 'olgierd_gpl' ) && parryInfo.attackActionName == 'attack_heavy' )
  1387. {
  1388. //DealCounterDamageToOlgierd();
  1389. GetTarget().AddAbility( 'HitCounterEnabled', false );
  1390. GetTarget().AddTimer( 'DisableHitCounterAfter', 3.0 );
  1391. }*/
  1392.  
  1393. //don't look at me like that. It is NOT a hack... follow the white rabbit...
  1394. if ( parryInfo.attacker.HasAbility('mon_gravehag') )
  1395. {
  1396. repelType = PRT_Slash;
  1397. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, 'ReflexParryPerformed');
  1398. //parryInfo.attacker.RemoveAbility('TongueAttack');
  1399. }
  1400. else if ( (CNewNPC)parryInfo.attacker && !((CNewNPC)parryInfo.attacker).IsHuman() )
  1401. {
  1402. repelType = PRT_SideStepSlash;
  1403. }
  1404. else if ( weaponTags.Contains('spear2h') )
  1405. {
  1406. repelType = PRT_SideStepSlash;
  1407. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed");
  1408. parryInfo.attacker.SignalGameplayEvent( 'SpearDestruction');
  1409. }
  1410. else
  1411. {
  1412. //-----pitch check------
  1413. thisPos = this.GetWorldPosition();
  1414. attackerPos = parryInfo.attacker.GetWorldPosition();
  1415. playerToTargetRot = VecToRotation( thisPos - attackerPos );
  1416. zDifference = thisPos.Z - attackerPos.Z;
  1417.  
  1418. if ( playerToTargetRot.Pitch < -5.f && zDifference > 0.35 )
  1419. {
  1420. repelType = PRT_Kick;
  1421. //Pass attacker to the timer so that he ragdolls after a delay
  1422. ragdollTarget = parryInfo.attacker;
  1423. AddTimer( 'ApplyCounterRagdollTimer', 0.3 );
  1424. }
  1425. else
  1426. {
  1427. useKnockdown = false;
  1428. if ( CanUseSkill(S_Sword_s11) )
  1429. {
  1430. if( GetSkillLevel(S_Sword_s11) > 1 && RandF() < GetWitcherPlayer().GetStat(BCS_Focus) )//CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s11, 'chance', false, true)) )
  1431. {
  1432. duration = CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s11, 'duration', false, true));
  1433. useKnockdown = true;
  1434. }
  1435. }
  1436. else if ( parryInfo.attacker.IsHuman() )
  1437. {
  1438. //Apply knockdown if npc is countered on ledge
  1439. tracePosStart = parryInfo.attacker.GetWorldPosition();
  1440. tracePosStart.Z += 1.f;
  1441. playerToAttackerVector = VecNormalize( parryInfo.attacker.GetWorldPosition() - parryInfo.target.GetWorldPosition() );
  1442. tracePosEnd = ( playerToAttackerVector * 0.75f ) + ( playerToAttackerVector * parryInfo.attacker.GetRadius() ) + parryInfo.attacker.GetWorldPosition();
  1443. tracePosEnd.Z += 1.f;
  1444.  
  1445. if ( !theGame.GetWorld().StaticTrace( tracePosStart, tracePosEnd, hitPos, hitNormal, counterCollisionGroupNames ) )
  1446. {
  1447. tracePosStart = tracePosEnd;
  1448. tracePosEnd -= 3.f;
  1449.  
  1450. if ( !theGame.GetWorld().StaticTrace( tracePosStart, tracePosEnd, hitPos, hitNormal, counterCollisionGroupNames ) )
  1451. useKnockdown = true;
  1452. }
  1453. }
  1454.  
  1455. if(useKnockdown && (!parryInfo.attacker.IsImmuneToBuff(EET_HeavyKnockdown) || !parryInfo.attacker.IsImmuneToBuff(EET_Knockdown)))
  1456. {
  1457. if(!parryInfo.attacker.IsImmuneToBuff(EET_HeavyKnockdown))
  1458. {
  1459. params.effectType = EET_HeavyKnockdown;
  1460. }
  1461. else
  1462. {
  1463. params.effectType = EET_Knockdown;
  1464. }
  1465.  
  1466. repelType = PRT_Kick;
  1467. params.creator = this;
  1468. params.sourceName = "ReflexParryPerformed";
  1469. params.duration = duration;
  1470.  
  1471. parryInfo.attacker.AddEffectCustom(params);
  1472. }
  1473. else
  1474. {
  1475. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed");
  1476. }
  1477. }
  1478. }
  1479.  
  1480. parryInfo.attacker.GetInventory().PlayItemEffect(parryInfo.attackerWeaponId, 'counterattack');
  1481.  
  1482. //by default repelType is PRT_Random
  1483. if ( repelType == PRT_Random )
  1484. if ( RandRange(100) > 50 )
  1485. repelType = PRT_Bash;
  1486. else
  1487. repelType = PRT_Kick;
  1488.  
  1489. this.SetBehaviorVariable( 'repelType', (int)repelType );
  1490. parryInfo.attacker.SetBehaviorVariable( 'repelType', (int)repelType );
  1491. }
  1492. else
  1493. {
  1494. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed");
  1495. }
  1496.  
  1497. //SetCustomOrientationTargetForCombatActions( OT_None );
  1498. SetParryTarget ( parryInfo.attacker );
  1499. SetSlideTarget( parryInfo.attacker );
  1500. if ( !IsActorLockedToTarget() )
  1501. SetMoveTarget( parryInfo.attacker );
  1502.  
  1503. if ( RaiseForceEvent( 'PerformCounter' ) )
  1504. OnCombatActionStart();
  1505.  
  1506. SetCustomRotation( 'Counter', VecHeading( parryInfo.attacker.GetWorldPosition() - this.GetWorldPosition() ), 0.0f, 0.2f, false );
  1507. AddTimer( 'UpdateCounterRotation', 0.4f, true );
  1508. AddTimer( 'SetCounterRotation', 0.2f );
  1509.  
  1510. IncreaseUninterruptedHitsCount(); //counters also count as uninterrupted hits
  1511.  
  1512. //drain stamina
  1513. if(IsHeavyAttack(parryInfo.attackActionName))
  1514. mult = theGame.params.HEAVY_STRIKE_COST_MULTIPLIER;
  1515.  
  1516. DrainStamina(ESAT_Counterattack, 0, 0, '', 0, mult);
  1517.  
  1518. theGame.GetGamerProfile().IncStat(ES_CounterattackChain);
  1519.  
  1520. }
  1521. else
  1522. {
  1523. ResetUninterruptedHitsCount();
  1524. }
  1525. return validCounter;
  1526. }
  1527.  
  1528. return false;
  1529. }
  1530.  
  1531. timer function UpdateCounterRotation( dt : float, id : int )
  1532. {
  1533. UpdateCustomRotationHeading( 'Counter', VecHeading( parryTarget.GetWorldPosition() - this.GetWorldPosition() ) );
  1534. }
  1535.  
  1536. timer function SetCounterRotation( dt : float, id : int )
  1537. {
  1538. SetCustomRotation( 'Counter', VecHeading( parryTarget.GetWorldPosition() - this.GetWorldPosition() ), 360.f, 0.2f, false );
  1539. }
  1540.  
  1541. private var parryTarget : CActor;
  1542. private function SetParryTarget( t : CActor )
  1543. {
  1544. parryTarget = t;
  1545. }
  1546.  
  1547. private var ragdollTarget : CActor;
  1548. timer function ApplyCounterRagdollTimer( time : float , id : int)
  1549. {
  1550. var actor : CActor;
  1551.  
  1552. actor = (CActor)ragdollTarget;
  1553.  
  1554. if(actor)
  1555. {
  1556. actor.AddEffectDefault(EET_HeavyKnockdown, this, 'ReflexParryPerformed');
  1557. }
  1558. }
  1559.  
  1560. ///////////////////////////////////////////////////////////////////////////
  1561. // Player Mode
  1562.  
  1563. public function EnableMode( mode : EPlayerMode, enable : bool )
  1564. {
  1565. playerMode.EnableMode( mode, enable );
  1566. }
  1567.  
  1568. public function GetPlayerMode() : W3PlayerMode
  1569. {
  1570. return playerMode;
  1571. }
  1572.  
  1573. private function GetClosestIncomingAttacker() : CActor
  1574. {
  1575. var i, size : int;
  1576. var attackerToPlayerDistances : array< float >;
  1577. var closestAttackerIndex : int;
  1578. var incomingAttackers : array<CActor>;
  1579.  
  1580. //incomingAttackers = this.combatManager.SendTicketOwners( CTT_Attack );
  1581. if(playerMode && playerMode.combatDataComponent)
  1582. {
  1583. if ( incomingAttackers.Size() <= 0 )
  1584. this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Charge' );
  1585.  
  1586. if ( incomingAttackers.Size() <= 0 )
  1587. this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Melee' );
  1588.  
  1589. if ( incomingAttackers.Size() <= 0 )
  1590. this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Range' );
  1591. }
  1592.  
  1593. size = incomingAttackers.Size();
  1594. attackerToPlayerDistances.Resize( size );
  1595.  
  1596. if ( size > 0 )
  1597. {
  1598. for ( i = incomingAttackers.Size()-1; i >= 0; i -= 1)
  1599. {
  1600. if ( !IsEnemyVisible( incomingAttackers[i] ) )
  1601. {
  1602. incomingAttackers.EraseFast( i );
  1603. }
  1604. }
  1605. }
  1606.  
  1607. if ( size > 0 )
  1608. {
  1609. for ( i = 0; i < size; i += 1 )
  1610. {
  1611. attackerToPlayerDistances[i] = VecDistance( incomingAttackers[i].GetWorldPosition(), this.GetWorldPosition() );
  1612. }
  1613. closestAttackerIndex = ArrayFindMinF( attackerToPlayerDistances );
  1614. return incomingAttackers[ closestAttackerIndex ];
  1615. }
  1616. else
  1617. {
  1618. return NULL;
  1619. }
  1620. }
  1621.  
  1622. // Combat Timer
  1623. timer function CombatCheck( time : float , id : int)
  1624. {
  1625. var i : int;
  1626. var strLevel, temp : string;
  1627. var enemies : array<CActor>;
  1628.  
  1629. UpdateFinishableEnemyList();
  1630. FindMoveTarget();
  1631. playerMode.UpdateCombatMode();
  1632.  
  1633. if( GetPlayerCombatStance() == PCS_Guarded )
  1634. {
  1635. if( GetTarget().GetHealthPercents() > 0.25f )
  1636. {
  1637. PlayBattleCry( 'BattleCryTaunt', 0.2f );
  1638. }
  1639. else
  1640. {
  1641. if( GetTarget().IsHuman() )
  1642. PlayBattleCry( 'BattleCryHumansEnd', 0.3f );
  1643. else
  1644. PlayBattleCry( 'BattleCryMonstersEnd', 0.3f );
  1645. }
  1646. }
  1647.  
  1648. if(IsThreatened() && ShouldProcessTutorial('TutorialMonsterThreatLevels') && FactsQuerySum("q001_nightmare_ended") > 0)
  1649. {
  1650. GetEnemiesInRange(enemies);
  1651. for(i=0; i<enemies.Size(); i+=1)
  1652. {
  1653. strLevel = ((CNewNPC)enemies[i]).GetExperienceDifferenceLevelName(temp);
  1654. if(strLevel == "deadlyLevel" || strLevel == "highLevel")
  1655. {
  1656. FactsAdd("tut_high_threat_monster");
  1657. break;
  1658. }
  1659. }
  1660. }
  1661. }
  1662.  
  1663. public function ReceivedDamageInCombat() : bool
  1664. {
  1665. return receivedDamageInCombat;
  1666. }
  1667.  
  1668. //called when combat starts
  1669. event OnCombatStart()
  1670. {
  1671. var weaponType : EPlayerWeapon;
  1672.  
  1673. theGame.CreateNoSaveLock( 'combat', noSaveLock );
  1674.  
  1675. //cerberus achievement
  1676. FactsRemove("statistics_cerberus_sign");
  1677. FactsRemove("statistics_cerberus_petard");
  1678. FactsRemove("statistics_cerberus_bolt");
  1679. FactsRemove("statistics_cerberus_fists");
  1680. FactsRemove("statistics_cerberus_melee");
  1681. FactsRemove("statistics_cerberus_environment");
  1682.  
  1683. BlockAction(EIAB_OpenMeditation, 'InCombat');
  1684. BlockAction(EIAB_HighlightObjective, 'InCombat');
  1685.  
  1686. if ( !this.IsUsingBoat() && GetTarget().GetAttitude(this) == AIA_Hostile )
  1687. {
  1688. weaponType = GetMostConvenientMeleeWeapon( GetTarget() );
  1689.  
  1690. if ( weaponType == PW_Steel || weaponType == PW_Silver )
  1691. this.OnEquipMeleeWeapon( weaponType, false );
  1692. }
  1693. }
  1694.  
  1695. //called when combat finishes
  1696. event OnCombatFinished()
  1697. {
  1698. var cnt : int;
  1699.  
  1700. reevaluateCurrentWeapon = false;
  1701.  
  1702. thePlayer.HardLockToTarget( false );
  1703.  
  1704. receivedDamageInCombat = false;
  1705.  
  1706. //cerberus achievement
  1707. cnt = 0;
  1708. if(FactsQuerySum("statistics_cerberus_sign") > 0)
  1709. cnt += 1;
  1710. if(FactsQuerySum("statistics_cerberus_petard") > 0)
  1711. cnt += 1;
  1712. if(FactsQuerySum("statistics_cerberus_bolt") > 0)
  1713. cnt += 1;
  1714. if(FactsQuerySum("statistics_cerberus_fists") > 0)
  1715. cnt += 1;
  1716. if(FactsQuerySum("statistics_cerberus_melee") > 0)
  1717. cnt += 1;
  1718. if(FactsQuerySum("statistics_cerberus_environment") > 0)
  1719. cnt += 1;
  1720.  
  1721. //failsafe
  1722. FactsRemove("statistics_cerberus_sign");
  1723. FactsRemove("statistics_cerberus_petard");
  1724. FactsRemove("statistics_cerberus_bolt");
  1725. FactsRemove("statistics_cerberus_fists");
  1726. FactsRemove("statistics_cerberus_melee");
  1727. FactsRemove("statistics_cerberus_environment");
  1728.  
  1729. if(cnt >= 3)
  1730. theGame.GetGamerProfile().AddAchievement(EA_Cerberus);
  1731. //end of cerberus
  1732.  
  1733. if(theGame.GetTutorialSystem() && FactsQuerySum("TutorialShowSilver") > 0)
  1734. {
  1735. FactsAdd("tut_show_silver_sword", 1);
  1736. FactsRemove("TutorialShowSilver");
  1737. }
  1738. this.SetBehaviorVariable('isInCombatForOverlay',0.f);
  1739. GoToExplorationIfNeeded();
  1740. theGame.ReleaseNoSaveLock( noSaveLock );
  1741. LogChannel( 'OnCombatFinished', "OnCombatFinished: ReleaseNoSaveLock" );
  1742.  
  1743. SetFailedFundamentalsFirstAchievementCondition(false);
  1744.  
  1745. UnblockAction(EIAB_OpenMeditation, 'InCombat');
  1746. UnblockAction(EIAB_HighlightObjective, 'InCombat');
  1747. }
  1748.  
  1749. event OnReactToBeingHit( damageAction : W3DamageAction )
  1750. {
  1751. var weaponType : EPlayerWeapon;
  1752.  
  1753. super.OnReactToBeingHit(damageAction);
  1754.  
  1755. if ( IsInCombat() && damageAction.attacker && damageAction.attacker == GetTarget() && !( this.IsUsingVehicle() && this.IsOnBoat() ) )
  1756. {
  1757. weaponType = GetMostConvenientMeleeWeapon( GetTarget() );
  1758. if ( weaponType != PW_Fists && weaponType != PW_None && weaponType != this.GetCurrentMeleeWeaponType() )
  1759. OnEquipMeleeWeapon( weaponType, false );
  1760. }
  1761. }
  1762.  
  1763. //called when player receives damage in combat(except for toxicity)
  1764. public function ReceivedCombatDamage()
  1765. {
  1766. receivedDamageInCombat = true;
  1767. }
  1768.  
  1769. ///////////////////////////////////////////////////////////////////////////
  1770. // @Uninterrupted hits
  1771. ///////////////////////////////////////////////////////////////////////////
  1772.  
  1773.  
  1774. timer function UninterruptedHitsResetOnIdle(dt : float, id : int)
  1775. {
  1776. ResetUninterruptedHitsCount();
  1777. }
  1778.  
  1779. public function ResetUninterruptedHitsCount()
  1780. {
  1781. uninterruptedHitsCount = 0;
  1782. LogUnitAtt("Uninterrupted attacks reset!!!!");
  1783. }
  1784.  
  1785. public function IncreaseUninterruptedHitsCount()
  1786. {
  1787. uninterruptedHitsCount += 1;
  1788. LogUnitAtt("Uninterrupted attacks count increased to " + uninterruptedHitsCount);
  1789.  
  1790. if(uninterruptedHitsCount == 4)
  1791. AddTimer('StartUninterruptedBlurr', 1, false);
  1792.  
  1793. //idle turn off timer
  1794. AddTimer('UninterruptedHitsResetOnIdle', 4.f, false);
  1795. }
  1796.  
  1797. timer function StartUninterruptedBlurr(dt : float, id : int)
  1798. {
  1799. var changed : bool;
  1800. var movingAgent : CMovingPhysicalAgentComponent;
  1801. var target : CActor;
  1802.  
  1803. //check if the timer is to be turned off
  1804. if(uninterruptedHitsCount < 4)
  1805. {
  1806. LogUnitAtt("Stopping camera effect");
  1807. thePlayer.StopEffect(uninterruptedHitsCurrentCameraEffect);
  1808. uninterruptedHitsCurrentCameraEffect = '';
  1809. uninterruptedHitsCameraStarted = false;
  1810. RemoveTimer('StartUninterruptedBlurr');
  1811. }
  1812. else //still valid
  1813. {
  1814. target = GetTarget();
  1815.  
  1816. if( target )
  1817. {
  1818. movingAgent = ( (CMovingPhysicalAgentComponent) (target.GetMovingAgentComponent()) );
  1819. }
  1820.  
  1821. if(!uninterruptedHitsCameraStarted)
  1822. {
  1823. LogUnitAtt("Starting camera effect");
  1824. AddTimer('StartUninterruptedBlurr', 0.001, true); //need to update per tick
  1825. if(movingAgent && movingAgent.GetCapsuleHeight() > 2)
  1826. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY;
  1827. else
  1828. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY;
  1829. thePlayer.PlayEffect(uninterruptedHitsCurrentCameraEffect);
  1830. uninterruptedHitsCameraStarted = true;
  1831. }
  1832. else
  1833. {
  1834. changed = false;
  1835. if(movingAgent && movingAgent.GetCapsuleHeight() > 2 && uninterruptedHitsCurrentCameraEffect != theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY)
  1836. changed = true;
  1837. else if(!movingAgent || ( movingAgent.GetCapsuleHeight() <= 2 && uninterruptedHitsCurrentCameraEffect != theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY) )
  1838. changed = true;
  1839.  
  1840. //if the target's height has changed then swap the camera effect
  1841. if(changed)
  1842. {
  1843. //stop current effect
  1844. thePlayer.StopEffect(uninterruptedHitsCurrentCameraEffect);
  1845.  
  1846. //change mode
  1847. if(uninterruptedHitsCurrentCameraEffect == theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY)
  1848. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY;
  1849. else
  1850. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY;
  1851.  
  1852. //turn new camera effect on
  1853. thePlayer.PlayEffect(uninterruptedHitsCurrentCameraEffect);
  1854. }
  1855. }
  1856. }
  1857. }
  1858.  
  1859. ///////////////////////////////////////////////////////////////////////////
  1860. // Exploration Actions
  1861. ///////////////////////////////////////////////////////////////////////////
  1862.  
  1863. private var playerActionEventListeners : array<CGameplayEntity>;
  1864. private var playerActionEventBlockingListeners : array<CGameplayEntity>;
  1865.  
  1866. private function PlayerActionBlockGameplayActions( sourceName : name, lock : bool, isFromPlace : bool )
  1867. {
  1868. if ( lock )
  1869. {
  1870. thePlayer.BlockAction( EIAB_Signs, sourceName, false, false, isFromPlace );
  1871. thePlayer.BlockAction( EIAB_DrawWeapon, sourceName, false, false, isFromPlace );
  1872. thePlayer.BlockAction( EIAB_CallHorse, sourceName, false, false, isFromPlace );
  1873. thePlayer.BlockAction( EIAB_FastTravel, sourceName, false, false, isFromPlace );
  1874. thePlayer.BlockAction( EIAB_Fists, sourceName, false, false, isFromPlace );
  1875. thePlayer.BlockAction( EIAB_InteractionAction, sourceName, false, false, isFromPlace );
  1876. thePlayer.DisableCombatState();
  1877. }
  1878. else
  1879. {
  1880. thePlayer.UnblockAction( EIAB_Signs, sourceName );
  1881. thePlayer.UnblockAction( EIAB_DrawWeapon, sourceName );
  1882. thePlayer.UnblockAction( EIAB_CallHorse, sourceName );
  1883. thePlayer.UnblockAction( EIAB_FastTravel, sourceName );
  1884. thePlayer.UnblockAction( EIAB_Fists, sourceName );
  1885. thePlayer.UnblockAction( EIAB_InteractionAction, sourceName );
  1886. }
  1887. }
  1888.  
  1889. public function GetPlayerActionEventListeners() : array<CGameplayEntity>
  1890. {
  1891. return playerActionEventListeners;
  1892. }
  1893.  
  1894. //Registers for event + blocks GameplayActions
  1895. public function RegisterForPlayerAction( listener : CGameplayEntity, isLockedByPlace : bool )
  1896. {
  1897. if ( !playerActionEventListeners.Contains( listener ) )
  1898. {
  1899. playerActionEventListeners.PushBack( listener );
  1900. }
  1901. if ( listener.ShouldBlockGameplayActionsOnInteraction() )
  1902. {
  1903. if ( !playerActionEventBlockingListeners.Contains( listener ) )
  1904. {
  1905. playerActionEventBlockingListeners.PushBack( listener );
  1906. }
  1907. if ( playerActionEventBlockingListeners.Size() == 1 )
  1908. {
  1909. PlayerActionBlockGameplayActions( 'PlayerAction', true, isLockedByPlace );
  1910. }
  1911. }
  1912. }
  1913.  
  1914. //Unregisters for event + unblocks GameplayActions
  1915. public function UnregisterForPlayerAction( listener : CGameplayEntity, isLockedByPlace : bool )
  1916. {
  1917. playerActionEventListeners.Remove( listener );
  1918. playerActionEventBlockingListeners.Remove( listener );
  1919. if ( playerActionEventBlockingListeners.Size() == 0 )
  1920. {
  1921. PlayerActionBlockGameplayActions( 'PlayerAction', false, isLockedByPlace );
  1922. }
  1923. }
  1924.  
  1925. event OnPlayerActionStart()
  1926. {
  1927. //MS: Only used for ProudWalk
  1928. thePlayer.SetBehaviorVariable( 'inJumpState', 1.f );
  1929. }
  1930.  
  1931. event OnPlayerActionEnd()
  1932. {
  1933. var i : int;
  1934. for ( i = playerActionEventListeners.Size() - 1; i >= 0; i-=1 )
  1935. {
  1936. playerActionEventListeners[i].OnPlayerActionEnd();
  1937. }
  1938. currentCustomAction = PEA_None;
  1939.  
  1940. //MS: Only used for ProudWalk
  1941. thePlayer.SetBehaviorVariable( 'inJumpState', 0.f );
  1942. }
  1943.  
  1944. event OnPlayerActionStartFinished()
  1945. {
  1946. var i : int;
  1947. for ( i = playerActionEventListeners.Size() - 1; i >= 0; i-=1 )
  1948. {
  1949. playerActionEventListeners[i].OnPlayerActionStartFinished();
  1950. }
  1951. }
  1952.  
  1953. function PlayerStartAction( playerAction : EPlayerExplorationAction, optional animName : name ) : bool
  1954. {
  1955. if ( playerAction == PEA_SlotAnimation && !IsNameValid(animName) )
  1956. {
  1957. return false;
  1958. }
  1959.  
  1960. SetBehaviorVariable( 'playerStopAction', 0.0);
  1961. SetBehaviorVariable( 'playerExplorationAction', (float)(int)playerAction);
  1962.  
  1963. /*if ( playerAction == PEA_SlotAnimation )
  1964. {
  1965. if ( !this.ActionPlaySlotAnimationAsync('PLAYER_ACTION_SLOT',animName) )
  1966. return false;
  1967. }*/
  1968.  
  1969. if ( RaiseForceEvent('playerActionStart') )
  1970. {
  1971. currentCustomAction = playerAction;
  1972. if ( playerAction == PEA_SlotAnimation )
  1973. {
  1974. playerActionSlotAnimName = animName;
  1975. AddTimer('PlayActionAnimWorkaround',0,false);
  1976. }
  1977. return true;
  1978. }
  1979. return false;
  1980. }
  1981.  
  1982. private var playerActionSlotAnimName : name;
  1983.  
  1984. timer function PlayActionAnimWorkaround( dt : float , id : int)
  1985. {
  1986. this.ActionPlaySlotAnimationAsync('PLAYER_ACTION_SLOT',playerActionSlotAnimName, 0.2, 0.2, true);
  1987. }
  1988.  
  1989. function PlayerStopAction( playerAction : EPlayerExplorationAction )
  1990. {
  1991. SetBehaviorVariable( 'playerExplorationAction', (float)(int)playerAction);
  1992. SetBehaviorVariable( 'playerStopAction', 1.0);
  1993. currentCustomAction = PEA_None;
  1994. }
  1995.  
  1996. function GetPlayerAction() : EPlayerExplorationAction
  1997. {
  1998. return currentCustomAction;
  1999. }
  2000.  
  2001. function MedallionPing()
  2002. {
  2003. var currTime : float = theGame.GetEngineTimeAsSeconds();
  2004.  
  2005. if ( lastMedallionEffect < currTime )
  2006. {
  2007. lastMedallionEffect = theGame.GetEngineTimeAsSeconds() + medallion.effectDuration;
  2008. medallion.TriggerMedallionFX();
  2009. }
  2010. }
  2011.  
  2012. ///////////////////////////////////////////////////////////////////////////
  2013. // @INTERACTIONS
  2014. ///////////////////////////////////////////////////////////////////////////
  2015.  
  2016. public function CanPerformPlayerAction(optional alsoOutsideExplorationState : bool) : bool
  2017. {
  2018. //if in exploration or in any state and flag set
  2019. if(!alsoOutsideExplorationState && GetCurrentStateName() != 'Exploration')
  2020. return false;
  2021.  
  2022. if( isInAir || (substateManager && !substateManager.CanInteract()) || IsInCombatAction() || GetCriticalBuffsCount() > 0)
  2023. return false;
  2024.  
  2025. return true;
  2026. }
  2027.  
  2028. //called when we receive an item
  2029. event OnItemGiven(data : SItemChangedData)
  2030. {
  2031. var keyName : name;
  2032. var i : int;
  2033. var hud : CR4ScriptedHud;
  2034. var message : string;
  2035. var inve : CInventoryComponent;
  2036.  
  2037. if(data.informGui)
  2038. {
  2039. hud = (CR4ScriptedHud)theGame.GetHud();
  2040. if(hud)
  2041. {
  2042. message = GetLocStringByKeyExt("panel_common_item_received") + ": " + GetLocStringByKeyExt(inv.GetItemLocalizedNameByUniqueID(data.ids[0]));
  2043. if(data.quantity > 1)
  2044. message += " x" + data.quantity;
  2045. hud.HudConsoleMsg(message);
  2046. }
  2047. }
  2048.  
  2049. inve = GetInventory(); //OnItemGiven can be called before we cache inventory component
  2050.  
  2051. //key - check if we're next to a lock that uses this key and update interaction if needed
  2052. if(inve.ItemHasTag(data.ids[0], 'key'))
  2053. {
  2054. keyName = inve.GetItemName(data.ids[0]);
  2055. for(i=nearbyLockedContainersNoKey.Size()-1; i>=0; i-=1)
  2056. {
  2057. if(nearbyLockedContainersNoKey[i].GetKeyName() == keyName && nearbyLockedContainersNoKey[i].IsEnabled())
  2058. {
  2059. nearbyLockedContainersNoKey[i].UpdateComponents("Unlock");
  2060. nearbyLockedContainersNoKey.Remove(nearbyLockedContainersNoKey[i]);
  2061. }
  2062. }
  2063. }
  2064.  
  2065. //alchemy level 3 items
  2066. if(inve.IsItemAlchemyItem(data.ids[0]))
  2067. {
  2068. UpgradeAlchemyItem(data.ids[0], CanUseSkill(S_Perk_08));
  2069. }
  2070.  
  2071. if(inve.ItemHasTag(data.ids[0], theGame.params.TAG_OFIR_SET))
  2072. CheckOfirSetAchievement();
  2073. }
  2074.  
  2075. private final function CheckOfirSetAchievement()
  2076. {
  2077. var hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders : bool;
  2078.  
  2079. //check player items
  2080. CheckOfirItems(GetInventory(), hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders);
  2081.  
  2082. //check stash items
  2083. CheckOfirItems(GetWitcherPlayer().GetHorseManager().GetInventoryComponent(), hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders);
  2084.  
  2085. if(hasArmor && hasBoots && hasGloves && hasPants && hasSword && hasSaddle && hasBag && hasBlinders)
  2086. theGame.GetGamerProfile().AddAchievement(EA_LatestFashion);
  2087. }
  2088.  
  2089. 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)
  2090. {
  2091. var ofirs : array<SItemUniqueId>;
  2092. var i : int;
  2093.  
  2094. ofirs = inv.GetItemsByTag(theGame.params.TAG_OFIR_SET);
  2095. for(i=0; i<ofirs.Size(); i+=1)
  2096. {
  2097. if(inv.IsItemChestArmor(ofirs[i]))
  2098. {
  2099. hasArmor = true;
  2100. continue;
  2101. }
  2102. else if(inv.IsItemBoots(ofirs[i]))
  2103. {
  2104. hasBoots = true;
  2105. continue;
  2106. }
  2107. else if(inv.IsItemGloves(ofirs[i]))
  2108. {
  2109. hasGloves = true;
  2110. continue;
  2111. }
  2112. else if(inv.IsItemPants(ofirs[i]))
  2113. {
  2114. hasPants = true;
  2115. continue;
  2116. }
  2117. else if(inv.IsItemSteelSwordUsableByPlayer(ofirs[i]))
  2118. {
  2119. hasSword = true;
  2120. continue;
  2121. }
  2122. else if(inv.IsItemSilverSwordUsableByPlayer(ofirs[i]))
  2123. {
  2124. hasSword = true;
  2125. continue;
  2126. }
  2127. else if(inv.IsItemSaddle(ofirs[i]))
  2128. {
  2129. hasSaddle = true;
  2130. continue;
  2131. }
  2132. else if(inv.IsItemHorseBag(ofirs[i]))
  2133. {
  2134. hasBag = true;
  2135. continue;
  2136. }
  2137. else if(inv.IsItemBlinders(ofirs[i]))
  2138. {
  2139. hasBlinders = true;
  2140. continue;
  2141. }
  2142. }
  2143. }
  2144.  
  2145. //changes all alchemy items of level 3 abilities from level 2 to 3 (if upgrade) or from 3 to 2 (if not upgrading)
  2146. public function ChangeAlchemyItemsAbilities(upgrade : bool)
  2147. {
  2148. var i : int;
  2149. var dm : CDefinitionsManagerAccessor;
  2150. var items : array<SItemUniqueId>;
  2151.  
  2152. inv.GetAllItems(items);
  2153. dm = theGame.GetDefinitionsManager();
  2154.  
  2155. for(i=0; i<items.Size(); i+=1)
  2156. if(inv.IsItemAlchemyItem(items[i]))
  2157. UpgradeAlchemyItem(items[i], upgrade);
  2158. }
  2159.  
  2160. //changes all alchemy items of level 3 abilities from level 2 to 3 (if upgrade) or from 3 to 2 (if not upgrading)
  2161. public function UpgradeAlchemyItem(itemID : SItemUniqueId, upgrade : bool)
  2162. {
  2163. var j, currLevel, otherLevel : int;
  2164. var dm : CDefinitionsManagerAccessor;
  2165. var abs, currAbilities, otherAbilities : array<name>;
  2166. var min, max : SAbilityAttributeValue;
  2167.  
  2168. if(!inv.IsItemAlchemyItem(itemID))
  2169. return;
  2170.  
  2171. //get current level
  2172. currLevel = (int)CalculateAttributeValue(inv.GetItemAttributeValue(itemID, 'level'));
  2173.  
  2174. //if level ok then exit
  2175. if(currLevel == 3 || currLevel == 2 || currLevel < 2 || currLevel > 3)
  2176. return;
  2177.  
  2178. //get current ability name
  2179. currAbilities = inv.GetItemAbilitiesWithAttribute(itemID, 'level', currLevel);
  2180.  
  2181. //get other ability name
  2182. inv.GetItemContainedAbilities(itemID, abs);
  2183. dm = theGame.GetDefinitionsManager();
  2184. for(j=0; j<abs.Size(); j+=1)
  2185. {
  2186. dm.GetAbilityAttributeValue(abs[j], 'level', min, max);
  2187. otherLevel = (int)CalculateAttributeValue(GetAttributeRandomizedValue(min, max));
  2188. if( (otherLevel == 2 || otherLevel == 3) && otherLevel != currLevel)
  2189. otherAbilities.PushBack(abs[j]);
  2190. }
  2191.  
  2192. //swap abilities
  2193. if(otherAbilities.Size() == 0)
  2194. {
  2195. LogAssert(false, "CR4Player.UpgradeAlchemyItem: cannot find ability to swap to from <<" + currAbilities[0] + ">> on item <<" + inv.GetItemName(itemID) + ">> !!!");
  2196. }
  2197. else
  2198. {
  2199. for(j=0; j<currAbilities.Size(); j+=1)
  2200. inv.RemoveItemBaseAbility(itemID, currAbilities[j]);
  2201.  
  2202. for(j=0; j<otherAbilities.Size(); j+=1)
  2203. inv.AddItemBaseAbility(itemID, otherAbilities[j]);
  2204. }
  2205. }
  2206.  
  2207. ///////////////////////////////////////////////////////////////////////////
  2208. // Movement adjustment helper functions
  2209. ///////////////////////////////////////////////////////////////////////////
  2210.  
  2211. public function MovAdjRotateToTarget( ticket : SMovementAdjustmentRequestTicket )
  2212. {
  2213. var movementAdjustor : CMovementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  2214. var localOrientationTarget : EOrientationTarget = GetOrientationTarget();
  2215.  
  2216. if ( localOrientationTarget == OT_CustomHeading )
  2217. {
  2218. movementAdjustor.RotateTo( ticket, GetOrientationTargetCustomHeading() );
  2219. }
  2220. else if ( localOrientationTarget == OT_Actor )
  2221. {
  2222. /*if ( parryTarget && IsGuarded() )
  2223. movementAdjustor.RotateTowards( ticket, parryTarget );
  2224. else*/ if ( slideTarget )
  2225. movementAdjustor.RotateTowards( ticket, slideTarget );
  2226. else if ( lAxisReleasedAfterCounter )
  2227. movementAdjustor.RotateTo( ticket, GetHeading() );
  2228. else
  2229. movementAdjustor.RotateTo( ticket, GetCombatActionHeading() );//rawPlayerHeading );
  2230. }
  2231. else if ( localOrientationTarget == OT_Player )
  2232. {
  2233. if ( bLAxisReleased )
  2234. movementAdjustor.RotateTo( ticket, GetHeading() );
  2235. else
  2236. movementAdjustor.RotateTo( ticket, rawPlayerHeading );//GetCombatActionHeading() );
  2237. }
  2238. else if ( localOrientationTarget == OT_CameraOffset )
  2239. {
  2240. //movementAdjustor.RotateTo( ticket, VecHeading( cachedCameraVector ) );//rawCameraHeading - oTCameraOffset );
  2241. movementAdjustor.RotateTo( ticket, VecHeading( theCamera.GetCameraDirection() ) );//rawCameraHeading );
  2242. }
  2243. else
  2244. {
  2245. // default to camera
  2246. movementAdjustor.RotateTo( ticket, rawCameraHeading );
  2247. }
  2248. // never rotate to player
  2249. }
  2250.  
  2251. ////////////////////////////////////////////////////////////////////////////////////
  2252. // Look at targets - moved here from movables
  2253. ////////////////////////////////////////////////////////////////////////////////////
  2254. //var cachedCameraVector : Vector;
  2255. public function UpdateLookAtTarget()
  2256. {
  2257. var localOrientationTarget : EOrientationTarget;
  2258. var playerRot : EulerAngles;
  2259. var lookAtActive : Float;
  2260. var lookAtTarget : Vector;
  2261. var headBoneIdx : int;
  2262. var tempComponent : CDrawableComponent;
  2263. var entityHeight : float;
  2264. var useTorsoBone : bool;
  2265.  
  2266. var angles : EulerAngles;
  2267. var dir : Vector;
  2268. var camZ : float;
  2269.  
  2270. var target : CActor;
  2271.  
  2272. lookAtActive = 0.0f;
  2273.  
  2274. localOrientationTarget = GetOrientationTarget();
  2275.  
  2276. if ( localOrientationTarget == OT_Player || localOrientationTarget == OT_CustomHeading )
  2277. {
  2278. /*headBoneIdx = GetTorsoBoneIndex();
  2279. if ( headBoneIdx >= 0 )
  2280. {
  2281. lookAtTarget = MatrixGetTranslation( GetBoneWorldMatrixByIndex( headBoneIdx ) );
  2282. }*/
  2283.  
  2284. //lookAtTarget = GetHeadingVector() * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2285.  
  2286. if ( localOrientationTarget == OT_Player )
  2287. angles = VecToRotation( GetHeadingVector() );
  2288. else if ( customOrientationInfoStack.Size() > 0 )
  2289. angles = VecToRotation( VecFromHeading( customOrientationInfoStack[ customOrientationInfoStack.Size() - 1 ].customHeading ) );
  2290. else
  2291. angles = VecToRotation( GetHeadingVector() );
  2292.  
  2293. //angles.Pitch = oTCameraPitchOffset;
  2294. dir = RotForward( angles );
  2295. lookAtTarget = dir * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2296. lookAtTarget.Z += 1.6f;
  2297. lookAtActive = 1.0f;
  2298. }
  2299. else if ( localOrientationTarget == OT_Camera )
  2300. {
  2301. headBoneIdx = GetHeadBoneIndex();
  2302. if ( headBoneIdx >= 0 )
  2303. {
  2304. lookAtTarget = MatrixGetTranslation( GetBoneWorldMatrixByIndex( headBoneIdx ) );
  2305. }
  2306. else
  2307. {
  2308. lookAtTarget = GetWorldPosition();
  2309. lookAtTarget.Z += 1.6f; // fake head?
  2310. }
  2311. lookAtTarget += theCamera.GetCameraDirection() * 100.f;
  2312. lookAtActive = 1.0f;
  2313. }
  2314. else if ( localOrientationTarget == OT_CameraOffset )
  2315. {
  2316. /*lookAtTarget = GetWorldPosition();
  2317. lookAtTarget.Z += 1.6f; // fake head?
  2318. camDir = theCamera.GetCameraDirection();
  2319. camZ = camDir.Z;// + 0.1;
  2320. camDir = VecFromHeading( VecHeading( theCamera.GetCameraDirection() ) - oTCameraOffset ) * VecLength2D( camDir );
  2321. camDir.Z = camZ;*/
  2322.  
  2323. dir = theCamera.GetCameraDirection();
  2324. angles = VecToRotation( dir );
  2325. angles.Pitch = -angles.Pitch + oTCameraPitchOffset;
  2326. angles.Yaw -= oTCameraOffset;
  2327. dir = RotForward( angles );
  2328.  
  2329. lookAtTarget = dir * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2330. lookAtTarget.Z += 1.6f;
  2331. lookAtActive = 1.0f;
  2332. }
  2333. else if ( localOrientationTarget == OT_Actor )
  2334. {
  2335. if ( IsInCombatAction() )
  2336. {
  2337. if ( ( ( ( W3PlayerWitcher )this ).GetCurrentlyCastSign() != ST_None && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign )
  2338. || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_ItemThrow )
  2339. //|| GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Crossbow )
  2340. useTorsoBone = true;
  2341. }
  2342.  
  2343. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  2344. useTorsoBone = true;
  2345.  
  2346. if ( tempLookAtTarget && (CActor)(tempLookAtTarget) )
  2347. {
  2348. lookAtTarget = ProcessLookAtTargetPosition( tempLookAtTarget, useTorsoBone );
  2349. lookAtActive = 1.0f;
  2350. }
  2351.  
  2352. if ( GetDisplayTarget() && IsDisplayTargetTargetable() )
  2353. {
  2354. lookAtTarget = ProcessLookAtTargetPosition( GetDisplayTarget(), useTorsoBone );
  2355. lookAtActive = 1.0f;
  2356. }
  2357. else
  2358. {
  2359. //FAIL SAFE in case the displayTarget disappears for some reason
  2360.  
  2361. if ( slideTarget )
  2362. {
  2363. lookAtTarget = ProcessLookAtTargetPosition( slideTarget, useTorsoBone );
  2364. }
  2365. else
  2366. {
  2367. target = GetTarget();
  2368. if ( target )
  2369. {
  2370. lookAtTarget = ProcessLookAtTargetPosition( target, useTorsoBone );
  2371. }
  2372. }
  2373.  
  2374. lookAtActive = 1.0f;
  2375. }
  2376.  
  2377. if ( !slideTarget && !IsUsingVehicle() )
  2378. {
  2379. // TODO maybe just get axis from head?
  2380. playerRot = GetWorldRotation();
  2381. lookAtTarget = GetWorldPosition() + VecFromHeading( playerRot.Yaw ) * 100.0f;
  2382. lookAtActive = 0.0f;
  2383. }
  2384.  
  2385. if ( useTorsoBone )
  2386. lookAtTarget.Z += 0.2f;
  2387. }
  2388.  
  2389.  
  2390. //lookAtTarget = player.GetHeadingVector() * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2391. //lookAtActive = 1.0f;
  2392. GetVisualDebug().AddSphere('lookAtTarget', 1.f, lookAtTarget, true, Color(255,0,0), 3.0f );
  2393. SetLookAtPosition( lookAtTarget );
  2394. UpdateLookAtVariables( lookAtActive, lookAtTarget );
  2395. }
  2396.  
  2397. private function ProcessLookAtTargetPosition( ent : CGameplayEntity, useTorsoBone : bool ) : Vector
  2398. {
  2399. var boneIdx : int;
  2400. var actor : CActor;
  2401. var lookAtTarget : Vector;
  2402. var tempComponent : CDrawableComponent;
  2403. var box : Box;
  2404. var entityHeight : float;
  2405. var entityPos : Vector;
  2406. var predictedPos : Vector;
  2407. var z : float;
  2408. var entMat : Matrix;
  2409.  
  2410. actor = (CActor)(ent);
  2411. entityPos = ent.GetWorldPosition();
  2412. lookAtTarget = entityPos;
  2413.  
  2414. if ( actor )
  2415. {
  2416. if ( useTorsoBone )
  2417. boneIdx = actor.GetTorsoBoneIndex();
  2418. else
  2419. boneIdx = actor.GetHeadBoneIndex();
  2420. }
  2421. else
  2422. boneIdx = -1;
  2423.  
  2424. if ( !( ent.aimVector.X == 0 && ent.aimVector.Y == 0 && ent.aimVector.Z == 0 ) )
  2425. {
  2426. entMat = ent.GetLocalToWorld();
  2427. lookAtTarget = VecTransform( entMat, ent.aimVector );
  2428. }
  2429. else if ( boneIdx >= 0 )
  2430. {
  2431. lookAtTarget = MatrixGetTranslation( ent.GetBoneWorldMatrixByIndex( boneIdx ) );
  2432. }
  2433. else
  2434. {
  2435. if ( actor )
  2436. lookAtTarget.Z += ( ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetCapsuleHeight() * 0.5 ); // fake head?
  2437. else
  2438. {
  2439. tempComponent = (CDrawableComponent)( ent.GetComponentByClassName('CDrawableComponent') );
  2440. if ( tempComponent.GetObjectBoundingVolume( box ) )
  2441. {
  2442. entityHeight = box.Max.Z - box.Min.Z;
  2443. lookAtTarget = lookAtTarget + Vector(0,0,entityHeight/2);
  2444. }
  2445. }
  2446. }
  2447. z = ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetCapsuleHeight();
  2448. if ( actor )
  2449. {
  2450. if ( PredictLookAtTargetPosition( actor, lookAtTarget.Z - entityPos.Z, predictedPos ) )
  2451. lookAtTarget = predictedPos;
  2452. }
  2453.  
  2454. return lookAtTarget;
  2455. }
  2456.  
  2457.  
  2458. private function PredictLookAtTargetPosition( targetActor : CActor, zOffSet : float, out predictedPos : Vector ) : bool
  2459. {
  2460. var virtualPos : Vector;
  2461. var i : int;
  2462. var dist : float;
  2463. var deltaTime : float;
  2464. var projSpeed : float;
  2465. var projSpeedInt : Vector;
  2466. var projAngle : float;
  2467.  
  2468. var e3Hack : bool;
  2469. var currentTimeInCurve : float;
  2470. e3Hack = false;
  2471.  
  2472. if ( rangedWeapon
  2473. && rangedWeapon.GetDeployedEntity()
  2474. && ( rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' || rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' ) )
  2475. {
  2476. projSpeed = rangedWeapon.GetDeployedEntity().projSpeed;
  2477.  
  2478. virtualPos = targetActor.GetWorldPosition();
  2479.  
  2480. if ( e3Hack && targetActor.HasTag( 'e3_griffin' ) )
  2481. {
  2482. for ( i = 0; i < 10; i += 1 )
  2483. {
  2484. dist = VecDistance( rangedWeapon.GetDeployedEntity().GetWorldPosition(), virtualPos );
  2485. deltaTime = dist/projSpeed;
  2486. virtualPos = targetActor.PredictWorldPosition( deltaTime );
  2487. }
  2488. }
  2489. else
  2490. return false;
  2491.  
  2492. virtualPos.Z += zOffSet;
  2493. predictedPos = virtualPos;
  2494. GetVisualDebug().AddSphere('CrossbowPredictedPos', 1.0f, virtualPos , true, Color(255,50,50), 5.0f );
  2495. return true;
  2496. }
  2497. return false;
  2498. }
  2499.  
  2500. public function SetLookAtPosition( vec : Vector )
  2501. {
  2502. lookAtPosition = vec;
  2503. }
  2504.  
  2505. public function GetLookAtPosition() : Vector
  2506. {
  2507. return lookAtPosition;
  2508. }
  2509.  
  2510. ////////////////////////////////////////////////////////////////////////////////////
  2511. // Scene
  2512. ////////////////////////////////////////////////////////////////////////////////////
  2513.  
  2514. event OnBlockingSceneEnded( optional output : CStorySceneOutput)
  2515. {
  2516. //hack for possible immortality from finishers
  2517. SetImmortalityMode( AIM_None, AIC_SyncedAnim );
  2518. super.OnBlockingSceneEnded(output);
  2519. }
  2520.  
  2521. ////////////////////////////////////////////////////////////////////////////////////
  2522. // New combat / exploration and weapon drawing
  2523. ////////////////////////////////////////////////////////////////////////////////////
  2524.  
  2525. function GetCurrentMeleeWeaponName() : name
  2526. {
  2527. return weaponHolster.GetCurrentMeleeWeaponName();
  2528. }
  2529.  
  2530. public function GetCurrentMeleeWeaponType() : EPlayerWeapon
  2531. {
  2532. return weaponHolster.GetCurrentMeleeWeapon();
  2533. }
  2534.  
  2535. public function OnMeleeForceHolster(ignoreActionLock : bool)
  2536. {
  2537. weaponHolster.HolsterWeapon(ignoreActionLock, true);
  2538. }
  2539.  
  2540. event OnForcedHolsterWeapon()
  2541. {
  2542. weaponHolster.OnForcedHolsterWeapon();
  2543. }
  2544.  
  2545. event OnEquippedItem( category : name, slotName : name )
  2546. {
  2547. var weaponType : EPlayerWeapon;
  2548.  
  2549. if ( slotName == 'r_weapon' )
  2550. {
  2551. switch ( category )
  2552. {
  2553. case 'None' :
  2554. weaponType = PW_None;
  2555. break;
  2556. case 'fist' :
  2557. weaponType = PW_Fists;
  2558. break;
  2559. case 'steelsword' :
  2560. weaponType = PW_Steel;
  2561. break;
  2562. case 'silversword' :
  2563. weaponType = PW_Silver;
  2564. break;
  2565. default :
  2566. return true;
  2567. }
  2568.  
  2569. weaponHolster.OnEquippedMeleeWeapon( weaponType );
  2570. }
  2571. }
  2572.  
  2573. private var isHoldingDeadlySword : bool;
  2574. public function ProcessIsHoldingDeadlySword()
  2575. {
  2576. isHoldingDeadlySword = IsDeadlySwordHeld();
  2577. }
  2578.  
  2579. public function IsHoldingDeadlySword() : bool
  2580. {
  2581. return isHoldingDeadlySword;
  2582. }
  2583.  
  2584. event OnHolsteredItem( category : name, slotName : name )
  2585. {
  2586. var weaponType : EPlayerWeapon;
  2587.  
  2588. if ( slotName == 'r_weapon' )
  2589. {
  2590. weaponType = weaponHolster.GetCurrentMeleeWeapon();
  2591. switch ( category )
  2592. {
  2593. case 'fist' :
  2594. if ( weaponType == PW_Fists )
  2595. weaponHolster.OnEquippedMeleeWeapon( PW_None );
  2596. return true;
  2597. case 'steelsword' :
  2598. if ( weaponType == PW_Steel )
  2599. weaponHolster.OnEquippedMeleeWeapon( PW_None );
  2600. return true;
  2601. case 'silversword' :
  2602. if ( weaponType == PW_Silver )
  2603. weaponHolster.OnEquippedMeleeWeapon( PW_None );
  2604. return true;
  2605. default :
  2606. return true;
  2607. }
  2608. }
  2609. }
  2610.  
  2611. event OnEquipMeleeWeapon( weaponType : EPlayerWeapon, ignoreActionLock : bool, optional sheatheIfAlreadyEquipped : bool )
  2612. {
  2613. RemoveTimer( 'DelayedSheathSword' );
  2614.  
  2615. weaponHolster.OnEquipMeleeWeapon( weaponType, ignoreActionLock, sheatheIfAlreadyEquipped );
  2616.  
  2617. /*// Check if we want to go to combat or exploration
  2618. if( weaponHolster.GetCurrentMeleeWeapon() == PW_None )
  2619. {
  2620. GoToExplorationIfNeeded( );
  2621. }
  2622. else
  2623. {
  2624. GoToCombatIfNeeded( );
  2625. }*/
  2626.  
  2627. m_RefreshWeaponFXType = true;
  2628. }
  2629.  
  2630. event OnHolsterLeftHandItem()
  2631. {
  2632. weaponHolster.OnHolsterLeftHandItem();
  2633. }
  2634.  
  2635. timer function DelayedSheathSword( dt: float, id : int )
  2636. {
  2637. if ( !IsCombatMusicEnabled() )
  2638. {
  2639. if ( IsInCombatAction() || !IsActionAllowed( EIAB_DrawWeapon ) )
  2640. {
  2641. LogChannel( 'OnCombatFinished', "DelayedSheathSword: Sheath pushed to buffer" );
  2642. PushCombatActionOnBuffer(EBAT_Sheathe_Sword,BS_Pressed);
  2643. }
  2644. else
  2645. {
  2646. LogChannel( 'OnCombatFinished', "DelayedSheathSword: Sheath successful" );
  2647. OnEquipMeleeWeapon( PW_None, false );
  2648. }
  2649. }
  2650. }
  2651.  
  2652. protected function ShouldAutoSheathSwordInstantly() : bool
  2653. {
  2654. var enemies : array<CActor>;
  2655. var i : int;
  2656.  
  2657. GetEnemiesInRange( enemies );
  2658.  
  2659. for ( i = 0; i < enemies.Size(); i += 1 )
  2660. {
  2661. if ( IsThreat( enemies[i] ) &&
  2662. VecDistance( enemies[i].GetWorldPosition(), this.GetWorldPosition() ) <= findMoveTargetDist )
  2663. {
  2664. return false;
  2665. }
  2666. }
  2667.  
  2668. return true;
  2669. }
  2670.  
  2671. public function PrepareToAttack( optional target : CActor, optional action : EBufferActionType )
  2672. {
  2673. var weaponType : EPlayerWeapon;
  2674.  
  2675. if( IsInAir() || !GetBIsCombatActionAllowed() )
  2676. {
  2677. return ;
  2678. }
  2679.  
  2680. if( !target )
  2681. {
  2682. target = (CActor)displayTarget;
  2683. }
  2684. if( !target && IsCombatMusicEnabled() )
  2685. {
  2686. target = moveTarget;
  2687. }
  2688. if( !target )
  2689. {
  2690. if ( this.GetCurrentStateName() == 'Exploration' )
  2691. {
  2692. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  2693. thePlayer.CanAttackWhenNotInCombat( action, false, target );
  2694. }
  2695. }
  2696.  
  2697. weaponHolster.TryToPrepareMeleeWeaponToAttack();
  2698.  
  2699. //if ( this.GetCurrentStateName() == 'Exploration' ) //PF - commenting this because Geralt won't switch to proper state when you sheathe sword while mashing attack
  2700. {
  2701. weaponType = GetCurrentMeleeWeaponType();
  2702.  
  2703. if ( weaponType == PW_None )
  2704. {
  2705. // Get the weapon we have to use
  2706. weaponType = GetMostConvenientMeleeWeapon( target );
  2707. }
  2708.  
  2709. // Can't go to combat if we are in not a proper state
  2710. if( !OnStateCanGoToCombat() )
  2711. {
  2712. return;
  2713. }
  2714.  
  2715. GoToCombat( weaponType );
  2716. }
  2717. }
  2718.  
  2719. public function DisplayCannotAttackMessage( actor : CActor ) : bool
  2720. {
  2721. if ( actor && ( actor.GetMovingAgentComponent().GetName() == "child_base" || ((CNewNPC)actor).GetNPCType() == ENGT_Quest ) )
  2722. {
  2723. DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_cant_attack_this_target"));
  2724. return true;
  2725. }
  2726.  
  2727. return false;
  2728. }
  2729.  
  2730. public function GetMostConvenientMeleeWeapon( targetToDrawAgainst : CActor, optional ignoreActionLock : bool ) : EPlayerWeapon
  2731. {
  2732. return weaponHolster.GetMostConvenientMeleeWeapon( targetToDrawAgainst, ignoreActionLock );
  2733. }
  2734.  
  2735. private var reevaluateCurrentWeapon : bool;
  2736.  
  2737. event OnTargetWeaponDrawn()
  2738. {
  2739. var weaponType : EPlayerWeapon = this.GetCurrentMeleeWeaponType();
  2740. if ( weaponType == PW_Fists )
  2741. reevaluateCurrentWeapon = true;
  2742. }
  2743.  
  2744. public function GoToCombatIfNeeded( optional enemy : CActor ) : bool
  2745. {
  2746. var weaponType : EPlayerWeapon;
  2747. var target : CActor;
  2748.  
  2749. if( !enemy && IsInCombat() )
  2750. {
  2751. target = GetTarget();
  2752.  
  2753. if ( target )
  2754. enemy = target;
  2755. else
  2756. enemy = moveTarget;
  2757. }
  2758.  
  2759. // Should we fight
  2760. if( !ShouldGoToCombat( enemy ) )
  2761. {
  2762. return false;
  2763. }
  2764.  
  2765. weaponType = this.GetCurrentMeleeWeaponType();
  2766.  
  2767. if ( weaponType == PW_None || ( reevaluateCurrentWeapon && weaponType == PW_Fists ) || ( !IsInCombat() && weaponHolster.IsOnTheMiddleOfHolstering() ) )
  2768. {
  2769. // Get the weapon we have to use
  2770. weaponType = weaponHolster.GetMostConvenientMeleeWeapon( enemy );
  2771. reevaluateCurrentWeapon = false;
  2772. }
  2773.  
  2774. // Change the state+
  2775. GoToCombat( weaponType );
  2776.  
  2777.  
  2778. return true;
  2779. }
  2780.  
  2781. public function GoToCombatIfWanted( ) : bool
  2782. {
  2783. var weaponType : EPlayerWeapon;
  2784. var target : CActor;
  2785. var enemy : CActor;
  2786.  
  2787.  
  2788. if( !IsInCombat() )
  2789. {
  2790. return false;
  2791. }
  2792.  
  2793. target = GetTarget();
  2794.  
  2795. if ( target )
  2796. enemy = target;
  2797. else
  2798. enemy = moveTarget;
  2799.  
  2800. weaponType = this.GetCurrentMeleeWeaponType();
  2801.  
  2802. if ( weaponType == PW_None || ( !IsInCombat() && weaponHolster.IsOnTheMiddleOfHolstering() ) )
  2803. {
  2804. // Get the weapon we have to use
  2805. weaponType = weaponHolster.GetMostConvenientMeleeWeapon( enemy );
  2806. }
  2807.  
  2808. // Change the state+
  2809. GoToCombat( weaponType );
  2810.  
  2811.  
  2812. return true;
  2813. }
  2814.  
  2815. public function GoToExplorationIfNeeded() : bool
  2816. {
  2817. /*
  2818. if( GetCurrentStateName() == 'Exploration' )
  2819. {
  2820. return false;
  2821. }
  2822. */
  2823.  
  2824. if( ! IsInCombatState() )
  2825. {
  2826. return false;
  2827. }
  2828.  
  2829. if( !ShouldGoToExploration() )
  2830. {
  2831. return false;
  2832. }
  2833.  
  2834. // Change fists weapon to none
  2835. weaponHolster.EndedCombat();
  2836.  
  2837. // Change the state
  2838. GotoState( 'Exploration' );
  2839. return true;
  2840. }
  2841.  
  2842. event OnStateCanGoToCombat()
  2843. {
  2844. return false;
  2845. }
  2846.  
  2847. event OnStateCanUpdateExplorationSubstates()
  2848. {
  2849. return false;
  2850. }
  2851.  
  2852. private function ShouldGoToCombat( optional enemy : CActor ) : bool
  2853. {
  2854. // TODO If we don't have a specific enemy, let's just check if there are hostiles to fight
  2855. if ( !enemy )
  2856. {
  2857. //return isFightingHostiles;
  2858. return false;
  2859. }
  2860.  
  2861. // Can't go to combat if we are in not a proper state
  2862. if( !OnStateCanGoToCombat() )
  2863. {
  2864. return false;
  2865. }
  2866.  
  2867. // See if we should be fighting this enemy
  2868. /*if ( !IsEnemyVisible( enemy ) )
  2869. {
  2870. return false;
  2871. }*/
  2872. /*if ( !WasVisibleInScaledFrame( enemy, 1.f, 1.f ) )
  2873. {
  2874. return false;
  2875. }*/
  2876.  
  2877. if ( this.GetCurrentStateName() == 'AimThrow' )
  2878. {
  2879. return false;
  2880. }
  2881.  
  2882. if ( this.GetCurrentStateName() == 'Swimming' )
  2883. {
  2884. return false;
  2885. }
  2886.  
  2887. if ( this.GetCurrentStateName() == 'TraverseExploration' )
  2888. {
  2889. return false;
  2890. }
  2891.  
  2892. // TODO: Reenable or find somethingbetter
  2893. // Temporaryly disabled cause it does not work on some terrain
  2894. /*
  2895. if ( !theGame.GetWorld().NavigationLineTest( GetWorldPosition(), enemy.GetWorldPosition(), 0.4 ) )
  2896.  
  2897. if ( !enemy )
  2898. {
  2899. return false;
  2900. }
  2901. */
  2902.  
  2903.  
  2904.  
  2905.  
  2906. return true;
  2907. }
  2908.  
  2909. private function ShouldGoToExploration() : bool
  2910. {
  2911. if ( IsInCombat() )//moveTarget && IsThreat( moveTarget ) )
  2912. {
  2913. return false;
  2914. }
  2915. /*if( IsGuarded() )
  2916. {
  2917. return false;
  2918. }*/
  2919. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  2920. {
  2921. return false;
  2922. }
  2923. if( IsFistFightMinigameEnabled() )
  2924. {
  2925. return false;
  2926. }
  2927. if( IsKnockedUnconscious() )
  2928. {
  2929. return false;
  2930. }
  2931. if( IsInCombatAction() )
  2932. {
  2933. return false;
  2934. }
  2935. if( GetCriticalBuffsCount() > 0 )
  2936. {
  2937. return false;
  2938. }
  2939.  
  2940. return true;
  2941. }
  2942.  
  2943. private function GoToCombat( weaponType : EPlayerWeapon, optional initialAction : EInitialAction )
  2944. {
  2945. // Set up and change state
  2946. switch( weaponType )
  2947. {
  2948. case PW_Silver:
  2949. ((W3PlayerWitcherStateCombatSilver) GetState('CombatSilver')).SetupState( initialAction );
  2950. GoToStateIfNew( 'CombatSilver' );
  2951. break;
  2952. case PW_Steel:
  2953. ((W3PlayerWitcherStateCombatSteel) GetState('CombatSteel')).SetupState( initialAction );
  2954. GoToStateIfNew( 'CombatSteel' );
  2955. break;
  2956. case PW_Fists:
  2957. case PW_None:
  2958. default :
  2959. ((W3PlayerWitcherStateCombatFists) GetState('CombatFists')).SetupState( initialAction );
  2960. GoToStateIfNew( 'CombatFists' );
  2961. break;
  2962. }
  2963. }
  2964.  
  2965. public function GoToStateIfNew( newState : name, optional keepStack : bool, optional forceEvents : bool )
  2966. {
  2967. if( newState != GetCurrentStateName() )
  2968. {
  2969. GotoState( newState, keepStack, forceEvents );
  2970. }
  2971. }
  2972.  
  2973. // So we can debug and control what is changing the state
  2974. public function GotoState( newState : name, optional keepStack : bool, optional forceEvents : bool )
  2975. {
  2976. /*if( newState == 'Exploration' )
  2977. {
  2978. newState = newState;
  2979. }*/
  2980.  
  2981. super.GotoState( newState, keepStack, forceEvents );
  2982. //PushState( newState );
  2983. }
  2984. /*
  2985. public function PushState( newState : name )
  2986. {
  2987. if( newState == 'Exploration' )
  2988. {
  2989. newState = newState;
  2990. }
  2991. super.PushState( newState );
  2992. }
  2993.  
  2994. public function PopState( optional popAll : bool )
  2995. {
  2996. super.PopState( popAll );
  2997. }
  2998. */
  2999. public function IsThisACombatSuperState( stateName : name ) : bool
  3000. {
  3001. return stateName == 'Combat' || stateName == 'CombatSteel' || stateName == 'CombatSilver' || stateName == 'CombatFists';
  3002. }
  3003.  
  3004. public function GetWeaponHolster() : WeaponHolster
  3005. {
  3006. return weaponHolster;
  3007. }
  3008.  
  3009. public function AbortSign()
  3010. {
  3011. var playerWitcher : W3PlayerWitcher;
  3012. var sign : W3SignEntity;
  3013.  
  3014. playerWitcher = (W3PlayerWitcher)this;
  3015.  
  3016. if(playerWitcher)
  3017. {
  3018. sign = (W3SignEntity)playerWitcher.GetCurrentSignEntity();
  3019. if (sign)
  3020. {
  3021. sign.OnSignAborted();
  3022. }
  3023. }
  3024. }
  3025.  
  3026. ///////////////////////////////////////////////////////////////////////////
  3027. // Animation event handlers
  3028. ///////////////////////////////////////////////////////////////////////////
  3029. protected var disableActionBlend : bool;
  3030.  
  3031. //KonradSuperDodgeHACK: To make dodge more responsive during NORMAL ATTACKS, dodge will fire immediately when hit animation can be played.
  3032. //When hit anim is disabled, then the action will be cached and will be processed at the END of DisallowHitAnim event.
  3033. //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.
  3034. event OnAnimEvent_DisallowHitAnim( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3035. {
  3036. if ( animEventType == AET_DurationEnd )
  3037. {
  3038. if ( ( BufferCombatAction == EBAT_Dodge || BufferCombatAction == EBAT_Roll )
  3039. && IsInCombatAction()
  3040. && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack )
  3041. {
  3042. //LogChannel('combatActionAllowed',"BufferCombatAction != EBAT_EMPTY");
  3043. ( (CR4Player)this ).ProcessCombatActionBuffer();
  3044. disableActionBlend = true;
  3045. }
  3046. }
  3047. else if ( IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge && animEventType == AET_DurationStart )
  3048. {
  3049. disableActionBlend = false;
  3050. }
  3051.  
  3052. super.OnAnimEvent_DisallowHitAnim( animEventName, animEventType, animInfo );
  3053. }
  3054.  
  3055.  
  3056. event OnAnimEvent_FadeOut( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3057. {
  3058. theGame.FadeOutAsync( 0.2, Color( 0, 0, 0, 1 ) );
  3059. }
  3060.  
  3061. event OnAnimEvent_FadeIn( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3062. {
  3063. theGame.FadeInAsync( 0.4 );
  3064. }
  3065.  
  3066. event OnAnimEvent_BloodTrailForced( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3067. {
  3068. var bloodTrailParam : CBloodTrailEffect;
  3069. var weaponId : SItemUniqueId;
  3070.  
  3071. if ( isInFinisher )
  3072. {
  3073. bloodTrailParam = (CBloodTrailEffect)(GetFinisherVictim()).GetGameplayEntityParam( 'CBloodTrailEffect' );
  3074. weaponId = this.inv.GetItemFromSlot('r_weapon');
  3075. if ( bloodTrailParam )
  3076. thePlayer.inv.PlayItemEffect( weaponId, bloodTrailParam.GetEffectName() );
  3077. }
  3078. }
  3079.  
  3080. event OnAnimEvent_SlowMo( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3081. {
  3082. if ( isInFinisher && DisableManualCameraControlStackHasSource( 'Finisher' ) )
  3083. {
  3084. if( animEventType != AET_DurationEnd )
  3085. theGame.SetTimeScale( 0.1f, 'AnimEventSlomoMo', 1000, true );
  3086. else
  3087. theGame.RemoveTimeScale( 'AnimEventSlomoMo' );
  3088. }
  3089. }
  3090.  
  3091. event OnAnimEvent_PlayFinisherBlood( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3092. {
  3093. if ( isInFinisher )
  3094. {
  3095. SpawnFinisherBlood();
  3096. }
  3097. }
  3098.  
  3099. event OnAnimEvent_OnWeaponDrawReady( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3100. {
  3101. weaponHolster.OnWeaponDrawReady();
  3102. }
  3103.  
  3104. event OnAnimEvent_OnWeaponHolsterReady( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3105. {
  3106. weaponHolster.OnWeaponHolsterReady();
  3107. }
  3108.  
  3109. event OnAnimEvent_ThrowHoldTest( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3110. {
  3111. var thrownEntity : CThrowable;
  3112.  
  3113. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  3114.  
  3115. if( IsThrowHold() )
  3116. {
  3117. SetBehaviorVariable( 'throwStage', (int)TS_Loop );
  3118. PushState( 'AimThrow' );
  3119. thrownEntity.StartAiming();
  3120. }
  3121. else
  3122. {
  3123. BombThrowRelease();
  3124. SetCombatIdleStance( 1.f );
  3125. }
  3126. }
  3127.  
  3128. event OnAnimEvent_AllowTempLookAt( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3129. {
  3130. if( animEventType == AET_DurationStart )
  3131. SetTempLookAtTarget( slideTarget );
  3132. else if( animEventType == AET_DurationEnd )
  3133. SetTempLookAtTarget( NULL );
  3134. }
  3135.  
  3136. protected var slideNPC : CNewNPC;
  3137. protected var minSlideDistance : float;
  3138. protected var maxSlideDistance : float;
  3139. protected var slideTicket : SMovementAdjustmentRequestTicket;
  3140.  
  3141. event OnAnimEvent_SlideToTarget( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3142. {
  3143. var movementAdjustor : CMovementAdjustor;
  3144.  
  3145. if ( animEventType == AET_DurationStart )
  3146. slideNPC = (CNewNPC)slideTarget;
  3147. }
  3148.  
  3149. if(!slideNPC)
  3150. return false;
  3151. }
  3152.  
  3153. if ( animEventType == AET_DurationStart && slideNPC.GetGameplayVisibility() )
  3154. {
  3155. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3156. slideTicket = movementAdjustor.GetRequest( 'SlideToTarget' );
  3157. movementAdjustor.CancelByName( 'SlideToTarget' );
  3158. slideTicket = movementAdjustor.CreateNewRequest( 'SlideToTarget' );
  3159. movementAdjustor.BindToEventAnimInfo( slideTicket, animInfo );
  3160. //movementAdjustor.Continuous(slideTicket);
  3161. movementAdjustor.MaxLocationAdjustmentSpeed( slideTicket, 1000000 );
  3162. movementAdjustor.ScaleAnimation( slideTicket );
  3163. minSlideDistance = ((CMovingPhysicalAgentComponent)this.GetMovingAgentComponent()).GetCapsuleRadius()+((CMovingPhysicalAgentComponent)slideNPC.GetMovingAgentComponent()).GetCapsuleRadius();
  3164. movementAdjustor.SlideTowards( slideTicket, slideTarget, minSlideDistance, minSlideDistance );
  3165. if( IsInCombatFist() )
  3166. {
  3167. maxSlideDistance = 1000.0f;
  3168. }
  3169. else
  3170. {
  3171. maxSlideDistance = minSlideDistance;
  3172. }
  3173. movementAdjustor.SlideTowards( slideTicket, slideTarget, minSlideDistance, maxSlideDistance );
  3174. }
  3175. else if ( !slideNPC.GetGameplayVisibility() )
  3176. {
  3177. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3178. movementAdjustor.CancelByName( 'SlideToTarget' );
  3179. slideNPC = NULL;
  3180. }
  3181. else
  3182. {
  3183. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3184. movementAdjustor.SlideTowards( slideTicket, slideTarget, minSlideDistance, minSlideDistance );
  3185. }
  3186. }
  3187.  
  3188. event OnAnimEvent_ActionBlend( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3189. {
  3190. }
  3191. /*
  3192. event OnAnimEvent_Throwable( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3193. {
  3194. var thrownEntity : CThrowable;
  3195.  
  3196. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  3197.  
  3198. if ( inv.IsItemCrossbow( inv.GetItemFromSlot('l_weapon') ) && rangedWeapon.OnProcessThrowEvent( animEventName ) )
  3199. {
  3200. return true;
  3201. }
  3202. else if( thrownEntity && IsThrowingItem() && thrownEntity.OnProcessThrowEvent( animEventName ) )
  3203. {
  3204. return true;
  3205. }
  3206. }*/
  3207.  
  3208. event OnAnimEvent_SubstateManager( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3209. {
  3210. // Notify the exploration manager
  3211. substateManager.OnAnimEvent( animEventName, animEventType, animInfo );
  3212. }
  3213.  
  3214. event OnAnimEvent_AllowFall( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3215. {
  3216. if ( !substateManager.m_OwnerMAC.IsOnGround() )
  3217. {
  3218. substateManager.m_SharedDataO.SetFallFromCritical( true );
  3219. substateManager.m_MoverO.SetVelocity( -6.0f * GetWorldForward() );
  3220. substateManager.QueueStateExternal( 'Jump' );
  3221. RemoveBuff( EET_Knockdown, true );
  3222. RemoveBuff( EET_HeavyKnockdown, true );
  3223. return true;
  3224. }
  3225. return false;
  3226. }
  3227.  
  3228. event OnAnimEvent_AllowFall2( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3229. {
  3230. if ( !substateManager.m_OwnerMAC.IsOnGround() )
  3231. {
  3232. //substateManager.m_SharedDataO.m_FromCriticalB = true;
  3233. //substateManager.m_MoverO.SetVelocity( -6.0f * GetWorldForward() );
  3234. substateManager.QueueStateExternal( 'Jump' );
  3235. RemoveBuff( EET_Knockdown, true );
  3236. RemoveBuff( EET_HeavyKnockdown, true );
  3237. }
  3238. if( substateManager.StateWantsAndCanEnter( 'Slide' ) )
  3239. {
  3240. substateManager.QueueStateExternal( 'Slide' );
  3241. }
  3242. }
  3243.  
  3244. event OnAnimEvent_DettachGround( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3245. {
  3246. //substateManager.m_MoverO.SetManualMovement( true );
  3247. }
  3248.  
  3249. //pad vibration for finishers
  3250. event OnAnimEvent_pad_vibration( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3251. {
  3252. var witcher : W3PlayerWitcher;
  3253.  
  3254. theGame.VibrateControllerHard();
  3255.  
  3256. //delayed FX for runeword 10 & 12
  3257. witcher = GetWitcherPlayer();
  3258. if(isInFinisher && witcher)
  3259. {
  3260. if(HasAbility('Runeword 10 _Stats', true) && !witcher.runeword10TriggerredOnFinisher && ((bool)theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'AutomaticFinishersEnabled')) == true)
  3261. {
  3262. witcher.Runeword10Triggerred();
  3263. witcher.runeword10TriggerredOnFinisher = true;
  3264. }
  3265. else if(HasAbility('Runeword 12 _Stats', true) && !witcher.runeword12TriggerredOnFinisher)
  3266. {
  3267. witcher.Runeword12Triggerred();
  3268. witcher.runeword12TriggerredOnFinisher = true;
  3269. }
  3270. }
  3271. }
  3272.  
  3273. //pad vibration light
  3274. event OnAnimEvent_pad_vibration_light( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3275. {
  3276. //theGame.VibrateControllerLight(); //draw & sheathe weapon
  3277. }
  3278.  
  3279. event OnAnimEvent_KillWithRagdoll( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3280. {
  3281. //thePlayer.SetKinematic( false );
  3282. //thePlayer.Kill();
  3283. }
  3284.  
  3285. event OnAnimEvent_RemoveBurning( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3286. {
  3287. thePlayer.AddBuffImmunity(EET_Burning, 'AnimEvent_RemoveBurning', true);
  3288. }
  3289.  
  3290. event OnAnimEvent_RemoveTangled( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3291. {
  3292. if ( this.HasBuff( EET_Tangled ) )
  3293. {
  3294. this.StopEffect('black_spider_web');
  3295. this.PlayEffectSingle('black_spider_web_break');
  3296. }
  3297. }
  3298. ///////////////////////////////////////////////////////////////////////////
  3299.  
  3300. event OnAnimEvent_MoveNoise( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3301. {
  3302. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'MoveNoise', -1, 30.0f, -1.f, -1, true );
  3303. }
  3304.  
  3305.  
  3306. event OnBehaviorGraphNotification( notificationName : name, stateName : name )
  3307. {
  3308. substateManager.OnBehaviorGraphNotification( notificationName, stateName );
  3309.  
  3310. if( notificationName == 'PlayerRunActivate' )
  3311. {
  3312. isInRunAnimation = true;
  3313. }
  3314. else if( notificationName == 'PlayerRunDeactivate' )
  3315. {
  3316. isInRunAnimation = false;
  3317. }
  3318. }
  3319.  
  3320. event OnEnumAnimEvent( animEventName : name, variant : SEnumVariant, animEventType : EAnimationEventType, animEventDuration : float, animInfo : SAnimationEventAnimInfo )
  3321. {
  3322. var movementAdjustor : CMovementAdjustor;
  3323. var ticket : SMovementAdjustmentRequestTicket;
  3324. var rotationRate : ERotationRate;
  3325.  
  3326. if ( animEventName == 'RotateToTarget' )
  3327. {
  3328. /**
  3329. * Rotate player to target
  3330. */
  3331. rotationRate = GetRotationRateFromAnimEvent( variant.enumValue );
  3332.  
  3333. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3334. if ( animEventType == AET_DurationStart || animEventType == AET_DurationStartInTheMiddle )
  3335. {
  3336. // when it starts (also in the middle - it may mean that we switch between events)
  3337. // create request if there isn't any and always setup rotation rate
  3338. if (! movementAdjustor.IsRequestActive( movementAdjustor.GetRequest( 'RotateToTarget' ) ) )
  3339. {
  3340. // start rotation adjustment
  3341. ticket = movementAdjustor.CreateNewRequest( 'RotateToTarget' );
  3342.  
  3343. // use adjustment duration only when RR_0 is selected, otherwise use continuous to match desired rotation as fast as possible
  3344. if ((int)rotationRate == 0)
  3345. movementAdjustor.AdjustmentDuration( ticket, animEventDuration );
  3346. else
  3347. {
  3348. movementAdjustor.Continuous( ticket );
  3349. movementAdjustor.BindToEvent( ticket, 'RotateToTarget' );
  3350. }
  3351.  
  3352. movementAdjustor.DontUseSourceAnimation( ticket ); // do not use source anim as it will use delta seconds from event
  3353. movementAdjustor.ReplaceRotation( ticket );
  3354. }
  3355. else
  3356. {
  3357. // get existing ticket to update rotation rate
  3358. ticket = movementAdjustor.GetRequest( 'RotateToTarget' );
  3359. }
  3360. MovAdjRotateToTarget( ticket );
  3361. // update rotationRate
  3362. if ((int)rotationRate > 0)
  3363. {
  3364. movementAdjustor.MaxRotationAdjustmentSpeed( ticket, (float)((int)rotationRate) );
  3365. }
  3366. }
  3367. else if ( animEventType == AET_DurationEnd )
  3368. {
  3369. // it will end if there's no event, but sometimes one event could end and be followed by another
  3370. // and we want to have that continuity kept, that's why we won't end request manually
  3371. }
  3372. else
  3373. {
  3374. // continuous update (makes more sense when there is no target and we want to rotate towards camera)
  3375. ticket = movementAdjustor.GetRequest( 'RotateToTarget' );
  3376. MovAdjRotateToTarget( ticket );
  3377. }
  3378. }
  3379. super.OnEnumAnimEvent(animEventName, variant, animEventType, animEventDuration, animInfo);
  3380. }
  3381.  
  3382. event OnTeleported()
  3383. {
  3384. if( substateManager )
  3385. {
  3386. substateManager.OnTeleported();
  3387. }
  3388. }
  3389.  
  3390. /*public function CaptureSafePosition()
  3391. {
  3392. lastSafePosition = GetWorldPosition();
  3393. lastSafeRotation = GetWorldRotation();
  3394. safePositionStored = true;
  3395. }*/
  3396.  
  3397. ///////////////////////////////////////////////////////////////////////////
  3398. // FISTFIGHT
  3399. ///////////////////////////////////////////////////////////////////////////
  3400.  
  3401.  
  3402.  
  3403.  
  3404.  
  3405. event OnStartFistfightMinigame()
  3406. {
  3407. super.OnStartFistfightMinigame();
  3408.  
  3409. //Goto state CombatFist
  3410. SetFistFightMinigameEnabled( true );
  3411. FistFightHealthChange( true );
  3412. thePlayer.GetPlayerMode().ForceCombatMode( FCMR_QuestFunction );
  3413. SetImmortalityMode(AIM_Unconscious, AIC_Fistfight);
  3414. thePlayer.SetBehaviorVariable( 'playerWeaponLatent', (int)PW_Fists );
  3415. GotoCombatStateWithAction( IA_None );
  3416. ((CMovingAgentComponent)this.GetMovingAgentComponent()).SnapToNavigableSpace( true );
  3417. EquipGeraltFistfightWeapon( true );
  3418. BlockAction( EIAB_RadialMenu, 'FistfightMinigame' ,,true);
  3419. BlockAction( EIAB_Signs, 'FistfightMinigame' ,,true);
  3420. BlockAction( EIAB_ThrowBomb, 'FistfightMinigame' ,,true);
  3421. BlockAction( EIAB_UsableItem, 'FistfightMinigame' ,,true);
  3422. BlockAction( EIAB_Crossbow, 'FistfightMinigame' ,,true);
  3423. BlockAction( EIAB_DrawWeapon, 'FistfightMinigame' ,,true);
  3424. BlockAction( EIAB_RunAndSprint, 'FistfightMinigame' ,,true);
  3425. BlockAction( EIAB_SwordAttack, 'FistfightMinigame' ,,true);
  3426. BlockAction( EIAB_CallHorse, 'FistfightMinigame' ,,true);
  3427. BlockAction( EIAB_Roll, 'FistfightMinigame' ,,true);
  3428. BlockAction( EIAB_Interactions, 'FistfightMinigame' ,,true);
  3429. BlockAction( EIAB_Explorations, 'FistfightMinigame' ,,true);
  3430. BlockAction( EIAB_OpenInventory, 'FistfightMinigame' ,,true);
  3431. BlockAction( EIAB_QuickSlots, 'FistfightMinigame' ,,true);
  3432. BlockAction( EIAB_OpenCharacterPanel, 'FistfightMinigame' ,,true);
  3433. }
  3434.  
  3435. event OnEndFistfightMinigame()
  3436. {
  3437. ((CMovingAgentComponent)this.GetMovingAgentComponent()).SnapToNavigableSpace( false );
  3438. FistFightHealthChange( false );
  3439. thePlayer.GetPlayerMode().ReleaseForceCombatMode( FCMR_QuestFunction );
  3440. EquipGeraltFistfightWeapon( false );
  3441. SetFistFightMinigameEnabled( false );
  3442. SetImmortalityMode(AIM_None, AIC_Fistfight);
  3443. BlockAllActions('FistfightMinigame',false);
  3444.  
  3445. super.OnEndFistfightMinigame();
  3446. }
  3447.  
  3448. public function GetFistFightFinisher( out masterAnimName, slaveAnimIndex : name )
  3449. {
  3450. var index : int;
  3451.  
  3452. index = RandRange(1);
  3453. switch ( index )
  3454. {
  3455. case 0 : masterAnimName = 'man_fistfight_finisher_1_win'; slaveAnimIndex = 'man_fistfight_finisher_1_looser';
  3456. }
  3457. }
  3458.  
  3459. public function SetFistFightMinigameEnabled( flag : bool )
  3460. {
  3461. fistFightMinigameEnabled = flag;
  3462. }
  3463.  
  3464. public function SetFistFightParams( toDeath : bool, endsWithBS : bool )
  3465. {
  3466. isFFMinigameToTheDeath = toDeath;
  3467. FFMinigameEndsithBS = endsWithBS;
  3468. }
  3469.  
  3470. public function IsFistFightMinigameEnabled() : bool
  3471. {
  3472. return fistFightMinigameEnabled;
  3473. }
  3474.  
  3475. public function IsFistFightMinigameToTheDeath() : bool
  3476. {
  3477. return isFFMinigameToTheDeath;
  3478. }
  3479.  
  3480. public function FistFightHealthChange( val : bool )
  3481. {
  3482. if( val == true )
  3483. {
  3484. GeraltMaxHealth = thePlayer.GetStatMax(BCS_Vitality);
  3485. ClampGeraltMaxHealth( 2000 );
  3486. SetHealthPerc( 100 );
  3487. }
  3488. else
  3489. {
  3490. ClampGeraltMaxHealth( GeraltMaxHealth );
  3491. SetHealthPerc( 100 );
  3492. }
  3493.  
  3494. }
  3495.  
  3496. function ClampGeraltMaxHealth( val : float )
  3497. {
  3498. thePlayer.abilityManager.SetStatPointMax( BCS_Vitality, val );
  3499. }
  3500.  
  3501. function EquipGeraltFistfightWeapon( val : bool )
  3502. {
  3503. if ( val )
  3504. {
  3505. fistsItems = thePlayer.GetInventory().AddAnItem( 'Geralt Fistfight Fists', 1, true, true );
  3506. thePlayer.GetInventory().MountItem( fistsItems[0] , true );
  3507. }
  3508. else
  3509. {
  3510. thePlayer.GetInventory().DropItem( fistsItems[0], true );
  3511. }
  3512. }
  3513.  
  3514. ///////////////////////////////////////////////////////////////////////////
  3515. // GWINT
  3516. ///////////////////////////////////////////////////////////////////////////
  3517. public function GetGwintAiDifficulty() : EGwintDifficultyMode
  3518. {
  3519. return gwintAiDifficulty;
  3520. }
  3521.  
  3522. public function SetGwintAiDifficulty( difficulty : EGwintDifficultyMode )
  3523. {
  3524. gwintAiDifficulty = difficulty;
  3525. }
  3526.  
  3527. public function GetGwintAiAggression() : EGwintAggressionMode
  3528. {
  3529. return gwintAiAggression;
  3530. }
  3531.  
  3532. public function SetGwintAiAggression( aggression : EGwintAggressionMode )
  3533. {
  3534. gwintAiAggression = aggression;
  3535. }
  3536.  
  3537. public function GetGwintMinigameState() : EMinigameState
  3538. {
  3539. return gwintMinigameState;
  3540. }
  3541.  
  3542. public function SetGwintMinigameState( minigameState : EMinigameState )
  3543. {
  3544. gwintMinigameState = minigameState;
  3545. }
  3546.  
  3547. public function OnGwintGameRequested( deckName : name )
  3548. {
  3549. var gwintManager:CR4GwintManager;
  3550. gwintManager = theGame.GetGwintManager();
  3551.  
  3552. gwintMinigameState = EMS_None;
  3553.  
  3554. gwintManager.SetEnemyDeckByName(deckName);
  3555. gwintManager.SetForcedFaction(forceFaction);
  3556.  
  3557. if (gwintManager.GetHasDoneTutorial() || !theGame.GetTutorialSystem().AreMessagesEnabled())
  3558. {
  3559. gwintManager.gameRequested = true;
  3560. theGame.RequestMenu( 'DeckBuilder' );
  3561. }
  3562. else
  3563. {
  3564. theGame.GetGuiManager().ShowUserDialog( UMID_SkipGwintTutorial, "gwint_tutorial_play_query_title", "gwint_tutorial_play_query", UDB_YesNo );
  3565. }
  3566. }
  3567.  
  3568. public function StartGwint_TutorialOrSkip( skipTutorial : bool )
  3569. {
  3570. var gwintManager : CR4GwintManager;
  3571.  
  3572. if( skipTutorial )
  3573. {
  3574. gwintManager = theGame.GetGwintManager();
  3575. gwintManager.gameRequested = true;
  3576. gwintManager.SetHasDoneTutorial(true);
  3577. gwintManager.SetHasDoneDeckTutorial(true);
  3578. theGame.RequestMenu( 'DeckBuilder' );
  3579. }
  3580. else
  3581. {
  3582. theGame.RequestMenu( 'GwintGame' );
  3583. }
  3584. }
  3585.  
  3586. private var gwintCardNumbersArray : array<int>;
  3587.  
  3588. public function InitGwintCardNumbersArray( arr : array<int> )
  3589. {
  3590. gwintCardNumbersArray.Clear();
  3591. gwintCardNumbersArray = arr;
  3592. }
  3593.  
  3594. public function GetCardNumbersArray() : array<int>
  3595. {
  3596. return gwintCardNumbersArray;
  3597. }
  3598. ///////////////////////////////////////////////////////////////////////////
  3599. // COMBAT CAMERA
  3600. ///////////////////////////////////////////////////////////////////////////
  3601.  
  3602. protected var customCameraStack : array<SCustomCameraParams>;
  3603.  
  3604. public function AddCustomCamToStack( customCameraParams : SCustomCameraParams ) : int
  3605. {
  3606. if( customCameraParams.useCustomCamera )
  3607. {
  3608. if ( customCameraParams.cameraParams.enums[0].enumType != 'ECustomCameraType' )
  3609. {
  3610. LogChannel( 'CustomCamera', "ERROR: Selected enum is not a custom camera!!!" );
  3611. return -1;
  3612. }
  3613. else
  3614. {
  3615. customCameraStack.PushBack( customCameraParams );
  3616. return ( customCameraStack.Size() - 1 );
  3617. }
  3618. }
  3619.  
  3620. return 0;
  3621. }
  3622.  
  3623. public function DisableCustomCamInStack( customCameraStackIndex : int )
  3624. {
  3625. if ( customCameraStackIndex != -1 )
  3626. customCameraStack[customCameraStackIndex].useCustomCamera = false;
  3627. else
  3628. LogChannel( 'CustomCamera', "ERROR: Custom camera to disable does not exist!!!" );
  3629. }
  3630.  
  3631. event OnInteriorStateChanged( inInterior : bool )
  3632. {
  3633. interiorCamera = inInterior;
  3634. }
  3635.  
  3636. event OnModifyPlayerSpeed( flag : bool )
  3637. {
  3638. modifyPlayerSpeed = flag;
  3639. SetBehaviorVariable( 'modifyPlayerSpeed', (float)modifyPlayerSpeed );
  3640. }
  3641.  
  3642. event OnGameCameraTick( out moveData : SCameraMovementData, dt : float )
  3643. {
  3644. var targetRotation : EulerAngles;
  3645. /*var dist : float;
  3646.  
  3647. if( thePlayer.IsInCombat() )
  3648. {
  3649. dist = VecDistance2D( thePlayer.GetWorldPosition(), thePlayer.GetTarget().GetWorldPosition() );
  3650. thePlayer.GetVisualDebug().AddText( 'dbg', dist, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) );
  3651. }*/
  3652.  
  3653. if ( isStartingFistFightMinigame )
  3654. {
  3655. moveData.pivotRotationValue = fistFightTeleportNode.GetWorldRotation();
  3656. isStartingFistFightMinigame = false;
  3657. }
  3658.  
  3659. // Specific substate
  3660. if( substateManager.UpdateCameraIfNeeded( moveData, dt ) )
  3661. {
  3662. return true;
  3663. }
  3664.  
  3665. // focusMode camera
  3666. if ( theGame.IsFocusModeActive() )
  3667. {
  3668. theGame.GetGameCamera().ChangePivotRotationController( 'Exploration' );
  3669. theGame.GetGameCamera().ChangePivotDistanceController( 'Default' );
  3670. theGame.GetGameCamera().ChangePivotPositionController( 'Default' );
  3671.  
  3672. // HACK
  3673. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  3674. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  3675. moveData.pivotPositionController = theGame.GetGameCamera().GetActivePivotPositionController();
  3676. // END HACK
  3677.  
  3678.  
  3679. moveData.pivotPositionController.SetDesiredPosition( thePlayer.GetWorldPosition() );
  3680.  
  3681. moveData.pivotRotationController.SetDesiredPitch( -10.0f );
  3682. moveData.pivotRotationController.maxPitch = 50.0;
  3683.  
  3684. moveData.pivotDistanceController.SetDesiredDistance( 3.5f );
  3685.  
  3686. if ( !interiorCamera )
  3687. {
  3688. moveData.pivotPositionController.offsetZ = 1.5f;
  3689. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5f, 2.0f, 0.3f ), 0.20f, dt );
  3690. }
  3691. else
  3692. {
  3693. moveData.pivotPositionController.offsetZ = 1.3f;
  3694. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5f, 2.3f, 0.5f ), 0.3f, dt );
  3695. }
  3696.  
  3697. return true;
  3698. }
  3699.  
  3700.  
  3701.  
  3702. // HACK: Target heading ( Made for ladder )
  3703. if( substateManager.m_SharedDataO.IsForceHeading( targetRotation ) )
  3704. {
  3705. moveData.pivotRotationController.SetDesiredHeading( targetRotation.Yaw );
  3706. moveData.pivotRotationController.SetDesiredPitch( targetRotation.Pitch );
  3707. moveData.pivotRotationValue.Yaw = LerpAngleF( 2.1f * dt, moveData.pivotRotationValue.Yaw, targetRotation.Yaw );
  3708. moveData.pivotRotationValue.Pitch = LerpAngleF( 1.0f * dt, moveData.pivotRotationValue.Pitch, targetRotation.Pitch );
  3709. //return true;
  3710. }
  3711.  
  3712.  
  3713. if( customCameraStack.Size() > 0 )
  3714. {
  3715. // HANDLE CUSTOM CAMERAS HERE
  3716. // IF HANDLED - RETURN TRUE
  3717. }
  3718.  
  3719. return false;
  3720. }
  3721.  
  3722. private var questCameraRequest : SQuestCameraRequest;
  3723. private var cameraRequestTimeStamp : float;
  3724.  
  3725. public function RequestQuestCamera( camera : SQuestCameraRequest )
  3726. {
  3727. questCameraRequest = camera;
  3728. questCameraRequest.requestTimeStamp = theGame.GetEngineTimeAsSeconds();
  3729. }
  3730.  
  3731. public function ResetQuestCameraRequest()
  3732. {
  3733. var cameraRequest : SQuestCameraRequest;
  3734.  
  3735. questCameraRequest = cameraRequest;
  3736. }
  3737.  
  3738. event OnGameCameraPostTick( out moveData : SCameraMovementData, dt : float )
  3739. {
  3740. var ent : CEntity;
  3741. var playerPos : Vector;
  3742. var angles : EulerAngles;
  3743.  
  3744. var distance : float;
  3745.  
  3746. /*if( thePlayer.IsInCombat() )
  3747. {
  3748. distance = VecDistance2D( thePlayer.GetWorldPosition(), thePlayer.GetTarget().GetWorldPosition() );
  3749. }
  3750.  
  3751. thePlayer.GetVisualDebug().AddText( 'Distance', "Distance form target: " + distance, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) );
  3752. */
  3753.  
  3754. if ( questCameraRequest.requestTimeStamp > 0 )
  3755. {
  3756. if ( questCameraRequest.duration > 0 && questCameraRequest.requestTimeStamp + questCameraRequest.duration < theGame.GetEngineTimeAsSeconds() )
  3757. {
  3758. ResetQuestCameraRequest();
  3759. return false;
  3760. }
  3761.  
  3762. if( questCameraRequest.lookAtTag )
  3763. {
  3764. ent = theGame.GetEntityByTag( questCameraRequest.lookAtTag );
  3765. playerPos = GetWorldPosition();
  3766. playerPos.Z += 1.8f;
  3767.  
  3768. angles = VecToRotation( ent.GetWorldPosition() - playerPos );
  3769.  
  3770. moveData.pivotRotationController.SetDesiredHeading( angles.Yaw );
  3771. moveData.pivotRotationController.SetDesiredPitch( -angles.Pitch );
  3772. }
  3773. else
  3774. {
  3775. if( questCameraRequest.requestYaw )
  3776. {
  3777. angles = GetWorldRotation();
  3778. moveData.pivotRotationController.SetDesiredHeading( angles.Yaw + questCameraRequest.yaw );
  3779. }
  3780.  
  3781. if( questCameraRequest.requestPitch )
  3782. {
  3783. moveData.pivotRotationController.SetDesiredPitch( questCameraRequest.pitch );
  3784. }
  3785. }
  3786. }
  3787. }
  3788.  
  3789. var wasRunning : bool;
  3790. var vel : float;
  3791. var smoothTime : float;
  3792.  
  3793. var constDamper : ConstDamper;
  3794. var rotMultVel : float;
  3795.  
  3796. public function UpdateCameraInterior( out moveData : SCameraMovementData, timeDelta : float )
  3797. {
  3798. var camDist : float;
  3799. var camOffset : float;
  3800. var rotMultDest : float;
  3801. var rotMult : float;
  3802. var angles : EulerAngles;
  3803.  
  3804. theGame.GetGameCamera().ChangePivotRotationController( 'ExplorationInterior' );
  3805. theGame.GetGameCamera().ChangePivotDistanceController( 'Default' );
  3806. theGame.GetGameCamera().ChangePivotPositionController( 'Default' );
  3807.  
  3808. // HACK
  3809. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  3810. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  3811. moveData.pivotPositionController = theGame.GetGameCamera().GetActivePivotPositionController();
  3812. // END HACK
  3813.  
  3814. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition(), 15.f );
  3815.  
  3816. if ( !constDamper )
  3817. {
  3818. constDamper = new ConstDamper in this;
  3819. constDamper.SetDamp( 0.35f );
  3820. }
  3821.  
  3822. if ( rawPlayerSpeed <= 0 || AbsF( AngleDistance( rawPlayerHeading, GetHeading() ) ) > 135 )
  3823. constDamper.Reset();
  3824. else if ( theGame.IsUberMovementEnabled() )
  3825. rotMult = 0.5f;
  3826. else
  3827. rotMult = 1.f;
  3828.  
  3829. rotMult = constDamper.UpdateAndGet( timeDelta, rotMult );
  3830.  
  3831. //DampFloatSpring( rotMult, rotMultVel, rotMultDest, 4.f, timeDelta );
  3832.  
  3833. if ( AbsF( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) ) < 135.f && rawPlayerSpeed > 0 )
  3834. moveData.pivotRotationController.SetDesiredHeading( GetHeading(), rotMult );
  3835. else
  3836. moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw );
  3837.  
  3838. moveData.pivotDistanceController.SetDesiredDistance( 1.5f );
  3839.  
  3840. angles = VecToRotation( GetMovingAgentComponent().GetVelocity() );
  3841. if ( AbsF( angles.Pitch ) < 8.f || bLAxisReleased )
  3842. moveData.pivotRotationController.SetDesiredPitch( -10.f );
  3843. else
  3844. moveData.pivotRotationController.SetDesiredPitch( -angles.Pitch - 18.f );
  3845.  
  3846. if ( IsGuarded() )
  3847. moveData.pivotPositionController.offsetZ = 1.0f;
  3848. else
  3849. moveData.pivotPositionController.offsetZ = 1.3f;
  3850.  
  3851. //if ( movementLockType == PMLT_NoSprint )
  3852. //{
  3853. if ( playerMoveType >= PMT_Run )
  3854. {
  3855. //camDist = 0.3f;
  3856. camDist = -0.5f;
  3857. camOffset = 0.25;
  3858.  
  3859. if ( !wasRunning )
  3860. {
  3861. smoothTime = 1.f;
  3862. wasRunning = true;
  3863. }
  3864. DampFloatSpring( smoothTime, vel, 0.1, 0.5, timeDelta );
  3865. }
  3866. else
  3867. {
  3868. //camDist = -0.6f;
  3869. camDist = 0.f;
  3870. camOffset = 0.4f;
  3871. smoothTime = 0.2f;
  3872. wasRunning = false;
  3873. }
  3874.  
  3875. //camDist = theGame.GetGameplayConfigFloatValue( 'debugA' );
  3876.  
  3877. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.3f, camDist, 0.3f ), smoothTime, timeDelta );
  3878. //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5, camDist, camOffset ), smoothTime, timeDelta );
  3879. //}
  3880. //else
  3881. // DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( theGame.GetGameplayConfigFloatValue( 'debugA' ),theGame.GetGameplayConfigFloatValue( 'debugB' ),theGame.GetGameplayConfigFloatValue( 'debugC' ) ), 0.4f, timeDelta );
  3882. //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.7f, 0.f, 0.3 ), 0.4f, timeDelta );
  3883. }
  3884.  
  3885.  
  3886. var wasBRAxisPushed : bool;
  3887. protected function UpdateCameraChanneledSign( out moveData : SCameraMovementData, timeDelta : float ) : bool
  3888. {
  3889. var screenSpaceOffset : float;
  3890. var screenSpaceOffsetFwd : float;
  3891. var screenSpaceOffsetUp : float;
  3892. var heading : float;
  3893. var pitch : float;
  3894. var playerToTargetRot : EulerAngles;
  3895. var rightOffset : float = -20.f;
  3896. var leftOffset : float = 15.f;
  3897. var angles : EulerAngles;
  3898.  
  3899. var vec : Vector;
  3900.  
  3901. if( this.IsCurrentSignChanneled() && this.GetCurrentlyCastSign() != ST_Quen && this.GetCurrentlyCastSign() != ST_Yrden )
  3902. {
  3903. theGame.GetGameCamera().ChangePivotRotationController( 'SignChannel' );
  3904. theGame.GetGameCamera().ChangePivotDistanceController( 'SignChannel' );
  3905. // HACK
  3906. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  3907. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  3908. // END HACK
  3909.  
  3910. if ( GetCurrentlyCastSign() == ST_Axii )
  3911. leftOffset = 32.f;
  3912.  
  3913. if ( oTCameraOffset != leftOffset && oTCameraOffset != rightOffset )
  3914. {
  3915. if( ( interiorCamera && !moveTarget )
  3916. || ( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) < 0 ) )
  3917. oTCameraOffset = leftOffset;
  3918. else
  3919. oTCameraOffset = rightOffset;
  3920. }
  3921.  
  3922. if ( oTCameraOffset == leftOffset )
  3923. {
  3924. screenSpaceOffset = 0.65f;
  3925. oTCameraPitchOffset = 13.f;
  3926. //moveData.pivotDistanceController.SetDesiredDistance( 0.5f, 3.f );
  3927. }
  3928. else if ( oTCameraOffset == rightOffset )
  3929. {
  3930. screenSpaceOffset = -0.65f;
  3931. oTCameraPitchOffset = 13.f;
  3932. //moveData.pivotDistanceController.SetDesiredDistance( 0.5f, 3.f );
  3933. }
  3934.  
  3935. moveData.pivotPositionController.offsetZ = 1.3f;
  3936.  
  3937. if ( !delayCameraOrientationChange )
  3938. {
  3939. if ( GetOrientationTarget() == OT_Camera || GetOrientationTarget() == OT_CameraOffset )
  3940. {
  3941. if ( bRAxisReleased )
  3942. {
  3943. heading = moveData.pivotRotationValue.Yaw;
  3944. pitch = moveData.pivotRotationValue.Pitch;
  3945. }
  3946. else
  3947. {
  3948. heading = moveData.pivotRotationValue.Yaw + oTCameraOffset;
  3949. pitch = moveData.pivotRotationValue.Pitch; //+ oTCameraPitchOffset;
  3950. }
  3951. }
  3952. else if ( GetOrientationTarget() == OT_Actor )
  3953. {
  3954. if ( GetDisplayTarget() )
  3955. vec = GetDisplayTarget().GetWorldPosition() - GetWorldPosition();
  3956. else if ( slideTarget )
  3957. vec = slideTarget.GetWorldPosition() - GetWorldPosition();
  3958. else if ( GetTarget() )
  3959. vec = GetTarget().GetWorldPosition() - GetWorldPosition();
  3960. else
  3961. vec = GetHeadingVector();
  3962.  
  3963. angles = VecToRotation( vec );
  3964. heading = angles.Yaw + oTCameraOffset;
  3965. pitch = -angles.Pitch - oTCameraPitchOffset;//-angles.Pitch;
  3966. }
  3967. else
  3968. {
  3969. angles = VecToRotation( GetHeadingVector() );
  3970. heading = angles.Yaw + oTCameraOffset;
  3971. pitch = -angles.Pitch - oTCameraPitchOffset;//-angles.Pitch;
  3972. }
  3973.  
  3974. if ( !wasBRAxisPushed && ( !bRAxisReleased ) )//|| !lastAxisInputIsMovement ) )
  3975. wasBRAxisPushed = true;
  3976.  
  3977. moveData.pivotRotationController.SetDesiredHeading( heading , 2.f );
  3978. moveData.pivotRotationController.SetDesiredPitch( pitch );
  3979. }
  3980. else
  3981. {
  3982. moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw, 1.f );
  3983. moveData.pivotRotationController.SetDesiredPitch( -oTCameraPitchOffset );
  3984. }
  3985.  
  3986. if ( moveData.pivotRotationValue.Pitch <= 5.f && moveData.pivotRotationValue.Pitch >= -15.f )
  3987. {
  3988. screenSpaceOffsetFwd = 1.8;
  3989. screenSpaceOffsetUp = 0.4;
  3990. }
  3991. else if ( moveData.pivotRotationValue.Pitch > 0 )
  3992. {
  3993. screenSpaceOffsetFwd = moveData.pivotRotationValue.Pitch*0.00727 + 1.275f;
  3994. screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, 1.5, 2.2 );
  3995.  
  3996. screenSpaceOffsetUp = -moveData.pivotRotationValue.Pitch*0.00727 + 0.4363f;
  3997. screenSpaceOffsetUp = ClampF( screenSpaceOffsetUp, 0, 0.3 );
  3998. }
  3999. else
  4000. {
  4001. if ( GetCurrentlyCastSign() == ST_Axii )
  4002. {
  4003. screenSpaceOffsetFwd = -moveData.pivotRotationValue.Pitch*0.0425 + 0.8625f;
  4004. screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, 1.5, 2.3 );
  4005. }
  4006. else
  4007. {
  4008. screenSpaceOffsetFwd = -moveData.pivotRotationValue.Pitch*0.035 + 0.75f;
  4009. screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, 1.5, 2.6 );
  4010. }
  4011. screenSpaceOffsetUp = -moveData.pivotRotationValue.Pitch*0.005 + 0.325f;
  4012. screenSpaceOffsetUp = ClampF( screenSpaceOffsetUp, 0.4, 0.5 );
  4013. }
  4014.  
  4015. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( screenSpaceOffset, screenSpaceOffsetFwd, screenSpaceOffsetUp ), 0.25f, timeDelta );//1.5,0.4
  4016. moveData.pivotDistanceController.SetDesiredDistance( 2.8f, 5.f );
  4017. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition() );
  4018.  
  4019. return true;
  4020. }
  4021. else
  4022. {
  4023. this.wasBRAxisPushed = false;
  4024.  
  4025. return false;
  4026. }
  4027. }
  4028.  
  4029. protected function UpdateCameraForSpecialAttack( out moveData : SCameraMovementData, timeDelta : float ) : bool
  4030. {
  4031. var screenSpaceOffset : float;
  4032. var tempHeading : float;
  4033. var cameraOffsetLeft : float;
  4034. var cameraOffsetRight : float;
  4035.  
  4036. if ( !specialAttackCamera )
  4037. return false;
  4038.  
  4039. theGame.GetGameCamera().ForceManualControlHorTimeout();
  4040. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4041. //if ( parent.delayCameraOrientationChange || parent.delayOrientationChange )
  4042. //{
  4043. cameraOffsetLeft = 30.f;
  4044. cameraOffsetRight = -30.f;
  4045. //}
  4046. //else
  4047. //{
  4048. // cameraOffsetLeft = 2.f;
  4049. // cameraOffsetRight = -2.f;
  4050. //}
  4051.  
  4052. theGame.GetGameCamera().ChangePivotRotationController( 'SignChannel' );
  4053. theGame.GetGameCamera().ChangePivotDistanceController( 'SignChannel' );
  4054. // HACK
  4055. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4056. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  4057.  
  4058. if ( slideTarget )
  4059. tempHeading = VecHeading( slideTarget.GetWorldPosition() - GetWorldPosition() );
  4060. else
  4061. tempHeading = GetHeading();
  4062.  
  4063. oTCameraPitchOffset = 0.f;
  4064.  
  4065. if( ( interiorCamera && !moveTarget )
  4066. || ( AngleDistance( tempHeading, moveData.pivotRotationValue.Yaw ) < 0 ) )
  4067. oTCameraOffset = cameraOffsetLeft;
  4068. else
  4069. oTCameraOffset = cameraOffsetRight;
  4070.  
  4071. if ( oTCameraOffset == cameraOffsetLeft )
  4072. {
  4073. if ( delayCameraOrientationChange || delayOrientationChange )
  4074. {
  4075. screenSpaceOffset = 0.75f;
  4076. moveData.pivotDistanceController.SetDesiredDistance( 1.6f, 3.f );
  4077. moveData.pivotPositionController.offsetZ = 1.4f;
  4078. moveData.pivotRotationController.SetDesiredPitch( -15.f );
  4079. }
  4080. else
  4081. {
  4082. screenSpaceOffset = 0.7f;
  4083. moveData.pivotDistanceController.SetDesiredDistance( 3.25f );
  4084. moveData.pivotPositionController.offsetZ = 1.2f;
  4085. moveData.pivotRotationController.SetDesiredPitch( -10.f );
  4086. }
  4087. }
  4088. else if ( oTCameraOffset == cameraOffsetRight )
  4089. {
  4090. if ( delayCameraOrientationChange || delayOrientationChange )
  4091. {
  4092. screenSpaceOffset = -0.85f;
  4093. moveData.pivotDistanceController.SetDesiredDistance( 1.6f, 3.f );
  4094. moveData.pivotPositionController.offsetZ = 1.4f;
  4095. moveData.pivotRotationController.SetDesiredPitch( -15.f );
  4096. }
  4097. else
  4098. {
  4099. screenSpaceOffset = -0.8f;
  4100. moveData.pivotDistanceController.SetDesiredDistance( 3.25f );
  4101. moveData.pivotPositionController.offsetZ = 1.2f;
  4102. moveData.pivotRotationController.SetDesiredPitch( -10.f );
  4103. }
  4104. }
  4105. else
  4106. {
  4107. moveData.pivotDistanceController.SetDesiredDistance( 1.25f, 3.f );
  4108. moveData.pivotPositionController.offsetZ = 1.3f;
  4109. moveData.pivotRotationController.SetDesiredPitch( -5.5f );
  4110. }
  4111.  
  4112. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( screenSpaceOffset, 0.f, 0.f ), 1.f, timeDelta );
  4113.  
  4114. if ( !delayCameraOrientationChange )
  4115. {
  4116. if ( moveTarget )
  4117. moveData.pivotRotationController.SetDesiredHeading( GetHeading() + oTCameraOffset, 0.5f );
  4118. else
  4119. moveData.pivotRotationController.SetDesiredHeading( GetHeading() + oTCameraOffset, 1.f );
  4120. }
  4121. else
  4122. moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw, 1.f );
  4123.  
  4124. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition() );
  4125.  
  4126. return true;
  4127. }
  4128.  
  4129.  
  4130. private var fovVel : float;
  4131. private var sprintOffset : Vector;
  4132. private var previousOffset : bool;
  4133. private var previousRotationVelocity : float;
  4134. private var pivotRotationTimeStamp : float;
  4135. protected function UpdateCameraSprint( out moveData : SCameraMovementData, timeDelta : float )
  4136. {
  4137. var angleDiff : float;
  4138. var camOffsetVector : Vector;
  4139. var smoothSpeed : float;
  4140. var camera : CCustomCamera;
  4141. var camAngularSpeed : float;
  4142.  
  4143. var playerToCamAngle : float;
  4144. var useExplorationSprintCam : bool;
  4145.  
  4146. camera = theGame.GetGameCamera();
  4147. if( camera )
  4148. {
  4149. if ( sprintingCamera )
  4150. {
  4151. //theGame.GetGameCamera().ForceManualControlHorTimeout();
  4152. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4153.  
  4154. if( thePlayer.GetAutoCameraCenter() )
  4155. {
  4156. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4157. }
  4158.  
  4159. playerToCamAngle = AbsF( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) );
  4160.  
  4161. /*if ( theGame.GetGameplayConfigFloatValue( 'debugE' ) > 0.1f )
  4162. useExplorationSprintCam = !IsInCombat() || ( moveTarget && VecDistance( moveTarget.GetWorldPosition(), GetWorldPosition() ) > findMoveTargetDistMax );
  4163. else*/
  4164. useExplorationSprintCam = false;// !IsInCombat() || ( moveTarget && VecDistance( moveTarget.GetWorldPosition(), GetWorldPosition() ) > findMoveTargetDistMax );
  4165.  
  4166. if ( useExplorationSprintCam )
  4167. {
  4168. if ( playerToCamAngle <= 45 )
  4169. {
  4170. theGame.GetGameCamera().ChangePivotRotationController( 'Sprint' );
  4171. // HACK
  4172. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4173.  
  4174. moveData.pivotRotationController.SetDesiredHeading( GetHeading(), 0.25f );
  4175. moveData.pivotRotationController.SetDesiredPitch( -3.5f, 0.5f );
  4176. thePlayer.EnableManualCameraControl( true, 'Sprint' );
  4177. }
  4178. else
  4179. {
  4180. thePlayer.EnableManualCameraControl( false, 'Sprint' );
  4181. }
  4182. }
  4183. else
  4184. {
  4185. if ( theGame.IsUberMovementEnabled() )
  4186. moveData.pivotRotationController.SetDesiredHeading( GetHeading(), 0.35f );
  4187.  
  4188. thePlayer.EnableManualCameraControl( true, 'Sprint' );
  4189. }
  4190.  
  4191. if ( bRAxisReleased )
  4192. {
  4193. if ( AbsF( rawLeftJoyRot ) > 25 )
  4194. angleDiff = AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw );
  4195.  
  4196. pivotRotationTimeStamp = theGame.GetEngineTimeAsSeconds();
  4197. previousRotationVelocity = 0.f;
  4198. }
  4199. else
  4200. {
  4201. if ( previousRotationVelocity <= 0 && AbsF( moveData.pivotRotationVelocity.Yaw ) > 250 )
  4202. {
  4203. pivotRotationTimeStamp = theGame.GetEngineTimeAsSeconds();
  4204. previousRotationVelocity = AbsF( moveData.pivotRotationVelocity.Yaw );
  4205. }
  4206. }
  4207.  
  4208. if ( pivotRotationTimeStamp + 0.4f <= theGame.GetEngineTimeAsSeconds() && AbsF( moveData.pivotRotationVelocity.Yaw ) > 250 )
  4209. angleDiff = VecHeading( rawRightJoyVec );
  4210.  
  4211. if ( useExplorationSprintCam )
  4212. {
  4213. if ( playerToCamAngle > 90 )
  4214. {
  4215. camOffsetVector.X = 0.f;
  4216. smoothSpeed = 1.f;
  4217. }
  4218. else if ( angleDiff > 15.f )
  4219. {
  4220. camOffsetVector.X = -0.8;
  4221. smoothSpeed = 1.f;
  4222. previousOffset = true;
  4223. }
  4224. else if ( angleDiff < -15.f )
  4225. {
  4226. camOffsetVector.X = 0.475f;
  4227. smoothSpeed = 1.5f;
  4228. previousOffset = false;
  4229. }
  4230. else
  4231. {
  4232. if ( previousOffset )
  4233. {
  4234. camOffsetVector.X = -0.8;
  4235. smoothSpeed = 1.5f;
  4236. }
  4237. else
  4238. {
  4239. camOffsetVector.X = 0.475f;
  4240. smoothSpeed = 1.5f;
  4241. }
  4242. }
  4243.  
  4244. camOffsetVector.Y = 1.4f;
  4245. camOffsetVector.Z = 0.275f;
  4246. }
  4247. else
  4248. {
  4249. /*camOffsetVector.X = 0.f;
  4250. camOffsetVector.Y = 0.4f;
  4251. camOffsetVector.Z = 0.2f;*/
  4252. smoothSpeed = 0.75f;
  4253.  
  4254. camOffsetVector.X = 0.f;
  4255. camOffsetVector.Y = 1.f;
  4256. camOffsetVector.Z = 0.2f;
  4257. moveData.pivotRotationController.SetDesiredPitch( -10.f, 0.5f );
  4258. }
  4259.  
  4260. DampVectorConst( sprintOffset, camOffsetVector, smoothSpeed, timeDelta );
  4261.  
  4262. moveData.cameraLocalSpaceOffset = sprintOffset;
  4263.  
  4264. DampFloatSpring( camera.fov, fovVel, 70.f, 1.0, timeDelta );
  4265. }
  4266. else
  4267. {
  4268. sprintOffset = moveData.cameraLocalSpaceOffset;
  4269. DampFloatSpring( camera.fov, fovVel, 60.f, 1.0, timeDelta );
  4270. previousOffset = false;
  4271. }
  4272. }
  4273. }
  4274.  
  4275. function EnableSprintingCamera( flag : bool )
  4276. {
  4277. if( !theGame.IsUberMovementEnabled() && !useSprintingCameraAnim )
  4278. {
  4279. return;
  4280. }
  4281.  
  4282. super.EnableSprintingCamera( flag );
  4283.  
  4284. if ( !flag )
  4285. {
  4286. thePlayer.EnableManualCameraControl( true, 'Sprint' );
  4287. }
  4288. }
  4289.  
  4290. protected function UpdateCameraCombatActionButNotInCombat( out moveData : SCameraMovementData, timeDelta : float )
  4291. {
  4292. var vel : Vector;
  4293. var heading : float;
  4294. var pitch : float;
  4295. var headingMult : float;
  4296. var pitchMult : float;
  4297. var camOffset : Vector;
  4298. var buff : CBaseGameplayEffect;
  4299. var runningAndAlertNear : bool;
  4300. var desiredDist : float;
  4301.  
  4302. if ( ( !IsCurrentSignChanneled() || GetCurrentlyCastSign() == ST_Quen || GetCurrentlyCastSign() == ST_Yrden ) && !specialAttackCamera && !IsInCombatActionFriendly() )
  4303. {
  4304. buff = GetCurrentlyAnimatedCS();
  4305. runningAndAlertNear = GetPlayerCombatStance() == PCS_AlertNear && playerMoveType == PMT_Run && !GetDisplayTarget();
  4306. if ( runningAndAlertNear ||
  4307. ( GetPlayerCombatStance() == PCS_AlertFar && !IsInCombatAction() && !buff ) )
  4308. {
  4309. camOffset.X = 0.f;
  4310. camOffset.Y = 0.f;
  4311. camOffset.Z = -0.1f;
  4312.  
  4313. if ( runningAndAlertNear )
  4314. {
  4315. moveData.pivotDistanceController.SetDesiredDistance( 4.f );
  4316. moveData.pivotPositionController.offsetZ = 1.5f;
  4317. }
  4318. }
  4319. else
  4320. {
  4321. camOffset.X = 0.f;
  4322. camOffset.Y = -1.5f;
  4323. camOffset.Z = -0.2f;
  4324. }
  4325.  
  4326. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( camOffset.X, camOffset.Y, camOffset.Z ), 0.4f, timeDelta );
  4327. sprintOffset = moveData.cameraLocalSpaceOffset;
  4328. heading = moveData.pivotRotationValue.Yaw;
  4329.  
  4330. if ( GetOrientationTarget() == OT_Camera || GetOrientationTarget() == OT_CameraOffset )
  4331. pitch = moveData.pivotRotationValue.Pitch;
  4332. else if ( lastAxisInputIsMovement
  4333. || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack
  4334. || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_SpecialAttack
  4335. || ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign && !IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Quen ) )
  4336. {
  4337. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4338. pitch = -20.f;
  4339. }
  4340. else
  4341. pitch = moveData.pivotRotationValue.Pitch;
  4342.  
  4343. headingMult = 1.f;
  4344. pitchMult = 1.f;
  4345.  
  4346. //if( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack )
  4347. if( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign
  4348. && ( GetEquippedSign() == ST_Aard || GetEquippedSign() == ST_Yrden )
  4349. && GetBehaviorVariable( 'alternateSignCast' ) == 1 )
  4350. {
  4351. //theGame.GetGameCamera().ForceManualControlHorTimeout();
  4352. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4353. pitch = -20.f;
  4354.  
  4355. //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( theGame.GetGameplayConfigFloatValue( 'debugA' ), theGame.GetGameplayConfigFloatValue( 'debugB' ), theGame.GetGameplayConfigFloatValue( 'debugC' ) ), 0.4f, timeDelta );
  4356. }
  4357.  
  4358. //vel = GetMovingAgentComponent().GetVelocity();
  4359. //if ( VecLength( vel ) > 0 && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge )
  4360. //{
  4361. /*theGame.GetGameCamera().ForceManualControlHorTimeout();
  4362. heading = GetHeading();
  4363. headingMult = 0.5f;*/
  4364. //}
  4365.  
  4366. if ( IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Quen )
  4367. {
  4368. pitch = moveData.pivotRotationValue.Pitch;
  4369. }
  4370.  
  4371. moveData.pivotRotationController.SetDesiredHeading( heading, );
  4372. moveData.pivotRotationController.SetDesiredPitch( pitch );
  4373. }
  4374. }
  4375.  
  4376. /*public function UpdateCameraForSpecialAttack( out moveData : SCameraMovementData, timeDelta : float ) : bool
  4377. {
  4378. return false;
  4379. }*/
  4380. //------------------------------------------------------------------------------------------------------------------
  4381. event OnGameCameraExplorationRotCtrlChange()
  4382. {
  4383. if( substateManager )
  4384. {
  4385. return substateManager.OnGameCameraExplorationRotCtrlChange( );
  4386. }
  4387.  
  4388. return false;
  4389. }
  4390.  
  4391. ///////////////////////////////////////////////////////////////////////////
  4392. // COMBAT MOVEMENT ORIENTATION
  4393. ///////////////////////////////////////////////////////////////////////////
  4394.  
  4395. //Rotation
  4396.  
  4397.  
  4398.  
  4399.  
  4400.  
  4401. function SetCustomRotation( customRotationName : name, rotHeading : float, rotSpeed : float, activeTime : float, rotateExistingDeltaLocation : bool )
  4402. {
  4403. var movementAdjustor : CMovementAdjustor;
  4404. var ticket : SMovementAdjustmentRequestTicket;
  4405.  
  4406. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4407. ticket = movementAdjustor.GetRequest( customRotationName );
  4408. movementAdjustor.Cancel( ticket );
  4409. ticket = movementAdjustor.CreateNewRequest( customRotationName );
  4410. movementAdjustor.Continuous( ticket );
  4411. movementAdjustor.ReplaceRotation( ticket );
  4412. movementAdjustor.RotateTo( ticket, rotHeading );
  4413. movementAdjustor.MaxRotationAdjustmentSpeed( ticket, rotSpeed );
  4414. if (rotSpeed == 0.0f)
  4415. {
  4416. movementAdjustor.AdjustmentDuration( ticket, activeTime );
  4417. }
  4418. movementAdjustor.KeepActiveFor( ticket, activeTime );
  4419. movementAdjustor.RotateExistingDeltaLocation( ticket, rotateExistingDeltaLocation );
  4420. }
  4421.  
  4422. function UpdateCustomRotationHeading( customRotationName : name, rotHeading : float )
  4423. {
  4424. var movementAdjustor : CMovementAdjustor;
  4425. var ticket : SMovementAdjustmentRequestTicket;
  4426.  
  4427. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4428. ticket = movementAdjustor.GetRequest( customRotationName );
  4429. movementAdjustor.RotateTo( ticket, rotHeading );
  4430. }
  4431.  
  4432. function SetCustomRotationTowards( customRotationName : name, target : CActor, rotSpeed : float, optional activeTime : float )
  4433. {
  4434. var movementAdjustor : CMovementAdjustor;
  4435. var ticket : SMovementAdjustmentRequestTicket;
  4436.  
  4437. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4438. ticket = movementAdjustor.GetRequest( customRotationName );
  4439. movementAdjustor.Cancel( ticket );
  4440. ticket = movementAdjustor.CreateNewRequest( customRotationName );
  4441. movementAdjustor.Continuous( ticket );
  4442. movementAdjustor.ReplaceRotation( ticket );
  4443. movementAdjustor.RotateTowards( ticket, target );
  4444. movementAdjustor.MaxRotationAdjustmentSpeed( ticket, rotSpeed );
  4445. if (activeTime > 0.0f)
  4446. {
  4447. movementAdjustor.KeepActiveFor( ticket, activeTime );
  4448. }
  4449. else
  4450. {
  4451. movementAdjustor.DontEnd( ticket );
  4452. }
  4453. }
  4454.  
  4455. //lock movement in dir
  4456. function CustomLockMovement( customMovementName : name, heading : float )
  4457. {
  4458. var movementAdjustor : CMovementAdjustor;
  4459. var ticket : SMovementAdjustmentRequestTicket;
  4460.  
  4461. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4462. ticket = movementAdjustor.GetRequest( customMovementName );
  4463. movementAdjustor.Cancel( ticket );
  4464. ticket = movementAdjustor.CreateNewRequest( customMovementName );
  4465. movementAdjustor.Continuous( ticket );
  4466. movementAdjustor.DontEnd( ticket );
  4467. movementAdjustor.LockMovementInDirection( ticket, heading );
  4468. }
  4469.  
  4470. function BindMovementAdjustmentToEvent( customRotationName : name, eventName : CName )
  4471. {
  4472. var movementAdjustor : CMovementAdjustor;
  4473. var ticket : SMovementAdjustmentRequestTicket;
  4474.  
  4475. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4476. ticket = movementAdjustor.GetRequest( customRotationName );
  4477. movementAdjustor.BindToEvent( ticket, eventName );
  4478. }
  4479.  
  4480. function UpdateCustomLockMovementHeading( customMovementName : name, heading : float )
  4481. {
  4482. var movementAdjustor : CMovementAdjustor;
  4483. var ticket : SMovementAdjustmentRequestTicket;
  4484.  
  4485. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4486. ticket = movementAdjustor.GetRequest( customMovementName );
  4487. movementAdjustor.LockMovementInDirection( ticket, heading );
  4488. }
  4489.  
  4490. function CustomLockDistance( customMovementName : name, maintainDistanceTo : CNode, minDist, maxDist : float )
  4491. {
  4492. var movementAdjustor : CMovementAdjustor;
  4493. var ticket : SMovementAdjustmentRequestTicket;
  4494.  
  4495. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4496. ticket = movementAdjustor.GetRequest( customMovementName );
  4497. movementAdjustor.Cancel( ticket );
  4498. ticket = movementAdjustor.CreateNewRequest( customMovementName );
  4499. movementAdjustor.Continuous( ticket );
  4500. movementAdjustor.SlideTowards( ticket, maintainDistanceTo, minDist, maxDist );
  4501. }
  4502.  
  4503. function UpdateCustomLockDistance( customMovementName : name, maintainDistanceTo : CNode, minDist, maxDist : float )
  4504. {
  4505. var movementAdjustor : CMovementAdjustor;
  4506. var ticket : SMovementAdjustmentRequestTicket;
  4507.  
  4508. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4509. ticket = movementAdjustor.GetRequest( customMovementName );
  4510. movementAdjustor.SlideTowards( ticket, maintainDistanceTo, minDist, maxDist );
  4511. }
  4512.  
  4513. private var disableManualCameraControlStack : array<name>;
  4514. public function EnableManualCameraControl( enable : bool, sourceName : name )
  4515. {
  4516. if ( !enable )
  4517. {
  4518. if ( !disableManualCameraControlStack.Contains( sourceName ) )
  4519. {
  4520. disableManualCameraControlStack.PushBack( sourceName );
  4521. }
  4522. }
  4523. else
  4524. {
  4525. disableManualCameraControlStack.Remove( sourceName );
  4526. }
  4527.  
  4528. if ( disableManualCameraControlStack.Size() > 0 )
  4529. theGame.GetGameCamera().EnableManualControl( false );
  4530. else
  4531. theGame.GetGameCamera().EnableManualControl( true );
  4532. }
  4533.  
  4534. public function IsCameraControlDisabled( optional disabledBySourceName : name ) : bool
  4535. {
  4536. if ( disabledBySourceName )
  4537. return disableManualCameraControlStack.Contains( disabledBySourceName );
  4538. else
  4539. return disableManualCameraControlStack.Size() > 0;
  4540. }
  4541.  
  4542. public function DisableManualCameraControlStackHasSource( sourceName : name ) : bool
  4543. {
  4544. return disableManualCameraControlStack.Contains( sourceName );
  4545. }
  4546.  
  4547. public function ClearDisableManualCameraControlStack()
  4548. {
  4549. disableManualCameraControlStack.Clear();
  4550. theGame.GetGameCamera().EnableManualControl( true );
  4551. }
  4552.  
  4553. function SetOrientationTarget( target : EOrientationTarget )
  4554. {
  4555. if ( IsPCModeEnabled() && target == OT_Player )
  4556. {
  4557. target = OT_Camera;
  4558. }
  4559.  
  4560. orientationTarget = target;
  4561. }
  4562.  
  4563. function GetOrientationTarget() : EOrientationTarget
  4564. {
  4565. return orientationTarget;
  4566. }
  4567.  
  4568. var customOrientationInfoStack : array<SCustomOrientationInfo>;
  4569. public function AddCustomOrientationTarget( orientationTarget : EOrientationTarget, sourceName : name )
  4570. {
  4571. var customOrientationInfo : SCustomOrientationInfo;
  4572. var i : int;
  4573.  
  4574. if ( customOrientationInfoStack.Size() > 0 )
  4575. {
  4576. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4577. {
  4578. if ( customOrientationInfoStack[i].sourceName == sourceName )
  4579. customOrientationInfoStack.Erase(i);
  4580. }
  4581. }
  4582.  
  4583. customOrientationInfo.sourceName = sourceName;
  4584. customOrientationInfo.orientationTarget = orientationTarget;
  4585. customOrientationInfoStack.PushBack( customOrientationInfo );
  4586. SetOrientationTarget( orientationTarget );
  4587. }
  4588.  
  4589. public function RemoveCustomOrientationTarget( sourceName : name )
  4590. {
  4591. var customOrientationInfo : SCustomOrientationInfo;
  4592. var i : int;
  4593.  
  4594. if ( customOrientationInfoStack.Size() > 0 )
  4595. {
  4596. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4597. {
  4598. if ( customOrientationInfoStack[i].sourceName == sourceName )
  4599. customOrientationInfoStack.Erase(i);
  4600. }
  4601. }
  4602. else
  4603. LogChannel( 'CustomOrienatation', "ERROR: Custom orientation cannot be removed, stack is already empty!!!" );
  4604. }
  4605.  
  4606. protected function ClearCustomOrientationInfoStack()
  4607. {
  4608. customOrientationInfoStack.Clear();
  4609. }
  4610.  
  4611. protected function GetCustomOrientationTarget( out infoStack : SCustomOrientationInfo ) : bool
  4612. {
  4613. var size : int;
  4614.  
  4615. size = customOrientationInfoStack.Size();
  4616.  
  4617. if ( size <= 0 )
  4618. return false;
  4619. else
  4620. {
  4621. infoStack = customOrientationInfoStack[ size - 1 ];
  4622. return true;
  4623. }
  4624. }
  4625.  
  4626. public function SetOrientationTargetCustomHeading( heading : float, sourceName : name ) : bool
  4627. {
  4628. var i : int;
  4629. if ( customOrientationInfoStack.Size() > 0 )
  4630. {
  4631. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4632. {
  4633. if ( customOrientationInfoStack[i].sourceName == sourceName )
  4634. {
  4635. customOrientationInfoStack[i].customHeading = heading;
  4636. return true;
  4637. }
  4638. }
  4639. }
  4640.  
  4641. LogChannel( 'SetOrientationTargetCustomHeading', "ERROR: Cannot set customHeading because stack is empty or sourceName is not found!!!" );
  4642. return false;
  4643. }
  4644.  
  4645. // returns the topmost OT_CustomHeading in stack
  4646. public function GetOrientationTargetCustomHeading() : float
  4647. {
  4648. var i : int;
  4649. if ( customOrientationInfoStack.Size() > 0 )
  4650. {
  4651. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4652. {
  4653. if ( customOrientationInfoStack[i].orientationTarget == OT_CustomHeading )
  4654. {
  4655. return customOrientationInfoStack[i].customHeading;
  4656. }
  4657. }
  4658. }
  4659.  
  4660. LogChannel( 'SetOrientationTargetCustomHeading', "ERROR: Cannot get customHeading because stack is empty or no OT_CustomHeading in stack!!!" );
  4661. return -1.f;
  4662. }
  4663.  
  4664. public function GetCombatActionOrientationTarget( combatActionType : ECombatActionType ) : EOrientationTarget
  4665. {
  4666. var newCustomOrientationTarget : EOrientationTarget;
  4667. var targetEnt : CGameplayEntity;
  4668. var targetActor : CActor;
  4669.  
  4670. if ( GetCurrentStateName() == 'AimThrow' )
  4671. newCustomOrientationTarget = OT_CameraOffset;
  4672. else
  4673. {
  4674. targetEnt = GetDisplayTarget();
  4675. targetActor = (CActor)targetEnt;
  4676.  
  4677. if ( targetEnt )
  4678. {
  4679. if ( targetActor )
  4680. {
  4681. if ( moveTarget )
  4682. newCustomOrientationTarget = OT_Actor;
  4683. else
  4684. {
  4685. if ( this.IsSwimming() )
  4686. newCustomOrientationTarget = OT_Camera;
  4687. else if ( lastAxisInputIsMovement )
  4688. newCustomOrientationTarget = OT_Player;
  4689. else
  4690. newCustomOrientationTarget = OT_Actor;
  4691. }
  4692. }
  4693. else
  4694. {
  4695. if ( combatActionType == CAT_Crossbow && targetEnt.HasTag( 'softLock_Bolt' ) )
  4696. newCustomOrientationTarget = OT_Actor;
  4697. else
  4698. {
  4699. if ( this.IsSwimming() )
  4700. newCustomOrientationTarget = OT_Camera;
  4701. else if ( lastAxisInputIsMovement )
  4702. newCustomOrientationTarget = OT_Player;
  4703. else
  4704. newCustomOrientationTarget = OT_Camera;
  4705.  
  4706. }
  4707. }
  4708. }
  4709. else
  4710. {
  4711. if ( IsUsingVehicle() )// || this.IsSwimming() )
  4712. newCustomOrientationTarget = OT_Camera;
  4713. else if ( lastAxisInputIsMovement )
  4714. {
  4715. if ( this.IsSwimming() )
  4716. {
  4717. //if ( !bRAxisReleased
  4718. // || ( GetOrientationTarget() == OT_Camera && ( this.rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' || this.rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' ) ) )
  4719. newCustomOrientationTarget = OT_Camera;
  4720. //else
  4721. // newCustomOrientationTarget = OT_CustomHeading;
  4722. }
  4723. else
  4724. newCustomOrientationTarget = OT_Player;
  4725.  
  4726. }
  4727. else
  4728. newCustomOrientationTarget = OT_Camera;
  4729. }
  4730. }
  4731.  
  4732. return newCustomOrientationTarget;
  4733. }
  4734.  
  4735. public function GetOrientationTargetHeading( orientationTarget : EOrientationTarget ) : float
  4736. {
  4737. var heading : float;
  4738.  
  4739. if( orientationTarget == OT_Camera )
  4740. heading = VecHeading( theCamera.GetCameraDirection() );
  4741. else if( orientationTarget == OT_CameraOffset )
  4742. heading = VecHeading( theCamera.GetCameraDirection() ) - oTCameraOffset;
  4743. else if( orientationTarget == OT_CustomHeading )
  4744. heading = GetOrientationTargetCustomHeading();
  4745. else if ( GetDisplayTarget() && orientationTarget == OT_Actor )
  4746. {
  4747. if ( (CActor)( GetDisplayTarget() ) )
  4748. {
  4749. //if ( GetPlayerCombatStance() == PCS_AlertNear )
  4750. heading = VecHeading( GetDisplayTarget().GetWorldPosition() - GetWorldPosition() );
  4751. //else
  4752. // heading = GetHeading();
  4753. }
  4754. else
  4755. {
  4756. if ( GetDisplayTarget().HasTag( 'softLock_Bolt' ) )
  4757. heading = VecHeading( GetDisplayTarget().GetWorldPosition() - GetWorldPosition() );
  4758. else
  4759. heading = GetHeading();
  4760. }
  4761. }
  4762. else
  4763. heading = GetHeading();
  4764.  
  4765. return heading;
  4766. }
  4767.  
  4768. event OnDelayOrientationChange()
  4769. {
  4770. var delayOrientation : bool;
  4771. var delayCameraRotation : bool;
  4772. var moveData : SCameraMovementData;
  4773. var time : float;
  4774.  
  4775. time = 0.01f;
  4776.  
  4777. if ( theInput.GetActionValue( 'CastSignHold' ) == 1.f )
  4778. {
  4779. actionType = 0;
  4780. if ( moveTarget )
  4781. delayOrientation = true;
  4782. else
  4783. {
  4784. if ( !GetBIsCombatActionAllowed() )
  4785. delayOrientation = true;
  4786. }
  4787.  
  4788.  
  4789. }
  4790. else if ( theInput.GetActionValue( 'ThrowItemHold' ) == 1.f )
  4791. {
  4792. actionType = 3;
  4793. delayOrientation = true;
  4794. }
  4795. else if ( theInput.GetActionValue( 'SpecialAttackHeavy' ) == 1.f )
  4796. {
  4797. actionType = 2;
  4798. if ( !slideTarget )
  4799. delayOrientation = true;
  4800. else
  4801. delayOrientation = true;
  4802. }
  4803. else if ( IsGuarded() && !moveTarget )
  4804. {
  4805. actionType = 1;
  4806. delayOrientation = true;
  4807. }
  4808.  
  4809. if ( delayOrientation )
  4810. {
  4811. delayOrientationChange = true;
  4812. theGame.GetGameCamera().ForceManualControlHorTimeout();
  4813. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4814. AddTimer( 'DelayOrientationChangeTimer', time, true );
  4815. }
  4816.  
  4817. if ( delayCameraRotation )
  4818. {
  4819. delayCameraOrientationChange = true;
  4820. theGame.GetGameCamera().ForceManualControlHorTimeout();
  4821. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4822. AddTimer( 'DelayOrientationChangeTimer', time, true );
  4823. }
  4824. }
  4825.  
  4826. //This is also called from behgraph (e.g. SpecialHeavyAttack)
  4827. event OnDelayOrientationChangeOff()
  4828. {
  4829. delayOrientationChange = false;
  4830. delayCameraOrientationChange = false;
  4831. RemoveTimer( 'DelayOrientationChangeTimer' );
  4832.  
  4833. //if ( !IsCameraLockedToTarget() )
  4834. // theGame.GetGameCamera().EnableManualControl( true );
  4835. }
  4836.  
  4837. timer function DelayOrientationChangeTimer( time : float , id : int)
  4838. {
  4839. if ( ( actionType == 0 && theInput.GetActionValue( 'CastSignHold' ) == 0.f )
  4840. || ( actionType == 2 && theInput.GetActionValue( 'SpecialAttackHeavy' ) == 0.f )
  4841. || ( actionType == 3 && theInput.GetActionValue( 'ThrowItemHold' ) == 0.f )
  4842. || ( actionType == 1 && !IsGuarded() )
  4843. || ( VecLength( rawRightJoyVec ) > 0.f ) )//&& !( slideTarget && IsInCombatAction() && GetBehaviorVariable( 'combatActionType') == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Axii ) ) )
  4844. {
  4845. OnDelayOrientationChangeOff();
  4846. }
  4847. }
  4848.  
  4849. public function SetCombatActionHeading( heading : float )
  4850. {
  4851. combatActionHeading = heading;
  4852. }
  4853.  
  4854. public function GetCombatActionHeading() : float
  4855. {
  4856. return combatActionHeading;
  4857. }
  4858.  
  4859. protected function EnableCloseCombatCharacterRadius( flag : bool )
  4860. {
  4861. var actor : CActor;
  4862.  
  4863. actor = (CActor)slideTarget;
  4864. if ( flag )
  4865. {
  4866. this.GetMovingAgentComponent().SetVirtualRadius( 'CloseCombatCharacterRadius' );
  4867. if(actor)
  4868. actor.GetMovingAgentComponent().SetVirtualRadius( 'CloseCombatCharacterRadius' );
  4869. }
  4870. else
  4871. {
  4872. if ( this.IsInCombat() )
  4873. {
  4874. GetMovingAgentComponent().SetVirtualRadius( 'CombatCharacterRadius' );
  4875. if(actor)
  4876. actor.GetMovingAgentComponent().SetVirtualRadius( 'CombatCharacterRadius' );
  4877. }
  4878. else
  4879. {
  4880. this.GetMovingAgentComponent().ResetVirtualRadius();
  4881. if(actor)
  4882. actor.GetMovingAgentComponent().ResetVirtualRadius();
  4883. }
  4884. }
  4885. }
  4886.  
  4887. ///////////////////////////////////////////////////////////////////////////
  4888. // Soft Lock Logic
  4889.  
  4890.  
  4891.  
  4892. private var isSnappedToNavMesh : bool;
  4893. private var snapToNavMeshCachedFlag : bool;
  4894. public function SnapToNavMesh( flag : bool )
  4895. {
  4896. var comp : CMovingAgentComponent;
  4897.  
  4898. comp = (CMovingAgentComponent)this.GetMovingAgentComponent();
  4899.  
  4900. if ( comp )
  4901. {
  4902. comp.SnapToNavigableSpace( flag );
  4903. isSnappedToNavMesh = flag;
  4904. }
  4905. else
  4906. {
  4907. snapToNavMeshCachedFlag = flag;
  4908. AddTimer( 'DelayedSnapToNavMesh', 0.2f );
  4909. }
  4910. }
  4911.  
  4912. public final function PlayRuneword4FX(optional weaponType : EPlayerWeapon)
  4913. {
  4914. var hasSwordDrawn : bool;
  4915. var sword : SItemUniqueId;
  4916.  
  4917. //we show fx only if overheal is greater than 1% - otherwise if we have a DoT and regen at the same time the health
  4918. //jumps back and forth between 100% and 99.99% stating and stopping the fx over and over
  4919. //needs to have sword drawn
  4920. if(abilityManager.GetOverhealBonus() > (0.005 * GetStatMax(BCS_Vitality)))
  4921. {
  4922. hasSwordDrawn = HasAbility('Runeword 4 _Stats', true);
  4923.  
  4924. if(!hasSwordDrawn && GetWitcherPlayer())
  4925. {
  4926. if(weaponType == PW_Steel)
  4927. {
  4928. if(GetWitcherPlayer().GetItemEquippedOnSlot(EES_SteelSword, sword))
  4929. hasSwordDrawn = inv.ItemHasAbility(sword, 'Runeword 4 _Stats');
  4930. }
  4931. else if(weaponType == PW_Silver)
  4932. {
  4933. if(GetWitcherPlayer().GetItemEquippedOnSlot(EES_SilverSword, sword))
  4934. hasSwordDrawn = inv.ItemHasAbility(sword, 'Runeword 4 _Stats');
  4935. }
  4936. }
  4937.  
  4938. if(hasSwordDrawn)
  4939. {
  4940. if(!IsEffectActive('runeword_4', true))
  4941. PlayEffect('runeword_4');
  4942. }
  4943. }
  4944. }
  4945.  
  4946. timer function DelayedSnapToNavMesh( dt : float, id : int)
  4947. {
  4948. SnapToNavMesh( snapToNavMeshCachedFlag );
  4949. }
  4950.  
  4951. saved var navMeshSnapInfoStack : array<name>;
  4952. public function EnableSnapToNavMesh( source : name, enable : bool )
  4953. {
  4954. if ( enable )
  4955. {
  4956. if ( !navMeshSnapInfoStack.Contains( source ) )
  4957. navMeshSnapInfoStack.PushBack( source );
  4958. }
  4959. else
  4960. {
  4961. if ( navMeshSnapInfoStack.Contains( source ) )
  4962. navMeshSnapInfoStack.Remove( source );
  4963. }
  4964.  
  4965. if ( navMeshSnapInfoStack.Size() > 0 )
  4966. SnapToNavMesh( true );
  4967. else
  4968. SnapToNavMesh( false );
  4969. }
  4970.  
  4971. public function ForceRemoveAllNavMeshSnaps()
  4972. {
  4973. navMeshSnapInfoStack.Clear();
  4974. SnapToNavMesh( false );
  4975. }
  4976.  
  4977. public function CanSprint( speed : float ) : bool
  4978. {
  4979. if( speed <= 0.8f )
  4980. {
  4981. return false;
  4982. }
  4983.  
  4984. if ( thePlayer.GetIsSprintToggled() )
  4985. {
  4986. }
  4987. else if ( !sprintActionPressed )
  4988. {
  4989. return false;
  4990. }
  4991. else if( !theInput.IsActionPressed('Sprint') || ( theInput.LastUsedGamepad() && IsInsideInteraction() && GetHowLongSprintButtonWasPressed() < 0.12 ) )
  4992. {
  4993. return false;
  4994. }
  4995.  
  4996. if ( thePlayer.HasBuff( EET_OverEncumbered ) )
  4997. {
  4998. return false;
  4999. }
  5000. if ( !IsSwimming() )
  5001. {
  5002. if ( ShouldUseStaminaWhileSprinting() && !GetIsSprinting() && !IsInCombat() && GetStatPercents(BCS_Stamina) <= 0.9 )
  5003. {
  5004. return false;
  5005. }
  5006. if( ( !IsCombatMusicEnabled() || IsInFistFightMiniGame() ) && ( !IsActionAllowed(EIAB_RunAndSprint) || !IsActionAllowed(EIAB_Sprint) ) )
  5007. {
  5008. return false;
  5009. }
  5010. if( IsTerrainTooSteepToRunUp() )
  5011. {
  5012. return false;
  5013. }
  5014. if( IsInCombatAction() )
  5015. {
  5016. return false;
  5017. }
  5018. if( IsInAir() )
  5019. {
  5020. return false;
  5021. }
  5022. }
  5023. if( theGame.IsFocusModeActive() )
  5024. {
  5025. return false;
  5026. }
  5027.  
  5028. return true;
  5029. }
  5030.  
  5031.  
  5032. public function SetTerrainPitch( pitch : float )
  5033. {
  5034. terrainPitch = pitch;
  5035. }
  5036.  
  5037. public function IsTerrainTooSteepToRunUp() : bool
  5038. {
  5039. return terrainPitch <= disableSprintTerrainPitch;
  5040. }
  5041.  
  5042. public function SetTempLookAtTarget( actor : CGameplayEntity )
  5043. {
  5044. tempLookAtTarget = actor;
  5045. }
  5046.  
  5047. private var beingWarnedBy : array<CActor>;
  5048.  
  5049. event OnBeingWarnedStart( sender : CActor )
  5050. {
  5051. if ( !beingWarnedBy.Contains(sender) )
  5052. beingWarnedBy.PushBack(sender);
  5053. }
  5054. event OnBeingWarnedStop( sender : CActor )
  5055. {
  5056. beingWarnedBy.Remove(sender);
  5057. }
  5058.  
  5059. event OnCanFindPath( sender : CActor )
  5060. {
  5061. AddCanFindPathEnemyToList(sender,true);
  5062. }
  5063. event OnCannotFindPath( sender : CActor )
  5064. {
  5065. AddCanFindPathEnemyToList(sender,false);
  5066. }
  5067. event OnBecomeAwareAndCanAttack( sender : CActor )
  5068. {
  5069. AddEnemyToHostileEnemiesList( sender, true );
  5070. OnApproachAttack( sender );
  5071. }
  5072. event OnBecomeUnawareOrCannotAttack( sender : CActor )
  5073. {
  5074. AddEnemyToHostileEnemiesList( sender, false );
  5075. OnApproachAttackEnd( sender );
  5076. OnCannotFindPath(sender);
  5077. }
  5078. event OnApproachAttack( sender : CActor )
  5079. {
  5080. AddEnemyToHostileEnemiesList( sender, true );
  5081. super.OnApproachAttack( sender );
  5082. }
  5083. event OnApproachAttackEnd( sender : CActor )
  5084. {
  5085. AddEnemyToHostileEnemiesList( sender, false );
  5086. super.OnApproachAttackEnd( sender );
  5087. }
  5088. event OnAttack( sender : CActor )
  5089. {
  5090. super.OnAttack( sender );
  5091. }
  5092. event OnAttackEnd( sender : CActor )
  5093. {
  5094. super.OnAttackEnd( sender );
  5095. }
  5096.  
  5097. event OnHitCeiling()
  5098. {
  5099. substateManager.ReactOnHitCeiling();
  5100. }
  5101.  
  5102. protected var hostileEnemies : array<CActor>; //all enemies that are actively engaged in combat with the player (may or may not be visible by Geralt)
  5103. private var hostileMonsters : array<CActor>; // subgroup from hostileEnemies containing only monsters for sound system
  5104. function AddEnemyToHostileEnemiesList( actor : CActor, add : bool )
  5105. {
  5106. if ( add )
  5107. {
  5108. RemoveTimer( 'RemoveEnemyFromHostileEnemiesListTimer' );
  5109. if ( !hostileEnemies.Contains( actor ) )
  5110. {
  5111. hostileEnemies.PushBack( actor );
  5112.  
  5113. if( !actor.IsHuman() )
  5114. hostileMonsters.PushBack( actor );
  5115. }
  5116. }
  5117. else
  5118. {
  5119. if ( hostileEnemies.Size() == 1 )
  5120. {
  5121. if ( !actor.IsAlive() || actor.IsKnockedUnconscious() )
  5122. {
  5123. hostileEnemies.Remove( actor );
  5124. if( !actor.IsHuman() )
  5125. hostileMonsters.Remove( actor );
  5126. }
  5127. else
  5128. {
  5129. // If we already waiting to remove an entity
  5130. if( hostileEnemyToRemove )
  5131. {
  5132. hostileEnemies.Remove( hostileEnemyToRemove );
  5133. if( !hostileEnemyToRemove.IsHuman() )
  5134. hostileMonsters.Remove( hostileEnemyToRemove );
  5135. }
  5136. hostileEnemyToRemove = actor;
  5137. AddTimer( 'RemoveEnemyFromHostileEnemiesListTimer', 3.f );
  5138. }
  5139. }
  5140. else
  5141. {
  5142. hostileEnemies.Remove( actor );
  5143. if( !actor.IsHuman() )
  5144. hostileMonsters.Remove( actor );
  5145. }
  5146. }
  5147. }
  5148.  
  5149.  
  5150.  
  5151. public function ShouldEnableCombatMusic() : bool
  5152. {
  5153. var moveTargetNPC : CNewNPC;
  5154.  
  5155. if ( thePlayer.GetPlayerMode().GetForceCombatMode() )
  5156. return true;
  5157. else if ( !IsCombatMusicEnabled() )
  5158. {
  5159. if ( IsInCombat() )
  5160. return true;
  5161. else if ( IsThreatened() )
  5162. {
  5163. moveTargetNPC = (CNewNPC)moveTarget;
  5164. if ( moveTargetNPC.IsRanged() && hostileEnemies.Contains( moveTargetNPC ) )
  5165. return true;
  5166. else
  5167. return false;
  5168. }
  5169. else
  5170. return false;
  5171. }
  5172. else if ( ( thePlayer.IsThreatened() && ( hostileEnemies.Size() > 0 || thePlayer.GetPlayerCombatStance() == PCS_AlertNear ) )
  5173. || IsInCombat()
  5174. || finishableEnemiesList.Size() > 0
  5175. || isInFinisher )
  5176. return true;
  5177. else
  5178. return false;
  5179.  
  5180. }
  5181.  
  5182. public var canFindPathEnemiesList : array<CActor>;
  5183. public var disablecanFindPathEnemiesListUpdate : bool;
  5184. private var lastCanFindPathEnemy : CActor;
  5185. private var cachedMoveTarget : CActor;
  5186. private var reachabilityTestId : int;
  5187. private var reachabilityTestId2 : int;
  5188. function AddCanFindPathEnemyToList( actor : CActor, add : bool )
  5189. {
  5190. if ( disablecanFindPathEnemiesListUpdate )
  5191. return;
  5192.  
  5193. if ( add && !canFindPathEnemiesList.Contains( actor ) )
  5194. {
  5195. canFindPathEnemiesList.PushBack(actor);
  5196. }
  5197. else if ( !add )
  5198. {
  5199. canFindPathEnemiesList.Remove(actor);
  5200.  
  5201. if ( canFindPathEnemiesList.Size() <= 0 )
  5202. playerMode.UpdateCombatMode();
  5203. }
  5204. }
  5205.  
  5206. public function ClearCanFindPathEnemiesList( dt : float, id : int )
  5207. {
  5208. canFindPathEnemiesList.Clear();
  5209. }
  5210.  
  5211. public var finishableEnemiesList : array<CActor>;
  5212. function AddToFinishableEnemyList( actor : CActor, add : bool )
  5213. {
  5214. if ( add && !finishableEnemiesList.Contains( actor ) )
  5215. {
  5216. finishableEnemiesList.PushBack(actor);
  5217. }
  5218. else if ( !add )
  5219. {
  5220. finishableEnemiesList.Remove(actor);
  5221. }
  5222. }
  5223.  
  5224. private function UpdateFinishableEnemyList()
  5225. {
  5226. var i : int;
  5227. i = 0;
  5228. while ( i < finishableEnemiesList.Size() )
  5229. {
  5230. if ( !finishableEnemiesList[ i ] )
  5231. {
  5232. finishableEnemiesList.EraseFast( i );
  5233. }
  5234. else
  5235. {
  5236. i += 1;
  5237. }
  5238. }
  5239. }
  5240.  
  5241. private timer function ClearFinishableEnemyList( dt : float, id : int )
  5242. {
  5243. finishableEnemiesList.Clear();
  5244. }
  5245.  
  5246. private var hostileEnemyToRemove : CActor;
  5247. private timer function RemoveEnemyFromHostileEnemiesListTimer( time : float , id : int)
  5248. {
  5249. hostileEnemies.Remove( hostileEnemyToRemove );
  5250.  
  5251. if( hostileEnemyToRemove.IsMonster() )
  5252. hostileMonsters.Remove( hostileEnemyToRemove );
  5253.  
  5254. hostileEnemyToRemove = NULL;
  5255. }
  5256.  
  5257. private function ClearHostileEnemiesList()
  5258. {
  5259. hostileEnemies.Clear();
  5260. hostileMonsters.Clear();
  5261. canFindPathEnemiesList.Clear();
  5262. }
  5263.  
  5264. private var moveTargets : array<CActor>; //all hostileEnemies that Geralt is aware of.
  5265. public function GetMoveTargets() : array<CActor> { return moveTargets; }
  5266. public function GetNumberOfMoveTargets() : int { return moveTargets.Size(); }
  5267. public function GetHostileEnemies() : array<CActor> { return hostileEnemies; }
  5268. public function GetHostileEnemiesCount() : int { return hostileEnemies.Size(); }
  5269.  
  5270. protected var enableStrafe : bool;
  5271.  
  5272.  
  5273. public function FindMoveTarget()
  5274. {
  5275. var moveTargetDists : array<float>;
  5276. var moveTargetCanPathFinds : array<bool>;
  5277. var aPotentialMoveTargetCanFindPath : bool;
  5278.  
  5279. var newMoveTarget : CActor;
  5280. var actors : array<CActor>;
  5281. var currentHeading : float;
  5282. var size, i : int;
  5283. var playerToNewMoveTargetDist : float;
  5284. var playerToMoveTargetDist : float;
  5285. var confirmEmptyMoveTarget : bool;
  5286. var newEmptyMoveTargetTimer : float;
  5287. var wasVisibleInFullFrame : bool;
  5288. var setIsThreatened : bool;
  5289.  
  5290. var enemysTarget : CActor;
  5291. var isEnemyInCombat : bool;
  5292. var potentialMoveTargets : array<CActor>;
  5293. var onlyThreatTargets : bool;
  5294.  
  5295. thePlayer.SetupEnemiesCollection( enemyCollectionDist, enemyCollectionDist, 10, 'None', FLAG_Attitude_Neutral + FLAG_Attitude_Hostile + FLAG_Attitude_Friendly + FLAG_OnlyAliveActors );
  5296.  
  5297. //if ( moveTarget )
  5298. // cachedMoveTarget = moveTarget;
  5299.  
  5300. if ( GetCurrentStateName() != 'PlayerDialogScene' && IsAlive() )//&& !IsInCombatAction() )//GetBIsCombatActionAllowed() )
  5301.  
  5302.  
  5303.  
  5304. if ( GetCurrentStateName() != 'PlayerDialogScene' && IsAlive() )
  5305. {
  5306. GetVisibleEnemies( actors );
  5307.  
  5308. //Include enemies that geralt cannot see, but is hostile to him
  5309. if ( hostileEnemies.Size() > 0 )
  5310. {
  5311. for( i=0; i < hostileEnemies.Size() ; i+=1 )
  5312. {
  5313. if ( !actors.Contains( hostileEnemies[i] ) )
  5314. actors.PushBack( hostileEnemies[i] );
  5315. }
  5316. }
  5317.  
  5318. //Include enemies that are technically dead, but can be finished off
  5319. if ( finishableEnemiesList.Size() > 0 )
  5320. {
  5321. for( i=0; i < finishableEnemiesList.Size() ; i+=1 )
  5322. {
  5323. if ( !actors.Contains( finishableEnemiesList[i] ) )
  5324. actors.PushBack( finishableEnemiesList[i] );
  5325. }
  5326. }
  5327.  
  5328. //Check the last moveTarget for situation where enemy targets an ally when you round a corner
  5329. if ( moveTarget && !actors.Contains( moveTarget ) )
  5330. actors.PushBack( moveTarget );
  5331.  
  5332. FilterActors( actors, onlyThreatTargets, false );
  5333.  
  5334. //Determine whether Player should be threatened
  5335. if ( actors.Size() > 0 )
  5336. {
  5337. setIsThreatened = false;
  5338.  
  5339. if ( onlyThreatTargets )
  5340. {
  5341. setIsThreatened = true;
  5342. }
  5343. else
  5344. {
  5345. for( i=0; i < actors.Size() ; i+=1 )
  5346. {
  5347. if ( IsThreat( actors[i] ) )
  5348. {
  5349. setIsThreatened = true;
  5350. break;
  5351. }
  5352. else
  5353. {
  5354. enemysTarget = actors[i].GetTarget();
  5355. isEnemyInCombat = actors[i].IsInCombat();
  5356. if ( isEnemyInCombat && enemysTarget && GetAttitudeBetween( enemysTarget, this ) == AIA_Friendly && enemysTarget.isPlayerFollower )
  5357. {
  5358. setIsThreatened = true;
  5359. break;
  5360. }
  5361. }
  5362. }
  5363. }
  5364.  
  5365. //After filtering you will only have either all hostile or all neutral npcs
  5366. for( i = actors.Size()-1; i>=0; i-=1 )
  5367. {
  5368. if ( ( !actors[i].IsAlive() && !finishableEnemiesList.Contains( actors[i] ) )
  5369. || actors[i].IsKnockedUnconscious()
  5370. || this.GetUsedVehicle() == actors[i]
  5371. || !actors[i].CanBeTargeted() )
  5372. {
  5373. actors.EraseFast(i);
  5374. }
  5375. else if ( !IsThreatened() )
  5376. {
  5377. if ( !WasVisibleInScaledFrame( actors[i], 1.f, 1.f ) )
  5378. actors.EraseFast(i);
  5379. }
  5380. }
  5381. }
  5382. else if ( moveTarget && IsThreat( moveTarget ) )
  5383. setIsThreatened = true;
  5384. //SetIsThreatened( true );
  5385. else
  5386. setIsThreatened = false;
  5387. //SetIsThreatened( false );
  5388.  
  5389. if ( setIsThreatened )
  5390. {
  5391. enemyCollectionDist = 50.f;
  5392. SetIsThreatened( true );
  5393. }
  5394. else
  5395. {
  5396. if ( IsThreatened() )
  5397. AddTimer( 'finishableEnemiesList', 1.f );
  5398.  
  5399. enemyCollectionDist = findMoveTargetDistMax;
  5400. SetIsThreatened( false );
  5401. }
  5402.  
  5403. moveTargets = actors;
  5404. potentialMoveTargets = moveTargets;
  5405.  
  5406. //MS: By default Geralt will not play PCS_AlertNear unless there is one guy among the hostile npcs that canBeStrafed
  5407. if ( !moveTarget )
  5408. enableStrafe = false;
  5409.  
  5410. if ( potentialMoveTargets.Size() > 0 )
  5411. {
  5412. for ( i = 0; i < potentialMoveTargets.Size(); i += 1 )
  5413. {
  5414. if ( potentialMoveTargets[i].CanBeStrafed() )
  5415. enableStrafe = true;
  5416.  
  5417. if ( !potentialMoveTargets[i].GetGameplayVisibility() )
  5418. moveTargetDists.PushBack( 100.f ); //Put invisible enemies as the last choice for moveTarget
  5419. else
  5420. moveTargetDists.PushBack( VecDistance( potentialMoveTargets[i].GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() ) );
  5421.  
  5422. if ( canFindPathEnemiesList.Contains( potentialMoveTargets[i] ) )
  5423. {
  5424. moveTargetCanPathFinds.PushBack( true );
  5425. aPotentialMoveTargetCanFindPath = true;
  5426. }
  5427. else
  5428. {
  5429. moveTargetCanPathFinds.PushBack( false );
  5430. }
  5431. }
  5432.  
  5433. if ( aPotentialMoveTargetCanFindPath )
  5434. {
  5435. for ( i = moveTargetCanPathFinds.Size()-1 ; i >= 0; i-=1 )
  5436. {
  5437. if ( !moveTargetCanPathFinds[i] )
  5438. {
  5439. moveTargetCanPathFinds.EraseFast(i);
  5440. potentialMoveTargets.EraseFast(i);
  5441. moveTargetDists.EraseFast(i);
  5442. }
  5443. }
  5444. }
  5445.  
  5446. if ( moveTargetDists.Size() > 0 )
  5447. newMoveTarget = potentialMoveTargets[ ArrayFindMinF( moveTargetDists ) ];
  5448. }
  5449.  
  5450. if ( newMoveTarget && newMoveTarget != moveTarget )
  5451. {
  5452. if ( moveTarget )
  5453. {
  5454. playerToNewMoveTargetDist = VecDistance( newMoveTarget.GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() );
  5455. playerToMoveTargetDist = VecDistance( moveTarget.GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() );
  5456. wasVisibleInFullFrame = WasVisibleInScaledFrame( moveTarget, 1.f, 1.f ) ;
  5457.  
  5458. if ( !IsThreat( moveTarget )
  5459. || !wasVisibleInFullFrame
  5460. || !IsEnemyVisible( moveTarget )
  5461. || ( !moveTarget.IsAlive() && !finishableEnemiesList.Contains( moveTarget ) )
  5462. || !moveTarget.GetGameplayVisibility()
  5463. || ( moveTarget.IsAlive() && moveTarget.IsKnockedUnconscious() )
  5464. || ( wasVisibleInFullFrame && IsEnemyVisible( moveTarget ) && playerToNewMoveTargetDist < playerToMoveTargetDist - 0.25f ) )
  5465. {
  5466. SetMoveTarget( newMoveTarget );
  5467. }
  5468. }
  5469. else
  5470. SetMoveTarget( newMoveTarget );
  5471. }
  5472.  
  5473.  
  5474. if ( !IsThreatened() )
  5475. {
  5476. if ( moveTarget
  5477. && ( ( !moveTarget.IsAlive() && !finishableEnemiesList.Contains( moveTarget ) ) || !WasVisibleInScaledFrame( moveTarget, 0.8f, 1.f ) || VecDistance( moveTarget.GetWorldPosition(), this.GetWorldPosition() ) > theGame.params.MAX_THROW_RANGE ) )
  5478. {
  5479. confirmEmptyMoveTarget = true;
  5480. newEmptyMoveTargetTimer = 0.f;
  5481. }
  5482. }
  5483. /*else if ( moveTarget
  5484. && ( moveTarget.IsAlive() || finishableEnemiesList.Contains( moveTarget ) )
  5485. //&& moveTarget.GetGameplayVisibility()
  5486. && hostileEnemies.Contains( moveTarget ) )
  5487. */
  5488. else if ( moveTarget && ( IsThreat( moveTarget ) || finishableEnemiesList.Contains( moveTarget ) ) )
  5489. {
  5490. if ( !IsEnemyVisible( moveTarget ) )
  5491. {
  5492. confirmEmptyMoveTarget = true;
  5493. newEmptyMoveTargetTimer = 5.f;
  5494. }
  5495. else
  5496. SetMoveTarget( moveTarget );
  5497. }
  5498. else if ( IsInCombat() )
  5499. {
  5500. confirmEmptyMoveTarget = true;
  5501. newEmptyMoveTargetTimer = 1.0f;
  5502. }
  5503.  
  5504. if ( confirmEmptyMoveTarget )
  5505. {
  5506. if ( newEmptyMoveTargetTimer < emptyMoveTargetTimer )
  5507. {
  5508. bIsConfirmingEmptyTarget = false;
  5509. emptyMoveTargetTimer = newEmptyMoveTargetTimer;
  5510. }
  5511.  
  5512. ConfirmEmptyMoveTarget( newEmptyMoveTargetTimer );
  5513. }
  5514. }
  5515. else
  5516. SetIsThreatened( false );
  5517.  
  5518. //reactionsSystem
  5519. if ( IsThreatened() && !IsInFistFightMiniGame() )
  5520. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'CombatNearbyAction', 5.0, 18.0f, -1.f, -1, true ); //reactionSystemSearch
  5521. else
  5522. theGame.GetBehTreeReactionManager().RemoveReactionEvent( this, 'CombatNearbyAction'); //reactionSystemSearch
  5523.  
  5524. // sending nearby monsters count as parameter to sound system
  5525. theSound.SoundParameter( "monster_count", hostileMonsters.Size() );
  5526. }
  5527.  
  5528. private function ConfirmEmptyMoveTarget( timeDelta : float )
  5529. {
  5530. if ( !bIsConfirmingEmptyTarget )
  5531. {
  5532. bIsConfirmingEmptyTarget = true;
  5533. AddTimer( 'ConfirmEmptyTargetTimer', timeDelta );
  5534. }
  5535. }
  5536.  
  5537. private timer function ConfirmEmptyTargetTimer( time : float , id : int)
  5538. {
  5539. SetMoveTarget( NULL );
  5540. }
  5541.  
  5542.  
  5543. var isInCombatReason : int;
  5544. var canFindPathToEnemy : bool;
  5545. var combatModeEnt : CEntity;
  5546. var navDist : float;
  5547. var directDist : float;
  5548. var reachableEnemyWasTooFar : bool;
  5549. var reachableEnemyWasTooFarTimeStamp : float;
  5550. var reachablilityFailed : bool;
  5551. var reachablilityFailedTimeStamp : float;
  5552. public function ShouldEnableCombat( out unableToPathFind : bool, forceCombatMode : bool ) : bool
  5553. {
  5554. var shouldFindPathToNPCs : bool;
  5555. var playerToTargetDist : float;
  5556. var canFindPathToTarget : bool;
  5557. var moveTargetNPC : CNewNPC;
  5558. var currentTime : float;
  5559. var currentTime2 : float;
  5560. var isReachableEnemyTooFar : bool;
  5561. var reachableEnemyWasTooFarTimeStampDelta : float;
  5562. var reachablilityFailedTimeStampDelta : float;
  5563. var currentTimeTemp : float;
  5564.  
  5565. /*if ( GetIsSprinting() )
  5566. {
  5567. unableToPathFind = true;
  5568. isInCombatReason = 0;
  5569. return false;
  5570. }*/
  5571.  
  5572. if ( forceCombatMode && isSnappedToNavMesh )
  5573. return true;
  5574.  
  5575. if ( !IsThreatened() )
  5576. {
  5577. reachableEnemyWasTooFar = false;
  5578. reachablilityFailed = false;
  5579. isInCombatReason = 0;
  5580. return false;
  5581. }
  5582.  
  5583. if( thePlayer.substateManager.GetStateCur() != 'CombatExploration' && !thePlayer.substateManager.CanChangeToState( 'CombatExploration' )
  5584. && thePlayer.substateManager.GetStateCur() != 'Ragdoll' ) //&& !thePlayer.substateManager.CanChangeToState( 'Ragdoll' ) ) )
  5585. {
  5586. reachableEnemyWasTooFar = false;
  5587. reachablilityFailed = false;
  5588. isInCombatReason = 0;
  5589. return false;
  5590. }
  5591.  
  5592. if ( moveTarget )
  5593. {
  5594. canFindPathToEnemy = CanFindPathToTarget( unableToPathFind );
  5595. currentTimeTemp = EngineTimeToFloat( theGame.GetEngineTime() );
  5596.  
  5597. if ( canFindPathToEnemy )
  5598. isReachableEnemyTooFar = IsReachableEnemyTooFar();
  5599.  
  5600. if ( IsInCombat() )
  5601. {
  5602. if ( canFindPathToEnemy )
  5603. {
  5604. if ( forceCombatMode )
  5605. return true;
  5606.  
  5607. reachablilityFailed = false;
  5608. reachablilityFailedTimeStamp = currentTimeTemp;
  5609.  
  5610. if ( reachableEnemyWasTooFar )
  5611. {
  5612. if ( isReachableEnemyTooFar )
  5613. {
  5614. currentTime = currentTimeTemp;
  5615.  
  5616. if ( GetIsSprinting() )
  5617. reachableEnemyWasTooFarTimeStampDelta = 0.f;
  5618. else
  5619. reachableEnemyWasTooFarTimeStampDelta = 3.f;
  5620.  
  5621. if ( currentTime > reachableEnemyWasTooFarTimeStamp + reachableEnemyWasTooFarTimeStampDelta )
  5622. {
  5623. isInCombatReason = 0;
  5624. unableToPathFind = true;
  5625. return false;
  5626. }
  5627. }
  5628. else
  5629. reachableEnemyWasTooFar = false;
  5630. }
  5631. else
  5632. {
  5633. if ( isReachableEnemyTooFar )
  5634. {
  5635. reachableEnemyWasTooFar = true;
  5636. reachableEnemyWasTooFarTimeStamp = currentTimeTemp;
  5637. }
  5638. else
  5639. reachableEnemyWasTooFar = false;
  5640. }
  5641.  
  5642. return true;
  5643. }
  5644. else
  5645. {
  5646. reachableEnemyWasTooFar = false;
  5647. reachableEnemyWasTooFarTimeStamp = currentTimeTemp;
  5648.  
  5649. if ( reachablilityFailed )
  5650. {
  5651. if ( IsEnemyTooHighToReach() )
  5652. reachablilityFailedTimeStampDelta = 1.f;
  5653. else
  5654. reachablilityFailedTimeStampDelta = 5.f;
  5655.  
  5656. currentTime2 = currentTimeTemp;
  5657. if ( currentTime2 > reachablilityFailedTimeStamp + reachablilityFailedTimeStampDelta )
  5658. {
  5659. unableToPathFind = true;
  5660. return false;
  5661. }
  5662. }
  5663. else
  5664. {
  5665. reachablilityFailed = true;
  5666. reachablilityFailedTimeStamp = currentTimeTemp;
  5667. }
  5668.  
  5669. return true;
  5670. }
  5671. }
  5672. else if ( canFindPathToEnemy )
  5673. {
  5674. if ( forceCombatMode )
  5675. {
  5676. reachableEnemyWasTooFar = false;
  5677. return true;
  5678. }
  5679.  
  5680. reachablilityFailed = false;
  5681. reachablilityFailedTimeStamp = currentTimeTemp;
  5682.  
  5683. moveTargetNPC = (CNewNPC)moveTarget;
  5684. playerToTargetDist = VecDistance( moveTarget.GetWorldPosition(), this.GetWorldPosition() );
  5685.  
  5686. /*if ( !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), moveTarget.GetWorldPosition(), 0.4f ) )
  5687. {
  5688. isInCombatReason = 0;
  5689. return false;
  5690. }
  5691. else*/ if ( reachableEnemyWasTooFar
  5692. && ( isReachableEnemyTooFar || !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), moveTarget.GetWorldPosition(), 0.4f ) ) )
  5693. {
  5694. isInCombatReason = 0;
  5695. return false;
  5696. }
  5697. else if ( playerToTargetDist <= findMoveTargetDistMin )
  5698. isInCombatReason = 1;
  5699. else if ( ( moveTargetNPC.GetCurrentStance() == NS_Fly || moveTargetNPC.IsRanged() ) && hostileEnemies.Contains( moveTarget ) )
  5700. isInCombatReason = 2;
  5701. else
  5702. {
  5703. isInCombatReason = 0;
  5704. return false;
  5705. }
  5706.  
  5707. reachableEnemyWasTooFar = false;
  5708. return true;
  5709. }
  5710. }
  5711. else
  5712. {
  5713. reachableEnemyWasTooFar = false;
  5714. reachablilityFailed = false;
  5715. }
  5716.  
  5717. isInCombatReason = 0;
  5718. return false;
  5719. }
  5720.  
  5721. private function CanFindPathToTarget( out unableToPathFind : bool, optional forcedTarget : CNewNPC ) : bool
  5722. {
  5723. var moveTargetNPC : CNewNPC;
  5724. var moveTargetsTemp : array<CActor>;
  5725. var i : int;
  5726. var safeSpotTolerance : float;
  5727. var ent : CEntity;
  5728.  
  5729. moveTargetsTemp = moveTargets;
  5730.  
  5731. for ( i = 0; i < moveTargetsTemp.Size(); i += 1 )
  5732. {
  5733. moveTargetNPC = (CNewNPC)moveTargetsTemp[i];
  5734.  
  5735. if ( moveTargetNPC && moveTargetNPC.GetCurrentStance() == NS_Fly )
  5736. {
  5737. isInCombatReason = 2;
  5738. return true;
  5739. }
  5740. }
  5741.  
  5742. switch ( navQuery.GetLastOutput( 0.4 ) )
  5743. {
  5744. case EAsyncTastResult_Failure:
  5745. {
  5746. isInCombatReason = 0;
  5747. return false;
  5748. }
  5749. case EAsyncTastResult_Success:
  5750. {
  5751. ent = navQuery.GetOutputClosestEntity();
  5752.  
  5753. if ( ent )
  5754. combatModeEnt = moveTarget;
  5755.  
  5756. navDist = navQuery.GetOutputClosestDistance();
  5757.  
  5758. isInCombatReason = 1;
  5759. return true;
  5760. }
  5761. case EAsyncTastResult_Pending:
  5762. {
  5763. return canFindPathToEnemy;
  5764. }
  5765. case EAsyncTastResult_Invalidated:
  5766. {
  5767. if ( IsInCombat() )
  5768. {
  5769. if ( IsEnemyTooHighToReach() )
  5770. safeSpotTolerance = 0.f;
  5771. else
  5772. safeSpotTolerance = 3.f;
  5773. }
  5774. else
  5775. safeSpotTolerance = 0.f;
  5776.  
  5777. switch( navQuery.TestActorsList( ENavigationReachability_Any, this, moveTargetsTemp, safeSpotTolerance, 75.0 ) )
  5778. {
  5779. case EAsyncTastResult_Failure:
  5780. {
  5781. isInCombatReason = 0;
  5782. return false;
  5783. }
  5784. case EAsyncTastResult_Success:
  5785. {
  5786. ent = navQuery.GetOutputClosestEntity();
  5787.  
  5788. if ( ent )
  5789. combatModeEnt = moveTarget;
  5790.  
  5791. navDist = navQuery.GetOutputClosestDistance();
  5792.  
  5793. isInCombatReason = 1;
  5794. return true;
  5795. }
  5796. case EAsyncTastResult_Pending:
  5797. {
  5798. return canFindPathToEnemy;
  5799. }
  5800. case EAsyncTastResult_Invalidated:
  5801. {
  5802. if ( IsInCombat() )
  5803. return true;
  5804. else
  5805. return false;
  5806. }
  5807. }
  5808. }
  5809. }
  5810. }
  5811.  
  5812. private function IsReachableEnemyTooFar() : bool
  5813. {
  5814. //var navDistFailMax : float = 100.f;
  5815. var navDistLimit : float = findMoveTargetDist; //25.f;
  5816. var navDistDivisor : float = 2.f;
  5817. var playerToTargetVector : Vector;
  5818.  
  5819. directDist = VecDistance( combatModeEnt.GetWorldPosition(), thePlayer.GetWorldPosition() );
  5820. playerToTargetVector = this.GetWorldPosition() - combatModeEnt.GetWorldPosition();
  5821.  
  5822. if ( playerMode.GetForceCombatMode() || isInCombatReason == 2 )
  5823. return false;
  5824.  
  5825. if ( ( playerToTargetVector.Z < 0.5 && navDist > navDistLimit && directDist < navDist/navDistDivisor ) )
  5826. return true;
  5827. else
  5828. return false;
  5829. }
  5830.  
  5831. private function IsEnemyTooHighToReach() : bool
  5832. {
  5833. var playerToTargetVector : Vector;
  5834.  
  5835. playerToTargetVector = this.GetWorldPosition() - combatModeEnt.GetWorldPosition();
  5836.  
  5837. if ( playerToTargetVector.Z < -0.5f && !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), combatModeEnt.GetWorldPosition(), 0.4f ) )
  5838. return true;
  5839. else
  5840. return false;
  5841. }
  5842.  
  5843. //Force Geralt to face an enemy for a moment before changing to another enemy
  5844. public function LockToMoveTarget( lockTime : float )
  5845. {
  5846. /*if ( IsMoveTargetChangeAllowed() )
  5847. {
  5848. bMoveTargetChangeAllowed = false;
  5849. AddTimer( 'DisableLockToMoveTargetTimer', lockTime );
  5850. }*/
  5851. }
  5852.  
  5853. private timer function DisableLockToMoveTargetTimer( time : float , id : int)
  5854. {
  5855. if ( !this.IsActorLockedToTarget() )
  5856. {
  5857. SetMoveTargetChangeAllowed( true );
  5858. }
  5859. }
  5860.  
  5861. public function SetMoveTargetChangeAllowed( flag : bool )
  5862. {
  5863. //bMoveTargetChangeAllowed = flag;
  5864. }
  5865.  
  5866. public function IsMoveTargetChangeAllowed() : bool
  5867. {
  5868. return bMoveTargetChangeAllowed;
  5869. }
  5870.  
  5871. public function SetMoveTarget( actor : CActor )
  5872. {
  5873. if ( !actor && ForceCombatModeOverride() )
  5874. return;
  5875.  
  5876. if ( IsMoveTargetChangeAllowed()
  5877. && moveTarget != actor )
  5878. {
  5879. moveTarget = actor;
  5880. bIsConfirmingEmptyTarget = false;
  5881. RemoveTimer( 'ConfirmEmptyTargetTimer' );
  5882.  
  5883. if ( !moveTarget )
  5884. SetScriptMoveTarget( moveTarget );
  5885. }
  5886. }
  5887.  
  5888. private var isThreatened : bool;
  5889. protected function SetIsThreatened( flag : bool )
  5890. {
  5891. var allowSetIsThreatened : bool;
  5892.  
  5893. allowSetIsThreatened = true;
  5894. if ( ForceCombatModeOverride() )
  5895. {
  5896. if ( flag || !moveTarget )
  5897. allowSetIsThreatened = true;
  5898. else
  5899. allowSetIsThreatened = false;
  5900. }
  5901.  
  5902. if ( allowSetIsThreatened )
  5903. {
  5904. isThreatened = flag;
  5905. }
  5906. }
  5907.  
  5908. public function ForceCombatModeOverride() : bool
  5909. {
  5910. if( this.GetPlayerMode().GetForceCombatMode()
  5911. && canFindPathToEnemy
  5912. && theGame.GetGlobalAttitude( GetBaseAttitudeGroup(), moveTarget.GetBaseAttitudeGroup() ) == AIA_Hostile )
  5913. return true;
  5914. else
  5915. return false;
  5916. }
  5917.  
  5918. public function IsThreatened() : bool { return isThreatened; }
  5919.  
  5920. public function EnableFindTarget( flag : bool )
  5921. {
  5922. var target : CActor;
  5923.  
  5924. if( IsActorLockedToTarget() )
  5925. {
  5926. target = GetTarget();
  5927.  
  5928. if ( target && target.IsAlive() )
  5929. bCanFindTarget = flag;
  5930. else
  5931. bCanFindTarget = true;
  5932. }
  5933. else
  5934. bCanFindTarget = flag;
  5935. }
  5936.  
  5937. public function UpdateDisplayTarget( optional forceUpdate : bool, optional forceNullActor : bool )
  5938. {
  5939. var hud : CR4ScriptedHud;
  5940. var tempTarget : CGameplayEntity;
  5941. var angleDist1 : float;
  5942. var angleDist2 : float;
  5943. var nonActorTargetMult : float;
  5944. var combatActionType : int;
  5945. var currTarget : CActor;
  5946. var interactionTarget : CInteractionComponent;
  5947.  
  5948. var heading : float;
  5949.  
  5950. if(theGame.IsDialogOrCutscenePlaying())
  5951. {
  5952. currentSelectedDisplayTarget = NULL;
  5953.  
  5954. if ( displayTarget )
  5955. ConfirmDisplayTarget( NULL );
  5956.  
  5957. return;
  5958. }
  5959.  
  5960. if ( forceNullActor )
  5961. currTarget = NULL;
  5962. else
  5963. currTarget = GetTarget();
  5964.  
  5965. currentSelectedDisplayTarget = currTarget;
  5966.  
  5967. if ( currTarget && !currTarget.IsTargetableByPlayer() )
  5968. {
  5969. currentSelectedDisplayTarget = NULL;
  5970. ConfirmDisplayTarget( currentSelectedDisplayTarget );
  5971. return;
  5972. }
  5973. //Setting multiplier that increases non actor target priority
  5974. nonActorTargetMult = 1.25;
  5975.  
  5976. //Update the interaction icon
  5977. hud = (CR4ScriptedHud)theGame.GetHud();
  5978.  
  5979. if ( !IsThreatened() )
  5980. {
  5981. if ( !bLAxisReleased || lastAxisInputIsMovement )
  5982. {
  5983. if ( currTarget )
  5984. angleDist1 = AbsF( AngleDistance( this.GetHeading(), VecHeading( currTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  5985. else
  5986. angleDist1 = 360;
  5987.  
  5988. if ( nonActorTarget )
  5989. angleDist2 = AbsF( AngleDistance( this.GetHeading(), VecHeading( nonActorTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  5990. else
  5991. angleDist2 = 360;
  5992. }
  5993. else
  5994. {
  5995. if ( currTarget )
  5996. angleDist1 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( currTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  5997. else
  5998. angleDist1 = 360;
  5999.  
  6000. if ( nonActorTarget )
  6001. angleDist2 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( nonActorTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6002. else
  6003. angleDist2 = 360;
  6004. }
  6005. }
  6006.  
  6007. else
  6008. {
  6009. if ( !bLAxisReleased )
  6010. {
  6011. if ( ShouldUsePCModeTargeting() )
  6012. {
  6013. if ( currTarget )
  6014. angleDist1 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( currTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6015. else
  6016. angleDist1 = 360;
  6017.  
  6018. if ( nonActorTarget && IsInCombatAction() )
  6019. {
  6020. angleDist2 = nonActorTargetMult * AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( nonActorTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6021. }
  6022. else
  6023. angleDist2 = 360;
  6024. }
  6025. else
  6026. {
  6027. if ( currTarget )
  6028. angleDist1 = AbsF( AngleDistance( rawPlayerHeading, VecHeading( currTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6029. else
  6030. angleDist1 = 360;
  6031.  
  6032. if ( nonActorTarget && IsInCombatAction() )
  6033. {
  6034. angleDist2 = nonActorTargetMult * AbsF( AngleDistance( rawPlayerHeading, VecHeading( nonActorTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6035. }
  6036. else
  6037. angleDist2 = 360;
  6038. }
  6039. }
  6040. else
  6041. {
  6042. angleDist1 = 0;
  6043. angleDist2 = 360;
  6044. }
  6045. }
  6046.  
  6047.  
  6048. if ( angleDist1 < angleDist2 )
  6049. tempTarget = currTarget;
  6050. else
  6051. tempTarget = nonActorTarget;
  6052.  
  6053.  
  6054. if ( slideTarget && IsInCombatAction() )
  6055. {
  6056. combatActionType = (int)this.GetBehaviorVariable( 'combatActionType' );
  6057. if ( combatActionType == (int)CAT_Attack
  6058. || ( combatActionType == (int)CAT_SpecialAttack && this.GetBehaviorVariable( 'playerAttackType' ) == 1.f )
  6059. || ( combatActionType == (int)CAT_ItemThrow )
  6060. || ( combatActionType == (int)CAT_CastSign && !IsCurrentSignChanneled() )
  6061. || ( combatActionType == (int)CAT_CastSign && IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Axii )
  6062. || ( combatActionType == (int)CAT_CastSign && IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Igni )
  6063. || combatActionType == (int)CAT_Dodge
  6064. || combatActionType == (int)CAT_Roll )
  6065. {
  6066. if ( combatActionType == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Igni && !IsCombatMusicEnabled() )
  6067. currentSelectedDisplayTarget = tempTarget;
  6068. else
  6069. currentSelectedDisplayTarget = slideTarget;
  6070. }
  6071. else
  6072. currentSelectedDisplayTarget = tempTarget;
  6073. }
  6074. else if ( slideTarget
  6075. && this.rangedWeapon
  6076. && this.rangedWeapon.GetCurrentStateName() != 'State_WeaponWait'
  6077. && this.playerAiming.GetCurrentStateName() == 'Waiting' ) //( this.rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' || this.rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' ) )
  6078. currentSelectedDisplayTarget = slideTarget;
  6079. else
  6080. currentSelectedDisplayTarget = tempTarget;
  6081.  
  6082. interactionTarget = theGame.GetInteractionsManager().GetActiveInteraction();
  6083. if ( interactionTarget && !IsThreatened() && !( this.IsCastingSign() && this.IsCurrentSignChanneled() ) )
  6084. {
  6085. tempTarget = (CGameplayEntity)interactionTarget.GetEntity();
  6086. if ( tempTarget && tempTarget != this.GetUsedVehicle() )
  6087. {
  6088. currentSelectedDisplayTarget = tempTarget;
  6089. SetDisplayTarget( currentSelectedDisplayTarget );
  6090. }
  6091. }
  6092.  
  6093. // disabling display for invisible targets
  6094. if ( (CActor)currentSelectedDisplayTarget && !((CActor)currentSelectedDisplayTarget).GetGameplayVisibility() )
  6095. {
  6096. currentSelectedDisplayTarget = NULL;
  6097. }
  6098.  
  6099. if ( displayTarget != currentSelectedDisplayTarget )
  6100. {
  6101. if ( forceUpdate )
  6102. SetDisplayTarget( currentSelectedDisplayTarget );
  6103. else
  6104. ConfirmDisplayTarget( currentSelectedDisplayTarget );
  6105. }
  6106. }
  6107.  
  6108. private var bConfirmDisplayTargetTimerEnabled : bool;
  6109. private var displayTargetToConfirm : CGameplayEntity;
  6110. private var currentSelectedDisplayTarget : CGameplayEntity;
  6111.  
  6112. private function ConfirmDisplayTarget( targetToConfirm : CGameplayEntity )
  6113. {
  6114. if ( targetToConfirm != displayTarget )
  6115. {
  6116. displayTargetToConfirm = targetToConfirm;
  6117. if( !bConfirmDisplayTargetTimerEnabled )
  6118. {
  6119. bConfirmDisplayTargetTimerEnabled = true;
  6120.  
  6121. if ( targetToConfirm )
  6122. AddTimer( 'ConfirmDisplayTargetTimer', 0.1f );
  6123. else
  6124. AddTimer( 'ConfirmDisplayTargetTimer', 0.f );
  6125. }
  6126. }
  6127. }
  6128.  
  6129. private timer function ConfirmDisplayTargetTimer( time : float, optional id : int)
  6130. {
  6131. if ( displayTargetToConfirm == currentSelectedDisplayTarget )
  6132. SetDisplayTarget( displayTargetToConfirm );
  6133.  
  6134. bConfirmDisplayTargetTimerEnabled = false;
  6135. }
  6136.  
  6137.  
  6138. protected function SetDisplayTarget( e : CGameplayEntity )
  6139. {
  6140. var displayTargetActor : CActor;
  6141.  
  6142. if ( e != displayTarget )
  6143. {
  6144. displayTarget = e;
  6145. displayTargetActor = (CActor)displayTarget;
  6146. SetPlayerCombatTarget( displayTargetActor );
  6147.  
  6148. if ( displayTargetActor && !displayTargetActor.IsTargetableByPlayer())
  6149. {
  6150. isDisplayTargetTargetable = false;
  6151. }
  6152. else if ( !displayTargetActor && displayTarget != nonActorTarget )
  6153. {
  6154. isDisplayTargetTargetable = false;
  6155. }
  6156. else
  6157. {
  6158. isDisplayTargetTargetable = true;
  6159. }
  6160. }
  6161. }
  6162.  
  6163. public function GetDisplayTarget() : CGameplayEntity { return displayTarget; }
  6164.  
  6165. private var isDisplayTargetTargetable : bool;
  6166. public function IsDisplayTargetTargetable() : bool
  6167. {
  6168. return isDisplayTargetTargetable;
  6169. }
  6170.  
  6171. public var radialSlots : array<name>;
  6172. public function EnableRadialSlots( enable : bool, slotNames : array<name> )
  6173. {
  6174. var hud : CR4ScriptedHud;
  6175. var module : CR4HudModuleRadialMenu;
  6176. var i : int;
  6177.  
  6178. hud = (CR4ScriptedHud)theGame.GetHud();
  6179. module = (CR4HudModuleRadialMenu)hud.GetHudModule("RadialMenuModule");
  6180.  
  6181. for(i=0; i<slotNames.Size(); i+=1)
  6182. {
  6183. module.SetDesaturated( !enable, slotNames[i] );
  6184. }
  6185. }
  6186.  
  6187. public function IsEnemyInCone( source : CActor, coneHeading : Vector, coneDist, coneAngle : float, out newLockTarget : CActor ) : bool
  6188. {
  6189. var targets : array<CActor>;
  6190. var sourceToTargetDists : array<float>;
  6191. var i : int;
  6192. var targetingInfo : STargetingInfo;
  6193.  
  6194. //GetVisibleEnemies( targets );
  6195. //targets = FilterActors( targets );
  6196. targets = GetMoveTargets();
  6197.  
  6198. if ( targets.Size() > 0 )
  6199. {
  6200. targetingInfo.source = this;
  6201. targetingInfo.canBeTargetedCheck = true;
  6202. targetingInfo.coneCheck = true;
  6203. targetingInfo.coneHalfAngleCos = CosF( Deg2Rad( coneAngle * 0.5f ) );
  6204. targetingInfo.coneDist = coneDist;
  6205. targetingInfo.coneHeadingVector = coneHeading;
  6206. targetingInfo.distCheck = true;
  6207. targetingInfo.invisibleCheck = true;
  6208. targetingInfo.navMeshCheck = true;
  6209. targetingInfo.inFrameCheck = false;
  6210. targetingInfo.frameScaleX = 1.f;
  6211. targetingInfo.frameScaleY = 1.f;
  6212. targetingInfo.knockDownCheck = false;
  6213. targetingInfo.knockDownCheckDist = 1.5f;
  6214. targetingInfo.rsHeadingCheck = false;
  6215. targetingInfo.rsHeadingLimitCos = 1.0f;
  6216.  
  6217. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  6218. {
  6219. targetingInfo.targetEntity = targets[i];
  6220. if ( !IsEntityTargetable( targetingInfo ) )
  6221. targets.Erase( i );
  6222. }
  6223.  
  6224. for ( i = 0; i < targets.Size(); i += 1 )
  6225. sourceToTargetDists.PushBack( VecDistance( source.GetWorldPosition(), targets[i].GetWorldPosition() ) );
  6226.  
  6227. if(sourceToTargetDists.Size() > 0)
  6228. newLockTarget = targets[ ArrayFindMinF( sourceToTargetDists ) ];
  6229. else
  6230. newLockTarget = NULL;
  6231. }
  6232.  
  6233. return targets.Size() > 0;
  6234. }
  6235.  
  6236. public function GetScreenSpaceLockTarget( sourceEnt : CGameplayEntity, coneAngle, coneDist, coneHeading : float, optional inFrameCheck : bool ) : CActor
  6237. {
  6238. var source : CActor;
  6239. var sourcePos, targetPos : Vector;
  6240. var targets : array<CActor>;
  6241. var sourceToTargetDists : array<float>;
  6242. var sourceCoord : Vector;
  6243. var targetCoord : Vector;
  6244. var i : int;
  6245. var angleDiff : float;
  6246. var sourceToTargetHeading : float;
  6247. var sourceToTargetDist : float;
  6248. var size : float;
  6249. var targetingDist : float;
  6250. var targetingInfo : STargetingInfo;
  6251.  
  6252. var temp : int;
  6253.  
  6254. // MAREK TODO : Need to use cached values of screenspace coords instead of calculating again
  6255. //GetVisibleEnemies( targets );
  6256. //targets = FilterActors( targets );
  6257. source = (CActor)sourceEnt;
  6258.  
  6259. targets = GetMoveTargets();
  6260.  
  6261. if ( this.IsPCModeEnabled() )
  6262. {
  6263. if ( ( coneHeading > -45.f && coneHeading < 45.f )
  6264. || coneHeading > 135.f
  6265. || coneHeading < -135.f )
  6266. {
  6267. if ( coneHeading > 0 )
  6268. coneHeading = 180 - coneHeading;
  6269. else
  6270. coneHeading = 180 + coneHeading;
  6271. }
  6272. }
  6273.  
  6274. /*if ( IsCombatMusicEnabled() || hostileEnemies.Size() > 0 )
  6275. {
  6276. if ( targets[0] && !IsThreat( targets[0] ) )
  6277. targets.Clear();
  6278. }*/
  6279.  
  6280. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  6281. {
  6282. if ( ( !targets[i].GetGameplayVisibility() || !IsThreat( targets[i] ) || !IsEnemyVisible( targets[i] ) || !this.CanBeTargetedIfSwimming( targets[i] ) )
  6283. && ( !IsCastingSign() || GetCurrentlyCastSign() != ST_Axii ) )
  6284. targets.Erase(i);
  6285. }
  6286.  
  6287. if ( source )
  6288. {
  6289. temp = source.GetTorsoBoneIndex();
  6290.  
  6291. if ( temp < 0 )
  6292. sourcePos = source.GetWorldPosition();
  6293. else
  6294. sourcePos = MatrixGetTranslation( source.GetBoneWorldMatrixByIndex( source.GetTorsoBoneIndex() ) );
  6295. }
  6296. else
  6297. sourcePos = sourceEnt.GetWorldPosition();
  6298.  
  6299. theCamera.WorldVectorToViewRatio( sourcePos, sourceCoord.X , sourceCoord.Y );
  6300.  
  6301. /*if ( !IsUsingVehicle() )
  6302. targetingDist = softLockDist;
  6303. else*/
  6304. targetingDist = softLockDistVehicle;
  6305.  
  6306. if ( targets.Size() > 0 )
  6307. {
  6308. targetingInfo.source = this;
  6309. targetingInfo.canBeTargetedCheck = true;
  6310. targetingInfo.coneCheck = false;
  6311. targetingInfo.coneHalfAngleCos = 0.86602540378f; // = CosF( Deg2Rad( 60.0f * 0.5f ) )
  6312. targetingInfo.coneDist = targetingDist;
  6313. targetingInfo.coneHeadingVector = Vector( 0.0f, 1.0f, 0.0f );
  6314. targetingInfo.distCheck = true;
  6315. targetingInfo.invisibleCheck = true;
  6316. targetingInfo.navMeshCheck = false;
  6317.  
  6318. if ( inFrameCheck )
  6319. targetingInfo.inFrameCheck = true;
  6320. else
  6321. targetingInfo.inFrameCheck = false;
  6322.  
  6323. targetingInfo.frameScaleX = 1.f;
  6324. targetingInfo.frameScaleY = 1.f;
  6325. targetingInfo.knockDownCheck = false;
  6326. targetingInfo.knockDownCheckDist = softLockDist;
  6327. if ( bRAxisReleased )
  6328. targetingInfo.rsHeadingCheck = false;
  6329. else
  6330. targetingInfo.rsHeadingCheck = true;
  6331. targetingInfo.rsHeadingLimitCos = -0.5f; // = CosF( Deg2Rad( 120.0f ) );
  6332.  
  6333. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  6334. {
  6335. temp = targets[i].GetTorsoBoneIndex();
  6336.  
  6337. if ( temp < 0 )
  6338. targetPos = targets[i].GetWorldPosition();
  6339. else
  6340. targetPos = MatrixGetTranslation( targets[i].GetBoneWorldMatrixByIndex( targets[i].GetTorsoBoneIndex() ) );
  6341.  
  6342. theCamera.WorldVectorToViewRatio( targetPos, targetCoord.X, targetCoord.Y );
  6343. sourceToTargetHeading = VecHeading( targetCoord - sourceCoord );
  6344. angleDiff = AbsF( AngleDistance( coneHeading, sourceToTargetHeading ) );
  6345.  
  6346. targetingInfo.targetEntity = targets[i];
  6347. if ( !IsEntityTargetable( targetingInfo ) )
  6348. targets.Erase( i );
  6349. else if ( !bRAxisReleased && angleDiff > ( coneAngle * 0.5 ) )
  6350. targets.Erase( i );
  6351. else if ( targets[i] == sourceEnt )
  6352. targets.Erase( i );
  6353.  
  6354. /*if ( GetDisplayTarget() && IsInCombatAction() && GetBehaviorVariable( 'combatActionType') == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Igni )
  6355. {
  6356.  
  6357. }
  6358. else
  6359. {
  6360. targetingInfo.rsHeadingCheck = false;
  6361. if ( !IsEntityTargetable( targetingInfo )
  6362. || angleDiff > ( coneAngle * 0.5 )
  6363. || targets[i] == sourceEnt )
  6364. targets.Erase( i );
  6365. }*/
  6366. }
  6367. }
  6368.  
  6369. size = targets.Size();
  6370. if ( size > 0 )
  6371. {
  6372. for ( i = 0; i < targets.Size(); i += 1 )
  6373. {
  6374. temp = targets[i].GetTorsoBoneIndex();
  6375.  
  6376. if ( temp < 0 )
  6377. targetPos = targets[i].GetWorldPosition();
  6378. else
  6379. targetPos = MatrixGetTranslation( targets[i].GetBoneWorldMatrixByIndex( targets[i].GetTorsoBoneIndex() ) );
  6380.  
  6381. theCamera.WorldVectorToViewRatio( targetPos, targetCoord.X, targetCoord.Y );
  6382. sourceToTargetHeading = AbsF( VecHeading( targetCoord - sourceCoord ) );
  6383. angleDiff = AngleDistance( 180, sourceToTargetHeading );
  6384. sourceToTargetDist = VecDistance2D( sourceCoord, targetCoord );
  6385.  
  6386. sourceToTargetDists.PushBack( SinF( Deg2Rad( angleDiff ) ) * sourceToTargetDist );
  6387. }
  6388. }
  6389.  
  6390. if ( targets.Size() > 0 )//GetDisplayTarget() )
  6391. return targets[ ArrayFindMinF( sourceToTargetDists ) ];
  6392. else
  6393. return NULL;
  6394. }
  6395.  
  6396. public function IsEntityTargetable( out info : STargetingInfo, optional usePrecalcs : bool ) : bool
  6397. {
  6398. var playerHasBlockingBuffs : bool;
  6399. var sourceActor : CActor;
  6400. var targetEntity : CEntity;
  6401. var targetActor : CActor;
  6402. var targetNPC : CNewNPC;
  6403. var sourcePosition : Vector;
  6404. var targetPosition : Vector;
  6405. var direction : Vector;
  6406. var sourceToTargetDist : float;
  6407. var sourceCapsuleRadius : float;
  6408. var mpac : CMovingPhysicalAgentComponent;
  6409.  
  6410. var coneDistSq : float;
  6411. var knockDownCheckDistSq : float;
  6412. var sourceToTargetAngleDist : float;
  6413. var b : bool;
  6414. var infoSourceWorldPos : Vector;
  6415. var infoTargetWorldPos : Vector;
  6416. var finishEnabled : bool;
  6417.  
  6418. if ( usePrecalcs )
  6419. {
  6420. playerHasBlockingBuffs = targetingIn.playerHasBlockingBuffs;
  6421. }
  6422. else
  6423. {
  6424. playerHasBlockingBuffs = thePlayer.HasBuff( EET_Confusion ) || thePlayer.HasBuff( EET_Hypnotized ) || thePlayer.HasBuff( EET_Blindness ) || thePlayer.HasBuff( EET_WraithBlindness );
  6425. }
  6426. if ( playerHasBlockingBuffs )
  6427. {
  6428. return false;
  6429. }
  6430.  
  6431. sourceActor = info.source;
  6432. targetEntity = info.targetEntity;
  6433. if ( !sourceActor || !targetEntity )
  6434. {
  6435. return false;
  6436. }
  6437.  
  6438. targetActor = (CActor)targetEntity;
  6439.  
  6440. // "can be targeted" check
  6441. if ( info.canBeTargetedCheck && !targetActor.CanBeTargeted() )
  6442. {
  6443. return false;
  6444. }
  6445.  
  6446. // visibility check
  6447. if ( info.invisibleCheck && !targetActor.GetGameplayVisibility() )
  6448. {
  6449. return false;
  6450. }
  6451.  
  6452. sourcePosition = sourceActor.GetWorldPosition();
  6453. targetPosition = targetEntity.GetWorldPosition();
  6454.  
  6455. if ( targetActor )
  6456. {
  6457. { // do not target mounted horses
  6458. targetNPC = (CNewNPC)targetActor;
  6459. if ( targetNPC )
  6460. {
  6461. if ( targetNPC.IsHorse() && !targetNPC.GetHorseComponent().IsDismounted() )
  6462. {
  6463. return false;
  6464. }
  6465. }
  6466. }
  6467. }
  6468.  
  6469. if ( info.distCheck || info.knockDownCheck )
  6470. {
  6471. if ( usePrecalcs )
  6472. {
  6473. if ( targetActor )
  6474. {
  6475. // radius is taken form the first actor
  6476. sourceToTargetDist = Distance2DBetweenCapsuleAndPoint( targetActor, sourceActor ) - targetingPrecalcs.playerRadius;
  6477. }
  6478. else
  6479. {
  6480. sourceToTargetDist = VecDistance2D( sourcePosition, targetPosition ) - targetingPrecalcs.playerRadius;
  6481. }
  6482. }
  6483. else
  6484. {
  6485. if ( targetActor )
  6486. {
  6487. sourceToTargetDist = Distance2DBetweenCapsules( sourceActor, targetActor );
  6488. }
  6489. else
  6490. {
  6491. sourceToTargetDist = Distance2DBetweenCapsuleAndPoint( sourceActor, targetEntity );
  6492. }
  6493. }
  6494. }
  6495.  
  6496. // distance check
  6497. if ( info.distCheck )
  6498. {
  6499. if ( sourceToTargetDist >= info.coneDist )
  6500. {
  6501. return false;
  6502. }
  6503. }
  6504.  
  6505. // prepare source to target direction if needed
  6506. if ( info.coneCheck || info.rsHeadingCheck )
  6507. {
  6508. direction = VecNormalize2D( targetPosition - sourcePosition );
  6509. }
  6510.  
  6511. // cone check
  6512. if ( info.coneCheck )
  6513. {
  6514. if ( VecDot2D( direction, info.coneHeadingVector ) < info.coneHalfAngleCos )
  6515. {
  6516. return false;
  6517. }
  6518. }
  6519.  
  6520. // heading cone check
  6521. if ( info.rsHeadingCheck )
  6522. {
  6523. if ( usePrecalcs )
  6524. {
  6525. if ( VecDot2D( direction, targetingIn.lookAtDirection ) < info.rsHeadingLimitCos )
  6526. {
  6527. return false;
  6528. }
  6529. }
  6530. else
  6531. {
  6532. if ( VecDot2D( direction, VecNormalize2D( GetLookAtPosition() - sourcePosition ) ) < info.rsHeadingLimitCos )
  6533. {
  6534. return false;
  6535. }
  6536. }
  6537. }
  6538.  
  6539. // "in frame" check
  6540. if ( info.inFrameCheck && !WasVisibleInScaledFrame( targetEntity, info.frameScaleX, info.frameScaleY ) )
  6541. {
  6542. return false;
  6543. }
  6544.  
  6545. // navmesh check
  6546. if ( info.navMeshCheck && !IsSwimming() )
  6547. {
  6548. sourceCapsuleRadius = 0.1f;
  6549. if ( usePrecalcs )
  6550. {
  6551. sourceCapsuleRadius = targetingPrecalcs.playerRadius;
  6552. }
  6553. else
  6554. {
  6555. mpac = (CMovingPhysicalAgentComponent)sourceActor.GetMovingAgentComponent();
  6556. if ( mpac )
  6557. {
  6558. sourceCapsuleRadius = mpac.GetCapsuleRadius();
  6559. }
  6560. }
  6561. if ( !theGame.GetWorld().NavigationLineTest( sourcePosition, targetPosition, sourceCapsuleRadius ) )
  6562. {
  6563. return false;
  6564. }
  6565. }
  6566.  
  6567. // knockdown check
  6568. if ( info.knockDownCheck )
  6569. {
  6570. // if actor is not alive
  6571. if ( targetActor && !targetActor.IsAlive() )
  6572. {
  6573. // and contains enabled "Finish" interaction
  6574. finishEnabled = targetActor.GetComponent( 'Finish' ).IsEnabled();
  6575. if ( finishEnabled )
  6576. {
  6577. // and is contained in finishable enemies list
  6578. if ( finishableEnemiesList.Contains( targetActor ) )
  6579. {
  6580. // and is too far to "finish" -> we cannot target it
  6581. if ( sourceToTargetDist >= info.knockDownCheckDist )
  6582. {
  6583. return false;
  6584. }
  6585. }
  6586. }
  6587. }
  6588. }
  6589.  
  6590. return true;
  6591. }
  6592.  
  6593. public function CanBeTargetedIfSwimming( actor : CActor, optional usePrecalcs : bool ) : bool
  6594. {
  6595. var subDepth : float;
  6596. var isDiving : bool;
  6597.  
  6598. if ( !actor )
  6599. {
  6600. return false;
  6601. }
  6602.  
  6603. if ( usePrecalcs )
  6604. {
  6605. isDiving = targetingIn.isDiving;
  6606. }
  6607. else
  6608. {
  6609. isDiving = IsSwimming() && OnCheckDiving();
  6610. }
  6611.  
  6612. subDepth = ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetSubmergeDepth();
  6613.  
  6614. if ( isDiving )
  6615. {
  6616. return ( subDepth < -1.0f );
  6617. }
  6618. else
  6619. {
  6620. return ( subDepth >= -1.0f );
  6621. }
  6622. }
  6623.  
  6624. /*
  6625. 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
  6626. {
  6627. var targetActor : CActor;
  6628. var targetNPC : CNewNPC;
  6629. var direction : Vector;
  6630. var sourceToTargetDist : float;
  6631. var coneDistSq : float;
  6632. var sourceCapsuleRadius : float;
  6633. var knockDownCheckDistSq : float;
  6634. var sourceToTargetAngleDist : float;
  6635. var b : bool;
  6636. var targetsHorse : W3HorseComponent;
  6637.  
  6638. direction = VecNormalize2D( targetEntity.GetWorldPosition() - source.GetWorldPosition() );
  6639. targetActor = (CActor)targetEntity;
  6640.  
  6641. if ( distCheck )
  6642. {
  6643. if ( targetActor )
  6644. sourceToTargetDist = VecDistanceSquared( source.GetWorldPosition(), targetActor.GetNearestPointInBothPersonalSpaces( source.GetWorldPosition() ) );
  6645. else
  6646. sourceToTargetDist = VecDistanceSquared( source.GetWorldPosition(), targetEntity.GetWorldPosition() );
  6647.  
  6648. coneDistSq = coneDist * coneDist;
  6649. }
  6650.  
  6651. if ( knockDownCheck && targetActor )
  6652. knockDownCheckDistSq = knockDownCheckDist * knockDownCheckDist;
  6653.  
  6654. if ( navMeshCheck && targetActor )
  6655. sourceCapsuleRadius = ((CMovingPhysicalAgentComponent)source.GetMovingAgentComponent()).GetCapsuleRadius();
  6656.  
  6657. if ( rsHeadingCheck )
  6658. sourceToTargetAngleDist = AngleDistance( VecHeading( GetLookAtPosition() - source.GetWorldPosition() ), VecHeading( targetEntity.GetWorldPosition() - source.GetWorldPosition() ) );
  6659.  
  6660. // do not target mounted horses
  6661. if(targetActor)
  6662. {
  6663. targetNPC = (CNewNPC)targetActor;
  6664. if(targetNPC)
  6665. {
  6666. targetsHorse = (W3HorseComponent)targetNPC.GetHorseComponent();
  6667. if(targetsHorse && targetsHorse.IsNotBeingUsed() )
  6668. return false;
  6669. }
  6670. }
  6671.  
  6672. b = !coneCheck || AbsF( AngleDistance( coneHeading, VecHeading( direction ) ) ) < ( coneAngle * 0.5 );
  6673. b = b && ( !distCheck || sourceToTargetDist < coneDistSq );
  6674. b = b && ( !invisibleCheck || targetActor.GetGameplayVisibility() );
  6675. b = b && ( !navMeshCheck || (!IsSwimming() && theGame.GetWorld().NavigationLineTest( source.GetWorldPosition(), targetActor.GetWorldPosition(), sourceCapsuleRadius ) ) );
  6676. b = b && ( !inFrameCheck || WasVisibleInScaledFrame( targetEntity, frameScaleX, frameScaleY ) );
  6677. b = b && ( !rsHeadingCheck || ( rsHeading >= 0 && sourceToTargetAngleDist < 0 && sourceToTargetAngleDist >= ( rsHeadingLimit * -1 ) ) || ( rsHeading < 0 && sourceToTargetAngleDist >= 0 && sourceToTargetAngleDist <= rsHeadingLimit ) );
  6678. b = b && ( !knockDownCheck || !targetActor.GetComponent( 'Finish' ).IsEnabled() || ( targetActor.GetComponent( 'Finish' ).IsEnabled() && sourceToTargetDist < knockDownCheckDistSq ) );
  6679.  
  6680. if ( b )
  6681. return true;
  6682. else
  6683. return false;
  6684. }
  6685. */
  6686. private function FilterActors( out targets : array<CActor>, out onlyThreatsReturned : bool, optional usePrecalcs : bool )
  6687. {
  6688. var i : int;
  6689. var size : int;
  6690. var foundThreat : bool;
  6691. var foundNonThreat : bool;
  6692. var threatsCount : int;
  6693. var tmpActor : CActor;
  6694.  
  6695. foundThreat = false;
  6696. foundNonThreat = false;
  6697.  
  6698. size = targets.Size();
  6699. i = 0;
  6700. threatsCount = 0;
  6701.  
  6702. // after that loop first "threatsCount" targets will be "threat"
  6703. for ( i = 0; i < size; i+=1 )
  6704. {
  6705. if( IsThreat( targets[ i ], usePrecalcs ) )
  6706. {
  6707. foundThreat = true;
  6708. if ( i != threatsCount )
  6709. {
  6710. tmpActor = targets[ i ];
  6711. targets[ i ] = targets[ threatsCount ];
  6712. targets[ threatsCount ] = tmpActor;
  6713. }
  6714. threatsCount += 1;
  6715. }
  6716. else
  6717. {
  6718. foundNonThreat = true;
  6719. }
  6720. }
  6721.  
  6722. if ( foundThreat )
  6723. {
  6724. onlyThreatsReturned = true;
  6725. if ( foundNonThreat )
  6726. {
  6727. targets.Resize( threatsCount );
  6728. }
  6729. }
  6730. }
  6731.  
  6732. private function InternalFindTargetsInCone( out targets : array< CActor >, out outHeadingVector : Vector, optional usePrecalcs : bool )
  6733. {
  6734. var size, i : int;
  6735. var coneHalfAngleDot : float;
  6736. var coneHeading : float;
  6737. var coneHeadingVector : Vector;
  6738. var position : Vector;
  6739. var direction : Vector;
  6740. var onlyThreatTargetsFound : bool;
  6741.  
  6742. targets.Clear();
  6743. GetVisibleEnemies( targets );
  6744.  
  6745. //Include enemies that are technically dead, but can be finished off
  6746. for( i = 0; i < finishableEnemiesList.Size() ; i+=1 )
  6747. {
  6748. if ( !targets.Contains( finishableEnemiesList[i] ) )
  6749. {
  6750. targets.PushBack( finishableEnemiesList[i] );
  6751. }
  6752. }
  6753.  
  6754. onlyThreatTargetsFound = false;
  6755. FilterActors( targets, onlyThreatTargetsFound, true );
  6756.  
  6757. if ( IsCombatMusicEnabled() && targets.Size() > 0 && !onlyThreatTargetsFound && !IsThreat( targets[0], usePrecalcs ) )
  6758. {
  6759. targets.Clear();
  6760. }
  6761.  
  6762. coneHeading = 0.0f;
  6763. coneHalfAngleDot = 0.0f;
  6764. if ( ( orientationTarget == OT_Camera ) || ( orientationTarget == OT_CameraOffset ) )
  6765. {
  6766. if ( usePrecalcs )
  6767. {
  6768. coneHeading = targetingPrecalcs.cameraHeading;
  6769. }
  6770. else
  6771. {
  6772. coneHeading = theGame.GetGameCamera().GetHeading();
  6773. }
  6774. coneHalfAngleDot = 0.5f; // = CosF( Deg2Rad( 120.f * 0.5f ) ); - Just use calculator... why not? this is constant.
  6775. }
  6776. else
  6777. {
  6778. if ( IsSwimming() )
  6779. {
  6780. if ( usePrecalcs )
  6781. {
  6782. coneHeading = targetingPrecalcs.cameraHeading;
  6783. }
  6784. else
  6785. {
  6786. coneHeading = theGame.GetGameCamera().GetHeading();
  6787. }
  6788. coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) );
  6789. }
  6790. else if ( bLAxisReleased )
  6791. {
  6792. if( IsInCombatAction() )
  6793. {
  6794. coneHeading = GetCombatActionHeading();
  6795. }
  6796. else
  6797. {
  6798. if ( ShouldUsePCModeTargeting() )
  6799. coneHeading = theGame.GetGameCamera().GetHeading();
  6800. else
  6801. coneHeading = cachedRawPlayerHeading;
  6802. }
  6803.  
  6804. if ( IsInCombat() )
  6805. {
  6806. if ( ShouldUsePCModeTargeting() )
  6807. coneHalfAngleDot = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) )
  6808. else
  6809. coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) );
  6810. }
  6811. else
  6812. {
  6813. coneHalfAngleDot = -1.0f;
  6814. }
  6815. }
  6816. else
  6817. {
  6818. if( IsInCombatAction() )
  6819. {
  6820. coneHeading = GetCombatActionHeading();
  6821. }
  6822. else
  6823. {
  6824. if ( ShouldUsePCModeTargeting() )
  6825. coneHeading = theGame.GetGameCamera().GetHeading();
  6826. else
  6827. coneHeading = cachedRawPlayerHeading;
  6828. }
  6829.  
  6830. if ( ShouldUsePCModeTargeting() )
  6831. coneHalfAngleDot = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) )
  6832. else
  6833. coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) );
  6834. }
  6835.  
  6836. coneHeadingVector = VecFromHeading( coneHeading );
  6837. position = this.GetWorldPosition();
  6838.  
  6839. for ( i = targets.Size() - 1; i >= 0; i -= 1 )
  6840. {
  6841. if ( !targets[i] )
  6842. {
  6843. targets.EraseFast(i);
  6844. continue;
  6845. }
  6846.  
  6847. direction = VecNormalize2D( targets[i].GetWorldPosition() - position );
  6848.  
  6849. if ( VecDot2D( coneHeadingVector, direction ) < coneHalfAngleDot )
  6850. {
  6851. targets.EraseFast( i );
  6852. }
  6853. }
  6854. }
  6855.  
  6856. outHeadingVector = coneHeadingVector;
  6857. }
  6858.  
  6859. ///////////////////////////////////////////////////////////////////////////
  6860. // (new) targeting
  6861.  
  6862. function InitTargeting()
  6863. {
  6864. var consts : SR4PlayerTargetingConsts;
  6865.  
  6866. if ( !targeting )
  6867. {
  6868. targeting = new CR4PlayerTargeting in this;
  6869. }
  6870. if ( targeting )
  6871. {
  6872. consts.softLockDistance = this.softLockDist;
  6873. consts.softLockFrameSize = this.softLockFrameSize;
  6874. targeting.SetConsts( consts );
  6875. }
  6876. }
  6877.  
  6878. function PrepareTargetingIn( actionCheck : bool, bufferActionType : EBufferActionType, actionInput : bool )
  6879. {
  6880. var coneDist : float;
  6881.  
  6882. if ( actionCheck && bufferActionType == EBAT_ItemUse )
  6883. {
  6884. coneDist = findMoveTargetDist;
  6885. }
  6886. else if ( IsSwimming() )
  6887. {
  6888. coneDist = theGame.params.MAX_THROW_RANGE;
  6889. }
  6890. else if ( ( GetPlayerCombatStance() == PCS_AlertNear ) && ( ( playerMoveType == PMT_Walk ) || ( playerMoveType == PMT_Idle ) ) )
  6891. {
  6892. coneDist = softLockDist;
  6893. }
  6894. else
  6895. {
  6896. coneDist = findMoveTargetDist;
  6897. }
  6898.  
  6899. targetingIn.canFindTarget = this.bCanFindTarget;
  6900. targetingIn.playerHasBlockingBuffs = thePlayer.HasBuff( EET_Confusion ) || thePlayer.HasBuff( EET_Hypnotized ) || thePlayer.HasBuff( EET_Blindness ) || thePlayer.HasBuff( EET_WraithBlindness );
  6901. targetingIn.isHardLockedToTarget = this.IsHardLockEnabled();
  6902. targetingIn.isActorLockedToTarget = this.IsActorLockedToTarget();
  6903. targetingIn.isCameraLockedToTarget = this.IsCameraLockedToTarget();
  6904. targetingIn.actionCheck = actionCheck;
  6905. targetingIn.actionInput = actionInput;
  6906. targetingIn.isInCombatAction = this.IsInCombatAction();
  6907. targetingIn.isLAxisReleased = this.bLAxisReleased;
  6908. targetingIn.isLAxisReleasedAfterCounter = this.lAxisReleasedAfterCounter;
  6909. targetingIn.isLAxisReleasedAfterCounterNoCA = this.lAxisReleasedAfterCounterNoCA;
  6910. targetingIn.lastAxisInputIsMovement = this.lastAxisInputIsMovement;
  6911. targetingIn.isAiming = this.playerAiming.GetCurrentStateName() == 'Aiming';
  6912. targetingIn.isSwimming = this.IsSwimming();
  6913. targetingIn.isDiving = this.IsSwimming() && OnCheckDiving();
  6914. targetingIn.isThreatened = this.IsThreatened();
  6915. targetingIn.isCombatMusicEnabled = this.IsCombatMusicEnabled();
  6916. targetingIn.isPcModeEnabled = this.IsPCModeEnabled();
  6917. targetingIn.isInParryOrCounter = this.isInParryOrCounter;
  6918. targetingIn.shouldUsePcModeTargeting = this.ShouldUsePCModeTargeting();
  6919. targetingIn.bufferActionType = bufferActionType;
  6920. targetingIn.orientationTarget = this.GetOrientationTarget();
  6921. targetingIn.coneDist = coneDist; // computed few lines above
  6922. targetingIn.findMoveTargetDist = this.findMoveTargetDist;
  6923. targetingIn.cachedRawPlayerHeading = this.cachedRawPlayerHeading;
  6924. targetingIn.combatActionHeading = this.GetCombatActionHeading();
  6925. targetingIn.rawPlayerHeadingVector = VecFromHeading( this.rawPlayerHeading );
  6926. targetingIn.lookAtDirection = VecNormalize2D( this.GetLookAtPosition() - GetWorldPosition() );
  6927. targetingIn.moveTarget = this.moveTarget;
  6928. targetingIn.aimingTarget = this.playerAiming.GetAimedTarget();
  6929. targetingIn.displayTarget = (CActor)this.displayTarget;
  6930. targetingIn.finishableEnemies = this.finishableEnemiesList;
  6931. targetingIn.hostileEnemies = this.hostileEnemies;
  6932. targetingIn.defaultSelectionWeights = ProcessSelectionWeights();
  6933. }
  6934.  
  6935. function ResetTargetingOut()
  6936. {
  6937. targetingOut.target = NULL;
  6938. targetingOut.result = false;
  6939. targetingOut.confirmNewTarget = false;
  6940. targetingOut.forceDisableUpdatePosition = false;
  6941. }
  6942.  
  6943. function MakeFindTargetPrecalcs()
  6944. {
  6945. var mpac : CMovingPhysicalAgentComponent;
  6946.  
  6947. targetingPrecalcs.playerPosition = thePlayer.GetWorldPosition();
  6948. targetingPrecalcs.playerHeading = thePlayer.GetHeading();
  6949. targetingPrecalcs.playerHeadingVector = thePlayer.GetHeadingVector();
  6950. targetingPrecalcs.playerHeadingVector.Z = 0;
  6951. targetingPrecalcs.playerHeadingVector = VecNormalize2D( targetingPrecalcs.playerHeadingVector );
  6952.  
  6953. targetingPrecalcs.playerRadius = 0.5f;
  6954. mpac = (CMovingPhysicalAgentComponent)thePlayer.GetMovingAgentComponent();
  6955. if ( mpac )
  6956. {
  6957. targetingPrecalcs.playerRadius = mpac.GetCapsuleRadius();
  6958. }
  6959.  
  6960. targetingPrecalcs.cameraPosition = theCamera.GetCameraPosition();
  6961. targetingPrecalcs.cameraDirection = theCamera.GetCameraDirection();
  6962. targetingPrecalcs.cameraHeadingVector = targetingPrecalcs.cameraDirection;
  6963. targetingPrecalcs.cameraHeadingVector.Z = 0;
  6964. targetingPrecalcs.cameraHeadingVector = VecNormalize2D( targetingPrecalcs.cameraHeadingVector );
  6965. targetingPrecalcs.cameraHeading = VecHeading( targetingPrecalcs.cameraHeadingVector );
  6966. }
  6967.  
  6968. public function GetForceDisableUpdatePosition() : bool
  6969. {
  6970. return targetingOut.forceDisableUpdatePosition;
  6971. }
  6972.  
  6973. public function SetUseNativeTargeting( use : bool )
  6974. {
  6975. useNativeTargeting = use;
  6976. }
  6977.  
  6978. protected function FindTarget( optional actionCheck : bool, optional action : EBufferActionType, optional actionInput : bool ) : CActor
  6979. {
  6980. if ( IsCombatMusicEnabled() && !IsInCombat() && reachableEnemyWasTooFar )
  6981. {
  6982. playerMode.UpdateCombatMode();
  6983. }
  6984.  
  6985. PrepareTargetingIn( actionCheck, action, actionInput );
  6986. if ( useNativeTargeting )
  6987. {
  6988. targeting.BeginFindTarget( targetingIn );
  6989. targeting.FindTarget();
  6990. targeting.EndFindTarget( targetingOut );
  6991. }
  6992. else
  6993. {
  6994. UpdateVisibleActors();
  6995. MakeFindTargetPrecalcs();
  6996. ResetTargetingOut();
  6997. FindTarget_Scripted();
  6998. }
  6999. if ( targetingOut.result )
  7000. {
  7001. if ( targetingOut.confirmNewTarget )
  7002. {
  7003. ConfirmNewTarget( targetingOut.target );
  7004. }
  7005. return targetingOut.target;
  7006. }
  7007. return NULL;
  7008. }
  7009.  
  7010. protected function FindTarget_Scripted()
  7011. {
  7012. var currentTarget : CActor;
  7013. var newTarget : CActor;
  7014. var selectedTarget : CActor;
  7015. var displayTargetActor : CActor;
  7016. var playerPosition : Vector;
  7017. var playerHeadingVector : Vector;
  7018. var cameraPosition : Vector;
  7019. var cameraHeadingVector : Vector;
  7020. var selectionHeadingVector : Vector;
  7021. var targetingInfo : STargetingInfo;
  7022. var selectionWeights : STargetSelectionWeights;
  7023. var targets : array< CActor >;
  7024. var isMoveTargetTargetable : bool;
  7025. var targetChangeFromActionInput : bool;
  7026. var retainCurrentTarget : bool;
  7027.  
  7028. // caching data
  7029.  
  7030. playerPosition = this.GetWorldPosition();
  7031. playerHeadingVector = targetingPrecalcs.playerHeadingVector;
  7032. cameraPosition = theCamera.GetCameraPosition();
  7033. cameraHeadingVector = targetingPrecalcs.cameraHeadingVector;
  7034.  
  7035. currentTarget = GetTarget();
  7036. if ( currentTarget )
  7037. {
  7038. if ( IsHardLockEnabled() && currentTarget.IsAlive() && !currentTarget.IsKnockedUnconscious() )
  7039. {
  7040. if ( VecDistanceSquared( playerPosition, currentTarget.GetWorldPosition() ) > 50.f * 50.0f )
  7041. {
  7042. HardLockToTarget( false );
  7043. }
  7044. else
  7045. {
  7046. targetingOut.target = currentTarget;
  7047. targetingOut.result = true;
  7048. return;
  7049. }
  7050. }
  7051. GetVisualDebug().AddSphere('target', 1.0f, currentTarget.GetWorldPosition(), true, Color( 255, 255, 0 ), 1.0f );
  7052. }
  7053.  
  7054. if ( bCanFindTarget && !IsActorLockedToTarget() )
  7055. {
  7056. if ( !targetingIn.playerHasBlockingBuffs )
  7057. {
  7058. InternalFindTargetsInCone( targets, selectionHeadingVector, true );
  7059. }
  7060.  
  7061. targetingInfo.source = this;
  7062. targetingInfo.canBeTargetedCheck = true;
  7063. targetingInfo.coneCheck = false;
  7064. targetingInfo.coneHalfAngleCos = 1.0f;
  7065. targetingInfo.coneDist = targetingIn.coneDist;
  7066. targetingInfo.distCheck = true;
  7067. targetingInfo.invisibleCheck = true;
  7068. targetingInfo.navMeshCheck = false; //true;
  7069.  
  7070. if ( ShouldUsePCModeTargeting() )
  7071. targetingInfo.inFrameCheck = false;
  7072. else
  7073. targetingInfo.inFrameCheck = true;
  7074.  
  7075. targetingInfo.frameScaleX = 1.0f;
  7076. targetingInfo.frameScaleY = 1.0f;
  7077. targetingInfo.knockDownCheck = false;
  7078. targetingInfo.knockDownCheckDist = 1.5f;
  7079. targetingInfo.rsHeadingCheck = false;
  7080. targetingInfo.rsHeadingLimitCos = 1.0f;
  7081.  
  7082. if ( currentTarget )
  7083. {
  7084. targetingInfo.targetEntity = currentTarget;
  7085. if ( !IsEntityTargetable( targetingInfo, true ) )
  7086. {
  7087. currentTarget = NULL;
  7088. }
  7089. if ( currentTarget && !CanBeTargetedIfSwimming( currentTarget, true ) )
  7090. {
  7091. currentTarget = NULL;
  7092. }
  7093. }
  7094.  
  7095. isMoveTargetTargetable = false;
  7096. if ( moveTarget )
  7097. {
  7098. if ( CanBeTargetedIfSwimming( moveTarget, true ) )
  7099. {
  7100. targetingInfo.targetEntity = moveTarget;
  7101. targetingInfo.coneDist = findMoveTargetDist;
  7102. targetingInfo.inFrameCheck = false;
  7103. if ( IsEntityTargetable( targetingInfo, true ) )
  7104. {
  7105. isMoveTargetTargetable = true;
  7106. }
  7107. }
  7108. }
  7109.  
  7110. // checking "standard" cone dist again
  7111. targetingInfo.coneDist = targetingIn.coneDist;
  7112.  
  7113. if ( !targetingIn.playerHasBlockingBuffs )
  7114. {
  7115. RemoveNonTargetable( targets, targetingInfo, selectionHeadingVector );
  7116. }
  7117.  
  7118. newTarget = NULL;
  7119. if ( this.playerAiming.GetCurrentStateName() == 'Aiming' )
  7120. {
  7121. newTarget = this.playerAiming.GetAimedTarget();
  7122. if ( !newTarget )
  7123. {
  7124. selectionWeights.angleWeight = 1.f;
  7125. selectionWeights.distanceWeight = 0.f;
  7126. selectionWeights.distanceRingWeight = 0.f;
  7127.  
  7128. selectedTarget = SelectTarget( targets, false, cameraPosition, cameraHeadingVector, selectionWeights, true );
  7129. newTarget = selectedTarget;
  7130. }
  7131. }
  7132. else if ( IsSwimming() )
  7133. {
  7134. selectionWeights.angleWeight = 0.9f;
  7135. selectionWeights.distanceWeight = 0.1f;
  7136. selectionWeights.distanceRingWeight = 0.f;
  7137.  
  7138. selectedTarget = SelectTarget( targets, true, cameraPosition, cameraHeadingVector, selectionWeights, true );
  7139. newTarget = selectedTarget;
  7140. }
  7141. else if ( IsThreatened() )
  7142. {
  7143. // Change locked enemy when the current one becomes invisible
  7144. if ( IsCameraLockedToTarget() )
  7145. {
  7146. if ( currentTarget && !currentTarget.GetGameplayVisibility() )
  7147. {
  7148. ForceSelectLockTarget();
  7149. }
  7150. }
  7151.  
  7152. displayTargetActor = (CActor)displayTarget;
  7153. selectedTarget = SelectTarget( targets, true, playerPosition, selectionHeadingVector, targetingIn.defaultSelectionWeights, true );
  7154.  
  7155. if ( !selectedTarget )
  7156. {
  7157. targetingOut.forceDisableUpdatePosition = true;
  7158. }
  7159.  
  7160. targetChangeFromActionInput = targetingIn.actionInput && !lAxisReleasedAfterCounter;
  7161. if ( selectedTarget &&
  7162. ( !IsThreat( currentTarget, true ) || ShouldUsePCModeTargeting() || ( !IsInCombatAction() && !lAxisReleasedAfterCounterNoCA ) || targetChangeFromActionInput ) )
  7163. {
  7164. newTarget = selectedTarget;
  7165. }
  7166. else if ( displayTargetActor &&
  7167. ( ( bLAxisReleased && !ShouldUsePCModeTargeting() )|| IsInCombatAction() ) &&
  7168. ( displayTargetActor.IsAlive() || finishableEnemiesList.Contains( displayTargetActor ) ) &&
  7169. displayTargetActor.GetGameplayVisibility() &&
  7170. ( IsEnemyVisible( displayTargetActor ) || finishableEnemiesList.Contains( displayTargetActor ) ) &&
  7171. this.CanBeTargetedIfSwimming( displayTargetActor, true ) &&
  7172. IsThreat( displayTargetActor, true ) &&
  7173. WasVisibleInScaledFrame( displayTargetActor, 1.f, 1.f ) )
  7174. {
  7175. newTarget = displayTargetActor;
  7176. }
  7177. // target closest enemy immediately when transitioning from running/sprint to walk/idle,
  7178. // 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
  7179. else if ( moveTarget &&
  7180. isMoveTargetTargetable &&
  7181. ( !IsInCombatAction() || isInParryOrCounter || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Roll ) )
  7182. {
  7183. newTarget = moveTarget;
  7184. }
  7185. else
  7186. {
  7187. newTarget = NULL;
  7188. }
  7189. }
  7190. else
  7191. {
  7192. retainCurrentTarget = false;
  7193. if ( lAxisReleasedAfterCounterNoCA )
  7194. {
  7195. if ( lastAxisInputIsMovement && !this.IsSwimming())
  7196. {
  7197. selectionWeights.angleWeight = 0.375f;
  7198. selectionWeights.distanceWeight = 0.275f;
  7199. selectionWeights.distanceRingWeight = 0.35f;
  7200. selectedTarget = SelectTarget( targets, false, playerPosition, playerHeadingVector, selectionWeights, true );
  7201.  
  7202. if ( currentTarget != selectedTarget )
  7203. {
  7204. targetingInfo.targetEntity = currentTarget;
  7205. if ( IsEntityTargetable( targetingInfo, true ) && currentTarget.IsAlive() )
  7206. {
  7207. retainCurrentTarget = true;
  7208. }
  7209. }
  7210. }
  7211. else
  7212. {
  7213. selectionWeights.angleWeight = 0.75f;
  7214. selectionWeights.distanceWeight = 0.125f;
  7215. selectionWeights.distanceRingWeight = 0.125f;
  7216. selectedTarget = SelectTarget( targets, false, cameraPosition, cameraHeadingVector, selectionWeights, true );
  7217. }
  7218. }
  7219. else
  7220. {
  7221. selectionWeights.angleWeight = 0.6f;
  7222. selectionWeights.distanceWeight = 0.4f;
  7223. selectionWeights.distanceRingWeight = 0.f;
  7224. selectedTarget = SelectTarget( targets, true, playerPosition, targetingIn.rawPlayerHeadingVector, selectionWeights, true );
  7225. }
  7226.  
  7227. if ( retainCurrentTarget )
  7228. {
  7229. newTarget = currentTarget;
  7230. }
  7231. else if ( IsInCombatAction() && GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.0f )
  7232. {
  7233. newTarget = moveTarget;
  7234. }
  7235. else if ( selectedTarget )
  7236. {
  7237. newTarget = selectedTarget;
  7238. }
  7239. else
  7240. {
  7241. newTarget = NULL;
  7242. }
  7243. }
  7244.  
  7245. targetingOut.confirmNewTarget = true;
  7246. }
  7247. else
  7248. {
  7249. newTarget = NULL;
  7250. }
  7251.  
  7252. targetingOut.result = true;
  7253. targetingOut.target = newTarget;
  7254. }
  7255.  
  7256. function UpdateVisibleActors()
  7257. {
  7258. var i : int;
  7259. var now : float;
  7260.  
  7261. now = theGame.GetEngineTimeAsSeconds();
  7262. for ( i = visibleActors.Size() - 1; i >= 0; i-=1 )
  7263. {
  7264. // wasn't visible for more than 1 second
  7265. if ( ( now - visibleActorsTime[i] ) > 1.0f )
  7266. {
  7267. visibleActors.EraseFast( i );
  7268. visibleActorsTime.EraseFast( i );
  7269. }
  7270. }
  7271. }
  7272.  
  7273. function RemoveNonTargetable( out targets : array< CActor >, out info : STargetingInfo, selectionHeadingVector : Vector )
  7274. {
  7275. var i : int;
  7276. var cameraPosition : Vector;
  7277. var cameraDirection : Vector;
  7278. var nonCombatCheck : bool;
  7279. var playerToCamPlaneDist : float;
  7280. var targetToCamPlaneDist : float;
  7281.  
  7282. if ( targets.Size() == 0 )
  7283. {
  7284. return;
  7285. }
  7286.  
  7287. nonCombatCheck = bLAxisReleased && !IsInCombat();
  7288.  
  7289. // first, let's prepare targeting info (so that we don't need to do it in each loop step)
  7290. if ( nonCombatCheck )
  7291. {
  7292. info.coneHeadingVector = targetingPrecalcs.playerHeadingVector;
  7293. if ( lastAxisInputIsMovement )
  7294. {
  7295. info.coneHeadingVector = selectionHeadingVector;
  7296. info.invisibleCheck = false;
  7297. info.coneCheck = true;
  7298. info.coneHalfAngleCos = 0.76604444311f; // = CosF( Deg2Rad( 80.0f * 0.5f ) )
  7299. }
  7300. else
  7301. {
  7302. info.invisibleCheck = false;
  7303. info.frameScaleX = 0.9f;
  7304. info.frameScaleY = 0.9f;
  7305. }
  7306. }
  7307. else
  7308. {
  7309. info.coneHeadingVector = Vector( 0.0f, 0.0f, 0.0f );
  7310.  
  7311. //MS: ConeCheck is false because it's already been filtered by InternalFindTargetsInCone
  7312. if ( IsInCombat() )
  7313. {
  7314. info.inFrameCheck = false;
  7315. }
  7316. else
  7317. {
  7318. if ( !bLAxisReleased )
  7319. {
  7320. info.coneCheck = true;
  7321.  
  7322. if ( this.IsSwimming() )
  7323. info.coneHalfAngleCos = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) )
  7324. else
  7325. info.coneHalfAngleCos = 0.86602540378f; // = CosF( Deg2Rad( 60.0f * 0.5f ) )
  7326.  
  7327. info.coneHeadingVector = targetingIn.rawPlayerHeadingVector;
  7328. }
  7329. }
  7330. }
  7331.  
  7332. cameraPosition = theCamera.GetCameraPosition();
  7333. cameraDirection = targetingPrecalcs.cameraDirection;
  7334. playerToCamPlaneDist = VecDot2D( cameraDirection, this.GetWorldPosition() - cameraPosition );
  7335.  
  7336. // then, using prepared info let's filter out invalid targets
  7337. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  7338. {
  7339. info.targetEntity = targets[i];
  7340.  
  7341. if ( !CanBeTargetedIfSwimming( targets[i], true ) )
  7342. {
  7343. targets.EraseFast( i );
  7344. }
  7345. else if ( !IsEntityTargetable( info, true ) )
  7346. {
  7347. targets.EraseFast( i );
  7348. }
  7349. else
  7350. {
  7351. if ( nonCombatCheck && !lastAxisInputIsMovement )
  7352. {
  7353. // removing targets between camera and player
  7354. targetToCamPlaneDist = VecDot2D( cameraDirection, targets[i].GetWorldPosition() - cameraPosition );
  7355. if ( targetToCamPlaneDist < playerToCamPlaneDist )
  7356. {
  7357. targets.EraseFast( i );
  7358. }
  7359. }
  7360. }
  7361. }
  7362. }
  7363.  
  7364. var combatModeColor : Color;
  7365. public function CombatModeDebug()
  7366. {
  7367. var visualDebug : CVisualDebug = GetVisualDebug();
  7368.  
  7369. var naviQueryMsg : string;
  7370. var naviQueryMsg1 : string;
  7371. var naviQueryMsg2 : string;
  7372.  
  7373. var navSnapMsg : string;
  7374. var i : int;
  7375.  
  7376. if ( IsCombatMusicEnabled() )
  7377. visualDebug.AddText( 'CombatMusic', "CombatMusic : On", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.7f ), true, , Color( 255, 255, 255 ) );
  7378. else
  7379. visualDebug.AddText( 'CombatMusic', "CombatMusic : Off", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.7f ), true, , Color( 0, 0, 0 ) );
  7380.  
  7381. if ( GetPlayerMode().GetForceCombatMode() )
  7382. visualDebug.AddText( 'ForcedCombatMode', "ForcedCombatMode : TRUE", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.6f ), true, , Color( 255, 255, 255 ) );
  7383. else
  7384. visualDebug.AddText( 'ForcedCombatMode', "ForcedCombatMode : FALSE", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.6f ), true, , Color( 0, 0, 0 ) );
  7385.  
  7386.  
  7387. if ( IsThreatened() )
  7388. {
  7389. if ( IsInCombat() )
  7390. visualDebug.AddText( 'CombatMode', "CombatMode : AlertNear/Far", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 255, 0, 0 ) );
  7391. else
  7392. visualDebug.AddText( 'CombatMode', "CombatMode : CombatExploration", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 255, 255, 0 ) );
  7393. }
  7394. else
  7395. visualDebug.AddText( 'CombatMode', "CombatMode : NormalExploration", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 0, 255, 0 ) );
  7396.  
  7397. visualDebug.AddText( 'NaviQuery', naviQueryMsg, combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7398. visualDebug.AddText( 'NaviQuery1', naviQueryMsg1, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7399. visualDebug.AddText( 'NaviQuery2', naviQueryMsg2, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7400.  
  7401. if ( isInCombatReason == 0 )
  7402. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : ", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 125, 125, 125 ) );
  7403. else if ( isInCombatReason == 1 )
  7404. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : Geralt CAN pathfind to NPC", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) );
  7405. else if ( isInCombatReason == 2 )
  7406. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : An NPC is flying or ranged", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) );
  7407. else if ( isInCombatReason == 2 )
  7408. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : Forced Combat Mode", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) );
  7409.  
  7410. if ( reachableEnemyWasTooFar )
  7411. {
  7412. combatModeColor.Red = 255;
  7413. combatModeColor.Green = 255;
  7414. combatModeColor.Blue = 0;
  7415. }
  7416. else
  7417. {
  7418. combatModeColor.Red = 0;
  7419. combatModeColor.Green = 255;
  7420. combatModeColor.Blue = 0;
  7421. }
  7422.  
  7423. if ( IsThreatened() )
  7424. {
  7425. switch ( navQuery.GetLastOutput( 2.0 ) )
  7426. {
  7427. case EAsyncTastResult_Failure:
  7428. {
  7429. if ( this.playerMode.GetForceCombatMode() )
  7430. {
  7431. if ( isSnappedToNavMesh )
  7432. {
  7433. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7434. visualDebug.AddText( 'NaviQuery1', "Naviquery : Snapped So no need for query", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7435. visualDebug.AddText( 'NaviQuery2', "Naviquery : Snapped So no need for query", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7436. }
  7437. else
  7438. {
  7439. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7440. visualDebug.AddText( 'NaviQuery1', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7441. visualDebug.AddText( 'NaviQuery2', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7442. }
  7443. }
  7444. else
  7445. {
  7446. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7447. visualDebug.AddText( 'NaviQuery1', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7448. visualDebug.AddText( 'NaviQuery2', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7449. }
  7450. break;
  7451. }
  7452. case EAsyncTastResult_Success:
  7453. {
  7454. visualDebug.AddText( 'NaviQuery', combatModeEnt.GetName(), combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7455. visualDebug.AddText( 'NaviQuery1', "Naviquery : Success (navDist: " + navDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7456. visualDebug.AddText( 'NaviQuery2', "Naviquery : Success (directDist: " + directDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7457. break;
  7458. }
  7459. case EAsyncTastResult_Pending:
  7460. {
  7461. visualDebug.AddText( 'NaviQuery', combatModeEnt.GetName(), combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7462. visualDebug.AddText( 'NaviQuery1', "Naviquery : Pending (navDist: " + navDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7463. visualDebug.AddText( 'NaviQuery2', "Naviquery : Pending (directDist: " + directDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7464. break;
  7465. }
  7466. case EAsyncTastResult_Invalidated:
  7467. {
  7468. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7469. visualDebug.AddText( 'NaviQuery1', "Naviquery : Invalidated", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7470. visualDebug.AddText( 'NaviQuery2', "Naviquery : Invalidated", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7471. break;
  7472. }
  7473. }
  7474. }
  7475. else
  7476. {
  7477. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7478. visualDebug.AddText( 'NaviQuery1', "", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7479. visualDebug.AddText( 'NaviQuery2', "", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7480. }
  7481.  
  7482. if ( navMeshSnapInfoStack.Size() > 0 )
  7483. {
  7484. for ( i = navMeshSnapInfoStack.Size()-1; i >= 0; i -= 1 )
  7485. {
  7486. navSnapMsg = navSnapMsg + navMeshSnapInfoStack[i] + " ";
  7487. }
  7488.  
  7489. visualDebug.AddText( 'NavMeshSnap', "NavMeshSnap: Enabled, Sources : " + navSnapMsg, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.1f ), true, , Color( 255, 255, 255 ) );
  7490. }
  7491. else
  7492. visualDebug.AddText( 'NavMeshSnap', "NavMeshSnap: Disabled" , thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.1f ), true, , Color( 0, 0, 0 ) );
  7493.  
  7494. }
  7495.  
  7496. function IsCombatMusicEnabled() : bool
  7497. {
  7498. if ( theSound.GetCurrentGameState() == ESGS_UnderwaterCombat
  7499. || theSound.GetCurrentGameState() == ESGS_Combat
  7500. || theSound.GetCurrentGameState() == ESGS_CombatMonsterHunt
  7501. || theSound.GetCurrentGameState() == ESGS_FocusUnderwaterCombat )
  7502. return true;
  7503. else
  7504. return false;
  7505. }
  7506.  
  7507. function IsSoundStateCombatMusic( gameState : ESoundGameState ) : bool
  7508. {
  7509. if ( gameState == ESGS_UnderwaterCombat
  7510. || gameState == ESGS_Combat
  7511. || gameState == ESGS_CombatMonsterHunt
  7512. || gameState == ESGS_FocusUnderwaterCombat )
  7513. return true;
  7514. else
  7515. return false;
  7516. }
  7517.  
  7518. private function ConfirmNewTarget( actorToConfirm : CActor )
  7519. {
  7520. var leftJoyRotLimit : float = 1.f;
  7521.  
  7522. var target : CActor;
  7523.  
  7524. target = GetTarget();
  7525.  
  7526. //MS: When Player pushes stick in npcs direction, he needs to push the stick beyond leftJoyRotLimit in order to change targets
  7527. if ( !target
  7528. || !moveTarget
  7529. || ( target && ( !IsThreat( target ) || !target.IsAlive() ) )
  7530. || VecLength( rawLeftJoyVec ) < 0.7f
  7531. || ( 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 ) ) ) )
  7532. || ( !IsInCombatAction() && ( !rangedWeapon || ( rangedWeapon.GetCurrentStateName() != 'State_WeaponHolster' ) ) ))//&& rangedWeapon.GetCurrentStateName() != 'State_WeaponShoot' ) && rangedWeapon.GetCurrentStateName() != 'State_WeaponAim' ) )
  7533. {
  7534. SetPrevRawLeftJoyRot();
  7535.  
  7536. if ( actorToConfirm != target )
  7537. {
  7538. SetTarget( actorToConfirm );
  7539. }
  7540. }
  7541. }
  7542.  
  7543. protected function SelectTarget( targets : array< CActor >, useVisibilityCheck : bool, sourcePosition : Vector, headingVector : Vector, selectionWeights : STargetSelectionWeights, optional usePrecalcs : bool ) : CActor
  7544. {
  7545. var i : int;
  7546. var target : CActor;
  7547. var selectedTarget : CActor;
  7548. var currentTarget : CActor;
  7549. var playerPosition : Vector;
  7550. var distanceToPlayer : float;
  7551. var priority : float;
  7552. var maxPriority : float;
  7553. var now : float;
  7554. var remove : bool;
  7555. var visibleActorIndex : int;
  7556.  
  7557. if ( useVisibilityCheck )
  7558. {
  7559. currentTarget = this.GetTarget();
  7560. playerPosition = this.GetWorldPosition();
  7561. now = theGame.GetEngineTimeAsSeconds();
  7562.  
  7563. for ( i = targets.Size() - 1; i >= 0; i-=1 )
  7564. {
  7565. target = targets[ i ];
  7566. if ( target != currentTarget && ( !IsPCModeEnabled() && !WasVisibleInScaledFrame( target, softLockFrameSize, softLockFrameSize ) ) )
  7567. {
  7568. remove = true;
  7569. visibleActorIndex = visibleActors.FindFirst( target );
  7570. if ( visibleActorIndex != -1 )
  7571. {
  7572. if ( usePrecalcs )
  7573. {
  7574. distanceToPlayer = Distance2DBetweenCapsuleAndPoint( target, this ) - targetingPrecalcs.playerRadius;
  7575. }
  7576. else
  7577. {
  7578. distanceToPlayer = Distance2DBetweenCapsules( this, target );
  7579. }
  7580. // if within soft lock distance and soft lock visibility duration -> don't remove yet
  7581. if ( distanceToPlayer < this.softLockDist && ( now - visibleActorsTime[ i ] ) < 1.0f )
  7582. {
  7583. remove = false;
  7584. }
  7585. }
  7586. if ( remove )
  7587. {
  7588. targets.EraseFast( i );
  7589. }
  7590. }
  7591. else
  7592. {
  7593. visibleActorIndex = visibleActors.FindFirst( target );
  7594. if ( visibleActorIndex == -1 )
  7595. {
  7596. visibleActors.PushBack( target );
  7597. visibleActorsTime.PushBack( now );
  7598. }
  7599. else
  7600. {
  7601. visibleActorsTime[ visibleActorIndex ] = now;
  7602. }
  7603. }
  7604. }
  7605. }
  7606.  
  7607. selectedTarget = NULL;
  7608. maxPriority = -1.0f;
  7609. for( i = targets.Size() - 1; i >= 0; i-=1 )
  7610. {
  7611. priority = CalcSelectionPriority( targets[ i ], selectionWeights, sourcePosition, headingVector );
  7612. if ( priority > maxPriority )
  7613. {
  7614. maxPriority = priority;
  7615. selectedTarget = targets[ i ];
  7616. }
  7617. }
  7618.  
  7619. //LogChannel( 'selectedTarget', selectedTarget );
  7620. return selectedTarget;
  7621. }
  7622.  
  7623. function Distance2DBetweenCapsuleAndPoint( actor : CActor, entity : CEntity ) : float
  7624. {
  7625. var distance : float;
  7626. var mpac : CMovingPhysicalAgentComponent;
  7627.  
  7628. distance = VecDistance2D( actor.GetWorldPosition(), entity.GetWorldPosition() );
  7629.  
  7630. mpac = (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent();
  7631. if ( mpac )
  7632. {
  7633. distance -= mpac.GetCapsuleRadius();
  7634. }
  7635.  
  7636. return distance;
  7637. }
  7638.  
  7639.  
  7640. function Distance2DBetweenCapsules( actor1 : CActor, actor2 : CActor ) : float
  7641. {
  7642. var distance : float;
  7643. var mpac : CMovingPhysicalAgentComponent;
  7644.  
  7645. distance = VecDistance2D( actor1.GetWorldPosition(), actor2.GetWorldPosition() );
  7646.  
  7647. mpac = (CMovingPhysicalAgentComponent)actor1.GetMovingAgentComponent();
  7648. if ( mpac )
  7649. {
  7650. distance -= mpac.GetCapsuleRadius();
  7651. }
  7652.  
  7653. mpac = (CMovingPhysicalAgentComponent)actor2.GetMovingAgentComponent();
  7654. if ( mpac )
  7655. {
  7656. distance -= mpac.GetCapsuleRadius();
  7657. }
  7658.  
  7659. return distance;
  7660. }
  7661.  
  7662. protected function ProcessSelectionWeights() : STargetSelectionWeights
  7663. {
  7664. var selectionWeights : STargetSelectionWeights;
  7665.  
  7666. if ( ShouldUsePCModeTargeting() )
  7667. {
  7668. selectionWeights.angleWeight = 0.75f;
  7669. selectionWeights.distanceWeight = 0.25f;
  7670. selectionWeights.distanceRingWeight = 0.f;
  7671. return selectionWeights;
  7672. }
  7673.  
  7674. if ( IsInCombatAction() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Roll ) )
  7675. {
  7676. selectionWeights.angleWeight = 0.575f;
  7677. selectionWeights.distanceWeight = 0.175f;
  7678. selectionWeights.distanceRingWeight = 0.25f;
  7679. }
  7680. if ( !lAxisReleasedAfterCounter || IsInCombatAction() ) // !bLAxisReleased ||
  7681. {
  7682. if ( theInput.GetActionValue( 'ThrowItem' ) == 1.f || ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) )
  7683. {
  7684. selectionWeights.angleWeight = 1.f;
  7685. selectionWeights.distanceWeight = 0.f;
  7686. selectionWeights.distanceRingWeight = 0.f;
  7687. }
  7688. else if ( !lAxisReleasedAfterCounter ) // !bLAxisReleased )
  7689. {
  7690. selectionWeights.angleWeight = 0.55f;//0.75f;
  7691. selectionWeights.distanceWeight = 0.45f;//0.25f;
  7692. selectionWeights.distanceRingWeight = 0.f;//0.3f;
  7693. }
  7694. else
  7695. {
  7696. selectionWeights.angleWeight = 0.75f;
  7697. selectionWeights.distanceWeight = 0.25f;
  7698. selectionWeights.distanceRingWeight = 0.f;//0.3f;
  7699. }
  7700. }
  7701. else if( !IsCurrentSignChanneled() )
  7702. {
  7703. selectionWeights.angleWeight = 0.35f;
  7704. selectionWeights.distanceWeight = 0.65f;
  7705. selectionWeights.distanceRingWeight = 0.f;
  7706. }
  7707. else
  7708. {
  7709. selectionWeights.angleWeight = 0.275f;
  7710. selectionWeights.distanceWeight = 0.375f;
  7711. selectionWeights.distanceRingWeight = 0.35f;
  7712. }
  7713.  
  7714. return selectionWeights;
  7715. }
  7716.  
  7717. protected function CalcSelectionPriority( target : CEntity, selectionWeights : STargetSelectionWeights, sourcePosition : Vector, headingVector : Vector ) : float
  7718. {
  7719. var sourceToTarget : Vector;
  7720. var sourceToTargetDist : float;
  7721. var sourceToTargetAngleDiff : float;
  7722. var selectionPriority : float;
  7723.  
  7724. sourceToTarget = target.GetWorldPosition() - sourcePosition;
  7725. sourceToTargetDist = VecLength2D( sourceToTarget );
  7726. // normalize2D sourcetoTarget
  7727. if ( sourceToTargetDist < 0.0001f )
  7728. {
  7729. sourceToTarget = Vector( 0.0f, 0.0f, 0.0f );
  7730. }
  7731. else
  7732. {
  7733. sourceToTarget *= ( 1.0f / sourceToTargetDist );
  7734. }
  7735. sourceToTargetAngleDiff = AbsF( Rad2Deg( AcosF( VecDot2D( sourceToTarget, headingVector ) ) ) );
  7736.  
  7737. selectionPriority = ( selectionWeights.angleWeight * ( ( 180 - sourceToTargetAngleDiff ) / 180 ) );
  7738. selectionPriority += selectionWeights.distanceWeight * ( ( softLockDist - sourceToTargetDist ) / softLockDist );
  7739.  
  7740. if ( sourceToTargetDist > 0.f && sourceToTargetDist <= 6.f )
  7741. {
  7742. selectionPriority += selectionWeights.distanceRingWeight * 1.0f;
  7743. }
  7744. else if ( sourceToTargetDist > 6.f && sourceToTargetDist <= softLockDist )
  7745. {
  7746. selectionPriority += selectionWeights.distanceRingWeight * 0.4f;
  7747. }
  7748.  
  7749. return selectionPriority;
  7750. }
  7751.  
  7752. protected function SetTarget( targetActor : CActor, optional forceSetTarget : bool )
  7753. {
  7754. var playerToTargetDistance : float;
  7755. var target : CActor;
  7756. var allow : bool;
  7757.  
  7758. target = GetTarget();
  7759.  
  7760. if ( !IsInNonGameplayCutscene() )
  7761. allow = true;
  7762.  
  7763. if ( allow )
  7764. {
  7765. if ( targetActor )
  7766. {
  7767. if ( ( targetActor.IsAlive() && !targetActor.IsKnockedUnconscious() ) || finishableEnemiesList.Contains( targetActor ) )
  7768. allow = true;
  7769. else
  7770. allow = false;
  7771. }
  7772. else
  7773. allow = true;
  7774. }
  7775.  
  7776. if ( forceSetTarget )
  7777. allow = true;
  7778.  
  7779. if ( allow && target != targetActor )
  7780. allow = true;
  7781. else
  7782. allow = false;
  7783.  
  7784. if ( allow )
  7785. {
  7786. SetPlayerTarget( targetActor );
  7787.  
  7788. //playerToTargetDistance = VecDistance( GetWorldPosition(), targetActor.GetNearestPointInBothPersonalSpaces( GetWorldPosition() ) );
  7789. //LogChannel( 'Targeting', "selection " + playerToTargetDistance );
  7790. }
  7791. }
  7792.  
  7793. /*
  7794. protected function SetTarget( targetActor : CActor, optional forceSetTarget : bool )
  7795. {
  7796. var playerToTargetDistance : float;
  7797. var target : CActor;
  7798. //var gec : CGameplayEffectsComponent;
  7799.  
  7800.  
  7801. if ( !IsInNonGameplayCutscene()
  7802. && ( ( ( !targetActor || ( ( targetActor.IsAlive() || finishableEnemiesList.Contains( targetActor ) ) && !targetActor.IsKnockedUnconscious() ) ) && !IsActorLockedToTarget() ) || forceSetTarget ) )
  7803. {
  7804. target = GetTarget();
  7805.  
  7806. if ( target != targetActor )
  7807. {
  7808. if( target )
  7809. {
  7810. target.StopEffect( 'select_character' );
  7811. //gec = GetGameplayEffectsComponent( target );
  7812. //if(gec)
  7813. // gec.SetGameplayEffectFlag( EGEF_OutlineTarget, 0 );
  7814. }
  7815.  
  7816. SetPlayerTarget( targetActor );
  7817. target = targetActor;
  7818.  
  7819. if(target)
  7820. {
  7821. playerToTargetDistance = VecDistance( GetWorldPosition(), target.GetNearestPointInBothPersonalSpaces( GetWorldPosition() ) );
  7822. }
  7823.  
  7824. //LogChannel( 'Targeting', "selection " + playerToTargetDistance );
  7825. }
  7826. }
  7827. }
  7828. */
  7829. public function SetSlideTarget( actor : CGameplayEntity )
  7830. {
  7831. //if ( slideTarget != actor && slideTarget )
  7832. // EnableCloseCombatCharacterRadius( false );
  7833.  
  7834. slideTarget = actor;
  7835.  
  7836. if ( slideTarget )
  7837. SetPlayerCombatTarget((CActor)slideTarget);
  7838. else
  7839. Log( "slideTarget = NULL" );
  7840.  
  7841. if ( slideTarget == nonActorTarget )
  7842. UpdateDisplayTarget( true, true );
  7843. else
  7844. UpdateDisplayTarget();
  7845.  
  7846. ConfirmDisplayTargetTimer(0.f);
  7847. }
  7848.  
  7849. event OnForceSelectLockTarget()
  7850. {
  7851. ForceSelectLockTarget();
  7852. }
  7853.  
  7854. private function ForceSelectLockTarget()
  7855. {
  7856. var newMoveTarget : CActor;
  7857. var target : CActor;
  7858.  
  7859. newMoveTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, 90 );
  7860.  
  7861. if ( !newMoveTarget )
  7862. newMoveTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, -90 );
  7863.  
  7864. if ( newMoveTarget )
  7865. {
  7866. thePlayer.ProcessLockTarget( newMoveTarget );
  7867.  
  7868. target = GetTarget();
  7869. if ( target )
  7870. {
  7871. thePlayer.SetSlideTarget( target );
  7872.  
  7873. if ( IsHardLockEnabled() )
  7874. thePlayer.HardLockToTarget( true );
  7875. }
  7876. }
  7877. else
  7878. {
  7879. thePlayer.HardLockToTarget( false );
  7880. }
  7881. }
  7882.  
  7883. public function SetFinisherVictim( actor : CActor )
  7884. {
  7885. finisherVictim = actor;
  7886. }
  7887.  
  7888. public function GetFinisherVictim() : CActor
  7889. {
  7890. return finisherVictim;
  7891. }
  7892.  
  7893. protected function SetNonActorTarget( actor : CGameplayEntity )
  7894. {
  7895. if ( nonActorTarget != actor )
  7896. nonActorTarget = actor;
  7897. }
  7898.  
  7899. timer function DisableTargetHighlightTimer( time : float , id : int)
  7900. {
  7901. var target : CActor;
  7902. target = GetTarget();
  7903.  
  7904. if( target )
  7905. {
  7906. target.StopEffect( 'select_character' );
  7907. }
  7908. }
  7909.  
  7910. public function WasVisibleInScaledFrame( entity : CEntity, frameSizeX : float, frameSizeY : float ) : bool
  7911. {
  7912. var position : Vector;
  7913. var positionFound : bool;
  7914. var inFront : bool;
  7915. var x, y : float;
  7916. var boneIndex : int;
  7917. var actor : CActor;
  7918. var gameplayEntity : CGameplayEntity;
  7919. var gameplayEntityMatrix : Matrix;
  7920. var drawableComp : CDrawableComponent;
  7921. var box : Box;
  7922. var ok : bool;
  7923.  
  7924. if ( !entity )
  7925. {
  7926. return false;
  7927. }
  7928. if ( frameSizeX <= 0.0f && frameSizeY <= 0.0f )
  7929. {
  7930. LogChannel( 'WasVisibleInScaledFrame', "ERROR: WasVisibleInScaledFrame: frameSizeX && frameSizeY are both negative!!!" );
  7931. return false;
  7932. }
  7933.  
  7934. if ( useNativeTargeting )
  7935. {
  7936. return targeting.WasVisibleInScaledFrame( entity, frameSizeX, frameSizeY );
  7937. }
  7938.  
  7939. position = entity.GetWorldPosition();
  7940.  
  7941. actor = (CActor)entity;
  7942. if ( actor )
  7943. {
  7944. boneIndex = entity.GetBoneIndex( 'pelvis' );
  7945. if ( boneIndex == -1 )
  7946. {
  7947. boneIndex = entity.GetBoneIndex( 'k_pelvis_g' ); // not hack at all. DONE !*100000000000000000000
  7948. }
  7949.  
  7950. if ( boneIndex != -1 )
  7951. {
  7952. position = MatrixGetTranslation( entity.GetBoneWorldMatrixByIndex( boneIndex ) );
  7953. }
  7954. else
  7955. {
  7956. position = entity.GetWorldPosition();
  7957. position.Z += ( (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent() ).GetCapsuleHeight() * 0.5;
  7958. }
  7959. positionFound = true;
  7960. }
  7961. else
  7962. {
  7963. gameplayEntity = (CGameplayEntity)entity;
  7964. if ( gameplayEntity && !( gameplayEntity.aimVector.X == 0 && gameplayEntity.aimVector.Y == 0 && gameplayEntity.aimVector.Z == 0 ) )
  7965. {
  7966. gameplayEntityMatrix = gameplayEntity.GetLocalToWorld();
  7967. position = VecTransform( gameplayEntityMatrix, gameplayEntity.aimVector );
  7968. positionFound = true;
  7969. }
  7970. }
  7971.  
  7972. // if still not found proper position for test
  7973. if ( !positionFound )
  7974. {
  7975. drawableComp = (CDrawableComponent)entity.GetComponentByClassName( 'CDrawableComponent' );
  7976. if ( drawableComp && drawableComp.GetObjectBoundingVolume( box ) )
  7977. {
  7978. position.Z += ( ( box.Max.Z - box.Min.Z ) * 0.66f );
  7979. }
  7980. }
  7981.  
  7982. inFront = theCamera.WorldVectorToViewRatio( position, x, y );
  7983. if ( !inFront )
  7984. {
  7985. return false;
  7986. }
  7987. x = AbsF( x );
  7988. y = AbsF( y );
  7989.  
  7990. ok = true;
  7991. ok = ok && ( frameSizeX <= 0.0f || x < frameSizeX );
  7992. ok = ok && ( frameSizeY <= 0.0f || y < frameSizeY );
  7993.  
  7994. return ok;
  7995. }
  7996.  
  7997. public function HardLockToTarget( flag : bool )
  7998. {
  7999. if( flag && GetTarget().HasTag( 'NoHardLock' ) )
  8000. return;
  8001.  
  8002. EnableHardLock( flag );
  8003. LockToTarget( flag );
  8004. }
  8005.  
  8006. public function LockToTarget( flag : bool )
  8007. {
  8008. if ( IsHardLockEnabled() && !flag )
  8009. return;
  8010.  
  8011. LockCameraToTarget( flag );
  8012. LockActorToTarget( flag );
  8013. }
  8014.  
  8015. public function LockCameraToTarget( flag : bool )
  8016. {
  8017. if ( flag && !IsCameraLockedToTarget() )
  8018. {
  8019. thePlayer.EnableManualCameraControl( false, 'LockCameraToTarget' );
  8020. //((CCustomCamera)theCamera.GetTopmostCameraObject()).EnableManualControl( false );
  8021. SetIsCameraLockedToTarget( flag );
  8022. }
  8023. else if ( !flag && IsCameraLockedToTarget() )
  8024. {
  8025. thePlayer.EnableManualCameraControl( true, 'LockCameraToTarget' );
  8026. //((CCustomCamera)theCamera.GetTopmostCameraObject()).EnableManualControl( true );
  8027. SetIsCameraLockedToTarget( flag );
  8028. }
  8029. }
  8030.  
  8031. public function LockActorToTarget( flag : bool, optional withoutIcon : bool )
  8032. {
  8033. var displayTargetActor : CActor;
  8034.  
  8035. if ( flag )
  8036. {
  8037. if ( !IsActorLockedToTarget() )
  8038. {
  8039. //SetSlideTarget( target );
  8040. SetIsActorLockedToTarget( flag );
  8041. SetMoveTargetChangeAllowed( true );
  8042. SetMoveTarget( GetTarget() );
  8043. SetMoveTargetChangeAllowed( false );
  8044. SetTarget( GetTarget() );
  8045. SetSlideTarget( GetTarget() );
  8046. AddTimer( 'CheckLockTargetIsAlive', 0.5, true );
  8047. }
  8048.  
  8049. if ( IsActorLockedToTarget() )
  8050. {
  8051. displayTargetActor = (CActor)( GetDisplayTarget() );
  8052.  
  8053. if ( displayTargetActor && IsThreat( displayTargetActor ) && !withoutIcon )
  8054. EnableHardLockIcon( flag );
  8055. }
  8056. }
  8057. else if ( !flag && IsActorLockedToTarget() )
  8058. {
  8059. SetIsActorLockedToTarget( flag );
  8060. SetMoveTargetChangeAllowed( true );
  8061. RemoveTimer( 'CheckLockTargetIsAlive' );
  8062. EnableHardLockIcon( flag );
  8063. }
  8064. }
  8065.  
  8066. private function EnableHardLockIcon( flag : bool )
  8067. {
  8068. var hud : CR4ScriptedHud;
  8069. var module : CR4HudModuleEnemyFocus;
  8070.  
  8071. if( GetTarget().HasTag( 'NoHardLockIcon' ) )
  8072. return;
  8073.  
  8074. hud = (CR4ScriptedHud)theGame.GetHud();
  8075. module = (CR4HudModuleEnemyFocus)hud.GetHudModule("EnemyFocusModule");
  8076. module.SetShowHardLock( flag );
  8077. }
  8078.  
  8079. private timer function CheckLockTargetIsAlive( time : float , id : int)
  8080. {
  8081. var vitality : float;
  8082. var essence : float;
  8083. var actor : CActor;
  8084. var target : CActor;
  8085.  
  8086. target = (CActor)GetDisplayTarget();
  8087.  
  8088. if( !target
  8089. || !target.IsAlive()
  8090. || ( !target.GetGameplayVisibility() )
  8091. || !CanBeTargetedIfSwimming( target )
  8092. || (!target.UsesVitality() && !target.UsesEssence()))
  8093. {
  8094. if ( !ProcessLockTarget() )
  8095. HardLockToTarget( false );
  8096. }
  8097. }
  8098.  
  8099. //////////////////////////////////////////////////////////////////////////////////////////
  8100. //
  8101. // @Damage
  8102. //
  8103. //////////////////////////////////////////////////////////////////////////////////////////
  8104. protected function PlayHitAnimation(damageAction : W3DamageAction, animType : EHitReactionType)
  8105. {
  8106. var hitRotation : float;
  8107. var hitRotation : float;
  8108. var onHitCounter : SAbilityAttributeValue;
  8109. var counter : int;
  8110.  
  8111. if( damageAction.HasAnyCriticalEffect() )
  8112. return;
  8113.  
  8114. if( !substateManager.ReactOnBeingHit() && !IsUsingVehicle() )
  8115. {
  8116. return;
  8117. }
  8118.  
  8119. if ( damageAction.GetHitReactionType() == EHRT_Reflect )
  8120. SetBehaviorVariable( 'isAttackReflected', 1.f );
  8121. else
  8122. SetBehaviorVariable( 'isAttackReflected', 0.f );
  8123.  
  8124. SetBehaviorVariable( 'HitReactionType',(int)animType);
  8125. SetBehaviorVariable( 'HitReactionWeapon', ProcessSwordOrFistHitReaction( this, (CActor)damageAction.attacker ) );
  8126.  
  8127. if (damageAction.attacker)
  8128. {
  8129. super.PlayHitAnimation( damageAction, animType );
  8130. if ( damageAction.attacker.HasAbility( 'IncreaseHitReactionSeverityWithHitCounter' ) )
  8131. {
  8132. counter = GetHitCounter();
  8133. switch ( counter )
  8134. {
  8135. case 2 :
  8136. SetBehaviorVariable( 'HitReactionType', 2 );
  8137. break;
  8138.  
  8139. case 3 :
  8140. AddEffectDefault( EET_Stagger, damageAction.attacker, damageAction.attacker.GetName() );
  8141. break;
  8142.  
  8143. case 4 :
  8144. AddEffectDefault( EET_Knockdown, damageAction.attacker, damageAction.attacker.GetName() );
  8145. break;
  8146.  
  8147. default :
  8148. break;
  8149. }
  8150. }
  8151. SetHitReactionDirection(damageAction.attacker);
  8152. SetDetailedHitReaction(damageAction.GetSwingType(), damageAction.GetSwingDirection());
  8153. }
  8154.  
  8155. RaiseForceEvent( 'Hit' );
  8156. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'ActorInHitReaction', -1, 30.0f, -1.f, -1, true );
  8157.  
  8158. if ( IsUsingBoat() )
  8159. {
  8160. SoundEvent("cmb_play_hit_light");
  8161. return;
  8162. }
  8163.  
  8164. if ( IsUsingVehicle() )
  8165. return;
  8166.  
  8167. if(damageAction.attacker)
  8168. {
  8169. hitRotation = VecHeading( damageAction.attacker.GetWorldPosition() - GetWorldPosition() );
  8170. if ( this.GetBehaviorVariable( 'HitReactionDirection' ) == (float)( (int)EHRD_Back ) )
  8171. hitRotation += 180.f;
  8172.  
  8173. //GetVisualDebug().AddArrow( 'temp', GetWorldPosition(), GetWorldPosition() + VecFromHeading( hitRotation )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f );
  8174. SetCustomRotation( 'Hit', hitRotation, 1080.f, 0.1f, false );
  8175. }
  8176.  
  8177. CriticalEffectAnimationInterrupted("PlayHitAnimation");
  8178. }
  8179.  
  8180. public function ReduceDamage( out damageData : W3DamageAction)
  8181. {
  8182. super.ReduceDamage(damageData);
  8183.  
  8184. //halve damage if from your own bomb
  8185. if(damageData.attacker == this && (damageData.GetBuffSourceName() == "petard" || (W3Petard)damageData.causer) )
  8186. {
  8187. if ( theGame.CanLog() )
  8188. {
  8189. LogDMHits("CR4Player.ReduceDamage: hitting self with own bomb - damage reduced by 50%", damageData );
  8190. }
  8191. damageData.processedDmg.vitalityDamage = damageData.processedDmg.vitalityDamage / 2;
  8192. damageData.processedDmg.essenceDamage = damageData.processedDmg.essenceDamage / 2;
  8193. }
  8194. }
  8195.  
  8196. //crit hit chance 0-1
  8197. public function GetCriticalHitChance(isHeavyAttack : bool, target : CActor, victimMonsterCategory : EMonsterCategory) : float
  8198. {
  8199. var critChance : float;
  8200. var oilChanceAttribute : name;
  8201. var weapons : array< SItemUniqueId >;
  8202. var i : int;
  8203. var holdsCrossbow : bool;
  8204. var critVal : SAbilityAttributeValue;
  8205.  
  8206. critChance = 0;
  8207.  
  8208. //cheats
  8209. if(FactsQuerySum('debug_fact_critical_boy') > 0)
  8210. {
  8211. critChance += 1;
  8212. }
  8213.  
  8214. if( IsInState( 'HorseRiding' ) && ((CActor)GetUsedVehicle()).GetMovingAgentComponent().GetRelativeMoveSpeed() >= 4.0 )
  8215. {
  8216. critChance += 1;
  8217. }
  8218.  
  8219. //normal case
  8220. critChance += CalculateAttributeValue(GetAttributeValue(theGame.params.CRITICAL_HIT_CHANCE));
  8221.  
  8222. //active skills bonus
  8223. if(isHeavyAttack && CanUseSkill(S_Sword_s08))
  8224. critChance += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s08, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s08);
  8225. else if (!isHeavyAttack && CanUseSkill(S_Sword_s17))
  8226. critChance += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s17, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s17);
  8227.  
  8228. if(target && target.HasBuff(EET_Confusion))
  8229.  
  8230. weapons = inv.GetHeldWeapons();
  8231. for( i=0; i<weapons.Size(); i+=1 )
  8232. {
  8233. holdsCrossbow = ( inv.IsItemCrossbow( weapons[i] ) || inv.IsItemBolt( weapons[i] ) );
  8234. if( holdsCrossbow != isBolt )
  8235. {
  8236. critVal = inv.GetItemAttributeValue( weapons[i], theGame.params.CRITICAL_HIT_CHANCE );
  8237. critChance -= CalculateAttributeValue( critVal );
  8238. }
  8239. }
  8240.  
  8241.  
  8242. if( isHeavyAttack && CanUseSkill( S_Sword_s08 ) )
  8243. {
  8244. critChance += CalculateAttributeValue( GetSkillAttributeValue( S_Sword_s08, theGame.params.CRITICAL_HIT_CHANCE, false, true ) ) * GetSkillLevel( S_Sword_s08 );
  8245. }
  8246. else if( isLightAttack && CanUseSkill( S_Sword_s17 ) )
  8247. {
  8248. critChance += CalculateAttributeValue( GetSkillAttributeValue( S_Sword_s17, theGame.params.CRITICAL_HIT_CHANCE, false, true ) ) * GetSkillLevel( S_Sword_s17 );
  8249. }
  8250.  
  8251. if( target && target.HasBuff( EET_Confusion ) )
  8252. {
  8253. critChance += ((W3ConfuseEffect)target.GetBuff(EET_Confusion)).GetCriticalHitChanceBonus();
  8254. }
  8255.  
  8256. //oils
  8257. oilChanceAttribute = MonsterCategoryToCriticalChanceBonus(victimMonsterCategory);
  8258. if(IsNameValid(oilChanceAttribute))
  8259. critChance += CalculateAttributeValue(GetAttributeValue(oilChanceAttribute));
  8260.  
  8261.  
  8262. oilChanceAttribute = MonsterCategoryToCriticalChanceBonus( victimMonsterCategory );
  8263. if( IsNameValid( oilChanceAttribute ) )
  8264. {
  8265. critChance += CalculateAttributeValue( GetAttributeValue( oilChanceAttribute ) );
  8266. }
  8267.  
  8268. return critChance;
  8269. }
  8270.  
  8271. //gets damage bonus for critical hit
  8272. public function GetCriticalHitDamageBonus(weaponId : SItemUniqueId, victimMonsterCategory : EMonsterCategory, isStrikeAtBack : bool) : SAbilityAttributeValue
  8273. {
  8274. var bonus, oilBonus : SAbilityAttributeValue;
  8275. var vsAttributeName : name;
  8276.  
  8277. bonus = super.GetCriticalHitDamageBonus(weaponId, victimMonsterCategory, isStrikeAtBack);
  8278.  
  8279. //oil bonus
  8280. if(inv.ItemHasOilApplied(weaponId))
  8281. {
  8282. vsAttributeName = MonsterCategoryToCriticalDamageBonus(victimMonsterCategory);
  8283. oilBonus = inv.GetItemAttributeValue(weaponId, vsAttributeName);
  8284. bonus += oilBonus;
  8285. }
  8286.  
  8287. return bonus;
  8288. }
  8289.  
  8290. /**
  8291. Called when we want to play hit animation
  8292. */
  8293. public function ReactToBeingHit(damageAction : W3DamageAction, optional buffNotApplied : bool) : bool
  8294. {
  8295. var strength : float;
  8296. var animType : EHitReactionType;
  8297. var sup : bool;
  8298. var boat : CBoatComponent;
  8299. var combatActionType : int;
  8300. var attackAction : W3Action_Attack;
  8301. var npc : CNewNPC;
  8302. var shakeCam : bool;
  8303.  
  8304. attackAction = (W3Action_Attack)damageAction;
  8305. //not parried, not countered, not dot, not dodged
  8306. if(!damageAction.IsDoTDamage() && (!attackAction || (!attackAction.IsParried() && !attackAction.IsCountered() && !attackAction.WasDodged()) ) )
  8307. {
  8308. npc = (CNewNPC)attackAction.attacker;
  8309. if(npc && npc.IsHeavyAttack(attackAction.GetAttackName()))
  8310. theGame.VibrateControllerVeryHard();//player got heavy hit
  8311. else
  8312. theGame.VibrateControllerHard();//player got hit
  8313. }
  8314.  
  8315. if ( (CActor)GetUsedVehicle() && this.playerAiming.GetCurrentStateName() == 'Aiming' )
  8316. {
  8317. OnRangedForceHolster( true, true );
  8318. }
  8319.  
  8320. combatActionType = (int)GetBehaviorVariable( 'combatActionType' );
  8321.  
  8322. if ( thePlayer.IsCurrentlyDodging() && ( combatActionType == (int)CAT_Roll || combatActionType == (int)CAT_CiriDodge ) )
  8323. sup = false;
  8324. else if ( this.GetCurrentStateName() == 'DismountHorse' )
  8325. sup = false;
  8326. else
  8327. sup = super.ReactToBeingHit(damageAction, buffNotApplied);
  8328. sup = false;
  8329. //telemetry
  8330. if(damageAction.attacker)
  8331. theTelemetry.LogWithLabelAndValue( TE_FIGHT_HERO_GETS_HIT, damageAction.attacker.ToString(), (int)damageAction.processedDmg.vitalityDamage );
  8332.  
  8333. //camera shake
  8334. if(damageAction.DealsAnyDamage())
  8335. {
  8336. if( ((W3PlayerWitcher)this) && GetWitcherPlayer().IsAnyQuenActive() && damageAction.IsDoTDamage())
  8337. {
  8338. shakeCam = false;
  8339. }
  8340. else
  8341. {
  8342. shakeCam = true;
  8343. }
  8344.  
  8345. if(shakeCam)
  8346. {
  8347. animType = ModifyHitSeverityReaction(this, damageAction.GetHitReactionType());
  8348.  
  8349. if(animType == EHRT_Light || animType == EHRT_LightClose)
  8350. strength = 0.1;
  8351. else if(animType == EHRT_Heavy || animType == EHRT_Igni)
  8352. strength = 0.2;
  8353.  
  8354. GCameraShakeLight(strength, false, GetWorldPosition(), 10.0);
  8355. }
  8356.  
  8357. this.HitReactionEffect( 0.25 );
  8358.  
  8359. //reset uninterrupted hits
  8360. ResetUninterruptedHitsCount();
  8361. }
  8362.  
  8363. //pause health regen
  8364. if(!damageAction.IsDoTDamage() && IsThreatened() && ShouldPauseHealthRegenOnHit() && damageAction.DealsAnyDamage() && !damageAction.WasDodged() && attackAction.CanBeParried() && !attackAction.IsParried())
  8365. {
  8366. PauseHPRegenEffects('being_hit', theGame.params.ON_HIT_HP_REGEN_DELAY);
  8367. }
  8368.  
  8369. //if player is on a boat and not moving then force dismount
  8370. /*if(usedVehicle)
  8371. {
  8372. boat = (CBoatComponent) usedVehicle.GetComponentByClassName('CBoatComponent');
  8373. if(boat && boat.GetLinearVelocityXY() < boat.IDLE_SPEED_THRESHOLD)
  8374. {
  8375. boat.StopAndDismountBoat();
  8376. }
  8377. }*/
  8378.  
  8379. //finesse achievement fail
  8380.  
  8381.  
  8382.  
  8383. if(damageAction.processedDmg.vitalityDamage > 0 && !((W3Effect_Toxicity)damageAction.causer))
  8384. ReceivedCombatDamage();
  8385.  
  8386. //tutorial
  8387. if(FactsQuerySum("tut_fight_use_slomo") > 0)
  8388. {
  8389. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) );
  8390. FactsRemove("tut_fight_slomo_ON");
  8391. }
  8392.  
  8393. // State
  8394. if( !substateManager.ReactOnBeingHit( damageAction ) )
  8395. {
  8396. GoToCombatIfNeeded();
  8397. //PushState( 'CombatFists' );
  8398. }
  8399.  
  8400. return sup;
  8401. }
  8402.  
  8403. protected function ShouldPauseHealthRegenOnHit() : bool
  8404. {
  8405. return true;
  8406. }
  8407.  
  8408. public function PlayHitEffect(damageAction : W3DamageAction)
  8409. {
  8410. super.PlayHitEffect(damageAction);
  8411.  
  8412. //fullscreen hit fx
  8413. if(damageAction.DealsAnyDamage() && !damageAction.IsDoTDamage())
  8414. PlayEffect('hit_screen');
  8415. }
  8416.  
  8417. function HitReactionEffect( interval : float )
  8418. {
  8419. if ( hitReactionEffect )
  8420. {
  8421. PlayEffect( 'radial_blur' );
  8422. hitReactionEffect = false;
  8423. }
  8424. else
  8425. {
  8426. AddTimer( 'HitReactionEffectCooldown', interval, false );
  8427. }
  8428. }
  8429.  
  8430. timer function HitReactionEffectCooldown( td : float , id : int)
  8431. {
  8432. hitReactionEffect = true;
  8433. }
  8434. //////////////////////////////////////////////////////////////////////////////////////////
  8435. //
  8436. // @Parry
  8437. //
  8438. //////////////////////////////////////////////////////////////////////////////////////////
  8439.  
  8440. function PerformParryCheck( parryInfo : SParryInfo) : bool
  8441. {
  8442. var mult : float;
  8443. var parryType : EParryType;
  8444. var parryDir : EPlayerParryDirection;
  8445. var parryHeading : float;
  8446. var fistFightParry : bool;
  8447. var action : W3DamageAction;
  8448. var xmlStaminaDamage : float;
  8449. var xmlStaminaDamageName : name = 'stamina_damage' ;
  8450.  
  8451. // if ( !parryInfo.canBeParried )
  8452. // return false;
  8453. var counter : int;
  8454. var onHitCounter : SAbilityAttributeValue;
  8455.  
  8456.  
  8457.  
  8458.  
  8459. if(CanParryAttack() && /*parryInfo.targetToAttackerAngleAbs < theGame.params.PARRY_HALF_ANGLE &&*/ FistFightCheck( parryInfo.target, parryInfo.attacker, fistFightParry ) )
  8460. {
  8461. parryHeading = GetParryHeading( parryInfo, parryDir ) ;
  8462. //GetVisualDebug().AddArrow( 'CombatActionHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( GetParryHeading( parryInfo, parryDir ) )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f );
  8463. SetBehaviorVariable( 'parryDirection', (float)( (int)( parryDir ) ) );
  8464. SetBehaviorVariable( 'parryDirectionOverlay', (float)( (int)( parryDir ) ) );
  8465. SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) );
  8466.  
  8467. if ( IsInCombatActionFriendly() )
  8468. RaiseEvent('CombatActionFriendlyEnd');
  8469.  
  8470. if ( HasStaminaToParry(parryInfo.attackActionName) )
  8471. {
  8472. this.SetBehaviorVariable( 'combatActionType', (int)CAT_Parry );
  8473.  
  8474. if ( parryInfo.targetToAttackerDist > 3.f && !bLAxisReleased && !thePlayer.IsCiri() )
  8475. {
  8476. if ( !RaiseForceEvent( 'PerformParryOverlay' ) )
  8477. return false;
  8478. else
  8479. {
  8480. ClearCustomOrientationInfoStack();
  8481. IncDefendCounter();
  8482. }
  8483. }
  8484. else
  8485. {
  8486. if ( RaiseForceEvent( 'PerformParry' ) )
  8487. counter = GetDefendCounter();
  8488. onHitCounter = parryInfo.attacker.GetAttributeValue( 'break_through_parry_on_hit_counter' );
  8489. if ( onHitCounter.valueBase > 0 && counter == onHitCounter.valueBase )
  8490. {
  8491. AddEffectDefault( EET_Stagger, parryInfo.attacker, "Break through parry" );
  8492. }
  8493. else if ( RaiseForceEvent( 'PerformParry' ) )
  8494. {
  8495. OnCombatActionStart();
  8496. ClearCustomOrientationInfoStack();
  8497. SetSlideTarget( parryInfo.attacker );
  8498. SetCustomRotation( 'Parry', parryHeading, 1080.f, 0.1f, false );
  8499. IncDefendCounter();
  8500. }
  8501. else
  8502. return false;
  8503. }
  8504. }
  8505. else
  8506. {
  8507. AddEffectDefault(EET_Stagger, parryInfo.attacker, "Parry");
  8508. return true;
  8509. }
  8510.  
  8511. //parryTarget := this
  8512. if ( parryInfo.attacker.IsWeaponHeld( 'fist' ) && !parryInfo.target.IsWeaponHeld( 'fist' ) )
  8513. {
  8514. parryInfo.attacker.ReactToReflectedAttack(parryInfo.target);
  8515. }
  8516. else
  8517. {
  8518. if ( this.IsInFistFightMiniGame() && fistFightParry )
  8519. {
  8520. if ( IsNameValid(xmlStaminaDamageName) )
  8521. {
  8522. xmlStaminaDamage = CalculateAttributeValue(parryInfo.attacker.GetAttributeValue( xmlStaminaDamageName ));
  8523. DrainStamina(ESAT_FixedValue, xmlStaminaDamage);
  8524. }
  8525. }
  8526. else
  8527. {
  8528. DrainStamina(ESAT_Parry, 0, 0, '', 0, mult);
  8529. }
  8530. if(IsLightAttack(parryInfo.attackActionName))
  8531. parryInfo.target.PlayEffectOnHeldWeapon('light_block');
  8532. else
  8533. parryInfo.target.PlayEffectOnHeldWeapon('heavy_block');
  8534. }
  8535. return true;
  8536. }
  8537.  
  8538. return false;
  8539. }
  8540.  
  8541. protected function GetParryHeading( parryInfo : SParryInfo, out parryDir : EPlayerParryDirection ) : float
  8542. {
  8543. var targetToAttackerHeading : float;
  8544. var currToTargetAttackerAngleDiff : float;
  8545.  
  8546. targetToAttackerHeading = VecHeading( parryInfo.attacker.GetWorldPosition() - parryInfo.target.GetWorldPosition() );
  8547. currToTargetAttackerAngleDiff = AngleDistance( VecHeading( parryInfo.target.GetHeadingVector() ), targetToAttackerHeading );
  8548.  
  8549. if ( !parryInfo.target.IsWeaponHeld( 'fist' ) )
  8550. {
  8551. if( currToTargetAttackerAngleDiff > -45 && currToTargetAttackerAngleDiff < 45 )
  8552. {
  8553. parryDir = PPD_Forward;
  8554. return targetToAttackerHeading;
  8555. }
  8556. else if( currToTargetAttackerAngleDiff >= 45 && currToTargetAttackerAngleDiff < 135 )
  8557. {
  8558. parryDir = PPD_Right;
  8559. //return targetToAttackerHeading;
  8560. return targetToAttackerHeading + 90;
  8561. }
  8562. else if( currToTargetAttackerAngleDiff <= -45 && currToTargetAttackerAngleDiff > -135 )
  8563. {
  8564. parryDir = PPD_Left;
  8565. //return targetToAttackerHeading;
  8566. return targetToAttackerHeading - 90;
  8567. }
  8568. else
  8569. {
  8570. parryDir = PPD_Back;
  8571. //return targetToAttackerHeading;
  8572. return targetToAttackerHeading + 180;
  8573. }
  8574. }
  8575. else
  8576. {
  8577. if( currToTargetAttackerAngleDiff > -45 && currToTargetAttackerAngleDiff < 45 )
  8578. {
  8579. parryDir = PPD_Forward;
  8580. return targetToAttackerHeading;
  8581. }
  8582. else if( currToTargetAttackerAngleDiff >= 45 && currToTargetAttackerAngleDiff < 180 )
  8583. {
  8584. parryDir = PPD_Right;
  8585. return targetToAttackerHeading + 90;
  8586. }
  8587. else if( currToTargetAttackerAngleDiff <= -45 && currToTargetAttackerAngleDiff >= -180 )
  8588. {
  8589. parryDir = PPD_Left;
  8590. return targetToAttackerHeading - 90;
  8591. }
  8592. else
  8593. {
  8594. parryDir = PPD_Back;
  8595. return targetToAttackerHeading + 180;
  8596. }
  8597. }
  8598. }
  8599.  
  8600. function ProcessLockTarget( optional newLockTarget : CActor, optional checkLeftStickHeading : bool ) : bool
  8601. {
  8602. var attackerNearestPoint : Vector;
  8603. var playerNearestPoint : Vector;
  8604. var incomingAttacker : CActor;
  8605. var tempLockTarget : CActor;
  8606. var target : CActor;
  8607. var useIncomingAttacker : bool;
  8608.  
  8609. if( newLockTarget.HasTag( 'NoHardLock' ) )
  8610. return false;
  8611.  
  8612. if ( newLockTarget )
  8613. tempLockTarget = newLockTarget;
  8614. else
  8615. {
  8616. incomingAttacker = GetClosestIncomingAttacker();
  8617. if ( incomingAttacker && incomingAttacker.IsAlive() && IsUsingVehicle() )
  8618. {
  8619. tempLockTarget = incomingAttacker;
  8620. useIncomingAttacker = false;
  8621. }
  8622.  
  8623. if ( !useIncomingAttacker )
  8624. {
  8625. target = GetTarget();
  8626. if ( target && target.IsAlive() && target.GetGameplayVisibility() && IsEnemyVisible( target ) && IsThreat( target ) && CanBeTargetedIfSwimming( target ) )
  8627. if( target.HasTag('ForceHardLock'))
  8628. {
  8629. return true;
  8630. }
  8631. else if ( target && target.IsAlive() && target.GetGameplayVisibility() && IsEnemyVisible( target ) && IsThreat( target ) && CanBeTargetedIfSwimming( target ) )
  8632. tempLockTarget = FindTarget();
  8633. else
  8634. {
  8635. tempLockTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, 0.f );
  8636. }
  8637. }
  8638. }
  8639.  
  8640. if( tempLockTarget.HasTag( 'NoHardLock' ) )
  8641. return false;
  8642.  
  8643. if ( tempLockTarget )
  8644. {
  8645. if ( IsCombatMusicEnabled() || hostileEnemies.Size() > 0 )
  8646. {
  8647. if ( !IsThreat( tempLockTarget ) )
  8648. tempLockTarget = NULL;
  8649. }
  8650. }
  8651.  
  8652. SetTarget( tempLockTarget, true );
  8653. SetMoveTargetChangeAllowed( true );
  8654. SetMoveTarget( tempLockTarget );
  8655. SetMoveTargetChangeAllowed( false );
  8656. SetSlideTarget( tempLockTarget );
  8657.  
  8658. if ( tempLockTarget )
  8659. {
  8660. if ( this.IsActorLockedToTarget() )
  8661. EnableHardLockIcon( true );
  8662.  
  8663. return true;
  8664. }
  8665. else
  8666. return false;
  8667. }
  8668.  
  8669. //////////////////////////////////////////////////////////////////////////////////////////
  8670. //////////////////////// @COMBAT ///////////////////////////////////////////////////////
  8671. //////////////////////////////////////////////////////////////////////////////////////////
  8672.  
  8673. //checks if player is doing special attack light/heavy
  8674.  
  8675.  
  8676.  
  8677. event OnTaskSyncAnim( npc : CNewNPC, animNameLeft : name ) {}
  8678.  
  8679.  
  8680. public function IsDoingSpecialAttack(heavy : bool) : bool
  8681. {
  8682. var pat : EPlayerAttackType;
  8683.  
  8684. if(IsInCombatAction() && ( (int)GetBehaviorVariable('combatActionType')) == CAT_SpecialAttack)
  8685. {
  8686. pat = (int)GetBehaviorVariable('playerAttackType');
  8687.  
  8688. if(heavy && pat == PAT_Heavy)
  8689. {
  8690. return true;
  8691. }
  8692. else if(!heavy && pat == PAT_Light)
  8693. {
  8694. return true;
  8695. }
  8696. }
  8697.  
  8698. return false;
  8699. }
  8700.  
  8701. public function SetIsCurrentlyDodging(enable : bool, optional isRolling : bool)
  8702. {
  8703. super.SetIsCurrentlyDodging(enable, isRolling);
  8704.  
  8705. if ( isRolling )
  8706. {
  8707. SetCanPlayHitAnim( false );
  8708. this.AddBuffImmunity( EET_KnockdownTypeApplicator, 'Roll', false );
  8709. this.AddBuffImmunity( EET_Knockdown, 'Roll', false );
  8710. this.AddBuffImmunity( EET_HeavyKnockdown, 'Roll', false );
  8711. this.AddBuffImmunity( EET_Stagger, 'Roll', false );
  8712. }
  8713. else
  8714. {
  8715. SetCanPlayHitAnim( true );
  8716. this.RemoveBuffImmunity( EET_KnockdownTypeApplicator, 'Roll' );
  8717. this.RemoveBuffImmunity( EET_Knockdown, 'Roll' );
  8718. this.RemoveBuffImmunity( EET_HeavyKnockdown, 'Roll' );
  8719. this.RemoveBuffImmunity( EET_Stagger, 'Roll' );
  8720. }
  8721. }
  8722.  
  8723. public function EnableHardLock( flag : bool )
  8724. {
  8725. super.EnableHardLock(flag);
  8726.  
  8727. if(flag && ShouldProcessTutorial('TutorialTargettingWaiting'))
  8728. {
  8729. FactsAdd("tut_hardlocked");
  8730. }
  8731. }
  8732.  
  8733. protected function TestParryAndCounter(data : CPreAttackEventData, weaponId : SItemUniqueId, out parried : bool, out countered : bool) : array<CActor>
  8734. {
  8735. var ret : array<CActor>;
  8736.  
  8737. //cheat for QA tests - NPCs won't parry/counter
  8738. if(FactsQuerySum('player_is_the_boss') > 0)
  8739. {
  8740. //---------------- DEBUG
  8741. //draw debug AR
  8742. SetDebugAttackRange(data.rangeName);
  8743. RemoveTimer('PostAttackDebugRangeClear'); //disable AR clearing since we've just set a new one
  8744.  
  8745. return ret;
  8746. }
  8747.  
  8748. ret = super.TestParryAndCounter(data, weaponId, parried, countered);
  8749.  
  8750. //achievement
  8751. if(parried)
  8752. theGame.GetGamerProfile().ResetStat(ES_CounterattackChain);
  8753.  
  8754. return ret;
  8755. }
  8756.  
  8757. public function SetSpecialAttackTimeRatio(f : float)
  8758. {
  8759. LogSpecialHeavy(f);
  8760. specialAttackTimeRatio = f;
  8761. }
  8762.  
  8763. public function GetSpecialAttackTimeRatio() : float
  8764. {
  8765. return specialAttackTimeRatio;
  8766. }
  8767.  
  8768. //called when we processed special heavy attack action - either from hit or from CombatActionEnd()
  8769. public function OnSpecialAttackHeavyActionProcess()
  8770. {
  8771. //clear ration after attack performed
  8772. SetSpecialAttackTimeRatio(0.f);
  8773. }
  8774.  
  8775. protected function DoAttack(animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array<CActor>, attackAnimationName : name, hitTime : float)
  8776. {
  8777. var shakeStr : float;
  8778. var weapon : EPlayerWeapon;
  8779. var targetActor : CActor;
  8780.  
  8781. //cam shake for player's heavy attacks
  8782. if ( animData.attackName == 'attack_heavy_special' )
  8783. {
  8784. if( specialAttackTimeRatio != 1 )
  8785. shakeStr = (specialAttackTimeRatio / 3.333) + 0.2;
  8786. else
  8787. shakeStr = 0.5;
  8788.  
  8789. GCameraShake( shakeStr, false, GetWorldPosition(), 10);
  8790. }
  8791. else if ( IsHeavyAttack(attackActionName) )
  8792. {
  8793. if(parriedBy.Size() > 0)
  8794. shakeStr = 0.2;
  8795. else
  8796. shakeStr = 0.1;
  8797.  
  8798. GCameraShake(shakeStr, false, GetWorldPosition(), 10);
  8799. }
  8800.  
  8801. targetActor = (CActor)slideTarget;
  8802. if ( targetActor && hitTargets.Contains(targetActor) )
  8803. {
  8804. weapon = this.GetMostConvenientMeleeWeapon(targetActor,true);
  8805. if ( this.GetCurrentMeleeWeaponType() != PW_Fists && weapon != this.GetCurrentMeleeWeaponType() )
  8806. {
  8807. if ( weapon == PW_Steel )
  8808. {
  8809. thePlayer.OnEquipMeleeWeapon(PW_Steel,true);
  8810. }
  8811. else if ( weapon == PW_Silver )
  8812. {
  8813. thePlayer.OnEquipMeleeWeapon(PW_Silver,true);
  8814. }
  8815.  
  8816. }
  8817. }
  8818.  
  8819. super.DoAttack(animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime);
  8820. }
  8821.  
  8822. //var delayCombatStanceTimeStamp : float;
  8823.  
  8824. private var confirmCombatStanceTimeStamp : float;
  8825. private var isConfirmingCombatStance : bool;
  8826. final function SetPlayerCombatStance(stance : EPlayerCombatStance, optional force : bool )
  8827. {
  8828. var stanceInt : int;
  8829.  
  8830. if ( !CanChangeCombatStance( stance, force ) )
  8831. return;
  8832.  
  8833. combatStance = stance;
  8834. stanceInt = (int)stance;
  8835.  
  8836. SetBehaviorVariable( 'playerCombatStance' , (float)stanceInt);
  8837. SetBehaviorVariable( 'playerCombatStanceForOverlay' , (float)stanceInt);
  8838. if ( force )
  8839. SetBehaviorVariable( 'forceCombatStance' , 1.f);
  8840. else
  8841. SetBehaviorVariable( 'forceCombatStance' , 0.f);
  8842.  
  8843. if ( stance == PCS_AlertNear )
  8844. this.SetBehaviorVariable('isInCombatForOverlay',1.f);
  8845. else
  8846. this.SetBehaviorVariable('isInCombatForOverlay',0.f);
  8847. }
  8848.  
  8849. private function CanChangeCombatStance( stance : EPlayerCombatStance, optional force : bool ) : bool
  8850. {
  8851. var currTime : float;
  8852.  
  8853. if ( force )
  8854. return true;
  8855.  
  8856. if ( IsInFistFightMiniGame() )
  8857. return true;
  8858.  
  8859. if ( isInHolsterAnim )
  8860. return false;
  8861.  
  8862. if ( ( combatStance == PCS_Normal || combatStance == PCS_AlertFar )
  8863. && stance == PCS_AlertNear )
  8864. {
  8865. currTime = theGame.GetEngineTimeAsSeconds();
  8866. if ( !isConfirmingCombatStance )
  8867. {
  8868. isConfirmingCombatStance = true;
  8869. confirmCombatStanceTimeStamp = currTime;
  8870.  
  8871. if ( this.playerMoveType == PMT_Idle )
  8872. this.SetBehaviorVariable('isInCombatForOverlay',0.f);
  8873. else
  8874. this.SetBehaviorVariable('isInCombatForOverlay',1.f);
  8875.  
  8876. return false;
  8877. }
  8878. else if ( currTime < confirmCombatStanceTimeStamp + 1.f )
  8879. {
  8880. if ( stance == PCS_AlertNear )
  8881. return false;
  8882. }
  8883. else
  8884. isConfirmingCombatStance = false;
  8885. }
  8886. else
  8887. isConfirmingCombatStance = false;
  8888.  
  8889. return true;
  8890. }
  8891.  
  8892. private var isInHolsterAnim : bool;
  8893. event OnHolsterWeaponStart()
  8894. {
  8895. isInHolsterAnim = true;
  8896. }
  8897.  
  8898. event OnHolsterWeaponEnd()
  8899. {
  8900. isInHolsterAnim = false;
  8901. }
  8902.  
  8903. final function GetPlayerCombatStance() : EPlayerCombatStance
  8904. {
  8905. return combatStance;
  8906. }
  8907.  
  8908. timer function DelayedDisableFindTarget( time : float , id : int)
  8909. {
  8910. if ( GetTarget().IsAlive() )
  8911. {
  8912. EnableFindTarget( false );
  8913. }
  8914. else
  8915. {
  8916. EnableFindTarget( true );
  8917. }
  8918. }
  8919.  
  8920. ///////////////////////////////////////////////////////////////////////////
  8921. // @BUFFER @COMBATACTIONBUFFER
  8922. ///////////////////////////////////////////////////////////////////////////
  8923.  
  8924. private var dodgeTimerRunning : bool;
  8925.  
  8926. function StartDodgeTimer()
  8927. {
  8928. dodgeTimerRunning = true;
  8929. thePlayer.AddTimer('DodgeTimer',0.2,false);
  8930. }
  8931.  
  8932. function StopDodgeTimer()
  8933. {
  8934. this.RemoveTimer('DodgeTimer');
  8935. dodgeTimerRunning = false;
  8936. }
  8937.  
  8938. function IsDodgeTimerRunning() : bool
  8939. {
  8940. return dodgeTimerRunning;
  8941. }
  8942.  
  8943. timer function DodgeTimer( dt : float, id : int )
  8944. {
  8945. dodgeTimerRunning = false;
  8946. }
  8947.  
  8948. public function EvadePressed( bufferAction : EBufferActionType )
  8949. {
  8950. }
  8951.  
  8952. public function PerformingCombatAction() : EBufferActionType
  8953. {
  8954. return BufferCombatAction;
  8955. }
  8956.  
  8957. public function PushCombatActionOnBuffer( action : EBufferActionType, stage : EButtonStage, optional allSteps : bool )
  8958. {
  8959. BufferButtonStage = stage;
  8960. BufferCombatAction = action;
  8961. BufferAllSteps = allSteps;
  8962. }
  8963.  
  8964. protected function ProcessCombatActionHeading( action : EBufferActionType ) : float
  8965. {
  8966. var processedActionHeading : float;
  8967.  
  8968. HandleMovement( 0.f );
  8969.  
  8970. if ( ShouldUsePCModeTargeting() )
  8971. return theGame.GetGameCamera().GetHeading();
  8972.  
  8973. if ( lAxisReleasedAfterCounter ) // && IsInCombatAction() )
  8974. ResetCachedRawPlayerHeading();
  8975.  
  8976. processedActionHeading = cachedRawPlayerHeading;
  8977.  
  8978. return processedActionHeading;
  8979. }
  8980. /*
  8981. private function ProcessCombatActionHeading( action : EBufferActionType ) : float
  8982. {
  8983. var processedActionHeading : float;
  8984. var unusedActor : CActor; //MS: placeholder variable to fix memory error
  8985.  
  8986. if ( IsUsingVehicle() )
  8987. {
  8988. processedActionHeading = theGame.GetGameCamera().GetHeading();
  8989. return processedActionHeading;
  8990. }
  8991.  
  8992. if ( !bLAxisReleased || lAxisPushedTimeStamp + 0.5f > theGame.GetEngineTimeAsSeconds() )
  8993. processedActionHeading = cachedRawPlayerHeading;
  8994. else
  8995. {
  8996. if ( GetDisplayTarget() )
  8997. {
  8998. if ( cachedCombatActionHeading == cachedRawPlayerHeading )
  8999. ResetCachedRawPlayerHeading();
  9000. else
  9001. {
  9002. cachedRawPlayerHeading = cachedCombatActionHeading;
  9003. canResetCachedCombatActionHeading = true;
  9004. }
  9005.  
  9006. processedActionHeading = cachedRawPlayerHeading;
  9007. }
  9008. else
  9009. {
  9010. if ( lAxisReleasedAfterCounterNoCA )
  9011. ResetRawPlayerHeading();
  9012.  
  9013. cachedRawPlayerHeading = rawPlayerHeading;
  9014.  
  9015. if ( lAxisReleasedAfterCounterNoCA )
  9016. processedActionHeading = GetHeading();
  9017. else
  9018. processedActionHeading = cachedRawPlayerHeading;
  9019. }
  9020. }
  9021.  
  9022. if ( this.IsCameraLockedToTarget() && this.IsActorLockedToTarget() && action != EBAT_Dodge && action != EBAT_Roll )
  9023. processedActionHeading = theGame.GetGameCamera().GetHeading();
  9024.  
  9025. if ( lAxisReleasedAfterCounterNoCA )
  9026. {
  9027. if ( action == EBAT_Dodge || action == EBAT_Roll )
  9028. {
  9029. if ( ( !IsEnemyInCone( this, GetHeadingVector(), softLockDist, 60.f, unusedActor ) || !IsEnemyInCone( this, GetHeadingVector() + 180, softLockDist, 60.f, unusedActor ) ) && moveTarget )
  9030. processedActionHeading = VecHeading( moveTarget.GetWorldPosition() - GetWorldPosition() ) + 180;
  9031. else
  9032. processedActionHeading = GetHeading() + 180;
  9033. }
  9034. }
  9035.  
  9036. //GetVisualDebug().AddArrow( 'cachedRawPlayerHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( cachedRawPlayerHeading ), 1.f, 0.2f, 0.2f, true, Color(0,255,128), true, 5.f );
  9037. //GetVisualDebug().AddArrow( 'CombatActionHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( GetCombatActionHeading() )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f );
  9038.  
  9039. return processedActionHeading;
  9040. }*/
  9041.  
  9042. function ResetRawPlayerHeading()
  9043. {
  9044. if ( GetDisplayTarget() )
  9045. rawPlayerHeading = VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() );
  9046. else
  9047. rawPlayerHeading = GetHeading();
  9048.  
  9049. //LogChannel('ResetRawPlayerHeading',"ResetRawPlayerHeading" );
  9050. }
  9051.  
  9052. function ResetCachedRawPlayerHeading()
  9053. {
  9054. cachedRawPlayerHeading = rawPlayerHeading;
  9055. if ( GetDisplayTarget() && IsDisplayTargetTargetable() && AbsF( AngleDistance( VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() ), this.GetHeading() ) ) < 90.f )
  9056. cachedRawPlayerHeading = VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() );
  9057. else
  9058. cachedRawPlayerHeading = this.GetHeading();
  9059.  
  9060. if ( canResetCachedCombatActionHeading )
  9061. cachedCombatActionHeading = cachedRawPlayerHeading;
  9062. }
  9063.  
  9064. public function GetCombatActionTarget( action : EBufferActionType ) : CGameplayEntity
  9065. {
  9066. var selectedTargetableEntity : CGameplayEntity;
  9067.  
  9068. if ( !this.IsUsingVehicle() )
  9069. selectedTargetableEntity = FindNonActorTarget( true, action );
  9070.  
  9071. if ( selectedTargetableEntity )
  9072. {
  9073. return selectedTargetableEntity;
  9074. }
  9075. else
  9076. {
  9077. /*if ( !IsCombatMusicEnabled() && displayTarget )
  9078. {
  9079. if ( !( (CActor)displayTarget ) )
  9080. return NULL;
  9081. else
  9082. return displayTarget;
  9083. }*/
  9084.  
  9085. if ( !this.IsUsingVehicle() )
  9086. FindTarget( true, action, true );
  9087. else
  9088. ((CR4PlayerStateUseGenericVehicle)this.GetState( 'UseGenericVehicle' )).FindTarget();
  9089.  
  9090. return GetTarget();
  9091. }
  9092. }
  9093.  
  9094. //MS: FindNonActorTarget may or may not have an interaction component, which is why it is separate from ProcessInteraction
  9095. private function FindNonActorTarget( actionCheck : bool, optional action : EBufferActionType ) : CGameplayEntity
  9096. {
  9097. var targetableEntities : array<CGameplayEntity>;
  9098. var selectedTargetableEntity : CGameplayEntity;
  9099. var selectionPriority : array< float >;
  9100. var selectionWeights : STargetSelectionWeights;
  9101. var findEntityDist : float;
  9102. var i, size : int;
  9103. var playerHeading : float;
  9104. var playerInventory : CInventoryComponent;
  9105. var castSignType : ESignType;
  9106. var targetingInfo : STargetingInfo;
  9107. var playerPosition : Vector;
  9108. var cameraPosition : Vector;
  9109. var playerHeadingVector : Vector;
  9110. var rawPlayerHeadingVector : Vector;
  9111.  
  9112. playerPosition = this.GetWorldPosition();
  9113. cameraPosition = theCamera.GetCameraPosition();
  9114. rawPlayerHeadingVector = VecFromHeading( rawPlayerHeading );
  9115.  
  9116. if ( bCanFindTarget && !IsHardLockEnabled() )
  9117. {
  9118. if ( actionCheck && IsInCombat() && action == EBAT_CastSign )
  9119. {
  9120. findEntityDist = 6.f;
  9121. selectionWeights.angleWeight = 0.375f;
  9122. selectionWeights.distanceWeight = 0.275f;
  9123. selectionWeights.distanceRingWeight = 0.35f;
  9124. }
  9125. else if ( !IsInCombat() && lastAxisInputIsMovement )
  9126. {
  9127. findEntityDist = softLockDist;
  9128. selectionWeights.angleWeight = 0.375f;
  9129. selectionWeights.distanceWeight = 0.275f;
  9130. selectionWeights.distanceRingWeight = 0.35f;
  9131. }
  9132. else
  9133. {
  9134. findEntityDist = softLockDist;
  9135. selectionWeights.angleWeight = 0.75f;
  9136. selectionWeights.distanceWeight = 0.125f;
  9137. selectionWeights.distanceRingWeight = 0.125f;
  9138. }
  9139.  
  9140. //MSTODO : Ask programmers for filter for interactive entities
  9141. if ( !IsInCombat() || !bLAxisReleased )
  9142. {
  9143. FindGameplayEntitiesInRange( targetableEntities, this, findEntityDist, 10, theGame.params.TAG_SOFT_LOCK );
  9144. }
  9145.  
  9146. if ( targetableEntities.Size() > 0 )
  9147. {
  9148. playerInventory = this.GetInventory();
  9149. castSignType = this.GetEquippedSign();
  9150.  
  9151. if ( !bLAxisReleased )
  9152. {
  9153. targetingInfo.source = this;
  9154. targetingInfo.canBeTargetedCheck = false;
  9155. targetingInfo.coneCheck = true;
  9156. targetingInfo.coneHalfAngleCos = 0.5f; // = CosF( Deg2Rad( 120.0f * 0.5f ) )
  9157. targetingInfo.coneDist = softLockDist;
  9158. targetingInfo.coneHeadingVector = rawPlayerHeadingVector;
  9159. targetingInfo.distCheck = true;
  9160. targetingInfo.invisibleCheck = false;
  9161. targetingInfo.navMeshCheck = false;
  9162. targetingInfo.frameScaleX = 1.0f;
  9163. targetingInfo.frameScaleY = 1.0f;
  9164. targetingInfo.knockDownCheck = false;
  9165. targetingInfo.knockDownCheckDist = 0.0f;
  9166. targetingInfo.rsHeadingCheck = false;
  9167. targetingInfo.rsHeadingLimitCos = 1.0f;
  9168. }
  9169.  
  9170. for( i = targetableEntities.Size()-1; i>=0; i-=1 )
  9171. {
  9172. if ( bLAxisReleased )
  9173. {
  9174. if ( !lastAxisInputIsMovement )
  9175. {
  9176. if ( !WasVisibleInScaledFrame( targetableEntities[i], 0.9f, 0.9f ) )
  9177. {
  9178. targetableEntities.Erase(i);
  9179. continue;
  9180. }
  9181. }
  9182. else if ( !WasVisibleInScaledFrame( targetableEntities[i], 1.f, 1.f ) )
  9183. {
  9184. targetableEntities.Erase(i);
  9185. continue;
  9186. }
  9187. }
  9188. else
  9189. {
  9190. targetingInfo.targetEntity = targetableEntities[i];
  9191. if ( actionCheck && moveTarget )
  9192. {
  9193. targetingInfo.inFrameCheck = false;
  9194. if ( !IsEntityTargetable( targetingInfo ) )
  9195. {
  9196. targetableEntities.Erase(i);
  9197. continue;
  9198. }
  9199. }
  9200. else
  9201. {
  9202. targetingInfo.inFrameCheck = true;
  9203. if ( !IsEntityTargetable( targetingInfo ) )
  9204. {
  9205. targetableEntities.Erase(i);
  9206. continue;
  9207. }
  9208. }
  9209. }
  9210.  
  9211. if ( actionCheck )
  9212. {
  9213. if ( action == EBAT_ItemUse )
  9214. {
  9215. if ( ( playerInventory.IsItemBomb( this.GetSelectedItemId() ) && !targetableEntities[i].HasTag( 'softLock_Bomb' ) )
  9216. || ( playerInventory.IsItemCrossbow( this.GetSelectedItemId() ) && !targetableEntities[i].HasTag( 'softLock_Bolt' ) ) )
  9217. {
  9218. targetableEntities.Erase(i);
  9219. continue;
  9220. }
  9221. }
  9222. else if ( action == EBAT_CastSign )
  9223. {
  9224. if ( ( castSignType == ST_Aard && !targetableEntities[i].HasTag( 'softLock_Aard' ) )
  9225. || ( castSignType == ST_Igni && !targetableEntities[i].HasTag( 'softLock_Igni' ) )
  9226. || ( castSignType == ST_Axii && !targetableEntities[i].HasTag( 'softLock_Axii' ) )
  9227. || castSignType == ST_Yrden
  9228. || castSignType == ST_Quen )
  9229. {
  9230. targetableEntities.Erase(i);
  9231. continue;
  9232. }
  9233. }
  9234. else if ( action == EBAT_LightAttack || action == EBAT_HeavyAttack || action == EBAT_SpecialAttack_Heavy )
  9235. {
  9236. if ( ( IsWeaponHeld( 'fist' ) && !targetableEntities[i].HasTag( 'softLock_Fist' ) ) || ( !IsWeaponHeld( 'fist' ) && !targetableEntities[i].HasTag( 'softLock_Weapon' ) ) )
  9237. {
  9238. targetableEntities.Erase(i);
  9239. continue;
  9240. }
  9241. }
  9242. else
  9243. {
  9244. targetableEntities.Erase(i);
  9245. continue;
  9246. }
  9247. }
  9248. }
  9249. }
  9250.  
  9251. if ( targetableEntities.Size() > 0)
  9252. {
  9253. playerHeading = this.GetHeading();
  9254. playerHeadingVector = this.GetHeadingVector();
  9255. if ( IsInCombat() )
  9256. {
  9257. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9258. {
  9259. if ( bLAxisReleased )
  9260. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, cameraPosition, rawPlayerHeadingVector ) );
  9261. else
  9262. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, rawPlayerHeadingVector ) );
  9263. }
  9264.  
  9265. if ( selectionPriority.Size() > 0 )
  9266. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9267. }
  9268. else
  9269. {
  9270. if ( bLAxisReleased )
  9271. {
  9272. if ( !lastAxisInputIsMovement )
  9273. {
  9274. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9275. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, cameraPosition, rawPlayerHeadingVector ) );
  9276.  
  9277. if ( selectionPriority.Size() > 0 )
  9278. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9279. }
  9280. else
  9281. {
  9282. if ( IsInCombatAction() )
  9283. selectedTargetableEntity = nonActorTarget;
  9284. else
  9285. {
  9286. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9287. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, playerHeadingVector ) );
  9288.  
  9289. if ( selectionPriority.Size() > 0 )
  9290. {
  9291. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9292.  
  9293. targetingInfo.source = this;
  9294. targetingInfo.targetEntity = selectedTargetableEntity;
  9295. targetingInfo.canBeTargetedCheck = false;
  9296. targetingInfo.coneCheck = true;
  9297. targetingInfo.coneHalfAngleCos = 0.0f; // = CosF( Deg2Rad( 180.0f * 0.5f ) )
  9298. targetingInfo.coneDist = softLockDist;
  9299. targetingInfo.coneHeadingVector = this.GetHeadingVector();
  9300. targetingInfo.distCheck = true;
  9301. targetingInfo.invisibleCheck = false;
  9302. targetingInfo.navMeshCheck = false;
  9303. targetingInfo.inFrameCheck = false;
  9304. targetingInfo.frameScaleX = 1.0f;
  9305. targetingInfo.frameScaleY = 1.0f;
  9306. targetingInfo.knockDownCheck = false;
  9307. targetingInfo.knockDownCheckDist = 0.0f;
  9308. targetingInfo.rsHeadingCheck = false;
  9309. targetingInfo.rsHeadingLimitCos = 1.0f;
  9310.  
  9311. if ( !IsEntityTargetable( targetingInfo ) )
  9312. selectedTargetableEntity = NULL;
  9313. }
  9314. }
  9315. }
  9316. }
  9317. else
  9318. {
  9319. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9320. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, rawPlayerHeadingVector ) );
  9321.  
  9322. if ( selectionPriority.Size() > 0 )
  9323. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9324. }
  9325. }
  9326. }
  9327. else
  9328. selectedTargetableEntity = NULL;
  9329. }
  9330.  
  9331. SetNonActorTarget( selectedTargetableEntity );
  9332. return selectedTargetableEntity;
  9333. }
  9334. /*
  9335. timer function IsItemUseInputHeld ( time : float , id : int)
  9336. {
  9337. if ( GetBIsInputAllowed()
  9338. && GetBIsCombatActionAllowed()
  9339. && IsActionAllowed( EIAB_Crossbow )
  9340. && inv.IsIdValid( GetSelectedItemId() )
  9341. && inv.IsItemCrossbow( GetSelectedItemId()En )
  9342. && rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' )
  9343. {
  9344. SetIsAimingCrossbow( true );
  9345. PushCombatActionOnBuffer( EBAT_ItemUse, BS_Pressed );
  9346. ProcessCombatActionBuffer();
  9347. }
  9348.  
  9349. if ( theInput.GetActionValue( 'ThrowItem' ) == 0.f )
  9350. {
  9351. if ( GetBIsCombatActionAllowed() )
  9352. {
  9353. PushCombatActionOnBuffer( EBAT_ItemUse, BS_Pressed );
  9354. ProcessCombatActionBuffer();
  9355. }
  9356.  
  9357. SetIsAimingCrossbow( false );
  9358. RemoveTimer( 'IsItemUseInputHeld' );
  9359. }
  9360. }*/
  9361.  
  9362. public function SetupCombatAction( action : EBufferActionType, stage : EButtonStage )
  9363. {
  9364. var weaponType : EPlayerWeapon;
  9365. var canAttackTarget : CGameplayEntity;
  9366. var target : CActor;
  9367.  
  9368. /*if( thePlayer.substateManager.GetStateCur() == 'Slide' )
  9369. {
  9370. return;
  9371. }*/
  9372. if ( !IsCombatMusicEnabled() )
  9373. {
  9374. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  9375. FindTarget();
  9376. UpdateDisplayTarget( true );
  9377. }
  9378.  
  9379. if ( displayTarget && IsDisplayTargetTargetable() )
  9380. canAttackTarget = displayTarget;
  9381. else if ( GetTarget() )
  9382. canAttackTarget = GetTarget();
  9383. else if( !target && IsCombatMusicEnabled() )
  9384. canAttackTarget = moveTarget;
  9385.  
  9386. target = (CActor)canAttackTarget;
  9387.  
  9388. if ( !AllowAttack( target, action ) )
  9389. return;
  9390.  
  9391. if( ( action != EBAT_ItemUse ) && ( action != EBAT_CastSign ) )
  9392. {
  9393. weaponType = weaponHolster.GetCurrentMeleeWeapon();
  9394. PrepareToAttack( target, action );
  9395.  
  9396. //Do not automatically attack when drawing sword
  9397. if ( weaponType != weaponHolster.GetCurrentMeleeWeapon() )
  9398. {
  9399. //Check if switching from PW_None to PW_Fists. If so, allow the attack
  9400. if ( !( weaponType == PW_None && weaponHolster.GetCurrentMeleeWeapon() == PW_Fists ) )
  9401. return;
  9402. }
  9403. }
  9404.  
  9405. //geralt's special attack heavy
  9406. if(action == EBAT_SpecialAttack_Heavy && !((W3ReplacerCiri)this) )
  9407. thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s02));
  9408.  
  9409. CriticalEffectAnimationInterrupted("SetupCombatAction " + action);
  9410. PushCombatActionOnBuffer( action, stage );
  9411.  
  9412. if( GetBIsCombatActionAllowed() )
  9413. {
  9414. ProcessCombatActionBuffer();
  9415. }
  9416. }
  9417.  
  9418. public function AllowAttack( target : CActor, action : EBufferActionType ) : bool
  9419. {
  9420. var newTarget : CActor;
  9421. var canAttackWhenNotInCombat : bool;
  9422. var messageDisplayed : bool;
  9423.  
  9424. var itemId : SItemUniqueId;
  9425. var isShootingCrossbow : bool;
  9426.  
  9427. var isInCorrectState : bool;
  9428.  
  9429. if ( target )
  9430. {
  9431. if ( target.IsTargetableByPlayer())
  9432. {
  9433. if ( !target.IsAttackableByPlayer() )
  9434. {
  9435. DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_cant_attack_this_target"));
  9436. return false;
  9437. }
  9438. }
  9439. }
  9440.  
  9441. if ( this.GetCurrentStateName() == 'Exploration' )
  9442. isInCorrectState = true;
  9443.  
  9444. if ( action == EBAT_ItemUse )
  9445. {
  9446. itemId = thePlayer.GetSelectedItemId();
  9447. if ( inv.IsIdValid(itemId) && inv.IsItemCrossbow(itemId) )
  9448. isShootingCrossbow = true;
  9449.  
  9450. if ( !isInCorrectState )
  9451. {
  9452. if ( this.GetCurrentStateName() == 'AimThrow' && !isShootingCrossbow )
  9453. {
  9454. isInCorrectState = true;
  9455. }
  9456. }
  9457. }
  9458.  
  9459. if ( isInCorrectState )
  9460. canAttackWhenNotInCombat = thePlayer.CanAttackWhenNotInCombat( action, false, newTarget, target );
  9461.  
  9462. if( !target )
  9463. {
  9464. if ( isInCorrectState )
  9465. {
  9466. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  9467. target = newTarget;
  9468. }
  9469. }
  9470.  
  9471. if ( isInCorrectState )
  9472. {
  9473. if ( !canAttackWhenNotInCombat )
  9474. {
  9475. if ( DisplayCannotAttackMessage( target ) )
  9476. messageDisplayed = true;
  9477. else if ( ( action == EBAT_LightAttack || action == EBAT_HeavyAttack )
  9478. && !RaiseAttackFriendlyEvent( target ) )
  9479. messageDisplayed = true;
  9480. else
  9481. {
  9482. if ( !CanRaiseCombatActionFriendlyEvent( isShootingCrossbow ) )
  9483. messageDisplayed = true;
  9484. }
  9485. }
  9486.  
  9487. if ( messageDisplayed )
  9488. {
  9489. theInput.ForceDeactivateAction('ThrowItem');
  9490. theInput.ForceDeactivateAction('ThrowItemHold');
  9491. this.SignalGameplayEvent( 'FriendlyAttackAction' );
  9492. return false;
  9493. }
  9494. }
  9495.  
  9496. return true;
  9497. }
  9498.  
  9499.  
  9500. //returns true if processed
  9501. public function ProcessCombatActionBuffer() : bool
  9502. {
  9503. var actionResult : bool;
  9504. var action : EBufferActionType = this.BufferCombatAction;
  9505. var stage : EButtonStage = this.BufferButtonStage;
  9506. var s : SNotWorkingOutFunctionParametersHackStruct1;
  9507. var allSteps : bool = this.BufferAllSteps;
  9508.  
  9509. if ( IsInCombatActionFriendly() )
  9510. {
  9511. RaiseEvent('CombatActionFriendlyEnd');
  9512. }
  9513.  
  9514. //Disable any npcs that are set to unpushable when Player performs another combat action
  9515. if ( ( action != EBAT_SpecialAttack_Heavy && action != EBAT_ItemUse )
  9516. || ( action == EBAT_SpecialAttack_Heavy && stage == BS_Pressed )
  9517. || ( action == EBAT_ItemUse && stage != BS_Released ) )
  9518. {
  9519. GetMovingAgentComponent().GetMovementAdjustor().CancelAll();
  9520. SetUnpushableTarget( NULL );
  9521. }
  9522.  
  9523. //if ( !( action == EBAT_Dodge && stage == BS_Pressed && IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge ) )
  9524. if ( !( action == EBAT_Dodge || action == EBAT_Roll ) )
  9525. {
  9526. SetIsCurrentlyDodging(false);
  9527.  
  9528. //-- init
  9529. }
  9530.  
  9531. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  9532.  
  9533. //theGame.GetSyncAnimManager().OnRemoveFinisherCameraAnimation();
  9534.  
  9535. if ( action == EBAT_ItemUse && GetInventory().IsItemCrossbow( selectedItemId ) )
  9536. {
  9537. //stage == BS_Pressed &&
  9538. if ( rangedWeapon
  9539. && ( ( rangedWeapon.GetCurrentStateName() != 'State_WeaponShoot' && rangedWeapon.GetCurrentStateName() != 'State_WeaponAim' ) || GetIsShootingFriendly() ) )
  9540. {
  9541. SetSlideTarget( GetCombatActionTarget( action ) );
  9542. }
  9543. }
  9544. else if ( !( ( action == EBAT_SpecialAttack_Heavy && stage == BS_Released ) || GetCurrentStateName() == 'AimThrow' ) )
  9545. {
  9546. SetSlideTarget( GetCombatActionTarget( action ) );
  9547. }
  9548.  
  9549. if( !slideTarget )
  9550. LogChannel( 'Targeting', "NO SLIDE TARGET" );
  9551.  
  9552. //-- process
  9553. actionResult = true;
  9554.  
  9555. switch ( action )
  9556. {
  9557. case EBAT_EMPTY :
  9558. {
  9559. this.BufferAllSteps = false;
  9560. return true;
  9561. } break;
  9562.  
  9563. case EBAT_LightAttack :
  9564. {
  9565. if ( IsCiri() )
  9566. return false;
  9567.  
  9568. switch ( stage )
  9569. {
  9570. case BS_Pressed ://BS_Released :
  9571. {
  9572. // early out, stamina drain etc
  9573. //if( HasStaminaToUseAction(ESAT_LightAttack) )
  9574. //{
  9575.  
  9576. // replacing stamina lock with stamina drain - change in design
  9577. /*
  9578. s = LockStamina(ESAT_LightAttack);
  9579. if(s.retValue)
  9580. {
  9581. AddCombatActionStaminaLock(s.outValue);
  9582. }
  9583. */
  9584. DrainStamina(ESAT_LightAttack);
  9585. //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack );
  9586.  
  9587. thePlayer.BreakPheromoneEffect();
  9588. actionResult = OnPerformAttack(theGame.params.ATTACK_NAME_LIGHT);
  9589. //}
  9590. } break;
  9591.  
  9592. default :
  9593. {
  9594. actionResult = false;
  9595. }break;
  9596. }
  9597. }break;
  9598.  
  9599. case EBAT_HeavyAttack :
  9600. {
  9601. if ( IsCiri() )
  9602. return false;
  9603.  
  9604. switch ( stage )
  9605. {
  9606. case BS_Released :
  9607. {
  9608. // early out, stamina drain etc
  9609. //if( HasStaminaToUseAction(ESAT_HeavyAttack) )
  9610. //{
  9611. // replacing stamina lock with stamina drain - change in design
  9612. /*
  9613. s = LockStamina(ESAT_HeavyAttack);
  9614. if(s.retValue)
  9615. {
  9616. AddCombatActionStaminaLock(s.outValue);
  9617. }
  9618. */
  9619. DrainStamina(ESAT_HeavyAttack);
  9620.  
  9621. //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack );
  9622.  
  9623. thePlayer.BreakPheromoneEffect();
  9624. actionResult = this.OnPerformAttack(theGame.params.ATTACK_NAME_HEAVY);
  9625. //}
  9626. } break;
  9627.  
  9628. case BS_Pressed :
  9629. {
  9630. if ( this.GetCurrentStateName() == 'CombatFists' )
  9631. {
  9632. // early out, stamina drain etc
  9633. //if( HasStaminaToUseAction(ESAT_HeavyAttack) )
  9634. //{
  9635. // replacing stamina lock with stamina drain - change in design
  9636. /*
  9637. s = LockStamina(ESAT_HeavyAttack);
  9638. if(s.retValue)
  9639. {
  9640. AddCombatActionStaminaLock(s.outValue);
  9641. }
  9642. */
  9643. DrainStamina(ESAT_HeavyAttack);
  9644.  
  9645. //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack );
  9646.  
  9647. thePlayer.BreakPheromoneEffect();
  9648. actionResult = this.OnPerformAttack(theGame.params.ATTACK_NAME_HEAVY);
  9649. //}
  9650. }
  9651. } break;
  9652.  
  9653. default :
  9654. {
  9655. actionResult = false;
  9656.  
  9657. } break;
  9658. }
  9659. } break;
  9660.  
  9661. case EBAT_ItemUse : //this gets called only for bombs. No usable items use this!
  9662. {
  9663. switch ( stage )
  9664. {
  9665. case BS_Pressed :
  9666. {
  9667. if ( !( (W3PlayerWitcher)this ) ||
  9668. ( !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) ) ) )
  9669. //( !IsCastingSign() && !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) ) )
  9670. {
  9671. if ( inv.IsItemCrossbow( selectedItemId ) )
  9672. {
  9673. rangedWeapon = ( Crossbow )( inv.GetItemEntityUnsafe( selectedItemId ) );
  9674. rangedWeapon.OnRangedWeaponPress();
  9675. GetTarget().SignalGameplayEvent( 'Approach' );
  9676. GetTarget().SignalGameplayEvent( 'ShootingCrossbow' );
  9677. }
  9678. else if(inv.IsItemBomb(selectedItemId) && this.inv.SingletonItemGetAmmo(selectedItemId) > 0 )
  9679. {
  9680. BombThrowStart();
  9681. GetTarget().SignalGameplayEvent( 'Approach' );
  9682. }
  9683. if( ((W3PlayerWitcher)this).GetBombDelay( ((W3PlayerWitcher)this).GetItemSlot( selectedItemId ) ) <= 0.0f )
  9684. {
  9685. BombThrowStart();
  9686. GetTarget().SignalGameplayEvent( 'Approach' );
  9687. }
  9688. }
  9689. else
  9690. {
  9691. DrainStamina(ESAT_UsableItem);
  9692. UsableItemStart();
  9693. }
  9694. }
  9695.  
  9696. } if (!allSteps) break;
  9697.  
  9698. case BS_Released:
  9699. {
  9700. if ( !( (W3PlayerWitcher)this ) ||
  9701. ( !IsInCombatActionFriendly() && ( GetBIsCombatActionAllowed() || !( !GetBIsCombatActionAllowed() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) ) ) ) )
  9702. //( !IsCastingSign() && !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) ) )
  9703. {
  9704. if ( inv.IsItemCrossbow( selectedItemId ) )
  9705. {
  9706. /*if ( rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' )
  9707. {
  9708. rangedWeapon = ( Crossbow )( inv.GetItemEntityUnsafe( selectedItemId ) );
  9709. rangedWeapon.OnRangedWeaponPress();
  9710. }*/
  9711. rangedWeapon.OnRangedWeaponRelease();
  9712. }
  9713. else if(inv.IsItemBomb(selectedItemId))
  9714. {
  9715. BombThrowRelease();
  9716. }
  9717. else
  9718. {
  9719. UsableItemRelease();
  9720. }
  9721. }
  9722. } break;
  9723.  
  9724. default :
  9725. {
  9726. actionResult = false;
  9727. break;
  9728. }
  9729. }
  9730. } break;
  9731.  
  9732. case EBAT_Dodge :
  9733. {
  9734. switch ( stage )
  9735. {
  9736. case BS_Released :
  9737. {
  9738. theGame.GetBehTreeReactionManager().CreateReactionEvent( this, 'PlayerEvade', 1.0f, 10.0f, -1.0f, -1 );
  9739. thePlayer.BreakPheromoneEffect();
  9740. actionResult = this.OnPerformEvade( PET_Dodge );
  9741. } break;
  9742.  
  9743. /*case BS_Pressed :
  9744. {
  9745. actionResult = this.OnPerformEvade( PET_Roll );
  9746. } break;*/
  9747.  
  9748. default :
  9749. {
  9750. actionResult = false;
  9751. } break;
  9752. }
  9753. } break;
  9754.  
  9755. case EBAT_Roll :
  9756. {
  9757. if ( IsCiri() )
  9758. return false;
  9759.  
  9760. switch ( stage )
  9761. {
  9762. case BS_Released :
  9763. {
  9764. theGame.GetBehTreeReactionManager().CreateReactionEvent( this, 'PlayerEvade', 1.0f, 10.0f, -1.0f, -1 );
  9765. thePlayer.BreakPheromoneEffect();
  9766. actionResult = this.OnPerformEvade( PET_Roll );
  9767. } break;
  9768.  
  9769. case BS_Pressed :
  9770. {
  9771. if ( this.GetBehaviorVariable( 'combatActionType' ) == 2.f )
  9772. {
  9773. if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' )
  9774. actionResult = this.OnPerformEvade( PET_Pirouette );
  9775. else
  9776. actionResult = this.OnPerformEvade( PET_Roll );
  9777. }
  9778. else
  9779. {
  9780. if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' )
  9781. {
  9782. actionResult = this.OnPerformEvade( PET_Dodge );
  9783. actionResult = this.OnPerformEvade( PET_Pirouette );
  9784. }
  9785. else
  9786. {
  9787. actionResult = this.OnPerformEvade( PET_Dodge );
  9788. actionResult = this.OnPerformEvade( PET_Roll );
  9789. }
  9790. }
  9791.  
  9792.  
  9793. } break;
  9794.  
  9795. default :
  9796. {
  9797. actionResult = false;
  9798. } break;
  9799. }
  9800. } break;
  9801.  
  9802. case EBAT_Draw_Steel :
  9803. {
  9804. switch ( stage )
  9805. {
  9806. case BS_Pressed :
  9807. {
  9808. if( !IsActionAllowed(EIAB_DrawWeapon) )
  9809. {
  9810. thePlayer.DisplayActionDisallowedHudMessage(EIAB_DrawWeapon);
  9811. actionResult = false;
  9812. break;
  9813. }
  9814. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'steelsword' ) )
  9815. {
  9816. OnEquipMeleeWeapon( PW_Steel, false, true );
  9817. }
  9818.  
  9819. actionResult = false;
  9820.  
  9821. } break;
  9822.  
  9823. default :
  9824. {
  9825. actionResult = false;
  9826. } break;
  9827. }
  9828. } break;
  9829.  
  9830. case EBAT_Draw_Silver :
  9831. {
  9832. switch ( stage )
  9833. {
  9834. case BS_Pressed :
  9835. {
  9836. if( !IsActionAllowed(EIAB_DrawWeapon) )
  9837. {
  9838. thePlayer.DisplayActionDisallowedHudMessage(EIAB_DrawWeapon);
  9839. actionResult = false;
  9840. break;
  9841. }
  9842. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'silversword' ) )
  9843. {
  9844. OnEquipMeleeWeapon( PW_Silver, false, true );
  9845. }
  9846.  
  9847. actionResult = false;
  9848.  
  9849. } break;
  9850.  
  9851. default :
  9852. {
  9853. actionResult = false;
  9854. } break;
  9855. }
  9856. } break;
  9857.  
  9858. case EBAT_Sheathe_Sword :
  9859. {
  9860. switch ( stage )
  9861. {
  9862. case BS_Pressed :
  9863. {
  9864. if( GetCurrentMeleeWeaponType() == PW_Silver )
  9865. {
  9866. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'silversword' ) )
  9867. {
  9868. OnEquipMeleeWeapon( PW_Silver, false, true );
  9869. }
  9870. }
  9871. else if( GetCurrentMeleeWeaponType() == PW_Steel )
  9872. {
  9873. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'steelsword' ) )
  9874. {
  9875. OnEquipMeleeWeapon( PW_Steel, false, true );
  9876. }
  9877. }
  9878.  
  9879. actionResult = false;
  9880.  
  9881. } break;
  9882.  
  9883. default :
  9884. {
  9885. actionResult = false;
  9886. } break;
  9887. }
  9888. } break;
  9889.  
  9890. default:
  9891. return false; //not processed
  9892. }
  9893.  
  9894. //if here then buffer was processed
  9895. CleanCombatActionBuffer();
  9896.  
  9897. if (actionResult)
  9898. {
  9899. SetCombatAction( action ) ;
  9900.  
  9901. if(GetWitcherPlayer().IsInFrenzy())
  9902. GetWitcherPlayer().SkillFrenzyFinish(0);
  9903. }
  9904.  
  9905. return true;
  9906. }
  9907.  
  9908. public function CleanCombatActionBuffer()
  9909. {
  9910. BufferCombatAction = EBAT_EMPTY;
  9911. BufferAllSteps = false;
  9912. }
  9913.  
  9914. public function CancelHoldAttacks()
  9915. {
  9916. thePlayer.RemoveTimer( 'IsSpecialLightAttackInputHeld' );
  9917. thePlayer.RemoveTimer( 'IsSpecialHeavyAttackInputHeld' );
  9918. thePlayer.RemoveTimer( 'SpecialAttackLightSustainCost' );
  9919. thePlayer.RemoveTimer( 'SpecialAttackHeavySustainCost' );
  9920. thePlayer.RemoveTimer( 'UpdateSpecialAttackLightHeading' );
  9921. thePlayer.UnblockAction( EIAB_Crossbow, 'SpecialAttack' );
  9922.  
  9923. if ( thePlayer.GetBehaviorVariable( 'combatActionType' ) == (int)CAT_SpecialAttack )
  9924. ResumeStaminaRegen('WhirlSkill');
  9925.  
  9926. if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_SpecialAttack && GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.f )
  9927. {
  9928. if( thePlayer.GetBehaviorVariable( 'playerAttackType' ) == (int)PAT_Light
  9929. && thePlayer.GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.f )
  9930. {
  9931. thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s01));
  9932. thePlayer.PushCombatActionOnBuffer( EBAT_SpecialAttack_Light, BS_Released );
  9933. thePlayer.ProcessCombatActionBuffer();
  9934. //thePlayer.SetupCombatAction( EBAT_SpecialAttack_Light, BS_Released );
  9935. ((W3PlayerWitcherStateCombatFists) GetState('Combat')).ResetTimeToEndCombat();
  9936.  
  9937. }
  9938. else if( thePlayer.GetBehaviorVariable( 'playerAttackType' ) == (int)PAT_Heavy
  9939. && thePlayer.GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.f )
  9940. {
  9941. thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s02));
  9942. thePlayer.PushCombatActionOnBuffer( EBAT_SpecialAttack_Heavy, BS_Released );
  9943. thePlayer.ProcessCombatActionBuffer();
  9944. //thePlayer.SetupCombatAction( EBAT_SpecialAttack_Heavy, BS_Released );
  9945. }
  9946. }
  9947. }
  9948.  
  9949. public function RaiseAttackFriendlyEvent( actor : CActor ) : bool
  9950. {
  9951. var playerToTargetHeading : float;
  9952.  
  9953. if ( actor && RaiseCombatActionFriendlyEvent() )
  9954. {
  9955. SetBehaviorVariable( 'tauntTypeForOverlay', 0.f );
  9956. SetBehaviorVariable( 'combatActionTypeForOverlay', (int)CAT_Attack );
  9957.  
  9958. if ( actor )
  9959. actor.SignalGameplayEvent('PersonalTauntAction');
  9960. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'TauntAction', -1.0, 4.5f, -1, 9999, true ); //reactionSystemSearch
  9961.  
  9962. OnCombatActionStart();
  9963.  
  9964. playerToTargetHeading = VecHeading( actor.GetWorldPosition() - GetWorldPosition() );
  9965.  
  9966. SetCustomRotation( 'Attack', playerToTargetHeading, 0.0f, 0.3f, false );
  9967.  
  9968. return true;
  9969. }
  9970.  
  9971. return false;
  9972. }
  9973.  
  9974. public function SendAttackReactionEvent()
  9975. {
  9976. var reactionName : name;
  9977.  
  9978. /*switch ( action )
  9979. {
  9980. case EBAT_LightAttack :
  9981. reactionName = 'AttackAction';
  9982. break;
  9983. case EBAT_HeavyAttack :
  9984. reactionName = 'AttackAction';
  9985. break;
  9986. case EBAT_SpecialAttack_Light :
  9987. reactionName = 'AttackAction';
  9988. break;
  9989. case EBAT_SpecialAttack_Heavy :
  9990. reactionName = 'AttackAction';
  9991. break;
  9992. case EBAT_Ciri_SpecialAttack :
  9993. reactionName = 'AttackAction';
  9994. break;
  9995. default:
  9996. return;
  9997. }*/
  9998.  
  9999. reactionName = 'AttackAction';
  10000.  
  10001. if ( IsNameValid(reactionName) )
  10002. {
  10003. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, reactionName, -1.0, 8.0f, -1, 5, true ); //reactionSystemSearch
  10004. }
  10005.  
  10006. // event for horse - trigger running away
  10007. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'outOfMyWay', -1.0, 2.0f, -1, 5, true ); //reactionSystemSearch
  10008. }
  10009.  
  10010. var forceCanAttackWhenNotInCombat : int; // 0 = NoForce, 1 = ForceWhenNoDisplayTarget 2 = ForceEvenWithDisplayTarget
  10011. public function SetForceCanAttackWhenNotInCombat( forceMode : int )
  10012. {
  10013. forceCanAttackWhenNotInCombat = forceMode;
  10014. }
  10015.  
  10016. public function CanAttackWhenNotInCombat( actionType : EBufferActionType, altCast : bool, out newTarget : CActor, optional target : CGameplayEntity ) : bool
  10017. {
  10018. var localTargets : array<CActor>;
  10019. var i, size : int;
  10020. var inputHeading : float;
  10021. var clearanceMin, clearanceMax : float;
  10022. var attackLength : float;
  10023. var attackAngle : float;
  10024. var npc : CNewNPC;
  10025. var canAttackTarget : CGameplayEntity;
  10026. var canAttackTargetActor : CActor;
  10027.  
  10028. if ( target )
  10029. canAttackTarget = target;
  10030. else if ( displayTarget && IsDisplayTargetTargetable() )
  10031. canAttackTarget = displayTarget;
  10032. else
  10033. canAttackTarget = slideTarget;
  10034.  
  10035. canAttackTargetActor = (CActor)canAttackTarget;
  10036.  
  10037. if ( forceCanAttackWhenNotInCombat == 2 )
  10038. return true;
  10039. else if ( forceCanAttackWhenNotInCombat == 1 && ( !canAttackTarget || !canAttackTargetActor.IsHuman() ) )
  10040. return true;
  10041.  
  10042. if ( actionType == EBAT_CastSign )
  10043. {
  10044. if ( thePlayer.GetEquippedSign() != ST_Quen && thePlayer.GetEquippedSign() != ST_Axii )
  10045. {
  10046. if ( CanUseSkill( S_Magic_s20 ) )
  10047. {
  10048. if ( thePlayer.GetEquippedSign() == ST_Aard )
  10049. attackLength = 6.f;
  10050. else if ( thePlayer.GetEquippedSign() == ST_Igni )
  10051. attackLength = 4.f;
  10052. else
  10053. attackLength = 6.f;
  10054. }
  10055. else
  10056. {
  10057. if ( thePlayer.GetEquippedSign() == ST_Aard )
  10058. attackLength = 9.f;
  10059. else if ( thePlayer.GetEquippedSign() == ST_Igni )
  10060. attackLength = 6.f;
  10061. else
  10062. attackLength = 6.f;
  10063. }
  10064.  
  10065. if ( altCast )
  10066. attackAngle = 180.f;
  10067. else
  10068. // sign cone angle / 2 with a bonus for safetey
  10069. attackAngle = 90.f;
  10070.  
  10071. if ( !lastAxisInputIsMovement )
  10072. inputHeading = VecHeading( theCamera.GetCameraDirection() );
  10073. else if ( lAxisReleasedAfterCounter )
  10074. inputHeading = GetHeading();
  10075. else
  10076. inputHeading = GetCombatActionHeading();
  10077.  
  10078. clearanceMin = 1.f;
  10079. clearanceMax = attackLength + 1.f;
  10080. }
  10081. else if ( thePlayer.GetEquippedSign() == ST_Axii )
  10082. {
  10083. npc = (CNewNPC)canAttackTarget;
  10084. if ( npc && npc.GetNPCType() == ENGT_Quest && !npc.HasTag(theGame.params.TAG_AXIIABLE_LOWER_CASE) && !npc.HasTag(theGame.params.TAG_AXIIABLE))
  10085. return false;
  10086. else if ( npc && npc.IsUsingHorse() )
  10087. return false;
  10088. else
  10089. return true;
  10090. }
  10091. else
  10092. return true;
  10093. }
  10094. else if ( actionType == EBAT_ItemUse )
  10095. {
  10096. attackLength = theGame.params.MAX_THROW_RANGE;
  10097. attackAngle = 90.f;
  10098.  
  10099. if ( thePlayer.lastAxisInputIsMovement )
  10100. inputHeading = GetCombatActionHeading();
  10101. else
  10102. inputHeading = VecHeading( theCamera.GetCameraDirection() );
  10103.  
  10104. clearanceMin = 0.8f;
  10105. clearanceMax = attackLength + 3.f;
  10106. }
  10107. else
  10108. {
  10109. if ( actionType == EBAT_SpecialAttack_Light || actionType == EBAT_SpecialAttack_Heavy )
  10110. {
  10111. attackLength = 1.9f;
  10112. attackAngle = 90.f;
  10113. }
  10114. else
  10115. {
  10116. if( thePlayer.GetCurrentMeleeWeaponType() == PW_Fists || thePlayer.GetCurrentMeleeWeaponType() == PW_None )
  10117. attackLength = 1.2f;
  10118. else
  10119. attackLength = 1.9f;
  10120.  
  10121. attackAngle = 90.f;
  10122. }
  10123.  
  10124. if ( lastAxisInputIsMovement )
  10125. inputHeading = GetCombatActionHeading();
  10126. else
  10127. inputHeading = VecHeading( theCamera.GetCameraDirection() );
  10128.  
  10129. clearanceMin = attackLength / 2.f;
  10130. clearanceMax = attackLength + 3.f;
  10131. }
  10132.  
  10133. //Use slideTarget first if it's NULL, then we try other npcs in the area
  10134. if ( canAttackTarget )
  10135. {
  10136. if ( ( canAttackTargetActor && canAttackTargetActor.IsHuman() ) || canAttackTargetActor.HasTag( 'softLock_Friendly' ) )
  10137. {
  10138. if ( ShouldPerformFriendlyAction( canAttackTargetActor, inputHeading, attackAngle, clearanceMin, clearanceMax ) )
  10139. {
  10140. SetSlideTarget( canAttackTargetActor );
  10141. newTarget = canAttackTargetActor;
  10142. return false;
  10143. }
  10144. }
  10145.  
  10146. //return true;
  10147. }
  10148.  
  10149. return true;
  10150.  
  10151. thePlayer.GetVisibleEnemies( localTargets );
  10152. size = localTargets.Size();
  10153.  
  10154. if ( size > 0 )
  10155. {
  10156. for ( i = size-1; i>=0; i-=1 )
  10157. {
  10158. /*
  10159. Andrzej: Geralt's friendly combat action - taunting actors with a sword or playing with Signs is set to work only for humans.
  10160. 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.
  10161. If you want Geralt to play friendly combat action when targeting monsters, add tag softLock_Friendly to monster's entity.
  10162. */
  10163. if ( !localTargets[i].IsHuman() && !localTargets[i].HasTag( 'softLock_Friendly' ) )
  10164. localTargets.Erase(i);
  10165. }
  10166. }
  10167.  
  10168. size = localTargets.Size();
  10169. if ( size > 0 )
  10170. {
  10171. for ( i = 0; i < localTargets.Size(); i += 1 )
  10172. {
  10173. if ( ShouldPerformFriendlyAction( localTargets[i], inputHeading, attackAngle, clearanceMin, clearanceMax ) )
  10174. {
  10175. SetSlideTarget( localTargets[i] );
  10176. newTarget = localTargets[i];
  10177. return false;
  10178. }
  10179. }
  10180. }
  10181.  
  10182. newTarget = NULL;
  10183.  
  10184. return true;
  10185. }
  10186.  
  10187. private function ShouldPerformFriendlyAction( actor : CActor, inputHeading, attackAngle, clearanceMin, clearanceMax : float ) : bool
  10188. {
  10189. var npc : CNewNPC;
  10190. var argh : float;
  10191. var playerToTargetDist : float;
  10192.  
  10193. npc = (CNewNPC)actor;
  10194.  
  10195. if ( npc &&
  10196. ( GetAttitudeBetween(thePlayer, npc) == AIA_Hostile || ( GetAttitudeBetween(thePlayer, npc) == AIA_Neutral && npc.GetNPCType() != ENGT_Guard ) ) )
  10197. {
  10198. }
  10199. else
  10200. {
  10201. playerToTargetDist = VecDistance( this.GetWorldPosition(), actor.PredictWorldPosition( 0.5f ) ); //actor.GetNearestPointInPersonalSpace( this.GetWorldPosition() ) );
  10202.  
  10203. argh = AbsF( AngleDistance( inputHeading, VecHeading( actor.GetWorldPosition() - thePlayer.GetWorldPosition() ) ) );
  10204.  
  10205. if ( AbsF( AngleDistance( inputHeading, VecHeading( actor.GetWorldPosition() - thePlayer.GetWorldPosition() ) ) ) < attackAngle )
  10206. {
  10207. if ( playerToTargetDist < clearanceMax )
  10208. {
  10209. return true;
  10210. }
  10211. }
  10212. else
  10213. {
  10214. if ( playerToTargetDist < clearanceMin )
  10215. {
  10216. return true;
  10217. }
  10218. }
  10219. }
  10220.  
  10221. return false;
  10222. }
  10223.  
  10224. ///////////////////////////////////////////////////////////////////////////
  10225. // HUD //#B
  10226. ///////////////////////////////////////////////////////////////////////////
  10227.  
  10228. public function GetHudMessagesSize() : int
  10229. {
  10230. return HudMessages.Size();
  10231. }
  10232.  
  10233. public function GetHudPendingMessage() : string
  10234. {
  10235. return HudMessages[0];
  10236. }
  10237.  
  10238. public function DisplayHudMessage( value : string ) : void
  10239. {
  10240. if (value == "")
  10241. {
  10242. return;
  10243. }
  10244.  
  10245. if( GetHudMessagesSize() > 0 )
  10246. {
  10247. if( HudMessages[HudMessages.Size()-1] == value )
  10248. {
  10249. return;
  10250. }
  10251. }
  10252. HudMessages.PushBack(value);
  10253. }
  10254.  
  10255. //hacks for review requests
  10256. private final function DisallowedActionDontShowHack(action : EInputActionBlock) : bool
  10257. {
  10258. var locks : array< SInputActionLock >;
  10259. var i : int;
  10260.  
  10261. //no info if we're trying to attack while staggered
  10262. 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)) )
  10263. {
  10264. return true;
  10265. }
  10266.  
  10267. //always show meditation message
  10268.  
  10269. if( action == EIAB_ThrowBomb && ( HasBuff( EET_Hypnotized ) || HasBuff( EET_Confusion ) ) )
  10270. {
  10271. return false;
  10272. }
  10273.  
  10274.  
  10275. if(isTimeLock)
  10276. return false;
  10277.  
  10278.  
  10279. if(action == EIAB_OpenMeditation)
  10280. return false;
  10281.  
  10282. //if there's at least one lock from quest or from location fine
  10283. locks = GetActionLocks(action);
  10284. for(i=0; i<locks.Size(); i+=1)
  10285. {
  10286. if(locks[i].isFromQuest || locks[i].isFromPlace)
  10287. return false;
  10288. }
  10289.  
  10290. if ( this.IsCurrentlyUsingItemL() )
  10291. {
  10292. if ( action == EIAB_HeavyAttacks || action == EIAB_Parry )
  10293. return false;
  10294. }
  10295.  
  10296. //otherwise we don't display locks
  10297. return true;
  10298. }
  10299.  
  10300. public final function DisplayActionDisallowedHudMessage(action : EInputActionBlock, optional isCombatLock : bool, optional isPlaceLock : bool, optional isTimeLock : bool, optional isDangerous : bool)
  10301. {
  10302. var lockType : name;
  10303.  
  10304. if(action != EIAB_Undefined && DisallowedActionDontShowHack(action))
  10305. return;
  10306.  
  10307. //combat lock is strongest - overrides all
  10308. if(IsInCombat() && !IsActionCombat(action))
  10309. isCombatLock = true;
  10310.  
  10311. //if no specific lock set, check based on action
  10312. if(!isCombatLock && !isPlaceLock && ! isTimeLock && action != EIAB_Undefined)
  10313. {
  10314. lockType = inputHandler.GetActionBlockedHudLockType(action);
  10315.  
  10316. if(lockType == 'combat')
  10317. isCombatLock = true;
  10318. else if(lockType == 'place')
  10319. isPlaceLock = true;
  10320. else if(lockType == 'time')
  10321. isTimeLock = true;
  10322. }
  10323.  
  10324. if(isDangerous)
  10325. {
  10326. DisplayHudMessage(GetLocStringByKeyExt( "message_meditation_too_dangerous" ));
  10327. }
  10328. else if(isCombatLock)
  10329. {
  10330. DisplayHudMessage(GetLocStringByKeyExt( "panel_hud_message_actionnotallowed_combat" ));
  10331. }
  10332. else if(isPlaceLock)
  10333. {
  10334. DisplayHudMessage(GetLocStringByKeyExt( "menu_cannot_perform_action_here" ));
  10335. }
  10336. else if(isTimeLock)
  10337. {
  10338. DisplayHudMessage(GetLocStringByKeyExt( "menu_cannot_perform_action_now" ));
  10339. }
  10340. }
  10341.  
  10342. //removes first or all instances of given message
  10343. public function RemoveHudMessageByString(msg : string, optional allQueuedInstances : bool)
  10344. {
  10345. var i, j : int;
  10346.  
  10347. for(i=0; i<HudMessages.Size(); i+=1)
  10348. {
  10349. if(HudMessages[i] == msg)
  10350. {
  10351. HudMessages.EraseFast(i);
  10352.  
  10353. if(!allQueuedInstances)
  10354. return;
  10355.  
  10356. break;
  10357. }
  10358. }
  10359.  
  10360. //if here then we want all remaining instances as well
  10361. for(j=HudMessages.Size()-1; j >= i; j-=1)
  10362. {
  10363. if(HudMessages[i] == msg)
  10364. {
  10365. HudMessages.EraseFast(i);
  10366. }
  10367. }
  10368. }
  10369.  
  10370. public function RemoveHudMessageByIndex(idx : int)
  10371. {
  10372. if(idx >= 0 && idx < HudMessages.Size())
  10373. HudMessages.Erase(idx);
  10374. }
  10375.  
  10376. function SetSettlementBlockCanter( valueAdd : int ) // #B
  10377. {
  10378. m_SettlementBlockCanter += valueAdd;
  10379. }
  10380.  
  10381. var countDownToStart : int;
  10382. default countDownToStart = 0;
  10383.  
  10384. function DisplayRaceStart( countDownSecondsNumber : int ) // #B
  10385. {
  10386. var i : int;
  10387. countDownToStart = countDownSecondsNumber;
  10388. for( i = countDownSecondsNumber; i > 0; i -= 1 )
  10389. {
  10390. DisplayHudMessage(IntToString(i));
  10391. }
  10392. DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_race_start"));
  10393. AddTimer('RaceCountdown',1,true);
  10394. }
  10395.  
  10396. timer function RaceCountdown(dt : float, id : int) // #B
  10397. {
  10398. var hud : CR4ScriptedHud;
  10399. var messageModule : CR4HudModuleMessage;
  10400.  
  10401. countDownToStart -= 1;
  10402. hud = (CR4ScriptedHud)theGame.GetHud();
  10403.  
  10404. if( hud )
  10405. {
  10406. messageModule = (CR4HudModuleMessage)hud.GetHudModule("MessageModule");
  10407. if( messageModule )
  10408. {
  10409. messageModule.OnMessageHidden(); // to force show next messeage
  10410. }
  10411. }
  10412.  
  10413. if( countDownToStart <= 0 )
  10414. {
  10415. RemoveTimer('RaceCountdown');
  10416. }
  10417. }
  10418.  
  10419. public function GetCountDownToStart() : int // #B
  10420. {
  10421. return countDownToStart;
  10422. }
  10423.  
  10424. public function HAXE3GetContainer() : W3Container //#B temp for E3
  10425. {
  10426. return HAXE3Container;
  10427. }
  10428.  
  10429. public function HAXE3SetContainer( container : W3Container) : void //#B temp for E3
  10430. {
  10431. HAXE3Container = container;
  10432. }
  10433.  
  10434. public function HAXE3GetAutoLoot() : bool //#B temp for E3
  10435. {
  10436. return HAXE3bAutoLoot;
  10437. }
  10438.  
  10439. public function HAXE3SetAutoLoot( value : bool ) : void //#B temp for E3
  10440. {
  10441. HAXE3bAutoLoot = value;
  10442. }
  10443.  
  10444. public function GetShowHud() : bool
  10445. {
  10446. return bShowHud;
  10447. }
  10448.  
  10449. public function SetShowHud( value : bool ) : void
  10450. {
  10451. bShowHud = value;
  10452. }
  10453.  
  10454. public function DisplayItemRewardNotification( itemName : name, optional quantity : int ) : void
  10455. {
  10456. var hud : CR4ScriptedHud;
  10457. hud = (CR4ScriptedHud)theGame.GetHud();
  10458. hud.OnItemRecivedDuringScene(itemName, quantity); // #B because our default currency are Crowns !!!
  10459. }
  10460.  
  10461. function IsNewQuest( questGuid : CGUID ) : bool // #B
  10462. {
  10463. var i : int;
  10464. for(i = 0; i < displayedQuestsGUID.Size(); i += 1 )
  10465. {
  10466. if( displayedQuestsGUID[i] == questGuid )
  10467. {
  10468. return false;
  10469. }
  10470. }
  10471. displayedQuestsGUID.PushBack(questGuid);
  10472. return true;
  10473. }
  10474.  
  10475. function GetRewardMultiplier( rewardName : name ) : float // #B
  10476. {
  10477. var defaultReward : SRewardMultiplier;
  10478. var i : int;
  10479.  
  10480. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10481. {
  10482. if( rewardsMultiplier[i].rewardName == rewardName )
  10483. {
  10484. return rewardsMultiplier[i];
  10485. }
  10486. }
  10487.  
  10488. defaultReward.rewardName = rewardName;
  10489. defaultReward.rewardMultiplier = 1.0;
  10490. defaultReward.isItemMultiplier = false;
  10491.  
  10492. return defaultReward;
  10493. }
  10494.  
  10495. function GetRewardMultiplier( rewardName : name ) : float
  10496. {
  10497. var i : int;
  10498. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10499. {
  10500. if( rewardsMultiplier[i].rewardName == rewardName )
  10501. {
  10502. return rewardsMultiplier[i].rewardMultiplier;
  10503. }
  10504. }
  10505. return 1.0;
  10506. }
  10507.  
  10508. function GetRewardMultiplierExists( rewardName : name ) : bool // #B
  10509. {
  10510. var i : int;
  10511. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10512. {
  10513. if( rewardsMultiplier[i].rewardName == rewardName )
  10514. {
  10515. return true;
  10516. }
  10517. }
  10518. return false;
  10519. }
  10520.  
  10521. function SetRewardMultiplier( rewardName : name, value : float ) : void // #B
  10522. {
  10523. var i : int;
  10524. var rewardMultiplier : SRewardMultiplier;
  10525.  
  10526. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10527. {
  10528. if( rewardsMultiplier[i].rewardName == rewardName )
  10529. {
  10530. rewardsMultiplier[i].rewardMultiplier = value;
  10531. rewardsMultiplier[i].isItemMultiplier = isItemMultiplier;
  10532. return;
  10533. }
  10534. }
  10535.  
  10536. rewardMultiplier.rewardName = rewardName;
  10537. rewardMultiplier.rewardMultiplier = value;
  10538. rewardMultiplier.isItemMultiplier = isItemMultiplier;
  10539.  
  10540. rewardsMultiplier.PushBack(rewardMultiplier);
  10541. }
  10542.  
  10543. function RemoveRewardMultiplier( rewardName : name ) : void // #B
  10544. {
  10545. var i : int;
  10546. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10547. {
  10548. if( rewardsMultiplier[i].rewardName == rewardName )
  10549. {
  10550. rewardsMultiplier.Erase(i);
  10551. return;
  10552. }
  10553. }
  10554. }
  10555.  
  10556. ////////////////////////////////////////////////////////////////////////////////
  10557. /////////////////////////// @OILS ////////////////////////////////////////////
  10558. ////////////////////////////////////////////////////////////////////////////////
  10559.  
  10560. public final function GetCurrentOilAmmo(id : SItemUniqueId) : int
  10561.  
  10562.  
  10563.  
  10564.  
  10565.  
  10566. public final function TissueExtractorDischarge() : bool
  10567. {
  10568. var ids : array<SItemUniqueId>;
  10569. var chargesLeft, uses, curr, max, red, blue, green : int;
  10570. var i : int;
  10571. var text : string;
  10572.  
  10573. ids = thePlayer.inv.GetItemsByName( 'q705_tissue_extractor' );
  10574. if( ids.Size() == 0 )
  10575. {
  10576. return false;
  10577. }
  10578.  
  10579. curr = GetTissueExtractorChargesCurr();
  10580. max = GetTissueExtractorChargesMax();
  10581.  
  10582. if( curr >= max )
  10583. {
  10584.  
  10585. uses = FloorF( ( ( float ) curr ) / ( ( float ) max ) );
  10586. chargesLeft = Max( 0, curr - uses * max );
  10587.  
  10588.  
  10589. {
  10590. return inv.GetItemModifierInt(id, 'oil_charges');
  10591. }
  10592.  
  10593. public final function GetMaxOilAmmo(id : SItemUniqueId) : int
  10594. {
  10595. return inv.GetItemModifierInt(id, 'oil_max_charges');
  10596. }
  10597.  
  10598. inv.SetItemModifierInt( ids[0], 'charges', chargesLeft );
  10599.  
  10600.  
  10601. blue = 0;
  10602. green = 0;
  10603. red = 0;
  10604. for( i=0; i<uses; i+=1 )
  10605. {
  10606. switch( RandRange( 3 ) )
  10607. {
  10608. case 0:
  10609. blue += 1;
  10610. break;
  10611. case 1:
  10612. green += 1;
  10613. break;
  10614. case 2:
  10615. red += 1;
  10616. }
  10617. }
  10618.  
  10619. text = GetLocStringByKeyExt( "message_q705_extractor_extracted" );
  10620.  
  10621. if( blue > 0 )
  10622. {
  10623. inv.AddAnItem( 'Greater mutagen blue', blue, false, true );
  10624. text += "<br/>" + blue + "x " + GetLocStringByKey( inv.GetItemLocalizedNameByName( 'Greater mutagen blue' ) );
  10625. }
  10626. if( green > 0 )
  10627. {
  10628. inv.AddAnItem( 'Greater mutagen green', green, false, true );
  10629. text += "<br/>" + green + "x " + GetLocStringByKey( inv.GetItemLocalizedNameByName( 'Greater mutagen green' ) );
  10630. }
  10631. if( red > 0 )
  10632. {
  10633. inv.AddAnItem( 'Greater mutagen red', red, false, true );
  10634. text += "<br/>" + red + "x " + GetLocStringByKey( inv.GetItemLocalizedNameByName( 'Greater mutagen red' ) );
  10635. }
  10636.  
  10637. public final function ReduceOilAmmo(id : SItemUniqueId, optional ammo : int)
  10638. {
  10639. var currentAmmo : int;
  10640.  
  10641. if(ammo == 0)
  10642. ammo = 1;
  10643.  
  10644. currentAmmo = GetCurrentOilAmmo(id);
  10645. if(currentAmmo > 0)
  10646. theGame.GetGuiManager().ShowNotification( text );
  10647.  
  10648.  
  10649. inv.SetItemModifierInt( ids[0], 'ui_notified', 0 );
  10650.  
  10651. return true;
  10652. }
  10653. else
  10654. {
  10655.  
  10656. theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt( "message_q705_extractor_too_few_charges" ) );
  10657. }
  10658.  
  10659. return false;
  10660. }
  10661.  
  10662. public final function TissueExtractorIncCharge()
  10663. {
  10664. var ids : array<SItemUniqueId>;
  10665. var uiData : SInventoryItemUIData;
  10666. var curr : int;
  10667.  
  10668. ids = thePlayer.inv.GetItemsByName( 'q705_tissue_extractor' );
  10669. if( ids.Size() == 0 )
  10670. {
  10671. currentAmmo = Max(currentAmmo - ammo, 0);
  10672. inv.SetItemModifierInt(id, 'oil_charges', currentAmmo);
  10673.  
  10674. if(currentAmmo == 0)
  10675. return;
  10676. }
  10677.  
  10678. curr = GetTissueExtractorChargesCurr() + 1;
  10679. inv.SetItemModifierInt( ids[0], 'charges', curr );
  10680.  
  10681.  
  10682. {
  10683. RemoveItemOil(id);
  10684.  
  10685. //count alchemy usage but only after nightmare
  10686. if(ShouldProcessTutorial('TutorialAlchemyRefill') && FactsQuerySum("q001_nightmare_ended") > 0 && GetWitcherPlayer())
  10687. FactsAdd('tut_alch_refill', 1);
  10688. }
  10689. }
  10690.  
  10691. theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnOilApplied );
  10692. if( curr >= GetTissueExtractorChargesMax() )
  10693. {
  10694. uiData = inv.GetInventoryItemUIData( ids[0] );
  10695. uiData.isNew = true;
  10696. inv.SetInventoryItemUIData( ids[0], uiData );
  10697.  
  10698.  
  10699. if( inv.GetItemModifierInt( ids[0], 'ui_notified', 0 ) == 0 )
  10700. {
  10701. inv.SetItemModifierInt( ids[0], 'ui_notified', 1 );
  10702. theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt( "message_q705_extractor_charged" ), , true );
  10703. }
  10704. }
  10705. }
  10706.  
  10707. public final function GetTissueExtractorChargesCurr() : int
  10708. {
  10709. var ids : array<SItemUniqueId>;
  10710.  
  10711. ids = thePlayer.inv.GetItemsByName( 'q705_tissue_extractor' );
  10712. if( ids.Size() == 0 )
  10713. {
  10714. return 0;
  10715. }
  10716.  
  10717. return inv.GetItemModifierInt( ids[0], 'charges', 0 );
  10718. }
  10719.  
  10720. //removes oil from given item
  10721. public function RemoveItemOil(id : SItemUniqueId)
  10722. {
  10723. var i : int;
  10724. var dm : CDefinitionsManagerAccessor;
  10725. var abilities : array<name>;
  10726. var sword : CWitcherSword;
  10727.  
  10728. dm = theGame.GetDefinitionsManager();
  10729. inv.GetItemAbilities(id, abilities);
  10730. var ids : array<SItemUniqueId>;
  10731. var val : SAbilityAttributeValue;
  10732.  
  10733. ids = thePlayer.inv.GetItemsByName( 'q705_tissue_extractor' );
  10734. if( ids.Size() == 0 )
  10735. {
  10736. return 0;
  10737. }
  10738.  
  10739. for(i=0; i<abilities.Size(); i+=1)
  10740. if(dm.AbilityHasTag(abilities[i], theGame.params.OIL_ABILITY_TAG))
  10741. inv.RemoveItemCraftedAbility(id, abilities[i]);
  10742.  
  10743. inv.SetItemModifierInt(id, 'oil_charges', -1);
  10744. inv.SetItemModifierInt(id, 'oil_max_charges', -1);
  10745. sword = (CWitcherSword) inv.GetItemEntityUnsafe(id);
  10746. sword.RemoveOil( inv );
  10747.  
  10748. theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnOilApplied );
  10749. }
  10750. ////////////////////////////////////////////////////////////////////////////////
  10751. //
  10752. // @Items
  10753. //
  10754. ////////////////////////////////////////////////////////////////////////////////
  10755.  
  10756. public final function HasRequiredLevelToEquipItem(item : SItemUniqueId) : bool
  10757. {
  10758. if(HasBuff(EET_WolfHour))
  10759. {
  10760. if((inv.GetItemLevel(item) - 2) > GetLevel() )
  10761. return false;
  10762. }
  10763. else
  10764. {
  10765. if(inv.GetItemLevel(item) > GetLevel() )
  10766. return false;
  10767. }
  10768.  
  10769. return true;
  10770. }
  10771.  
  10772. public function SkillReduceBombAmmoBonus()
  10773. {
  10774. var i, ammo, maxAmmo : int;
  10775. var items : array<SItemUniqueId>;
  10776.  
  10777. items = inv.GetSingletonItems();
  10778.  
  10779. for(i=0; i<items.Size(); i+=1)
  10780. {
  10781. ammo = inv.GetItemModifierInt(items[i], 'ammo_current');
  10782.  
  10783. //if doesn't have infinite ammo
  10784. if(ammo > 0)
  10785. {
  10786. maxAmmo = inv.SingletonItemGetMaxAmmo(items[i]);
  10787.  
  10788. //if current ammo > max ammo, set current ammo to max ammo
  10789. if(ammo > maxAmmo)
  10790. {
  10791. inv.SetItemModifierInt(items[i], 'ammo_current', maxAmmo);
  10792. }
  10793. }
  10794. }
  10795. theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnAmmoChanged );
  10796. }
  10797.  
  10798. public function ConsumeItem( itemId : SItemUniqueId ) : bool
  10799. {
  10800. var params : SCustomEffectParams;
  10801. var buffs : array<SEffectInfo>;
  10802. var i : int;
  10803. var category : name;
  10804. var potionToxicity : float;
  10805.  
  10806. if(!inv.IsIdValid(itemId))
  10807. return false;
  10808.  
  10809. //apply buff
  10810. category = inv.GetItemCategory(itemId);
  10811. if(category == 'edibles' || inv.ItemHasTag(itemId, 'Drinks') || ( category == 'alchemy_ingredient' && inv.ItemHasTag(itemId, 'Alcohol')) )
  10812. {
  10813. //cannot eat in fistfights
  10814. if(IsFistFightMinigameEnabled())
  10815. {
  10816. DisplayActionDisallowedHudMessage(EIAB_Undefined, false, false, true);
  10817. return false;
  10818. }
  10819.  
  10820. //edible buff
  10821. inv.GetItemBuffs(itemId, buffs);
  10822.  
  10823. for(i=0; i<buffs.Size(); i+=1)
  10824. {
  10825. params.effectType = buffs[i].effectType;
  10826. params.creator = this;
  10827. params.sourceName = "edible";
  10828. params.customAbilityName = buffs[i].effectAbilityName;
  10829. AddEffectCustom(params);
  10830. }
  10831.  
  10832. //custom hack
  10833. if ( inv.ItemHasTag(itemId, 'Alcohol') )
  10834. {
  10835. potionToxicity = CalculateAttributeValue(inv.GetItemAttributeValue(itemId, 'toxicity'));
  10836. abilityManager.GainStat(BCS_Toxicity, potionToxicity );
  10837. AddEffectDefault(EET_Drunkenness, NULL, inv.GetItemName(itemId));
  10838. }
  10839. PlayItemConsumeSound( itemId );
  10840. }
  10841.  
  10842. if(inv.IsItemFood(itemId))
  10843. FactsAdd("consumed_food_cnt");
  10844.  
  10845. //remove item
  10846. if(!inv.ItemHasTag(itemId, theGame.params.TAG_INFINITE_USE) && !inv.RemoveItem(itemId))
  10847. {
  10848. LogAssert(false,"Failed to remove consumable item from player inventory!" + inv.GetItemName( itemId ) );
  10849. return false;
  10850. }
  10851.  
  10852. return true;
  10853. }
  10854.  
  10855. public function MountVehicle( vehicleEntity : CEntity, mountType : EVehicleMountType, optional vehicleSlot : EVehicleSlot )
  10856. {
  10857. var vehicle : CVehicleComponent;
  10858. vehicle = (CVehicleComponent)(vehicleEntity.GetComponentByClassName('CVehicleComponent'));
  10859.  
  10860. if ( vehicle )
  10861. vehicle.Mount( this, mountType, vehicleSlot );
  10862. }
  10863.  
  10864. public function DismountVehicle( vehicleEntity : CEntity, dismountType : EDismountType )
  10865. {
  10866. var vehicle : CVehicleComponent;
  10867. vehicle = (CVehicleComponent)(vehicleEntity.GetComponentByClassName('CVehicleComponent'));
  10868.  
  10869. if ( vehicle )
  10870. vehicle.IssueCommandToDismount( dismountType );
  10871. }
  10872.  
  10873. ////////////////
  10874. // @stamina @stats
  10875. ////////////////
  10876.  
  10877. //Returns true if actor has enough stamina to perform given action type (refer to DrainStamina for more info).
  10878. //If there is not enough stamina and actor is a player character then a insufficient stamina indication is shown on HUD
  10879.  
  10880.  
  10881.  
  10882. protected function ShouldDrainStaminaWhileSprinting() : bool
  10883. {
  10884. if( HasBuff( EET_PolishedGenitals ) && !IsInCombat() && !IsThreatened() )
  10885. {
  10886. return false;
  10887. }
  10888.  
  10889. return super.ShouldDrainStaminaWhileSprinting();
  10890. }
  10891.  
  10892.  
  10893.  
  10894. public function HasStaminaToUseAction(action : EStaminaActionType, optional abilityName : name, optional dt :float, optional multiplier : float) : bool
  10895. {
  10896. var cost : float;
  10897. var ret : bool;
  10898.  
  10899. ret = super.HasStaminaToUseAction(action, abilityName, dt, multiplier);
  10900.  
  10901. if(!ret)
  10902. {
  10903. SetCombatActionHeading( GetHeading() );
  10904.  
  10905. if(multiplier == 0)
  10906. multiplier = 1;
  10907.  
  10908. cost = multiplier * GetStaminaActionCost(action, abilityName, dt);
  10909. SetShowToLowStaminaIndication(cost);
  10910. }
  10911.  
  10912. return ret;
  10913. }
  10914.  
  10915. //since we cannot add timer on abilityManager...
  10916. timer function AbilityManager_FloorStaminaSegment(dt : float, id : int)
  10917. {
  10918. ((W3PlayerAbilityManager)abilityManager).FloorStaminaSegment();
  10919. }
  10920.  
  10921. public function DrainToxicity(amount : float )
  10922. {
  10923. if(abilityManager && abilityManager.IsInitialized() && IsAlive())
  10924. abilityManager.DrainToxicity(amount);
  10925. }
  10926.  
  10927. public function DrainFocus(amount : float )
  10928. {
  10929. if(abilityManager && abilityManager.IsInitialized() && IsAlive())
  10930. abilityManager.DrainFocus(amount);
  10931. }
  10932.  
  10933. public function GetOffenseStat():int
  10934. {
  10935. if(abilityManager && abilityManager.IsInitialized())
  10936. return ((W3PlayerAbilityManager)abilityManager).GetOffenseStat();
  10937.  
  10938. return 0;
  10939. }
  10940.  
  10941. public function GetDefenseStat():int
  10942. {
  10943. if(abilityManager && abilityManager.IsInitialized())
  10944. return ((W3PlayerAbilityManager)abilityManager).GetDefenseStat();
  10945.  
  10946. return 0;
  10947. }
  10948.  
  10949. public function GetSignsStat():float
  10950. {
  10951. if(abilityManager && abilityManager.IsInitialized())
  10952. return ((W3PlayerAbilityManager)abilityManager).GetSignsStat();
  10953.  
  10954. return 0;
  10955. }
  10956.  
  10957. ////////////////
  10958. // water
  10959. ////////////////
  10960.  
  10961. private var inWaterTrigger : bool;
  10962.  
  10963. event OnOceanTriggerEnter()
  10964. {
  10965. inWaterTrigger = true;
  10966. }
  10967.  
  10968. event OnOceanTriggerLeave()
  10969. {
  10970. inWaterTrigger = false;
  10971. }
  10972.  
  10973. public function IsInWaterTrigger() : bool
  10974. {
  10975. return inWaterTrigger;
  10976. }
  10977.  
  10978. //////////////////////////////////////////////////////////////////////////////////////////
  10979. // @Skills @Perks
  10980. //////////////////////////////////////////////////////////////////////////////////////////
  10981.  
  10982. public function GetSkillColor(skill : ESkill) : ESkillColor
  10983. {
  10984. if(abilityManager && abilityManager.IsInitialized())
  10985. return ((W3PlayerAbilityManager)abilityManager).GetSkillColor(skill);
  10986.  
  10987. return SC_None;
  10988. }
  10989.  
  10990. public function GetSkillSlotIndexFromSkill(skill : ESkill) : int
  10991. {
  10992. if(abilityManager && abilityManager.IsInitialized())
  10993. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIndexFromSkill(skill);
  10994.  
  10995. return -1;
  10996. }
  10997.  
  10998. public final function GetSkillSlotIndex(slotID : int, checkIfUnlocked : bool) : int
  10999. {
  11000. if(abilityManager && abilityManager.IsInitialized())
  11001. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIndex(slotID, checkIfUnlocked);
  11002.  
  11003. return -1;
  11004. }
  11005.  
  11006. public final function GetSkillSlotIDFromIndex(skillSlotIndex : int) : int
  11007. {
  11008. if(abilityManager && abilityManager.IsInitialized())
  11009. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIDFromIndex(skillSlotIndex);
  11010.  
  11011. return -1;
  11012. }
  11013.  
  11014. public function GetSkillSlotID(skill : ESkill) : int
  11015. {
  11016. if(abilityManager && abilityManager.IsInitialized())
  11017. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotID(skill);
  11018.  
  11019. return -1;
  11020. }
  11021.  
  11022. public function GetSkillGroupBonus(groupID : int) : name
  11023. {
  11024. if(abilityManager && abilityManager.IsInitialized())
  11025. return ((W3PlayerAbilityManager)abilityManager).GetGroupBonus(groupID);
  11026.  
  11027. return '';
  11028. }
  11029.  
  11030. public function GetGroupBonusCount(commonColor : ESkillColor,groupID : int) : int
  11031. {
  11032. if(abilityManager && abilityManager.IsInitialized())
  11033. return ((W3PlayerAbilityManager)abilityManager).GetGroupBonusCount(commonColor, groupID);
  11034.  
  11035. return 0;
  11036. }
  11037.  
  11038. public function GetMutagenSlotIDFromGroupID(groupID : int) : int
  11039. {
  11040. if(abilityManager && abilityManager.IsInitialized())
  11041. return ((W3PlayerAbilityManager)abilityManager).GetMutagenSlotIDFromGroupID(groupID);
  11042.  
  11043. return -1;
  11044. }
  11045.  
  11046. public function GetSkillLevel(skill : ESkill) : int
  11047. {
  11048. if(abilityManager && abilityManager.IsInitialized())
  11049. return ((W3PlayerAbilityManager)abilityManager).GetSkillLevel(skill);
  11050.  
  11051. return -1;
  11052. }
  11053.  
  11054. public function GetBoughtSkillLevel(skill : ESkill) : int
  11055. {
  11056. if(abilityManager && abilityManager.IsInitialized())
  11057. return ((W3PlayerAbilityManager)abilityManager).GetBoughtSkillLevel(skill);
  11058.  
  11059. return -1;
  11060. }
  11061.  
  11062. public function AddSkill(skill : ESkill, optional isTemporary : bool)
  11063. {
  11064. if(abilityManager && abilityManager.IsInitialized())
  11065. ((W3PlayerAbilityManager)abilityManager).AddSkill(skill, isTemporary);
  11066. }
  11067.  
  11068. public function AddMultipleSkills(skill : ESkill, optional number : int, optional isTemporary : bool)
  11069. {
  11070. var i : int;
  11071.  
  11072. if(number)
  11073. {
  11074. for( i=0; i<number; i+=1)
  11075. {
  11076. AddSkill(skill,isTemporary);
  11077. }
  11078. }
  11079. else
  11080. {
  11081. AddSkill(skill,isTemporary);
  11082. }
  11083. }
  11084.  
  11085. public function GetSkillAbilityName(skill : ESkill) : name
  11086. {
  11087. if(abilityManager && abilityManager.IsInitialized())
  11088. return ((W3PlayerAbilityManager)abilityManager).GetSkillAbilityName(skill);
  11089.  
  11090. return '';
  11091. }
  11092.  
  11093. public function HasStaminaToUseSkill(skill : ESkill, optional perSec : bool, optional signHack : bool) : bool
  11094. {
  11095. var ret : bool;
  11096. var cost : float;
  11097.  
  11098. cost = GetSkillStaminaUseCost(skill, perSec);
  11099.  
  11100. ret = ( CanUseSkill(skill) && (abilityManager.GetStat(BCS_Stamina, signHack) >= cost) );
  11101.  
  11102. //perk, using adrenaline instead of stamina when out of stamina
  11103. if(!ret && IsSkillSign(skill) && CanUseSkill(S_Perk_09) && GetStat(BCS_Focus) >= 1)
  11104. {
  11105. ret = true;
  11106. }
  11107.  
  11108.  
  11109. if( !ret && IsSkillSign( skill ) && GetWitcherPlayer().HasBuff( EET_GryphonSetBonus ) )
  11110. {
  11111. ret = true;
  11112. }
  11113.  
  11114. if(!ret)
  11115. {
  11116. SetCombatActionHeading( GetHeading() );
  11117. SetShowToLowStaminaIndication(cost);
  11118. }
  11119.  
  11120. return ret;
  11121. }
  11122.  
  11123. protected function GetSkillStaminaUseCost(skill : ESkill, optional perSec : bool) : float
  11124. {
  11125. if(abilityManager && abilityManager.IsInitialized())
  11126. return ((W3PlayerAbilityManager)abilityManager).GetSkillStaminaUseCost(skill, perSec);
  11127.  
  11128. return 0;
  11129. }
  11130.  
  11131. //works for perks and bookperks as well
  11132. public function GetSkillAttributeValue(skill : ESkill, attributeName : name, addBaseCharAttribute : bool, addSkillModsAttribute : bool) : SAbilityAttributeValue
  11133. {
  11134. var null : SAbilityAttributeValue;
  11135.  
  11136. if(abilityManager && abilityManager.IsInitialized())
  11137. return abilityManager.GetSkillAttributeValue(SkillEnumToName(skill), attributeName, addBaseCharAttribute, addSkillModsAttribute);
  11138.  
  11139. return null;
  11140. }
  11141.  
  11142. public function GetSkillLocalisationKeyName(skill : ESkill) : string // #B
  11143. {
  11144. if(abilityManager && abilityManager.IsInitialized())
  11145. return ((W3PlayerAbilityManager)abilityManager).GetSkillLocalisationKeyName(skill);
  11146.  
  11147. return "";
  11148. }
  11149.  
  11150. public function GetSkillLocalisationKeyDescription(skill : ESkill) : string // #B
  11151. {
  11152. if(abilityManager && abilityManager.IsInitialized())
  11153. return ((W3PlayerAbilityManager)abilityManager).GetSkillLocalisationKeyDescription(skill);
  11154.  
  11155. return "";
  11156. }
  11157.  
  11158. public function GetSkillIconPath(skill : ESkill) : string // #B
  11159. {
  11160. if(abilityManager && abilityManager.IsInitialized())
  11161. return ((W3PlayerAbilityManager)abilityManager).GetSkillIconPath(skill);
  11162.  
  11163. return "";
  11164. }
  11165.  
  11166. public function HasLearnedSkill(skill : ESkill) : bool
  11167. {
  11168. if(abilityManager && abilityManager.IsInitialized())
  11169. return ((W3PlayerAbilityManager)abilityManager).HasLearnedSkill(skill);
  11170.  
  11171. return false;
  11172. }
  11173.  
  11174. public function IsSkillEquipped(skill : ESkill) : bool
  11175. {
  11176. if(abilityManager && abilityManager.IsInitialized())
  11177. return ((W3PlayerAbilityManager)abilityManager).IsSkillEquipped(skill);
  11178.  
  11179. return false;
  11180. }
  11181.  
  11182. public function CanUseSkill(skill : ESkill) : bool
  11183. {
  11184. if(abilityManager && abilityManager.IsInitialized())
  11185. return ((W3PlayerAbilityManager)abilityManager).CanUseSkill(skill);
  11186.  
  11187. return false;
  11188. }
  11189.  
  11190. public function CanLearnSkill(skill : ESkill) : bool //#B
  11191. {
  11192. if(abilityManager && abilityManager.IsInitialized())
  11193. return ((W3PlayerAbilityManager)abilityManager).CanLearnSkill(skill);
  11194.  
  11195. return false;
  11196. }
  11197.  
  11198. public function HasSpentEnoughPoints(skill : ESkill) : bool //#J
  11199. {
  11200. if(abilityManager && abilityManager.IsInitialized())
  11201. return ((W3PlayerAbilityManager)abilityManager).HasSpentEnoughPoints(skill);
  11202.  
  11203. return false;
  11204. }
  11205.  
  11206. public function PathPointsForSkillsPath(skill : ESkill) : int //#J
  11207. {
  11208. if(abilityManager && abilityManager.IsInitialized())
  11209. return ((W3PlayerAbilityManager)abilityManager).PathPointsSpentInSkillPathOfSkill(skill);
  11210.  
  11211. return -1;
  11212. }
  11213.  
  11214. public function GetPlayerSkills() : array<SSkill> // #B
  11215. {
  11216. var null : array<SSkill>;
  11217.  
  11218. if(abilityManager && abilityManager.IsInitialized())
  11219. return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkills();
  11220.  
  11221. return null;
  11222. }
  11223.  
  11224. public function GetPlayerSkill(s : ESkill) : SSkill // #B
  11225. {
  11226. var null : SSkill;
  11227.  
  11228. if(abilityManager && abilityManager.IsInitialized())
  11229. return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkill(s);
  11230.  
  11231. return null;
  11232. }
  11233.  
  11234. public function GetSkillSubPathType(s : ESkill) : ESkillSubPath // #B
  11235. {
  11236. if(abilityManager && abilityManager.IsInitialized())
  11237. return ((W3PlayerAbilityManager)abilityManager).GetSkillSubPathType(s);
  11238.  
  11239. return ESSP_NotSet;
  11240. }
  11241.  
  11242. public function GetSkillSlotsCount() : int
  11243. {
  11244. if(abilityManager && abilityManager.IsInitialized())
  11245. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotsCount();
  11246.  
  11247. return 0;
  11248. }
  11249.  
  11250. public function GetSkillSlots() : array<SSkillSlot>
  11251. {
  11252. var null : array<SSkillSlot>;
  11253.  
  11254. if(abilityManager && abilityManager.IsInitialized())
  11255. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlots();
  11256.  
  11257. return null;
  11258. }
  11259.  
  11260. public function GetPlayerSkillMutagens() : array<SMutagenSlot>
  11261. {
  11262. var null : array<SMutagenSlot>;
  11263.  
  11264. if(abilityManager && abilityManager.IsInitialized())
  11265. return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkillMutagens();
  11266.  
  11267. return null;
  11268. }
  11269.  
  11270. // mutagens
  11271. //public function OnSkillMutagenEquipped()
  11272.  
  11273. public function BlockSkill(skill : ESkill, block : bool, optional cooldown : float) : bool
  11274. {
  11275. if(abilityManager && abilityManager.IsInitialized())
  11276. return ((W3PlayerAbilityManager)abilityManager).BlockSkill(skill, block, cooldown);
  11277.  
  11278. return false;
  11279. }
  11280.  
  11281. public function IsSkillBlocked(skill : ESkill) : bool
  11282. {
  11283. if(abilityManager && abilityManager.IsInitialized())
  11284. return ((W3PlayerAbilityManager)abilityManager).IsSkillBlocked(skill);
  11285.  
  11286. return false;
  11287. }
  11288.  
  11289. //returns true if succeeded
  11290. public function EquipSkill(skill : ESkill, slotID : int) : bool
  11291. {
  11292. var ret : bool;
  11293. var groupID : int;
  11294. var pam : W3PlayerAbilityManager;
  11295.  
  11296. if(abilityManager && abilityManager.IsInitialized())
  11297. {
  11298. pam = (W3PlayerAbilityManager)abilityManager;
  11299. ret = pam.EquipSkill(skill, slotID);
  11300. if(ret)
  11301. {
  11302. groupID = pam.GetSkillGroupIdFromSkillSlotId(slotID);
  11303. LogSkillColors("Equipped <<" + GetSkillColor(skill) + ">> skill <<" + skill + ">> to group <<" + groupID + ">>");
  11304. LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>");
  11305. LogSkillColors("");
  11306. }
  11307.  
  11308. return ret;
  11309. }
  11310.  
  11311. return false;
  11312. }
  11313.  
  11314. //returns true if succeeded
  11315. public function UnequipSkill(slotID : int) : bool
  11316. {
  11317. var ret : bool;
  11318. var groupID : int;
  11319. var skill : ESkill;
  11320. var pam : W3PlayerAbilityManager;
  11321.  
  11322. if(abilityManager && abilityManager.IsInitialized())
  11323. {
  11324. pam = (W3PlayerAbilityManager)abilityManager;
  11325. GetSkillOnSlot(slotID, skill);
  11326. ret = pam.UnequipSkill(slotID);
  11327. if(ret)
  11328. {
  11329. groupID = pam.GetSkillGroupIdFromSkillSlotId(slotID);
  11330. LogSkillColors("Unequipped <<" + GetSkillColor(skill) + ">> skill <<" + skill + ">> from group <<" + groupID + ">>");
  11331. LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>");
  11332. LogSkillColors("");
  11333. }
  11334. return ret;
  11335. }
  11336.  
  11337. return false;
  11338. }
  11339.  
  11340. //returns true if succeeded
  11341. public function GetSkillOnSlot(slotID : int, out skill : ESkill) : bool
  11342. {
  11343. if(abilityManager && abilityManager.IsInitialized())
  11344. return ((W3PlayerAbilityManager)abilityManager).GetSkillOnSlot(slotID, skill);
  11345.  
  11346. skill = S_SUndefined;
  11347. return false;
  11348. }
  11349.  
  11350. //returns random free skill slot (if any, otherwise -1)
  11351. public function GetFreeSkillSlot() : int
  11352. {
  11353. var i, size : int;
  11354. var skill : ESkill;
  11355.  
  11356. size = ((W3PlayerAbilityManager)abilityManager).GetSkillSlotsCount();
  11357. for(i=1; i<size; i+=1)
  11358. {
  11359. if(!GetSkillOnSlot(i, skill))
  11360. continue; //if slot locked
  11361.  
  11362. if(skill == S_SUndefined) //empty unlocked slot
  11363. return i;
  11364. }
  11365.  
  11366. return -1;
  11367. }
  11368.  
  11369. //////////////////
  11370. // @attacks
  11371. //////////////////
  11372.  
  11373. //performs an attack (mechanics wise) on given target and using given attack data
  11374.  
  11375.  
  11376.  
  11377.  
  11378. protected function Attack( hitTarget : CGameplayEntity, animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array<CActor>, attackAnimationName : name, hitTime : float, weaponEntity : CItemEntity)
  11379. {
  11380. var attackAction : W3Action_Attack;
  11381.  
  11382. if(!PrepareAttackAction(hitTarget, animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime, weaponEntity, attackAction))
  11383. return; //failed to create a valid attack action
  11384.  
  11385. if ( attackAction.IsParried() && ( ((CNewNPC)attackAction.victim).IsShielded(attackAction.attacker) || ((CNewNPC)attackAction.victim).SignalGameplayEventReturnInt('IsDefending',0) == 1 ) )
  11386. {
  11387. thePlayer.SetCanPlayHitAnim(true);
  11388. thePlayer.ReactToReflectedAttack(attackAction.victim);
  11389. }
  11390.  
  11391. theTelemetry.LogWithLabel( TE_FIGHT_PLAYER_ATTACKS, attackAction.GetAttackName() );
  11392.  
  11393. //process action
  11394. theGame.damageMgr.ProcessAction(attackAction);
  11395.  
  11396. delete attackAction;
  11397. }
  11398.  
  11399. public function IsHeavyAttack(attackName : name) : bool
  11400. {
  11401. var skill : ESkill;
  11402. var sup : bool;
  11403.  
  11404. sup = super.IsHeavyAttack(attackName);
  11405. if(sup)
  11406. return true;
  11407.  
  11408. if ( attackName == 'attack_heavy_special' )
  11409. return true;
  11410.  
  11411. skill = SkillNameToEnum(attackName);
  11412.  
  11413. return skill == S_Sword_2 || skill == S_Sword_s02;
  11414. }
  11415.  
  11416. public function IsLightAttack(attackName : name) : bool
  11417. {
  11418. var skill : ESkill;
  11419. var sup : bool;
  11420.  
  11421. sup = super.IsLightAttack(attackName);
  11422. if(sup)
  11423. return true;
  11424.  
  11425. skill = SkillNameToEnum(attackName);
  11426.  
  11427. return skill == S_Sword_1 || skill == S_Sword_s01;
  11428. }
  11429.  
  11430. public final function ProcessWeaponCollision()
  11431. {
  11432. var l_stateName : name;
  11433.  
  11434. var l_weaponPosition : Vector;
  11435. var l_weaponTipPos : Vector;
  11436. var l_collidingPosition : Vector;
  11437. var l_offset : Vector;
  11438. var l_normal : Vector;
  11439.  
  11440. var l_slotMatrix : Matrix;
  11441.  
  11442. var l_distance : float;
  11443.  
  11444. var l_materialName : name;
  11445. var l_hitComponent : CComponent;
  11446. var l_destructibleCmp : CDestructionSystemComponent;
  11447. var barrel : COilBarrelEntity;
  11448.  
  11449. //return;
  11450.  
  11451. if( isCurrentlyDodging )
  11452. return;
  11453.  
  11454. l_stateName = GetCurrentStateName();
  11455.  
  11456. if( !attackEventInProgress && l_stateName == 'CombatFists' )
  11457. return;
  11458.  
  11459. CalcEntitySlotMatrix('r_weapon', l_slotMatrix);
  11460.  
  11461. l_weaponPosition = MatrixGetTranslation( l_slotMatrix );
  11462.  
  11463. // Finding weapon's tip
  11464. switch( l_stateName )
  11465. {
  11466. case 'CombatFists':
  11467. l_offset = MatrixGetAxisX( l_slotMatrix );
  11468. l_offset = VecNormalize( l_offset ) * 0.25f;
  11469. break;
  11470. // sword
  11471. default:
  11472. l_offset = MatrixGetAxisZ( l_slotMatrix );
  11473. l_offset = VecNormalize( l_offset ) * 1.f;
  11474. break;
  11475. }
  11476.  
  11477. l_weaponTipPos = l_weaponPosition + l_offset;
  11478.  
  11479.  
  11480.  
  11481. if( !attackEventInProgress )
  11482. {
  11483. // If the weapon is not moving fast enough, do not play collision fx
  11484. if( m_LastWeaponTipPos == Vector ( 0, 0, 0 ) )
  11485. l_distance = 0;
  11486. else
  11487. l_distance = VecDistance( l_weaponTipPos, m_LastWeaponTipPos ) ;
  11488.  
  11489. //GetVisualDebug().AddText( 'LastWeaponTipText', "Last - dist: " + l_distance, m_LastWeaponTipPos, true, , Color( 249, 98, 158 ) );
  11490. //GetVisualDebug().AddArrow( 'OldDirectArrow', l_weaponPosition, m_LastWeaponTipPos , 0.8f, 0.1f, 0.2f, true, Color( 249, 98, 158 ) );
  11491.  
  11492. m_LastWeaponTipPos = l_weaponTipPos;
  11493. if( l_distance < 0.35f )
  11494. return;
  11495.  
  11496. }
  11497.  
  11498. /*GetVisualDebug().AddSphere( 'WeaponPosition', 0.1f, l_weaponPosition, true, Color( 249, 98, 158 ) );
  11499. GetVisualDebug().AddText( 'WeaponTipText', "Weapon Tip", l_weaponTipPos, true, , Color( 249, 98, 158 ) );
  11500. GetVisualDebug().AddArrow( 'CollisionArrow', l_weaponPosition, l_weaponTipPos , 0.8f, 0.1f, 0.2f, true, Color( 249, 98, 158 ) );*/
  11501.  
  11502. m_LastWeaponTipPos = l_weaponTipPos;
  11503.  
  11504. if ( !theGame.GetWorld().StaticTraceWithAdditionalInfo( l_weaponPosition, l_weaponTipPos, l_collidingPosition, l_normal, l_materialName, l_hitComponent, m_WeaponFXCollisionGroupNames ) )
  11505. {
  11506. // Test left fist
  11507. if( l_stateName == 'CombatFists' )
  11508. {
  11509. CalcEntitySlotMatrix('l_weapon', l_slotMatrix);
  11510. l_weaponPosition = MatrixGetTranslation( l_slotMatrix );
  11511. l_offset = MatrixGetAxisX( l_slotMatrix );
  11512. l_offset = VecNormalize( l_offset ) * 0.25f;
  11513. l_weaponTipPos = l_weaponPosition + l_offset;
  11514. if( !theGame.GetWorld().StaticTrace( l_weaponPosition, l_weaponTipPos, l_collidingPosition, l_normal, m_WeaponFXCollisionGroupNames ) )
  11515. {
  11516. return;
  11517. }
  11518. }
  11519. else
  11520. {
  11521. return;
  11522. }
  11523. }
  11524.  
  11525. if( !m_CollisionEffect )
  11526. {
  11527. m_CollisionEffect = theGame.CreateEntity( m_CollisionFxTemplate, l_collidingPosition, EulerAngles(0,0,0) );
  11528. }
  11529.  
  11530. m_CollisionEffect.Teleport( l_collidingPosition );
  11531.  
  11532. // Play hit effect
  11533. switch( l_stateName )
  11534. {
  11535. case 'CombatFists':
  11536. m_CollisionEffect.PlayEffect('fist');
  11537. break;
  11538. default:
  11539. // Optimisation because IsSwordWooden() is heavy (around 0.13 ms)
  11540. if( m_RefreshWeaponFXType )
  11541. {
  11542. m_PlayWoodenFX = IsSwordWooden();
  11543. m_RefreshWeaponFXType = false;
  11544. }
  11545.  
  11546. if( m_PlayWoodenFX )
  11547. {
  11548. m_CollisionEffect.PlayEffect('wood');
  11549. }
  11550. else
  11551. {
  11552. switch( l_materialName )
  11553. {
  11554. case 'wood_hollow':
  11555. case 'wood_debris':
  11556. case 'wood_solid':
  11557. m_CollisionEffect.PlayEffect('wood');
  11558. break;
  11559. case 'dirt_hard':
  11560. case 'dirt_soil':
  11561. case 'hay':
  11562. m_CollisionEffect.PlayEffect('fist');
  11563. break;
  11564. case 'stone_debris':
  11565. case 'stone_solid':
  11566. case 'clay_tile':
  11567. case 'gravel_large':
  11568. case 'gravel_small':
  11569. case 'metal':
  11570. case 'custom_sword':
  11571. m_CollisionEffect.PlayEffect('sparks');
  11572. break;
  11573. case 'flesh':
  11574. m_CollisionEffect.PlayEffect('blood');
  11575. break;
  11576. default:
  11577. m_CollisionEffect.PlayEffect('wood');
  11578. break;
  11579. }
  11580.  
  11581. }
  11582. break;
  11583. }
  11584.  
  11585. //don't ask...
  11586. if(l_hitComponent)
  11587. {
  11588. barrel = (COilBarrelEntity)l_hitComponent.GetEntity();
  11589. if(barrel)
  11590. {
  11591. barrel.OnFireHit(NULL); //sets barrel on fire so that it explodes in a few sec
  11592. return;
  11593. }
  11594. }
  11595.  
  11596. // Destroy destructibles
  11597. l_destructibleCmp = (CDestructionSystemComponent) l_hitComponent;
  11598. if( l_destructibleCmp && l_stateName != 'CombatFists' )
  11599. {
  11600. l_destructibleCmp.ApplyFracture();
  11601. }
  11602.  
  11603.  
  11604. //GetVisualDebug().AddText( 'collisionText', "Collision Here", l_collidingPosition, true, , Color( 249, 98, 158 ) );
  11605. }
  11606.  
  11607. public function ReactToReflectedAttack( target : CGameplayEntity)
  11608. {
  11609.  
  11610. var hp, dmg : float;
  11611. var action : W3DamageAction;
  11612.  
  11613. super.ReactToReflectedAttack(target);
  11614.  
  11615. if ( !((CNewNPC)target).IsShielded(this) )
  11616. {
  11617. action = new W3DamageAction in this;
  11618. action.Initialize(target,this,NULL,'',EHRT_Reflect,CPS_AttackPower,true,false,false,false);
  11619. action.AddEffectInfo(EET_Stagger);
  11620. action.SetProcessBuffsIfNoDamage(true);
  11621.  
  11622. theGame.damageMgr.ProcessAction( action );
  11623. delete action;
  11624. }
  11625.  
  11626. theGame.VibrateControllerLight();//player attack was reflected
  11627. }
  11628.  
  11629. //////////////////
  11630. // falling damage
  11631. //////////////////
  11632.  
  11633. //return false when not falling
  11634.  
  11635.  
  11636.  
  11637. function GetFallDist( out fallDist : float ) : bool
  11638. {
  11639. var fallDiff, jumpTotalDiff : float;
  11640.  
  11641. // Get the falling height
  11642. substateManager.m_SharedDataO.CalculateFallingHeights( fallDiff, jumpTotalDiff );
  11643.  
  11644. if ( fallDiff <= 0 )
  11645. return false;
  11646.  
  11647. fallDist = fallDiff;
  11648. return true;
  11649. }
  11650.  
  11651. function ApplyFallingDamage(heightDiff : float, optional reducing : bool) : float
  11652. {
  11653. var hpPerc : float;
  11654. var tut : STutorialMessage;
  11655.  
  11656. if ( IsSwimming() || FactsQuerySum("block_falling_damage") >= 1 )
  11657. return 0.0f;
  11658.  
  11659. hpPerc = super.ApplyFallingDamage( heightDiff, reducing );
  11660.  
  11661. if(hpPerc > 0)
  11662. {
  11663. theGame.VibrateControllerHard();//player falling damage
  11664.  
  11665. if(IsAlive())
  11666. {
  11667. if(ShouldProcessTutorial('TutorialFallingDamage'))
  11668. {
  11669. FactsAdd("tutorial_falling_damage");
  11670. }
  11671.  
  11672. if(FactsQuerySum("tutorial_falling_damage") > 1 && ShouldProcessTutorial('TutorialFallingRoll'))
  11673. {
  11674. //fill tutorial object data
  11675. tut.type = ETMT_Hint;
  11676. tut.tutorialScriptTag = 'TutorialFallingRoll';
  11677. tut.hintPositionType = ETHPT_DefaultGlobal;
  11678. tut.hintDurationType = ETHDT_Long;
  11679. tut.canBeShownInMenus = false;
  11680. tut.glossaryLink = false;
  11681. tut.markAsSeenOnShow = true;
  11682.  
  11683. //show tutorial
  11684. theGame.GetTutorialSystem().DisplayTutorial(tut);
  11685. }
  11686. }
  11687. }
  11688.  
  11689. return hpPerc;
  11690. }
  11691.  
  11692. //--------------------------------- STAMINA INDICATOR #B --------------------------------------
  11693.  
  11694. public function SetShowToLowStaminaIndication( value : float ) : void
  11695. {
  11696. fShowToLowStaminaIndication = value;
  11697. }
  11698.  
  11699. public function GetShowToLowStaminaIndication() : float
  11700. {
  11701. return fShowToLowStaminaIndication;
  11702. }
  11703.  
  11704. public final function IndicateTooLowAdrenaline()
  11705. {
  11706. SoundEvent("gui_no_adrenaline");
  11707. showTooLowAdrenaline = true;
  11708. }
  11709.  
  11710. /////////////////////////////////
  11711.  
  11712. protected function GotoCombatStateWithAction( initialAction : EInitialAction, optional initialBuff : CBaseGameplayEffect )
  11713. {
  11714. if ( this.GetCurrentActionType() == ActorAction_Exploration )
  11715. ActionCancelAll();
  11716.  
  11717. ((W3PlayerWitcherStateCombatFists)this.GetState('CombatFists')).SetupState( initialAction, initialBuff );
  11718. this.GotoState( 'CombatFists' );
  11719.  
  11720. }
  11721. ///////////////////////////////////////////////////////////////////////////////////////////
  11722. // COMBAT
  11723. public function IsThreat( actor : CActor, optional usePrecalcs : bool ) : bool
  11724. {
  11725. var npc : CNewNPC;
  11726. var dist : float;
  11727. var targetCapsuleHeight : float;
  11728. var isDistanceExpanded : bool;
  11729. var distanceToTarget : float;
  11730. var attitude : EAIAttitude;
  11731.  
  11732. if (!actor)
  11733. {
  11734. return false;
  11735. }
  11736.  
  11737. if ( finishableEnemiesList.Contains( actor ) )
  11738. {
  11739. return true;
  11740. }
  11741.  
  11742. if ( !actor.IsAlive() || actor.IsKnockedUnconscious() )
  11743. {
  11744. return false;
  11745. }
  11746.  
  11747. npc = (CNewNPC)actor;
  11748. if (npc && npc.IsHorse() )
  11749. {
  11750. return false;
  11751. }
  11752.  
  11753. if ( hostileEnemies.Contains( actor ) )
  11754. {
  11755. return true;
  11756. }
  11757.  
  11758. //MS: We add a tolerance to make geralt go to alertfar everytime he runs away from npc
  11759. if ( GetAttitudeBetween( this, actor ) == AIA_Hostile )
  11760. {
  11761. if ( usePrecalcs )
  11762. {
  11763. distanceToTarget = Distance2DBetweenCapsuleAndPoint( actor, this ) - targetingPrecalcs.playerRadius;
  11764. }
  11765. else
  11766. {
  11767. distanceToTarget = Distance2DBetweenCapsules( this, actor );
  11768. }
  11769.  
  11770. // shortDistance = findMoveTargetDist + 5.0f;
  11771. if ( distanceToTarget < findMoveTargetDist + 5.0f )
  11772. {
  11773. return true;
  11774. }
  11775.  
  11776. if ( actor.IsInCombat() || this.IsHardLockEnabled() )
  11777. {
  11778. targetCapsuleHeight = ( (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent() ).GetCapsuleHeight();
  11779. if ( targetCapsuleHeight >= 2.0f || npc.GetCurrentStance() == NS_Fly )
  11780. {
  11781. // expandedDistance = 40.f;
  11782. if ( distanceToTarget < 40.0f )
  11783. {
  11784. return true;
  11785. }
  11786. }
  11787. }
  11788. }
  11789.  
  11790. if ( actor.GetAttitudeGroup() == 'npc_charmed' )
  11791. {
  11792. if ( theGame.GetGlobalAttitude( GetBaseAttitudeGroup(), actor.GetBaseAttitudeGroup() ) == AIA_Hostile )
  11793. {
  11794. return true;
  11795. }
  11796. }
  11797.  
  11798. return false;
  11799. }
  11800.  
  11801. function SetBIsCombatActionAllowed ( flag : bool )
  11802. {
  11803. bIsCombatActionAllowed = flag;
  11804.  
  11805. if ( !flag )
  11806. {
  11807. SetBIsInCombatAction(true);
  11808. }
  11809. else
  11810. {
  11811. this.ProcessLAxisCaching();
  11812. //UnblockAction(EIAB_Interactions, 'InsideCombatAction' );
  11813. }
  11814.  
  11815. //LogChannel('combatActionAllowed', "Is SET TO: " + flag );
  11816. }
  11817.  
  11818. function GetBIsCombatActionAllowed() : bool
  11819. {
  11820. return bIsCombatActionAllowed;
  11821. }
  11822.  
  11823. function SetCombatAction( action : EBufferActionType )
  11824. {
  11825. currentCombatAction = action;
  11826. }
  11827.  
  11828. function GetCombatAction() : EBufferActionType
  11829. {
  11830. return currentCombatAction;
  11831. }
  11832.  
  11833. protected function WhenCombatActionIsFinished()
  11834. {
  11835. if(IsThrowingItem() || IsThrowingItemWithAim() )
  11836. {
  11837. if(inv.IsItemBomb(selectedItemId))
  11838. {
  11839. BombThrowAbort();
  11840. }
  11841. else
  11842. {
  11843. ThrowingAbort();
  11844. }
  11845. }
  11846.  
  11847. if ( this.GetCurrentStateName() != 'DismountHorse' )
  11848. OnRangedForceHolster( true );
  11849.  
  11850. //SetBehaviorVariable( 'combatActionType', (int)CAT_None2);
  11851. }
  11852.  
  11853. public function IsInCombatAction_Attack(): bool
  11854. {
  11855. if ( IsInCombatAction_NonSpecialAttack() || IsInCombatAction_SpecialAttack() )
  11856. return true;
  11857. else
  11858. return false;
  11859. }
  11860.  
  11861. public function IsInCombatAction_NonSpecialAttack(): bool
  11862. {
  11863. if ( IsInCombatAction() && ( GetCombatAction() == EBAT_LightAttack || GetCombatAction() == EBAT_HeavyAttack ) )
  11864. return true;
  11865. else
  11866. return false;
  11867. }
  11868.  
  11869. public function IsInSpecificCombatAction ( specificCombatAction : EBufferActionType ) : bool
  11870. {
  11871. if ( IsInCombatAction() && GetCombatAction() == specificCombatAction )
  11872. return true;
  11873. else
  11874. return false;
  11875. }
  11876.  
  11877. public function IsInRunAnimation() : bool
  11878. {
  11879. return isInRunAnimation;
  11880. }
  11881.  
  11882. //I need to call it after scene ends thats why it's public. PF
  11883. public function SetCombatIdleStance( stance : float )
  11884. {
  11885. SetBehaviorVariable( 'combatIdleStance', stance );
  11886. SetBehaviorVariable( 'CombatStanceForOverlay', stance );
  11887.  
  11888. if ( stance == 0.f )
  11889. LogChannel( 'ComboInput', "combatIdleStance = Left" );
  11890. else
  11891. LogChannel( 'ComboInput', "combatIdleStance = Right" );
  11892. }
  11893.  
  11894. public function GetCombatIdleStance() : float
  11895. {
  11896. // 0.f == Left
  11897. return GetBehaviorVariable( 'combatIdleStance' );
  11898. }
  11899.  
  11900. protected var isRotatingInPlace : bool;
  11901. event OnRotateInPlaceStart()
  11902. {
  11903. isRotatingInPlace = true;
  11904. }
  11905.  
  11906. event OnRotateInPlaceEnd()
  11907. {
  11908. isRotatingInPlace = false;
  11909. }
  11910.  
  11911. event OnFullyBlendedIdle()
  11912. {
  11913. if ( bLAxisReleased )
  11914. {
  11915. ResetRawPlayerHeading();
  11916. ResetCachedRawPlayerHeading();
  11917. defaultLocomotionController.ResetMoveDirection();
  11918. }
  11919. }
  11920.  
  11921. private var isInIdle : bool;
  11922.  
  11923. event OnPlayerIdleStart()
  11924. {
  11925. isInIdle = true;
  11926. }
  11927.  
  11928. event OnPlayerIdleEnd()
  11929. {
  11930. isInIdle = false;
  11931. }
  11932.  
  11933. public function IsInIdle() : bool
  11934. {
  11935. return isInIdle;
  11936. }
  11937.  
  11938. event OnRunLoopStart()
  11939. {
  11940. EnableRunCamera( true );
  11941. }
  11942.  
  11943. event OnRunLoopEnd()
  11944. {
  11945. EnableRunCamera( false );
  11946. }
  11947.  
  11948. event OnCombatActionStartBehgraph()
  11949. {
  11950. var buff : CBaseGameplayEffect;
  11951. var action : EBufferActionType;
  11952. var cost, delay : float;
  11953.  
  11954. // Block saves
  11955. //theGame.CreateNoSaveLock( noSaveLockCombatActionName, noSaveLockCombatAction, true );
  11956.  
  11957. OnCombatActionStart();
  11958.  
  11959. //Pause the stamina regen for as long as we're doing combat actions.
  11960. //Pause only once to avoid the pause counter from increasing with each lock
  11961. buff = GetBuff(EET_AutoStaminaRegen);
  11962.  
  11963. action = PerformingCombatAction();
  11964. switch ( action )
  11965. {
  11966. case EBAT_LightAttack :
  11967. {
  11968. abilityManager.GetStaminaActionCost(ESAT_LightAttack, cost, delay);
  11969. } break;
  11970. case EBAT_HeavyAttack :
  11971. {
  11972. abilityManager.GetStaminaActionCost(ESAT_HeavyAttack, cost, delay);
  11973. } break;
  11974. case EBAT_ItemUse :
  11975. {
  11976. abilityManager.GetStaminaActionCost(ESAT_UsableItem, cost, delay);
  11977. } break;
  11978. case EBAT_Parry :
  11979. {
  11980. abilityManager.GetStaminaActionCost(ESAT_Parry, cost, delay);
  11981. } break;
  11982. case EBAT_Dodge :
  11983. {
  11984. abilityManager.GetStaminaActionCost(ESAT_Dodge, cost, delay);
  11985. } break;
  11986. case EBAT_Roll :
  11987. abilityManager.GetStaminaActionCost(ESAT_Roll, cost, delay);
  11988. break;
  11989. case EBAT_SpecialAttack_Light :
  11990. {
  11991. abilityManager.GetStaminaActionCost(ESAT_Ability, cost, delay, 0,0, GetSkillAbilityName(S_Sword_s01));
  11992. } break;
  11993. case EBAT_SpecialAttack_Heavy :
  11994. {
  11995. abilityManager.GetStaminaActionCost(ESAT_Ability, cost, delay, 0,0, GetSkillAbilityName(S_Sword_s02));
  11996. } break;
  11997. case EBAT_Roll :
  11998. {
  11999. abilityManager.GetStaminaActionCost(ESAT_Evade, cost, delay);
  12000. } break;
  12001. /*
  12002. case EBAT_Ciri_SpecialAttack :
  12003. {
  12004. cost = GetStaminaActionCost();
  12005. } break;
  12006. */
  12007. default :
  12008. ;
  12009. }
  12010.  
  12011. if( (!buff || !buff.IsPaused('InsideCombatAction')) && delay > 0 )
  12012. PauseEffects(EET_AutoStaminaRegen, 'InsideCombatAction');
  12013. if( delay > 0 )
  12014. PauseStaminaRegen( 'InsideCombatAction' );
  12015. }
  12016.  
  12017. public function HolsterUsableItem() : bool
  12018. {
  12019. return holsterUsableItem;
  12020. }
  12021.  
  12022. private var isInGuardedState : bool;
  12023. public function IsInGuardedState() : bool
  12024. {
  12025. return isInGuardedState;
  12026. }
  12027.  
  12028. event OnGuardedStart()
  12029. {
  12030. isInParryOrCounter = true;
  12031. isInGuardedState = true;
  12032. }
  12033.  
  12034. event OnGuardedEnd()
  12035. {
  12036. isInParryOrCounter = false;
  12037. isInGuardedState = false;
  12038. }
  12039.  
  12040. private var restoreUsableItem : bool;
  12041. private var holsterUsableItem : bool;
  12042. event OnCombatActionStart()
  12043. {
  12044. //Block Actions
  12045. //BlockAction( EIAB_DrawWeapon, 'OnCombatActionStart' );
  12046. BlockAction( EIAB_UsableItem, 'OnCombatActionStart' );
  12047. BlockAction( EIAB_CallHorse, 'OnCombatActionStart' );
  12048.  
  12049. /*if ( !IsGuarded() )
  12050. SetParryTarget( NULL );*/
  12051.  
  12052. LogChannel('combatActionAllowed',"FALSE OnCombatActionStart");
  12053. SetBIsCombatActionAllowed( false );
  12054. SetBIsInputAllowed( false, 'OnCombatActionStart' );
  12055. //lastAxisInputIsMovement = true;
  12056.  
  12057. ClearFinishableEnemyList( 0.f, 0 );
  12058.  
  12059. bIsInHitAnim = false;
  12060.  
  12061. //Holster Crossbow if it's held
  12062. //if ( inv.IsItemCrossbow( inv.GetItemFromSlot( 'l_weapon' ) ) )//&& GetBehaviorVariable( 'combatActionType' ) != (int)CAT_Crossbow )
  12063. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  12064. {
  12065. CleanCombatActionBuffer();
  12066. SetIsAimingCrossbow( false );
  12067. OnRangedForceHolster( false, true );
  12068. }
  12069.  
  12070. //Holster UsableItem if it's held
  12071. holsterUsableItem = false;
  12072. if ( thePlayer.IsHoldingItemInLHand() ) // && !thePlayer.IsUsableItemLBlocked() )
  12073. {
  12074. if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign )
  12075. holsterUsableItem = false;
  12076. else if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack )
  12077. {
  12078. if ( this.GetCurrentStateName() == 'CombatFists' )
  12079. holsterUsableItem = false;
  12080. }
  12081. }
  12082.  
  12083. if ( holsterUsableItem )
  12084. {
  12085. thePlayer.SetPlayerActionToRestore ( PATR_None );
  12086. thePlayer.OnUseSelectedItem( true );
  12087.  
  12088. restoreUsableItem = true;
  12089. }
  12090.  
  12091. //Stop Geralt from automatically attacking while in AttackApproach when Player performs a non-attack combat action
  12092. if ( GetBehaviorVariable( 'combatActionType' ) != (int)CAT_Attack && GetBehaviorVariable( 'combatActionType' ) != (int)CAT_PreAttack )
  12093. {
  12094. RemoveTimer( 'ProcessAttackTimer' );
  12095. RemoveTimer( 'AttackTimerEnd' );
  12096. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12097. }
  12098. else
  12099. {
  12100. //MS: Do not remove this!! The attack to idle transition states will not work correctly if you change weapon mid-attack.
  12101. BlockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12102. }
  12103.  
  12104. //GetMovingAgentComponent().SnapToNavigableSpace(true);
  12105. }
  12106.  
  12107. var isInParryOrCounter : bool;
  12108. event OnParryOrCounterStart()
  12109. {
  12110. isInParryOrCounter = true;
  12111. OnCombatActionStartBehgraph();
  12112. }
  12113.  
  12114. event OnParryOrCounterEnd()
  12115. {
  12116. isInParryOrCounter = false;
  12117. OnCombatActionEnd();
  12118. SetBIsInCombatAction( false );
  12119. }
  12120.  
  12121. //called when a combat action is completed (e.g. single hit in a combo sequence)
  12122. event OnCombatActionEnd()
  12123. {
  12124. var item : SItemUniqueId;
  12125. var combatActionType : float;
  12126.  
  12127. super.OnCombatActionEnd();
  12128.  
  12129.  
  12130. //Unblock Actions
  12131. BlockAllActions( 'OnCombatActionStart', false );
  12132.  
  12133. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12134.  
  12135. //why? this way after EACH attack you reset it - what's the point then?
  12136. //ResetUninterruptedHitsCount();
  12137.  
  12138.  
  12139. UnblockAction( EIAB_Movement, 'CombatActionFriendly' );
  12140.  
  12141.  
  12142.  
  12143.  
  12144. oTCameraOffset = 0.f;
  12145. oTCameraPitchOffset = 0.f;
  12146.  
  12147. //LogChannel('combatActionAllowed',"TRUE OnCombatActionEnd");
  12148. SetBIsCombatActionAllowed( true );
  12149. //reapply critical buff if any
  12150. //Z ReapplyCriticalBuff();
  12151. SetBIsInputAllowed( true, 'OnCombatActionEnd' );
  12152. SetCanPlayHitAnim( true );
  12153. EnableFindTarget( true );
  12154.  
  12155. SetIsCurrentlyDodging( false );
  12156.  
  12157.  
  12158. SetFinisherVictim( NULL );
  12159.  
  12160. OnBlockAllCombatTickets( false );
  12161.  
  12162. LogStamina("CombatActionEnd");
  12163.  
  12164. //GetMovingAgentComponent().SnapToNavigableSpace(false);
  12165.  
  12166. SetAttackActionName('');
  12167. combatActionType = GetBehaviorVariable('combatActionType');
  12168.  
  12169. //clean-up after special attack heavy finishes
  12170. if(GetBehaviorVariable('combatActionType') == (int)CAT_SpecialAttack)
  12171. {
  12172. theGame.GetGameCamera().StopAnimation( 'camera_shake_loop_lvl1_1' );
  12173. OnSpecialAttackHeavyActionProcess();
  12174. }
  12175. // Do we need to interrupt?
  12176. substateManager.ReactToChanceToFallAndSlide();
  12177. }
  12178.  
  12179. event OnCombatActionFriendlyStart()
  12180. {
  12181. SetBIsInCombatActionFriendly(true);
  12182. BlockAction( EIAB_Movement, 'CombatActionFriendly', false, false, false );
  12183. OnCombatActionStart();
  12184. }
  12185.  
  12186. event OnCombatActionFriendlyEnd()
  12187. {
  12188. SetBIsInCombatActionFriendly(false);
  12189. UnblockAction( EIAB_Movement, 'CombatActionFriendly' );
  12190. OnCombatActionEnd();
  12191. SetBIsInCombatAction(false);
  12192. //RaiseForceEvent( 'ForceIdle' );
  12193. }
  12194.  
  12195. event OnHitStart()
  12196. {
  12197. var timeLeft : float;
  12198. var currentEffects : array<CBaseGameplayEffect>;
  12199. var none : SAbilityAttributeValue;
  12200.  
  12201. CancelHoldAttacks();
  12202. WhenCombatActionIsFinished();
  12203. if ( isInFinisher )
  12204. {
  12205. if ( finisherTarget )
  12206. ( (CNewNPC)finisherTarget ).SignalGameplayEvent( 'FinisherInterrupt' );
  12207. isInFinisher = false;
  12208. finisherTarget = NULL;
  12209. SetBIsCombatActionAllowed( true );
  12210. }
  12211.  
  12212. bIsInHitAnim = true;
  12213.  
  12214. OnCombatActionStart(); //"because it's needed"
  12215.  
  12216. //OnCombatActionStart pauses the regen and we don't want that
  12217. ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction');
  12218.  
  12219. if( GetHealthPercents() < 0.3f )
  12220. {
  12221. PlayBattleCry('BattleCryBadSituation', 0.10f, true );
  12222. }
  12223. else
  12224. {
  12225. PlayBattleCry('BattleCryBadSituation', 0.05f, true );
  12226. }
  12227. }
  12228.  
  12229. event OnHitStartSwimming()
  12230. {
  12231. OnRangedForceHolster( true, true, false );
  12232. }
  12233.  
  12234. private var finisherSaveLock : int;
  12235. event OnFinisherStart()
  12236. {
  12237. var currentEffects : array<CBaseGameplayEffect>;
  12238.  
  12239. theGame.CreateNoSaveLock("Finisher",finisherSaveLock,true,false);
  12240.  
  12241. isInFinisher = true;
  12242.  
  12243. finisherTarget = slideTarget;
  12244. OnCombatActionStart();
  12245.  
  12246. CancelHoldAttacks();
  12247.  
  12248. PlayFinisherCameraAnimation( theGame.GetSyncAnimManager().GetFinisherCameraAnimName() );
  12249. this.AddAnimEventCallback('SyncEvent','OnFinisherAnimEvent_SyncEvent');
  12250. SetImmortalityMode( AIM_Invulnerable, AIC_SyncedAnim );
  12251. }
  12252.  
  12253. public function IsPerformingFinisher() : bool
  12254. {
  12255. return isInFinisher;
  12256. }
  12257.  
  12258. private function PlayFinisherCameraAnimation( cameraAnimName : name )
  12259. {
  12260. var camera : CCustomCamera = theGame.GetGameCamera();
  12261. var animation : SCameraAnimationDefinition;
  12262.  
  12263. if (IsLastEnemyKilled() && theGame.GetWorld().NavigationCircleTest( this.GetWorldPosition(), 3.f ) )
  12264. {
  12265. camera.StopAnimation('camera_shake_hit_lvl3_1' );
  12266.  
  12267. animation.animation = cameraAnimName;
  12268. animation.priority = CAP_Highest;
  12269. animation.blendIn = 0.15f;
  12270. animation.blendOut = 1.0f;
  12271. animation.weight = 1.f;
  12272. animation.speed = 1.0f;
  12273. animation.reset = true;
  12274.  
  12275. camera.PlayAnimation( animation );
  12276. //thePlayer.AddTimer( 'RemoveFinisherCameraAnimationCheck', 0.01, true );
  12277.  
  12278. thePlayer.EnableManualCameraControl( false, 'Finisher' );
  12279. }
  12280. }
  12281.  
  12282. public function IsLastEnemyKilled() : bool
  12283. {
  12284. var tempMoveTargets : array<CActor>;
  12285.  
  12286. FindMoveTarget();
  12287. tempMoveTargets = GetMoveTargets();
  12288. if ( tempMoveTargets.Size() <= 0 || !thePlayer.IsThreat( tempMoveTargets[0] ) )
  12289. return true;
  12290.  
  12291. return false;
  12292. }
  12293.  
  12294. event OnFinisherAnimEvent_SyncEvent( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  12295. {
  12296. if ( finisherTarget )
  12297. ( (CNewNPC)finisherTarget ).SignalGameplayEvent('FinisherKill');
  12298. finisherTarget = NULL;
  12299. }
  12300.  
  12301. event OnFinisherEnd()
  12302. {
  12303. isInFinisher = false;
  12304. finisherTarget = NULL;
  12305.  
  12306. theGame.ReleaseNoSaveLock(finisherSaveLock);
  12307.  
  12308. this.RemoveAnimEventCallback('SyncEvent');
  12309.  
  12310. //SetIsPerformingPhaseChangeAnimation( false ); // for eredin fight
  12311. SetImmortalityMode( AIM_None, AIC_SyncedAnim );
  12312. theGame.RemoveTimeScale( 'AnimEventSlomoMo' );
  12313. AddTimer( 'FinisherEndEnableCamera', 0.5f );
  12314. //OnBlockAllCombatTickets( false );
  12315. OnCombatActionEnd();
  12316. OnCombatActionEndComplete();
  12317. }
  12318.  
  12319. private timer function FinisherEndEnableCamera( dt : float, id : int )
  12320. {
  12321. thePlayer.EnableManualCameraControl( true, 'Finisher' );
  12322. }
  12323.  
  12324. public function SpawnFinisherBlood()
  12325. {
  12326. var weaponEntity : CEntity;
  12327. var weaponSlotMatrix : Matrix;
  12328. var bloodFxPos : Vector;
  12329. var bloodFxRot : EulerAngles;
  12330. var tempEntity : CEntity;
  12331.  
  12332. weaponEntity = this.GetInventory().GetItemEntityUnsafe( GetInventory().GetItemFromSlot('r_weapon') );
  12333. weaponEntity.CalcEntitySlotMatrix( 'blood_fx_point', weaponSlotMatrix );
  12334. bloodFxPos = MatrixGetTranslation( weaponSlotMatrix );
  12335. bloodFxRot = this.GetWorldRotation();//MatrixGetRotation( weaponSlotMatrix );
  12336. tempEntity = theGame.CreateEntity( (CEntityTemplate)LoadResource('finisher_blood'), bloodFxPos, bloodFxRot);
  12337. tempEntity.PlayEffect('crawl_blood');
  12338. }
  12339.  
  12340. //called when all combat actions have ended (e.g. whole combo)
  12341. event OnCombatActionEndComplete()
  12342. {
  12343. var buff : CBaseGameplayEffect;
  12344.  
  12345. buff = ChooseCurrentCriticalBuffForAnim();
  12346. SetCombatAction( EBAT_EMPTY );
  12347.  
  12348. //Unblock Actions what you wann
  12349. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart' );
  12350. UnblockAction( EIAB_OpenInventory, 'OnCombatActionStart' );
  12351. UnblockAction( EIAB_UsableItem, 'OnCombatActionStart' );
  12352.  
  12353. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12354.  
  12355. SetUnpushableTarget( NULL );
  12356. SetBIsInCombatAction(false);
  12357. SetIsCurrentlyDodging(false);
  12358. SetMoveTargetChangeAllowed( true );
  12359. SetCanPlayHitAnim( true );
  12360.  
  12361. SetFinisherVictim( NULL );
  12362.  
  12363. this.RemoveBuffImmunity(EET_Burning, 'AnimEvent_RemoveBurning');
  12364.  
  12365. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' && !buff )
  12366. {
  12367. ClearCustomOrientationInfoStack();
  12368. SetSlideTarget( NULL );
  12369. }
  12370.  
  12371. UnblockAction( EIAB_Crossbow, 'OnForceHolster' );
  12372.  
  12373. specialAttackCamera = false;
  12374.  
  12375. bIsRollAllowed = false;
  12376.  
  12377. if ( bLAxisReleased )
  12378. {
  12379. ResetRawPlayerHeading();
  12380. ResetCachedRawPlayerHeading();
  12381. }
  12382.  
  12383. //reapply critical buff if any
  12384. ReapplyCriticalBuff();
  12385. SetBIsInputAllowed( true, 'OnCombatActionEndComplete' );
  12386.  
  12387. //stamina regen is paused as long as we are doing some combat actions
  12388. ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction');
  12389.  
  12390. bIsInHitAnim = false;
  12391.  
  12392. SetBIsCombatActionAllowed( true );
  12393.  
  12394. m_LastWeaponTipPos = Vector(0, 0, 0, 0 );
  12395.  
  12396. //free tickets
  12397. this.AddTimer('FreeTickets',3.f,false);
  12398.  
  12399. // remove save lock
  12400. //theGame.ReleaseNoSaveLockByName( noSaveLockCombatActionName );
  12401. }
  12402.  
  12403. event OnMovementFullyBlended()
  12404. {
  12405. SetBehaviorVariable( 'isPerformingSpecialAttack', 0.f );
  12406.  
  12407. if ( restoreUsableItem )
  12408. {
  12409. restoreUsableItem = false;
  12410. SetPlayerActionToRestore ( PATR_Default );
  12411. OnUseSelectedItem();
  12412. }
  12413. }
  12414.  
  12415. event OnCombatMovementStart()
  12416. {
  12417. SetCombatIdleStance( 1.f );
  12418. OnCombatActionEndComplete();
  12419. }
  12420.  
  12421. timer function FreeTickets( dt : float, id : int )
  12422. {
  12423. FreeTicketAtCombatTarget();
  12424. }
  12425.  
  12426.  
  12427. /*
  12428. These declarations are needed here only to call event with the same name inside combat state (there's no other way to call it!).
  12429. */
  12430. event OnGuardedReleased(){}
  12431. event OnPerformAttack( playerAttackType : name ){}
  12432. event OnPerformEvade( playerEvadeType : EPlayerEvadeType ){}
  12433. event OnInterruptAttack(){}
  12434. event OnPerformGuard(){}
  12435. event OnSpawnHorse(){}
  12436. event OnDismountActionScriptCallback(){}
  12437.  
  12438. event OnHorseSummonStart()
  12439. {
  12440. thePlayer.BlockAction(EIAB_CallHorse, 'HorseSummon');
  12441. thePlayer.BlockAction(EIAB_Signs, 'HorseSummon');
  12442. thePlayer.BlockAction(EIAB_Crossbow, 'HorseSummon');
  12443. thePlayer.BlockAction(EIAB_UsableItem, 'HorseSummon');
  12444. thePlayer.BlockAction(EIAB_ThrowBomb, 'HorseSummon');
  12445. thePlayer.BlockAction(EIAB_SwordAttack, 'HorseSummon');
  12446. thePlayer.BlockAction(EIAB_Jump, 'HorseSummon');
  12447. thePlayer.BlockAction(EIAB_Dodge, 'HorseSummon');
  12448. thePlayer.BlockAction(EIAB_LightAttacks, 'HorseSummon');
  12449. thePlayer.BlockAction(EIAB_HeavyAttacks, 'HorseSummon');
  12450. thePlayer.BlockAction(EIAB_SpecialAttackLight, 'HorseSummon');
  12451. thePlayer.BlockAction(EIAB_SpecialAttackHeavy, 'HorseSummon');
  12452.  
  12453. horseSummonTimeStamp = theGame.GetEngineTimeAsSeconds();
  12454. }
  12455.  
  12456. event OnHorseSummonStop()
  12457. {
  12458. thePlayer.BlockAllActions('HorseSummon',false);
  12459. }
  12460.  
  12461. /*
  12462. CombatAction events when on vehicles
  12463. */
  12464. event OnCombatActionStartVehicle( action : EVehicleCombatAction )
  12465. {
  12466. this.SetBIsCombatActionAllowed( false );
  12467.  
  12468. if ( action != EHCA_ShootCrossbow )
  12469. {
  12470. SetIsAimingCrossbow( false );
  12471. OnRangedForceHolster();
  12472. }
  12473. }
  12474.  
  12475. event OnCombatActionEndVehicle()
  12476. {
  12477. this.SetBIsCombatActionAllowed( true );
  12478. }
  12479.  
  12480. ////////////////////////////////////////////////////////////////////////////////////////////
  12481. /////////////////////////// @CRITICAL STATES /////////////////////////////////////////////
  12482. ////////////////////////////////////////////////////////////////////////////////////////////
  12483.  
  12484. protected function CriticalBuffInformBehavior(buff : CBaseGameplayEffect)
  12485. {
  12486. /*if ( this.GetCurrentStateName() == 'Exploration' || this.GetCurrentStateName() == 'AimThrow' )
  12487. GotoCombatStateWithAction( IA_CriticalState, buff );
  12488. else
  12489. {*/
  12490. if( !CanAnimationReactToCriticalState( buff ) )
  12491. {
  12492. return;
  12493. }
  12494.  
  12495. // if ( IsInCombatAction() )
  12496. // RaiseEvent('ForceBlendOut');
  12497.  
  12498. SetBehaviorVariable( 'CriticalStateType', (int)GetBuffCriticalType(buff) );
  12499. SetBehaviorVariable( 'bCriticalState', 1);
  12500.  
  12501. if(CriticalBuffUsesFullBodyAnim(buff))
  12502. RaiseEvent('CriticalState');
  12503.  
  12504. SetBehaviorVariable( 'IsInAir', (int)IsInAir());
  12505.  
  12506. LogCritical("Sending player critical state event for <<" + buff.GetEffectType() + ">>");
  12507.  
  12508. //}
  12509. }
  12510.  
  12511. private function CanAnimationReactToCriticalState( buff : CBaseGameplayEffect ) : bool
  12512. {
  12513. var buffCritical : W3CriticalEffect;
  12514. var buffCriticalDOT : W3CriticalDOTEffect;
  12515. var isHeavyCritical : bool;
  12516.  
  12517. isHeavyCritical = false;
  12518.  
  12519. // Find out if it is a heavy critical state
  12520. buffCritical = ( W3CriticalEffect ) buff;
  12521. if( buffCritical )
  12522. {
  12523. isHeavyCritical = buffCritical.explorationStateHandling == ECH_HandleNow;
  12524. }
  12525. else
  12526. {
  12527. buffCriticalDOT = ( W3CriticalDOTEffect ) buff;
  12528. if( buffCriticalDOT )
  12529. {
  12530. isHeavyCritical = buffCriticalDOT.explorationStateHandling == ECH_HandleNow;
  12531. }
  12532. }
  12533.  
  12534. // If it is not, we may skip it
  12535. if( !isHeavyCritical )
  12536. {
  12537. if( !CanReactToCriticalState() )
  12538. {
  12539. return false;
  12540. }
  12541. }
  12542.  
  12543. return true;
  12544. }
  12545.  
  12546. public function CanReactToCriticalState() : bool
  12547. {
  12548. return substateManager.CanReactToHardCriticalState();
  12549. }
  12550.  
  12551. event OnCriticalStateAnimStart()
  12552. {
  12553. var heading : float;
  12554. var newCritical : ECriticalStateType;
  12555. var newReqCS : CBaseGameplayEffect;
  12556.  
  12557. OnCombatActionEndComplete();
  12558.  
  12559. //abort throwing if super was processed properly
  12560. newReqCS = newRequestedCS;
  12561. if(super.OnCriticalStateAnimStart())
  12562. {
  12563. //WhenCombatActionIsFinished();
  12564. RemoveTimer( 'IsItemUseInputHeld' );
  12565. keepRequestingCriticalAnimStart = false;
  12566. CancelHoldAttacks();
  12567.  
  12568. //knockdown direction
  12569. // No knockdown when using a vehicule: the vehicule will handle the knock down logic
  12570. //PFTODO
  12571. //we need this for NPCs also (knockdown dir)
  12572. if(!IsUsingVehicle())
  12573. {
  12574. newCritical = GetBuffCriticalType(newReqCS);
  12575. if(newCritical == ECST_HeavyKnockdown
  12576. || newCritical == ECST_Knockdown
  12577. || newCritical == ECST_Stagger
  12578. || newCritical == ECST_Ragdoll
  12579. || newCritical == ECST_LongStagger )
  12580. {
  12581. if(newReqCS.GetCreator())
  12582. heading = VecHeading(newReqCS.GetCreator().GetWorldPosition() - GetWorldPosition());
  12583. else
  12584. heading = GetHeading();
  12585.  
  12586. //this.GetMovingAgentComponent().GetMovementAdjustor().CancelAll();
  12587. SetCustomRotation( 'Knockdown', heading, 2160.f, 0.1f, true );
  12588.  
  12589. if ( newCritical != ECST_Stagger && newCritical != ECST_LongStagger )
  12590. substateManager.ReactOnCriticalState( true );
  12591. }
  12592. }
  12593.  
  12594. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'CriticalEffectStart', -1, 30.0f, -1.f, -1, true );
  12595. return true;
  12596. }
  12597.  
  12598. //SetBehaviorVariable( 'bCriticalStopped', 1);
  12599. return false;
  12600. }
  12601.  
  12602. /*
  12603. Called when new critical effect has started
  12604. This will interrupt current critical state
  12605.  
  12606. returns true if the effect got fired properly
  12607. */
  12608. public function StartCSAnim(buff : CBaseGameplayEffect) : bool
  12609. {
  12610. SetBehaviorVariable( 'bCriticalStopped', 0 );
  12611.  
  12612. if(super.StartCSAnim(buff))
  12613. {
  12614. if(!CriticalBuffUsesFullBodyAnim(buff))
  12615. {
  12616. OnCriticalStateAnimStart();
  12617. }
  12618.  
  12619. ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction');
  12620.  
  12621. keepRequestingCriticalAnimStart = true;
  12622. AddTimer('RequestCriticalAnimStart', 0, true);
  12623. //RequestCriticalAnimStart(0);
  12624.  
  12625. return true;
  12626. }
  12627.  
  12628. return false;
  12629. }
  12630.  
  12631. public function CriticalEffectAnimationInterrupted(reason : string) : bool
  12632. {
  12633. var ret : bool; //for debug
  12634.  
  12635. LogCriticalPlayer("R4Player.CriticalEffectAnimationInterrupted() - because: " + reason);
  12636.  
  12637. ret = super.CriticalEffectAnimationInterrupted(reason);
  12638.  
  12639. if(ret)
  12640. {
  12641. keepRequestingCriticalAnimStart = false;
  12642. }
  12643.  
  12644. substateManager.ReactOnCriticalState( false );
  12645.  
  12646. return ret;
  12647. }
  12648.  
  12649. public function CriticalStateAnimStopped(forceRemoveBuff : bool)
  12650. {
  12651. LogCriticalPlayer("R4Player.CriticalStateAnimStopped() - forced: " + forceRemoveBuff);
  12652.  
  12653. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'RecoveredFromCriticalEffect', -1, 30.0f, -1.f, -1, true );
  12654. super.CriticalStateAnimStopped(forceRemoveBuff);
  12655.  
  12656. substateManager.ReactOnCriticalState( false );
  12657. }
  12658.  
  12659. // keeps requesting (sending event) to enter critical states anim state in behavior
  12660. timer function RequestCriticalAnimStart(dt : float, id : int)
  12661. {
  12662. if(keepRequestingCriticalAnimStart)
  12663. {
  12664. if(newRequestedCS && newRequestedCS.GetDurationLeft() > 0)
  12665. {
  12666. CriticalBuffInformBehavior(newRequestedCS);
  12667. }
  12668. else
  12669. {
  12670. keepRequestingCriticalAnimStart = false;
  12671. RemoveTimer('RequestCriticalAnimStart');
  12672. }
  12673. }
  12674. else
  12675. {
  12676. RemoveTimer('RequestCriticalAnimStart');
  12677. }
  12678. }
  12679.  
  12680. event OnRagdollUpdate(progress : float)
  12681. {
  12682. //super.OnRagdollUpdate(progress);
  12683.  
  12684. SetIsInAir(progress == 0);
  12685. }
  12686.  
  12687. // getting from ragdoll after certain time has passed
  12688. event OnRagdollOnGround()
  12689. {
  12690. // try to getup immediately as currently when laying on ground we might be constantly switched between on ground and in air
  12691. TryToEndRagdollOnGround( 0.0f );
  12692. }
  12693.  
  12694. event OnRagdollInAir()
  12695. {
  12696. RemoveTimer('TryToEndRagdollOnGround');
  12697. }
  12698.  
  12699. event OnNoLongerInRagdoll()
  12700. {
  12701. RemoveTimer('TryToEndRagdollOnGround');
  12702. }
  12703.  
  12704. timer function TryToEndRagdollOnGround( td : float, optional id : int)
  12705. {
  12706. var critical : CBaseGameplayEffect;
  12707. var type : EEffectType;
  12708.  
  12709. critical = GetCurrentlyAnimatedCS();
  12710. if(critical)
  12711. {
  12712. type = critical.GetEffectType();
  12713. if(type == EET_Knockdown || type == EET_HeavyKnockdown || type == EET_Ragdoll)
  12714. {
  12715. // 2.5 seconds is not that long but this is not ragdoll simulator :)
  12716. if (critical.GetTimeActive() >= 2.5f)
  12717. {
  12718. SetIsInAir(false);
  12719. RequestCriticalAnimStop();
  12720. RemoveTimer('TryToEndRagdollOnGround');
  12721. }
  12722. else
  12723. {
  12724. AddTimer('TryToEndRagdollOnGround', 0.2f, true);
  12725. }
  12726. return;
  12727. }
  12728. }
  12729.  
  12730. // not in critical or type differs
  12731. RemoveTimer('TryToEndRagdollOnGround');
  12732. }
  12733.  
  12734. public function RequestCriticalAnimStop(optional dontSetCriticalToStopped : bool)
  12735. {
  12736. var buff : CBaseGameplayEffect;
  12737.  
  12738. buff = GetCurrentlyAnimatedCS();
  12739. if(buff && !CriticalBuffUsesFullBodyAnim(buff))
  12740. {
  12741. CriticalStateAnimStopped(false);
  12742. }
  12743.  
  12744. if(!buff || !CriticalBuffUsesFullBodyAnim(buff))
  12745. {
  12746. SetBehaviorVariable( 'bCriticalState', 0);
  12747. }
  12748.  
  12749. super.RequestCriticalAnimStop(dontSetCriticalToStopped);
  12750. }
  12751. ////////////////////////////////////////////////////////////////////////////////////////////
  12752. // @Buffs @Effects
  12753. ////////////////////////////////////////////////////////////////////////////////////////////
  12754.  
  12755. public function SimulateBuffTimePassing(simulatedTime : float)
  12756. {
  12757. effectManager.SimulateBuffTimePassing(simulatedTime);
  12758. }
  12759.  
  12760. public function AddEffectDefault(effectType : EEffectType, creat : CGameplayEntity, srcName : string, optional isSignEffect : bool) : EEffectInteract
  12761. {
  12762. var params : SCustomEffectParams;
  12763.  
  12764. /*
  12765. Welcome to the Ancient Pit. If you're here reading this then you're doomed...
  12766.  
  12767. You're probably asking why someone is overriding default effect durations with some custom arbitrary numbers...
  12768.  
  12769. The thuth is: noone remembers...
  12770.  
  12771. But we need this and you cannot remove it or shit will start falling apart.
  12772. */
  12773. if(effectType == EET_Stagger || effectType == EET_LongStagger || effectType == EET_Knockdown || effectType == EET_HeavyKnockdown)
  12774. {
  12775. params.effectType = effectType;
  12776. params.creator = creat;
  12777. params.sourceName = srcName;
  12778. params.isSignEffect = isSignEffect;
  12779.  
  12780. if ( effectType == EET_Stagger )
  12781. params.duration = 1.83;
  12782. else if ( effectType == EET_LongStagger )
  12783. params.duration = 4;
  12784. else if ( effectType == EET_Knockdown )
  12785. params.duration = 2.5;
  12786. else if ( effectType == EET_HeavyKnockdown )
  12787. params.duration = 4;
  12788.  
  12789. return super.AddEffectCustom(params);
  12790. }
  12791. else
  12792. {
  12793. return super.AddEffectDefault(effectType, creat, srcName, isSignEffect);
  12794. }
  12795. }
  12796.  
  12797.  
  12798. ////////////////////////////////////////////////////////////////////////////////////////////
  12799.  
  12800. //a cheat to ressurect player
  12801.  
  12802.  
  12803. public function CheatResurrect()
  12804. {
  12805. var items : array< SItemUniqueId >;
  12806. var i, size, itemLevel, maxPrice, itemPrice : int;
  12807. var itemToEquip : SItemUniqueId;
  12808.  
  12809. if(IsAlive())
  12810. return;
  12811.  
  12812.  
  12813. if ( !theGame.GetGuiManager().GetRootMenu() )
  12814. {
  12815. Log(" *** Call this function after DeathScreen appears *** ");
  12816. return;
  12817. }
  12818.  
  12819. SetAlive(true);
  12820.  
  12821. SetKinematic(true);
  12822.  
  12823. delete abilityManager;
  12824. delete effectManager;
  12825.  
  12826. SetAbilityManager(); //defined in inheriting classes but must be called before setting any other managers - sets skills and stats
  12827. abilityManager.Init(this, GetCharacterStats(), false, theGame.GetDifficultyMode());
  12828.  
  12829. SetEffectManager();
  12830.  
  12831. abilityManager.PostInit(); //called after other managers are ready
  12832.  
  12833. EnableFindTarget( true );
  12834. SetBehaviorVariable( 'Ragdoll_Weight', 0.f );
  12835. RaiseForceEvent( 'RecoverFromRagdoll' );
  12836. SetCanPlayHitAnim( true );
  12837. SetBehaviorVariable( 'CriticalStateType', (int)ECST_None );
  12838. //if( GetCurrentStateName() != 'CombatSteel')
  12839. // PushState( 'CombatSteel' );
  12840. //else
  12841. GoToStateIfNew('Exploration');
  12842.  
  12843. ( (CDismembermentComponent)this.GetComponent( 'Dismemberment' ) ).ClearVisibleWound();
  12844.  
  12845. SetIsInAir(false); //might block getup from ragdol in knockdown
  12846.  
  12847. theInput.SetContext('Exploration');
  12848.  
  12849. ResetDeathType();
  12850.  
  12851. ForceUnlockAllInputActions(false);
  12852.  
  12853. theGame.CloseMenu('DeathScreenMenu');
  12854.  
  12855. //restore sounds
  12856. theSound.LeaveGameState(ESGS_Death);
  12857.  
  12858. theGame.ReleaseNoSaveLock(deathNoSaveLock);
  12859.  
  12860.  
  12861. abilityManager.ForceSetStat(BCS_Vitality, GetStatMax(BCS_Vitality));
  12862. effectManager.StopVitalityRegen();
  12863. abilityManager.ForceSetStat( BCS_Air , 100.f );
  12864. effectManager.StopAirRegen();
  12865. abilityManager.ForceSetStat( BCS_Stamina , 100.f );
  12866. effectManager.StopStaminaRegen();
  12867. abilityManager.ForceSetStat( BCS_Toxicity , 0.f );
  12868. abilityManager.ForceSetStat( BCS_Focus , 0.f );
  12869. GetWitcherPlayer().UpdateEncumbrance();
  12870.  
  12871.  
  12872. if ( !inv.IsThereItemOnSlot( EES_SteelSword ) )
  12873. {
  12874. items = inv.GetItemsByCategory( 'steelsword' );
  12875. }
  12876. else if ( !inv.IsThereItemOnSlot( EES_SilverSword ) )
  12877. {
  12878. items = inv.GetItemsByCategory( 'silversword' );
  12879. }
  12880.  
  12881. size = items.Size();
  12882. maxPrice = -1;
  12883. for ( i = 0; i < size; i += 1 )
  12884. {
  12885. itemPrice = inv.GetItemPrice(items[i]);
  12886. itemLevel = inv.GetItemLevel(items[i]);
  12887. if ( itemLevel <= GetLevel() && itemPrice > maxPrice )
  12888. {
  12889. maxPrice = itemPrice;
  12890. itemToEquip = items[i];
  12891. }
  12892. }
  12893. if( inv.IsIdValid( itemToEquip ) )
  12894. {
  12895. EquipItem( itemToEquip , , true );
  12896. }
  12897.  
  12898. theGame.ReleaseNoSaveLock(deathNoSaveLock);
  12899. }
  12900.  
  12901. ////////////////////////////////////////////////////////////////////////////////////////////
  12902.  
  12903. public function SetIsInsideInteraction(b : bool) {isInsideInteraction = b;}
  12904. public function IsInsideInteraction() : bool {return isInsideInteraction;}
  12905.  
  12906. public function SetIsInsideHorseInteraction( b : bool, horse : CEntity )
  12907. {
  12908. isInsideHorseInteraction = b;
  12909. horseInteractionSource = horse;
  12910. }
  12911. public function IsInsideHorseInteraction() : bool {return isInsideHorseInteraction;}
  12912.  
  12913.  
  12914. event OnInteractionActivationTest( interactionComponentName : string, activator : CEntity )
  12915. {
  12916. if ( interactionComponentName == "ClimbLadder" )
  12917. {
  12918. if( PlayerHasLadderExplorationReady() )
  12919. {
  12920. return true;
  12921. }
  12922. }
  12923.  
  12924. return false;
  12925. }
  12926.  
  12927. private function PlayerHasLadderExplorationReady() : bool
  12928. {
  12929. if( !substateManager.CanInteract() )
  12930. {
  12931. return false;
  12932. }
  12933.  
  12934. if( !substateManager.m_SharedDataO.HasValidLadderExploration() )
  12935. {
  12936. return false;
  12937. }
  12938.  
  12939. return true;
  12940. }
  12941.  
  12942. ////////////////////////////////////////////////////////////////////////////////////////////
  12943. ////////////////////////////// @COMBAT /////////////////////////////////////////////////
  12944. ////////////////////////////////////////////////////////////////////////////////////////////
  12945.  
  12946. public function SetGuarded(flag : bool)
  12947. {
  12948. super.SetGuarded(flag);
  12949.  
  12950. if(flag && FactsQuerySum("tut_fight_use_slomo") > 0)
  12951. {
  12952. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) );
  12953. FactsRemove("tut_fight_slomo_ON");
  12954. }
  12955. }
  12956.  
  12957.  
  12958. public function IsGuarded() : bool
  12959. {
  12960. return super.IsGuarded() && ( !rangedWeapon || rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' );
  12961. }
  12962. ////////////////////////////////////////////////////////////////////////////////////////////
  12963. ///////////////////// @THROWABLE @BOMBS @PETARDS @Usable ///////////////////////////////////
  12964. ////////////////////////////////////////////////////////////////////////////////////////////
  12965.  
  12966. public function GetSelectedItemId() : SItemUniqueId {return selectedItemId;}
  12967. public function ClearSelectedItemId() {selectedItemId = GetInvalidUniqueId();}
  12968.  
  12969. public function IsHoldingItemInLHand() : bool
  12970. {
  12971. return currentlyEquipedItemL != GetInvalidUniqueId();
  12972. }
  12973.  
  12974. public function GetCurrentlyUsedItemL () : W3UsableItem
  12975. {
  12976. return currentlyUsedItemL;
  12977. }
  12978.  
  12979. public function SetPlayerActionToRestore ( actionToRestoreType : EPlayerActionToRestore )
  12980. {
  12981. playerActionToRestore = actionToRestoreType;
  12982. }
  12983.  
  12984. public function IsCurrentlyUsingItemL () : bool
  12985. {
  12986. return currentlyUsingItem;
  12987. }
  12988.  
  12989. function BlockSlotsOnLItemUse ()
  12990. {
  12991. var slotsToBlock : array<name>;
  12992.  
  12993. slotsToBlock.PushBack( 'Slot1' );
  12994. slotsToBlock.PushBack( 'Slot2' );
  12995. slotsToBlock.PushBack( 'Slot3' );
  12996. slotsToBlock.PushBack( 'Slot4' );
  12997. slotsToBlock.PushBack( 'Slot5' );
  12998. slotsToBlock.PushBack( 'Yrden' );
  12999. slotsToBlock.PushBack( 'Quen' );
  13000. slotsToBlock.PushBack( 'Igni' );
  13001. slotsToBlock.PushBack( 'Axii' );
  13002. slotsToBlock.PushBack( 'Aard' );
  13003.  
  13004.  
  13005. EnableRadialSlotsWithSource ( false, slotsToBlock, 'usableItemL' );
  13006. }
  13007.  
  13008. function UnblockSlotsOnLItemUse ()
  13009. {
  13010. var slotsToBlock : array<name>;
  13011.  
  13012. slotsToBlock.PushBack( 'Slot1' );
  13013. slotsToBlock.PushBack( 'Slot2' );
  13014. slotsToBlock.PushBack( 'Slot3' );
  13015. slotsToBlock.PushBack( 'Slot4' );
  13016. slotsToBlock.PushBack( 'Slot5' );
  13017. slotsToBlock.PushBack( 'Yrden' );
  13018. slotsToBlock.PushBack( 'Quen' );
  13019. slotsToBlock.PushBack( 'Igni' );
  13020. slotsToBlock.PushBack( 'Axii' );
  13021. slotsToBlock.PushBack( 'Aard' );
  13022.  
  13023.  
  13024. EnableRadialSlotsWithSource ( true, slotsToBlock, 'usableItemL' );
  13025. }
  13026.  
  13027. function IsUsableItemLBlocked () : bool
  13028. {
  13029. return isUsableItemBlocked;
  13030. }
  13031. function HideUsableItem( optional force : bool )
  13032. {
  13033. if( currentlyEquipedItemL != GetInvalidUniqueId() )
  13034. {
  13035. if ( force )
  13036. {
  13037. if (!RaiseEvent( 'ItemEndL' ) )
  13038. {
  13039.  
  13040. OnUsingItemsReset();
  13041. }
  13042. return;
  13043.  
  13044. }
  13045. RaiseEvent( 'ItemUseL' );
  13046. }
  13047. }
  13048. function ProcessUsableItemsTransition ( actionToRestore : EPlayerActionToRestore )
  13049. {
  13050. var category : name;
  13051. var signSkill : ESkill;
  13052.  
  13053. category = inv.GetItemCategory ( selectedItemId );
  13054. signSkill = SignEnumToSkillEnum( GetEquippedSign());
  13055.  
  13056. switch ( actionToRestore )
  13057. {
  13058. case PATR_None:
  13059. if ( currentlyUsedItemL )
  13060. {
  13061. inv.UnmountItem( currentlyEquipedItemL, true );
  13062. }
  13063. currentlyEquipedItemL = GetInvalidUniqueId();
  13064. return;
  13065.  
  13066. case PATR_Default:
  13067. if ( IsSlotQuickslot( inv.GetSlotForItemId ( selectedItemId )) && category == 'usable' && currentlyEquipedItemL != selectedItemId )
  13068. {
  13069. if ( currentlyUsedItemL )
  13070. {
  13071. inv.UnmountItem( currentlyEquipedItemL, true );
  13072. }
  13073. currentlyEquipedItemL = GetInvalidUniqueId();
  13074. OnUseSelectedItem();
  13075. return;
  13076. }
  13077. break;
  13078. case PATR_Crossbow:
  13079. if ( inv.IsItemCrossbow ( selectedItemId ) )
  13080. {
  13081. if ( currentlyUsedItemL )
  13082. {
  13083. inv.UnmountItem( currentlyEquipedItemL, true );
  13084. }
  13085. currentlyEquipedItemL = GetInvalidUniqueId();
  13086. SetIsAimingCrossbow( true );
  13087.  
  13088. if ( theInput.IsActionPressed( 'ThrowItem' ) )
  13089. SetupCombatAction( EBAT_ItemUse, BS_Pressed );
  13090. else
  13091. {
  13092. SetupCombatAction( EBAT_ItemUse, BS_Pressed );
  13093. SetupCombatAction( EBAT_ItemUse, BS_Released );
  13094. }
  13095. return;
  13096. }
  13097. break;
  13098. case PATR_CastSign:
  13099. if( signSkill != S_SUndefined && playerActionToRestore == PATR_CastSign )
  13100. {
  13101. if ( currentlyUsedItemL )
  13102. {
  13103. inv.UnmountItem( currentlyEquipedItemL, true );
  13104. }
  13105. currentlyEquipedItemL = GetInvalidUniqueId();
  13106.  
  13107. if( HasStaminaToUseSkill( signSkill, false ) )
  13108. {
  13109. if( GetInvalidUniqueId() != inv.GetItemFromSlot( 'l_weapon' ) )
  13110. PushCombatActionOnBuffer( EBAT_CastSign, BS_Pressed );
  13111. else
  13112. SetupCombatAction( EBAT_CastSign, BS_Pressed );
  13113. }
  13114. else
  13115. {
  13116. thePlayer.SoundEvent("gui_no_stamina");
  13117. }
  13118. return;
  13119. }
  13120. break;
  13121. case PATR_ThrowBomb:
  13122. if ( inv.IsItemBomb ( selectedItemId ) )
  13123. {
  13124. if ( currentlyUsedItemL )
  13125. {
  13126. inv.UnmountItem( currentlyEquipedItemL, true );
  13127. }
  13128. currentlyEquipedItemL = GetInvalidUniqueId();
  13129. PrepareToAttack();
  13130. SetupCombatAction( EBAT_ItemUse, BS_Pressed );
  13131. return;
  13132. }
  13133. break;
  13134. case PATR_CallHorse:
  13135. theGame.OnSpawnPlayerHorse();
  13136. break;
  13137. default:
  13138. if ( currentlyUsedItemL )
  13139. {
  13140. inv.UnmountItem( currentlyEquipedItemL, true );
  13141. }
  13142. currentlyEquipedItemL = GetInvalidUniqueId();
  13143. return;
  13144. }
  13145. if ( currentlyUsedItemL )
  13146. {
  13147. inv.UnmountItem( currentlyEquipedItemL, true );
  13148. }
  13149. currentlyEquipedItemL = GetInvalidUniqueId();
  13150. }
  13151.  
  13152. function GetUsableItemLtransitionAllowed () : bool
  13153. {
  13154. return isUsableItemLtransitionAllowed;
  13155. }
  13156.  
  13157. function SetUsableItemLtransitionAllowed ( isAllowed : bool)
  13158. {
  13159. isUsableItemLtransitionAllowed = isAllowed;
  13160. }
  13161.  
  13162. event OnItemUseLUnBlocked ()
  13163. {
  13164. if ( isUsableItemBlocked )
  13165. {
  13166. isUsableItemBlocked = false;
  13167. UnblockSlotsOnLItemUse ();
  13168. }
  13169. }
  13170.  
  13171. event OnItemUseLBlocked ()
  13172. {
  13173. if ( !isUsableItemBlocked )
  13174. {
  13175. isUsableItemBlocked = true;
  13176. BlockSlotsOnLItemUse ();
  13177. }
  13178. }
  13179.  
  13180. event OnUsingItemsReset()
  13181. {
  13182. if ( currentlyUsingItem )
  13183. {
  13184. OnItemUseLUnBlocked ();
  13185. OnUsingItemsComplete();
  13186. }
  13187. }
  13188. event OnUsingItemsComplete ()
  13189. {
  13190. if ( isUsableItemBlocked )
  13191. {
  13192. OnItemUseLUnBlocked ();
  13193. }
  13194. currentlyUsingItem = false;
  13195. if ( GetUsableItemLtransitionAllowed () )
  13196. {
  13197. ProcessUsableItemsTransition( playerActionToRestore );
  13198. }
  13199. else
  13200. {
  13201. if ( currentlyUsedItemL )
  13202. {
  13203. inv.UnmountItem( currentlyEquipedItemL, true );
  13204. }
  13205. currentlyEquipedItemL = GetInvalidUniqueId();
  13206. }
  13207.  
  13208. SetPlayerActionToRestore ( PATR_Default );
  13209. }
  13210.  
  13211. event OnUseSelectedItem( optional force : bool )
  13212. {
  13213. var category : name;
  13214. var itemEntity : W3UsableItem;
  13215.  
  13216. if ( isUsableItemBlocked && !force )
  13217. {
  13218. return false;
  13219. }
  13220. if ( IsCastingSign() )
  13221. return false;
  13222.  
  13223. if ( currentlyEquipedItemL != GetInvalidUniqueId() )
  13224. {
  13225. SetBehaviorVariable( 'SelectedItemL', (int)GetUsableItemTypeById( currentlyEquipedItemL ) );
  13226. if ( force )
  13227. {
  13228. if ( RaiseEvent( 'ItemEndL' ) )
  13229. {
  13230. SetUsableItemLtransitionAllowed ( true );
  13231. return true;
  13232. }
  13233. }
  13234. else
  13235. {
  13236. if ( RaiseEvent( 'ItemUseL' ) )
  13237. {
  13238. SetUsableItemLtransitionAllowed ( true );
  13239. return true;
  13240. }
  13241. }
  13242. }
  13243. else
  13244. {
  13245. category = inv.GetItemCategory( selectedItemId );
  13246. if( category != 'usable' )
  13247. {
  13248. return false;
  13249. }
  13250. SetBehaviorVariable( 'SelectedItemL', (int)GetUsableItemTypeById( selectedItemId ) );
  13251. if( RaiseEvent( 'ItemUseL' ) )
  13252. {
  13253. currentlyEquipedItemL = selectedItemId;
  13254. SetUsableItemLtransitionAllowed ( false );
  13255. currentlyUsingItem = true;
  13256.  
  13257. return true;
  13258. }
  13259. inv.UnmountItem( selectedItemId, true );
  13260. }
  13261. }
  13262.  
  13263. protected saved var currentlyUsingItem : bool;
  13264.  
  13265. public function ProcessUseSelectedItem( itemEntity : W3UsableItem, optional shouldCallOnUsed : bool )
  13266. {
  13267. currentlyUsedItemL = itemEntity;
  13268. DrainStamina(ESAT_UsableItem);
  13269.  
  13270. if ( shouldCallOnUsed )
  13271. {
  13272. currentlyUsedItemL.OnUsed( thePlayer );
  13273. }
  13274. }
  13275.  
  13276. function GetUsableItemTypeById ( itemId : SItemUniqueId ) : EUsableItemType
  13277. {
  13278. var itemName : name;
  13279.  
  13280. itemName = inv.GetItemName ( itemId );
  13281.  
  13282. return theGame.GetDefinitionsManager().GetUsableItemType ( itemName );
  13283.  
  13284. }
  13285.  
  13286. // Starts the 'WaitForItemSpawnAndProccesTask' task
  13287. public function StartWaitForItemSpawnAndProccesTask()
  13288. {
  13289. AddTimer( 'WaitForItemSpawnAndProccesTask', 0.001f, true,,,,true );
  13290. }
  13291.  
  13292. // Kills the 'WaitForItemSpawnAndProccesTask' task
  13293. public function KillWaitForItemSpawnAndProccesTask()
  13294. {
  13295. RemoveTimer ( 'WaitForItemSpawnAndProccesTask' );
  13296. }
  13297.  
  13298. // Informs the 'WaitForItemSpawnAndProccesTask' task, that selected item should be used ASAP.
  13299. // Flag will be reset by the task itself
  13300. public function AllowUseSelectedItem()
  13301. {
  13302. m_useSelectedItemIfSpawned = true;
  13303. }
  13304.  
  13305. // Task waits for inventory to created selected item. Item will be used ASAP as the task is allowed to do so.
  13306. // Right after that - it kills itself.
  13307. timer function WaitForItemSpawnAndProccesTask( timeDelta : float , id : int )
  13308. {
  13309. var itemEntity : W3UsableItem;
  13310. var canTaskBeKilled : bool;
  13311. canTaskBeKilled = false;
  13312.  
  13313. if ( IsCastingSign() )
  13314. {
  13315. return;
  13316. }
  13317.  
  13318. // selectad item is wrong!
  13319. if ( selectedItemId == GetInvalidUniqueId() )
  13320. {
  13321. canTaskBeKilled = true;
  13322. }
  13323.  
  13324. itemEntity = (W3UsableItem)inv.GetItemEntityUnsafe( selectedItemId );
  13325. if ( itemEntity && m_useSelectedItemIfSpawned )
  13326. {
  13327. // we have selected item and we are allowed to use it, so to it and kill itself.
  13328. canTaskBeKilled = true;
  13329. m_useSelectedItemIfSpawned = false; // reset flag
  13330. ProcessUseSelectedItem( itemEntity, true );
  13331. }
  13332.  
  13333. if ( canTaskBeKilled )
  13334. {
  13335. KillWaitForItemSpawnAndProccesTask();
  13336. }
  13337. }
  13338.  
  13339. event OnBombProjectileReleased()
  13340. {
  13341. ResetRawPlayerHeading();
  13342. UnblockAction(EIAB_ThrowBomb, 'BombThrow');
  13343. UnblockAction(EIAB_Crossbow, 'BombThrow');
  13344.  
  13345. if(GetCurrentStateName() == 'AimThrow')
  13346. PopState();
  13347.  
  13348. FactsAdd("ach_bomb", 1, 4 );
  13349. theGame.GetGamerProfile().CheckLearningTheRopes();
  13350. }
  13351.  
  13352. public function SetIsThrowingItemWithAim(b : bool)
  13353. {
  13354. isThrowingItemWithAim = b;
  13355. }
  13356.  
  13357. public function SetIsThrowingItem( flag : bool ) {isThrowingItem = flag;}
  13358. public function IsThrowingItem() : bool {return isThrowingItem;}
  13359. public function IsThrowingItemWithAim() : bool {return isThrowingItemWithAim;}
  13360. public function SetThrowHold(b : bool) {isThrowHoldPressed = b;}
  13361. public function IsThrowHold() : bool {return isThrowHoldPressed;}
  13362. public function SetIsAimingCrossbow( flag : bool ) {isAimingCrossbow = flag;}
  13363. public function GetIsAimingCrossbow() : bool {return isAimingCrossbow;}
  13364.  
  13365. event OnThrowAnimLeave()
  13366. {
  13367. var throwStage : EThrowStage;
  13368. var thrownEntity : CThrowable;
  13369.  
  13370. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  13371.  
  13372. if(thrownEntity && !thrownEntity.WasThrown())
  13373. {
  13374. throwStage = (int)GetBehaviorVariable( 'throwStage', (int)TS_Stop);
  13375. if(inv.IsItemBomb(selectedItemId))
  13376. {
  13377. BombThrowCleanUp();
  13378. }
  13379. else
  13380. {
  13381. ThrowingAbort();
  13382. }
  13383. }
  13384.  
  13385. thrownEntity = NULL;
  13386. SetIsThrowingItem( false );
  13387. SetIsThrowingItemWithAim( false );
  13388.  
  13389. this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' );
  13390. UnblockAction(EIAB_ThrowBomb, 'BombThrow');
  13391. UnblockAction(EIAB_Crossbow, 'BombThrow');
  13392. }
  13393.  
  13394. //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
  13395. protected function BombThrowStart()
  13396. {
  13397. var slideTargetActor : CActor;
  13398.  
  13399. BlockAction( EIAB_ThrowBomb, 'BombThrow' );
  13400. BlockAction(EIAB_Crossbow, 'BombThrow');
  13401.  
  13402. SetBehaviorVariable( 'throwStage', (int)TS_Start );
  13403. SetBehaviorVariable( 'combatActionType', (int)CAT_ItemThrow );
  13404.  
  13405. if ( slideTarget )
  13406. {
  13407. AddCustomOrientationTarget( OT_Actor, 'BombThrow' );
  13408.  
  13409. slideTargetActor = (CActor)( slideTarget );
  13410.  
  13411. //AK BOMB: moved rotation from anim event to scripts to prevent rotation to friendly and neutral npcs.
  13412. // removed the check after commenting out ProcessCanAttackWhenNotInCombatBomb
  13413. //if( !slideTargetActor || ( slideTargetActor && GetAttitudeBetween(this, slideTarget) == AIA_Hostile ) )
  13414. // SetCustomRotation( 'Throw', VecHeading( slideTarget.GetWorldPosition() - GetWorldPosition() ), 0.0f, 0.3f, false );
  13415. }
  13416. else
  13417. {
  13418. if ( lastAxisInputIsMovement )
  13419. AddCustomOrientationTarget( OT_Actor, 'BombThrow' );
  13420. else
  13421. AddCustomOrientationTarget( OT_Camera, 'BombThrow' );
  13422. }
  13423.  
  13424. UpdateLookAtTarget();
  13425. SetCustomRotation( 'Throw', VecHeading( this.GetLookAtPosition() - GetWorldPosition() ), 0.0f, 0.3f, false );
  13426.  
  13427. SetBehaviorVariable( 'itemType', (int)IT_Petard );
  13428.  
  13429. ProcessCanAttackWhenNotInCombatBomb();
  13430.  
  13431. if ( RaiseForceEvent('CombatAction') )
  13432. OnCombatActionStart();
  13433.  
  13434. //FIXME might be aborted afterwards and no bomb would be thrown actually
  13435. theTelemetry.LogWithLabel(TE_FIGHT_HERO_THROWS_BOMB, inv.GetItemName( selectedItemId ));
  13436. }
  13437.  
  13438. //from animation
  13439. event OnThrowAnimStart()
  13440. {
  13441. var itemId : SItemUniqueId;
  13442. var thrownEntity : CThrowable;
  13443. //Disable slots on radial menu
  13444. this.radialSlots.Clear();
  13445. GetWitcherPlayer().GetItemEquippedOnSlot(EES_Petard1, itemId );
  13446.  
  13447. if( GetSelectedItemId() == itemId )
  13448. {
  13449. this.radialSlots.PushBack( 'Slot2' );
  13450. }
  13451. else
  13452. {
  13453. this.radialSlots.PushBack( 'Slot1' );
  13454. }
  13455. this.radialSlots.PushBack( 'Slot3' );
  13456. this.radialSlots.PushBack( 'Slot4' );
  13457. this.radialSlots.PushBack( 'Slot5' );
  13458. this.EnableRadialSlotsWithSource( false, this.radialSlots, 'throwBomb' );
  13459.  
  13460. thrownEntity = (CThrowable)inv.GetDeploymentItemEntity( selectedItemId,,,true );
  13461. thrownEntity.Initialize( this, selectedItemId );
  13462. EntityHandleSet( thrownEntityHandle, thrownEntity );
  13463. SetIsThrowingItem( true );
  13464. }
  13465.  
  13466. public function BombThrowAbort()
  13467. {
  13468. BombThrowCleanUp();
  13469. UnblockAction( EIAB_ThrowBomb, 'BombThrow' );
  13470. UnblockAction(EIAB_Crossbow, 'BombThrow');
  13471. }
  13472.  
  13473. private function BombThrowCleanUp()
  13474. {
  13475. var throwStage : EThrowStage;
  13476. var thrownEntity : CThrowable;
  13477. var vehicle : CVehicleComponent;
  13478.  
  13479. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  13480.  
  13481. this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' );
  13482. throwStage = (int)GetBehaviorVariable( 'throwStage', (int)TS_Stop);
  13483.  
  13484. SetBehaviorVariable( 'throwStage', (int)TS_Stop );
  13485.  
  13486. if( GetCurrentStateName() == 'AimThrow')
  13487. {
  13488. PopState();
  13489. thrownEntity.StopAiming( true );
  13490. }
  13491. else if ( this.IsUsingHorse() )
  13492. {
  13493. vehicle = (CVehicleComponent)(GetUsedVehicle().GetComponentByClassName('CVehicleComponent'));
  13494. vehicle.GetUserCombatManager().OnForceItemActionAbort();
  13495. }
  13496.  
  13497. //if bomb was not detached yet (is not flying)
  13498. if(thrownEntity && !thrownEntity.WasThrown())
  13499. {
  13500. thrownEntity.BreakAttachment();
  13501. thrownEntity.Destroy();
  13502. }
  13503.  
  13504. thrownEntity = NULL;
  13505. SetIsThrowingItem( false );
  13506. SetIsThrowingItemWithAim( false );
  13507. RemoveCustomOrientationTarget( 'BombThrow' );
  13508. }
  13509.  
  13510. public function ProcessCanAttackWhenNotInCombatBomb()
  13511. {
  13512. /* //AK BOMB: keeping it just in case we need to bring it back
  13513. var impactRange : float;
  13514. var entities : array<CGameplayEntity>;
  13515. var ent : CEntity;
  13516. var actor : CActor;
  13517. var petard : W3Petard;
  13518. var vehicle : CEntity;
  13519. var slotMatrix : Matrix;
  13520. var isShootingFriendly : bool;
  13521.  
  13522.  
  13523. if ( thrownEntity )
  13524. {
  13525. petard = (W3Petard)( thrownEntity );
  13526.  
  13527. if ( !IsThreatened() )
  13528.  
  13529.  
  13530.  
  13531.  
  13532. throwFrom = playerAiming.GetThrowStartPosition();
  13533. throwTo = playerAiming.GetThrowPosition();
  13534. throwVector = throwTo - throwFrom;
  13535. throwVecLen = VecDistance( throwFrom, throwTo );
  13536. throwVectorU = throwVector / throwVecLen;
  13537. if( theGame.GetWorld().StaticTraceWithAdditionalInfo( throwFrom, throwTo + throwVectorU, temp, temp, temp_n, component ) && component && component.GetEntity().HasTag( 'BombThrowSpecificTarget' ) )
  13538. {
  13539. if ( this.playerAiming.GetCurrentStateName() == 'Aiming' )
  13540. ent = playerAiming.GetSweptFriendly();
  13541. else
  13542. actor = (CActor)GetDisplayTarget();
  13543.  
  13544. if( ent || ( actor && actor.IsHuman() && !IsThreat( actor ) ) )
  13545. SetIsShootingFriendly( true );
  13546. else
  13547. SetIsShootingFriendly( false );
  13548. SetIsShootingFriendly( false );
  13549. }
  13550. else
  13551. {
  13552. SetIsShootingFriendly( true );
  13553. }
  13554. }
  13555. else if( FactsQuerySum( "BombThrowDisallowSpecificTargets" ) > 0 )
  13556. {
  13557.  
  13558. throwFrom = playerAiming.GetThrowStartPosition();
  13559. throwTo = playerAiming.GetThrowPosition();
  13560. throwVector = throwTo - throwFrom;
  13561. throwVecLen = VecDistance( throwFrom, throwTo );
  13562. throwVectorU = throwVector / throwVecLen;
  13563. if( theGame.GetWorld().StaticTraceWithAdditionalInfo( throwFrom, throwTo + throwVectorU, temp, temp, temp_n, component ) && component && component.GetEntity().HasTag( 'BombThrowDisallowedTarget' ) )
  13564. {
  13565. SetIsShootingFriendly( true );
  13566. }
  13567. else
  13568. {
  13569. SetIsShootingFriendly( false );
  13570. }
  13571. else
  13572. SetIsShootingFriendly( false );
  13573. }
  13574. else
  13575. {
  13576. SetIsShootingFriendly( false );
  13577. }
  13578. else
  13579. SetIsShootingFriendly( false );
  13580. */
  13581.  
  13582. SetIsShootingFriendly( false );
  13583. SetBehaviorVariable( 'isShootingFriendly', (float)( GetIsShootingFriendly() ) );
  13584. }
  13585.  
  13586. public function SetIsShootingFriendly( flag : bool )
  13587. {
  13588. isShootingFriendly = flag;
  13589. }
  13590.  
  13591. public function GetIsShootingFriendly() : bool
  13592. {
  13593. return isShootingFriendly;
  13594. }
  13595.  
  13596. //only for usable items
  13597. protected function UsableItemStart()
  13598. {
  13599. var thrownEntity : CThrowable;
  13600.  
  13601. //this seems like bullshit but it's because usable items use the same code as throwing bombs and shooting crossbow
  13602. thrownEntity = (CThrowable)inv.GetDeploymentItemEntity( selectedItemId,,,true );
  13603. thrownEntity.Initialize( this, selectedItemId );
  13604. EntityHandleSet( thrownEntityHandle, thrownEntity );
  13605. SetBehaviorVariable( 'throwStage', (int)TS_Start );
  13606. SetIsThrowingItem( true );
  13607. SetBehaviorVariable( 'combatActionType', (int)CAT_ItemThrow );
  13608.  
  13609. if ( slideTarget )
  13610. {
  13611. AddCustomOrientationTarget( OT_Actor, 'UsableItems' );
  13612. }
  13613. else
  13614. {
  13615. if ( lastAxisInputIsMovement )
  13616. AddCustomOrientationTarget( OT_Actor, 'UsableItems' );
  13617. else
  13618. AddCustomOrientationTarget( OT_Camera, 'UsableItems' );
  13619. }
  13620.  
  13621. SetBehaviorVariable( 'itemType', (int)(-1) );
  13622.  
  13623. if ( RaiseForceEvent('CombatAction') )
  13624. OnCombatActionStart();
  13625. }
  13626.  
  13627. protected function BombThrowRelease()
  13628. {
  13629. var stateName : name;
  13630.  
  13631. stateName = playerAiming.GetCurrentStateName();
  13632. OnDelayOrientationChangeOff();
  13633.  
  13634. if ( GetIsShootingFriendly() )
  13635. if( GetIsShootingFriendly() || ( FactsQuerySum( "BombThrowSpecificTargets" ) > 0 && stateName != 'Aiming' ) )
  13636. {
  13637. BombThrowAbort();
  13638. }
  13639. else
  13640. {
  13641. SetBehaviorVariable( 'throwStage', (int)TS_End );
  13642.  
  13643. if ( playerAiming.GetCurrentStateName() == 'Aiming' )
  13644. if ( stateName == 'Aiming' )
  13645. {
  13646. SetCustomRotation( 'Throw', VecHeading( this.GetLookAtPosition() - GetWorldPosition() ), 0.0f, 0.2f, false );
  13647. }
  13648. }
  13649. }
  13650. }
  13651. }
  13652.  
  13653. protected function UsableItemRelease()
  13654. {
  13655. OnDelayOrientationChangeOff();
  13656. SetBehaviorVariable( 'throwStage', (int)TS_End );
  13657. RemoveCustomOrientationTarget( 'UsableItems' );
  13658. }
  13659.  
  13660. // Called when usable item use or crossbow shot was aborted (bombs use different function)
  13661. public function ThrowingAbort()
  13662. {
  13663. var thrownEntity : CThrowable;
  13664.  
  13665. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  13666.  
  13667. SetBehaviorVariable( 'throwStage', (int)TS_Stop );
  13668. RaiseEvent( 'actionStop' );
  13669.  
  13670. if( GetCurrentStateName() == 'AimThrow')
  13671. {
  13672. PopState();
  13673. thrownEntity.StopAiming( true );
  13674. }
  13675.  
  13676. //if bomb was not detached yet (is not flying)
  13677. if(thrownEntity && !thrownEntity.WasThrown())
  13678. {
  13679. thrownEntity.BreakAttachment();
  13680. thrownEntity.Destroy();
  13681. }
  13682. this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' );
  13683. }
  13684.  
  13685. public function CanSetupCombatAction_Throw() : bool
  13686. {
  13687. //if has item selected
  13688. if(!inv.IsIdValid( selectedItemId ))
  13689. return false;
  13690.  
  13691. //if not a throwable item
  13692. if(!inv.IsItemSingletonItem(selectedItemId))
  13693. return false;
  13694.  
  13695. //if input is not blocked
  13696. if(!GetBIsInputAllowed())
  13697. return false;
  13698.  
  13699. //if has ammo
  13700. if(inv.GetItemQuantity(GetSelectedItemId()) <= 0 && !inv.ItemHasTag(selectedItemId, theGame.params.TAG_INFINITE_AMMO))
  13701. return false;
  13702.  
  13703. //if action is not blocked or (HACK) we're in swimming
  13704. if(!inputHandler.IsActionAllowed(EIAB_ThrowBomb) && GetCurrentStateName() != 'Swimming')
  13705. return false;
  13706.  
  13707. return true;
  13708. }
  13709.  
  13710. public function GetThrownEntity() : CThrowable
  13711. {
  13712. return (CThrowable)EntityHandleGet( thrownEntityHandle );
  13713. }
  13714.  
  13715. // Crossbow events and functions
  13716. event OnWeaponWait() { rangedWeapon.OnWeaponWait(); }
  13717. event OnWeaponDrawStart() { rangedWeapon.OnWeaponDrawStart(); }
  13718. event OnWeaponReloadStart() { rangedWeapon.OnWeaponReloadStart(); }
  13719. event OnWeaponReloadEnd() { rangedWeapon.OnWeaponReloadEnd(); }
  13720. event OnWeaponAimStart() { rangedWeapon.OnWeaponAimStart(); }
  13721. event OnWeaponShootStart() { rangedWeapon.OnWeaponShootStart(); }
  13722. event OnWeaponShootEnd() { rangedWeapon.OnWeaponShootEnd(); }
  13723. event OnWeaponAimEnd() { rangedWeapon.OnWeaponAimEnd(); }
  13724. event OnWeaponHolsterStart() { rangedWeapon.OnWeaponHolsterStart(); }
  13725. event OnWeaponHolsterEnd() { rangedWeapon.OnWeaponHolsterEnd(); }
  13726. event OnWeaponToNormalTransStart() { rangedWeapon.OnWeaponToNormalTransStart(); }
  13727. event OnWeaponToNormalTransEnd() { rangedWeapon.OnWeaponToNormalTransEnd(); }
  13728.  
  13729. event OnEnableAimingMode( enable : bool )
  13730. {
  13731. if( !crossbowDontPopStateHack )
  13732. {
  13733. if ( enable )
  13734. PushState( 'AimThrow' );
  13735. else if ( GetCurrentStateName() == 'AimThrow' )
  13736. PopState();
  13737. }
  13738. }
  13739.  
  13740. event OnRangedForceHolster( optional forceUpperBodyAnim, instant, dropItem : bool )
  13741. {
  13742. if(rangedWeapon)
  13743. rangedWeapon.OnForceHolster( forceUpperBodyAnim, instant, dropItem );
  13744. }
  13745.  
  13746.  
  13747. public function IsCrossbowHeld() : bool
  13748. {
  13749. if (rangedWeapon)
  13750. return rangedWeapon.GetCurrentStateName() != 'State_WeaponWait';
  13751. return false;
  13752. }
  13753.  
  13754. // Tickets
  13755. event OnBlockAllCombatTickets( release : bool )
  13756. {
  13757. if (!release )
  13758. ((CR4PlayerStateCombat)GetState('Combat')).OnBlockAllCombatTickets(false);
  13759. }
  13760. event OnForceTicketUpdate() {}
  13761.  
  13762. ////////////////////////////////////////////////////////////////////////////////////////////
  13763. /////////////////////////// @ATTACKS /////////////////////////////////////////////
  13764. ////////////////////////////////////////////////////////////////////////////////////////////
  13765.  
  13766. /*script*/ event OnPocessActionPost(action : W3DamageAction)
  13767.  
  13768.  
  13769.  
  13770. event OnProcessActionPost(action : W3DamageAction)
  13771. {
  13772. var npc : CNewNPC;
  13773. var attackAction : W3Action_Attack;
  13774. var lifeLeech : float;
  13775.  
  13776. super.OnPocessActionPost(action);
  13777.  
  13778. attackAction = (W3Action_Attack)action;
  13779.  
  13780. if(attackAction)
  13781. {
  13782. npc = (CNewNPC)action.victim;
  13783.  
  13784. if(npc && npc.IsHuman() )
  13785. {
  13786. PlayBattleCry('BattleCryHumansHit', 0.05f );
  13787. }
  13788. else
  13789. {
  13790. PlayBattleCry('BattleCryMonstersHit', 0.05f );
  13791. }
  13792.  
  13793. if(attackAction.IsActionMelee())
  13794. {
  13795. //uninterrupted hits counting
  13796. IncreaseUninterruptedHitsCount();
  13797.  
  13798. //camera shake
  13799. if( IsLightAttack( attackAction.GetAttackName() ) )
  13800. {
  13801. GCameraShake(0.1, false, GetWorldPosition(), 10);
  13802. }
  13803.  
  13804. //Caretaker Shovel life steal
  13805. if(npc && inv.GetItemName(attackAction.GetWeaponId()) == 'PC Caretaker Shovel')
  13806. {
  13807. //inv.PlayItemEffect( items[i], 'stab_attack' );
  13808. lifeLeech = CalculateAttributeValue(inv.GetItemAttributeValue(attackAction.GetWeaponId() ,'lifesteal'));
  13809. if (npc.UsesVitality())
  13810. lifeLeech *= action.processedDmg.vitalityDamage;
  13811. else if (UsesEssence())
  13812. lifeLeech *= action.processedDmg.essenceDamage;
  13813. else
  13814. lifeLeech = 0;
  13815.  
  13816. if ( lifeLeech > 0 )
  13817. {
  13818. inv.PlayItemEffect( attackAction.GetWeaponId(), 'stab_attack' );
  13819. PlayEffect('drain_energy_caretaker_shovel');
  13820. GainStat(BCS_Vitality, lifeLeech);
  13821. }
  13822. }
  13823. }
  13824. }
  13825. }
  13826.  
  13827. public function SetHitReactTransScale(f : float) {hitReactTransScale = f;}
  13828. public function GetHitReactTransScale() : float
  13829. {
  13830. if ( ( (CNewNPC)slideTarget ).GetIsTranslationScaled() )
  13831. return hitReactTransScale;
  13832. else
  13833. return 1.f;
  13834. }
  13835.  
  13836. ////////////////////////////////////////////////////////////////////////////////////////////
  13837. /////////////////////////// @HORSE /////////////////////////////////////////////
  13838. ////////////////////////////////////////////////////////////////////////////////////////////
  13839.  
  13840. public function GetHorseWithInventory() : CNewNPC
  13841. {
  13842. return (CNewNPC)EntityHandleGet( horseWithInventory );
  13843. }
  13844. public function GetHorseCurrentlyMounted() : CNewNPC
  13845. {
  13846. return currentlyMountedHorse;
  13847. }
  13848. // Do not use outside of vehicle component
  13849. public function _SetHorseCurrentlyMounted( horse : CNewNPC )
  13850. {
  13851. currentlyMountedHorse = horse;
  13852. }
  13853.  
  13854. public function WasHorseRecentlySummoned() : bool
  13855. {
  13856. if ( horseSummonTimeStamp + 5.f > theGame.GetEngineTimeAsSeconds() )
  13857. return true;
  13858.  
  13859. return false;
  13860. }
  13861.  
  13862. private const var MOUNT_DISTANCE_CBT : float;
  13863. default MOUNT_DISTANCE_CBT = 3.0;
  13864.  
  13865. private const var MOUNT_ANGLE_CBT : float;
  13866. default MOUNT_ANGLE_CBT = 35.0;
  13867.  
  13868. private const var MOUNT_ANGLE_EXP : float;
  13869. default MOUNT_ANGLE_EXP = 45.0;
  13870.  
  13871. public function IsMountingHorseAllowed( optional alwaysAllowedInExploration : bool ) : bool
  13872. {
  13873. var angle : float;
  13874. var distance : float;
  13875.  
  13876. if( IsInsideHorseInteraction() )
  13877. {
  13878. angle = AngleDistance( thePlayer.rawPlayerHeading, VecHeading( thePlayer.horseInteractionSource.GetWorldPosition() - thePlayer.GetWorldPosition() ) );
  13879.  
  13880. if( thePlayer.IsInCombat() )
  13881. {
  13882. if( AbsF( angle ) < MOUNT_ANGLE_CBT )
  13883. {
  13884. distance = VecDistance( thePlayer.GetWorldPosition(), thePlayer.horseInteractionSource.GetWorldPosition() );
  13885.  
  13886. if( distance < MOUNT_DISTANCE_CBT )
  13887. {
  13888. return true;
  13889. }
  13890. else
  13891. {
  13892. return false;
  13893. }
  13894. }
  13895. else
  13896. {
  13897. return false;
  13898. }
  13899.  
  13900. }
  13901. else
  13902. {
  13903. if( alwaysAllowedInExploration )
  13904. {
  13905. return true;
  13906. }
  13907. else
  13908. {
  13909. if( AbsF( angle ) < MOUNT_ANGLE_EXP )
  13910. {
  13911. return true;
  13912. }
  13913. else
  13914. {
  13915. return false;
  13916. }
  13917. }
  13918. }
  13919. }
  13920. else
  13921. {
  13922. return false;
  13923. }
  13924. }
  13925.  
  13926. public function FollowActor( actor : CActor )
  13927. {
  13928. var l_aiTreeDecorator : CAIPlayerActionDecorator;
  13929. var l_aiTree_onFoot : CAIFollowSideBySideAction;
  13930. var l_aiTree_onHorse : CAIRiderFollowSideBySideAction;
  13931. var l_success : bool = false;
  13932.  
  13933. actor.AddTag( 'playerFollowing' );
  13934.  
  13935. if( thePlayer.IsUsingHorse() )
  13936. {
  13937. l_aiTree_onHorse = new CAIRiderFollowSideBySideAction in this;
  13938. l_aiTree_onHorse.OnCreated();
  13939.  
  13940. l_aiTree_onHorse.params.targetTag = 'playerFollowing';
  13941. }
  13942. else
  13943. {
  13944. l_aiTree_onFoot = new CAIFollowSideBySideAction in this;
  13945. l_aiTree_onFoot.OnCreated();
  13946.  
  13947. l_aiTree_onFoot.params.targetTag = 'playerFollowing';
  13948. }
  13949.  
  13950. l_aiTreeDecorator = new CAIPlayerActionDecorator in this;
  13951. l_aiTreeDecorator.OnCreated();
  13952. l_aiTreeDecorator.interruptOnInput = false;
  13953.  
  13954. if( thePlayer.IsUsingHorse() )
  13955. l_aiTreeDecorator.scriptedAction = l_aiTree_onHorse;
  13956. else
  13957. l_aiTreeDecorator.scriptedAction = l_aiTree_onFoot;
  13958.  
  13959. if( l_aiTreeDecorator )
  13960. l_success = ForceAIBehavior( l_aiTreeDecorator, BTAP_Emergency );
  13961. else if( thePlayer.IsUsingHorse() )
  13962. l_success = ForceAIBehavior( l_aiTree_onHorse, BTAP_Emergency );
  13963. else
  13964. l_success = ForceAIBehavior( l_aiTree_onFoot, BTAP_Emergency );
  13965.  
  13966. if ( l_success )
  13967. {
  13968. GetMovingAgentComponent().SetGameplayRelativeMoveSpeed( 0.0f );
  13969. }
  13970. }
  13971.  
  13972. public function SetCanFollowNpc( val : bool, actor : CActor ) { canFollowNpc = val; actorToFollow = actor; }
  13973. public function CanFollowNpc() : bool { return canFollowNpc; }
  13974. public function GetActorToFollow() : CActor { return actorToFollow; }
  13975.  
  13976. /*public function SetIsFollowing( val : bool )
  13977. {
  13978. isFollowing = val;
  13979.  
  13980. if( val )
  13981. followingStartTime = theGame.GetEngineTimeAsSeconds();
  13982. else
  13983. followingStartTime = 0.0;
  13984. }
  13985. public function GetFollowingStartTime() : float { return followingStartTime; }
  13986. public function IsFollowing() : bool { return isFollowing; }
  13987.  
  13988. timer function ResetIsFollowing( td : float, id : int )
  13989. {
  13990. isFollowing = false;
  13991. }*/
  13992.  
  13993. ////////////////////////////////////////////////////////////////////////////////////////////
  13994. ///////////////////// @SWIMMING ////////////////////////////////////////////////////////
  13995. ////////////////////////////////////////////////////////////////////////////////////////////
  13996.  
  13997. public function SetIsSwimming ( toggle : bool )
  13998. {
  13999. if( isSwimming != toggle )
  14000. {
  14001. thePlayer.substateManager.SetBehaviorParamBool( 'isSwimmingForOverlay', toggle );
  14002. isSwimming = toggle;
  14003. }
  14004. }
  14005. //public function IsSwimming () : bool { return isSwimming; }
  14006.  
  14007. ////////////////////////////////////////////////////////////////////////////////////////////
  14008. /////////////////////////// @DURABILITY //////////////////////////////////////////////////
  14009. ////////////////////////////////////////////////////////////////////////////////////////////
  14010.  
  14011. //returns true if repaired
  14012.  
  14013.  
  14014.  
  14015.  
  14016.  
  14017. public function RepairItemUsingConsumable(item, consumable : SItemUniqueId) : bool
  14018. {
  14019. inv.SetItemDurabilityScript(item, inv.GetItemMaxDurability(item));
  14020. var curr, max, repairValue, itemValue, repairBonus, newDurability : float;
  14021.  
  14022. //basic check
  14023. if(!inv.IsIdValid(item) || !inv.IsIdValid(consumable) || !inv.HasItemDurability(item))
  14024. return false;
  14025.  
  14026. curr = inv.GetItemDurability(item);
  14027. max = inv.GetItemMaxDurability(item);
  14028.  
  14029. //check durability level
  14030. if(curr > max)
  14031. return false;
  14032.  
  14033. //check consumable type
  14034. if( (inv.IsItemAnyArmor(item) && inv.ItemHasTag(consumable, theGame.params.TAG_REPAIR_CONSUMABLE_ARMOR)) ||
  14035. (inv.IsItemSilverSwordUsableByPlayer(item) && inv.ItemHasTag(consumable, theGame.params.TAG_REPAIR_CONSUMABLE_SILVER)) ||
  14036. (inv.IsItemSteelSwordUsableByPlayer(item) && inv.ItemHasTag(consumable, theGame.params.TAG_REPAIR_CONSUMABLE_STEEL)) )
  14037. {
  14038. //item stats
  14039. itemValue = CalculateAttributeValue(inv.GetItemAttributeValue(consumable, 'durabilityRepairValue'));
  14040. if(itemValue <= 0)
  14041. {
  14042. LogAssert(false, "CR4Player.RepairItemUsingConsumable: consumable <<" + inv.GetItemName(consumable) + ">> has <=0 durabilityRepairValue!!!");
  14043. return false;
  14044. }
  14045. repairBonus = CalculateAttributeValue(inv.GetItemAttributeValue(consumable, 'durabilityBonusValue'));
  14046.  
  14047. //calculate
  14048. repairValue = max * itemValue /100;
  14049.  
  14050. /* disabled repairing over 100%
  14051. if(HasBookPerk(S_Book_28))
  14052. max = max * (1 + (repairBonus + perkValue) /100);
  14053. */
  14054.  
  14055. newDurability = MinF(max, curr + repairValue);
  14056.  
  14057. inv.SetItemDurabilityScript(item, newDurability);
  14058.  
  14059. //consume
  14060. return true;
  14061. }
  14062. inv.RemoveItem(consumable);
  14063.  
  14064. return true;
  14065. }
  14066. return false;
  14067. }
  14068.  
  14069. ////////////////////////////////////////////////////////////////////////////////////////////
  14070. /////////////////////////// @PushingObject /////////////////////////////////////////////
  14071. ///////////////////////////////////////////////////////////////////////////////////////////
  14072. /*
  14073. event OnRigidBodyCollision( component : CComponent, actorIndex : int, shapeIndex : int )
  14074. {
  14075. pushableComponent = component;
  14076. if ( pushableComponent )
  14077. this.RaiseEvent('PushObject');
  14078.  
  14079. //component.ApplyForceAtPointToPhysicalObject
  14080. }
  14081.  
  14082. event OnRigidBodyExit( component : CComponent )
  14083. {
  14084. this.RaiseEvent('PushObjectEnd');
  14085. pushableComponent = NULL;
  14086. }
  14087.  
  14088. event OnPushObjectStart()
  14089. {
  14090. moveAdj = GetMovingAgentComponent().GetMovementAdjustor();
  14091. moveAdj.CancelAll();
  14092. pushRotTicket = moveAdj.CreateNewRequest( 'RotateToObject' );
  14093. moveAdj.MaxRotationAdjustmentSpeed(pushRotTicket,30);
  14094. moveAdj.Continuous(pushRotTicket);
  14095. moveAdj.DontEnd(pushRotTicket);
  14096. this.AddTimer('PushObjectUpdate',0.01,true, , , true);
  14097.  
  14098. }
  14099.  
  14100. event OnPushObjectStop()
  14101. {
  14102. this.RemoveTimer('PushObjectUpdate');
  14103. moveAdj.CancelByName('RotateToObject');
  14104. moveAdj = NULL;
  14105. }
  14106.  
  14107. timer function PushObjectUpdate( dt : float , id : int)
  14108. {
  14109. var impulse : Vector;
  14110. moveAdj.RotateTo( pushRotTicket, rawPlayerHeading );
  14111. impulse = this.GetHeadingVector()*10.0;
  14112. //impulse.Z += 0.5;
  14113. //pushableComponent.ApplyLocalImpulseToPhysicalObject(impulse);
  14114. }
  14115. */
  14116.  
  14117. ///////////////////////////////////////////////////////////////////////////////////////////
  14118. /////////////////////////// @DAY @NIGHT CYCLE CHECK /////////////////////////////////////
  14119. ///////////////////////////////////////////////////////////////////////////////////////////
  14120.  
  14121. private function CheckDayNightCycle()
  14122. {
  14123. var time : GameTime;
  14124. var isNight : bool;
  14125.  
  14126. //if changed
  14127. isNight = theGame.envMgr.IsNight();
  14128. if(prevDayNightIsNight != isNight)
  14129. {
  14130. if(isNight)
  14131. OnNightStarted();
  14132. else
  14133. OnDayStarted();
  14134.  
  14135. prevDayNightIsNight = isNight;
  14136. }
  14137.  
  14138. //schedule next call
  14139. if(isNight)
  14140. time = theGame.envMgr.GetGameTimeTillNextDay();
  14141. else
  14142. time = theGame.envMgr.GetGameTimeTillNextNight();
  14143.  
  14144. AddGameTimeTimer('DayNightCycle', time);
  14145. }
  14146.  
  14147. timer function DayNightCycle(dt : GameTime, id : int)
  14148. {
  14149. CheckDayNightCycle();
  14150. }
  14151.  
  14152. /*script*/ event OnNightStarted()
  14153. {
  14154. var pam : W3PlayerAbilityManager;
  14155.  
  14156. if(CanUseSkill(S_Perk_01))
  14157. {
  14158. pam = (W3PlayerAbilityManager)abilityManager;
  14159. pam.SetPerk01Abilities(false, true);
  14160. }
  14161. }
  14162.  
  14163. /*script*/ event OnDayStarted()
  14164. {
  14165. var pam : W3PlayerAbilityManager;
  14166.  
  14167. if(CanUseSkill(S_Perk_01))
  14168. {
  14169. pam = (W3PlayerAbilityManager)abilityManager;
  14170. pam.SetPerk01Abilities(true, false);
  14171. }
  14172. }
  14173.  
  14174. ///////////////////////////////////////////////////////////////////////////////////////////
  14175. /////////////////////////// @INPUT //////////////////////////////////////////////////////
  14176. ///////////////////////////////////////////////////////////////////////////////////////////
  14177.  
  14178. public function ForceUnlockAllInputActions(alsoQuestLocks : bool)
  14179. {
  14180. if ( inputHandler )
  14181. inputHandler.ForceUnlockAllInputActions(alsoQuestLocks);
  14182. }
  14183.  
  14184. public function SetPrevRawLeftJoyRot()
  14185. {
  14186. prevRawLeftJoyRot = rawLeftJoyRot;
  14187. }
  14188.  
  14189. public function GetPrevRawLeftJoyRot() : float
  14190. {
  14191. return prevRawLeftJoyRot;
  14192. }
  14193.  
  14194. public function GetExplorationInputContext() : name
  14195. {
  14196. return explorationInputContext;
  14197. }
  14198.  
  14199. public function GetCombatInputContext() : name
  14200. {
  14201. return combatInputContext;
  14202. }
  14203.  
  14204. ///////////////////////////////////////////////////////////////////////////////////////////
  14205. /////////////////////////// @EXPLORATION ////////////////////////////////////////////////
  14206. ///////////////////////////////////////////////////////////////////////////////////////////
  14207.  
  14208. public function SetIsOnBoat(b : bool)
  14209. {
  14210. isOnBoat = b;
  14211. }
  14212.  
  14213. public function IsOnBoat() : bool
  14214. {
  14215. return isOnBoat;
  14216. }
  14217.  
  14218. public function IsInShallowWater() : bool
  14219. {
  14220. return isInShallowWater;
  14221. }
  14222.  
  14223. event OnEnterShallowWater()
  14224. {
  14225. if ( isInShallowWater )
  14226. return false;
  14227.  
  14228. isInShallowWater = true;
  14229. BlockAction( EIAB_Dodge,'ShallowWater', false, false, true );
  14230. BlockAction( EIAB_Sprint,'ShallowWater', false, false, true );
  14231. BlockAction( EIAB_Crossbow,'ShallowWater', false, false, true );
  14232.  
  14233. //--===modJumpInShallowWater Begin===--
  14234. //BlockAction( EIAB_Jump,'ShallowWater', false, false, true );
  14235. //--===modJumpInShallowWater End===--
  14236. SetBehaviorVariable( 'shallowWater',1.0);
  14237. }
  14238. event OnExitShallowWater()
  14239. {
  14240. if ( !isInShallowWater )
  14241. return false;
  14242.  
  14243. isInShallowWater = false;
  14244. BlockAllActions('ShallowWater',false);
  14245. SetBehaviorVariable( 'shallowWater',0.0);
  14246. }
  14247.  
  14248. public function TestIsInSettlement() : bool
  14249. {
  14250. return IsInSettlement();
  14251. }
  14252.  
  14253. ///////////////////////////////////////////////////////////////////////////////////////////
  14254. /////////////////////////// GLOSSARY ////////////////////////////////////////////////
  14255. ///////////////////////////////////////////////////////////////////////////////////////////
  14256.  
  14257. //Processes glossary image filename and exchanges it with override if provided
  14258.  
  14259.  
  14260.  
  14261.  
  14262.  
  14263. public function ProcessGlossaryImageOverride( defaultImage : string, uniqueTag : name ) : string
  14264. {
  14265. var size : int;
  14266. var i : int;
  14267.  
  14268. size = glossaryImageOverride.Size();
  14269.  
  14270. if( size == 0 )
  14271. return defaultImage;
  14272.  
  14273. for( i = 0; i < size; i += 1 )
  14274. {
  14275. if( glossaryImageOverride[i].uniqueTag == uniqueTag )
  14276. return glossaryImageOverride[i].imageFileName;
  14277.  
  14278. }
  14279.  
  14280. return defaultImage;
  14281. }
  14282.  
  14283. //Adds glossary image override filename to array
  14284. public function EnableGlossaryImageOverride( uniqueTag : name, imageFileName : string, enable : bool )
  14285. {
  14286. var imageData : SGlossaryImageOverride;
  14287. var size : int;
  14288. var i : int;
  14289.  
  14290. for( i = 0; i < glossaryImageOverride.Size(); i += 1 )
  14291. {
  14292. if( glossaryImageOverride[i].uniqueTag == uniqueTag )
  14293. {
  14294. glossaryImageOverride.Remove(glossaryImageOverride[i]);
  14295. }
  14296. }
  14297.  
  14298. if( enable )
  14299. {
  14300. if( IsNameValid(uniqueTag) && imageFileName != "" )
  14301. {
  14302. glossaryImageOverride.PushBack( SGlossaryImageOverride( uniqueTag, imageFileName ) );
  14303. }
  14304. }
  14305. }
  14306. ///////////////////////////////////////////////////////////////////////////////////////////
  14307. /////////////////////////// MONSTER HUNT INVESTIGATION AREAS /////////////////////////////
  14308. ///////////////////////////////////////////////////////////////////////////////////////////
  14309.  
  14310.  
  14311.  
  14312. public function SetWeatherDisplayDisabled( disable : bool )
  14313. {
  14314. disableWeatherDisplay = disable;
  14315. }
  14316.  
  14317. public function GetWeatherDisplayDisabled() : bool
  14318. {
  14319. return disableWeatherDisplay;
  14320. }
  14321.  
  14322.  
  14323.  
  14324.  
  14325.  
  14326. public function SetCurrentMonsterHuntInvestigationArea ( area : W3MonsterHuntInvestigationArea )
  14327. {
  14328. currentMonsterHuntInvestigationArea = area;
  14329. }
  14330.  
  14331.  
  14332. ///////////////////////////////////////////////////////////////////////////////////////////
  14333. /////////////////////////// BARBER SYSTEM CUSTOM HEAD /////////////////////////////
  14334. ///////////////////////////////////////////////////////////////////////////////////////////
  14335.  
  14336. public function RememberCustomHead( headName : name )
  14337. {
  14338. rememberedCustomHead = headName;
  14339. }
  14340.  
  14341. public function GetRememberedCustomHead() : name
  14342. {
  14343. return rememberedCustomHead;
  14344. }
  14345.  
  14346. public function ClearRememberedCustomHead()
  14347. {
  14348. rememberedCustomHead = '';
  14349. }
  14350.  
  14351. ///////////////////////////////////////////////////////////////////////////////////////////
  14352. /////////////////////////// @TUTORIAL ////////////////////////////////////////////////
  14353. ///////////////////////////////////////////////////////////////////////////////////////////
  14354.  
  14355. public function CreateTutorialInput()
  14356. {
  14357. var prevInputHandler : CPlayerInput;
  14358.  
  14359. prevInputHandler = inputHandler;
  14360. inputHandler = new W3PlayerTutorialInput in this;
  14361. inputHandler.Initialize(false, prevInputHandler);
  14362.  
  14363. if(prevInputHandler)
  14364. delete prevInputHandler;
  14365. }
  14366.  
  14367. public function CreateInput()
  14368. {
  14369. var oldInputHandler : CPlayerInput;
  14370.  
  14371. oldInputHandler = inputHandler;
  14372. inputHandler = new CPlayerInput in this;
  14373. inputHandler.Initialize(false, oldInputHandler);
  14374. }
  14375.  
  14376. timer function TutorialSilverCombat(dt : float, id : int)
  14377. {
  14378. var i : int;
  14379. var actors : array<CActor>;
  14380.  
  14381. if(IsInCombat())
  14382. {
  14383. actors = GetNPCsAndPlayersInRange(20, 1000000, ,FLAG_ExcludePlayer + FLAG_OnlyAliveActors);
  14384. for(i=0; i<actors.Size(); i+=1)
  14385. {
  14386. if(actors[i] && IsRequiredAttitudeBetween(this, actors[i], true) && actors[i].UsesEssence())
  14387. {
  14388. FactsAdd("TutorialShowSilver");
  14389.  
  14390. RemoveTimer('TutorialSilverCombat');
  14391. break;
  14392. }
  14393. }
  14394. }
  14395. }
  14396.  
  14397. private saved var m_bossTag : name;
  14398.  
  14399. public function GetBossTag() : name
  14400. {
  14401. return m_bossTag;
  14402. }
  14403.  
  14404. public function SetBossTag( bossTag : name )
  14405. {
  14406. m_bossTag = bossTag;
  14407. }
  14408.  
  14409. private saved var m_usingCoatOfArms : bool; default m_usingCoatOfArms = false;
  14410.  
  14411. public function IsUsingCoatOfArms() : bool
  14412. {
  14413. return m_usingCoatOfArms;
  14414. }
  14415.  
  14416. public function SetUsingCoatOfArms( using : bool)
  14417. {
  14418. m_usingCoatOfArms = using;
  14419. }
  14420.  
  14421. private saved var m_initialTimeOut : float;
  14422. private saved var m_currentTimeOut : float;
  14423.  
  14424. public function GetInitialTimeOut() : float
  14425. {
  14426. return m_initialTimeOut;
  14427. }
  14428.  
  14429. public function SetInitialTimeOut( timeOut : float )
  14430. {
  14431. m_initialTimeOut = timeOut;
  14432. }
  14433.  
  14434. public function GetCurrentTimeOut() : float
  14435. {
  14436. return m_currentTimeOut;
  14437. }
  14438.  
  14439. public function SetCurrentTimeOut( timeOut : float )
  14440. {
  14441. m_currentTimeOut = timeOut;
  14442. }
  14443.  
  14444.  
  14445. ///////////////////////////////////////////////////////////////////////////////////////////
  14446. /////////////////////////// @FINISHERS ////////////////////////////////////////////
  14447. ///////////////////////////////////////////////////////////////////////////////////////////
  14448.  
  14449. timer function DelayedFinisherInputTimer(dt : float, id : int)
  14450. {
  14451. //theGame.SetTimeScale( 0.1, theGame.GetTimescaleSource(ETS_FinisherInput), theGame.GetTimescalePriority(ETS_FinisherInput) );
  14452. //GetFinisherVictim().EnableFinishComponent( true );
  14453. }
  14454.  
  14455. timer function RemoveFinisherCameraAnimationCheck(dt : float, id : int)
  14456. {
  14457. if ( !isInFinisher && !bLAxisReleased )
  14458. {
  14459. theGame.GetSyncAnimManager().OnRemoveFinisherCameraAnimation();
  14460. RemoveTimer( 'RemoveFinisherCameraAnimationCheck' );
  14461. }
  14462. }
  14463.  
  14464. ///////////////////////////////////////////////////////////////////////////////////////////
  14465. /////////////////////////// @DEBUG @TIMERS ////////////////////////////////////////////
  14466. ///////////////////////////////////////////////////////////////////////////////////////////
  14467.  
  14468. timer function GameplayFactRemove(dt : float, timerId : int)
  14469. {
  14470. theGame.GameplayFactRemoveFromTimer(timerId);
  14471. }
  14472.  
  14473. //gives NORMAL starting inventory
  14474. timer function GiveStartingItems(dt : float, timerId : int)
  14475. {
  14476. var template : CEntityTemplate;
  14477. var invEntity : CInventoryComponent;
  14478. var entity : CEntity;
  14479. var items : array<SItemUniqueId>;
  14480. var id : SItemUniqueId;
  14481. var i : int;
  14482.  
  14483. //wait for inventory to init
  14484. if(inv)
  14485. {
  14486. inv.GetAllItems(items);
  14487. if(items.Size() <= 0)
  14488. {
  14489. return;
  14490. }
  14491. }
  14492. else
  14493. {
  14494. return;
  14495. }
  14496.  
  14497. //add items
  14498. template = (CEntityTemplate)LoadResource("geralt_inventory_release");
  14499. entity = theGame.CreateEntity(template, Vector(0,0,0));
  14500. invEntity = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent');
  14501.  
  14502. invEntity.GetAllItems(items);
  14503. for(i=0; i<items.Size(); i+=1)
  14504. {
  14505. id = invEntity.GiveItemTo(inv, items[i], 0, false, true);
  14506. if ( inv.ItemHasTag(id,'Scabbard') )
  14507. {
  14508. inv.MountItem(id);
  14509. }
  14510. else if(!inv.IsItemFists(id) && inv.GetItemName(id) != 'Cat 1') //hack for cat potion - don't equip!
  14511. {
  14512. EquipItem(id);
  14513. }
  14514. else if(inv.IsItemSingletonItem(id))
  14515. {
  14516. inv.SingletonItemSetAmmo(id, inv.SingletonItemGetMaxAmmo(id));
  14517. }
  14518. }
  14519.  
  14520. entity.Destroy();
  14521.  
  14522. //remove timer
  14523. RemoveTimer('GiveStartingItems');
  14524. }
  14525.  
  14526. //Adds items used for testing. Won't be called in final release. Items are added from geralt_inventory entity.
  14527. //Works as a timer since we need to wait for inventory to init and there is no such event.
  14528. timer function Debug_GiveTestingItems(dt : float, optional id : int)
  14529. {
  14530. var template : CEntityTemplate;
  14531. var invTesting : CInventoryComponent;
  14532. var entity : CEntity;
  14533. var items : array<SItemUniqueId>;
  14534. var i : int;
  14535. var slot : EEquipmentSlots;
  14536.  
  14537. //wait for inventory to init
  14538. if(inv)
  14539. {
  14540. inv.GetAllItems(items);
  14541. if(items.Size() <= 0)
  14542. {
  14543. return;
  14544. }
  14545. }
  14546. else
  14547. {
  14548. return;
  14549. }
  14550.  
  14551. template = (CEntityTemplate)LoadResource("geralt_inventory_internal");
  14552. entity = theGame.CreateEntity(template, Vector(0,0,0));
  14553. invTesting = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent');
  14554. invTesting.GiveAllItemsTo(inv, true);
  14555. entity.Destroy();
  14556.  
  14557. //once called remove the timer
  14558. RemoveTimer('Debug_GiveTestingItems');
  14559.  
  14560. //equip crossbow, bombs and bolts, select bolts
  14561. inv.GetAllItems(items);
  14562.  
  14563. for(i=0; i<items.Size(); i+=1)
  14564. {
  14565. if( inv.IsItemCrossbow(items[i]) || inv.IsItemBomb(items[i]) )
  14566. {
  14567. slot = inv.GetSlotForItemId(items[i]);
  14568. EquipItem(items[i], slot);
  14569.  
  14570. if( (W3PlayerWitcher)this && inv.IsItemCrossbow(items[i]) )
  14571. GetWitcherPlayer().SelectQuickslotItem(slot);
  14572. }
  14573. else if(inv.IsItemBolt(items[i]))
  14574. {
  14575. slot = inv.GetSlotForItemId(items[i]);
  14576. EquipItem(items[i], slot);
  14577. }
  14578.  
  14579. if(inv.IsItemSingletonItem(items[i]))
  14580. {
  14581. inv.SingletonItemSetAmmo(items[i], inv.SingletonItemGetMaxAmmo(items[i]));
  14582. }
  14583. }
  14584. }
  14585.  
  14586. //called in tutorial in not final version to remove testing items
  14587. timer function Debug_RemoveTestingItems(dt : float, id : int)
  14588. {
  14589. var template : CEntityTemplate;
  14590. var entity : CEntity;
  14591. var invTesting : CInventoryComponent;
  14592. var ids : array<SItemUniqueId>;
  14593. var i : int;
  14594.  
  14595. template = (CEntityTemplate)LoadResource("geralt_inventory_internal");
  14596. entity = theGame.CreateEntity(template, Vector(0,0,0));
  14597. invTesting = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent');
  14598. invTesting.GetAllItems(ids);
  14599.  
  14600. for(i=0; i<ids.Size(); i+=1)
  14601. inv.RemoveItemByName(invTesting.GetItemName(ids[i]), invTesting.GetItemQuantity(ids[i]));
  14602.  
  14603. entity.Destroy();
  14604. RemoveTimer('Debug_RemoveTestingItems');
  14605. }
  14606.  
  14607. timer function Debug_DelayedConsoleCommand(dt : float, id : int)
  14608. {
  14609. //inv.AddAnItem('Recipe for Mutagen 23');
  14610. inv.AddAnItem('Boots 2 schematic');
  14611. }
  14612.  
  14613. function DBG_SkillSlots()
  14614. {
  14615. ((W3PlayerAbilityManager)abilityManager).DBG_SkillSlots();
  14616. }
  14617.  
  14618. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14619. //////////////////////////////// @BACKLIGHT COLOR ////////////////////////////////////////////////////////////////////
  14620. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14621.  
  14622. public final function SetPadBacklightColor(r, g, b : int)
  14623. {
  14624. var padBacklightColor : Vector;
  14625.  
  14626. padBacklightColor.X = r / 255;
  14627. padBacklightColor.Y = g / 255;
  14628. padBacklightColor.Z = b / 255;
  14629.  
  14630. SetBacklightColor(padBacklightColor);
  14631. }
  14632.  
  14633. public final function SetPadBacklightColorFromSign(signType : ESignType)
  14634. {
  14635. LogPS4Light("SetPadBacklightColorFromSign... " + signType);
  14636.  
  14637. switch(signType)
  14638. {
  14639. case ST_Yrden: SetPadBacklightColor( 200 , 81 , 255 ); break; // Violet
  14640. case ST_Quen: SetPadBacklightColor( 255 , 205 , 68 ); break; // Yellow
  14641. case ST_Igni: SetPadBacklightColor( 255 , 79 , 10 ); break; // Orange
  14642. case ST_Axii: SetPadBacklightColor( 255 , 255 , 255 ); break; // White
  14643. case ST_Aard: SetPadBacklightColor( 158 , 214 , 255 ); break; // Blue
  14644. }
  14645. }
  14646.  
  14647. timer function ResetPadBacklightColorTimer(dt : float, id : int)
  14648. {
  14649. ResetPadBacklightColor();
  14650. }
  14651.  
  14652. public final function ResetPadBacklightColor(optional skipHeldWeapon : bool)
  14653. {
  14654. var weapons : array<SItemUniqueId>;
  14655. var sword : CWitcherSword;
  14656. var healthPercentage : float;
  14657. var tmpBacklight : Vector;
  14658.  
  14659. if(!skipHeldWeapon)
  14660. {
  14661. weapons = inv.GetHeldWeapons();
  14662.  
  14663. //if holding a sword the default backlight color matches the one set in sword entity
  14664. if(weapons.Size() > 0)
  14665. {
  14666. sword = (CWitcherSword)inv.GetItemEntityUnsafe(weapons[0]);
  14667. if(sword)
  14668. {
  14669. tmpBacklight.X = sword.padBacklightColor.X / 255.0f;
  14670. tmpBacklight.Y = sword.padBacklightColor.Y / 255.0f;
  14671. tmpBacklight.Z = sword.padBacklightColor.Z / 255.0f;
  14672. tmpBacklight.W = 1.0f;
  14673. SetBacklightColor( tmpBacklight );
  14674. LogPS4Light("Setting light from sword template: " + NoTrailZeros(sword.padBacklightColor.X) + ", " + NoTrailZeros(sword.padBacklightColor.Y) + ", " + NoTrailZeros(sword.padBacklightColor.Z) );
  14675. return;
  14676. }
  14677. }
  14678. }
  14679.  
  14680. healthPercentage = GetStatPercents( BCS_Vitality );
  14681. SetBacklightFromHealth( healthPercentage );
  14682. LogPS4Light("Setting light from health, " + NoTrailZeros(RoundMath(healthPercentage*100)) + "%");
  14683. }
  14684.  
  14685. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14686.  
  14687. event OnOpenningDoor()
  14688. {
  14689. if( !thePlayer.IsUsingHorse() )
  14690. RaiseEvent('OpenDoor');
  14691. }
  14692.  
  14693. public final function SetLoopingCameraShakeAnimName( n : name )
  14694. {
  14695. loopingCameraShakeAnimName = n;
  14696. }
  14697.  
  14698. public var loopingCameraShakeAnimName : name;
  14699. timer function RemoveQuestCameraShakeTimer( dt : float , id : int)
  14700. {
  14701. RemoveQuestCameraShake( loopingCameraShakeAnimName );
  14702. }
  14703.  
  14704. public function RemoveQuestCameraShake( animName : name )
  14705. {
  14706. var camera : CCustomCamera = theGame.GetGameCamera();
  14707. var animation : SCameraAnimationDefinition;
  14708.  
  14709. camera.StopAnimation( animName );
  14710. }
  14711.  
  14712. public function GetCameraPadding() : float
  14713. {
  14714. if( theGame.IsFocusModeActive() )
  14715. {
  14716. return 0.25; // Tweaked for [108933] Geralt is being clipped when using focus mode while running towards camera.
  14717. }
  14718. else
  14719. {
  14720. return 0.02f; // Tweaked for [114907] Player dissolving while aiming crossbow.
  14721. }
  14722. }
  14723.  
  14724. public function IsPerformingPhaseChangeAnimation() : bool { return isPerformingPhaseChangeAnimation; }
  14725. public function SetIsPerformingPhaseChangeAnimation( val : bool ) { isPerformingPhaseChangeAnimation = val; }
  14726.  
  14727. private function DealCounterDamageToOlgierd()
  14728. {
  14729. var damage : W3DamageAction;
  14730.  
  14731. damage = new W3DamageAction in this;
  14732.  
  14733. damage.Initialize( thePlayer.GetTarget(), thePlayer.GetTarget(), NULL, this, EHRT_None, CPS_Undefined, false, false, false, true );
  14734. damage.AddDamage( theGame.params.DAMAGE_NAME_DIRECT, thePlayer.GetTarget().GetStatMax( BCS_Vitality ) * 3 / 100 );
  14735. theGame.damageMgr.ProcessAction( damage );
  14736.  
  14737. delete damage;
  14738. }
  14739.  
  14740. timer function PlayDelayedCounterDamageEffect( dt : float, id : int )
  14741. {
  14742. thePlayer.GetTarget().PlayEffect( 'olgierd_energy_blast' );
  14743. }
  14744.  
  14745. // TEST
  14746. public function SetTestAdjustRequestedMovementDirection( val : bool )
  14747. {
  14748. testAdjustRequestedMovementDirection = val;
  14749. }
  14750.  
  14751. event OnVisualDebug( frame : CScriptedRenderFrame, flag : EShowFlags )
  14752. {
  14753. var boneFollow : int;
  14754. var bonePosition : Vector;
  14755. var yrdenEntity : W3YrdenEntity;
  14756.  
  14757. substateManager.OnVisualDebug( frame, flag );
  14758.  
  14759. boneFollow = thePlayer.GetBoneIndex( 'Reference' );
  14760. bonePosition = MatrixGetTranslation( thePlayer.GetBoneWorldMatrixByIndex( boneFollow ) );
  14761. frame.DrawText( "R", bonePosition, Color( 50, 200, 70 ) );
  14762. //frame.DrawText( "R", bonePositionCam, Color( 200, 50, 70 ) );
  14763.  
  14764. boneFollow = thePlayer.GetBoneIndex( 'Trajectory' );
  14765. bonePosition = MatrixGetTranslation( thePlayer.GetBoneWorldMatrixByIndex( boneFollow ) );
  14766. frame.DrawSphere( bonePosition, 0.1f, Color( 200, 50, 70 ) );
  14767. frame.DrawText( "T", bonePosition, Color( 200, 50, 70 ) );
  14768.  
  14769. //frame.DrawSphere( lastSafePosition, 1.0f, Color( 50, 200, 70 ) );
  14770. //frame.DrawText( "SavePos", lastSafePosition, Color( 50, 200, 70 ) );
  14771.  
  14772. yrdenEntity = (W3YrdenEntity)GetWitcherPlayer().GetSignEntity(ST_Yrden);
  14773. yrdenEntity.OnVisualDebug(frame, flag, false);
  14774.  
  14775. return true;
  14776. }
  14777.  
  14778. timer function PotDrinkTimer(dt : float, id : int)
  14779. {
  14780. inputHandler.PotDrinkTimer(false);
  14781. }
  14782.  
  14783. public function SetIsHorseRacing( val : bool )
  14784. {
  14785. isHorseRacing = val;
  14786. }
  14787.  
  14788. public function GetIsHorseRacing() : bool
  14789. {
  14790. return isHorseRacing;
  14791. }
  14792.  
  14793. public function SetHorseCombatSlowMo( val : bool )
  14794. {
  14795. horseCombatSlowMo = val;
  14796. }
  14797.  
  14798. public function GetHorseCombatSlowMo() : bool
  14799. {
  14800. return horseCombatSlowMo;
  14801. }
  14802.  
  14803. public function SetItemsPerLevelGiven( id : int )
  14804. {
  14805. itemsPerLevelGiven[id] = true;
  14806. }
  14807.  
  14808. private function AddItemPerLevelList()
  14809. {
  14810. var i : int;
  14811.  
  14812. itemsPerLevel.Clear();
  14813. itemsPerLevel.PushBack('O');
  14814. itemsPerLevel.PushBack('No Mans Land sword 2');
  14815. itemsPerLevel.PushBack('No Mans Land sword 3');
  14816. itemsPerLevel.PushBack('Silver sword 2');
  14817. itemsPerLevel.PushBack('Boots 01');
  14818. itemsPerLevel.PushBack('Novigraadan sword 2');
  14819. itemsPerLevel.PushBack('Light armor 01');
  14820. itemsPerLevel.PushBack('Heavy boots 01');
  14821. itemsPerLevel.PushBack('Nilfgaardian sword 3');
  14822. itemsPerLevel.PushBack('Silver sword 3');
  14823. itemsPerLevel.PushBack('Heavy gloves 01');
  14824. itemsPerLevel.PushBack('Skellige sword 2');
  14825. itemsPerLevel.PushBack('Heavy pants 01');
  14826. itemsPerLevel.PushBack('Silver sword 4');
  14827. itemsPerLevel.PushBack('No Mans Land sword 4');
  14828. itemsPerLevel.PushBack('Heavy armor 01');
  14829. itemsPerLevel.PushBack('Heavy boots 02');
  14830. itemsPerLevel.PushBack('Skellige sword 3');
  14831. itemsPerLevel.PushBack('Silver sword 5');
  14832. itemsPerLevel.PushBack('Heavy pants 02');
  14833. itemsPerLevel.PushBack('Heavy gloves 02');
  14834. itemsPerLevel.PushBack('Heavy gloves 02');
  14835. itemsPerLevel.PushBack('Heavy armor 02');
  14836. itemsPerLevel.PushBack('Scoiatael sword 1');
  14837.  
  14838. if ( itemsPerLevelGiven.Size() < 49 )
  14839. {
  14840. itemsPerLevelGiven.Clear();
  14841. for (i = 0; i < itemsPerLevel.Size(); i += 1) { itemsPerLevelGiven.PushBack( false ); }
  14842. }
  14843. }
  14844.  
  14845. // TEMP
  14846. public function DealDamageToBoat( dmg : float, index : int, optional globalHitPos : Vector )
  14847. {
  14848. var boat : CBoatDestructionComponent;
  14849.  
  14850. if(usedVehicle)
  14851. {
  14852. boat = (CBoatDestructionComponent) usedVehicle.GetComponentByClassName( 'CBoatDestructionComponent' );
  14853. if( boat )
  14854. {
  14855. boat.DealDamage( dmg, index, globalHitPos );
  14856. }
  14857. }
  14858. }
  14859.  
  14860. ////////////////////////////////////////////////////////////////////////////////
  14861. //
  14862. // PLAYABLE AREA
  14863. //
  14864. public function OnStartTeleportingPlayerToPlayableArea()
  14865. {
  14866. var FADEOUT_INTERVAL : float = 0.5;
  14867.  
  14868. // if we jumped on horse right before being teleported, we need to disable falling damage because height difference may kill us
  14869. if ( thePlayer.IsUsingHorse() )
  14870. {
  14871. if ( thePlayer.GetUsedHorseComponent().OnCheckHorseJump() )
  14872. {
  14873. thePlayer.GetUsedHorseComponent().SetCanTakeDamageFromFalling( false );
  14874. }
  14875. }
  14876.  
  14877. if ( thePlayer.IsActionAllowed( EIAB_FastTravel ) )
  14878. {
  14879. OnOpenMapToLetPlayerGoBackToPlayableArea();
  14880. }
  14881. else
  14882. {
  14883. theGame.FadeOutAsync( FADEOUT_INTERVAL );
  14884. thePlayer.AddTimer( 'BorderTeleportFadeOutTimer', FADEOUT_INTERVAL, false );
  14885. }
  14886. }
  14887.  
  14888. timer function BorderTeleportFadeOutTimer( dt : float, id : int )
  14889. {
  14890. OnTeleportPlayerToPlayableArea( false );
  14891. }
  14892.  
  14893. public function OnOpenMapToLetPlayerGoBackToPlayableArea()
  14894. {
  14895. var initData : W3MapInitData;
  14896.  
  14897. initData = new W3MapInitData in this;
  14898. initData.SetTriggeredExitEntity( true );
  14899. initData.ignoreSaveSystem = true;
  14900. initData.setDefaultState('FastTravel');
  14901. theGame.RequestMenuWithBackground( 'MapMenu', 'CommonMenu', initData );
  14902. }
  14903.  
  14904. public function OnTeleportPlayerToPlayableArea( afterClosingMap : bool )
  14905. {
  14906. var BLACKSCREEN_INTERVAL : float = 0.5;
  14907. var manager : CCommonMapManager = theGame.GetCommonMapManager();
  14908.  
  14909. theGame.FadeOutAsync( 0 );
  14910. thePlayer.TeleportWithRotation( manager.GetBorderTeleportPosition(), manager.GetBorderTeleportRotation() );
  14911. thePlayer.AddTimer( 'BorderTeleportFadeInTimer', BLACKSCREEN_INTERVAL, false );
  14912.  
  14913. theGame.FadeOutAsync( 0 );
  14914. theGame.SetFadeLock('PlayerTeleportation');
  14915. }
  14916.  
  14917. timer function BorderTeleportFadeInTimer( dt : float, id : int )
  14918. {
  14919. var FADEIN_INTERVAL : float = 0.5;
  14920.  
  14921. theGame.FadeInAsync( FADEIN_INTERVAL );
  14922. }
  14923.  
  14924. public final function SetLastInstantKillTime(g : GameTime)
  14925. {
  14926. lastInstantKillTime = g;
  14927. }
  14928. //
  14929. //
  14930. //
  14931. ////////////////////////////////////////////////////////////////////////////////
  14932.  
  14933. timer function TestTimer(dt : float, id : int )
  14934. {
  14935. LogChannel('asdf', "asdf");
  14936. theGame.FadeOutAsync( 5 );
  14937. }
  14938.  
  14939. public final function Debug_ReleaseCriticalStateSaveLocks()
  14940. {
  14941. effectManager.Debug_ReleaseCriticalStateSaveLocks();
  14942. }
  14943.  
  14944. timer function Debug_SpamSpeed(dt : float, id : int)
  14945. {
  14946. if(currentlyMountedHorse)
  14947. {
  14948. LogSpeed("curr player's horse speed: " + NoTrailZeros(currentlyMountedHorse.GetMovingAgentComponent().GetSpeed())) ;
  14949. }
  14950. else
  14951. {
  14952. LogSpeed("curr player speed: " + NoTrailZeros(GetMovingAgentComponent().GetSpeed())) ;
  14953. }
  14954. }
  14955.  
  14956. timer function RemoveInstantKillSloMo(dt : float, id : int)
  14957. {
  14958. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_InstantKill) );
  14959. }
  14960.  
  14961. timer function RemoveForceFinisher(dt : float, id : int)
  14962. {
  14963. forceFinisher = false;
  14964. }
  14965.  
  14966. public final function Debug_ClearAllActionLocks(optional action : EInputActionBlock, optional all : bool)
  14967. {
  14968. inputHandler.Debug_ClearAllActionLocks(action, all);
  14969. }
  14970.  
  14971. function OnFocusedCameraBlendBegin() {}
  14972. function OnFocusedCameraBlendUpdate( progress : float ) {}
  14973. function OnFocusedCameraBlendEnd() {}
  14974.  
  14975. public function GetEtherealCount() : int { return etherealCount; }
  14976. public function IncrementEtherealCount()
  14977. {
  14978. etherealCount += 1;
  14979. if( etherealCount == 6 )
  14980. ResetEtherealCount();
  14981. }
  14982. public function ResetEtherealCount() { etherealCount = 0; }
  14983.  
  14984. // PHANTOM WEAPON
  14985. //------------------------------------------------------------------------------------------------------------------
  14986. public function SetInsideDiveAttackArea( val : bool ) { insideDiveAttackArea = val; }
  14987. public function IsInsideDiveAttackArea() : bool { return insideDiveAttackArea; }
  14988. public function SetDiveAreaNumber( val : int ) { diveAreaNumber = val; }
  14989. public function GetDiveAreaNumber() : int { return diveAreaNumber; }
  14990.  
  14991.  
  14992.  
  14993. public function InitPhantomWeaponMgr()
  14994. {
  14995. if( !phantomWeaponMgr )
  14996. {
  14997. phantomWeaponMgr = new CPhantomWeaponManager in this;
  14998. phantomWeaponMgr.Init( this.GetInventory() );
  14999. }
  15000. }
  15001.  
  15002. public function DestroyPhantomWeaponMgr()
  15003. {
  15004. if( phantomWeaponMgr )
  15005. {
  15006. delete phantomWeaponMgr;
  15007. }
  15008. }
  15009.  
  15010. public function GetPhantomWeaponMgr() : CPhantomWeaponManager
  15011. {
  15012. if( phantomWeaponMgr )
  15013. {
  15014. return phantomWeaponMgr;
  15015. }
  15016. else
  15017. {
  15018. return NULL;
  15019. }
  15020. }
  15021.  
  15022. public timer function DischargeWeaponAfter( td : float, id : int )
  15023. {
  15024. GetPhantomWeaponMgr().DischargeWeapon();
  15025. }
  15026. //------------------------------------------------------------------------------------------------------------------
  15027.  
  15028.  
  15029.  
  15030.  
  15031. private var forcedFinisherVictim : CActor;
  15032.  
  15033. timer function PerformFinisher( time : float , id : int )
  15034. {
  15035. var combatTarget : CActor;
  15036. var i : int;
  15037.  
  15038. combatTarget = thePlayer.GetTarget();
  15039.  
  15040. if( combatTarget )
  15041. {
  15042. combatTarget.Kill( 'AutoFinisher', false, thePlayer );
  15043. thePlayer.SetFinisherVictim( combatTarget );
  15044. forcedFinisherVictim = combatTarget;
  15045. thePlayer.CleanCombatActionBuffer();
  15046. thePlayer.OnBlockAllCombatTickets( true );
  15047. moveTargets = thePlayer.GetMoveTargets();
  15048.  
  15049. for( i = 0; i < moveTargets.Size(); i += 1 )
  15050. {
  15051. if( combatTarget != moveTargets[i] )
  15052. moveTargets[i].SignalGameplayEvent( 'InterruptChargeAttack' );
  15053. }
  15054.  
  15055. if( theGame.GetInGameConfigWrapper().GetVarValue( 'Gameplay', 'AutomaticFinishersEnabled' ) == "true" )
  15056. combatTarget.AddAbility( 'ForceFinisher', false );
  15057.  
  15058. if( combatTarget.HasTag( 'ForceFinisher' ) )
  15059. combatTarget.AddAbility( 'ForceFinisher', false );
  15060.  
  15061. combatTarget.SignalGameplayEvent( 'ForceFinisher' );
  15062.  
  15063. thePlayer.FindMoveTarget();
  15064.  
  15065. thePlayer.AddTimer( 'SignalFinisher', 0.2, false );
  15066. }
  15067. }
  15068.  
  15069. timer function SignalFinisher( time : float , id : int )
  15070. {
  15071. forcedFinisherVictim.SignalGameplayEvent( 'Finisher' );
  15072. forcedFinisherVictim = NULL;
  15073. }
  15074. }
  15075.  
  15076. exec function ttt()
  15077. {
  15078. thePlayer.AddTimer( 'TestTimer', 5, false );
  15079. }
  15080.  
Add Comment
Please, Sign In to add comment