Advertisement
Guest User

Script compilation error

a guest
Dec 30th, 2019
516
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 460.08 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.  
  111. // FISTFIGHT MINIGAME
  112. private var fistFightMinigameEnabled : bool;
  113. private var isFFMinigameToTheDeath : bool;
  114. private var FFMinigameEndsithBS : bool;
  115. public var fistFightTeleportNode : CNode;
  116. public var isStartingFistFightMinigame : bool;
  117. public var GeraltMaxHealth : float;
  118. public var fistsItems : array< SItemUniqueId >;
  119.  
  120. default FFMinigameEndsithBS = false;
  121. default fistFightMinigameEnabled = false;
  122. default isFFMinigameToTheDeath = false;
  123.  
  124. // GWINT MINIGAME
  125. private var gwintAiDifficulty : EGwintDifficultyMode; default gwintAiDifficulty = EGDM_Easy;
  126. private var gwintAiAggression : EGwintAggressionMode; default gwintAiAggression = EGAM_Defensive;
  127. private var gwintMinigameState : EMinigameState; default gwintMinigameState = EMS_None;
  128.  
  129. // HORSE
  130. import private var horseWithInventory : EntityHandle; // if spawned handle is valid ( horse with inventory )
  131. private var currentlyMountedHorse : CNewNPC;
  132. private var horseSummonTimeStamp : float;
  133. private saved var isHorseRacing : bool;
  134. private var horseCombatSlowMo : bool;
  135. default isHorseRacing = false;
  136. default horseCombatSlowMo = true;
  137.  
  138. // HUD FIXME - shouldn't this all be in hud / ui rather than player?
  139. private var HudMessages : array <string>; //#B change to struct with message type, message duration etc
  140. protected var fShowToLowStaminaIndication : float;
  141. public var showTooLowAdrenaline : bool;
  142. private var HAXE3Container : W3Container; //#B temp for E3
  143. private var HAXE3bAutoLoot: bool; //#B temp for E3
  144. private var bShowHud : bool;
  145. private var dodgeFeedbackTarget : CActor;
  146.  
  147. default HAXE3bAutoLoot = false;
  148. default fShowToLowStaminaIndication = 0.0f;
  149. default bShowHud = true;
  150.  
  151. saved var displayedQuestsGUID : array< CGUID >; // #B moved here because saved in journal doesn't work.
  152. saved var rewardsMultiplier : array< SRewardMultiplier >; // #B moved here because saved in journal doesn't work.s
  153. saved var glossaryImageOverride : array< SGlossaryImageOverride >; // #B moved here because saved in journal doesn't work.s
  154.  
  155. // INPUT
  156. private var prevRawLeftJoyRot : float;
  157. protected var explorationInputContext : name;
  158. protected var combatInputContext : name;
  159. protected var combatFistsInputContext : name;
  160.  
  161. // INTERACTIONS
  162. private var isInsideInteraction : bool; //set to true when player is inside any interaction range, used to prioritize input
  163. private var isInsideHorseInteraction : bool;
  164. public var horseInteractionSource : CEntity;
  165. public var nearbyLockedContainersNoKey : array<W3LockableEntity>; //to update tooltip if player is close to a locked container and is THEN given a key
  166.  
  167. // MOVEMENT
  168. private var bMoveTargetChangeAllowed : bool; default bMoveTargetChangeAllowed = true;
  169. private var moveAdj : CMovementAdjustor;
  170. private var defaultLocomotionController : CR4LocomotionPlayerControllerScript;
  171. //private var isFollowing : bool;
  172. //private var followingStartTime : float;
  173. private var canFollowNpc : bool;
  174. private var actorToFollow : CActor;
  175. public var terrainPitch : float;
  176. public var steepSlopeNormalPitch : float; default steepSlopeNormalPitch = 65.f;
  177. public var disableSprintTerrainPitch : float; default disableSprintTerrainPitch = 54.f;
  178. private var submergeDepth : float;
  179.  
  180. private var m_useSelectedItemIfSpawned : bool; default m_useSelectedItemIfSpawned = false; // Used only in WaitForItemSpawnAndProccesTask
  181.  
  182.  
  183. var navQuery : CNavigationReachabilityQueryInterface;
  184.  
  185. // BARBER
  186. public saved var rememberedCustomHead : name;
  187.  
  188. // WEATHER DISPLAY
  189. public saved var disableWeatherDisplay : bool;
  190.  
  191. // EPISODE1
  192. public saved var proudWalk : bool;
  193. private var etherealCount : int;
  194. default etherealCount = 0;
  195.  
  196. // EPISODE2
  197. public saved var injuredWalk : bool;
  198. public saved var tiedWalk : bool;
  199. private var insideDiveAttackArea : bool;
  200. default insideDiveAttackArea = false;
  201. private var diveAreaNumber : int;
  202. default diveAreaNumber = -1;
  203.  
  204. // CAMERA
  205. private var flyingBossCamera : bool;
  206. default flyingBossCamera = false;
  207.  
  208. public function SetFlyingBossCamera( val : bool ) { flyingBossCamera = val; }
  209. public function GetFlyingBossCamera() : bool { return flyingBossCamera; }
  210.  
  211. // TOOLTIP
  212. public saved var upscaledTooltipState : bool;
  213. default upscaledTooltipState = false;
  214.  
  215. // PHANTOM WEAPON
  216. private var phantomWeaponMgr : CPhantomWeaponManager;
  217.  
  218. /*public var bonePositionCam : Vector;
  219.  
  220. public function SetBonePositionCam( pos : Vector )
  221. {
  222. bonePositionCam = pos;
  223. }*/
  224.  
  225. function EnablePCMode( flag : bool )
  226. {
  227. pcMode = flag;
  228. }
  229.  
  230. public function IsPCModeEnabled() : bool
  231. {
  232. return pcMode && theInput.LastUsedPCInput();
  233. }
  234.  
  235. public function ShouldUsePCModeTargeting() : bool
  236. {
  237. return IsPCModeEnabled() && !lastAxisInputIsMovement;
  238. }
  239.  
  240. public function SetDodgeFeedbackTarget( target : CActor )
  241. {
  242. dodgeFeedbackTarget = target;
  243. }
  244.  
  245. public function GetDodgeFeedbackTarget() : CActor
  246. {
  247. return dodgeFeedbackTarget;
  248. }
  249.  
  250. public function SetSubmergeDepth( depth : float )
  251. {
  252. submergeDepth = depth;
  253. }
  254.  
  255. public function GetSubmergeDepth() : float
  256. {
  257. return submergeDepth;
  258. }
  259.  
  260. // ONELINERS
  261. editable var delayBetweenIllusionOneliners : float;
  262.  
  263. hint delayBetweenIllusionOneliners = "delay in secs between oneliners about illusionary objects";
  264.  
  265. default delayBetweenIllusionOneliners = 5;
  266.  
  267. // Battlecry
  268. private var battlecry_timeForNext : float;
  269. private var battlecry_delayMin : float; default battlecry_delayMin = 15;
  270. private var battlecry_delayMax : float; default battlecry_delayMax = 60;
  271. private var battlecry_lastTry : name;
  272.  
  273. // Weather
  274. private var previousWeather : name;
  275. private var previousRainStrength : float;
  276.  
  277. //OTHER
  278. protected var receivedDamageInCombat : bool; //set when you got hit
  279. protected var prevDayNightIsNight : bool; //Day-Night cycle check - value of previous check
  280. //Shaedhen - Atmospheric Nights - Starts here
  281. var environmentDN : CEnvironmentDefinition; //Will be used to store darkness_upon_us
  282. var environmentDN2 : CEnvironmentDefinition; //Will be used to store darkness_upon_us
  283. var environmentDNegated : CEnvironmentDefinition; //Will be used to store darkness_upon_us
  284. private var envIdDN : Int32; //Id to deactivate darkness_upon_us
  285. default envIdDN = -1;
  286. private var envIdDN2 : Int32; //Id to deactivate darkness_upon_us
  287. default envIdDN2 = -1;
  288. private var envIdDNegated : Int32; //Id to deactivate darkness_upon_us
  289. default envIdDNegated = -1;
  290. private var inGameConfigWrapperDN : CInGameConfigWrapper;
  291. var intensityDN : array<float>;
  292. var startDN : int;
  293. default startDN = 1200;
  294. var startTimeDN : int;
  295. default startTimeDN = 120;
  296. var endDN : int;
  297. default endDN = 180;
  298. var endTimeDN : int;
  299. default endTimeDN = 180;
  300. public var realHoursPerMinutesDN : float;
  301. default realHoursPerMinutesDN = 0.25;
  302. private var justSpawnedDN : bool;
  303. private var isEnabledDN : bool;
  304. private var listOfStartTimesDK : array<int>;
  305. private var listOfStartDurationTimesDK : array<int>;
  306. private var listOfEndTimesDK : array<int>;
  307. private var listOfEndDurationTimesDK : array<int>;
  308. //Shaedhen - Atmospheric Nights - Ends here
  309. public var failedFundamentalsFirstAchievementCondition : bool;
  310.  
  311. private var spawnedTime : float;
  312.  
  313. public var currentMonsterHuntInvestigationArea : W3MonsterHuntInvestigationArea;
  314.  
  315. private var isPerformingPhaseChangeAnimation : bool; // flag for suppressing game camera update during synced animation in eredin fight
  316. default isPerformingPhaseChangeAnimation = false;
  317.  
  318. default receivedDamageInCombat = false;
  319.  
  320. // PLAYER MODE
  321. public var playerMode : W3PlayerMode;
  322.  
  323. // QUICKSLOTS
  324. protected saved var selectedItemId : SItemUniqueId; //id of item selected from quickslots
  325. protected saved var blockedRadialSlots : array < SRadialSlotDef >; // radial menu slots blocked by different sources
  326.  
  327. // SOFT LOCK TARGETING
  328. public var enemyCollectionDist : float;
  329. public var findMoveTargetDistMin : float; //distance from player to get softlocked targets
  330. public var findMoveTargetDistMax : float; //distance from player that target gets disengaged from soft lock
  331. private var findMoveTargetScaledFrame : float; //xaxis scale to find non-hostile targets when stationary
  332. public var interactDist : float; //distance from player to attack or interact with a non-hostile npc
  333. protected var bCanFindTarget : bool;
  334. private var bIsConfirmingEmptyTarget : bool;
  335. private var displayTarget : CGameplayEntity; //entity to show health bar on hud;
  336. private var isShootingFriendly : bool;
  337.  
  338. default findMoveTargetDistMax = 18.f;
  339. default findMoveTargetScaledFrame = 0.5f;
  340. default interactDist = 3.5f;
  341.  
  342. //Target Selection
  343. private var currentSelectedTarget : CActor;
  344. private var selectedTargetToConfirm : CActor;
  345. private var bConfirmTargetTimerIsEnabled : bool;
  346.  
  347. // THROWABLES
  348. public saved var thrownEntityHandle : EntityHandle; //entity of currently thrown item (in aiming)
  349. private var isThrowingItemWithAim : bool;
  350. private saved var isThrowingItem : bool; //used for aim mode to check if we're in throwing logic
  351. private var isThrowHoldPressed : bool;
  352.  
  353. // CROSSBOW
  354. private var isAimingCrossbow : bool;
  355.  
  356. default isThrowingItemWithAim = false;
  357.  
  358. // AIMING MODE
  359. public var playerAiming : PlayerAiming;
  360.  
  361. // DISMEMBERMENT
  362. public var forceDismember : bool;
  363. public var forceDismemberName : name;
  364. public var forceDismemberChance : int;
  365. public var forceDismemberExplosion : bool;
  366.  
  367. // FINISHER
  368. private var finisherVictim : CActor;
  369. public var forceFinisher : bool;
  370. public var forceFinisherAnimName : name;
  371. public var forceFinisherChance : int;
  372. public var forcedStance : bool;
  373.  
  374. // WEAPON COLLISION FX
  375. private var m_WeaponFXCollisionGroupNames : array <name>;
  376. private var m_CollisionEffect : CEntity;
  377. private var m_LastWeaponTipPos : Vector;
  378. private var m_CollisionFxTemplate : CEntityTemplate;
  379. private var m_RefreshWeaponFXType : bool;
  380. private var m_PlayWoodenFX : bool;
  381.  
  382. // POSTERS
  383. private var m_activePoster : W3Poster;
  384.  
  385. public function SetActivePoster ( poster : W3Poster )
  386. {
  387. m_activePoster = poster;
  388. }
  389.  
  390. public function RemoveActivePoster ()
  391. {
  392. m_activePoster = NULL;
  393. }
  394.  
  395. public function GetActivePoster () : W3Poster
  396. {
  397. return m_activePoster;
  398. }
  399. // SAVE / LOAD
  400. //private saved var safePositionStored: bool; default safePositionStored = false;
  401. //private saved var lastSafePosition : Vector;
  402. //private saved var lastSafeRotation : EulerAngles;
  403.  
  404. public var horseOnNavMesh : bool;
  405. default horseOnNavMesh = true;
  406.  
  407. public function SetHorseNav( val : bool ) { horseOnNavMesh = val; }
  408.  
  409. // TEST
  410. public var testAdjustRequestedMovementDirection : bool; // TEST
  411. default testAdjustRequestedMovementDirection = false;
  412.  
  413. // State
  414. default autoState = 'Exploration';
  415.  
  416. ///////////////////////////////////////////////////////////////////////////
  417. /////////////////// IMPORTED C++ FUNCTIONS //////////////////////////////
  418. ///////////////////////////////////////////////////////////////////////////
  419.  
  420. // All following functions give cached data from previous frame
  421. import final function GetEnemiesInRange( out enemies : array< CActor > );
  422. import final function GetVisibleEnemies( out enemies : array< CActor > );
  423. import final function IsEnemyVisible( enemy : CActor ) : bool;
  424.  
  425. // Set this up in order to use above functions and get the proper data
  426. import final function SetupEnemiesCollection( range, heightTolerance : float,
  427. maxEnemies : int,
  428. optional tag : name,
  429. optional flags : int ); // please combine EScriptQueryFlags - FLAG_ExcludePlayer is always on
  430.  
  431. import final function IsInInterior() : bool;
  432. import final function IsInSettlement() : bool;
  433. import final function EnterSettlement( isEntering : bool );
  434. import final function ActionDirectControl( controller : CR4LocomotionDirectController ) : bool;
  435. import final function SetPlayerTarget( target : CActor );
  436. import final function SetPlayerCombatTarget( target : CActor );
  437. import final function ObtainTicketFromCombatTarget( ticketName : CName, ticketsCount : int );
  438. import final function FreeTicketAtCombatTarget();
  439. import final function SetScriptMoveTarget( target : CActor );
  440. import final function GetRiderData() : CAIStorageRiderData;
  441. import final function SetIsInCombat( inCombat : bool );
  442. import final function SaveLastMountedHorse( mountedHorse : CActor );
  443.  
  444. import final function SetBacklightFromHealth( healthPercentage : float );
  445. import private final function SetBacklightColor( color : Vector );
  446.  
  447. import final function GetCombatDataComponent() : CCombatDataComponent;
  448.  
  449. import final function GetTemplatePathAndAppearance( out templatePath : string, out appearance : name );
  450.  
  451. import final function HACK_BoatDismountPositionCorrection( slotPos : Vector );
  452.  
  453. import final function HACK_ForceGetBonePosition( boneIndex : int ) : Vector;
  454.  
  455.  
  456. public function GetLevel() : int
  457. {
  458. return 0;
  459. }
  460.  
  461. ///////////////////////////////////////////////////////////////////////////
  462. // (new) targeting
  463.  
  464. var targeting : CR4PlayerTargeting;
  465. var targetingPrecalcs : SR4PlayerTargetingPrecalcs;
  466. var targetingIn : SR4PlayerTargetingIn;
  467. var targetingOut : SR4PlayerTargetingOut;
  468. var useNativeTargeting : bool;
  469. default useNativeTargeting = true;
  470.  
  471. var visibleActors : array< CActor >;
  472. var visibleActorsTime : array< float >;
  473.  
  474. ///////////////////////////////////////////////////////////////////////////
  475.  
  476. event OnSpawned( spawnData : SEntitySpawnData )
  477. {
  478. var atts : array<name>;
  479. var skill : ESkill;
  480. var i : int;
  481. var item : SItemUniqueId;
  482.  
  483. AddAnimEventCallback('ThrowHoldTest', 'OnAnimEvent_ThrowHoldTest');
  484. AddAnimEventCallback('OnWeaponDrawReady', 'OnAnimEvent_OnWeaponDrawReady');
  485. AddAnimEventCallback('OnWeaponHolsterReady', 'OnAnimEvent_OnWeaponHolsterReady');
  486. AddAnimEventCallback('AllowTempLookAt', 'OnAnimEvent_AllowTempLookAt');
  487. AddAnimEventCallback('SlideToTarget', 'OnAnimEvent_SlideToTarget');
  488. AddAnimEventCallback('PlayFinisherBlood', 'OnAnimEvent_PlayFinisherBlood');
  489. AddAnimEventCallback('SlowMo', 'OnAnimEvent_SlowMo');
  490. AddAnimEventCallback('BloodTrailForced', 'OnAnimEvent_BloodTrailForced');
  491. AddAnimEventCallback('FadeOut', 'OnAnimEvent_FadeOut');
  492. AddAnimEventCallback('FadeIn', 'OnAnimEvent_FadeIn');
  493. AddAnimEventCallback('DisallowHitAnim', 'OnAnimEvent_DisallowHitAnim');
  494. AddAnimEventCallback('AllowFall', 'OnAnimEvent_AllowFall');
  495. AddAnimEventCallback('AllowFall2', 'OnAnimEvent_AllowFall2');
  496. AddAnimEventCallback('DettachGround', 'OnAnimEvent_DettachGround');
  497. AddAnimEventCallback('KillWithRagdoll', 'OnAnimEvent_KillWithRagdoll');
  498. AddAnimEventCallback('pad_vibration', 'OnAnimEvent_pad_vibration');
  499. AddAnimEventCallback('pad_vibration_light', 'OnAnimEvent_pad_vibration_light');
  500. AddAnimEventCallback('RemoveBurning', 'OnAnimEvent_RemoveBurning');
  501. AddAnimEventCallback('RemoveTangled', 'OnAnimEvent_RemoveTangled');
  502. AddAnimEventCallback('MoveNoise', 'OnAnimEvent_MoveNoise');
  503.  
  504. AddItemPerLevelList();
  505.  
  506. enemyCollectionDist = findMoveTargetDistMax;
  507.  
  508. //retrofix - removing saved timescale
  509. theGame.RemoveTimeScale('horse_melee');
  510.  
  511. //give items
  512. if(!spawnData.restored && !((W3ReplacerCiri)this) )
  513. {
  514. AddTimer('GiveStartingItems', 0.00001, true, , , true);
  515.  
  516. if(!theGame.IsFinalBuild())
  517. {
  518. //unlock skills for testing purposes
  519. AddAbility('GeraltSkills_Testing');
  520. AddTimer('Debug_GiveTestingItems',0.0001,true);
  521. }
  522.  
  523. //disable retro-stash-tutorial on fresh playthroughs
  524. FactsAdd("tut_stash_fresh_playthrough");
  525. }
  526.  
  527. InitTargeting();
  528.  
  529. // After load
  530. if( spawnData.restored )
  531. {
  532. // ED this line was not called before, because of extra if conditions regarding "safe position stored" but it was uncommented
  533. //OnUseSelectedItem();
  534.  
  535. theGame.GameplayFactsRemove( "in_combat" );
  536. }
  537.  
  538.  
  539. // Create the sword holster (it is a saved property, there is no need of re-creating it when playing from save)
  540. if ( !weaponHolster )
  541. {
  542. weaponHolster = new WeaponHolster in this;
  543. }
  544. // temp workaround of not saving states:
  545. weaponHolster.Initialize( this, spawnData.restored );
  546.  
  547. if ( !interiorTracker )
  548. {
  549. interiorTracker = new CPlayerInteriorTracker in this;
  550. }
  551. interiorTracker.Init( spawnData.restored );
  552.  
  553.  
  554. super.OnSpawned( spawnData );
  555.  
  556. // Create medallion
  557. medallion = new W3MedallionFX in this;
  558.  
  559. playerMode = new W3PlayerMode in this;
  560. playerMode.Initialize( this );
  561.  
  562. // Initialize Aiming Mode
  563. playerAiming = new PlayerAiming in this;
  564. playerAiming.Initialize( this );
  565.  
  566. // Initialize reachability query
  567. navQuery = new CNavigationReachabilityQueryInterface in this;
  568.  
  569. // Start looking for soft-lock targets
  570. EnableFindTarget( true );
  571. AddTimer( 'CombatCheck', 0.2f, true );
  572.  
  573. // Get the exploration state manager component
  574. substateManager = ( CExplorationStateManager ) GetComponentByClassName( 'CExplorationStateManager' );
  575.  
  576. findMoveTargetDist = findMoveTargetDistMax;
  577.  
  578. SetupEnemiesCollection( enemyCollectionDist, findMoveTargetDist, 10, 'None', FLAG_Attitude_Neutral + FLAG_Attitude_Hostile + FLAG_Attitude_Friendly + FLAG_OnlyAliveActors );
  579.  
  580. //for geralt-replacer switching
  581. inputHandler.RemoveLocksOnSpawn();
  582.  
  583. // Player has the lowest push priority
  584. ((CActor) this ).SetInteractionPriority( IP_Prio_0 );
  585.  
  586. prevDayNightIsNight = theGame.envMgr.IsNight();
  587. //Shaedhen - Atmospheric Nights - Starts here
  588. environmentDN = (CEnvironmentDefinition)LoadResource("fx\demos_and_temp_fx\darkness_upon_us.env",true);
  589. environmentDN2 = (CEnvironmentDefinition)LoadResource("fx\demos_and_temp_fx\darkness_upon_us.env",true);
  590. environmentDNegated = (CEnvironmentDefinition)LoadResource("fx\demos_and_temp_fx\darkness_upon_us.env",true);
  591. envIdDN = -1;
  592. envIdDN2 = -1;
  593. envIdDNegated = -1;
  594. justSpawnedDN = true;
  595. InitAtmosphericNights();
  596. UpdateValuesDK();
  597. //Shaedhen - Atmospheric Nights - Ends here
  598. CheckDayNightCycle();
  599. justSpawnedDN = false; //Shaedhen - Atmospheric Nights
  600.  
  601. // Debug
  602. EnableVisualDebug( SHOW_AI, true );
  603.  
  604. //oneliners delay
  605. FactsRemove("blocked_illusion_oneliner");
  606.  
  607. SetFailedFundamentalsFirstAchievementCondition(false);
  608. m_CollisionFxTemplate = (CEntityTemplate) LoadResource( 'sword_colision_fx' );
  609. if( m_WeaponFXCollisionGroupNames.Size() == 0 )
  610. {
  611. m_WeaponFXCollisionGroupNames.PushBack('Static');
  612. m_WeaponFXCollisionGroupNames.PushBack('Foliage');
  613. m_WeaponFXCollisionGroupNames.PushBack('Fence');
  614. m_WeaponFXCollisionGroupNames.PushBack('BoatSide');
  615. m_WeaponFXCollisionGroupNames.PushBack('Door');
  616. m_WeaponFXCollisionGroupNames.PushBack('RigidBody');
  617. m_WeaponFXCollisionGroupNames.PushBack('Dynamic');
  618. m_WeaponFXCollisionGroupNames.PushBack('Destructible');
  619. }
  620.  
  621. if ( counterCollisionGroupNames.Size() == 0 )
  622. {
  623. counterCollisionGroupNames.PushBack('Static');
  624. counterCollisionGroupNames.PushBack('Foliage');
  625. counterCollisionGroupNames.PushBack('Fence');
  626. counterCollisionGroupNames.PushBack('Terrain');
  627. counterCollisionGroupNames.PushBack('Door');
  628. counterCollisionGroupNames.PushBack('RigidBody');
  629. counterCollisionGroupNames.PushBack('Dynamic');
  630. counterCollisionGroupNames.PushBack('Destructible');
  631. }
  632.  
  633. //ps4 pad backlight color
  634. ResetPadBacklightColor();
  635.  
  636. if( spawnData.restored )
  637. {
  638. if (IsCurrentlyUsingItemL())
  639. {
  640. if (inv.HasItemById( currentlyEquipedItemL ))
  641. {
  642. OnUseSelectedItem();
  643. }
  644. else
  645. {
  646. HideUsableItem(true);
  647. }
  648. }
  649. if ( GetCurrentMeleeWeaponType() == PW_Steel || GetCurrentMeleeWeaponType() == PW_Silver )
  650. {
  651. OnEquipMeleeWeapon(GetCurrentMeleeWeaponType(), true, true);
  652. }
  653.  
  654. AddTimer( 'UnmountCrossbowTimer', 0.01, true );
  655.  
  656. ClearBlockedSlots();
  657. }
  658.  
  659. ((CR4PlayerStateSwimming)this.GetState('Swimming')).OnParentSpawned();
  660.  
  661. //hack for possible immortality from finishers
  662. SetImmortalityMode( AIM_None, AIC_SyncedAnim );
  663.  
  664. //disable Dimeritium Bomb skill locks after load
  665. theGame.GetDefinitionsManager().GetContainedAbilities('DwimeritiumBomb_3', atts);
  666. for(i=0; i<atts.Size(); i+=1)
  667. {
  668. skill = SkillNameToEnum(atts[i]);
  669. if(skill != S_SUndefined)
  670. BlockSkill(skill, false);
  671. }
  672.  
  673. // phantom weapon manager
  674. this.GetInventory().GetItemEquippedOnSlot( EES_SteelSword, item );
  675. if( this.GetInventory().ItemHasTag( item, 'PhantomWeapon' ) )
  676. {
  677. this.InitPhantomWeaponMgr();
  678. }
  679.  
  680. //retoractive fix
  681. if(FactsQuerySum("mq3036_fact_done") > 0)
  682. BlockAllActions('mq3036', false);
  683.  
  684. spawnedTime = theGame.GetEngineTimeAsSeconds();
  685.  
  686. if ( theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'EnableUberMovement' ) == "1" )
  687. theGame.EnableUberMovement( true );
  688. else
  689. theGame.EnableUberMovement( false );
  690.  
  691. // Initial level for Gwint Difficulty (Normal)
  692. if ( !FactsDoesExist("gwent_difficulty") )
  693. FactsAdd("gwent_difficulty", 2);
  694.  
  695. //NG+
  696. if(!newGamePlusInitialized && FactsQuerySum("NewGamePlus") > 0)
  697. {
  698. NewGamePlusInitialize();
  699. }
  700.  
  701. //fix wrapped instant kill time stamp
  702. if( lastInstantKillTime > theGame.GetGameTime() )
  703. {
  704. SetLastInstantKillTime( GameTimeCreate(0) );
  705. }
  706. }
  707.  
  708. public function NewGamePlusInitialize()
  709. {
  710. //reset instant kill cooldown
  711. SetLastInstantKillTime( GameTimeCreate(0) );
  712. }
  713.  
  714. public function GetTimeSinceSpawned() : float
  715. {
  716. return theGame.GetEngineTimeAsSeconds() - spawnedTime;
  717. }
  718.  
  719. timer function UnmountCrossbowTimer( dt : float, id : int )
  720. {
  721. var itemId : SItemUniqueId;
  722.  
  723. itemId = this.inv.GetItemFromSlot( 'l_weapon' );
  724. if ( inv.IsIdValid( itemId ) && inv.IsItemCrossbow( itemId ) )
  725. {
  726. rangedWeapon = (Crossbow)( inv.GetItemEntityUnsafe( itemId ) );
  727.  
  728. if (rangedWeapon)
  729. {
  730. rangedWeapon.Initialize( (CActor)( rangedWeapon.GetParentEntity() ) );
  731. OnRangedForceHolster( true, true );
  732. RemoveTimer( 'UnmountCrossbowTimer' );
  733. }
  734. }
  735. else
  736. RemoveTimer( 'UnmountCrossbowTimer' );
  737. }
  738.  
  739. event OnDestroyed()
  740. {
  741. playerAiming.RemoveAimingSloMo();
  742.  
  743. if(rangedWeapon)
  744. rangedWeapon.ClearDeployedEntity(true);
  745.  
  746. ResetPadBacklightColor();
  747.  
  748. //remove combat mode no-save lock
  749. theGame.ReleaseNoSaveLock( noSaveLock );
  750. }
  751.  
  752. /////////////////////////////////////////////////////////////////////
  753. ////////////////////////Radial Menu//////////////////////////////////
  754. ////////////////////////////////////////////////////////////////////
  755.  
  756. public function GetBlockedSlots () : array < SRadialSlotDef >
  757. {
  758. return blockedRadialSlots;
  759. }
  760.  
  761. public function ClearBlockedSlots()
  762. {
  763. var i : int;
  764. //var blockedSigns : array<ESignType>;
  765. //var playerWitcher : W3PlayerWitcher;
  766.  
  767. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  768. {
  769. if( !IsSwimming() )
  770. {
  771. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'swimming'))
  772. {
  773. i-=1;
  774. continue;
  775. }
  776. }
  777. if (!IsUsingVehicle())
  778. {
  779. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'useVehicle'))
  780. {
  781. i-=1;
  782. continue;
  783. }
  784. }
  785. if ( !IsCurrentlyUsingItemL() || !IsUsableItemLBlocked() )
  786. {
  787. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'usableItemL'))
  788. {
  789. i-=1;
  790. continue;
  791. }
  792. }
  793. if ( !IsThrowingItem() )
  794. {
  795. if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'throwBomb'))
  796. {
  797. i-=1;
  798. continue;
  799. }
  800. }
  801. }
  802. // 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.
  803. /*playerWitcher = (W3PlayerWitcher)this;
  804.  
  805. if ( playerWitcher )
  806. {
  807. blockedSigns = playerWitcher.GetBlockedSigns();
  808.  
  809. i = 0;
  810. for ( i = 0; i < blockedSigns.Size(); i+=1 )
  811. {
  812. switch( blockedSigns[i] )
  813. {
  814. case ST_Aard :
  815. if ( !IsRadialSlotBlocked ( 'Aard') )
  816. {
  817. playerWitcher.BlockSignSelection(ST_Aard, false);
  818. }
  819. break;
  820. case ST_Axii :
  821. if ( !IsRadialSlotBlocked ( 'Axii') )
  822. {
  823. playerWitcher.BlockSignSelection(ST_Axii, false );
  824. }
  825. break;
  826. case ST_Igni :
  827. if ( !IsRadialSlotBlocked ( 'Igni') )
  828. {
  829. playerWitcher.BlockSignSelection(ST_Igni, false );
  830. }
  831. break;
  832. case ST_Quen :
  833. if ( !IsRadialSlotBlocked ( 'Quen') )
  834. {
  835. playerWitcher.BlockSignSelection(ST_Quen, false );
  836. }
  837. break;
  838. case ST_Yrden :
  839. if ( !IsRadialSlotBlocked ( 'Yrden') )
  840. {
  841. playerWitcher.BlockSignSelection(ST_Yrden, false );
  842. }
  843. break;
  844. default:
  845. break;
  846. }
  847. }
  848. }*/
  849.  
  850. }
  851.  
  852. public function RestoreBlockedSlots ()
  853. {
  854. var i : int;
  855. var slotsToBlock : array<name>;
  856.  
  857. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  858. {
  859. slotsToBlock.PushBack ( blockedRadialSlots[i].slotName );
  860. }
  861. if ( slotsToBlock.Size() > 0 )
  862. {
  863. EnableRadialSlots ( false, slotsToBlock );
  864. }
  865. }
  866. private function DisableRadialSlot ( slotName : name, sourceName : name ) : bool
  867. {
  868. var i : int;
  869. var k : int;
  870. var slotsToBlock : array<name>;
  871.  
  872. var blockedRadialSlotEntry : SRadialSlotDef;
  873.  
  874. slotsToBlock.PushBack ( slotName );
  875.  
  876. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  877. {
  878. if ( blockedRadialSlots[i].slotName == slotName )
  879. {
  880. if ( sourceName != '' )
  881. {
  882. for ( k = 0; k < blockedRadialSlots[i].disabledBySources.Size(); k += 1 )
  883. {
  884. if ( blockedRadialSlots[i].disabledBySources[k] == sourceName )
  885. {
  886. return false;
  887. }
  888. }
  889. blockedRadialSlots[i].disabledBySources.PushBack ( sourceName );
  890. return false;
  891. }
  892.  
  893. return false;
  894. }
  895. }
  896.  
  897. blockedRadialSlotEntry = InitBlockedRadialSlotEntry ( slotName );
  898.  
  899. if ( sourceName != '' )
  900. {
  901. blockedRadialSlotEntry.disabledBySources.PushBack ( sourceName );
  902. }
  903. blockedRadialSlots.PushBack ( blockedRadialSlotEntry );
  904. EnableRadialSlots ( false, slotsToBlock );
  905. return true;
  906. }
  907.  
  908. public function EnableRadialSlot ( slotName : name, sourceName : name ) : bool
  909. {
  910. var i : int;
  911. var k : int;
  912.  
  913. var slotsToBlock : array<name>;
  914.  
  915. slotsToBlock.PushBack ( slotName );
  916.  
  917. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  918. {
  919. if ( blockedRadialSlots[i].slotName == slotName )
  920. {
  921.  
  922. if ( sourceName != '' )
  923. {
  924. for ( k = 0; k < blockedRadialSlots[i].disabledBySources.Size(); k += 1 )
  925. {
  926. if ( blockedRadialSlots[i].disabledBySources[k] == sourceName )
  927. {
  928. blockedRadialSlots[i].disabledBySources.Remove ( blockedRadialSlots[i].disabledBySources[k] );
  929. }
  930. }
  931. }
  932. if ( blockedRadialSlots[i].disabledBySources.Size() <= 0 )
  933. {
  934. blockedRadialSlots.Remove( blockedRadialSlots[i] );
  935. EnableRadialSlots ( true, slotsToBlock );
  936. return true;
  937. }
  938. return false;
  939. }
  940. }
  941. return false;
  942.  
  943. }
  944.  
  945. private function InitBlockedRadialSlotEntry ( slotName : name ) : SRadialSlotDef
  946. {
  947. var blockedRadialSlotEntry : SRadialSlotDef;
  948.  
  949. blockedRadialSlotEntry.slotName = slotName;
  950.  
  951. return blockedRadialSlotEntry;
  952.  
  953. }
  954.  
  955. public function EnableRadialSlotsWithSource ( enable : bool, slotsToBlock : array < name >, sourceName : name )
  956. {
  957. var i : int;
  958.  
  959. for ( i = 0; i < slotsToBlock.Size(); i+=1 )
  960. {
  961. if ( enable )
  962. {
  963. EnableRadialSlot ( slotsToBlock[i], sourceName );
  964. }
  965. else
  966. {
  967. DisableRadialSlot ( slotsToBlock[i], sourceName );
  968. }
  969. }
  970. if ( blockedRadialSlots.Size() <= 0 )
  971. {
  972. blockedRadialSlots.Clear();
  973. }
  974. }
  975.  
  976. public function IsRadialSlotBlocked ( slotName : name ) : bool
  977. {
  978. var i : int;
  979.  
  980. for ( i = 0; i < blockedRadialSlots.Size(); i+=1 )
  981. {
  982. if ( blockedRadialSlots[i].slotName == slotName )
  983. {
  984. return true;
  985. }
  986. }
  987. return false;
  988. }
  989.  
  990.  
  991. /////////////////////////////////////////////////////////////////////
  992. ////////////////////////////////////////////////////////////////////
  993. /////////////////////// @Reapir Kits ////////////////////////////////////
  994. ////////////////////////////////////////////////////////////////////
  995. public function RepairItem ( rapairKitId : SItemUniqueId, usedOnItem : SItemUniqueId );
  996. public function HasRepairAbleGearEquiped () : bool;
  997. public function HasRepairAbleWaponEquiped () : bool;
  998. public function IsItemRepairAble ( item : SItemUniqueId ) : bool;
  999.  
  1000. /////////////////////////////////////////////////////////////////////
  1001. ////////////////////////////////////////////////////////////////////
  1002. /////////////////////// @OILS ////////////////////////////////////
  1003. ////////////////////////////////////////////////////////////////////
  1004.  
  1005. public final function ReduceAllOilsAmmo( id : SItemUniqueId )
  1006. {
  1007. var i : int;
  1008. var oils : array< W3Effect_Oil >;
  1009.  
  1010. oils = inv.GetOilsAppliedOnItem( id );
  1011.  
  1012. for( i=0; i<oils.Size(); i+=1 )
  1013. {
  1014. oils[ i ].ReduceAmmo();
  1015. }
  1016. }
  1017.  
  1018. public final function ResumeOilBuffs( steel : bool )
  1019. {
  1020. var item : SItemUniqueId;
  1021. var oils : array< CBaseGameplayEffect >;
  1022. var buff, recentOil : W3Effect_Oil;
  1023. var i : int;
  1024.  
  1025. item = GetEquippedSword( steel );
  1026. oils = GetBuffs( EET_Oil );
  1027.  
  1028. if( oils.Size() > 1 )
  1029. {
  1030. //if we have more than 1 oil applied on sword, we need to resume most recent one as the last one
  1031. //in order to show proper oil color on the blade
  1032. recentOil = inv.GetNewestOilAppliedOnItem( item, false );
  1033. }
  1034.  
  1035. for( i=0; i<oils.Size(); i+=1 )
  1036. {
  1037. buff = ( W3Effect_Oil ) oils[ i ];
  1038.  
  1039. if( recentOil && recentOil == buff )
  1040. {
  1041. continue;
  1042. }
  1043.  
  1044. if(buff && buff.GetSwordItemId() == item )
  1045. {
  1046. buff.Resume( '' );
  1047. }
  1048. }
  1049.  
  1050. if( recentOil )
  1051. {
  1052. recentOil.Resume( '' );
  1053. }
  1054. }
  1055.  
  1056. protected final function PauseOilBuffs( isSteel : bool )
  1057. {
  1058. var item : SItemUniqueId;
  1059. var oils : array< CBaseGameplayEffect >;
  1060. var buff : W3Effect_Oil;
  1061. var i : int;
  1062.  
  1063. item = GetEquippedSword( isSteel );
  1064. oils = GetBuffs( EET_Oil );
  1065.  
  1066. for( i=0; i<oils.Size(); i+=1 )
  1067. {
  1068. buff = ( W3Effect_Oil ) oils[ i ];
  1069. if(buff && buff.GetSwordItemId() == item )
  1070. {
  1071. buff.Pause( '', true );
  1072. }
  1073. }
  1074. }
  1075.  
  1076. public final function ManageAerondightBuff( apply : bool )
  1077. {
  1078. var aerondight : W3Effect_Aerondight;
  1079. var item : SItemUniqueId;
  1080.  
  1081. item = inv.GetCurrentlyHeldSword();
  1082.  
  1083. if( inv.ItemHasTag( item, 'Aerondight' ) )
  1084. {
  1085. aerondight = (W3Effect_Aerondight)GetBuff( EET_Aerondight );
  1086.  
  1087. if( apply )
  1088. {
  1089. if( !aerondight )
  1090. {
  1091. AddEffectDefault( EET_Aerondight, this, "Aerondight" );
  1092. }
  1093. else
  1094. {
  1095. aerondight.Resume( 'ManageAerondightBuff' );
  1096. }
  1097. }
  1098. else
  1099. {
  1100. aerondight.Pause( 'ManageAerondightBuff' );
  1101. }
  1102. }
  1103. }
  1104.  
  1105. //applies oil on given player item
  1106. public function ApplyOil( oilId : SItemUniqueId, usedOnItem : SItemUniqueId ) : bool
  1107. {
  1108. var oilAbilities : array< name >;
  1109. var ammo, ammoBonus : float;
  1110. var dm : CDefinitionsManagerAccessor;
  1111. var buffParams : SCustomEffectParams;
  1112. var oilParams : W3OilBuffParams;
  1113. var oilName : name;
  1114. var min, max : SAbilityAttributeValue;
  1115. var i : int;
  1116. var oils : array< W3Effect_Oil >;
  1117. var existingOil : W3Effect_Oil;
  1118.  
  1119. if( !CanApplyOilOnItem( oilId, usedOnItem ) )
  1120. {
  1121. return false;
  1122. }
  1123.  
  1124. dm = theGame.GetDefinitionsManager();
  1125. inv.GetItemAbilitiesWithTag( oilId, theGame.params.OIL_ABILITY_TAG, oilAbilities );
  1126. oilName = inv.GetItemName( oilId );
  1127. oils = inv.GetOilsAppliedOnItem( usedOnItem );
  1128.  
  1129. //check if oil is already applied
  1130. for( i=0; i<oils.Size(); i+=1 )
  1131. {
  1132. if( oils[ i ].GetOilItemName() == oilName )
  1133. {
  1134. existingOil = oils[ i ];
  1135. break;
  1136. }
  1137. }
  1138.  
  1139. //remove previous oil
  1140. if( !existingOil )
  1141. {
  1142. if( !GetWitcherPlayer() || !GetWitcherPlayer().IsSetBonusActive( EISB_Wolf_1 ) )
  1143. {
  1144. inv.RemoveAllOilsFromItem( usedOnItem );
  1145. }
  1146. else
  1147. {
  1148. dm.GetAbilityAttributeValue( GetSetBonusAbility( EISB_Wolf_1 ), 'max_oils_count', min, max );
  1149. if( inv.GetActiveOilsAppliedOnItemCount( usedOnItem ) >= CalculateAttributeValue( max ) )
  1150. {
  1151. inv.RemoveOldestOilFromItem( usedOnItem );
  1152. }
  1153. }
  1154. }
  1155.  
  1156. //set charges
  1157. ammo = CalculateAttributeValue(inv.GetItemAttributeValue(oilId, 'ammo'));
  1158. if(CanUseSkill(S_Alchemy_s06))
  1159. {
  1160. ammoBonus = CalculateAttributeValue(GetSkillAttributeValue(S_Alchemy_s06, 'ammo_bonus', false, false));
  1161. ammo *= 1 + ammoBonus * GetSkillLevel(S_Alchemy_s06);
  1162. }
  1163.  
  1164. //add new oil
  1165. if( existingOil )
  1166. {
  1167. existingOil.Reapply( RoundMath( ammo ) );
  1168. }
  1169. else
  1170. {
  1171. buffParams.effectType = EET_Oil;
  1172. buffParams.creator = this;
  1173. oilParams = new W3OilBuffParams in this;
  1174. oilParams.iconPath = dm.GetItemIconPath( oilName );
  1175. oilParams.localizedName = dm.GetItemLocalisationKeyName( oilName );
  1176. oilParams.localizedDescription = dm.GetItemLocalisationKeyName( oilName );
  1177. oilParams.sword = usedOnItem;
  1178. oilParams.maxCount = RoundMath( ammo );
  1179. oilParams.currCount = RoundMath( ammo );
  1180. oilParams.oilAbilityName = oilAbilities[ 0 ];
  1181. oilParams.oilItemName = oilName;
  1182. buffParams.buffSpecificParams = oilParams;
  1183.  
  1184. AddEffectCustom( buffParams );
  1185.  
  1186. delete oilParams;
  1187. }
  1188.  
  1189. LogOils("Added oil <<" + oilName + ">> to <<" + inv.GetItemName( usedOnItem ) + ">>");
  1190.  
  1191. //fundamentals first achievement
  1192. SetFailedFundamentalsFirstAchievementCondition( true );
  1193.  
  1194. theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnOilApplied );
  1195.  
  1196. if( !inv.IsItemHeld( usedOnItem ) )
  1197. {
  1198. PauseOilBuffs( inv.IsItemSteelSwordUsableByPlayer( usedOnItem ) );
  1199. }
  1200.  
  1201. return true;
  1202. }
  1203.  
  1204. // Returns true if given sword type is upgraded with given oil
  1205. public final function IsEquippedSwordUpgradedWithOil(steel : bool, optional oilName : name) : bool
  1206. {
  1207. var sword : SItemUniqueId;
  1208. var i : int;
  1209. var oils : array< W3Effect_Oil >;
  1210.  
  1211. sword = GetEquippedSword( steel );
  1212. if( !inv.IsIdValid( sword ) )
  1213. {
  1214. return false;
  1215. }
  1216.  
  1217. if( oilName == '' )
  1218. {
  1219. return inv.ItemHasAnyActiveOilApplied( sword );
  1220. }
  1221.  
  1222. oils = inv.GetOilsAppliedOnItem( sword );
  1223. for( i=0; i<oils.Size(); i+=1 )
  1224. {
  1225. if( oils[ i ].GetOilItemName() == oilName )
  1226. {
  1227. return true;
  1228. }
  1229. }
  1230.  
  1231. return false;
  1232. }
  1233.  
  1234. public function CanApplyOilOnItem(oilId : SItemUniqueId, usedOnItem : SItemUniqueId) : bool
  1235. {
  1236. if(inv.ItemHasTag(oilId, theGame.params.TAG_STEEL_OIL) && inv.IsItemSteelSwordUsableByPlayer(usedOnItem))
  1237. return true;
  1238.  
  1239. if(inv.ItemHasTag(oilId, theGame.params.TAG_SILVER_OIL) && inv.IsItemSilverSwordUsableByPlayer(usedOnItem))
  1240. return true;
  1241.  
  1242. return false;
  1243. }
  1244. ////////////////////////////////////////////////////////////////////
  1245.  
  1246. public final function DidFailFundamentalsFirstAchievementCondition() : bool
  1247. {
  1248. return failedFundamentalsFirstAchievementCondition;
  1249. }
  1250.  
  1251. public final function SetFailedFundamentalsFirstAchievementCondition(b : bool)
  1252. {
  1253. var i : int;
  1254. var npc : CNewNPC;
  1255.  
  1256. failedFundamentalsFirstAchievementCondition = b;
  1257.  
  1258. //save info in enemy since we might run away from combat and return, triggering new combat encounter
  1259. if(failedFundamentalsFirstAchievementCondition)
  1260. {
  1261. for(i=0; i<hostileEnemies.Size(); i+=1)
  1262. {
  1263. if(hostileEnemies[i].HasTag(theGame.params.MONSTER_HUNT_ACTOR_TAG))
  1264. {
  1265. npc = (CNewNPC)hostileEnemies[i];
  1266. npc.AddTag('failedFundamentalsAchievement');
  1267. npc.AddTimer('FundamentalsAchFailTimer', 30*60, , , , true, true);
  1268. }
  1269. }
  1270. }
  1271. }
  1272.  
  1273. public function IsInCombatFist() : bool
  1274. {
  1275. return this.GetCurrentStateName() == 'CombatFists';
  1276. }
  1277.  
  1278. public function IsInitialized() : bool;
  1279.  
  1280. public function IsCiri() : bool
  1281. {
  1282. return ((W3ReplacerCiri)this);
  1283. }
  1284.  
  1285. protected function WouldLikeToMove() : bool
  1286. {
  1287. var speedVec : Vector;
  1288. var speed, speedMult : float;
  1289.  
  1290. // Get speed from input
  1291. speedVec.X = theInput.GetActionValue( 'GI_AxisLeftX' ); //player.mainInput.aLeftJoyX;
  1292. speedVec.Y = theInput.GetActionValue( 'GI_AxisLeftY' );//player.mainInput.aLeftJoyY;
  1293. speed = VecLength2D( speedVec );
  1294.  
  1295. return speed > 0.1f;
  1296. }
  1297.  
  1298. function HandleMovement( deltaTime : float )
  1299. {
  1300. // just to see if player would like to move if there would be possibility
  1301. // example of use: movement is blocked when in critical state, but it can end earlier only if it would be desired by player
  1302. // and this is nothing but desire to move
  1303. // note: for some reason, when doing WouldLikeToMove()? 1.0f : 0.0f it just doesn't care and gives 0.0f
  1304. if (WouldLikeToMove())
  1305. SetBehaviorVariable( 'playerWouldLikeToMove', 1.0f);
  1306. else
  1307. SetBehaviorVariable( 'playerWouldLikeToMove', 0.0f);
  1308.  
  1309. super.HandleMovement( deltaTime );
  1310. }
  1311.  
  1312. function BattleCryIsReady( ) : bool
  1313. {
  1314. var l_currentTime : float;
  1315.  
  1316. l_currentTime = theGame.GetEngineTimeAsSeconds();
  1317.  
  1318. if( l_currentTime >= battlecry_timeForNext )
  1319. {
  1320. return true;
  1321. }
  1322. return false;
  1323. }
  1324.  
  1325. function PlayBattleCry( _BattleCry : name , _Chance : float, optional _IgnoreDelay, ignoreRepeatCheck : bool )
  1326. {
  1327. var l_randValue : float;
  1328. var fact : int;
  1329.  
  1330. fact = FactsQuerySum("force_stance_normal");
  1331.  
  1332. if( IsSwimming()
  1333. || theGame.IsDialogOrCutscenePlaying()
  1334. || IsInNonGameplayCutscene()
  1335. || IsInGameplayScene()
  1336. || theGame.IsCurrentlyPlayingNonGameplayScene()
  1337. || theGame.IsFading()
  1338. || theGame.IsBlackscreen()
  1339. || FactsQuerySum("force_stance_normal") > 0 )
  1340. {
  1341. return;
  1342. }
  1343.  
  1344. // To avoid calling too often the same type of battle cry
  1345. if ( !ignoreRepeatCheck )
  1346. {
  1347. if( battlecry_lastTry == _BattleCry )
  1348. return;
  1349. }
  1350.  
  1351. battlecry_lastTry = _BattleCry;
  1352.  
  1353. l_randValue = RandF();
  1354.  
  1355. // Either use delay or chance
  1356. if( l_randValue < _Chance && ( _IgnoreDelay || BattleCryIsReady() ) )
  1357. {
  1358. thePlayer.PlayVoiceset( 90, _BattleCry );
  1359. // Restart counter
  1360. battlecry_timeForNext = theGame.GetEngineTimeAsSeconds() + RandRangeF( battlecry_delayMax, battlecry_delayMin );
  1361. }
  1362.  
  1363. }
  1364.  
  1365. public final function OnWeatherChanged()
  1366. {
  1367. if( IsInInterior()
  1368. || GetCurrentStateName() != 'Exploration'
  1369. || theGame.IsDialogOrCutscenePlaying()
  1370. || IsInNonGameplayCutscene()
  1371. || IsInGameplayScene()
  1372. || theGame.IsCurrentlyPlayingNonGameplayScene()
  1373. || theGame.IsFading()
  1374. || theGame.IsBlackscreen()
  1375. || GetTimeSinceSpawned() < 60 )
  1376. {
  1377. return;
  1378. }
  1379.  
  1380. AddTimer( 'CommentOnWeather', 1 );
  1381. }
  1382.  
  1383. public final timer function CommentOnWeather( _Delta : float, _Id : int )
  1384. {
  1385. var l_weather : name;
  1386. var l_currentArea : EAreaName;
  1387. var l_rand : float;
  1388.  
  1389. l_weather = GetWeatherConditionName();
  1390.  
  1391. l_currentArea = theGame.GetCommonMapManager().GetCurrentArea();
  1392.  
  1393. switch ( l_weather )
  1394. {
  1395. case 'WT_Clear':
  1396.  
  1397. l_rand = RandF();
  1398.  
  1399. if( l_rand > 0.66f && !AreaIsCold() && theGame.envMgr.IsDay() )
  1400. {
  1401. thePlayer.PlayVoiceset( 90, 'WeatherHot' );
  1402. }
  1403. else if ( l_rand > 0.33f )
  1404. {
  1405. thePlayer.PlayVoiceset( 90, 'WeatherClearingUp' );
  1406. }
  1407. break;
  1408.  
  1409. case 'WT_Rain_Storm':
  1410. thePlayer.PlayVoiceset( 90, 'WeatherStormy' );
  1411. break;
  1412.  
  1413. case 'WT_Light_Clouds':
  1414. if( previousRainStrength < GetRainStrength() )
  1415. {
  1416. thePlayer.PlayVoiceset( 90, 'WeatherLooksLikeRain' );
  1417. }
  1418. else if( AreaIsCold() && previousWeather == 'WT_Clear' )
  1419. {
  1420. thePlayer.PlayVoiceset( 90, 'WeatherCold' );
  1421. }
  1422. break;
  1423.  
  1424. case 'WT_Mid_Clouds':
  1425. if( previousRainStrength < GetRainStrength() )
  1426. {
  1427. thePlayer.PlayVoiceset( 90, 'WeatherRaining' );
  1428. }
  1429. else if( AreaIsCold() && previousWeather == 'WT_Clear' )
  1430. {
  1431. thePlayer.PlayVoiceset( 90, 'WeatherCold' );
  1432. }
  1433. break;
  1434.  
  1435. case 'WT_Mid_Clouds_Dark':
  1436. if( previousWeather != 'WT_Heavy_Clouds' && previousWeather != 'WT_Heavy_Clouds_Dark' )
  1437. thePlayer.PlayVoiceset( 90, 'WeatherWindy' );
  1438. break;
  1439.  
  1440. case 'WT_Heavy_Clouds':
  1441. if( previousWeather != 'WT_Mid_Clouds_Dark' && previousWeather != 'WT_Heavy_Clouds_Dark' )
  1442. thePlayer.PlayVoiceset( 90, 'WeatherWindy' );
  1443. break;
  1444.  
  1445. case 'WT_Heavy_Clouds_Dark':
  1446. if( thePlayer.IsOnBoat() )
  1447. {
  1448. thePlayer.PlayVoiceset( 90, 'WeatherSeaWillStorm' );
  1449. }
  1450. else if( previousRainStrength < GetRainStrength() )
  1451. {
  1452. thePlayer.PlayVoiceset( 90, 'WeatherLooksLikeRain' );
  1453. }
  1454. else
  1455. {
  1456. thePlayer.PlayVoiceset( 90, 'WeatherWindy' );
  1457. }
  1458. break;
  1459.  
  1460. case 'WT_Snow':
  1461. if( RandF() > 0.5f )
  1462. thePlayer.PlayVoiceset( 90, 'WeatherSnowy' );
  1463. else
  1464. thePlayer.PlayVoiceset( 90, 'WeatherCold' );
  1465. break;
  1466. }
  1467.  
  1468. previousRainStrength = GetRainStrength();
  1469. previousWeather = l_weather;
  1470. }
  1471.  
  1472. function CanUpdateMovement() : bool
  1473. {
  1474. if ( rangedWeapon
  1475. && GetBehaviorVariable( 'fullBodyAnimWeight' ) >= 1.f
  1476. && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  1477. return false;
  1478.  
  1479. return true;
  1480. }
  1481.  
  1482. public function SetDefaultLocomotionController()
  1483. {
  1484. if( !defaultLocomotionController )
  1485. {
  1486. defaultLocomotionController = new CR4LocomotionPlayerControllerScript in this;
  1487. }
  1488.  
  1489. ActionDirectControl( defaultLocomotionController );
  1490. }
  1491.  
  1492. event OnPlayerTickTimer( deltaTime : float )
  1493. {
  1494. var focusModeController : CFocusModeController;
  1495. var cnt : int;
  1496.  
  1497. super.OnPlayerTickTimer( deltaTime );
  1498.  
  1499. HandleMovement( deltaTime );
  1500.  
  1501. if ( playerAiming.GetCurrentStateName() == 'Aiming' )
  1502. {
  1503. FindTarget();
  1504. FindNonActorTarget( false );
  1505. UpdateDisplayTarget();
  1506. UpdateLookAtTarget();
  1507. }
  1508. else
  1509. {
  1510. if( playerTickTimerPhase == 0 )
  1511. {
  1512. FindTarget();
  1513. }
  1514. else if( playerTickTimerPhase == 1 )
  1515. {
  1516. FindNonActorTarget( false );
  1517. }
  1518. else if ( playerTickTimerPhase == 2 )
  1519. {
  1520. UpdateDisplayTarget();
  1521. UpdateLookAtTarget();
  1522. }
  1523. }
  1524.  
  1525. //CombatModeDebug();
  1526.  
  1527. playerTickTimerPhase = ( playerTickTimerPhase + 1 ) % 3;
  1528.  
  1529. focusModeController = theGame.GetFocusModeController();
  1530. focusModeController.UpdateFocusInteractions( deltaTime );
  1531.  
  1532. //some behavior hack for critical states, moved from effectsManager.PerformUpdate() since it does not tick continuously anymore
  1533. cnt = (int)( effectManager.GetCriticalBuffsCount() > 0 );
  1534. SetBehaviorVariable('hasCriticalBuff', cnt);
  1535. }
  1536.  
  1537. event OnDeath( damageAction : W3DamageAction )
  1538. {
  1539. super.OnDeath( damageAction );
  1540.  
  1541. RemoveTimer('RequestCriticalAnimStart');
  1542. //theInput.SetContext('Death');
  1543. EnableFindTarget( false );
  1544. BlockAllActions('Death', true);
  1545.  
  1546. EnableHardLock( false );
  1547.  
  1548. theGame.CreateNoSaveLock( 'player_death', deathNoSaveLock, false, false );
  1549. theGame.SetDeathSaveLockId( deathNoSaveLock );
  1550.  
  1551. ClearHostileEnemiesList();
  1552. RemoveReactions();
  1553. SetPlayerCombatTarget(NULL);
  1554. OnEnableAimingMode( false );
  1555.  
  1556. theGame.EnableFreeCamera( false );
  1557. }
  1558.  
  1559. // Called when the actor gets out of unconscious state
  1560. function OnRevived()
  1561. {
  1562. super.OnRevived();
  1563. BlockAllActions('Death', false);
  1564.  
  1565. theGame.ReleaseNoSaveLock(deathNoSaveLock);
  1566.  
  1567. this.RestartReactionsIfNeeded();
  1568. }
  1569.  
  1570. public function CanStartTalk() : bool
  1571. {
  1572. if ( beingWarnedBy.Size() > 0 )
  1573. return false;
  1574.  
  1575. return super.CanStartTalk();
  1576. }
  1577.  
  1578. ///////////////////////////////////////////////////////////////////////////
  1579. // @Counters
  1580. ///////////////////////////////////////////////////////////////////////////
  1581.  
  1582. //caches timestamp of counter use (button press)
  1583. public function AddCounterTimeStamp(time : EngineTime) {counterTimestamps.PushBack(time);}
  1584.  
  1585. /*
  1586. This function checks if we have performed a counter
  1587. It checks timestamps of moments when we pressed the parry/counter button in order
  1588. to determine if the player was spamming the button. If so then this is not a counter.
  1589.  
  1590. Returns true if the counter is valid
  1591. */
  1592. public function CheckCounterSpamming(attacker : CActor) : bool
  1593. {
  1594. var counterWindowStartTime : EngineTime; //the time when the counter window (in anim) started
  1595. var i, spamCounter : int;
  1596. var reflexAction : bool;
  1597. var testEngineTime : EngineTime;
  1598.  
  1599. if(!attacker)
  1600. return false;
  1601.  
  1602. counterWindowStartTime = ((CNewNPC)attacker).GetCounterWindowStartTime();
  1603. spamCounter = 0;
  1604. reflexAction = false;
  1605.  
  1606. //if counterWindowStartTime was never set return false - PF
  1607. if ( counterWindowStartTime == testEngineTime )
  1608. {
  1609. return false;
  1610. }
  1611.  
  1612. for(i = counterTimestamps.Size() - 1; i>=0; i-=1)
  1613. {
  1614. //log number of button presses since 0.4 seconds before the counter timewindow
  1615. if(counterTimestamps[i] >= (counterWindowStartTime - EngineTimeFromFloat(0.4)) )
  1616. {
  1617. spamCounter += 1;
  1618. }
  1619. //and at the same time remove all outdated data on the fly
  1620. else
  1621. {
  1622. counterTimestamps.Remove(counterTimestamps[i]);
  1623. continue;
  1624. }
  1625.  
  1626. //set info that we have a potential parry if this press was after the counter timewindow started
  1627. if(!reflexAction && (counterTimestamps[i] >= counterWindowStartTime))
  1628. reflexAction = true;
  1629. }
  1630.  
  1631. /*
  1632. If reflexAction is set then we have at least 1 button press within the counter timewindow.
  1633.  
  1634. As for the spam counter:
  1635. 0 means no button was pressed - no counter
  1636. 1 means exactly one button press - a potential counter (if reflexAction is set as well)
  1637. >1 means spamming
  1638. */
  1639. if(spamCounter == 1 && reflexAction)
  1640. return true;
  1641.  
  1642. return false;
  1643. }
  1644.  
  1645. protected function PerformCounterCheck(parryInfo: SParryInfo) : bool
  1646. {
  1647. var mult : float;
  1648. var parryType : EParryType;
  1649. var validCounter, useKnockdown : bool;
  1650. var slideDistance, duration : float;
  1651. var playerToTargetRot : EulerAngles;
  1652. var zDifference, mutation8TriggerHP : float;
  1653. var effectType : EEffectType;
  1654. var repelType : EPlayerRepelType = PRT_Random;
  1655. var params : SCustomEffectParams;
  1656. var thisPos, attackerPos : Vector;
  1657. var fistFightCheck, isMutation8 : bool;
  1658. var fistFightCounter : bool;
  1659. var attackerInventory : CInventoryComponent;
  1660. var weaponId : SItemUniqueId;
  1661. var weaponTags : array<name>;
  1662. var playerToAttackerVector : Vector;
  1663. var tracePosStart : Vector;
  1664. var tracePosEnd : Vector;
  1665. var hitPos : Vector;
  1666. var hitNormal : Vector;
  1667. var min, max : SAbilityAttributeValue;
  1668. var npc : CNewNPC;
  1669.  
  1670. if(ShouldProcessTutorial('TutorialDodge') || ShouldProcessTutorial('TutorialCounter'))
  1671. {
  1672. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) );
  1673. FactsRemove("tut_fight_slomo_ON");
  1674. }
  1675.  
  1676. if ( !parryInfo.canBeParried || parryInfo.attacker.HasAbility( 'CannotBeCountered' ) )
  1677. return false;
  1678.  
  1679. fistFightCheck = FistFightCheck( parryInfo.target, parryInfo.attacker, fistFightCounter );
  1680.  
  1681. if( ParryCounterCheck() && parryInfo.targetToAttackerAngleAbs < theGame.params.PARRY_HALF_ANGLE && fistFightCheck )
  1682. {
  1683. //check if this is a valid counter
  1684. validCounter = CheckCounterSpamming(parryInfo.attacker);
  1685.  
  1686. if(validCounter)
  1687. {
  1688. if ( IsInCombatActionFriendly() )
  1689. RaiseEvent('CombatActionFriendlyEnd');
  1690.  
  1691. SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) );
  1692. SetBehaviorVariable( 'counter', (float)validCounter); //1/true when the parry is a counter/reflex_parry
  1693.  
  1694. //PPPP counter success sound
  1695. //SoundEvent("global_machines_lift_wood1_mechanism_stop" );
  1696. SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) );
  1697. SetBehaviorVariable( 'counter', (float)validCounter); //1/true when the parry is a counter/reflex_parry
  1698. this.SetBehaviorVariable( 'combatActionType', (int)CAT_Parry );
  1699.  
  1700.  
  1701. if ( !fistFightCounter )
  1702. {
  1703. attackerInventory = parryInfo.attacker.GetInventory();
  1704. weaponId = attackerInventory.GetItemFromSlot('r_weapon');
  1705. attackerInventory.GetItemTags( weaponId , weaponTags );
  1706.  
  1707. if( GetWitcherPlayer().IsMutationActive( EPMT_Mutation8 ) )
  1708. {
  1709. isMutation8 = true;
  1710. theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation8', 'hp_perc_trigger', min, max );
  1711. mutation8TriggerHP = min.valueMultiplicative;
  1712. }
  1713.  
  1714. /*if( parryInfo.attacker.HasTag( 'olgierd_gpl' ) && parryInfo.attackActionName == 'attack_heavy' )
  1715. {
  1716. //DealCounterDamageToOlgierd();
  1717. GetTarget().AddAbility( 'HitCounterEnabled', false );
  1718. GetTarget().AddTimer( 'DisableHitCounterAfter', 3.0 );
  1719. }*/
  1720.  
  1721. npc = (CNewNPC)parryInfo.attacker;
  1722.  
  1723. //don't look at me like that. It is NOT a hack... follow the white rabbit...
  1724. if ( parryInfo.attacker.HasAbility('mon_gravehag') )
  1725. {
  1726. repelType = PRT_Slash;
  1727. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, 'ReflexParryPerformed');
  1728. //parryInfo.attacker.RemoveAbility('TongueAttack');
  1729. }
  1730. else if ( npc && !npc.IsHuman() && !npc.HasTag( 'dettlaff_vampire' ) )
  1731. {
  1732. repelType = PRT_SideStepSlash;
  1733. }
  1734. else if ( weaponTags.Contains('spear2h') )
  1735. {
  1736. repelType = PRT_SideStepSlash;
  1737. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed");
  1738. parryInfo.attacker.SignalGameplayEvent( 'SpearDestruction');
  1739. }
  1740. else if( isMutation8 && npc && !npc.IsImmuneToMutation8Finisher() )
  1741. {
  1742. repelType = PRT_RepelToFinisher;
  1743. npc.AddEffectDefault( EET_CounterStrikeHit, this, "ReflexParryPerformed" );
  1744.  
  1745. //finishers are performed on current target
  1746. SetTarget( npc, true );
  1747.  
  1748. PerformFinisher( 0.f, 0 );
  1749. }
  1750. else
  1751. {
  1752. //-----pitch check------
  1753. thisPos = this.GetWorldPosition();
  1754. attackerPos = parryInfo.attacker.GetWorldPosition();
  1755. playerToTargetRot = VecToRotation( thisPos - attackerPos );
  1756. zDifference = thisPos.Z - attackerPos.Z;
  1757.  
  1758. if ( playerToTargetRot.Pitch < -5.f && zDifference > 0.35 )
  1759. {
  1760. repelType = PRT_Kick;
  1761. //Pass attacker to the timer so that he ragdolls after a delay
  1762. ragdollTarget = parryInfo.attacker;
  1763. AddTimer( 'ApplyCounterRagdollTimer', 0.3 );
  1764. }
  1765. else
  1766. {
  1767. useKnockdown = false;
  1768. if ( CanUseSkill(S_Sword_s11) )
  1769. {
  1770. if( GetSkillLevel(S_Sword_s11) > 1 && RandRangeF(3,0) < GetWitcherPlayer().GetStat(BCS_Focus) )//CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s11, 'chance', false, true)) )
  1771. {
  1772. duration = CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s11, 'duration', false, true));
  1773. useKnockdown = true;
  1774. }
  1775. }
  1776. else if ( parryInfo.attacker.IsHuman() )
  1777. {
  1778. //Apply knockdown if npc is countered on ledge
  1779. tracePosStart = parryInfo.attacker.GetWorldPosition();
  1780. tracePosStart.Z += 1.f;
  1781. playerToAttackerVector = VecNormalize( parryInfo.attacker.GetWorldPosition() - parryInfo.target.GetWorldPosition() );
  1782. tracePosEnd = ( playerToAttackerVector * 0.75f ) + ( playerToAttackerVector * parryInfo.attacker.GetRadius() ) + parryInfo.attacker.GetWorldPosition();
  1783. tracePosEnd.Z += 1.f;
  1784.  
  1785. if ( !theGame.GetWorld().StaticTrace( tracePosStart, tracePosEnd, hitPos, hitNormal, counterCollisionGroupNames ) )
  1786. {
  1787. tracePosStart = tracePosEnd;
  1788. tracePosEnd -= 3.f;
  1789.  
  1790. if ( !theGame.GetWorld().StaticTrace( tracePosStart, tracePosEnd, hitPos, hitNormal, counterCollisionGroupNames ) )
  1791. useKnockdown = true;
  1792. }
  1793. }
  1794.  
  1795. if(useKnockdown && (!parryInfo.attacker.IsImmuneToBuff(EET_HeavyKnockdown) || !parryInfo.attacker.IsImmuneToBuff(EET_Knockdown)))
  1796. {
  1797. if(!parryInfo.attacker.IsImmuneToBuff(EET_HeavyKnockdown))
  1798. {
  1799. params.effectType = EET_HeavyKnockdown;
  1800. }
  1801. else
  1802. {
  1803. params.effectType = EET_Knockdown;
  1804. }
  1805.  
  1806. repelType = PRT_Kick;
  1807. params.creator = this;
  1808. params.sourceName = "ReflexParryPerformed";
  1809. params.duration = duration;
  1810.  
  1811. parryInfo.attacker.AddEffectCustom(params);
  1812. }
  1813. else
  1814. {
  1815. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed");
  1816. }
  1817. }
  1818. }
  1819.  
  1820. parryInfo.attacker.GetInventory().PlayItemEffect(parryInfo.attackerWeaponId, 'counterattack');
  1821.  
  1822. //by default repelType is PRT_Random
  1823. if ( repelType == PRT_Random )
  1824. if ( RandRange(100) > 50 )
  1825. repelType = PRT_Bash;
  1826. else
  1827. repelType = PRT_Kick;
  1828.  
  1829. this.SetBehaviorVariable( 'repelType', (int)repelType );
  1830. parryInfo.attacker.SetBehaviorVariable( 'repelType', (int)repelType );
  1831. }
  1832. else
  1833. {
  1834. parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed");
  1835. }
  1836.  
  1837. //SetCustomOrientationTargetForCombatActions( OT_None );
  1838. SetParryTarget ( parryInfo.attacker );
  1839. SetSlideTarget( parryInfo.attacker );
  1840. if ( !IsActorLockedToTarget() )
  1841. SetMoveTarget( parryInfo.attacker );
  1842.  
  1843. if ( RaiseForceEvent( 'PerformCounter' ) )
  1844. OnCombatActionStart();
  1845.  
  1846. SetCustomRotation( 'Counter', VecHeading( parryInfo.attacker.GetWorldPosition() - this.GetWorldPosition() ), 0.0f, 0.2f, false );
  1847. AddTimer( 'UpdateCounterRotation', 0.4f, true );
  1848. AddTimer( 'SetCounterRotation', 0.2f );
  1849.  
  1850. IncreaseUninterruptedHitsCount(); //counters also count as uninterrupted hits
  1851.  
  1852. //drain stamina
  1853. if(IsHeavyAttack(parryInfo.attackActionName))
  1854. mult = theGame.params.HEAVY_STRIKE_COST_MULTIPLIER;
  1855.  
  1856. DrainStamina(ESAT_Counterattack, 0, 0, '', 0, mult);
  1857.  
  1858. theGame.GetGamerProfile().IncStat(ES_CounterattackChain);
  1859.  
  1860. }
  1861. else
  1862. {
  1863. ResetUninterruptedHitsCount();
  1864. }
  1865. return validCounter;
  1866. }
  1867.  
  1868. return false;
  1869. }
  1870.  
  1871. timer function UpdateCounterRotation( dt : float, id : int )
  1872. {
  1873. UpdateCustomRotationHeading( 'Counter', VecHeading( parryTarget.GetWorldPosition() - this.GetWorldPosition() ) );
  1874. }
  1875.  
  1876. timer function SetCounterRotation( dt : float, id : int )
  1877. {
  1878. SetCustomRotation( 'Counter', VecHeading( parryTarget.GetWorldPosition() - this.GetWorldPosition() ), 360.f, 0.2f, false );
  1879. }
  1880.  
  1881. private var parryTarget : CActor;
  1882. private function SetParryTarget( t : CActor )
  1883. {
  1884. parryTarget = t;
  1885. }
  1886.  
  1887. private var ragdollTarget : CActor;
  1888. timer function ApplyCounterRagdollTimer( time : float , id : int)
  1889. {
  1890. var actor : CActor;
  1891.  
  1892. actor = (CActor)ragdollTarget;
  1893.  
  1894. if(actor)
  1895. {
  1896. actor.AddEffectDefault(EET_HeavyKnockdown, this, 'ReflexParryPerformed');
  1897. }
  1898. }
  1899.  
  1900. ///////////////////////////////////////////////////////////////////////////
  1901. // Player Mode
  1902.  
  1903. public function EnableMode( mode : EPlayerMode, enable : bool )
  1904. {
  1905. playerMode.EnableMode( mode, enable );
  1906. }
  1907.  
  1908. public function GetPlayerMode() : W3PlayerMode
  1909. {
  1910. return playerMode;
  1911. }
  1912.  
  1913. private function GetClosestIncomingAttacker() : CActor
  1914. {
  1915. var i, size : int;
  1916. var attackerToPlayerDistances : array< float >;
  1917. var closestAttackerIndex : int;
  1918. var incomingAttackers : array<CActor>;
  1919.  
  1920. //incomingAttackers = this.combatManager.SendTicketOwners( CTT_Attack );
  1921. if(playerMode && playerMode.combatDataComponent)
  1922. {
  1923. if ( incomingAttackers.Size() <= 0 )
  1924. this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Charge' );
  1925.  
  1926. if ( incomingAttackers.Size() <= 0 )
  1927. this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Melee' );
  1928.  
  1929. if ( incomingAttackers.Size() <= 0 )
  1930. this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Range' );
  1931. }
  1932.  
  1933. size = incomingAttackers.Size();
  1934. attackerToPlayerDistances.Resize( size );
  1935.  
  1936. if ( size > 0 )
  1937. {
  1938. for ( i = incomingAttackers.Size()-1; i >= 0; i -= 1)
  1939. {
  1940. if ( !IsEnemyVisible( incomingAttackers[i] ) )
  1941. {
  1942. incomingAttackers.EraseFast( i );
  1943. }
  1944. }
  1945. }
  1946.  
  1947. if ( size > 0 )
  1948. {
  1949. for ( i = 0; i < size; i += 1 )
  1950. {
  1951. attackerToPlayerDistances[i] = VecDistance( incomingAttackers[i].GetWorldPosition(), this.GetWorldPosition() );
  1952. }
  1953. closestAttackerIndex = ArrayFindMinF( attackerToPlayerDistances );
  1954. return incomingAttackers[ closestAttackerIndex ];
  1955. }
  1956. else
  1957. {
  1958. return NULL;
  1959. }
  1960. }
  1961.  
  1962. // Combat Timer
  1963. timer function CombatCheck( time : float , id : int)
  1964. {
  1965. var i : int;
  1966. var strLevel, temp : string;
  1967. var enemies : array<CActor>;
  1968.  
  1969. UpdateFinishableEnemyList();
  1970. FindMoveTarget();
  1971. playerMode.UpdateCombatMode();
  1972.  
  1973. if( GetPlayerCombatStance() == PCS_Guarded )
  1974. {
  1975. if( GetTarget().GetHealthPercents() > 0.25f )
  1976. {
  1977. PlayBattleCry( 'BattleCryTaunt', 0.2f );
  1978. }
  1979. else
  1980. {
  1981. if( GetTarget().IsHuman() )
  1982. PlayBattleCry( 'BattleCryHumansEnd', 0.3f );
  1983. else
  1984. PlayBattleCry( 'BattleCryMonstersEnd', 0.3f );
  1985. }
  1986. }
  1987.  
  1988. if(IsThreatened() && ShouldProcessTutorial('TutorialMonsterThreatLevels') && FactsQuerySum("q001_nightmare_ended") > 0)
  1989. {
  1990. GetEnemiesInRange(enemies);
  1991. for(i=0; i<enemies.Size(); i+=1)
  1992. {
  1993. strLevel = ((CNewNPC)enemies[i]).GetExperienceDifferenceLevelName(temp);
  1994. if(strLevel == "deadlyLevel" || strLevel == "highLevel")
  1995. {
  1996. FactsAdd("tut_high_threat_monster");
  1997. break;
  1998. }
  1999. }
  2000. }
  2001. }
  2002.  
  2003. public function ReceivedDamageInCombat() : bool
  2004. {
  2005. return receivedDamageInCombat;
  2006. }
  2007.  
  2008. //called when combat starts
  2009. event OnCombatStart()
  2010. {
  2011. var weaponType : EPlayerWeapon;
  2012.  
  2013. theGame.CreateNoSaveLock( 'combat', noSaveLock );
  2014.  
  2015. theGame.GameplayFactsAdd( "in_combat" );
  2016.  
  2017. //cerberus achievement
  2018. FactsRemove("statistics_cerberus_sign");
  2019. FactsRemove("statistics_cerberus_petard");
  2020. FactsRemove("statistics_cerberus_bolt");
  2021. FactsRemove("statistics_cerberus_fists");
  2022. FactsRemove("statistics_cerberus_melee");
  2023. FactsRemove("statistics_cerberus_environment");
  2024.  
  2025. BlockAction(EIAB_OpenMeditation, 'InCombat');
  2026. BlockAction(EIAB_HighlightObjective, 'InCombat');
  2027.  
  2028. if ( !this.IsUsingBoat() && GetTarget().GetAttitude(this) == AIA_Hostile )
  2029. {
  2030. weaponType = GetMostConvenientMeleeWeapon( GetTarget() );
  2031.  
  2032. if ( weaponType == PW_Steel || weaponType == PW_Silver )
  2033. this.OnEquipMeleeWeapon( weaponType, false );
  2034. }
  2035. }
  2036.  
  2037. //called when combat finishes
  2038. event OnCombatFinished()
  2039. {
  2040. var cnt : int;
  2041.  
  2042. reevaluateCurrentWeapon = false;
  2043.  
  2044. thePlayer.HardLockToTarget( false );
  2045.  
  2046. receivedDamageInCombat = false;
  2047.  
  2048. theGame.GameplayFactsRemove( "in_combat" );
  2049.  
  2050. //cerberus achievement
  2051. cnt = 0;
  2052. if(FactsQuerySum("statistics_cerberus_sign") > 0)
  2053. cnt += 1;
  2054. if(FactsQuerySum("statistics_cerberus_petard") > 0)
  2055. cnt += 1;
  2056. if(FactsQuerySum("statistics_cerberus_bolt") > 0)
  2057. cnt += 1;
  2058. if(FactsQuerySum("statistics_cerberus_fists") > 0)
  2059. cnt += 1;
  2060. if(FactsQuerySum("statistics_cerberus_melee") > 0)
  2061. cnt += 1;
  2062. if(FactsQuerySum("statistics_cerberus_environment") > 0)
  2063. cnt += 1;
  2064.  
  2065. //failsafe
  2066. FactsRemove("statistics_cerberus_sign");
  2067. FactsRemove("statistics_cerberus_petard");
  2068. FactsRemove("statistics_cerberus_bolt");
  2069. FactsRemove("statistics_cerberus_fists");
  2070. FactsRemove("statistics_cerberus_melee");
  2071. FactsRemove("statistics_cerberus_environment");
  2072.  
  2073. if(cnt >= 3)
  2074. theGame.GetGamerProfile().AddAchievement(EA_Cerberus);
  2075. //end of cerberus
  2076.  
  2077. if(theGame.GetTutorialSystem() && FactsQuerySum("TutorialShowSilver") > 0)
  2078. {
  2079. FactsAdd("tut_show_silver_sword", 1);
  2080. FactsRemove("TutorialShowSilver");
  2081. }
  2082. this.SetBehaviorVariable('isInCombatForOverlay',0.f);
  2083. GoToExplorationIfNeeded();
  2084. theGame.ReleaseNoSaveLock( noSaveLock );
  2085. LogChannel( 'OnCombatFinished', "OnCombatFinished: ReleaseNoSaveLock" );
  2086.  
  2087. SetFailedFundamentalsFirstAchievementCondition(false);
  2088.  
  2089. UnblockAction(EIAB_OpenMeditation, 'InCombat');
  2090. UnblockAction(EIAB_HighlightObjective, 'InCombat');
  2091. }
  2092.  
  2093. event OnReactToBeingHit( damageAction : W3DamageAction )
  2094. {
  2095. var weaponType : EPlayerWeapon;
  2096.  
  2097. super.OnReactToBeingHit(damageAction);
  2098. IncHitCounter();
  2099.  
  2100. if ( IsInCombat() && damageAction.attacker && damageAction.attacker == GetTarget() && !( this.IsUsingVehicle() && this.IsOnBoat() ) )
  2101. {
  2102. weaponType = GetMostConvenientMeleeWeapon( GetTarget() );
  2103. if ( weaponType != PW_Fists && weaponType != PW_None && weaponType != this.GetCurrentMeleeWeaponType() )
  2104. OnEquipMeleeWeapon( weaponType, false );
  2105. }
  2106. }
  2107.  
  2108. //called when player receives damage in combat(except for toxicity)
  2109. public function ReceivedCombatDamage()
  2110. {
  2111. receivedDamageInCombat = true;
  2112. }
  2113.  
  2114. ///////////////////////////////////////////////////////////////////////////
  2115. // @Uninterrupted hits
  2116. ///////////////////////////////////////////////////////////////////////////
  2117.  
  2118.  
  2119. timer function UninterruptedHitsResetOnIdle(dt : float, id : int)
  2120. {
  2121. ResetUninterruptedHitsCount();
  2122. }
  2123.  
  2124. public function ResetUninterruptedHitsCount()
  2125. {
  2126. uninterruptedHitsCount = 0;
  2127. LogUnitAtt("Uninterrupted attacks reset!!!!");
  2128. }
  2129.  
  2130. public function IncreaseUninterruptedHitsCount()
  2131. {
  2132. uninterruptedHitsCount += 1;
  2133. LogUnitAtt("Uninterrupted attacks count increased to " + uninterruptedHitsCount);
  2134.  
  2135. if(uninterruptedHitsCount == 4)
  2136. AddTimer('StartUninterruptedBlurr', 1, false);
  2137.  
  2138. //idle turn off timer
  2139. AddTimer('UninterruptedHitsResetOnIdle', 4.f, false);
  2140. }
  2141.  
  2142. timer function StartUninterruptedBlurr(dt : float, id : int)
  2143. {
  2144. var changed : bool;
  2145. var movingAgent : CMovingPhysicalAgentComponent;
  2146. var target : CActor;
  2147.  
  2148. //check if the timer is to be turned off
  2149. if(uninterruptedHitsCount < 4)
  2150. {
  2151. LogUnitAtt("Stopping camera effect");
  2152. thePlayer.StopEffect(uninterruptedHitsCurrentCameraEffect);
  2153. uninterruptedHitsCurrentCameraEffect = '';
  2154. uninterruptedHitsCameraStarted = false;
  2155. RemoveTimer('StartUninterruptedBlurr');
  2156. }
  2157. else //still valid
  2158. {
  2159. target = GetTarget();
  2160.  
  2161. if( target )
  2162. {
  2163. movingAgent = ( (CMovingPhysicalAgentComponent) (target.GetMovingAgentComponent()) );
  2164. }
  2165.  
  2166. if(!uninterruptedHitsCameraStarted)
  2167. {
  2168. LogUnitAtt("Starting camera effect");
  2169. AddTimer('StartUninterruptedBlurr', 0.001, true); //need to update per tick
  2170. if(movingAgent && movingAgent.GetCapsuleHeight() > 2)
  2171. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY;
  2172. else
  2173. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY;
  2174. thePlayer.PlayEffect(uninterruptedHitsCurrentCameraEffect);
  2175. uninterruptedHitsCameraStarted = true;
  2176. }
  2177. else
  2178. {
  2179. changed = false;
  2180. if(movingAgent && movingAgent.GetCapsuleHeight() > 2 && uninterruptedHitsCurrentCameraEffect != theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY)
  2181. changed = true;
  2182. else if(!movingAgent || ( movingAgent.GetCapsuleHeight() <= 2 && uninterruptedHitsCurrentCameraEffect != theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY) )
  2183. changed = true;
  2184.  
  2185. //if the target's height has changed then swap the camera effect
  2186. if(changed)
  2187. {
  2188. //stop current effect
  2189. thePlayer.StopEffect(uninterruptedHitsCurrentCameraEffect);
  2190.  
  2191. //change mode
  2192. if(uninterruptedHitsCurrentCameraEffect == theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY)
  2193. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY;
  2194. else
  2195. uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY;
  2196.  
  2197. //turn new camera effect on
  2198. thePlayer.PlayEffect(uninterruptedHitsCurrentCameraEffect);
  2199. }
  2200. }
  2201. }
  2202. }
  2203.  
  2204. ///////////////////////////////////////////////////////////////////////////
  2205. // Exploration Actions
  2206. ///////////////////////////////////////////////////////////////////////////
  2207.  
  2208. private var playerActionEventListeners : array<CGameplayEntity>;
  2209. private var playerActionEventBlockingListeners : array<CGameplayEntity>;
  2210.  
  2211. private function PlayerActionBlockGameplayActions( sourceName : name, lock : bool, isFromPlace : bool )
  2212. {
  2213. if ( lock )
  2214. {
  2215. thePlayer.BlockAction( EIAB_Signs, sourceName, false, false, isFromPlace );
  2216. thePlayer.BlockAction( EIAB_DrawWeapon, sourceName, false, false, isFromPlace );
  2217. thePlayer.BlockAction( EIAB_CallHorse, sourceName, false, false, isFromPlace );
  2218. thePlayer.BlockAction( EIAB_FastTravel, sourceName, false, false, isFromPlace );
  2219. thePlayer.BlockAction( EIAB_Fists, sourceName, false, false, isFromPlace );
  2220. thePlayer.BlockAction( EIAB_InteractionAction, sourceName, false, false, isFromPlace );
  2221. thePlayer.DisableCombatState();
  2222. }
  2223. else
  2224. {
  2225. thePlayer.UnblockAction( EIAB_Signs, sourceName );
  2226. thePlayer.UnblockAction( EIAB_DrawWeapon, sourceName );
  2227. thePlayer.UnblockAction( EIAB_CallHorse, sourceName );
  2228. thePlayer.UnblockAction( EIAB_FastTravel, sourceName );
  2229. thePlayer.UnblockAction( EIAB_Fists, sourceName );
  2230. thePlayer.UnblockAction( EIAB_InteractionAction, sourceName );
  2231. }
  2232. }
  2233.  
  2234. public function GetPlayerActionEventListeners() : array<CGameplayEntity>
  2235. {
  2236. return playerActionEventListeners;
  2237. }
  2238.  
  2239. //Registers for event + blocks GameplayActions
  2240. public function RegisterForPlayerAction( listener : CGameplayEntity, isLockedByPlace : bool )
  2241. {
  2242. if ( !playerActionEventListeners.Contains( listener ) )
  2243. {
  2244. playerActionEventListeners.PushBack( listener );
  2245. }
  2246. if ( listener.ShouldBlockGameplayActionsOnInteraction() )
  2247. {
  2248. if ( !playerActionEventBlockingListeners.Contains( listener ) )
  2249. {
  2250. playerActionEventBlockingListeners.PushBack( listener );
  2251. }
  2252. if ( playerActionEventBlockingListeners.Size() == 1 )
  2253. {
  2254. PlayerActionBlockGameplayActions( 'PlayerAction', true, isLockedByPlace );
  2255. }
  2256. }
  2257. }
  2258.  
  2259. //Unregisters for event + unblocks GameplayActions
  2260. public function UnregisterForPlayerAction( listener : CGameplayEntity, isLockedByPlace : bool )
  2261. {
  2262. playerActionEventListeners.Remove( listener );
  2263. playerActionEventBlockingListeners.Remove( listener );
  2264. if ( playerActionEventBlockingListeners.Size() == 0 )
  2265. {
  2266. PlayerActionBlockGameplayActions( 'PlayerAction', false, isLockedByPlace );
  2267. }
  2268. }
  2269.  
  2270. event OnPlayerActionStart()
  2271. {
  2272. //MS: Only used for ProudWalk
  2273. thePlayer.SetBehaviorVariable( 'inJumpState', 1.f );
  2274. }
  2275.  
  2276. event OnPlayerActionEnd()
  2277. {
  2278. var i : int;
  2279. for ( i = playerActionEventListeners.Size() - 1; i >= 0; i-=1 )
  2280. {
  2281. playerActionEventListeners[i].OnPlayerActionEnd();
  2282. }
  2283. currentCustomAction = PEA_None;
  2284.  
  2285. //MS: Only used for ProudWalk
  2286. thePlayer.SetBehaviorVariable( 'inJumpState', 0.f );
  2287. }
  2288.  
  2289. event OnPlayerActionStartFinished()
  2290. {
  2291. var i : int;
  2292. for ( i = playerActionEventListeners.Size() - 1; i >= 0; i-=1 )
  2293. {
  2294. playerActionEventListeners[i].OnPlayerActionStartFinished();
  2295. }
  2296. }
  2297.  
  2298. function PlayerStartAction( playerAction : EPlayerExplorationAction, optional animName : name ) : bool
  2299. {
  2300. if ( playerAction == PEA_SlotAnimation && !IsNameValid(animName) )
  2301. {
  2302. return false;
  2303. }
  2304.  
  2305. SetBehaviorVariable( 'playerStopAction', 0.0);
  2306. SetBehaviorVariable( 'playerExplorationAction', (float)(int)playerAction);
  2307.  
  2308. /*if ( playerAction == PEA_SlotAnimation )
  2309. {
  2310. if ( !this.ActionPlaySlotAnimationAsync('PLAYER_ACTION_SLOT',animName) )
  2311. return false;
  2312. }*/
  2313.  
  2314. if ( RaiseForceEvent('playerActionStart') )
  2315. {
  2316. currentCustomAction = playerAction;
  2317. if ( playerAction == PEA_SlotAnimation )
  2318. {
  2319. playerActionSlotAnimName = animName;
  2320. AddTimer('PlayActionAnimWorkaround',0,false);
  2321. }
  2322. return true;
  2323. }
  2324. return false;
  2325. }
  2326.  
  2327. private var playerActionSlotAnimName : name;
  2328.  
  2329. timer function PlayActionAnimWorkaround( dt : float , id : int)
  2330. {
  2331. this.ActionPlaySlotAnimationAsync('PLAYER_ACTION_SLOT',playerActionSlotAnimName, 0.2, 0.2, true);
  2332. }
  2333.  
  2334. function PlayerStopAction( playerAction : EPlayerExplorationAction )
  2335. {
  2336. SetBehaviorVariable( 'playerExplorationAction', (float)(int)playerAction);
  2337. SetBehaviorVariable( 'playerStopAction', 1.0);
  2338. currentCustomAction = PEA_None;
  2339. }
  2340.  
  2341. function GetPlayerAction() : EPlayerExplorationAction
  2342. {
  2343. return currentCustomAction;
  2344. }
  2345.  
  2346. function MedallionPing()
  2347. {
  2348. var currTime : float = theGame.GetEngineTimeAsSeconds();
  2349.  
  2350. if ( lastMedallionEffect < currTime )
  2351. {
  2352. lastMedallionEffect = theGame.GetEngineTimeAsSeconds() + medallion.effectDuration;
  2353. medallion.TriggerMedallionFX();
  2354. }
  2355. }
  2356.  
  2357. ///////////////////////////////////////////////////////////////////////////
  2358. // @INTERACTIONS
  2359. ///////////////////////////////////////////////////////////////////////////
  2360.  
  2361. public function CanPerformPlayerAction(optional alsoOutsideExplorationState : bool) : bool
  2362. {
  2363. //if in exploration or in any state and flag set
  2364. if(!alsoOutsideExplorationState && GetCurrentStateName() != 'Exploration')
  2365. return false;
  2366.  
  2367. if( isInAir || (substateManager && !substateManager.CanInteract()) || IsInCombatAction() || GetCriticalBuffsCount() > 0)
  2368. return false;
  2369.  
  2370. return true;
  2371. }
  2372.  
  2373. //called when we receive an item
  2374. event OnItemGiven(data : SItemChangedData)
  2375. {
  2376. var keyName : name;
  2377. var i : int;
  2378. var hud : CR4ScriptedHud;
  2379. var message : string;
  2380. var inve : CInventoryComponent;
  2381.  
  2382. if(data.informGui)
  2383. {
  2384. hud = (CR4ScriptedHud)theGame.GetHud();
  2385. if(hud)
  2386. {
  2387. message = GetLocStringByKeyExt("panel_common_item_received") + ": " + GetLocStringByKeyExt(inv.GetItemLocalizedNameByUniqueID(data.ids[0]));
  2388. if(data.quantity > 1)
  2389. message += " x" + data.quantity;
  2390. hud.HudConsoleMsg(message);
  2391. }
  2392. }
  2393.  
  2394. inve = GetInventory(); //OnItemGiven can be called before we cache inventory component
  2395.  
  2396. //key - check if we're next to a lock that uses this key and update interaction if needed
  2397. if(inve.ItemHasTag(data.ids[0], 'key'))
  2398. {
  2399. keyName = inve.GetItemName(data.ids[0]);
  2400. for(i=nearbyLockedContainersNoKey.Size()-1; i>=0; i-=1)
  2401. {
  2402. if(nearbyLockedContainersNoKey[i].GetKeyName() == keyName && nearbyLockedContainersNoKey[i].IsEnabled())
  2403. {
  2404. nearbyLockedContainersNoKey[i].UpdateComponents("Unlock");
  2405. nearbyLockedContainersNoKey.Remove(nearbyLockedContainersNoKey[i]);
  2406. }
  2407. }
  2408. }
  2409.  
  2410. //alchemy level 3 items
  2411. if(inve.IsItemAlchemyItem(data.ids[0]))
  2412. {
  2413. UpgradeAlchemyItem(data.ids[0], CanUseSkill(S_Perk_08));
  2414. }
  2415.  
  2416. if(inve.ItemHasTag(data.ids[0], theGame.params.TAG_OFIR_SET))
  2417. CheckOfirSetAchievement();
  2418. }
  2419.  
  2420. private final function CheckOfirSetAchievement()
  2421. {
  2422. var hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders : bool;
  2423.  
  2424. //check player items
  2425. CheckOfirItems(GetInventory(), hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders);
  2426.  
  2427. //check stash items
  2428. CheckOfirItems(GetWitcherPlayer().GetHorseManager().GetInventoryComponent(), hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders);
  2429.  
  2430. if(hasArmor && hasBoots && hasGloves && hasPants && hasSword && hasSaddle && hasBag && hasBlinders)
  2431. theGame.GetGamerProfile().AddAchievement(EA_LatestFashion);
  2432. }
  2433.  
  2434. 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)
  2435. {
  2436. var ofirs : array<SItemUniqueId>;
  2437. var i : int;
  2438.  
  2439. ofirs = inv.GetItemsByTag(theGame.params.TAG_OFIR_SET);
  2440. for(i=0; i<ofirs.Size(); i+=1)
  2441. {
  2442. if(inv.IsItemChestArmor(ofirs[i]))
  2443. {
  2444. hasArmor = true;
  2445. continue;
  2446. }
  2447. else if(inv.IsItemBoots(ofirs[i]))
  2448. {
  2449. hasBoots = true;
  2450. continue;
  2451. }
  2452. else if(inv.IsItemGloves(ofirs[i]))
  2453. {
  2454. hasGloves = true;
  2455. continue;
  2456. }
  2457. else if(inv.IsItemPants(ofirs[i]))
  2458. {
  2459. hasPants = true;
  2460. continue;
  2461. }
  2462. else if(inv.IsItemSteelSwordUsableByPlayer(ofirs[i]))
  2463. {
  2464. hasSword = true;
  2465. continue;
  2466. }
  2467. else if(inv.IsItemSilverSwordUsableByPlayer(ofirs[i]))
  2468. {
  2469. hasSword = true;
  2470. continue;
  2471. }
  2472. else if(inv.IsItemSaddle(ofirs[i]))
  2473. {
  2474. hasSaddle = true;
  2475. continue;
  2476. }
  2477. else if(inv.IsItemHorseBag(ofirs[i]))
  2478. {
  2479. hasBag = true;
  2480. continue;
  2481. }
  2482. else if(inv.IsItemBlinders(ofirs[i]))
  2483. {
  2484. hasBlinders = true;
  2485. continue;
  2486. }
  2487. }
  2488. }
  2489.  
  2490. //changes all alchemy items of level 3 abilities from level 2 to 3 (if upgrade) or from 3 to 2 (if not upgrading)
  2491. public function ChangeAlchemyItemsAbilities(upgrade : bool)
  2492. {
  2493. var i : int;
  2494. var dm : CDefinitionsManagerAccessor;
  2495. var items : array<SItemUniqueId>;
  2496.  
  2497. inv.GetAllItems(items);
  2498. dm = theGame.GetDefinitionsManager();
  2499.  
  2500. for(i=0; i<items.Size(); i+=1)
  2501. if(inv.IsItemAlchemyItem(items[i]))
  2502. UpgradeAlchemyItem(items[i], upgrade);
  2503. }
  2504.  
  2505. //changes all alchemy items of level 3 abilities from level 2 to 3 (if upgrade) or from 3 to 2 (if not upgrading)
  2506. public function UpgradeAlchemyItem(itemID : SItemUniqueId, upgrade : bool)
  2507. {
  2508. var j, currLevel, otherLevel : int;
  2509. var dm : CDefinitionsManagerAccessor;
  2510. var abs, currAbilities, otherAbilities : array<name>;
  2511. var min, max : SAbilityAttributeValue;
  2512.  
  2513. if(!inv.IsItemAlchemyItem(itemID))
  2514. return;
  2515.  
  2516. //get current level
  2517. currLevel = (int)CalculateAttributeValue(inv.GetItemAttributeValue(itemID, 'level'));
  2518.  
  2519. //if level ok then exit
  2520. if(currLevel == 3 || currLevel == 2 || currLevel < 2 || currLevel > 3)
  2521. return;
  2522.  
  2523. //get current ability name
  2524. currAbilities = inv.GetItemAbilitiesWithAttribute(itemID, 'level', currLevel);
  2525.  
  2526. //get other ability name
  2527. inv.GetItemContainedAbilities(itemID, abs);
  2528. dm = theGame.GetDefinitionsManager();
  2529. for(j=0; j<abs.Size(); j+=1)
  2530. {
  2531. dm.GetAbilityAttributeValue(abs[j], 'level', min, max);
  2532. otherLevel = (int)CalculateAttributeValue(GetAttributeRandomizedValue(min, max));
  2533. if( (otherLevel == 2 || otherLevel == 3) && otherLevel != currLevel)
  2534. otherAbilities.PushBack(abs[j]);
  2535. }
  2536.  
  2537. //swap abilities
  2538. if(otherAbilities.Size() == 0)
  2539. {
  2540. LogAssert(false, "CR4Player.UpgradeAlchemyItem: cannot find ability to swap to from <<" + currAbilities[0] + ">> on item <<" + inv.GetItemName(itemID) + ">> !!!");
  2541. }
  2542. else
  2543. {
  2544. for(j=0; j<currAbilities.Size(); j+=1)
  2545. inv.RemoveItemBaseAbility(itemID, currAbilities[j]);
  2546.  
  2547. for(j=0; j<otherAbilities.Size(); j+=1)
  2548. inv.AddItemBaseAbility(itemID, otherAbilities[j]);
  2549. }
  2550. }
  2551.  
  2552. ///////////////////////////////////////////////////////////////////////////
  2553. // Movement adjustment helper functions
  2554. ///////////////////////////////////////////////////////////////////////////
  2555.  
  2556. public function MovAdjRotateToTarget( ticket : SMovementAdjustmentRequestTicket )
  2557. {
  2558. var movementAdjustor : CMovementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  2559. var localOrientationTarget : EOrientationTarget = GetOrientationTarget();
  2560.  
  2561. if ( localOrientationTarget == OT_CustomHeading )
  2562. {
  2563. movementAdjustor.RotateTo( ticket, GetOrientationTargetCustomHeading() );
  2564. }
  2565. else if ( localOrientationTarget == OT_Actor )
  2566. {
  2567. /*if ( parryTarget && IsGuarded() )
  2568. movementAdjustor.RotateTowards( ticket, parryTarget );
  2569. else*/ if ( slideTarget )
  2570. movementAdjustor.RotateTowards( ticket, slideTarget );
  2571. else if ( lAxisReleasedAfterCounter )
  2572. movementAdjustor.RotateTo( ticket, GetHeading() );
  2573. else
  2574. movementAdjustor.RotateTo( ticket, GetCombatActionHeading() );//rawPlayerHeading );
  2575. }
  2576. else if ( localOrientationTarget == OT_Player )
  2577. {
  2578. if ( bLAxisReleased )
  2579. movementAdjustor.RotateTo( ticket, GetHeading() );
  2580. else
  2581. movementAdjustor.RotateTo( ticket, rawPlayerHeading );//GetCombatActionHeading() );
  2582. }
  2583. else if ( localOrientationTarget == OT_CameraOffset )
  2584. {
  2585. //movementAdjustor.RotateTo( ticket, VecHeading( cachedCameraVector ) );//rawCameraHeading - oTCameraOffset );
  2586. movementAdjustor.RotateTo( ticket, VecHeading( theCamera.GetCameraDirection() ) );//rawCameraHeading );
  2587. }
  2588. else
  2589. {
  2590. // default to camera
  2591. movementAdjustor.RotateTo( ticket, rawCameraHeading );
  2592. }
  2593. // never rotate to player
  2594. }
  2595.  
  2596. ////////////////////////////////////////////////////////////////////////////////////
  2597. // Look at targets - moved here from movables
  2598. ////////////////////////////////////////////////////////////////////////////////////
  2599. //var cachedCameraVector : Vector;
  2600. public function UpdateLookAtTarget()
  2601. {
  2602. var localOrientationTarget : EOrientationTarget;
  2603. var playerRot : EulerAngles;
  2604. var lookAtActive : Float;
  2605. var lookAtTarget : Vector;
  2606. var headBoneIdx : int;
  2607. var tempComponent : CDrawableComponent;
  2608. var entityHeight : float;
  2609. var useTorsoBone : bool;
  2610.  
  2611. var angles : EulerAngles;
  2612. var dir : Vector;
  2613. var camZ : float;
  2614.  
  2615. var target : CActor;
  2616.  
  2617. lookAtActive = 0.0f;
  2618.  
  2619. localOrientationTarget = GetOrientationTarget();
  2620.  
  2621. if ( localOrientationTarget == OT_Player || localOrientationTarget == OT_CustomHeading )
  2622. {
  2623. /*headBoneIdx = GetTorsoBoneIndex();
  2624. if ( headBoneIdx >= 0 )
  2625. {
  2626. lookAtTarget = MatrixGetTranslation( GetBoneWorldMatrixByIndex( headBoneIdx ) );
  2627. }*/
  2628.  
  2629. //lookAtTarget = GetHeadingVector() * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2630.  
  2631. if ( localOrientationTarget == OT_Player )
  2632. angles = VecToRotation( GetHeadingVector() );
  2633. else if ( customOrientationInfoStack.Size() > 0 )
  2634. angles = VecToRotation( VecFromHeading( customOrientationInfoStack[ customOrientationInfoStack.Size() - 1 ].customHeading ) );
  2635. else
  2636. angles = VecToRotation( GetHeadingVector() );
  2637.  
  2638. //angles.Pitch = oTCameraPitchOffset;
  2639. dir = RotForward( angles );
  2640. lookAtTarget = dir * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2641. lookAtTarget.Z += 1.6f;
  2642. lookAtActive = 1.0f;
  2643. }
  2644. else if ( localOrientationTarget == OT_Camera )
  2645. {
  2646. headBoneIdx = GetHeadBoneIndex();
  2647. if ( headBoneIdx >= 0 )
  2648. {
  2649. lookAtTarget = MatrixGetTranslation( GetBoneWorldMatrixByIndex( headBoneIdx ) );
  2650. }
  2651. else
  2652. {
  2653. lookAtTarget = GetWorldPosition();
  2654. lookAtTarget.Z += 1.6f; // fake head?
  2655. }
  2656. lookAtTarget += theCamera.GetCameraDirection() * 100.f;
  2657. lookAtActive = 1.0f;
  2658. }
  2659. else if ( localOrientationTarget == OT_CameraOffset )
  2660. {
  2661. /*lookAtTarget = GetWorldPosition();
  2662. lookAtTarget.Z += 1.6f; // fake head?
  2663. camDir = theCamera.GetCameraDirection();
  2664. camZ = camDir.Z;// + 0.1;
  2665. camDir = VecFromHeading( VecHeading( theCamera.GetCameraDirection() ) - oTCameraOffset ) * VecLength2D( camDir );
  2666. camDir.Z = camZ;*/
  2667.  
  2668. dir = theCamera.GetCameraDirection();
  2669. angles = VecToRotation( dir );
  2670. angles.Pitch = -angles.Pitch + oTCameraPitchOffset;
  2671. angles.Yaw -= oTCameraOffset;
  2672. dir = RotForward( angles );
  2673.  
  2674. lookAtTarget = dir * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2675. lookAtTarget.Z += 1.6f;
  2676. lookAtActive = 1.0f;
  2677. }
  2678. else if ( localOrientationTarget == OT_Actor )
  2679. {
  2680. if ( IsInCombatAction() )
  2681. {
  2682. if ( ( ( ( W3PlayerWitcher )this ).GetCurrentlyCastSign() != ST_None && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign )
  2683. || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_ItemThrow )
  2684. //|| GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Crossbow )
  2685. useTorsoBone = true;
  2686. }
  2687.  
  2688. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  2689. useTorsoBone = true;
  2690.  
  2691. if ( tempLookAtTarget && (CActor)(tempLookAtTarget) )
  2692. {
  2693. lookAtTarget = ProcessLookAtTargetPosition( tempLookAtTarget, useTorsoBone );
  2694. lookAtActive = 1.0f;
  2695. }
  2696.  
  2697. if ( GetDisplayTarget() && IsDisplayTargetTargetable() )
  2698. {
  2699. lookAtTarget = ProcessLookAtTargetPosition( GetDisplayTarget(), useTorsoBone );
  2700. lookAtActive = 1.0f;
  2701. }
  2702. else
  2703. {
  2704. //FAIL SAFE in case the displayTarget disappears for some reason
  2705.  
  2706. if ( slideTarget )
  2707. {
  2708. lookAtTarget = ProcessLookAtTargetPosition( slideTarget, useTorsoBone );
  2709. }
  2710. else
  2711. {
  2712. target = GetTarget();
  2713. if ( target )
  2714. {
  2715. lookAtTarget = ProcessLookAtTargetPosition( target, useTorsoBone );
  2716. }
  2717. }
  2718.  
  2719. lookAtActive = 1.0f;
  2720. }
  2721.  
  2722. if ( !slideTarget && !IsUsingVehicle() )
  2723. {
  2724. // TODO maybe just get axis from head?
  2725. playerRot = GetWorldRotation();
  2726. lookAtTarget = GetWorldPosition() + VecFromHeading( playerRot.Yaw ) * 100.0f;
  2727. lookAtActive = 0.0f;
  2728. }
  2729.  
  2730. if ( useTorsoBone )
  2731. lookAtTarget.Z += 0.2f;
  2732. }
  2733.  
  2734.  
  2735. //lookAtTarget = player.GetHeadingVector() * 30.f + this.GetWorldPosition();// + lookAtTarget;
  2736. //lookAtActive = 1.0f;
  2737. GetVisualDebug().AddSphere('lookAtTarget', 1.f, lookAtTarget, true, Color(255,0,0), 3.0f );
  2738. SetLookAtPosition( lookAtTarget );
  2739. UpdateLookAtVariables( lookAtActive, lookAtTarget );
  2740. }
  2741.  
  2742. private function ProcessLookAtTargetPosition( ent : CGameplayEntity, useTorsoBone : bool ) : Vector
  2743. {
  2744. var boneIdx : int;
  2745. var actor : CActor;
  2746. var lookAtTarget : Vector;
  2747. var tempComponent : CDrawableComponent;
  2748. var box : Box;
  2749. var entityHeight : float;
  2750. var entityPos : Vector;
  2751. var predictedPos : Vector;
  2752. var z : float;
  2753. var entMat : Matrix;
  2754.  
  2755. actor = (CActor)(ent);
  2756. entityPos = ent.GetWorldPosition();
  2757. lookAtTarget = entityPos;
  2758.  
  2759. if ( actor )
  2760. {
  2761. if ( useTorsoBone )
  2762. boneIdx = actor.GetTorsoBoneIndex();
  2763. else
  2764. boneIdx = actor.GetHeadBoneIndex();
  2765. }
  2766. else
  2767. boneIdx = -1;
  2768.  
  2769. if ( !( ent.aimVector.X == 0 && ent.aimVector.Y == 0 && ent.aimVector.Z == 0 ) )
  2770. {
  2771. entMat = ent.GetLocalToWorld();
  2772. lookAtTarget = VecTransform( entMat, ent.aimVector );
  2773. }
  2774. else if ( boneIdx >= 0 )
  2775. {
  2776. lookAtTarget = MatrixGetTranslation( ent.GetBoneWorldMatrixByIndex( boneIdx ) );
  2777. }
  2778. else
  2779. {
  2780. if ( actor )
  2781. lookAtTarget.Z += ( ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetCapsuleHeight() * 0.5 ); // fake head?
  2782. else
  2783. {
  2784. tempComponent = (CDrawableComponent)( ent.GetComponentByClassName('CDrawableComponent') );
  2785. if ( tempComponent.GetObjectBoundingVolume( box ) )
  2786. {
  2787. entityHeight = box.Max.Z - box.Min.Z;
  2788. lookAtTarget = lookAtTarget + Vector(0,0,entityHeight/2);
  2789. }
  2790. }
  2791. }
  2792. z = ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetCapsuleHeight();
  2793. if ( actor )
  2794. {
  2795. if ( PredictLookAtTargetPosition( actor, lookAtTarget.Z - entityPos.Z, predictedPos ) )
  2796. lookAtTarget = predictedPos;
  2797. }
  2798.  
  2799. return lookAtTarget;
  2800. }
  2801.  
  2802.  
  2803. private function PredictLookAtTargetPosition( targetActor : CActor, zOffSet : float, out predictedPos : Vector ) : bool
  2804. {
  2805. var virtualPos : Vector;
  2806. var i : int;
  2807. var dist : float;
  2808. var deltaTime : float;
  2809. var projSpeed : float;
  2810. var projSpeedInt : Vector;
  2811. var projAngle : float;
  2812.  
  2813. var e3Hack : bool;
  2814. var currentTimeInCurve : float;
  2815. e3Hack = false;
  2816.  
  2817. if ( rangedWeapon
  2818. && rangedWeapon.GetDeployedEntity()
  2819. && ( rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' || rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' ) )
  2820. {
  2821. projSpeed = rangedWeapon.GetDeployedEntity().projSpeed;
  2822.  
  2823. virtualPos = targetActor.GetWorldPosition();
  2824.  
  2825. if ( e3Hack && targetActor.HasTag( 'e3_griffin' ) )
  2826. {
  2827. for ( i = 0; i < 10; i += 1 )
  2828. {
  2829. dist = VecDistance( rangedWeapon.GetDeployedEntity().GetWorldPosition(), virtualPos );
  2830. deltaTime = dist/projSpeed;
  2831. virtualPos = targetActor.PredictWorldPosition( deltaTime );
  2832. }
  2833. }
  2834. else
  2835. return false;
  2836.  
  2837. virtualPos.Z += zOffSet;
  2838. predictedPos = virtualPos;
  2839. GetVisualDebug().AddSphere('CrossbowPredictedPos', 1.0f, virtualPos , true, Color(255,50,50), 5.0f );
  2840. return true;
  2841. }
  2842. return false;
  2843. }
  2844.  
  2845. public function SetLookAtPosition( vec : Vector )
  2846. {
  2847. lookAtPosition = vec;
  2848. }
  2849.  
  2850. public function GetLookAtPosition() : Vector
  2851. {
  2852. return lookAtPosition;
  2853. }
  2854.  
  2855. ////////////////////////////////////////////////////////////////////////////////////
  2856. // Scene
  2857. ////////////////////////////////////////////////////////////////////////////////////
  2858.  
  2859. event OnBlockingSceneEnded( optional output : CStorySceneOutput)
  2860. {
  2861. //hack for possible immortality from finishers
  2862. SetImmortalityMode( AIM_None, AIC_SyncedAnim );
  2863. super.OnBlockingSceneEnded(output);
  2864. }
  2865.  
  2866. ////////////////////////////////////////////////////////////////////////////////////
  2867. // New combat / exploration and weapon drawing
  2868. ////////////////////////////////////////////////////////////////////////////////////
  2869.  
  2870. function GetCurrentMeleeWeaponName() : name
  2871. {
  2872. return weaponHolster.GetCurrentMeleeWeaponName();
  2873. }
  2874.  
  2875. public function GetCurrentMeleeWeaponType() : EPlayerWeapon
  2876. {
  2877. return weaponHolster.GetCurrentMeleeWeapon();
  2878. }
  2879.  
  2880. public function OnMeleeForceHolster(ignoreActionLock : bool)
  2881. {
  2882. weaponHolster.HolsterWeapon(ignoreActionLock, true);
  2883. }
  2884.  
  2885. event OnForcedHolsterWeapon()
  2886. {
  2887. weaponHolster.OnForcedHolsterWeapon();
  2888. }
  2889.  
  2890. event OnEquippedItem( category : name, slotName : name )
  2891. {
  2892. var weaponType : EPlayerWeapon;
  2893.  
  2894. if ( slotName == 'r_weapon' )
  2895. {
  2896. switch ( category )
  2897. {
  2898. case 'None' :
  2899. weaponType = PW_None;
  2900. break;
  2901. case 'fist' :
  2902. weaponType = PW_Fists;
  2903. break;
  2904. case 'steelsword' :
  2905. weaponType = PW_Steel;
  2906. break;
  2907. case 'silversword' :
  2908. weaponType = PW_Silver;
  2909. break;
  2910. default :
  2911. return true;
  2912. }
  2913.  
  2914. weaponHolster.OnEquippedMeleeWeapon( weaponType );
  2915. }
  2916. }
  2917.  
  2918. private var isHoldingDeadlySword : bool;
  2919. public function ProcessIsHoldingDeadlySword()
  2920. {
  2921. isHoldingDeadlySword = IsDeadlySwordHeld();
  2922. }
  2923.  
  2924. public function IsHoldingDeadlySword() : bool
  2925. {
  2926. return isHoldingDeadlySword;
  2927. }
  2928.  
  2929. event OnHolsteredItem( category : name, slotName : name )
  2930. {
  2931. var weaponType : EPlayerWeapon;
  2932.  
  2933. //hide HUD buff icon
  2934. if ( slotName == 'r_weapon' && (category == 'steelsword' || category == 'silversword') )
  2935. {
  2936. if( category == 'silversword' )
  2937. {
  2938. ManageAerondightBuff( false );
  2939. }
  2940.  
  2941. GetBuff( EET_LynxSetBonus ).Pause( 'drawing weapon' );
  2942.  
  2943. PauseOilBuffs( category == 'steelsword' );
  2944. }
  2945.  
  2946. if ( slotName == 'r_weapon' )
  2947. {
  2948. weaponType = weaponHolster.GetCurrentMeleeWeapon();
  2949. switch ( category )
  2950. {
  2951. case 'fist' :
  2952. if ( weaponType == PW_Fists )
  2953. weaponHolster.OnEquippedMeleeWeapon( PW_None );
  2954. return true;
  2955. case 'steelsword' :
  2956. if ( weaponType == PW_Steel )
  2957. weaponHolster.OnEquippedMeleeWeapon( PW_None );
  2958. return true;
  2959. case 'silversword' :
  2960. if ( weaponType == PW_Silver )
  2961. weaponHolster.OnEquippedMeleeWeapon( PW_None );
  2962. return true;
  2963. default :
  2964. return true;
  2965. }
  2966. }
  2967. }
  2968.  
  2969. event OnEquipMeleeWeapon( weaponType : EPlayerWeapon, ignoreActionLock : bool, optional sheatheIfAlreadyEquipped : bool )
  2970. {
  2971. RemoveTimer( 'DelayedSheathSword' );
  2972.  
  2973. weaponHolster.OnEquipMeleeWeapon( weaponType, ignoreActionLock, sheatheIfAlreadyEquipped );
  2974.  
  2975. /*// Check if we want to go to combat or exploration
  2976. if( weaponHolster.GetCurrentMeleeWeapon() == PW_None )
  2977. {
  2978. GoToExplorationIfNeeded( );
  2979. }
  2980. else
  2981. {
  2982. GoToCombatIfNeeded( );
  2983. }*/
  2984.  
  2985. m_RefreshWeaponFXType = true;
  2986. }
  2987.  
  2988. event OnHolsterLeftHandItem()
  2989. {
  2990. weaponHolster.OnHolsterLeftHandItem();
  2991. }
  2992.  
  2993. timer function DelayedTryToReequipWeapon( dt: float, id : int )
  2994. {
  2995. var weaponType : EPlayerWeapon;
  2996.  
  2997. if( IsInCombat() && GetTarget() )
  2998. {
  2999. weaponType = GetMostConvenientMeleeWeapon( GetTarget() );
  3000.  
  3001. if ( weaponType == PW_Steel || weaponType == PW_Silver )
  3002. weaponHolster.OnEquipMeleeWeapon( weaponType, false );
  3003. }
  3004. }
  3005.  
  3006. timer function DelayedSheathSword( dt: float, id : int )
  3007. {
  3008. if ( !IsCombatMusicEnabled() )
  3009. {
  3010. if ( IsInCombatAction() || !IsActionAllowed( EIAB_DrawWeapon ) )
  3011. {
  3012. LogChannel( 'OnCombatFinished', "DelayedSheathSword: Sheath pushed to buffer" );
  3013. PushCombatActionOnBuffer(EBAT_Sheathe_Sword,BS_Pressed);
  3014. }
  3015. else
  3016. {
  3017. LogChannel( 'OnCombatFinished', "DelayedSheathSword: Sheath successful" );
  3018. OnEquipMeleeWeapon( PW_None, false );
  3019. }
  3020. }
  3021. }
  3022.  
  3023. protected function ShouldAutoSheathSwordInstantly() : bool
  3024. {
  3025. var enemies : array<CActor>;
  3026. var i : int;
  3027.  
  3028. GetEnemiesInRange( enemies );
  3029.  
  3030. for ( i = 0; i < enemies.Size(); i += 1 )
  3031. {
  3032. if ( IsThreat( enemies[i] ) &&
  3033. VecDistance( enemies[i].GetWorldPosition(), this.GetWorldPosition() ) <= findMoveTargetDist )
  3034. {
  3035. return false;
  3036. }
  3037. }
  3038.  
  3039. return true;
  3040. }
  3041.  
  3042. public function PrepareToAttack( optional target : CActor, optional action : EBufferActionType )
  3043. {
  3044. var weaponType : EPlayerWeapon;
  3045.  
  3046. if( IsInAir() || !GetBIsCombatActionAllowed() )
  3047. {
  3048. return ;
  3049. }
  3050.  
  3051. if( !target )
  3052. {
  3053. target = (CActor)displayTarget;
  3054. }
  3055. if( !target && IsCombatMusicEnabled() )
  3056. {
  3057. target = moveTarget;
  3058. }
  3059. if( !target )
  3060. {
  3061. if ( this.GetCurrentStateName() == 'Exploration' )
  3062. {
  3063. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  3064. thePlayer.CanAttackWhenNotInCombat( action, false, target );
  3065. }
  3066. }
  3067.  
  3068. weaponHolster.TryToPrepareMeleeWeaponToAttack();
  3069.  
  3070. //if ( this.GetCurrentStateName() == 'Exploration' ) //PF - commenting this because Geralt won't switch to proper state when you sheathe sword while mashing attack
  3071. {
  3072. weaponType = GetCurrentMeleeWeaponType();
  3073.  
  3074. if ( weaponType == PW_None )
  3075. {
  3076. // Get the weapon we have to use
  3077. weaponType = GetMostConvenientMeleeWeapon( target );
  3078. }
  3079.  
  3080. // Can't go to combat if we are in not a proper state
  3081. if( !OnStateCanGoToCombat() )
  3082. {
  3083. return;
  3084. }
  3085.  
  3086. GoToCombat( weaponType );
  3087. }
  3088. }
  3089.  
  3090. public function DisplayCannotAttackMessage( actor : CActor ) : bool
  3091. {
  3092. if ( actor && ( actor.GetMovingAgentComponent().GetName() == "child_base" || ((CNewNPC)actor).GetNPCType() == ENGT_Quest ) )
  3093. {
  3094. DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_cant_attack_this_target"));
  3095. return true;
  3096. }
  3097.  
  3098. return false;
  3099. }
  3100.  
  3101. public function GetMostConvenientMeleeWeapon( targetToDrawAgainst : CActor, optional ignoreActionLock : bool ) : EPlayerWeapon
  3102. {
  3103. return weaponHolster.GetMostConvenientMeleeWeapon( targetToDrawAgainst, ignoreActionLock );
  3104. }
  3105.  
  3106. private var reevaluateCurrentWeapon : bool;
  3107.  
  3108. event OnTargetWeaponDrawn()
  3109. {
  3110. var weaponType : EPlayerWeapon = this.GetCurrentMeleeWeaponType();
  3111. if ( weaponType == PW_Fists )
  3112. reevaluateCurrentWeapon = true;
  3113. }
  3114.  
  3115. public function GoToCombatIfNeeded( optional enemy : CActor ) : bool
  3116. {
  3117. var weaponType : EPlayerWeapon;
  3118. var target : CActor;
  3119.  
  3120. if( !enemy && IsInCombat() )
  3121. {
  3122. target = GetTarget();
  3123.  
  3124. if ( target )
  3125. enemy = target;
  3126. else
  3127. enemy = moveTarget;
  3128. }
  3129.  
  3130. // Should we fight
  3131. if( !ShouldGoToCombat( enemy ) )
  3132. {
  3133. return false;
  3134. }
  3135.  
  3136. weaponType = this.GetCurrentMeleeWeaponType();
  3137.  
  3138. if ( weaponType == PW_None || ( reevaluateCurrentWeapon && weaponType == PW_Fists ) || ( !IsInCombat() && weaponHolster.IsOnTheMiddleOfHolstering() ) )
  3139. {
  3140. // Get the weapon we have to use
  3141. weaponType = weaponHolster.GetMostConvenientMeleeWeapon( enemy );
  3142. reevaluateCurrentWeapon = false;
  3143. }
  3144.  
  3145. // Change the state+
  3146. GoToCombat( weaponType );
  3147.  
  3148.  
  3149. return true;
  3150. }
  3151.  
  3152. public function GoToCombatIfWanted( ) : bool
  3153. {
  3154. var weaponType : EPlayerWeapon;
  3155. var target : CActor;
  3156. var enemy : CActor;
  3157.  
  3158.  
  3159. if( !IsInCombat() )
  3160. {
  3161. return false;
  3162. }
  3163.  
  3164. target = GetTarget();
  3165.  
  3166. if ( target )
  3167. enemy = target;
  3168. else
  3169. enemy = moveTarget;
  3170.  
  3171. weaponType = this.GetCurrentMeleeWeaponType();
  3172.  
  3173. if ( weaponType == PW_None || ( !IsInCombat() && weaponHolster.IsOnTheMiddleOfHolstering() ) )
  3174. {
  3175. // Get the weapon we have to use
  3176. weaponType = weaponHolster.GetMostConvenientMeleeWeapon( enemy );
  3177. }
  3178.  
  3179. // Change the state+
  3180. GoToCombat( weaponType );
  3181.  
  3182.  
  3183. return true;
  3184. }
  3185.  
  3186. public function GoToExplorationIfNeeded() : bool
  3187. {
  3188. /*
  3189. if( GetCurrentStateName() == 'Exploration' )
  3190. {
  3191. return false;
  3192. }
  3193. */
  3194.  
  3195. if( ! IsInCombatState() )
  3196. {
  3197. return false;
  3198. }
  3199.  
  3200. if( !ShouldGoToExploration() )
  3201. {
  3202. return false;
  3203. }
  3204.  
  3205. // Change fists weapon to none
  3206. weaponHolster.EndedCombat();
  3207.  
  3208. // Change the state
  3209. GotoState( 'Exploration' );
  3210. return true;
  3211. }
  3212.  
  3213. event OnStateCanGoToCombat()
  3214. {
  3215. return false;
  3216. }
  3217.  
  3218. event OnStateCanUpdateExplorationSubstates()
  3219. {
  3220. return false;
  3221. }
  3222.  
  3223. private function ShouldGoToCombat( optional enemy : CActor ) : bool
  3224. {
  3225. var currentStateName : name;
  3226.  
  3227. // Can't go to combat if we are in not a proper state
  3228. if( !OnStateCanGoToCombat() )
  3229. {
  3230. return false;
  3231. }
  3232.  
  3233. currentStateName = GetCurrentStateName();
  3234.  
  3235. if( currentStateName == 'AimThrow' )
  3236. {
  3237. return false;
  3238. }
  3239.  
  3240. if( currentStateName == 'Swimming' )
  3241. {
  3242. return false;
  3243. }
  3244.  
  3245. if( currentStateName == 'TraverseExploration' )
  3246. {
  3247. return false;
  3248. }
  3249.  
  3250. // TODO: Reenable or find somethingbetter
  3251. // Temporaryly disabled cause it does not work on some terrain
  3252. /*
  3253. if ( !theGame.GetWorld().NavigationLineTest( GetWorldPosition(), enemy.GetWorldPosition(), 0.4 ) )
  3254. {
  3255. return false;
  3256. }
  3257. */
  3258.  
  3259. // if there is no enemy, check if combat is forced
  3260. if ( !enemy )
  3261. {
  3262. return playerMode.combatMode;
  3263. }
  3264.  
  3265. // See if we should be fighting this enemy
  3266. /*if ( !IsEnemyVisible( enemy ) )
  3267. {
  3268. return false;
  3269. }*/
  3270. /*if ( !WasVisibleInScaledFrame( enemy, 1.f, 1.f ) )
  3271. {
  3272. return false;
  3273. }*/
  3274.  
  3275. return true;
  3276. }
  3277.  
  3278. private function ShouldGoToExploration() : bool
  3279. {
  3280. if ( IsInCombat() )//moveTarget && IsThreat( moveTarget ) )
  3281. {
  3282. return false;
  3283. }
  3284. /*if( IsGuarded() )
  3285. {
  3286. return false;
  3287. }*/
  3288. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  3289. {
  3290. return false;
  3291. }
  3292. if( IsFistFightMinigameEnabled() )
  3293. {
  3294. return false;
  3295. }
  3296. if( IsKnockedUnconscious() )
  3297. {
  3298. return false;
  3299. }
  3300. if( IsInCombatAction() )
  3301. {
  3302. return false;
  3303. }
  3304. if( GetCriticalBuffsCount() > 0 )
  3305. {
  3306. return false;
  3307. }
  3308.  
  3309. return true;
  3310. }
  3311.  
  3312. private function GoToCombat( weaponType : EPlayerWeapon, optional initialAction : EInitialAction )
  3313. {
  3314. // Set up and change state
  3315. switch( weaponType )
  3316. {
  3317. case PW_Silver:
  3318. ((W3PlayerWitcherStateCombatSilver) GetState('CombatSilver')).SetupState( initialAction );
  3319. GoToStateIfNew( 'CombatSilver' );
  3320. break;
  3321. case PW_Steel:
  3322. ((W3PlayerWitcherStateCombatSteel) GetState('CombatSteel')).SetupState( initialAction );
  3323. GoToStateIfNew( 'CombatSteel' );
  3324. break;
  3325. case PW_Fists:
  3326. case PW_None:
  3327. default :
  3328. ((W3PlayerWitcherStateCombatFists) GetState('CombatFists')).SetupState( initialAction );
  3329. GoToStateIfNew( 'CombatFists' );
  3330. break;
  3331. }
  3332. }
  3333.  
  3334. public function GoToStateIfNew( newState : name, optional keepStack : bool, optional forceEvents : bool )
  3335. {
  3336. if( newState != GetCurrentStateName() )
  3337. {
  3338. GotoState( newState, keepStack, forceEvents );
  3339. }
  3340. }
  3341.  
  3342. // So we can debug and control what is changing the state
  3343. public function GotoState( newState : name, optional keepStack : bool, optional forceEvents : bool )
  3344. {
  3345. /*if( newState == 'Exploration' )
  3346. {
  3347. newState = newState;
  3348. }*/
  3349.  
  3350. super.GotoState( newState, keepStack, forceEvents );
  3351. //PushState( newState );
  3352. }
  3353. /*
  3354. public function PushState( newState : name )
  3355. {
  3356. if( newState == 'Exploration' )
  3357. {
  3358. newState = newState;
  3359. }
  3360. super.PushState( newState );
  3361. }
  3362.  
  3363. public function PopState( optional popAll : bool )
  3364. {
  3365. super.PopState( popAll );
  3366. }
  3367. */
  3368. public function IsThisACombatSuperState( stateName : name ) : bool
  3369. {
  3370. return stateName == 'Combat' || stateName == 'CombatSteel' || stateName == 'CombatSilver' || stateName == 'CombatFists';
  3371. }
  3372.  
  3373. public function GetWeaponHolster() : WeaponHolster
  3374. {
  3375. return weaponHolster;
  3376. }
  3377.  
  3378. public function AbortSign()
  3379. {
  3380. var playerWitcher : W3PlayerWitcher;
  3381. var sign : W3SignEntity;
  3382.  
  3383. playerWitcher = (W3PlayerWitcher)this;
  3384.  
  3385. if(playerWitcher)
  3386. {
  3387. sign = (W3SignEntity)playerWitcher.GetCurrentSignEntity();
  3388. if (sign)
  3389. {
  3390. sign.OnSignAborted();
  3391. }
  3392. }
  3393. }
  3394.  
  3395. ///////////////////////////////////////////////////////////////////////////
  3396. // Animation event handlers
  3397. ///////////////////////////////////////////////////////////////////////////
  3398. protected var disableActionBlend : bool;
  3399.  
  3400. //KonradSuperDodgeHACK: To make dodge more responsive during NORMAL ATTACKS, dodge will fire immediately when hit animation can be played.
  3401. //When hit anim is disabled, then the action will be cached and will be processed at the END of DisallowHitAnim event.
  3402. //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.
  3403. event OnAnimEvent_DisallowHitAnim( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3404. {
  3405. if ( animEventType == AET_DurationEnd )
  3406. {
  3407. if ( ( BufferCombatAction == EBAT_Dodge || BufferCombatAction == EBAT_Roll )
  3408. && IsInCombatAction()
  3409. && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack )
  3410. {
  3411. //LogChannel('combatActionAllowed',"BufferCombatAction != EBAT_EMPTY");
  3412. ( (CR4Player)this ).ProcessCombatActionBuffer();
  3413. disableActionBlend = true;
  3414. }
  3415. }
  3416. else if ( IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge && animEventType == AET_DurationStart )
  3417. {
  3418. disableActionBlend = false;
  3419. }
  3420.  
  3421. super.OnAnimEvent_DisallowHitAnim( animEventName, animEventType, animInfo );
  3422. }
  3423.  
  3424.  
  3425. event OnAnimEvent_FadeOut( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3426. {
  3427. theGame.FadeOutAsync( 0.2, Color( 0, 0, 0, 1 ) );
  3428. }
  3429.  
  3430. event OnAnimEvent_FadeIn( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3431. {
  3432. theGame.FadeInAsync( 0.4 );
  3433. }
  3434.  
  3435. event OnAnimEvent_BloodTrailForced( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3436. {
  3437. var bloodTrailParam : CBloodTrailEffect;
  3438. var weaponId : SItemUniqueId;
  3439.  
  3440. if ( isInFinisher )
  3441. {
  3442. bloodTrailParam = (CBloodTrailEffect)(GetFinisherVictim()).GetGameplayEntityParam( 'CBloodTrailEffect' );
  3443. weaponId = this.inv.GetItemFromSlot('r_weapon');
  3444. if ( bloodTrailParam )
  3445. thePlayer.inv.PlayItemEffect( weaponId, bloodTrailParam.GetEffectName() );
  3446. }
  3447. }
  3448.  
  3449. event OnAnimEvent_SlowMo( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3450. {
  3451. if ( isInFinisher && DisableManualCameraControlStackHasSource( 'Finisher' ) )
  3452. {
  3453. if( animEventType != AET_DurationEnd )
  3454. theGame.SetTimeScale( 0.1f, 'AnimEventSlomoMo', 1000, true );
  3455. else
  3456. theGame.RemoveTimeScale( 'AnimEventSlomoMo' );
  3457. }
  3458. }
  3459.  
  3460. event OnAnimEvent_PlayFinisherBlood( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3461. {
  3462. if ( isInFinisher )
  3463. {
  3464. SpawnFinisherBlood();
  3465. }
  3466. }
  3467.  
  3468. event OnAnimEvent_OnWeaponDrawReady( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3469. {
  3470. weaponHolster.OnWeaponDrawReady();
  3471. }
  3472.  
  3473. event OnAnimEvent_OnWeaponHolsterReady( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3474. {
  3475. weaponHolster.OnWeaponHolsterReady();
  3476. }
  3477.  
  3478. event OnAnimEvent_ThrowHoldTest( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3479. {
  3480. var thrownEntity : CThrowable;
  3481.  
  3482. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  3483.  
  3484. if( IsThrowHold() )
  3485. {
  3486. SetBehaviorVariable( 'throwStage', (int)TS_Loop );
  3487. PushState( 'AimThrow' );
  3488. thrownEntity.StartAiming();
  3489. }
  3490. else
  3491. {
  3492. BombThrowRelease();
  3493. SetCombatIdleStance( 1.f );
  3494. }
  3495. }
  3496.  
  3497. event OnAnimEvent_AllowTempLookAt( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3498. {
  3499. if( animEventType == AET_DurationStart )
  3500. SetTempLookAtTarget( slideTarget );
  3501. else if( animEventType == AET_DurationEnd )
  3502. SetTempLookAtTarget( NULL );
  3503. }
  3504.  
  3505. protected var slideNPC : CNewNPC;
  3506. protected var minSlideDistance : float;
  3507. protected var maxSlideDistance : float;
  3508. protected var slideTicket : SMovementAdjustmentRequestTicket;
  3509.  
  3510. event OnAnimEvent_SlideToTarget( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3511. {
  3512. var movementAdjustor : CMovementAdjustor;
  3513.  
  3514. if( animEventType == AET_DurationStart )
  3515. {
  3516. slideNPC = (CNewNPC)slideTarget;
  3517. }
  3518.  
  3519. if( !slideNPC )
  3520. {
  3521. return false;
  3522. }
  3523.  
  3524. if( animEventType == AET_DurationStart && slideNPC.GetGameplayVisibility() )
  3525. {
  3526. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3527. slideTicket = movementAdjustor.GetRequest( 'SlideToTarget' );
  3528. movementAdjustor.CancelByName( 'SlideToTarget' );
  3529. slideTicket = movementAdjustor.CreateNewRequest( 'SlideToTarget' );
  3530. movementAdjustor.BindToEventAnimInfo( slideTicket, animInfo );
  3531. //movementAdjustor.Continuous(slideTicket);
  3532. movementAdjustor.MaxLocationAdjustmentSpeed( slideTicket, 1000000 );
  3533. movementAdjustor.ScaleAnimation( slideTicket );
  3534. minSlideDistance = ((CMovingPhysicalAgentComponent)this.GetMovingAgentComponent()).GetCapsuleRadius()+((CMovingPhysicalAgentComponent)slideNPC.GetMovingAgentComponent()).GetCapsuleRadius();
  3535. if( IsInCombatFist() )
  3536. {
  3537. maxSlideDistance = 1000.0f;
  3538. }
  3539. else
  3540. {
  3541. maxSlideDistance = minSlideDistance;
  3542. }
  3543. movementAdjustor.SlideTowards( slideTicket, slideTarget, minSlideDistance, maxSlideDistance );
  3544. }
  3545. else if( !slideNPC.GetGameplayVisibility() )
  3546. {
  3547. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3548. movementAdjustor.CancelByName( 'SlideToTarget' );
  3549. slideNPC = NULL;
  3550. }
  3551. else
  3552. {
  3553. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3554. movementAdjustor.SlideTowards( slideTicket, slideTarget, minSlideDistance, maxSlideDistance );
  3555. }
  3556. }
  3557.  
  3558. event OnAnimEvent_ActionBlend( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3559. {
  3560. }
  3561. /*
  3562. event OnAnimEvent_Throwable( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3563. {
  3564. var thrownEntity : CThrowable;
  3565.  
  3566. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  3567.  
  3568. if ( inv.IsItemCrossbow( inv.GetItemFromSlot('l_weapon') ) && rangedWeapon.OnProcessThrowEvent( animEventName ) )
  3569. {
  3570. return true;
  3571. }
  3572. else if( thrownEntity && IsThrowingItem() && thrownEntity.OnProcessThrowEvent( animEventName ) )
  3573. {
  3574. return true;
  3575. }
  3576. }*/
  3577.  
  3578. event OnAnimEvent_SubstateManager( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3579. {
  3580. // Notify the exploration manager
  3581. substateManager.OnAnimEvent( animEventName, animEventType, animInfo );
  3582. }
  3583.  
  3584. event OnAnimEvent_AllowFall( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3585. {
  3586. if ( !substateManager.m_OwnerMAC.IsOnGround() )
  3587. {
  3588. substateManager.m_SharedDataO.SetFallFromCritical( true );
  3589. substateManager.m_MoverO.SetVelocity( -6.0f * GetWorldForward() );
  3590. substateManager.QueueStateExternal( 'Jump' );
  3591. RemoveBuff( EET_Knockdown, true );
  3592. RemoveBuff( EET_HeavyKnockdown, true );
  3593. return true;
  3594. }
  3595. return false;
  3596. }
  3597.  
  3598. event OnAnimEvent_AllowFall2( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3599. {
  3600. if ( !substateManager.m_OwnerMAC.IsOnGround() )
  3601. {
  3602. //substateManager.m_SharedDataO.m_FromCriticalB = true;
  3603. //substateManager.m_MoverO.SetVelocity( -6.0f * GetWorldForward() );
  3604. substateManager.QueueStateExternal( 'Jump' );
  3605. RemoveBuff( EET_Knockdown, true );
  3606. RemoveBuff( EET_HeavyKnockdown, true );
  3607. }
  3608. if( substateManager.StateWantsAndCanEnter( 'Slide' ) )
  3609. {
  3610. substateManager.QueueStateExternal( 'Slide' );
  3611. }
  3612. }
  3613.  
  3614. event OnAnimEvent_DettachGround( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3615. {
  3616. //substateManager.m_MoverO.SetManualMovement( true );
  3617. }
  3618.  
  3619. //pad vibration for finishers
  3620. event OnAnimEvent_pad_vibration( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3621. {
  3622. var witcher : W3PlayerWitcher;
  3623.  
  3624. theGame.VibrateControllerHard();
  3625.  
  3626. //delayed FX for runeword 10 & 12
  3627. witcher = GetWitcherPlayer();
  3628. if(isInFinisher && witcher)
  3629. {
  3630. if(HasAbility('Runeword 10 _Stats', true) && !witcher.runeword10TriggerredOnFinisher && ((bool)theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'AutomaticFinishersEnabled')) == true)
  3631. {
  3632. witcher.Runeword10Triggerred();
  3633. witcher.runeword10TriggerredOnFinisher = true;
  3634. }
  3635. else if(HasAbility('Runeword 12 _Stats', true) && !witcher.runeword12TriggerredOnFinisher)
  3636. {
  3637. witcher.Runeword12Triggerred();
  3638. witcher.runeword12TriggerredOnFinisher = true;
  3639. }
  3640. }
  3641. }
  3642.  
  3643. //pad vibration light
  3644. event OnAnimEvent_pad_vibration_light( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3645. {
  3646. //theGame.VibrateControllerLight(); //draw & sheathe weapon
  3647. }
  3648.  
  3649. event OnAnimEvent_KillWithRagdoll( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3650. {
  3651. //thePlayer.SetKinematic( false );
  3652. //thePlayer.Kill();
  3653. }
  3654.  
  3655. event OnAnimEvent_RemoveBurning( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3656. {
  3657. thePlayer.AddBuffImmunity(EET_Burning, 'AnimEvent_RemoveBurning', true);
  3658. }
  3659.  
  3660. event OnAnimEvent_RemoveTangled( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3661. {
  3662. if ( this.HasBuff( EET_Tangled ) )
  3663. {
  3664. this.StopEffect('black_spider_web');
  3665. this.PlayEffectSingle('black_spider_web_break');
  3666. }
  3667. }
  3668.  
  3669. // sound generation for creatures following noise instead of just finding combat target
  3670. event OnAnimEvent_MoveNoise( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  3671. {
  3672. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'MoveNoise', -1, 30.0f, -1.f, -1, true );
  3673. }
  3674. ///////////////////////////////////////////////////////////////////////////
  3675.  
  3676. event OnBehaviorGraphNotification( notificationName : name, stateName : name )
  3677. {
  3678. substateManager.OnBehaviorGraphNotification( notificationName, stateName );
  3679.  
  3680. if( notificationName == 'PlayerRunActivate' )
  3681. {
  3682. isInRunAnimation = true;
  3683. }
  3684. else if( notificationName == 'PlayerRunDeactivate' )
  3685. {
  3686. isInRunAnimation = false;
  3687. }
  3688. }
  3689.  
  3690. event OnEnumAnimEvent( animEventName : name, variant : SEnumVariant, animEventType : EAnimationEventType, animEventDuration : float, animInfo : SAnimationEventAnimInfo )
  3691. {
  3692. var movementAdjustor : CMovementAdjustor;
  3693. var ticket : SMovementAdjustmentRequestTicket;
  3694. var rotationRate : ERotationRate;
  3695.  
  3696. if ( animEventName == 'RotateToTarget' )
  3697. {
  3698. /**
  3699. * Rotate player to target
  3700. */
  3701. rotationRate = GetRotationRateFromAnimEvent( variant.enumValue );
  3702.  
  3703. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  3704. if ( animEventType == AET_DurationStart || animEventType == AET_DurationStartInTheMiddle )
  3705. {
  3706. // when it starts (also in the middle - it may mean that we switch between events)
  3707. // create request if there isn't any and always setup rotation rate
  3708. if (! movementAdjustor.IsRequestActive( movementAdjustor.GetRequest( 'RotateToTarget' ) ) )
  3709. {
  3710. // start rotation adjustment
  3711. ticket = movementAdjustor.CreateNewRequest( 'RotateToTarget' );
  3712.  
  3713. // use adjustment duration only when RR_0 is selected, otherwise use continuous to match desired rotation as fast as possible
  3714. if ((int)rotationRate == 0)
  3715. movementAdjustor.AdjustmentDuration( ticket, animEventDuration );
  3716. else
  3717. {
  3718. movementAdjustor.Continuous( ticket );
  3719. movementAdjustor.BindToEvent( ticket, 'RotateToTarget' );
  3720. }
  3721.  
  3722. movementAdjustor.DontUseSourceAnimation( ticket ); // do not use source anim as it will use delta seconds from event
  3723. movementAdjustor.ReplaceRotation( ticket );
  3724. }
  3725. else
  3726. {
  3727. // get existing ticket to update rotation rate
  3728. ticket = movementAdjustor.GetRequest( 'RotateToTarget' );
  3729. }
  3730. MovAdjRotateToTarget( ticket );
  3731. // update rotationRate
  3732. if ((int)rotationRate > 0)
  3733. {
  3734. movementAdjustor.MaxRotationAdjustmentSpeed( ticket, (float)((int)rotationRate) );
  3735. }
  3736. }
  3737. else if ( animEventType == AET_DurationEnd )
  3738. {
  3739. // it will end if there's no event, but sometimes one event could end and be followed by another
  3740. // and we want to have that continuity kept, that's why we won't end request manually
  3741. }
  3742. else
  3743. {
  3744. // continuous update (makes more sense when there is no target and we want to rotate towards camera)
  3745. ticket = movementAdjustor.GetRequest( 'RotateToTarget' );
  3746. MovAdjRotateToTarget( ticket );
  3747. }
  3748. }
  3749. super.OnEnumAnimEvent(animEventName, variant, animEventType, animEventDuration, animInfo);
  3750. }
  3751.  
  3752. event OnTeleported()
  3753. {
  3754. if( substateManager )
  3755. {
  3756. substateManager.OnTeleported();
  3757. }
  3758. }
  3759.  
  3760. /*public function CaptureSafePosition()
  3761. {
  3762. lastSafePosition = GetWorldPosition();
  3763. lastSafeRotation = GetWorldRotation();
  3764. safePositionStored = true;
  3765. }*/
  3766.  
  3767. ///////////////////////////////////////////////////////////////////////////
  3768. // FISTFIGHT
  3769. ///////////////////////////////////////////////////////////////////////////
  3770. event OnStartFistfightMinigame()
  3771. {
  3772. super.OnStartFistfightMinigame();
  3773.  
  3774. //Goto state CombatFist
  3775. SetFistFightMinigameEnabled( true );
  3776. FistFightHealthChange( true );
  3777. thePlayer.GetPlayerMode().ForceCombatMode( FCMR_QuestFunction );
  3778. SetImmortalityMode(AIM_Unconscious, AIC_Fistfight);
  3779. thePlayer.SetBehaviorVariable( 'playerWeaponLatent', (int)PW_Fists );
  3780. GotoCombatStateWithAction( IA_None );
  3781. ((CMovingAgentComponent)this.GetMovingAgentComponent()).SnapToNavigableSpace( true );
  3782. EquipGeraltFistfightWeapon( true );
  3783. BlockAction( EIAB_RadialMenu, 'FistfightMinigame' ,,true);
  3784. BlockAction( EIAB_Signs, 'FistfightMinigame' ,,true);
  3785. BlockAction( EIAB_ThrowBomb, 'FistfightMinigame' ,,true);
  3786. BlockAction( EIAB_UsableItem, 'FistfightMinigame' ,,true);
  3787. BlockAction( EIAB_Crossbow, 'FistfightMinigame' ,,true);
  3788. BlockAction( EIAB_DrawWeapon, 'FistfightMinigame' ,,true);
  3789. BlockAction( EIAB_RunAndSprint, 'FistfightMinigame' ,,true);
  3790. BlockAction( EIAB_SwordAttack, 'FistfightMinigame' ,,true);
  3791. BlockAction( EIAB_CallHorse, 'FistfightMinigame' ,,true);
  3792. BlockAction( EIAB_Roll, 'FistfightMinigame' ,,true);
  3793. BlockAction( EIAB_Interactions, 'FistfightMinigame' ,,true);
  3794. BlockAction( EIAB_Explorations, 'FistfightMinigame' ,,true);
  3795. BlockAction( EIAB_OpenInventory, 'FistfightMinigame' ,,true);
  3796. BlockAction( EIAB_QuickSlots, 'FistfightMinigame' ,,true);
  3797. BlockAction( EIAB_OpenCharacterPanel, 'FistfightMinigame' ,,true);
  3798. }
  3799.  
  3800. event OnEndFistfightMinigame()
  3801. {
  3802. ((CMovingAgentComponent)this.GetMovingAgentComponent()).SnapToNavigableSpace( false );
  3803. FistFightHealthChange( false );
  3804. thePlayer.GetPlayerMode().ReleaseForceCombatMode( FCMR_QuestFunction );
  3805. EquipGeraltFistfightWeapon( false );
  3806. SetFistFightMinigameEnabled( false );
  3807. SetImmortalityMode(AIM_None, AIC_Fistfight);
  3808. BlockAllActions('FistfightMinigame',false);
  3809.  
  3810. super.OnEndFistfightMinigame();
  3811. }
  3812.  
  3813. public function GetFistFightFinisher( out masterAnimName, slaveAnimIndex : name )
  3814. {
  3815. var index : int;
  3816.  
  3817. index = RandRange(1);
  3818. switch ( index )
  3819. {
  3820. case 0 : masterAnimName = 'man_fistfight_finisher_1_win'; slaveAnimIndex = 'man_fistfight_finisher_1_looser';
  3821. }
  3822. }
  3823.  
  3824. public function SetFistFightMinigameEnabled( flag : bool )
  3825. {
  3826. fistFightMinigameEnabled = flag;
  3827. }
  3828.  
  3829. public function SetFistFightParams( toDeath : bool, endsWithBS : bool )
  3830. {
  3831. isFFMinigameToTheDeath = toDeath;
  3832. FFMinigameEndsithBS = endsWithBS;
  3833. }
  3834.  
  3835. public function IsFistFightMinigameEnabled() : bool
  3836. {
  3837. return fistFightMinigameEnabled;
  3838. }
  3839.  
  3840. public function IsFistFightMinigameToTheDeath() : bool
  3841. {
  3842. return isFFMinigameToTheDeath;
  3843. }
  3844.  
  3845. public function FistFightHealthChange( val : bool )
  3846. {
  3847. if( val == true )
  3848. {
  3849. GeraltMaxHealth = thePlayer.GetStatMax(BCS_Vitality);
  3850. ClampGeraltMaxHealth( 2000 );
  3851. SetHealthPerc( 100 );
  3852. }
  3853. else
  3854. {
  3855. ClampGeraltMaxHealth( GeraltMaxHealth );
  3856. SetHealthPerc( 100 );
  3857. }
  3858.  
  3859. }
  3860.  
  3861. function ClampGeraltMaxHealth( val : float )
  3862. {
  3863. thePlayer.abilityManager.SetStatPointMax( BCS_Vitality, val );
  3864. }
  3865.  
  3866. function EquipGeraltFistfightWeapon( val : bool )
  3867. {
  3868. if ( val )
  3869. {
  3870. fistsItems = thePlayer.GetInventory().AddAnItem( 'Geralt Fistfight Fists', 1, true, true );
  3871. thePlayer.GetInventory().MountItem( fistsItems[0] , true );
  3872. }
  3873. else
  3874. {
  3875. thePlayer.GetInventory().DropItem( fistsItems[0], true );
  3876. }
  3877. }
  3878.  
  3879. ///////////////////////////////////////////////////////////////////////////
  3880. // GWINT
  3881. ///////////////////////////////////////////////////////////////////////////
  3882. public function GetGwintAiDifficulty() : EGwintDifficultyMode
  3883. {
  3884. return gwintAiDifficulty;
  3885. }
  3886.  
  3887. public function SetGwintAiDifficulty( difficulty : EGwintDifficultyMode )
  3888. {
  3889. gwintAiDifficulty = difficulty;
  3890. }
  3891.  
  3892. public function GetGwintAiAggression() : EGwintAggressionMode
  3893. {
  3894. return gwintAiAggression;
  3895. }
  3896.  
  3897. public function SetGwintAiAggression( aggression : EGwintAggressionMode )
  3898. {
  3899. gwintAiAggression = aggression;
  3900. }
  3901.  
  3902. public function GetGwintMinigameState() : EMinigameState
  3903. {
  3904. return gwintMinigameState;
  3905. }
  3906.  
  3907. public function SetGwintMinigameState( minigameState : EMinigameState )
  3908. {
  3909. gwintMinigameState = minigameState;
  3910. }
  3911.  
  3912. public function OnGwintGameRequested( deckName : name, forceFaction : eGwintFaction )
  3913. {
  3914. var gwintManager:CR4GwintManager;
  3915. gwintManager = theGame.GetGwintManager();
  3916.  
  3917. gwintMinigameState = EMS_None;
  3918.  
  3919. gwintManager.SetEnemyDeckByName(deckName);
  3920. gwintManager.SetForcedFaction(forceFaction);
  3921.  
  3922. if (gwintManager.GetHasDoneTutorial() || !theGame.GetTutorialSystem().AreMessagesEnabled())
  3923. {
  3924. gwintManager.gameRequested = true;
  3925. theGame.RequestMenu( 'DeckBuilder' );
  3926. }
  3927. else
  3928. {
  3929. theGame.GetGuiManager().ShowUserDialog( UMID_SkipGwintTutorial, "gwint_tutorial_play_query_title", "gwint_tutorial_play_query", UDB_YesNo );
  3930. }
  3931. }
  3932.  
  3933. public function StartGwint_TutorialOrSkip( skipTutorial : bool )
  3934. {
  3935. var gwintManager : CR4GwintManager;
  3936.  
  3937. if( skipTutorial )
  3938. {
  3939. gwintManager = theGame.GetGwintManager();
  3940. gwintManager.gameRequested = true;
  3941. gwintManager.SetHasDoneTutorial(true);
  3942. gwintManager.SetHasDoneDeckTutorial(true);
  3943. theGame.RequestMenu( 'DeckBuilder' );
  3944. }
  3945. else
  3946. {
  3947. theGame.RequestMenu( 'GwintGame' );
  3948. }
  3949. }
  3950.  
  3951. private var gwintCardNumbersArray : array<int>;
  3952.  
  3953. public function InitGwintCardNumbersArray( arr : array<int> )
  3954. {
  3955. gwintCardNumbersArray.Clear();
  3956. gwintCardNumbersArray = arr;
  3957. }
  3958.  
  3959. public function GetCardNumbersArray() : array<int>
  3960. {
  3961. return gwintCardNumbersArray;
  3962. }
  3963. ///////////////////////////////////////////////////////////////////////////
  3964. // COMBAT CAMERA
  3965. ///////////////////////////////////////////////////////////////////////////
  3966.  
  3967. protected var customCameraStack : array<SCustomCameraParams>;
  3968.  
  3969. public function AddCustomCamToStack( customCameraParams : SCustomCameraParams ) : int
  3970. {
  3971. if( customCameraParams.useCustomCamera )
  3972. {
  3973. if ( customCameraParams.cameraParams.enums[0].enumType != 'ECustomCameraType' )
  3974. {
  3975. LogChannel( 'CustomCamera', "ERROR: Selected enum is not a custom camera!!!" );
  3976. return -1;
  3977. }
  3978. else
  3979. {
  3980. customCameraStack.PushBack( customCameraParams );
  3981. return ( customCameraStack.Size() - 1 );
  3982. }
  3983. }
  3984.  
  3985. return 0;
  3986. }
  3987.  
  3988. public function DisableCustomCamInStack( customCameraStackIndex : int )
  3989. {
  3990. if ( customCameraStackIndex != -1 )
  3991. customCameraStack[customCameraStackIndex].useCustomCamera = false;
  3992. else
  3993. LogChannel( 'CustomCamera', "ERROR: Custom camera to disable does not exist!!!" );
  3994. }
  3995.  
  3996. event OnInteriorStateChanged( inInterior : bool )
  3997. {
  3998. interiorCamera = inInterior;
  3999. }
  4000.  
  4001. event OnModifyPlayerSpeed( flag : bool )
  4002. {
  4003. modifyPlayerSpeed = flag;
  4004. SetBehaviorVariable( 'modifyPlayerSpeed', (float)modifyPlayerSpeed );
  4005. }
  4006.  
  4007. event OnGameCameraTick( out moveData : SCameraMovementData, dt : float )
  4008. {
  4009. var targetRotation : EulerAngles;
  4010. var dist : float;
  4011.  
  4012. if( thePlayer.IsInCombat() )
  4013. {
  4014. dist = VecDistance2D( thePlayer.GetWorldPosition(), thePlayer.GetTarget().GetWorldPosition() );
  4015. thePlayer.GetVisualDebug().AddText( 'dbg', dist, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) );
  4016. }
  4017.  
  4018. if ( isStartingFistFightMinigame )
  4019. {
  4020. moveData.pivotRotationValue = fistFightTeleportNode.GetWorldRotation();
  4021. isStartingFistFightMinigame = false;
  4022. }
  4023.  
  4024. // Specific substate
  4025. if( substateManager.UpdateCameraIfNeeded( moveData, dt ) )
  4026. {
  4027. return true;
  4028. }
  4029.  
  4030. // focusMode camera
  4031. if ( theGame.IsFocusModeActive() )
  4032. {
  4033. theGame.GetGameCamera().ChangePivotRotationController( 'Exploration' );
  4034. theGame.GetGameCamera().ChangePivotDistanceController( 'Default' );
  4035. theGame.GetGameCamera().ChangePivotPositionController( 'Default' );
  4036.  
  4037. // HACK
  4038. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4039. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  4040. moveData.pivotPositionController = theGame.GetGameCamera().GetActivePivotPositionController();
  4041. // END HACK
  4042.  
  4043.  
  4044. moveData.pivotPositionController.SetDesiredPosition( thePlayer.GetWorldPosition() );
  4045.  
  4046. moveData.pivotRotationController.SetDesiredPitch( -10.0f );
  4047. moveData.pivotRotationController.maxPitch = 50.0;
  4048.  
  4049. moveData.pivotDistanceController.SetDesiredDistance( 3.5f );
  4050.  
  4051. if ( !interiorCamera )
  4052. {
  4053. moveData.pivotPositionController.offsetZ = 1.5f;
  4054. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5f, 2.0f, 0.3f ), 0.20f, dt );
  4055. }
  4056. else
  4057. {
  4058. moveData.pivotPositionController.offsetZ = 1.3f;
  4059. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5f, 2.3f, 0.5f ), 0.3f, dt );
  4060. }
  4061.  
  4062. return true;
  4063. }
  4064.  
  4065.  
  4066.  
  4067. // HACK: Target heading ( Made for ladder )
  4068. if( substateManager.m_SharedDataO.IsForceHeading( targetRotation ) )
  4069. {
  4070. moveData.pivotRotationController.SetDesiredHeading( targetRotation.Yaw );
  4071. moveData.pivotRotationController.SetDesiredPitch( targetRotation.Pitch );
  4072. moveData.pivotRotationValue.Yaw = LerpAngleF( 2.1f * dt, moveData.pivotRotationValue.Yaw, targetRotation.Yaw );
  4073. moveData.pivotRotationValue.Pitch = LerpAngleF( 1.0f * dt, moveData.pivotRotationValue.Pitch, targetRotation.Pitch );
  4074. //return true;
  4075. }
  4076.  
  4077.  
  4078. if( customCameraStack.Size() > 0 )
  4079. {
  4080. // HANDLE CUSTOM CAMERAS HERE
  4081. // IF HANDLED - RETURN TRUE
  4082. }
  4083.  
  4084. return false;
  4085. }
  4086.  
  4087. private var questCameraRequest : SQuestCameraRequest;
  4088. private var cameraRequestTimeStamp : float;
  4089.  
  4090. public function RequestQuestCamera( camera : SQuestCameraRequest )
  4091. {
  4092. questCameraRequest = camera;
  4093. questCameraRequest.requestTimeStamp = theGame.GetEngineTimeAsSeconds();
  4094. }
  4095.  
  4096. public function ResetQuestCameraRequest()
  4097. {
  4098. var cameraRequest : SQuestCameraRequest;
  4099.  
  4100. questCameraRequest = cameraRequest;
  4101. }
  4102.  
  4103. event OnGameCameraPostTick( out moveData : SCameraMovementData, dt : float )
  4104. {
  4105. var ent : CEntity;
  4106. var playerPos : Vector;
  4107. var angles : EulerAngles;
  4108.  
  4109. var distance : float;
  4110.  
  4111. /*if( thePlayer.IsInCombat() )
  4112. {
  4113. distance = VecDistance2D( thePlayer.GetWorldPosition(), thePlayer.GetTarget().GetWorldPosition() );
  4114. }
  4115.  
  4116. thePlayer.GetVisualDebug().AddText( 'Distance', "Distance form target: " + distance, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) );
  4117. */
  4118.  
  4119. if ( questCameraRequest.requestTimeStamp > 0 )
  4120. {
  4121. if ( questCameraRequest.duration > 0 && questCameraRequest.requestTimeStamp + questCameraRequest.duration < theGame.GetEngineTimeAsSeconds() )
  4122. {
  4123. ResetQuestCameraRequest();
  4124. return false;
  4125. }
  4126.  
  4127. if( questCameraRequest.lookAtTag )
  4128. {
  4129. ent = theGame.GetEntityByTag( questCameraRequest.lookAtTag );
  4130. playerPos = GetWorldPosition();
  4131. playerPos.Z += 1.8f;
  4132.  
  4133. angles = VecToRotation( ent.GetWorldPosition() - playerPos );
  4134.  
  4135. moveData.pivotRotationController.SetDesiredHeading( angles.Yaw );
  4136. moveData.pivotRotationController.SetDesiredPitch( -angles.Pitch );
  4137. }
  4138. else
  4139. {
  4140. if( questCameraRequest.requestYaw )
  4141. {
  4142. angles = GetWorldRotation();
  4143. moveData.pivotRotationController.SetDesiredHeading( angles.Yaw + questCameraRequest.yaw );
  4144. }
  4145.  
  4146. if( questCameraRequest.requestPitch )
  4147. {
  4148. moveData.pivotRotationController.SetDesiredPitch( questCameraRequest.pitch );
  4149. }
  4150. }
  4151. }
  4152. }
  4153.  
  4154. var wasRunning : bool;
  4155. var vel : float;
  4156. var smoothTime : float;
  4157.  
  4158. var constDamper : ConstDamper;
  4159. var rotMultVel : float;
  4160.  
  4161. public function UpdateCameraInterior( out moveData : SCameraMovementData, timeDelta : float )
  4162. {
  4163. var camDist : float;
  4164. var camOffset : float;
  4165. var rotMultDest : float;
  4166. var rotMult : float;
  4167. var angles : EulerAngles;
  4168.  
  4169. theGame.GetGameCamera().ChangePivotRotationController( 'ExplorationInterior' );
  4170. theGame.GetGameCamera().ChangePivotDistanceController( 'Default' );
  4171. theGame.GetGameCamera().ChangePivotPositionController( 'Default' );
  4172.  
  4173. // HACK
  4174. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4175. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  4176. moveData.pivotPositionController = theGame.GetGameCamera().GetActivePivotPositionController();
  4177. // END HACK
  4178.  
  4179. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition(), 15.f );
  4180.  
  4181. if ( !constDamper )
  4182. {
  4183. constDamper = new ConstDamper in this;
  4184. constDamper.SetDamp( 0.35f );
  4185. }
  4186.  
  4187. if ( rawPlayerSpeed <= 0 || AbsF( AngleDistance( rawPlayerHeading, GetHeading() ) ) > 135 )
  4188. constDamper.Reset();
  4189. else if ( theGame.IsUberMovementEnabled() )
  4190. rotMult = 0.5f;
  4191. else
  4192. rotMult = 1.f;
  4193.  
  4194. rotMult = constDamper.UpdateAndGet( timeDelta, rotMult );
  4195.  
  4196. //DampFloatSpring( rotMult, rotMultVel, rotMultDest, 4.f, timeDelta );
  4197.  
  4198. if ( AbsF( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) ) < 135.f && rawPlayerSpeed > 0 )
  4199. moveData.pivotRotationController.SetDesiredHeading( GetHeading(), rotMult );
  4200. else
  4201. moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw );
  4202.  
  4203. moveData.pivotDistanceController.SetDesiredDistance( 1.5f );
  4204.  
  4205. angles = VecToRotation( GetMovingAgentComponent().GetVelocity() );
  4206. if ( AbsF( angles.Pitch ) < 8.f || bLAxisReleased )
  4207. moveData.pivotRotationController.SetDesiredPitch( -10.f );
  4208. else
  4209. moveData.pivotRotationController.SetDesiredPitch( -angles.Pitch - 18.f );
  4210.  
  4211. if ( IsGuarded() )
  4212. moveData.pivotPositionController.offsetZ = 1.0f;
  4213. else
  4214. moveData.pivotPositionController.offsetZ = 1.3f;
  4215.  
  4216. //if ( movementLockType == PMLT_NoSprint )
  4217. //{
  4218. if ( playerMoveType >= PMT_Run )
  4219. {
  4220. //camDist = 0.3f;
  4221. camDist = -0.5f;
  4222. camOffset = 0.25;
  4223.  
  4224. if ( !wasRunning )
  4225. {
  4226. smoothTime = 1.f;
  4227. wasRunning = true;
  4228. }
  4229. DampFloatSpring( smoothTime, vel, 0.1, 0.5, timeDelta );
  4230. }
  4231. else
  4232. {
  4233. //camDist = -0.6f;
  4234. camDist = 0.f;
  4235. camOffset = 0.4f;
  4236. smoothTime = 0.2f;
  4237. wasRunning = false;
  4238. }
  4239.  
  4240. //camDist = theGame.GetGameplayConfigFloatValue( 'debugA' );
  4241.  
  4242. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.3f, camDist, 0.3f ), smoothTime, timeDelta );
  4243. //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5, camDist, camOffset ), smoothTime, timeDelta );
  4244. //}
  4245. //else
  4246. // DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( theGame.GetGameplayConfigFloatValue( 'debugA' ),theGame.GetGameplayConfigFloatValue( 'debugB' ),theGame.GetGameplayConfigFloatValue( 'debugC' ) ), 0.4f, timeDelta );
  4247. //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.7f, 0.f, 0.3 ), 0.4f, timeDelta );
  4248. }
  4249.  
  4250.  
  4251. var wasBRAxisPushed : bool;
  4252. protected function UpdateCameraChanneledSign( out moveData : SCameraMovementData, timeDelta : float ) : bool
  4253. {
  4254. var screenSpaceOffset : float;
  4255. var screenSpaceOffsetFwd : float;
  4256. var screenSpaceOffsetUp : float;
  4257. var heading : float;
  4258. var pitch : float;
  4259. var playerToTargetRot : EulerAngles;
  4260. var rightOffset : float = -20.f;
  4261. var leftOffset : float = 15.f;
  4262. var angles : EulerAngles;
  4263.  
  4264. var vec : Vector;
  4265.  
  4266. if( this.IsCurrentSignChanneled() && this.GetCurrentlyCastSign() != ST_Quen && this.GetCurrentlyCastSign() != ST_Yrden )
  4267. {
  4268. theGame.GetGameCamera().ChangePivotRotationController( 'SignChannel' );
  4269. theGame.GetGameCamera().ChangePivotDistanceController( 'SignChannel' );
  4270. // HACK
  4271. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4272. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  4273. // END HACK
  4274.  
  4275. if ( GetCurrentlyCastSign() == ST_Axii )
  4276. leftOffset = 32.f;
  4277.  
  4278. if ( oTCameraOffset != leftOffset && oTCameraOffset != rightOffset )
  4279. {
  4280. if( ( interiorCamera && !moveTarget )
  4281. || ( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) < 0 ) )
  4282. oTCameraOffset = leftOffset;
  4283. else
  4284. oTCameraOffset = rightOffset;
  4285. }
  4286.  
  4287. if ( oTCameraOffset == leftOffset )
  4288. {
  4289. screenSpaceOffset = 0.65f;
  4290. oTCameraPitchOffset = 13.f;
  4291. //moveData.pivotDistanceController.SetDesiredDistance( 0.5f, 3.f );
  4292. }
  4293. else if ( oTCameraOffset == rightOffset )
  4294. {
  4295. screenSpaceOffset = -0.65f;
  4296. oTCameraPitchOffset = 13.f;
  4297. //moveData.pivotDistanceController.SetDesiredDistance( 0.5f, 3.f );
  4298. }
  4299.  
  4300. moveData.pivotPositionController.offsetZ = 1.3f;
  4301.  
  4302. if ( !delayCameraOrientationChange )
  4303. {
  4304. if ( GetOrientationTarget() == OT_Camera || GetOrientationTarget() == OT_CameraOffset )
  4305. {
  4306. if ( bRAxisReleased )
  4307. {
  4308. heading = moveData.pivotRotationValue.Yaw;
  4309. pitch = moveData.pivotRotationValue.Pitch;
  4310. }
  4311. else
  4312. {
  4313. heading = moveData.pivotRotationValue.Yaw + oTCameraOffset;
  4314. pitch = moveData.pivotRotationValue.Pitch; //+ oTCameraPitchOffset;
  4315. }
  4316. }
  4317. else if ( GetOrientationTarget() == OT_Actor )
  4318. {
  4319. if ( GetDisplayTarget() )
  4320. vec = GetDisplayTarget().GetWorldPosition() - GetWorldPosition();
  4321. else if ( slideTarget )
  4322. vec = slideTarget.GetWorldPosition() - GetWorldPosition();
  4323. else if ( GetTarget() )
  4324. vec = GetTarget().GetWorldPosition() - GetWorldPosition();
  4325. else
  4326. vec = GetHeadingVector();
  4327.  
  4328. angles = VecToRotation( vec );
  4329. heading = angles.Yaw + oTCameraOffset;
  4330. pitch = -angles.Pitch - oTCameraPitchOffset;//-angles.Pitch;
  4331. }
  4332. else
  4333. {
  4334. angles = VecToRotation( GetHeadingVector() );
  4335. heading = angles.Yaw + oTCameraOffset;
  4336. pitch = -angles.Pitch - oTCameraPitchOffset;//-angles.Pitch;
  4337. }
  4338.  
  4339. if ( !wasBRAxisPushed && ( !bRAxisReleased ) )//|| !lastAxisInputIsMovement ) )
  4340. wasBRAxisPushed = true;
  4341.  
  4342. moveData.pivotRotationController.SetDesiredHeading( heading , 2.f );
  4343. moveData.pivotRotationController.SetDesiredPitch( pitch );
  4344. }
  4345. else
  4346. {
  4347. moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw, 1.f );
  4348. moveData.pivotRotationController.SetDesiredPitch( -oTCameraPitchOffset );
  4349. }
  4350.  
  4351. if ( moveData.pivotRotationValue.Pitch <= 5.f && moveData.pivotRotationValue.Pitch >= -15.f )
  4352. {
  4353. screenSpaceOffsetFwd = 1.8;
  4354. screenSpaceOffsetUp = 0.4;
  4355. }
  4356. else if ( moveData.pivotRotationValue.Pitch > 0 )
  4357. {
  4358. screenSpaceOffsetFwd = moveData.pivotRotationValue.Pitch*0.00727 + 1.275f;
  4359. screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, 1.5, 2.2 );
  4360.  
  4361. screenSpaceOffsetUp = -moveData.pivotRotationValue.Pitch*0.00727 + 0.4363f;
  4362. screenSpaceOffsetUp = ClampF( screenSpaceOffsetUp, 0, 0.3 );
  4363. }
  4364. else
  4365. {
  4366. if ( GetCurrentlyCastSign() == ST_Axii )
  4367. {
  4368. screenSpaceOffsetFwd = -moveData.pivotRotationValue.Pitch*0.0425 + 0.8625f;
  4369. screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, 1.5, 2.3 );
  4370. }
  4371. else
  4372. {
  4373. screenSpaceOffsetFwd = -moveData.pivotRotationValue.Pitch*0.035 + 0.75f;
  4374. screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, 1.5, 2.6 );
  4375. }
  4376. screenSpaceOffsetUp = -moveData.pivotRotationValue.Pitch*0.005 + 0.325f;
  4377. screenSpaceOffsetUp = ClampF( screenSpaceOffsetUp, 0.4, 0.5 );
  4378. }
  4379.  
  4380. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( screenSpaceOffset, screenSpaceOffsetFwd, screenSpaceOffsetUp ), 0.25f, timeDelta );//1.5,0.4
  4381. moveData.pivotDistanceController.SetDesiredDistance( 2.8f, 5.f );
  4382. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition() );
  4383.  
  4384. return true;
  4385. }
  4386. else
  4387. {
  4388. this.wasBRAxisPushed = false;
  4389.  
  4390. return false;
  4391. }
  4392. }
  4393.  
  4394. protected function UpdateCameraForSpecialAttack( out moveData : SCameraMovementData, timeDelta : float ) : bool
  4395. {
  4396. var screenSpaceOffset : float;
  4397. var tempHeading : float;
  4398. var cameraOffsetLeft : float;
  4399. var cameraOffsetRight : float;
  4400.  
  4401. if ( !specialAttackCamera )
  4402. return false;
  4403.  
  4404. theGame.GetGameCamera().ForceManualControlHorTimeout();
  4405. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4406. //if ( parent.delayCameraOrientationChange || parent.delayOrientationChange )
  4407. //{
  4408. cameraOffsetLeft = 30.f;
  4409. cameraOffsetRight = -30.f;
  4410. //}
  4411. //else
  4412. //{
  4413. // cameraOffsetLeft = 2.f;
  4414. // cameraOffsetRight = -2.f;
  4415. //}
  4416.  
  4417. theGame.GetGameCamera().ChangePivotRotationController( 'SignChannel' );
  4418. theGame.GetGameCamera().ChangePivotDistanceController( 'SignChannel' );
  4419. // HACK
  4420. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4421. moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController();
  4422.  
  4423. if ( slideTarget )
  4424. tempHeading = VecHeading( slideTarget.GetWorldPosition() - GetWorldPosition() );
  4425. else
  4426. tempHeading = GetHeading();
  4427.  
  4428. oTCameraPitchOffset = 0.f;
  4429.  
  4430. if( ( interiorCamera && !moveTarget )
  4431. || ( AngleDistance( tempHeading, moveData.pivotRotationValue.Yaw ) < 0 ) )
  4432. oTCameraOffset = cameraOffsetLeft;
  4433. else
  4434. oTCameraOffset = cameraOffsetRight;
  4435.  
  4436. if ( oTCameraOffset == cameraOffsetLeft )
  4437. {
  4438. if ( delayCameraOrientationChange || delayOrientationChange )
  4439. {
  4440. screenSpaceOffset = 0.75f;
  4441. moveData.pivotDistanceController.SetDesiredDistance( 1.6f, 3.f );
  4442. moveData.pivotPositionController.offsetZ = 1.4f;
  4443. moveData.pivotRotationController.SetDesiredPitch( -15.f );
  4444. }
  4445. else
  4446. {
  4447. screenSpaceOffset = 0.7f;
  4448. moveData.pivotDistanceController.SetDesiredDistance( 3.25f );
  4449. moveData.pivotPositionController.offsetZ = 1.2f;
  4450. moveData.pivotRotationController.SetDesiredPitch( -10.f );
  4451. }
  4452. }
  4453. else if ( oTCameraOffset == cameraOffsetRight )
  4454. {
  4455. if ( delayCameraOrientationChange || delayOrientationChange )
  4456. {
  4457. screenSpaceOffset = -0.85f;
  4458. moveData.pivotDistanceController.SetDesiredDistance( 1.6f, 3.f );
  4459. moveData.pivotPositionController.offsetZ = 1.4f;
  4460. moveData.pivotRotationController.SetDesiredPitch( -15.f );
  4461. }
  4462. else
  4463. {
  4464. screenSpaceOffset = -0.8f;
  4465. moveData.pivotDistanceController.SetDesiredDistance( 3.25f );
  4466. moveData.pivotPositionController.offsetZ = 1.2f;
  4467. moveData.pivotRotationController.SetDesiredPitch( -10.f );
  4468. }
  4469. }
  4470. else
  4471. {
  4472. moveData.pivotDistanceController.SetDesiredDistance( 1.25f, 3.f );
  4473. moveData.pivotPositionController.offsetZ = 1.3f;
  4474. moveData.pivotRotationController.SetDesiredPitch( -5.5f );
  4475. }
  4476.  
  4477. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( screenSpaceOffset, 0.f, 0.f ), 1.f, timeDelta );
  4478.  
  4479. if ( !delayCameraOrientationChange )
  4480. {
  4481. if ( moveTarget )
  4482. moveData.pivotRotationController.SetDesiredHeading( GetHeading() + oTCameraOffset, 0.5f );
  4483. else
  4484. moveData.pivotRotationController.SetDesiredHeading( GetHeading() + oTCameraOffset, 1.f );
  4485. }
  4486. else
  4487. moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw, 1.f );
  4488.  
  4489. moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition() );
  4490.  
  4491. return true;
  4492. }
  4493.  
  4494.  
  4495. private var fovVel : float;
  4496. private var sprintOffset : Vector;
  4497. private var previousOffset : bool;
  4498. private var previousRotationVelocity : float;
  4499. private var pivotRotationTimeStamp : float;
  4500. protected function UpdateCameraSprint( out moveData : SCameraMovementData, timeDelta : float )
  4501. {
  4502. var angleDiff : float;
  4503. var camOffsetVector : Vector;
  4504. var smoothSpeed : float;
  4505. var camera : CCustomCamera;
  4506. var camAngularSpeed : float;
  4507.  
  4508. var playerToCamAngle : float;
  4509. var useExplorationSprintCam : bool;
  4510.  
  4511. camera = theGame.GetGameCamera();
  4512. if( camera )
  4513. {
  4514. if ( sprintingCamera )
  4515. {
  4516. //theGame.GetGameCamera().ForceManualControlHorTimeout();
  4517. if( thePlayer.GetAutoCameraCenter() )
  4518. {
  4519. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4520. }
  4521.  
  4522. playerToCamAngle = AbsF( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) );
  4523.  
  4524. /*if ( theGame.GetGameplayConfigFloatValue( 'debugE' ) > 0.1f )
  4525. useExplorationSprintCam = !IsInCombat() || ( moveTarget && VecDistance( moveTarget.GetWorldPosition(), GetWorldPosition() ) > findMoveTargetDistMax );
  4526. else*/
  4527. useExplorationSprintCam = false;// !IsInCombat() || ( moveTarget && VecDistance( moveTarget.GetWorldPosition(), GetWorldPosition() ) > findMoveTargetDistMax );
  4528.  
  4529. if ( useExplorationSprintCam )
  4530. {
  4531. if ( playerToCamAngle <= 45 )
  4532. {
  4533. theGame.GetGameCamera().ChangePivotRotationController( 'Sprint' );
  4534. // HACK
  4535. moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController();
  4536.  
  4537. moveData.pivotRotationController.SetDesiredHeading( GetHeading(), 0.25f );
  4538. moveData.pivotRotationController.SetDesiredPitch( -3.5f, 0.5f );
  4539. thePlayer.EnableManualCameraControl( true, 'Sprint' );
  4540. }
  4541. else
  4542. {
  4543. thePlayer.EnableManualCameraControl( false, 'Sprint' );
  4544. }
  4545. }
  4546. else
  4547. {
  4548. if ( theGame.IsUberMovementEnabled() )
  4549. moveData.pivotRotationController.SetDesiredHeading( GetHeading(), 0.35f );
  4550.  
  4551. thePlayer.EnableManualCameraControl( true, 'Sprint' );
  4552. }
  4553.  
  4554. if ( bRAxisReleased )
  4555. {
  4556. if ( AbsF( rawLeftJoyRot ) > 25 )
  4557. angleDiff = AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw );
  4558.  
  4559. pivotRotationTimeStamp = theGame.GetEngineTimeAsSeconds();
  4560. previousRotationVelocity = 0.f;
  4561. }
  4562. else
  4563. {
  4564. if ( previousRotationVelocity <= 0 && AbsF( moveData.pivotRotationVelocity.Yaw ) > 250 )
  4565. {
  4566. pivotRotationTimeStamp = theGame.GetEngineTimeAsSeconds();
  4567. previousRotationVelocity = AbsF( moveData.pivotRotationVelocity.Yaw );
  4568. }
  4569. }
  4570.  
  4571. if ( pivotRotationTimeStamp + 0.4f <= theGame.GetEngineTimeAsSeconds() && AbsF( moveData.pivotRotationVelocity.Yaw ) > 250 )
  4572. angleDiff = VecHeading( rawRightJoyVec );
  4573.  
  4574. if ( useExplorationSprintCam )
  4575. {
  4576. if ( playerToCamAngle > 90 )
  4577. {
  4578. camOffsetVector.X = 0.f;
  4579. smoothSpeed = 1.f;
  4580. }
  4581. else if ( angleDiff > 15.f )
  4582. {
  4583. camOffsetVector.X = -0.8;
  4584. smoothSpeed = 1.f;
  4585. previousOffset = true;
  4586. }
  4587. else if ( angleDiff < -15.f )
  4588. {
  4589. camOffsetVector.X = 0.475f;
  4590. smoothSpeed = 1.5f;
  4591. previousOffset = false;
  4592. }
  4593. else
  4594. {
  4595. if ( previousOffset )
  4596. {
  4597. camOffsetVector.X = -0.8;
  4598. smoothSpeed = 1.5f;
  4599. }
  4600. else
  4601. {
  4602. camOffsetVector.X = 0.475f;
  4603. smoothSpeed = 1.5f;
  4604. }
  4605. }
  4606.  
  4607. camOffsetVector.Y = 1.4f;
  4608. camOffsetVector.Z = 0.275f;
  4609. }
  4610. else
  4611. {
  4612. /*camOffsetVector.X = 0.f;
  4613. camOffsetVector.Y = 0.4f;
  4614. camOffsetVector.Z = 0.2f;*/
  4615. smoothSpeed = 0.75f;
  4616.  
  4617. camOffsetVector.X = 0.f;
  4618. camOffsetVector.Y = 1.f;
  4619. camOffsetVector.Z = 0.2f;
  4620. moveData.pivotRotationController.SetDesiredPitch( -10.f, 0.5f );
  4621. }
  4622.  
  4623. DampVectorConst( sprintOffset, camOffsetVector, smoothSpeed, timeDelta );
  4624.  
  4625. moveData.cameraLocalSpaceOffset = sprintOffset;
  4626.  
  4627. DampFloatSpring( camera.fov, fovVel, 70.f, 1.0, timeDelta );
  4628. }
  4629. else
  4630. {
  4631. sprintOffset = moveData.cameraLocalSpaceOffset;
  4632. DampFloatSpring( camera.fov, fovVel, 60.f, 1.0, timeDelta );
  4633. previousOffset = false;
  4634. }
  4635. }
  4636. }
  4637.  
  4638. function EnableSprintingCamera( flag : bool )
  4639. {
  4640. if( !theGame.IsUberMovementEnabled() && !useSprintingCameraAnim )
  4641. {
  4642. return;
  4643. }
  4644.  
  4645. super.EnableSprintingCamera( flag );
  4646.  
  4647. if ( !flag )
  4648. {
  4649. thePlayer.EnableManualCameraControl( true, 'Sprint' );
  4650. }
  4651. }
  4652.  
  4653. protected function UpdateCameraCombatActionButNotInCombat( out moveData : SCameraMovementData, timeDelta : float )
  4654. {
  4655. var vel : Vector;
  4656. var heading : float;
  4657. var pitch : float;
  4658. var headingMult : float;
  4659. var pitchMult : float;
  4660. var camOffset : Vector;
  4661. var buff : CBaseGameplayEffect;
  4662. var runningAndAlertNear : bool;
  4663. var desiredDist : float;
  4664.  
  4665. if ( ( !IsCurrentSignChanneled() || GetCurrentlyCastSign() == ST_Quen || GetCurrentlyCastSign() == ST_Yrden ) && !specialAttackCamera && !IsInCombatActionFriendly() )
  4666. {
  4667. buff = GetCurrentlyAnimatedCS();
  4668. runningAndAlertNear = GetPlayerCombatStance() == PCS_AlertNear && playerMoveType == PMT_Run && !GetDisplayTarget();
  4669. if ( runningAndAlertNear ||
  4670. ( GetPlayerCombatStance() == PCS_AlertFar && !IsInCombatAction() && !buff ) )
  4671. {
  4672. camOffset.X = 0.f;
  4673. camOffset.Y = 0.f;
  4674. camOffset.Z = -0.1f;
  4675.  
  4676. if ( runningAndAlertNear )
  4677. {
  4678. moveData.pivotDistanceController.SetDesiredDistance( 4.f );
  4679. moveData.pivotPositionController.offsetZ = 1.5f;
  4680. }
  4681. }
  4682. else
  4683. {
  4684. camOffset.X = 0.f;
  4685. camOffset.Y = -1.5f;
  4686. camOffset.Z = -0.2f;
  4687. }
  4688.  
  4689. DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( camOffset.X, camOffset.Y, camOffset.Z ), 0.4f, timeDelta );
  4690. sprintOffset = moveData.cameraLocalSpaceOffset;
  4691. heading = moveData.pivotRotationValue.Yaw;
  4692.  
  4693. if ( GetOrientationTarget() == OT_Camera || GetOrientationTarget() == OT_CameraOffset )
  4694. pitch = moveData.pivotRotationValue.Pitch;
  4695. else if ( lastAxisInputIsMovement
  4696. || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack
  4697. || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_SpecialAttack
  4698. || ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign && !IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Quen ) )
  4699. {
  4700. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4701. pitch = -20.f;
  4702. }
  4703. else
  4704. pitch = moveData.pivotRotationValue.Pitch;
  4705.  
  4706. headingMult = 1.f;
  4707. pitchMult = 1.f;
  4708.  
  4709. //if( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack )
  4710. if( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign
  4711. && ( GetEquippedSign() == ST_Aard || GetEquippedSign() == ST_Yrden )
  4712. && GetBehaviorVariable( 'alternateSignCast' ) == 1 )
  4713. {
  4714. //theGame.GetGameCamera().ForceManualControlHorTimeout();
  4715. theGame.GetGameCamera().ForceManualControlVerTimeout();
  4716. pitch = -20.f;
  4717.  
  4718. //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( theGame.GetGameplayConfigFloatValue( 'debugA' ), theGame.GetGameplayConfigFloatValue( 'debugB' ), theGame.GetGameplayConfigFloatValue( 'debugC' ) ), 0.4f, timeDelta );
  4719. }
  4720.  
  4721. //vel = GetMovingAgentComponent().GetVelocity();
  4722. //if ( VecLength( vel ) > 0 && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge )
  4723. //{
  4724. /*theGame.GetGameCamera().ForceManualControlHorTimeout();
  4725. heading = GetHeading();
  4726. headingMult = 0.5f;*/
  4727. //}
  4728.  
  4729. if ( IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Quen )
  4730. {
  4731. pitch = moveData.pivotRotationValue.Pitch;
  4732. }
  4733.  
  4734. moveData.pivotRotationController.SetDesiredHeading( heading, );
  4735. moveData.pivotRotationController.SetDesiredPitch( pitch );
  4736. }
  4737. }
  4738.  
  4739. /*public function UpdateCameraForSpecialAttack( out moveData : SCameraMovementData, timeDelta : float ) : bool
  4740. {
  4741. return false;
  4742. }*/
  4743. //------------------------------------------------------------------------------------------------------------------
  4744. event OnGameCameraExplorationRotCtrlChange()
  4745. {
  4746. if( substateManager )
  4747. {
  4748. return substateManager.OnGameCameraExplorationRotCtrlChange( );
  4749. }
  4750.  
  4751. return false;
  4752. }
  4753.  
  4754. ///////////////////////////////////////////////////////////////////////////
  4755. // COMBAT MOVEMENT ORIENTATION
  4756. ///////////////////////////////////////////////////////////////////////////
  4757.  
  4758. //Rotation
  4759. function SetCustomRotation( customRotationName : name, rotHeading : float, rotSpeed : float, activeTime : float, rotateExistingDeltaLocation : bool )
  4760. {
  4761. var movementAdjustor : CMovementAdjustor;
  4762. var ticket : SMovementAdjustmentRequestTicket;
  4763.  
  4764. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4765. ticket = movementAdjustor.GetRequest( customRotationName );
  4766. movementAdjustor.Cancel( ticket );
  4767. ticket = movementAdjustor.CreateNewRequest( customRotationName );
  4768. movementAdjustor.Continuous( ticket );
  4769. movementAdjustor.ReplaceRotation( ticket );
  4770. movementAdjustor.RotateTo( ticket, rotHeading );
  4771. movementAdjustor.MaxRotationAdjustmentSpeed( ticket, rotSpeed );
  4772. if (rotSpeed == 0.0f)
  4773. {
  4774. movementAdjustor.AdjustmentDuration( ticket, activeTime );
  4775. }
  4776. movementAdjustor.KeepActiveFor( ticket, activeTime );
  4777. movementAdjustor.RotateExistingDeltaLocation( ticket, rotateExistingDeltaLocation );
  4778. }
  4779.  
  4780. function UpdateCustomRotationHeading( customRotationName : name, rotHeading : float )
  4781. {
  4782. var movementAdjustor : CMovementAdjustor;
  4783. var ticket : SMovementAdjustmentRequestTicket;
  4784.  
  4785. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4786. ticket = movementAdjustor.GetRequest( customRotationName );
  4787. movementAdjustor.RotateTo( ticket, rotHeading );
  4788. }
  4789.  
  4790. function SetCustomRotationTowards( customRotationName : name, target : CActor, rotSpeed : float, optional activeTime : float )
  4791. {
  4792. var movementAdjustor : CMovementAdjustor;
  4793. var ticket : SMovementAdjustmentRequestTicket;
  4794.  
  4795. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4796. ticket = movementAdjustor.GetRequest( customRotationName );
  4797. movementAdjustor.Cancel( ticket );
  4798. ticket = movementAdjustor.CreateNewRequest( customRotationName );
  4799. movementAdjustor.Continuous( ticket );
  4800. movementAdjustor.ReplaceRotation( ticket );
  4801. movementAdjustor.RotateTowards( ticket, target );
  4802. movementAdjustor.MaxRotationAdjustmentSpeed( ticket, rotSpeed );
  4803. if (activeTime > 0.0f)
  4804. {
  4805. movementAdjustor.KeepActiveFor( ticket, activeTime );
  4806. }
  4807. else
  4808. {
  4809. movementAdjustor.DontEnd( ticket );
  4810. }
  4811. }
  4812.  
  4813. //lock movement in dir
  4814. function CustomLockMovement( customMovementName : name, heading : float )
  4815. {
  4816. var movementAdjustor : CMovementAdjustor;
  4817. var ticket : SMovementAdjustmentRequestTicket;
  4818.  
  4819. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4820. ticket = movementAdjustor.GetRequest( customMovementName );
  4821. movementAdjustor.Cancel( ticket );
  4822. ticket = movementAdjustor.CreateNewRequest( customMovementName );
  4823. movementAdjustor.Continuous( ticket );
  4824. movementAdjustor.DontEnd( ticket );
  4825. movementAdjustor.LockMovementInDirection( ticket, heading );
  4826. }
  4827.  
  4828. function BindMovementAdjustmentToEvent( customRotationName : name, eventName : CName )
  4829. {
  4830. var movementAdjustor : CMovementAdjustor;
  4831. var ticket : SMovementAdjustmentRequestTicket;
  4832.  
  4833. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4834. ticket = movementAdjustor.GetRequest( customRotationName );
  4835. movementAdjustor.BindToEvent( ticket, eventName );
  4836. }
  4837.  
  4838. function UpdateCustomLockMovementHeading( customMovementName : name, heading : float )
  4839. {
  4840. var movementAdjustor : CMovementAdjustor;
  4841. var ticket : SMovementAdjustmentRequestTicket;
  4842.  
  4843. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4844. ticket = movementAdjustor.GetRequest( customMovementName );
  4845. movementAdjustor.LockMovementInDirection( ticket, heading );
  4846. }
  4847.  
  4848. function CustomLockDistance( customMovementName : name, maintainDistanceTo : CNode, minDist, maxDist : float )
  4849. {
  4850. var movementAdjustor : CMovementAdjustor;
  4851. var ticket : SMovementAdjustmentRequestTicket;
  4852.  
  4853. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4854. ticket = movementAdjustor.GetRequest( customMovementName );
  4855. movementAdjustor.Cancel( ticket );
  4856. ticket = movementAdjustor.CreateNewRequest( customMovementName );
  4857. movementAdjustor.Continuous( ticket );
  4858. movementAdjustor.SlideTowards( ticket, maintainDistanceTo, minDist, maxDist );
  4859. }
  4860.  
  4861. function UpdateCustomLockDistance( customMovementName : name, maintainDistanceTo : CNode, minDist, maxDist : float )
  4862. {
  4863. var movementAdjustor : CMovementAdjustor;
  4864. var ticket : SMovementAdjustmentRequestTicket;
  4865.  
  4866. movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor();
  4867. ticket = movementAdjustor.GetRequest( customMovementName );
  4868. movementAdjustor.SlideTowards( ticket, maintainDistanceTo, minDist, maxDist );
  4869. }
  4870.  
  4871. private var disableManualCameraControlStack : array<name>;
  4872. public function EnableManualCameraControl( enable : bool, sourceName : name )
  4873. {
  4874. if ( !enable )
  4875. {
  4876. if ( !disableManualCameraControlStack.Contains( sourceName ) )
  4877. {
  4878. disableManualCameraControlStack.PushBack( sourceName );
  4879. }
  4880. }
  4881. else
  4882. {
  4883. disableManualCameraControlStack.Remove( sourceName );
  4884. }
  4885.  
  4886. if ( disableManualCameraControlStack.Size() > 0 )
  4887. theGame.GetGameCamera().EnableManualControl( false );
  4888. else
  4889. theGame.GetGameCamera().EnableManualControl( true );
  4890. }
  4891.  
  4892. public function IsCameraControlDisabled( optional disabledBySourceName : name ) : bool
  4893. {
  4894. if ( disabledBySourceName )
  4895. return disableManualCameraControlStack.Contains( disabledBySourceName );
  4896. else
  4897. return disableManualCameraControlStack.Size() > 0;
  4898. }
  4899.  
  4900. public function DisableManualCameraControlStackHasSource( sourceName : name ) : bool
  4901. {
  4902. return disableManualCameraControlStack.Contains( sourceName );
  4903. }
  4904.  
  4905. public function ClearDisableManualCameraControlStack()
  4906. {
  4907. disableManualCameraControlStack.Clear();
  4908. theGame.GetGameCamera().EnableManualControl( true );
  4909. }
  4910.  
  4911. function SetOrientationTarget( target : EOrientationTarget )
  4912. {
  4913. if ( IsPCModeEnabled() && target == OT_Player )
  4914. {
  4915. target = OT_Camera;
  4916. }
  4917.  
  4918. orientationTarget = target;
  4919. }
  4920.  
  4921. function GetOrientationTarget() : EOrientationTarget
  4922. {
  4923. return orientationTarget;
  4924. }
  4925.  
  4926. var customOrientationInfoStack : array<SCustomOrientationInfo>;
  4927. public function AddCustomOrientationTarget( orientationTarget : EOrientationTarget, sourceName : name )
  4928. {
  4929. var customOrientationInfo : SCustomOrientationInfo;
  4930. var i : int;
  4931.  
  4932. if ( customOrientationInfoStack.Size() > 0 )
  4933. {
  4934. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4935. {
  4936. if ( customOrientationInfoStack[i].sourceName == sourceName )
  4937. customOrientationInfoStack.Erase(i);
  4938. }
  4939. }
  4940.  
  4941. customOrientationInfo.sourceName = sourceName;
  4942. customOrientationInfo.orientationTarget = orientationTarget;
  4943. customOrientationInfoStack.PushBack( customOrientationInfo );
  4944. SetOrientationTarget( orientationTarget );
  4945. }
  4946.  
  4947. public function RemoveCustomOrientationTarget( sourceName : name )
  4948. {
  4949. var customOrientationInfo : SCustomOrientationInfo;
  4950. var i : int;
  4951.  
  4952. if ( customOrientationInfoStack.Size() > 0 )
  4953. {
  4954. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4955. {
  4956. if ( customOrientationInfoStack[i].sourceName == sourceName )
  4957. customOrientationInfoStack.Erase(i);
  4958. }
  4959. }
  4960. else
  4961. LogChannel( 'CustomOrienatation', "ERROR: Custom orientation cannot be removed, stack is already empty!!!" );
  4962. }
  4963.  
  4964. protected function ClearCustomOrientationInfoStack()
  4965. {
  4966. customOrientationInfoStack.Clear();
  4967. }
  4968.  
  4969. protected function GetCustomOrientationTarget( out infoStack : SCustomOrientationInfo ) : bool
  4970. {
  4971. var size : int;
  4972.  
  4973. size = customOrientationInfoStack.Size();
  4974.  
  4975. if ( size <= 0 )
  4976. return false;
  4977. else
  4978. {
  4979. infoStack = customOrientationInfoStack[ size - 1 ];
  4980. return true;
  4981. }
  4982. }
  4983.  
  4984. public function SetOrientationTargetCustomHeading( heading : float, sourceName : name ) : bool
  4985. {
  4986. var i : int;
  4987. if ( customOrientationInfoStack.Size() > 0 )
  4988. {
  4989. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  4990. {
  4991. if ( customOrientationInfoStack[i].sourceName == sourceName )
  4992. {
  4993. customOrientationInfoStack[i].customHeading = heading;
  4994. return true;
  4995. }
  4996. }
  4997. }
  4998.  
  4999. LogChannel( 'SetOrientationTargetCustomHeading', "ERROR: Cannot set customHeading because stack is empty or sourceName is not found!!!" );
  5000. return false;
  5001. }
  5002.  
  5003. // returns the topmost OT_CustomHeading in stack
  5004. public function GetOrientationTargetCustomHeading() : float
  5005. {
  5006. var i : int;
  5007. if ( customOrientationInfoStack.Size() > 0 )
  5008. {
  5009. for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 )
  5010. {
  5011. if ( customOrientationInfoStack[i].orientationTarget == OT_CustomHeading )
  5012. {
  5013. return customOrientationInfoStack[i].customHeading;
  5014. }
  5015. }
  5016. }
  5017.  
  5018. LogChannel( 'SetOrientationTargetCustomHeading', "ERROR: Cannot get customHeading because stack is empty or no OT_CustomHeading in stack!!!" );
  5019. return -1.f;
  5020. }
  5021.  
  5022. public function GetCombatActionOrientationTarget( combatActionType : ECombatActionType ) : EOrientationTarget
  5023. {
  5024. var newCustomOrientationTarget : EOrientationTarget;
  5025. var targetEnt : CGameplayEntity;
  5026. var targetActor : CActor;
  5027.  
  5028. if ( GetCurrentStateName() == 'AimThrow' )
  5029. newCustomOrientationTarget = OT_CameraOffset;
  5030. else
  5031. {
  5032. targetEnt = GetDisplayTarget();
  5033. targetActor = (CActor)targetEnt;
  5034.  
  5035. if ( targetEnt )
  5036. {
  5037. if ( targetActor )
  5038. {
  5039. if ( moveTarget )
  5040. newCustomOrientationTarget = OT_Actor;
  5041. else
  5042. {
  5043. if ( this.IsSwimming() )
  5044. newCustomOrientationTarget = OT_Camera;
  5045. else if ( lastAxisInputIsMovement )
  5046. newCustomOrientationTarget = OT_Player;
  5047. else
  5048. newCustomOrientationTarget = OT_Actor;
  5049. }
  5050. }
  5051. else
  5052. {
  5053. if ( combatActionType == CAT_Crossbow && targetEnt.HasTag( 'softLock_Bolt' ) )
  5054. newCustomOrientationTarget = OT_Actor;
  5055. else
  5056. {
  5057. if ( this.IsSwimming() )
  5058. newCustomOrientationTarget = OT_Camera;
  5059. else if ( lastAxisInputIsMovement )
  5060. newCustomOrientationTarget = OT_Player;
  5061. else
  5062. newCustomOrientationTarget = OT_Camera;
  5063.  
  5064. }
  5065. }
  5066. }
  5067. else
  5068. {
  5069. if ( IsUsingVehicle() )// || this.IsSwimming() )
  5070. newCustomOrientationTarget = OT_Camera;
  5071. else if ( lastAxisInputIsMovement )
  5072. {
  5073. if ( this.IsSwimming() )
  5074. {
  5075. //if ( !bRAxisReleased
  5076. // || ( GetOrientationTarget() == OT_Camera && ( this.rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' || this.rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' ) ) )
  5077. newCustomOrientationTarget = OT_Camera;
  5078. //else
  5079. // newCustomOrientationTarget = OT_CustomHeading;
  5080. }
  5081. else
  5082. newCustomOrientationTarget = OT_Player;
  5083.  
  5084. }
  5085. else
  5086. newCustomOrientationTarget = OT_Camera;
  5087. }
  5088. }
  5089.  
  5090. return newCustomOrientationTarget;
  5091. }
  5092.  
  5093. public function GetOrientationTargetHeading( orientationTarget : EOrientationTarget ) : float
  5094. {
  5095. var heading : float;
  5096.  
  5097. if( orientationTarget == OT_Camera )
  5098. heading = VecHeading( theCamera.GetCameraDirection() );
  5099. else if( orientationTarget == OT_CameraOffset )
  5100. heading = VecHeading( theCamera.GetCameraDirection() ) - oTCameraOffset;
  5101. else if( orientationTarget == OT_CustomHeading )
  5102. heading = GetOrientationTargetCustomHeading();
  5103. else if ( GetDisplayTarget() && orientationTarget == OT_Actor )
  5104. {
  5105. if ( (CActor)( GetDisplayTarget() ) )
  5106. {
  5107. //if ( GetPlayerCombatStance() == PCS_AlertNear )
  5108. heading = VecHeading( GetDisplayTarget().GetWorldPosition() - GetWorldPosition() );
  5109. //else
  5110. // heading = GetHeading();
  5111. }
  5112. else
  5113. {
  5114. if ( GetDisplayTarget().HasTag( 'softLock_Bolt' ) )
  5115. heading = VecHeading( GetDisplayTarget().GetWorldPosition() - GetWorldPosition() );
  5116. else
  5117. heading = GetHeading();
  5118. }
  5119. }
  5120. else
  5121. heading = GetHeading();
  5122.  
  5123. return heading;
  5124. }
  5125.  
  5126. event OnDelayOrientationChange()
  5127. {
  5128. var delayOrientation : bool;
  5129. var delayCameraRotation : bool;
  5130. var moveData : SCameraMovementData;
  5131. var time : float;
  5132.  
  5133. time = 0.01f;
  5134.  
  5135. if ( theInput.GetActionValue( 'CastSignHold' ) == 1.f )
  5136. {
  5137. actionType = 0;
  5138. if ( moveTarget )
  5139. delayOrientation = true;
  5140. else
  5141. {
  5142. if ( !GetBIsCombatActionAllowed() )
  5143. delayOrientation = true;
  5144. }
  5145.  
  5146.  
  5147. }
  5148. else if ( theInput.GetActionValue( 'ThrowItemHold' ) == 1.f )
  5149. {
  5150. actionType = 3;
  5151. delayOrientation = true;
  5152. }
  5153. else if ( theInput.GetActionValue( 'SpecialAttackHeavy' ) == 1.f )
  5154. {
  5155. actionType = 2;
  5156. if ( !slideTarget )
  5157. delayOrientation = true;
  5158. else
  5159. delayOrientation = true;
  5160. }
  5161. else if ( IsGuarded() && !moveTarget )
  5162. {
  5163. actionType = 1;
  5164. delayOrientation = true;
  5165. }
  5166.  
  5167. if ( delayOrientation )
  5168. {
  5169. delayOrientationChange = true;
  5170. theGame.GetGameCamera().ForceManualControlHorTimeout();
  5171. theGame.GetGameCamera().ForceManualControlVerTimeout();
  5172. AddTimer( 'DelayOrientationChangeTimer', time, true );
  5173. }
  5174.  
  5175. if ( delayCameraRotation )
  5176. {
  5177. delayCameraOrientationChange = true;
  5178. theGame.GetGameCamera().ForceManualControlHorTimeout();
  5179. theGame.GetGameCamera().ForceManualControlVerTimeout();
  5180. AddTimer( 'DelayOrientationChangeTimer', time, true );
  5181. }
  5182. }
  5183.  
  5184. //This is also called from behgraph (e.g. SpecialHeavyAttack)
  5185. event OnDelayOrientationChangeOff()
  5186. {
  5187. delayOrientationChange = false;
  5188. delayCameraOrientationChange = false;
  5189. RemoveTimer( 'DelayOrientationChangeTimer' );
  5190.  
  5191. //if ( !IsCameraLockedToTarget() )
  5192. // theGame.GetGameCamera().EnableManualControl( true );
  5193. }
  5194.  
  5195. timer function DelayOrientationChangeTimer( time : float , id : int)
  5196. {
  5197. if ( ( actionType == 0 && theInput.GetActionValue( 'CastSignHold' ) == 0.f )
  5198. || ( actionType == 2 && theInput.GetActionValue( 'SpecialAttackHeavy' ) == 0.f )
  5199. || ( actionType == 3 && theInput.GetActionValue( 'ThrowItemHold' ) == 0.f )
  5200. || ( actionType == 1 && !IsGuarded() )
  5201. || ( VecLength( rawRightJoyVec ) > 0.f ) )//&& !( slideTarget && IsInCombatAction() && GetBehaviorVariable( 'combatActionType') == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Axii ) ) )
  5202. {
  5203. OnDelayOrientationChangeOff();
  5204. }
  5205. }
  5206.  
  5207. public function SetCombatActionHeading( heading : float )
  5208. {
  5209. combatActionHeading = heading;
  5210. }
  5211.  
  5212. public function GetCombatActionHeading() : float
  5213. {
  5214. return combatActionHeading;
  5215. }
  5216.  
  5217. protected function EnableCloseCombatCharacterRadius( flag : bool )
  5218. {
  5219. var actor : CActor;
  5220.  
  5221. actor = (CActor)slideTarget;
  5222. if ( flag )
  5223. {
  5224. this.GetMovingAgentComponent().SetVirtualRadius( 'CloseCombatCharacterRadius' );
  5225. if(actor)
  5226. actor.GetMovingAgentComponent().SetVirtualRadius( 'CloseCombatCharacterRadius' );
  5227. }
  5228. else
  5229. {
  5230. if ( this.IsInCombat() )
  5231. {
  5232. GetMovingAgentComponent().SetVirtualRadius( 'CombatCharacterRadius' );
  5233. if(actor)
  5234. actor.GetMovingAgentComponent().SetVirtualRadius( 'CombatCharacterRadius' );
  5235. }
  5236. else
  5237. {
  5238. this.GetMovingAgentComponent().ResetVirtualRadius();
  5239. if(actor)
  5240. actor.GetMovingAgentComponent().ResetVirtualRadius();
  5241. }
  5242. }
  5243. }
  5244.  
  5245. ///////////////////////////////////////////////////////////////////////////
  5246. // Soft Lock Logic
  5247.  
  5248.  
  5249.  
  5250. private var isSnappedToNavMesh : bool;
  5251. private var snapToNavMeshCachedFlag : bool;
  5252. public function SnapToNavMesh( flag : bool )
  5253. {
  5254. var comp : CMovingAgentComponent;
  5255.  
  5256. comp = (CMovingAgentComponent)this.GetMovingAgentComponent();
  5257.  
  5258. if ( comp )
  5259. {
  5260. comp.SnapToNavigableSpace( flag );
  5261. isSnappedToNavMesh = flag;
  5262. }
  5263. else
  5264. {
  5265. snapToNavMeshCachedFlag = flag;
  5266. AddTimer( 'DelayedSnapToNavMesh', 0.2f );
  5267. }
  5268. }
  5269.  
  5270. public final function PlayRuneword4FX(optional weaponType : EPlayerWeapon)
  5271. {
  5272. var hasSwordDrawn : bool;
  5273. var sword : SItemUniqueId;
  5274.  
  5275. //we show fx only if overheal is greater than 1% - otherwise if we have a DoT and regen at the same time the health
  5276. //jumps back and forth between 100% and 99.99% stating and stopping the fx over and over
  5277. //needs to have sword drawn
  5278. if(abilityManager.GetOverhealBonus() > (0.005 * GetStatMax(BCS_Vitality)))
  5279. {
  5280. hasSwordDrawn = HasAbility('Runeword 4 _Stats', true);
  5281.  
  5282. if(!hasSwordDrawn && GetWitcherPlayer())
  5283. {
  5284. if(weaponType == PW_Steel)
  5285. {
  5286. if(GetWitcherPlayer().GetItemEquippedOnSlot(EES_SteelSword, sword))
  5287. hasSwordDrawn = inv.ItemHasAbility(sword, 'Runeword 4 _Stats');
  5288. }
  5289. else if(weaponType == PW_Silver)
  5290. {
  5291. if(GetWitcherPlayer().GetItemEquippedOnSlot(EES_SilverSword, sword))
  5292. hasSwordDrawn = inv.ItemHasAbility(sword, 'Runeword 4 _Stats');
  5293. }
  5294. }
  5295.  
  5296. if(hasSwordDrawn)
  5297. {
  5298. if(!IsEffectActive('runeword_4', true))
  5299. PlayEffect('runeword_4');
  5300. }
  5301. }
  5302. }
  5303.  
  5304. timer function DelayedSnapToNavMesh( dt : float, id : int)
  5305. {
  5306. SnapToNavMesh( snapToNavMeshCachedFlag );
  5307. }
  5308.  
  5309. saved var navMeshSnapInfoStack : array<name>;
  5310. public function EnableSnapToNavMesh( source : name, enable : bool )
  5311. {
  5312. if ( enable )
  5313. {
  5314. if ( !navMeshSnapInfoStack.Contains( source ) )
  5315. navMeshSnapInfoStack.PushBack( source );
  5316. }
  5317. else
  5318. {
  5319. if ( navMeshSnapInfoStack.Contains( source ) )
  5320. navMeshSnapInfoStack.Remove( source );
  5321. }
  5322.  
  5323. if ( navMeshSnapInfoStack.Size() > 0 )
  5324. SnapToNavMesh( true );
  5325. else
  5326. SnapToNavMesh( false );
  5327. }
  5328.  
  5329. public function ForceRemoveAllNavMeshSnaps()
  5330. {
  5331. navMeshSnapInfoStack.Clear();
  5332. SnapToNavMesh( false );
  5333. }
  5334.  
  5335. public function CanSprint( speed : float ) : bool
  5336. {
  5337. if( speed <= 0.8f )
  5338. {
  5339. return false;
  5340. }
  5341.  
  5342. if ( thePlayer.GetIsSprintToggled() )
  5343. {
  5344. }
  5345. else if ( !sprintActionPressed )
  5346. {
  5347. return false;
  5348. }
  5349. else if( !theInput.IsActionPressed('Sprint') || ( theInput.LastUsedGamepad() && IsInsideInteraction() && GetHowLongSprintButtonWasPressed() < 0.12 ) )
  5350. {
  5351. return false;
  5352. }
  5353.  
  5354. if ( thePlayer.HasBuff( EET_OverEncumbered ) )
  5355. {
  5356. return false;
  5357. }
  5358. if ( !IsSwimming() )
  5359. {
  5360. if ( ShouldUseStaminaWhileSprinting() && !GetIsSprinting() && !IsInCombat() && GetStatPercents(BCS_Stamina) <= 0.9 )
  5361. {
  5362. return false;
  5363. }
  5364. if( ( !IsCombatMusicEnabled() || IsInFistFightMiniGame() ) && ( !IsActionAllowed(EIAB_RunAndSprint) || !IsActionAllowed(EIAB_Sprint) ) )
  5365. {
  5366. return false;
  5367. }
  5368. if( IsTerrainTooSteepToRunUp() )
  5369. {
  5370. return false;
  5371. }
  5372. if( IsInCombatAction() )
  5373. {
  5374. return false;
  5375. }
  5376. if( IsInAir() )
  5377. {
  5378. return false;
  5379. }
  5380. }
  5381. if( theGame.IsFocusModeActive() )
  5382. {
  5383. return false;
  5384. }
  5385.  
  5386. return true;
  5387. }
  5388.  
  5389.  
  5390. public function SetTerrainPitch( pitch : float )
  5391. {
  5392. terrainPitch = pitch;
  5393. }
  5394.  
  5395. public function IsTerrainTooSteepToRunUp() : bool
  5396. {
  5397. return terrainPitch <= disableSprintTerrainPitch;
  5398. }
  5399.  
  5400. public function SetTempLookAtTarget( actor : CGameplayEntity )
  5401. {
  5402. tempLookAtTarget = actor;
  5403. }
  5404.  
  5405. private var beingWarnedBy : array<CActor>;
  5406.  
  5407. event OnBeingWarnedStart( sender : CActor )
  5408. {
  5409. if ( !beingWarnedBy.Contains(sender) )
  5410. beingWarnedBy.PushBack(sender);
  5411. }
  5412. event OnBeingWarnedStop( sender : CActor )
  5413. {
  5414. beingWarnedBy.Remove(sender);
  5415. }
  5416.  
  5417. event OnCanFindPath( sender : CActor )
  5418. {
  5419. AddCanFindPathEnemyToList(sender,true);
  5420. }
  5421. event OnCannotFindPath( sender : CActor )
  5422. {
  5423. AddCanFindPathEnemyToList(sender,false);
  5424. }
  5425. event OnBecomeAwareAndCanAttack( sender : CActor )
  5426. {
  5427. AddEnemyToHostileEnemiesList( sender, true );
  5428. OnApproachAttack( sender );
  5429. }
  5430. event OnBecomeUnawareOrCannotAttack( sender : CActor )
  5431. {
  5432. AddEnemyToHostileEnemiesList( sender, false );
  5433. OnApproachAttackEnd( sender );
  5434. OnCannotFindPath(sender);
  5435. }
  5436. event OnApproachAttack( sender : CActor )
  5437. {
  5438. AddEnemyToHostileEnemiesList( sender, true );
  5439. super.OnApproachAttack( sender );
  5440. }
  5441. event OnApproachAttackEnd( sender : CActor )
  5442. {
  5443. AddEnemyToHostileEnemiesList( sender, false );
  5444. super.OnApproachAttackEnd( sender );
  5445. }
  5446. event OnAttack( sender : CActor )
  5447. {
  5448. super.OnAttack( sender );
  5449. }
  5450. event OnAttackEnd( sender : CActor )
  5451. {
  5452. super.OnAttackEnd( sender );
  5453. }
  5454.  
  5455. event OnHitCeiling()
  5456. {
  5457. substateManager.ReactOnHitCeiling();
  5458. }
  5459.  
  5460. protected var hostileEnemies : array<CActor>; //all enemies that are actively engaged in combat with the player (may or may not be visible by Geralt)
  5461. private var hostileMonsters : array<CActor>; // subgroup from hostileEnemies containing only monsters for sound system
  5462. function AddEnemyToHostileEnemiesList( actor : CActor, add : bool )
  5463. {
  5464. if ( add )
  5465. {
  5466. RemoveTimer( 'RemoveEnemyFromHostileEnemiesListTimer' );
  5467. if ( !hostileEnemies.Contains( actor ) )
  5468. {
  5469. hostileEnemies.PushBack( actor );
  5470.  
  5471. if( !actor.IsHuman() )
  5472. hostileMonsters.PushBack( actor );
  5473. }
  5474. }
  5475. else
  5476. {
  5477. if ( hostileEnemies.Size() == 1 )
  5478. {
  5479. if ( !actor.IsAlive() || actor.IsKnockedUnconscious() )
  5480. {
  5481. hostileEnemies.Remove( actor );
  5482. if( !actor.IsHuman() )
  5483. hostileMonsters.Remove( actor );
  5484. }
  5485. else
  5486. {
  5487. // If we already waiting to remove an entity
  5488. if( hostileEnemyToRemove )
  5489. {
  5490. hostileEnemies.Remove( hostileEnemyToRemove );
  5491. if( !hostileEnemyToRemove.IsHuman() )
  5492. hostileMonsters.Remove( hostileEnemyToRemove );
  5493. }
  5494. hostileEnemyToRemove = actor;
  5495. AddTimer( 'RemoveEnemyFromHostileEnemiesListTimer', 3.f );
  5496. }
  5497. }
  5498. else
  5499. {
  5500. hostileEnemies.Remove( actor );
  5501. if( !actor.IsHuman() )
  5502. hostileMonsters.Remove( actor );
  5503. }
  5504. }
  5505. }
  5506.  
  5507.  
  5508.  
  5509. public function ShouldEnableCombatMusic() : bool
  5510. {
  5511. var moveTargetNPC : CNewNPC;
  5512.  
  5513. if ( thePlayer.GetPlayerMode().GetForceCombatMode() )
  5514. return true;
  5515. else if ( !IsCombatMusicEnabled() )
  5516. {
  5517. if ( IsInCombat() )
  5518. return true;
  5519. else if ( IsThreatened() )
  5520. {
  5521. moveTargetNPC = (CNewNPC)moveTarget;
  5522. if ( moveTargetNPC.IsRanged() && hostileEnemies.Contains( moveTargetNPC ) )
  5523. return true;
  5524. else
  5525. return false;
  5526. }
  5527. else
  5528. return false;
  5529. }
  5530. else if ( ( thePlayer.IsThreatened() && ( hostileEnemies.Size() > 0 || thePlayer.GetPlayerCombatStance() == PCS_AlertNear ) )
  5531. || IsInCombat()
  5532. || finishableEnemiesList.Size() > 0
  5533. || isInFinisher )
  5534. return true;
  5535. else
  5536. return false;
  5537.  
  5538. }
  5539.  
  5540. public var canFindPathEnemiesList : array<CActor>;
  5541. public var disablecanFindPathEnemiesListUpdate : bool;
  5542. private var lastCanFindPathEnemy : CActor;
  5543. private var cachedMoveTarget : CActor;
  5544. private var reachabilityTestId : int;
  5545. private var reachabilityTestId2 : int;
  5546. function AddCanFindPathEnemyToList( actor : CActor, add : bool )
  5547. {
  5548. if ( disablecanFindPathEnemiesListUpdate )
  5549. return;
  5550.  
  5551. if ( add && !canFindPathEnemiesList.Contains( actor ) )
  5552. {
  5553. canFindPathEnemiesList.PushBack(actor);
  5554. }
  5555. else if ( !add )
  5556. {
  5557. canFindPathEnemiesList.Remove(actor);
  5558.  
  5559. if ( canFindPathEnemiesList.Size() <= 0 )
  5560. playerMode.UpdateCombatMode();
  5561. }
  5562. }
  5563.  
  5564. public function ClearCanFindPathEnemiesList( dt : float, id : int )
  5565. {
  5566. canFindPathEnemiesList.Clear();
  5567. }
  5568.  
  5569. public var finishableEnemiesList : array<CActor>;
  5570. function AddToFinishableEnemyList( actor : CActor, add : bool )
  5571. {
  5572. if ( add && !finishableEnemiesList.Contains( actor ) )
  5573. {
  5574. finishableEnemiesList.PushBack(actor);
  5575. }
  5576. else if ( !add )
  5577. {
  5578. finishableEnemiesList.Remove(actor);
  5579. }
  5580. }
  5581.  
  5582. private function UpdateFinishableEnemyList()
  5583. {
  5584. var i : int;
  5585. i = 0;
  5586. while ( i < finishableEnemiesList.Size() )
  5587. {
  5588. if ( !finishableEnemiesList[ i ] )
  5589. {
  5590. finishableEnemiesList.EraseFast( i );
  5591. }
  5592. else
  5593. {
  5594. i += 1;
  5595. }
  5596. }
  5597. }
  5598.  
  5599. private timer function ClearFinishableEnemyList( dt : float, id : int )
  5600. {
  5601. finishableEnemiesList.Clear();
  5602. }
  5603.  
  5604. private var hostileEnemyToRemove : CActor;
  5605. private timer function RemoveEnemyFromHostileEnemiesListTimer( time : float , id : int)
  5606. {
  5607. hostileEnemies.Remove( hostileEnemyToRemove );
  5608.  
  5609. if( hostileEnemyToRemove.IsMonster() )
  5610. hostileMonsters.Remove( hostileEnemyToRemove );
  5611.  
  5612. hostileEnemyToRemove = NULL;
  5613. }
  5614.  
  5615. private function ClearHostileEnemiesList()
  5616. {
  5617. hostileEnemies.Clear();
  5618. hostileMonsters.Clear();
  5619. canFindPathEnemiesList.Clear();
  5620. }
  5621.  
  5622. private var moveTargets : array<CActor>; //all hostileEnemies that Geralt is aware of.
  5623. public function GetMoveTargets() : array<CActor> { return moveTargets; }
  5624. public function GetNumberOfMoveTargets() : int { return moveTargets.Size(); }
  5625. public function GetHostileEnemies() : array<CActor> { return hostileEnemies; }
  5626. public function GetHostileEnemiesCount() : int { return hostileEnemies.Size(); }
  5627.  
  5628. protected var enableStrafe : bool;
  5629.  
  5630.  
  5631. public function FindMoveTarget()
  5632. {
  5633. var moveTargetDists : array<float>;
  5634. var moveTargetCanPathFinds : array<bool>;
  5635. var aPotentialMoveTargetCanFindPath : bool;
  5636.  
  5637. var newMoveTarget : CActor;
  5638. var actors : array<CActor>;
  5639. var currentHeading : float;
  5640. var size, i : int;
  5641. var playerToNewMoveTargetDist : float;
  5642. var playerToMoveTargetDist : float;
  5643. var confirmEmptyMoveTarget : bool;
  5644. var newEmptyMoveTargetTimer : float;
  5645. var wasVisibleInFullFrame : bool;
  5646. var setIsThreatened : bool;
  5647.  
  5648. var enemysTarget : CActor;
  5649. var isEnemyInCombat : bool;
  5650. var potentialMoveTargets : array<CActor>;
  5651. var onlyThreatTargets : bool;
  5652.  
  5653. thePlayer.SetupEnemiesCollection( enemyCollectionDist, enemyCollectionDist, 10, 'None', FLAG_Attitude_Neutral + FLAG_Attitude_Hostile + FLAG_Attitude_Friendly + FLAG_OnlyAliveActors );
  5654.  
  5655. //if ( moveTarget )
  5656. // cachedMoveTarget = moveTarget;
  5657.  
  5658. if ( GetCurrentStateName() != 'PlayerDialogScene' && IsAlive() )//&& !IsInCombatAction() )//GetBIsCombatActionAllowed() )
  5659. {
  5660. GetVisibleEnemies( actors );
  5661.  
  5662. //Include enemies that geralt cannot see, but is hostile to him
  5663. if ( hostileEnemies.Size() > 0 )
  5664. {
  5665. for( i=0; i < hostileEnemies.Size() ; i+=1 )
  5666. {
  5667. if ( !actors.Contains( hostileEnemies[i] ) )
  5668. actors.PushBack( hostileEnemies[i] );
  5669. }
  5670. }
  5671.  
  5672. //Include enemies that are technically dead, but can be finished off
  5673. if ( finishableEnemiesList.Size() > 0 )
  5674. {
  5675. for( i=0; i < finishableEnemiesList.Size() ; i+=1 )
  5676. {
  5677. if ( !actors.Contains( finishableEnemiesList[i] ) )
  5678. actors.PushBack( finishableEnemiesList[i] );
  5679. }
  5680. }
  5681.  
  5682. //Check the last moveTarget for situation where enemy targets an ally when you round a corner
  5683. if ( moveTarget && !actors.Contains( moveTarget ) )
  5684. actors.PushBack( moveTarget );
  5685.  
  5686. FilterActors( actors, onlyThreatTargets, false );
  5687.  
  5688. //Determine whether Player should be threatened
  5689. if ( actors.Size() > 0 )
  5690. {
  5691. setIsThreatened = false;
  5692.  
  5693. if ( onlyThreatTargets )
  5694. {
  5695. setIsThreatened = true;
  5696. }
  5697. else
  5698. {
  5699. for( i=0; i < actors.Size() ; i+=1 )
  5700. {
  5701. if ( IsThreat( actors[i] ) )
  5702. {
  5703. setIsThreatened = true;
  5704. break;
  5705. }
  5706. else
  5707. {
  5708. enemysTarget = actors[i].GetTarget();
  5709. isEnemyInCombat = actors[i].IsInCombat();
  5710. if ( isEnemyInCombat && enemysTarget && GetAttitudeBetween( enemysTarget, this ) == AIA_Friendly && enemysTarget.isPlayerFollower )
  5711. {
  5712. setIsThreatened = true;
  5713. break;
  5714. }
  5715. }
  5716. }
  5717. }
  5718.  
  5719. //After filtering you will only have either all hostile or all neutral npcs
  5720. for( i = actors.Size()-1; i>=0; i-=1 )
  5721. {
  5722. if ( ( !actors[i].IsAlive() && !finishableEnemiesList.Contains( actors[i] ) )
  5723. || actors[i].IsKnockedUnconscious()
  5724. || this.GetUsedVehicle() == actors[i]
  5725. || !actors[i].CanBeTargeted() )
  5726. {
  5727. actors.EraseFast(i);
  5728. }
  5729. else if ( !IsThreatened() )
  5730. {
  5731. if ( !WasVisibleInScaledFrame( actors[i], 1.f, 1.f ) )
  5732. actors.EraseFast(i);
  5733. }
  5734. }
  5735. }
  5736. else if ( moveTarget && IsThreat( moveTarget ) )
  5737. setIsThreatened = true;
  5738. //SetIsThreatened( true );
  5739. else
  5740. setIsThreatened = false;
  5741. //SetIsThreatened( false );
  5742.  
  5743. if ( setIsThreatened )
  5744. {
  5745. enemyCollectionDist = 50.f;
  5746. SetIsThreatened( true );
  5747. }
  5748. else
  5749. {
  5750. if ( IsThreatened() )
  5751. AddTimer( 'finishableEnemiesList', 1.f );
  5752.  
  5753. enemyCollectionDist = findMoveTargetDistMax;
  5754. SetIsThreatened( false );
  5755. }
  5756.  
  5757. moveTargets = actors;
  5758. potentialMoveTargets = moveTargets;
  5759.  
  5760. //MS: By default Geralt will not play PCS_AlertNear unless there is one guy among the hostile npcs that canBeStrafed
  5761. if ( !moveTarget )
  5762. enableStrafe = false;
  5763.  
  5764. if ( potentialMoveTargets.Size() > 0 )
  5765. {
  5766. for ( i = 0; i < potentialMoveTargets.Size(); i += 1 )
  5767. {
  5768. if ( potentialMoveTargets[i].CanBeStrafed() )
  5769. enableStrafe = true;
  5770.  
  5771. if ( !potentialMoveTargets[i].GetGameplayVisibility() )
  5772. moveTargetDists.PushBack( 100.f ); //Put invisible enemies as the last choice for moveTarget
  5773. else
  5774. moveTargetDists.PushBack( VecDistance( potentialMoveTargets[i].GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() ) );
  5775.  
  5776. if ( canFindPathEnemiesList.Contains( potentialMoveTargets[i] ) )
  5777. {
  5778. moveTargetCanPathFinds.PushBack( true );
  5779. aPotentialMoveTargetCanFindPath = true;
  5780. }
  5781. else
  5782. {
  5783. moveTargetCanPathFinds.PushBack( false );
  5784. }
  5785. }
  5786.  
  5787. if ( aPotentialMoveTargetCanFindPath )
  5788. {
  5789. for ( i = moveTargetCanPathFinds.Size()-1 ; i >= 0; i-=1 )
  5790. {
  5791. if ( !moveTargetCanPathFinds[i] )
  5792. {
  5793. moveTargetCanPathFinds.EraseFast(i);
  5794. potentialMoveTargets.EraseFast(i);
  5795. moveTargetDists.EraseFast(i);
  5796. }
  5797. }
  5798. }
  5799.  
  5800. if ( moveTargetDists.Size() > 0 )
  5801. newMoveTarget = potentialMoveTargets[ ArrayFindMinF( moveTargetDists ) ];
  5802. }
  5803.  
  5804. if ( newMoveTarget && newMoveTarget != moveTarget )
  5805. {
  5806. if ( moveTarget )
  5807. {
  5808. playerToNewMoveTargetDist = VecDistance( newMoveTarget.GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() );
  5809. playerToMoveTargetDist = VecDistance( moveTarget.GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() );
  5810. wasVisibleInFullFrame = WasVisibleInScaledFrame( moveTarget, 1.f, 1.f ) ;
  5811.  
  5812. if ( !IsThreat( moveTarget )
  5813. || !wasVisibleInFullFrame
  5814. || !IsEnemyVisible( moveTarget )
  5815. || ( !moveTarget.IsAlive() && !finishableEnemiesList.Contains( moveTarget ) )
  5816. || !moveTarget.GetGameplayVisibility()
  5817. || ( moveTarget.IsAlive() && moveTarget.IsKnockedUnconscious() )
  5818. || ( wasVisibleInFullFrame && IsEnemyVisible( moveTarget ) && playerToNewMoveTargetDist < playerToMoveTargetDist - 0.25f ) )
  5819. {
  5820. SetMoveTarget( newMoveTarget );
  5821. }
  5822. }
  5823. else
  5824. SetMoveTarget( newMoveTarget );
  5825. }
  5826.  
  5827.  
  5828. if ( !IsThreatened() )
  5829. {
  5830. if ( moveTarget
  5831. && ( ( !moveTarget.IsAlive() && !finishableEnemiesList.Contains( moveTarget ) ) || !WasVisibleInScaledFrame( moveTarget, 0.8f, 1.f ) || VecDistance( moveTarget.GetWorldPosition(), this.GetWorldPosition() ) > theGame.params.MAX_THROW_RANGE ) )
  5832. {
  5833. confirmEmptyMoveTarget = true;
  5834. newEmptyMoveTargetTimer = 0.f;
  5835. }
  5836. }
  5837. /*else if ( moveTarget
  5838. && ( moveTarget.IsAlive() || finishableEnemiesList.Contains( moveTarget ) )
  5839. //&& moveTarget.GetGameplayVisibility()
  5840. && hostileEnemies.Contains( moveTarget ) )
  5841. */
  5842. else if ( moveTarget && ( IsThreat( moveTarget ) || finishableEnemiesList.Contains( moveTarget ) ) )
  5843. {
  5844. if ( !IsEnemyVisible( moveTarget ) )
  5845. {
  5846. confirmEmptyMoveTarget = true;
  5847. newEmptyMoveTargetTimer = 5.f;
  5848. }
  5849. else
  5850. SetMoveTarget( moveTarget );
  5851. }
  5852. else if ( IsInCombat() )
  5853. {
  5854. confirmEmptyMoveTarget = true;
  5855. newEmptyMoveTargetTimer = 1.0f;
  5856. }
  5857.  
  5858. if ( confirmEmptyMoveTarget )
  5859. {
  5860. if ( newEmptyMoveTargetTimer < emptyMoveTargetTimer )
  5861. {
  5862. bIsConfirmingEmptyTarget = false;
  5863. emptyMoveTargetTimer = newEmptyMoveTargetTimer;
  5864. }
  5865.  
  5866. ConfirmEmptyMoveTarget( newEmptyMoveTargetTimer );
  5867. }
  5868. }
  5869. else
  5870. SetIsThreatened( false );
  5871.  
  5872. //reactionsSystem
  5873. if ( IsThreatened() && !IsInFistFightMiniGame() )
  5874. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'CombatNearbyAction', 5.0, 18.0f, -1.f, -1, true ); //reactionSystemSearch
  5875. else
  5876. theGame.GetBehTreeReactionManager().RemoveReactionEvent( this, 'CombatNearbyAction'); //reactionSystemSearch
  5877.  
  5878. // sending nearby monsters count as parameter to sound system
  5879. theSound.SoundParameter( "monster_count", hostileMonsters.Size() );
  5880. }
  5881.  
  5882. private function ConfirmEmptyMoveTarget( timeDelta : float )
  5883. {
  5884. if ( !bIsConfirmingEmptyTarget )
  5885. {
  5886. bIsConfirmingEmptyTarget = true;
  5887. AddTimer( 'ConfirmEmptyTargetTimer', timeDelta );
  5888. }
  5889. }
  5890.  
  5891. private timer function ConfirmEmptyTargetTimer( time : float , id : int)
  5892. {
  5893. SetMoveTarget( NULL );
  5894. }
  5895.  
  5896.  
  5897. var isInCombatReason : int;
  5898. var canFindPathToEnemy : bool;
  5899. var combatModeEnt : CEntity;
  5900. var navDist : float;
  5901. var directDist : float;
  5902. var reachableEnemyWasTooFar : bool;
  5903. var reachableEnemyWasTooFarTimeStamp : float;
  5904. var reachablilityFailed : bool;
  5905. var reachablilityFailedTimeStamp : float;
  5906. public function ShouldEnableCombat( out unableToPathFind : bool, forceCombatMode : bool ) : bool
  5907. {
  5908. var shouldFindPathToNPCs : bool;
  5909. var playerToTargetDist : float;
  5910. var canFindPathToTarget : bool;
  5911. var moveTargetNPC : CNewNPC;
  5912. var currentTime : float;
  5913. var currentTime2 : float;
  5914. var isReachableEnemyTooFar : bool;
  5915. var reachableEnemyWasTooFarTimeStampDelta : float;
  5916. var reachablilityFailedTimeStampDelta : float;
  5917. var currentTimeTemp : float;
  5918.  
  5919. /*if ( GetIsSprinting() )
  5920. {
  5921. unableToPathFind = true;
  5922. isInCombatReason = 0;
  5923. return false;
  5924. }*/
  5925.  
  5926. if ( forceCombatMode && isSnappedToNavMesh )
  5927. return true;
  5928.  
  5929. if ( !IsThreatened() )
  5930. {
  5931. reachableEnemyWasTooFar = false;
  5932. reachablilityFailed = false;
  5933. isInCombatReason = 0;
  5934. return false;
  5935. }
  5936.  
  5937. if( thePlayer.substateManager.GetStateCur() != 'CombatExploration' && !thePlayer.substateManager.CanChangeToState( 'CombatExploration' )
  5938. && thePlayer.substateManager.GetStateCur() != 'Ragdoll' ) //&& !thePlayer.substateManager.CanChangeToState( 'Ragdoll' ) ) )
  5939. {
  5940. reachableEnemyWasTooFar = false;
  5941. reachablilityFailed = false;
  5942. isInCombatReason = 0;
  5943. return false;
  5944. }
  5945.  
  5946. if ( moveTarget )
  5947. {
  5948. canFindPathToEnemy = CanFindPathToTarget( unableToPathFind );
  5949. currentTimeTemp = EngineTimeToFloat( theGame.GetEngineTime() );
  5950.  
  5951. if ( canFindPathToEnemy )
  5952. isReachableEnemyTooFar = IsReachableEnemyTooFar();
  5953.  
  5954. if ( IsInCombat() )
  5955. {
  5956. if ( canFindPathToEnemy )
  5957. {
  5958. if ( forceCombatMode )
  5959. return true;
  5960.  
  5961. reachablilityFailed = false;
  5962. reachablilityFailedTimeStamp = currentTimeTemp;
  5963.  
  5964. if ( reachableEnemyWasTooFar )
  5965. {
  5966. if ( isReachableEnemyTooFar )
  5967. {
  5968. currentTime = currentTimeTemp;
  5969.  
  5970. if ( GetIsSprinting() )
  5971. reachableEnemyWasTooFarTimeStampDelta = 0.f;
  5972. else
  5973. reachableEnemyWasTooFarTimeStampDelta = 3.f;
  5974.  
  5975. if ( currentTime > reachableEnemyWasTooFarTimeStamp + reachableEnemyWasTooFarTimeStampDelta )
  5976. {
  5977. isInCombatReason = 0;
  5978. unableToPathFind = true;
  5979. return false;
  5980. }
  5981. }
  5982. else
  5983. reachableEnemyWasTooFar = false;
  5984. }
  5985. else
  5986. {
  5987. if ( isReachableEnemyTooFar )
  5988. {
  5989. reachableEnemyWasTooFar = true;
  5990. reachableEnemyWasTooFarTimeStamp = currentTimeTemp;
  5991. }
  5992. else
  5993. reachableEnemyWasTooFar = false;
  5994. }
  5995.  
  5996. return true;
  5997. }
  5998. else
  5999. {
  6000. reachableEnemyWasTooFar = false;
  6001. reachableEnemyWasTooFarTimeStamp = currentTimeTemp;
  6002.  
  6003. if ( reachablilityFailed )
  6004. {
  6005. if ( IsEnemyTooHighToReach() )
  6006. reachablilityFailedTimeStampDelta = 1.f;
  6007. else
  6008. reachablilityFailedTimeStampDelta = 5.f;
  6009.  
  6010. currentTime2 = currentTimeTemp;
  6011. if ( currentTime2 > reachablilityFailedTimeStamp + reachablilityFailedTimeStampDelta )
  6012. {
  6013. unableToPathFind = true;
  6014. return false;
  6015. }
  6016. }
  6017. else
  6018. {
  6019. reachablilityFailed = true;
  6020. reachablilityFailedTimeStamp = currentTimeTemp;
  6021. }
  6022.  
  6023. return true;
  6024. }
  6025. }
  6026. else if ( canFindPathToEnemy )
  6027. {
  6028. if ( forceCombatMode )
  6029. {
  6030. reachableEnemyWasTooFar = false;
  6031. return true;
  6032. }
  6033.  
  6034. reachablilityFailed = false;
  6035. reachablilityFailedTimeStamp = currentTimeTemp;
  6036.  
  6037. moveTargetNPC = (CNewNPC)moveTarget;
  6038. playerToTargetDist = VecDistance( moveTarget.GetWorldPosition(), this.GetWorldPosition() );
  6039.  
  6040. /*if ( !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), moveTarget.GetWorldPosition(), 0.4f ) )
  6041. {
  6042. isInCombatReason = 0;
  6043. return false;
  6044. }
  6045. else*/ if ( reachableEnemyWasTooFar
  6046. && ( isReachableEnemyTooFar || !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), moveTarget.GetWorldPosition(), 0.4f ) ) )
  6047. {
  6048. isInCombatReason = 0;
  6049. return false;
  6050. }
  6051. else if ( playerToTargetDist <= findMoveTargetDistMin )
  6052. isInCombatReason = 1;
  6053. else if ( ( moveTargetNPC.GetCurrentStance() == NS_Fly || moveTargetNPC.IsRanged() ) && hostileEnemies.Contains( moveTarget ) )
  6054. isInCombatReason = 2;
  6055. else
  6056. {
  6057. isInCombatReason = 0;
  6058. return false;
  6059. }
  6060.  
  6061. reachableEnemyWasTooFar = false;
  6062. return true;
  6063. }
  6064. }
  6065. else
  6066. {
  6067. reachableEnemyWasTooFar = false;
  6068. reachablilityFailed = false;
  6069. }
  6070.  
  6071. isInCombatReason = 0;
  6072. return false;
  6073. }
  6074.  
  6075. private function CanFindPathToTarget( out unableToPathFind : bool, optional forcedTarget : CNewNPC ) : bool
  6076. {
  6077. var moveTargetNPC : CNewNPC;
  6078. var moveTargetsTemp : array<CActor>;
  6079. var i : int;
  6080. var safeSpotTolerance : float;
  6081. var ent : CEntity;
  6082.  
  6083. moveTargetsTemp = moveTargets;
  6084.  
  6085. for ( i = 0; i < moveTargetsTemp.Size(); i += 1 )
  6086. {
  6087. moveTargetNPC = (CNewNPC)moveTargetsTemp[i];
  6088.  
  6089. if ( moveTargetNPC && moveTargetNPC.GetCurrentStance() == NS_Fly )
  6090. {
  6091. isInCombatReason = 2;
  6092. return true;
  6093. }
  6094. }
  6095.  
  6096. switch ( navQuery.GetLastOutput( 0.4 ) )
  6097. {
  6098. case EAsyncTastResult_Failure:
  6099. {
  6100. isInCombatReason = 0;
  6101. return false;
  6102. }
  6103. case EAsyncTastResult_Success:
  6104. {
  6105. ent = navQuery.GetOutputClosestEntity();
  6106.  
  6107. if ( ent )
  6108. combatModeEnt = moveTarget;
  6109.  
  6110. navDist = navQuery.GetOutputClosestDistance();
  6111.  
  6112. isInCombatReason = 1;
  6113. return true;
  6114. }
  6115. case EAsyncTastResult_Pending:
  6116. {
  6117. return canFindPathToEnemy;
  6118. }
  6119. case EAsyncTastResult_Invalidated:
  6120. {
  6121. if ( IsInCombat() )
  6122. {
  6123. if ( IsEnemyTooHighToReach() )
  6124. safeSpotTolerance = 0.f;
  6125. else
  6126. safeSpotTolerance = 3.f;
  6127. }
  6128. else
  6129. safeSpotTolerance = 0.f;
  6130.  
  6131. switch( navQuery.TestActorsList( ENavigationReachability_Any, this, moveTargetsTemp, safeSpotTolerance, 75.0 ) )
  6132. {
  6133. case EAsyncTastResult_Failure:
  6134. {
  6135. isInCombatReason = 0;
  6136. return false;
  6137. }
  6138. case EAsyncTastResult_Success:
  6139. {
  6140. ent = navQuery.GetOutputClosestEntity();
  6141.  
  6142. if ( ent )
  6143. combatModeEnt = moveTarget;
  6144.  
  6145. navDist = navQuery.GetOutputClosestDistance();
  6146.  
  6147. isInCombatReason = 1;
  6148. return true;
  6149. }
  6150. case EAsyncTastResult_Pending:
  6151. {
  6152. return canFindPathToEnemy;
  6153. }
  6154. case EAsyncTastResult_Invalidated:
  6155. {
  6156. if ( IsInCombat() )
  6157. return true;
  6158. else
  6159. return false;
  6160. }
  6161. }
  6162. }
  6163. }
  6164. }
  6165.  
  6166. private function IsReachableEnemyTooFar() : bool
  6167. {
  6168. //var navDistFailMax : float = 100.f;
  6169. var navDistLimit : float = findMoveTargetDist; //25.f;
  6170. var navDistDivisor : float = 2.f;
  6171. var playerToTargetVector : Vector;
  6172.  
  6173. directDist = VecDistance( combatModeEnt.GetWorldPosition(), thePlayer.GetWorldPosition() );
  6174. playerToTargetVector = this.GetWorldPosition() - combatModeEnt.GetWorldPosition();
  6175.  
  6176. if ( playerMode.GetForceCombatMode() || isInCombatReason == 2 )
  6177. return false;
  6178.  
  6179. if ( ( playerToTargetVector.Z < 0.5 && navDist > navDistLimit && directDist < navDist/navDistDivisor ) )
  6180. return true;
  6181. else
  6182. return false;
  6183. }
  6184.  
  6185. private function IsEnemyTooHighToReach() : bool
  6186. {
  6187. var playerToTargetVector : Vector;
  6188.  
  6189. playerToTargetVector = this.GetWorldPosition() - combatModeEnt.GetWorldPosition();
  6190.  
  6191. if ( playerToTargetVector.Z < -0.5f && !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), combatModeEnt.GetWorldPosition(), 0.4f ) )
  6192. return true;
  6193. else
  6194. return false;
  6195. }
  6196.  
  6197. //Force Geralt to face an enemy for a moment before changing to another enemy
  6198. public function LockToMoveTarget( lockTime : float )
  6199. {
  6200. /*if ( IsMoveTargetChangeAllowed() )
  6201. {
  6202. bMoveTargetChangeAllowed = false;
  6203. AddTimer( 'DisableLockToMoveTargetTimer', lockTime );
  6204. }*/
  6205. }
  6206.  
  6207. private timer function DisableLockToMoveTargetTimer( time : float , id : int)
  6208. {
  6209. if ( !this.IsActorLockedToTarget() )
  6210. {
  6211. SetMoveTargetChangeAllowed( true );
  6212. }
  6213. }
  6214.  
  6215. public function SetMoveTargetChangeAllowed( flag : bool )
  6216. {
  6217. //bMoveTargetChangeAllowed = flag;
  6218. }
  6219.  
  6220. public function IsMoveTargetChangeAllowed() : bool
  6221. {
  6222. return bMoveTargetChangeAllowed;
  6223. }
  6224.  
  6225. public function SetMoveTarget( actor : CActor )
  6226. {
  6227. if ( !actor && ForceCombatModeOverride() )
  6228. return;
  6229.  
  6230. if ( IsMoveTargetChangeAllowed()
  6231. && moveTarget != actor )
  6232. {
  6233. moveTarget = actor;
  6234. bIsConfirmingEmptyTarget = false;
  6235. RemoveTimer( 'ConfirmEmptyTargetTimer' );
  6236.  
  6237. if ( !moveTarget )
  6238. SetScriptMoveTarget( moveTarget );
  6239. }
  6240. }
  6241.  
  6242. private var isThreatened : bool;
  6243. protected function SetIsThreatened( flag : bool )
  6244. {
  6245. var allowSetIsThreatened : bool;
  6246.  
  6247. allowSetIsThreatened = true;
  6248. if ( ForceCombatModeOverride() )
  6249. {
  6250. if ( flag || !moveTarget )
  6251. allowSetIsThreatened = true;
  6252. else
  6253. allowSetIsThreatened = false;
  6254. }
  6255.  
  6256. if ( allowSetIsThreatened )
  6257. {
  6258. isThreatened = flag;
  6259. }
  6260. }
  6261.  
  6262. public function ForceCombatModeOverride() : bool
  6263. {
  6264. if( this.GetPlayerMode().GetForceCombatMode()
  6265. && canFindPathToEnemy
  6266. && theGame.GetGlobalAttitude( GetBaseAttitudeGroup(), moveTarget.GetBaseAttitudeGroup() ) == AIA_Hostile )
  6267. return true;
  6268. else
  6269. return false;
  6270. }
  6271.  
  6272. public function IsThreatened() : bool { return isThreatened; }
  6273.  
  6274. public function EnableFindTarget( flag : bool )
  6275. {
  6276. var target : CActor;
  6277.  
  6278. if( IsActorLockedToTarget() )
  6279. {
  6280. target = GetTarget();
  6281.  
  6282. if ( target && target.IsAlive() )
  6283. bCanFindTarget = flag;
  6284. else
  6285. bCanFindTarget = true;
  6286. }
  6287. else
  6288. bCanFindTarget = flag;
  6289. }
  6290.  
  6291. public function UpdateDisplayTarget( optional forceUpdate : bool, optional forceNullActor : bool )
  6292. {
  6293. var hud : CR4ScriptedHud;
  6294. var tempTarget : CGameplayEntity;
  6295. var angleDist1 : float;
  6296. var angleDist2 : float;
  6297. var nonActorTargetMult : float;
  6298. var combatActionType : int;
  6299. var currTarget : CActor;
  6300. var interactionTarget : CInteractionComponent;
  6301.  
  6302. var heading : float;
  6303.  
  6304. if(theGame.IsDialogOrCutscenePlaying())
  6305. {
  6306. currentSelectedDisplayTarget = NULL;
  6307.  
  6308. if ( displayTarget )
  6309. ConfirmDisplayTarget( NULL );
  6310.  
  6311. return;
  6312. }
  6313.  
  6314. if ( forceNullActor )
  6315. currTarget = NULL;
  6316. else
  6317. currTarget = GetTarget();
  6318.  
  6319. currentSelectedDisplayTarget = currTarget;
  6320.  
  6321. if ( currTarget && !currTarget.IsTargetableByPlayer() )
  6322. {
  6323. currentSelectedDisplayTarget = NULL;
  6324. ConfirmDisplayTarget( currentSelectedDisplayTarget );
  6325. return;
  6326. }
  6327. //Setting multiplier that increases non actor target priority
  6328. nonActorTargetMult = 1.25;
  6329.  
  6330. //Update the interaction icon
  6331. hud = (CR4ScriptedHud)theGame.GetHud();
  6332.  
  6333. if ( !IsThreatened() )
  6334. {
  6335. if ( !bLAxisReleased || lastAxisInputIsMovement )
  6336. {
  6337. if ( currTarget )
  6338. angleDist1 = AbsF( AngleDistance( this.GetHeading(), VecHeading( currTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6339. else
  6340. angleDist1 = 360;
  6341.  
  6342. if ( nonActorTarget )
  6343. angleDist2 = AbsF( AngleDistance( this.GetHeading(), VecHeading( nonActorTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6344. else
  6345. angleDist2 = 360;
  6346. }
  6347. else
  6348. {
  6349. if ( currTarget )
  6350. angleDist1 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( currTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6351. else
  6352. angleDist1 = 360;
  6353.  
  6354. if ( nonActorTarget )
  6355. angleDist2 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( nonActorTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6356. else
  6357. angleDist2 = 360;
  6358. }
  6359. }
  6360.  
  6361. else
  6362. {
  6363. if ( !bLAxisReleased )
  6364. {
  6365. if ( ShouldUsePCModeTargeting() )
  6366. {
  6367. if ( currTarget )
  6368. angleDist1 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( currTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6369. else
  6370. angleDist1 = 360;
  6371.  
  6372. if ( nonActorTarget && IsInCombatAction() )
  6373. {
  6374. angleDist2 = nonActorTargetMult * AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( nonActorTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) );
  6375. }
  6376. else
  6377. angleDist2 = 360;
  6378. }
  6379. else
  6380. {
  6381. if ( currTarget )
  6382. angleDist1 = AbsF( AngleDistance( rawPlayerHeading, VecHeading( currTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6383. else
  6384. angleDist1 = 360;
  6385.  
  6386. if ( nonActorTarget && IsInCombatAction() )
  6387. {
  6388. angleDist2 = nonActorTargetMult * AbsF( AngleDistance( rawPlayerHeading, VecHeading( nonActorTarget.GetWorldPosition() - this.GetWorldPosition() ) ) );
  6389. }
  6390. else
  6391. angleDist2 = 360;
  6392. }
  6393. }
  6394. else
  6395. {
  6396. angleDist1 = 0;
  6397. angleDist2 = 360;
  6398. }
  6399. }
  6400.  
  6401.  
  6402. if ( angleDist1 < angleDist2 )
  6403. tempTarget = currTarget;
  6404. else
  6405. tempTarget = nonActorTarget;
  6406.  
  6407.  
  6408. if ( slideTarget && IsInCombatAction() )
  6409. {
  6410. combatActionType = (int)this.GetBehaviorVariable( 'combatActionType' );
  6411. if ( combatActionType == (int)CAT_Attack
  6412. || ( combatActionType == (int)CAT_SpecialAttack && this.GetBehaviorVariable( 'playerAttackType' ) == 1.f )
  6413. || ( combatActionType == (int)CAT_ItemThrow )
  6414. || ( combatActionType == (int)CAT_CastSign && !IsCurrentSignChanneled() )
  6415. || ( combatActionType == (int)CAT_CastSign && IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Axii )
  6416. || ( combatActionType == (int)CAT_CastSign && IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Igni )
  6417. || combatActionType == (int)CAT_Dodge
  6418. || combatActionType == (int)CAT_Roll )
  6419. {
  6420. if ( combatActionType == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Igni && !IsCombatMusicEnabled() )
  6421. currentSelectedDisplayTarget = tempTarget;
  6422. else
  6423. currentSelectedDisplayTarget = slideTarget;
  6424. }
  6425. else
  6426. currentSelectedDisplayTarget = tempTarget;
  6427. }
  6428. else if ( slideTarget
  6429. && this.rangedWeapon
  6430. && this.rangedWeapon.GetCurrentStateName() != 'State_WeaponWait'
  6431. && this.playerAiming.GetCurrentStateName() == 'Waiting' ) //( this.rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' || this.rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' ) )
  6432. currentSelectedDisplayTarget = slideTarget;
  6433. else
  6434. currentSelectedDisplayTarget = tempTarget;
  6435.  
  6436. interactionTarget = theGame.GetInteractionsManager().GetActiveInteraction();
  6437. if ( interactionTarget && !IsThreatened() && !( this.IsCastingSign() && this.IsCurrentSignChanneled() ) )
  6438. {
  6439. tempTarget = (CGameplayEntity)interactionTarget.GetEntity();
  6440. if ( tempTarget && tempTarget != this.GetUsedVehicle() )
  6441. {
  6442. currentSelectedDisplayTarget = tempTarget;
  6443. SetDisplayTarget( currentSelectedDisplayTarget );
  6444. }
  6445. }
  6446.  
  6447. // disabling display for invisible targets
  6448. if ( (CActor)currentSelectedDisplayTarget && !((CActor)currentSelectedDisplayTarget).GetGameplayVisibility() )
  6449. {
  6450. currentSelectedDisplayTarget = NULL;
  6451. }
  6452.  
  6453. if ( displayTarget != currentSelectedDisplayTarget )
  6454. {
  6455. if ( forceUpdate )
  6456. SetDisplayTarget( currentSelectedDisplayTarget );
  6457. else
  6458. ConfirmDisplayTarget( currentSelectedDisplayTarget );
  6459. }
  6460. }
  6461.  
  6462. private var bConfirmDisplayTargetTimerEnabled : bool;
  6463. private var displayTargetToConfirm : CGameplayEntity;
  6464. private var currentSelectedDisplayTarget : CGameplayEntity;
  6465.  
  6466. private function ConfirmDisplayTarget( targetToConfirm : CGameplayEntity )
  6467. {
  6468. if ( targetToConfirm != displayTarget )
  6469. {
  6470. displayTargetToConfirm = targetToConfirm;
  6471. if( !bConfirmDisplayTargetTimerEnabled )
  6472. {
  6473. bConfirmDisplayTargetTimerEnabled = true;
  6474.  
  6475. if ( targetToConfirm )
  6476. AddTimer( 'ConfirmDisplayTargetTimer', 0.1f );
  6477. else
  6478. AddTimer( 'ConfirmDisplayTargetTimer', 0.f );
  6479. }
  6480. }
  6481. }
  6482.  
  6483. private timer function ConfirmDisplayTargetTimer( time : float, optional id : int)
  6484. {
  6485. if ( displayTargetToConfirm == currentSelectedDisplayTarget )
  6486. SetDisplayTarget( displayTargetToConfirm );
  6487.  
  6488. bConfirmDisplayTargetTimerEnabled = false;
  6489. }
  6490.  
  6491.  
  6492. protected function SetDisplayTarget( e : CGameplayEntity )
  6493. {
  6494. var displayTargetActor : CActor;
  6495.  
  6496. if ( e != displayTarget )
  6497. {
  6498. displayTarget = e;
  6499. displayTargetActor = (CActor)displayTarget;
  6500. SetPlayerCombatTarget( displayTargetActor );
  6501.  
  6502. if ( displayTargetActor && !displayTargetActor.IsTargetableByPlayer())
  6503. {
  6504. isDisplayTargetTargetable = false;
  6505. }
  6506. else if ( !displayTargetActor && displayTarget != nonActorTarget )
  6507. {
  6508. isDisplayTargetTargetable = false;
  6509. }
  6510. else
  6511. {
  6512. isDisplayTargetTargetable = true;
  6513. }
  6514. }
  6515. }
  6516.  
  6517. public function GetDisplayTarget() : CGameplayEntity { return displayTarget; }
  6518.  
  6519. private var isDisplayTargetTargetable : bool;
  6520. public function IsDisplayTargetTargetable() : bool
  6521. {
  6522. return isDisplayTargetTargetable;
  6523. }
  6524.  
  6525. public var radialSlots : array<name>;
  6526. public function EnableRadialSlots( enable : bool, slotNames : array<name> )
  6527. {
  6528. var hud : CR4ScriptedHud;
  6529. var module : CR4HudModuleRadialMenu;
  6530. var i : int;
  6531.  
  6532. hud = (CR4ScriptedHud)theGame.GetHud();
  6533. module = (CR4HudModuleRadialMenu)hud.GetHudModule("RadialMenuModule");
  6534.  
  6535. for(i=0; i<slotNames.Size(); i+=1)
  6536. {
  6537. module.SetDesaturated( !enable, slotNames[i] );
  6538. }
  6539. }
  6540.  
  6541. public function IsEnemyInCone( source : CActor, coneHeading : Vector, coneDist, coneAngle : float, out newLockTarget : CActor ) : bool
  6542. {
  6543. var targets : array<CActor>;
  6544. var sourceToTargetDists : array<float>;
  6545. var i : int;
  6546. var targetingInfo : STargetingInfo;
  6547.  
  6548. //GetVisibleEnemies( targets );
  6549. //targets = FilterActors( targets );
  6550. targets = GetMoveTargets();
  6551.  
  6552. if ( targets.Size() > 0 )
  6553. {
  6554. targetingInfo.source = this;
  6555. targetingInfo.canBeTargetedCheck = true;
  6556. targetingInfo.coneCheck = true;
  6557. targetingInfo.coneHalfAngleCos = CosF( Deg2Rad( coneAngle * 0.5f ) );
  6558. targetingInfo.coneDist = coneDist;
  6559. targetingInfo.coneHeadingVector = coneHeading;
  6560. targetingInfo.distCheck = true;
  6561. targetingInfo.invisibleCheck = true;
  6562. targetingInfo.navMeshCheck = true;
  6563. targetingInfo.inFrameCheck = false;
  6564. targetingInfo.frameScaleX = 1.f;
  6565. targetingInfo.frameScaleY = 1.f;
  6566. targetingInfo.knockDownCheck = false;
  6567. targetingInfo.knockDownCheckDist = 1.5f;
  6568. targetingInfo.rsHeadingCheck = false;
  6569. targetingInfo.rsHeadingLimitCos = 1.0f;
  6570.  
  6571. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  6572. {
  6573. targetingInfo.targetEntity = targets[i];
  6574. if ( !IsEntityTargetable( targetingInfo ) )
  6575. targets.Erase( i );
  6576. }
  6577.  
  6578. for ( i = 0; i < targets.Size(); i += 1 )
  6579. sourceToTargetDists.PushBack( VecDistance( source.GetWorldPosition(), targets[i].GetWorldPosition() ) );
  6580.  
  6581. if(sourceToTargetDists.Size() > 0)
  6582. newLockTarget = targets[ ArrayFindMinF( sourceToTargetDists ) ];
  6583. else
  6584. newLockTarget = NULL;
  6585. }
  6586.  
  6587. return targets.Size() > 0;
  6588. }
  6589.  
  6590. public function GetScreenSpaceLockTarget( sourceEnt : CGameplayEntity, coneAngle, coneDist, coneHeading : float, optional inFrameCheck : bool ) : CActor
  6591. {
  6592. var source : CActor;
  6593. var sourcePos, targetPos : Vector;
  6594. var targets : array<CActor>;
  6595. var sourceToTargetDists : array<float>;
  6596. var sourceCoord : Vector;
  6597. var targetCoord : Vector;
  6598. var i : int;
  6599. var angleDiff : float;
  6600. var sourceToTargetHeading : float;
  6601. var sourceToTargetDist : float;
  6602. var size : float;
  6603. var targetingDist : float;
  6604. var targetingInfo : STargetingInfo;
  6605.  
  6606. var temp : int;
  6607.  
  6608. // MAREK TODO : Need to use cached values of screenspace coords instead of calculating again
  6609. //GetVisibleEnemies( targets );
  6610. //targets = FilterActors( targets );
  6611. source = (CActor)sourceEnt;
  6612.  
  6613. targets = GetMoveTargets();
  6614.  
  6615. if ( this.IsPCModeEnabled() )
  6616. {
  6617. if ( ( coneHeading > -45.f && coneHeading < 45.f )
  6618. || coneHeading > 135.f
  6619. || coneHeading < -135.f )
  6620. {
  6621. if ( coneHeading > 0 )
  6622. coneHeading = 180 - coneHeading;
  6623. else
  6624. coneHeading = 180 + coneHeading;
  6625. }
  6626. }
  6627.  
  6628. /*if ( IsCombatMusicEnabled() || hostileEnemies.Size() > 0 )
  6629. {
  6630. if ( targets[0] && !IsThreat( targets[0] ) )
  6631. targets.Clear();
  6632. }*/
  6633.  
  6634. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  6635. {
  6636. if ( ( !targets[i].GetGameplayVisibility() || !IsThreat( targets[i] ) || !IsEnemyVisible( targets[i] ) || !this.CanBeTargetedIfSwimming( targets[i] ) )
  6637. && ( !IsCastingSign() || GetCurrentlyCastSign() != ST_Axii ) )
  6638. targets.Erase(i);
  6639. }
  6640.  
  6641. if ( source )
  6642. {
  6643. temp = source.GetTorsoBoneIndex();
  6644.  
  6645. if ( temp < 0 )
  6646. sourcePos = source.GetWorldPosition();
  6647. else
  6648. sourcePos = MatrixGetTranslation( source.GetBoneWorldMatrixByIndex( source.GetTorsoBoneIndex() ) );
  6649. }
  6650. else
  6651. sourcePos = sourceEnt.GetWorldPosition();
  6652.  
  6653. theCamera.WorldVectorToViewRatio( sourcePos, sourceCoord.X , sourceCoord.Y );
  6654.  
  6655. /*if ( !IsUsingVehicle() )
  6656. targetingDist = softLockDist;
  6657. else*/
  6658. targetingDist = softLockDistVehicle;
  6659.  
  6660. if ( targets.Size() > 0 )
  6661. {
  6662. targetingInfo.source = this;
  6663. targetingInfo.canBeTargetedCheck = true;
  6664. targetingInfo.coneCheck = false;
  6665. targetingInfo.coneHalfAngleCos = 0.86602540378f; // = CosF( Deg2Rad( 60.0f * 0.5f ) )
  6666. targetingInfo.coneDist = targetingDist;
  6667. targetingInfo.coneHeadingVector = Vector( 0.0f, 1.0f, 0.0f );
  6668. targetingInfo.distCheck = true;
  6669. targetingInfo.invisibleCheck = true;
  6670. targetingInfo.navMeshCheck = false;
  6671.  
  6672. if ( inFrameCheck )
  6673. targetingInfo.inFrameCheck = true;
  6674. else
  6675. targetingInfo.inFrameCheck = false;
  6676.  
  6677. targetingInfo.frameScaleX = 1.f;
  6678. targetingInfo.frameScaleY = 1.f;
  6679. targetingInfo.knockDownCheck = false;
  6680. targetingInfo.knockDownCheckDist = softLockDist;
  6681. if ( bRAxisReleased )
  6682. targetingInfo.rsHeadingCheck = false;
  6683. else
  6684. targetingInfo.rsHeadingCheck = true;
  6685. targetingInfo.rsHeadingLimitCos = -0.5f; // = CosF( Deg2Rad( 120.0f ) );
  6686.  
  6687. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  6688. {
  6689. temp = targets[i].GetTorsoBoneIndex();
  6690.  
  6691. if ( temp < 0 )
  6692. targetPos = targets[i].GetWorldPosition();
  6693. else
  6694. targetPos = MatrixGetTranslation( targets[i].GetBoneWorldMatrixByIndex( targets[i].GetTorsoBoneIndex() ) );
  6695.  
  6696. theCamera.WorldVectorToViewRatio( targetPos, targetCoord.X, targetCoord.Y );
  6697. sourceToTargetHeading = VecHeading( targetCoord - sourceCoord );
  6698. angleDiff = AbsF( AngleDistance( coneHeading, sourceToTargetHeading ) );
  6699.  
  6700. targetingInfo.targetEntity = targets[i];
  6701. if ( !IsEntityTargetable( targetingInfo ) )
  6702. targets.Erase( i );
  6703. else if ( !bRAxisReleased && angleDiff > ( coneAngle * 0.5 ) )
  6704. targets.Erase( i );
  6705. else if ( targets[i] == sourceEnt )
  6706. targets.Erase( i );
  6707.  
  6708. /*if ( GetDisplayTarget() && IsInCombatAction() && GetBehaviorVariable( 'combatActionType') == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Igni )
  6709. {
  6710.  
  6711. }
  6712. else
  6713. {
  6714. targetingInfo.rsHeadingCheck = false;
  6715. if ( !IsEntityTargetable( targetingInfo )
  6716. || angleDiff > ( coneAngle * 0.5 )
  6717. || targets[i] == sourceEnt )
  6718. targets.Erase( i );
  6719. }*/
  6720. }
  6721. }
  6722.  
  6723. size = targets.Size();
  6724. if ( size > 0 )
  6725. {
  6726. for ( i = 0; i < targets.Size(); i += 1 )
  6727. {
  6728. temp = targets[i].GetTorsoBoneIndex();
  6729.  
  6730. if ( temp < 0 )
  6731. targetPos = targets[i].GetWorldPosition();
  6732. else
  6733. targetPos = MatrixGetTranslation( targets[i].GetBoneWorldMatrixByIndex( targets[i].GetTorsoBoneIndex() ) );
  6734.  
  6735. theCamera.WorldVectorToViewRatio( targetPos, targetCoord.X, targetCoord.Y );
  6736. sourceToTargetHeading = AbsF( VecHeading( targetCoord - sourceCoord ) );
  6737. angleDiff = AngleDistance( 180, sourceToTargetHeading );
  6738. sourceToTargetDist = VecDistance2D( sourceCoord, targetCoord );
  6739.  
  6740. sourceToTargetDists.PushBack( SinF( Deg2Rad( angleDiff ) ) * sourceToTargetDist );
  6741. }
  6742. }
  6743.  
  6744. if ( targets.Size() > 0 )//GetDisplayTarget() )
  6745. return targets[ ArrayFindMinF( sourceToTargetDists ) ];
  6746. else
  6747. return NULL;
  6748. }
  6749.  
  6750. public function IsEntityTargetable( out info : STargetingInfo, optional usePrecalcs : bool ) : bool
  6751. {
  6752. var playerHasBlockingBuffs : bool;
  6753. var sourceActor : CActor;
  6754. var targetEntity : CEntity;
  6755. var targetActor : CActor;
  6756. var targetNPC : CNewNPC;
  6757. var sourcePosition : Vector;
  6758. var targetPosition : Vector;
  6759. var direction : Vector;
  6760. var sourceToTargetDist : float;
  6761. var sourceCapsuleRadius : float;
  6762. var mpac : CMovingPhysicalAgentComponent;
  6763.  
  6764. var coneDistSq : float;
  6765. var knockDownCheckDistSq : float;
  6766. var sourceToTargetAngleDist : float;
  6767. var b : bool;
  6768. var infoSourceWorldPos : Vector;
  6769. var infoTargetWorldPos : Vector;
  6770. var finishEnabled : bool;
  6771.  
  6772. if ( usePrecalcs )
  6773. {
  6774. playerHasBlockingBuffs = targetingIn.playerHasBlockingBuffs;
  6775. }
  6776. else
  6777. {
  6778. playerHasBlockingBuffs = thePlayer.HasBuff( EET_Confusion ) || thePlayer.HasBuff( EET_Hypnotized ) || thePlayer.HasBuff( EET_Blindness ) || thePlayer.HasBuff( EET_WraithBlindness );
  6779. }
  6780. if ( playerHasBlockingBuffs )
  6781. {
  6782. return false;
  6783. }
  6784.  
  6785. sourceActor = info.source;
  6786. targetEntity = info.targetEntity;
  6787. if ( !sourceActor || !targetEntity )
  6788. {
  6789. return false;
  6790. }
  6791.  
  6792. targetActor = (CActor)targetEntity;
  6793.  
  6794. // "can be targeted" check
  6795. if ( info.canBeTargetedCheck && !targetActor.CanBeTargeted() )
  6796. {
  6797. return false;
  6798. }
  6799.  
  6800. // visibility check
  6801. if ( info.invisibleCheck && !targetActor.GetGameplayVisibility() )
  6802. {
  6803. return false;
  6804. }
  6805.  
  6806. sourcePosition = sourceActor.GetWorldPosition();
  6807. targetPosition = targetEntity.GetWorldPosition();
  6808.  
  6809. if ( targetActor )
  6810. {
  6811. { // do not target mounted horses
  6812. targetNPC = (CNewNPC)targetActor;
  6813. if ( targetNPC )
  6814. {
  6815. if ( targetNPC.IsHorse() && !targetNPC.GetHorseComponent().IsDismounted() )
  6816. {
  6817. return false;
  6818. }
  6819. }
  6820. }
  6821. }
  6822.  
  6823. if ( info.distCheck || info.knockDownCheck )
  6824. {
  6825. if ( usePrecalcs )
  6826. {
  6827. if ( targetActor )
  6828. {
  6829. // radius is taken form the first actor
  6830. sourceToTargetDist = Distance2DBetweenCapsuleAndPoint( targetActor, sourceActor ) - targetingPrecalcs.playerRadius;
  6831. }
  6832. else
  6833. {
  6834. sourceToTargetDist = VecDistance2D( sourcePosition, targetPosition ) - targetingPrecalcs.playerRadius;
  6835. }
  6836. }
  6837. else
  6838. {
  6839. if ( targetActor )
  6840. {
  6841. sourceToTargetDist = Distance2DBetweenCapsules( sourceActor, targetActor );
  6842. }
  6843. else
  6844. {
  6845. sourceToTargetDist = Distance2DBetweenCapsuleAndPoint( sourceActor, targetEntity );
  6846. }
  6847. }
  6848. }
  6849.  
  6850. // distance check
  6851. if ( info.distCheck )
  6852. {
  6853. if ( sourceToTargetDist >= info.coneDist )
  6854. {
  6855. return false;
  6856. }
  6857. }
  6858.  
  6859. // prepare source to target direction if needed
  6860. if ( info.coneCheck || info.rsHeadingCheck )
  6861. {
  6862. direction = VecNormalize2D( targetPosition - sourcePosition );
  6863. }
  6864.  
  6865. // cone check
  6866. if ( info.coneCheck )
  6867. {
  6868. if ( VecDot2D( direction, info.coneHeadingVector ) < info.coneHalfAngleCos )
  6869. {
  6870. return false;
  6871. }
  6872. }
  6873.  
  6874. // heading cone check
  6875. if ( info.rsHeadingCheck )
  6876. {
  6877. if ( usePrecalcs )
  6878. {
  6879. if ( VecDot2D( direction, targetingIn.lookAtDirection ) < info.rsHeadingLimitCos )
  6880. {
  6881. return false;
  6882. }
  6883. }
  6884. else
  6885. {
  6886. if ( VecDot2D( direction, VecNormalize2D( GetLookAtPosition() - sourcePosition ) ) < info.rsHeadingLimitCos )
  6887. {
  6888. return false;
  6889. }
  6890. }
  6891. }
  6892.  
  6893. // "in frame" check
  6894. if ( info.inFrameCheck && !WasVisibleInScaledFrame( targetEntity, info.frameScaleX, info.frameScaleY ) )
  6895. {
  6896. return false;
  6897. }
  6898.  
  6899. // navmesh check
  6900. if ( info.navMeshCheck && !IsSwimming() )
  6901. {
  6902. sourceCapsuleRadius = 0.1f;
  6903. if ( usePrecalcs )
  6904. {
  6905. sourceCapsuleRadius = targetingPrecalcs.playerRadius;
  6906. }
  6907. else
  6908. {
  6909. mpac = (CMovingPhysicalAgentComponent)sourceActor.GetMovingAgentComponent();
  6910. if ( mpac )
  6911. {
  6912. sourceCapsuleRadius = mpac.GetCapsuleRadius();
  6913. }
  6914. }
  6915. if ( !theGame.GetWorld().NavigationLineTest( sourcePosition, targetPosition, sourceCapsuleRadius ) )
  6916. {
  6917. return false;
  6918. }
  6919. }
  6920.  
  6921. // knockdown check
  6922. if ( info.knockDownCheck )
  6923. {
  6924. // if actor is not alive
  6925. if ( targetActor && !targetActor.IsAlive() )
  6926. {
  6927. // and contains enabled "Finish" interaction
  6928. finishEnabled = targetActor.GetComponent( 'Finish' ).IsEnabled();
  6929. if ( finishEnabled )
  6930. {
  6931. // and is contained in finishable enemies list
  6932. if ( finishableEnemiesList.Contains( targetActor ) )
  6933. {
  6934. // and is too far to "finish" -> we cannot target it
  6935. if ( sourceToTargetDist >= info.knockDownCheckDist )
  6936. {
  6937. return false;
  6938. }
  6939. }
  6940. }
  6941. }
  6942. }
  6943.  
  6944. return true;
  6945. }
  6946.  
  6947. public function CanBeTargetedIfSwimming( actor : CActor, optional usePrecalcs : bool ) : bool
  6948. {
  6949. var subDepth : float;
  6950. var isDiving : bool;
  6951.  
  6952. if ( !actor )
  6953. {
  6954. return false;
  6955. }
  6956.  
  6957. if ( usePrecalcs )
  6958. {
  6959. isDiving = targetingIn.isDiving;
  6960. }
  6961. else
  6962. {
  6963. isDiving = IsSwimming() && OnCheckDiving();
  6964. }
  6965.  
  6966. subDepth = ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetSubmergeDepth();
  6967.  
  6968. if ( isDiving )
  6969. {
  6970. return ( subDepth < -1.0f );
  6971. }
  6972. else
  6973. {
  6974. return ( subDepth >= -1.0f );
  6975. }
  6976. }
  6977.  
  6978. /*
  6979. 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
  6980. {
  6981. var targetActor : CActor;
  6982. var targetNPC : CNewNPC;
  6983. var direction : Vector;
  6984. var sourceToTargetDist : float;
  6985. var coneDistSq : float;
  6986. var sourceCapsuleRadius : float;
  6987. var knockDownCheckDistSq : float;
  6988. var sourceToTargetAngleDist : float;
  6989. var b : bool;
  6990. var targetsHorse : W3HorseComponent;
  6991.  
  6992. direction = VecNormalize2D( targetEntity.GetWorldPosition() - source.GetWorldPosition() );
  6993. targetActor = (CActor)targetEntity;
  6994.  
  6995. if ( distCheck )
  6996. {
  6997. if ( targetActor )
  6998. sourceToTargetDist = VecDistanceSquared( source.GetWorldPosition(), targetActor.GetNearestPointInBothPersonalSpaces( source.GetWorldPosition() ) );
  6999. else
  7000. sourceToTargetDist = VecDistanceSquared( source.GetWorldPosition(), targetEntity.GetWorldPosition() );
  7001.  
  7002. coneDistSq = coneDist * coneDist;
  7003. }
  7004.  
  7005. if ( knockDownCheck && targetActor )
  7006. knockDownCheckDistSq = knockDownCheckDist * knockDownCheckDist;
  7007.  
  7008. if ( navMeshCheck && targetActor )
  7009. sourceCapsuleRadius = ((CMovingPhysicalAgentComponent)source.GetMovingAgentComponent()).GetCapsuleRadius();
  7010.  
  7011. if ( rsHeadingCheck )
  7012. sourceToTargetAngleDist = AngleDistance( VecHeading( GetLookAtPosition() - source.GetWorldPosition() ), VecHeading( targetEntity.GetWorldPosition() - source.GetWorldPosition() ) );
  7013.  
  7014. // do not target mounted horses
  7015. if(targetActor)
  7016. {
  7017. targetNPC = (CNewNPC)targetActor;
  7018. if(targetNPC)
  7019. {
  7020. targetsHorse = (W3HorseComponent)targetNPC.GetHorseComponent();
  7021. if(targetsHorse && targetsHorse.IsNotBeingUsed() )
  7022. return false;
  7023. }
  7024. }
  7025.  
  7026. b = !coneCheck || AbsF( AngleDistance( coneHeading, VecHeading( direction ) ) ) < ( coneAngle * 0.5 );
  7027. b = b && ( !distCheck || sourceToTargetDist < coneDistSq );
  7028. b = b && ( !invisibleCheck || targetActor.GetGameplayVisibility() );
  7029. b = b && ( !navMeshCheck || (!IsSwimming() && theGame.GetWorld().NavigationLineTest( source.GetWorldPosition(), targetActor.GetWorldPosition(), sourceCapsuleRadius ) ) );
  7030. b = b && ( !inFrameCheck || WasVisibleInScaledFrame( targetEntity, frameScaleX, frameScaleY ) );
  7031. b = b && ( !rsHeadingCheck || ( rsHeading >= 0 && sourceToTargetAngleDist < 0 && sourceToTargetAngleDist >= ( rsHeadingLimit * -1 ) ) || ( rsHeading < 0 && sourceToTargetAngleDist >= 0 && sourceToTargetAngleDist <= rsHeadingLimit ) );
  7032. b = b && ( !knockDownCheck || !targetActor.GetComponent( 'Finish' ).IsEnabled() || ( targetActor.GetComponent( 'Finish' ).IsEnabled() && sourceToTargetDist < knockDownCheckDistSq ) );
  7033.  
  7034. if ( b )
  7035. return true;
  7036. else
  7037. return false;
  7038. }
  7039. */
  7040. private function FilterActors( out targets : array<CActor>, out onlyThreatsReturned : bool, optional usePrecalcs : bool )
  7041. {
  7042. var i : int;
  7043. var size : int;
  7044. var foundThreat : bool;
  7045. var foundNonThreat : bool;
  7046. var threatsCount : int;
  7047. var tmpActor : CActor;
  7048.  
  7049. foundThreat = false;
  7050. foundNonThreat = false;
  7051.  
  7052. size = targets.Size();
  7053. i = 0;
  7054. threatsCount = 0;
  7055.  
  7056. // after that loop first "threatsCount" targets will be "threat"
  7057. for ( i = 0; i < size; i+=1 )
  7058. {
  7059. if( IsThreat( targets[ i ], usePrecalcs ) )
  7060. {
  7061. foundThreat = true;
  7062. if ( i != threatsCount )
  7063. {
  7064. tmpActor = targets[ i ];
  7065. targets[ i ] = targets[ threatsCount ];
  7066. targets[ threatsCount ] = tmpActor;
  7067. }
  7068. threatsCount += 1;
  7069. }
  7070. else
  7071. {
  7072. foundNonThreat = true;
  7073. }
  7074. }
  7075.  
  7076. if ( foundThreat )
  7077. {
  7078. onlyThreatsReturned = true;
  7079. if ( foundNonThreat )
  7080. {
  7081. targets.Resize( threatsCount );
  7082. }
  7083. }
  7084. }
  7085.  
  7086. private function InternalFindTargetsInCone( out targets : array< CActor >, out outHeadingVector : Vector, optional usePrecalcs : bool )
  7087. {
  7088. var size, i : int;
  7089. var coneHalfAngleDot : float;
  7090. var coneHeading : float;
  7091. var coneHeadingVector : Vector;
  7092. var position : Vector;
  7093. var direction : Vector;
  7094. var onlyThreatTargetsFound : bool;
  7095.  
  7096. targets.Clear();
  7097. GetVisibleEnemies( targets );
  7098.  
  7099. //Include enemies that are technically dead, but can be finished off
  7100. for( i = 0; i < finishableEnemiesList.Size() ; i+=1 )
  7101. {
  7102. if ( !targets.Contains( finishableEnemiesList[i] ) )
  7103. {
  7104. targets.PushBack( finishableEnemiesList[i] );
  7105. }
  7106. }
  7107.  
  7108. onlyThreatTargetsFound = false;
  7109. FilterActors( targets, onlyThreatTargetsFound, true );
  7110.  
  7111. if ( IsCombatMusicEnabled() && targets.Size() > 0 && !onlyThreatTargetsFound && !IsThreat( targets[0], usePrecalcs ) )
  7112. {
  7113. targets.Clear();
  7114. }
  7115.  
  7116. coneHeading = 0.0f;
  7117. coneHalfAngleDot = 0.0f;
  7118. if ( ( orientationTarget == OT_Camera ) || ( orientationTarget == OT_CameraOffset ) )
  7119. {
  7120. if ( usePrecalcs )
  7121. {
  7122. coneHeading = targetingPrecalcs.cameraHeading;
  7123. }
  7124. else
  7125. {
  7126. coneHeading = theGame.GetGameCamera().GetHeading();
  7127. }
  7128. coneHalfAngleDot = 0.5f; // = CosF( Deg2Rad( 120.f * 0.5f ) ); - Just use calculator... why not? this is constant.
  7129. }
  7130. else
  7131. {
  7132. if ( IsSwimming() )
  7133. {
  7134. if ( usePrecalcs )
  7135. {
  7136. coneHeading = targetingPrecalcs.cameraHeading;
  7137. }
  7138. else
  7139. {
  7140. coneHeading = theGame.GetGameCamera().GetHeading();
  7141. }
  7142. coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) );
  7143. }
  7144. else if ( bLAxisReleased )
  7145. {
  7146. if( IsInCombatAction() )
  7147. {
  7148. coneHeading = GetCombatActionHeading();
  7149. }
  7150. else
  7151. {
  7152. if ( ShouldUsePCModeTargeting() )
  7153. coneHeading = theGame.GetGameCamera().GetHeading();
  7154. else
  7155. coneHeading = cachedRawPlayerHeading;
  7156. }
  7157.  
  7158. if ( IsInCombat() )
  7159. {
  7160. if ( ShouldUsePCModeTargeting() )
  7161. coneHalfAngleDot = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) )
  7162. else
  7163. coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) );
  7164. }
  7165. else
  7166. {
  7167. coneHalfAngleDot = -1.0f;
  7168. }
  7169. }
  7170. else
  7171. {
  7172. if( IsInCombatAction() )
  7173. {
  7174. coneHeading = GetCombatActionHeading();
  7175. }
  7176. else
  7177. {
  7178. if ( ShouldUsePCModeTargeting() )
  7179. coneHeading = theGame.GetGameCamera().GetHeading();
  7180. else
  7181. coneHeading = cachedRawPlayerHeading;
  7182. }
  7183.  
  7184. if ( ShouldUsePCModeTargeting() )
  7185. coneHalfAngleDot = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) )
  7186. else
  7187. coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) );
  7188. }
  7189.  
  7190. coneHeadingVector = VecFromHeading( coneHeading );
  7191. position = this.GetWorldPosition();
  7192.  
  7193. for ( i = targets.Size() - 1; i >= 0; i -= 1 )
  7194. {
  7195. if ( !targets[i] )
  7196. {
  7197. targets.EraseFast(i);
  7198. continue;
  7199. }
  7200.  
  7201. direction = VecNormalize2D( targets[i].GetWorldPosition() - position );
  7202.  
  7203. if ( VecDot2D( coneHeadingVector, direction ) < coneHalfAngleDot )
  7204. {
  7205. targets.EraseFast( i );
  7206. }
  7207. }
  7208. }
  7209.  
  7210. outHeadingVector = coneHeadingVector;
  7211. }
  7212.  
  7213. ///////////////////////////////////////////////////////////////////////////
  7214. // (new) targeting
  7215.  
  7216. function InitTargeting()
  7217. {
  7218. var consts : SR4PlayerTargetingConsts;
  7219.  
  7220. if ( !targeting )
  7221. {
  7222. targeting = new CR4PlayerTargeting in this;
  7223. }
  7224. if ( targeting )
  7225. {
  7226. consts.softLockDistance = this.softLockDist;
  7227. consts.softLockFrameSize = this.softLockFrameSize;
  7228. targeting.SetConsts( consts );
  7229. }
  7230. }
  7231.  
  7232. function PrepareTargetingIn( actionCheck : bool, bufferActionType : EBufferActionType, actionInput : bool )
  7233. {
  7234. var coneDist : float;
  7235.  
  7236. if ( actionCheck && bufferActionType == EBAT_ItemUse )
  7237. {
  7238. coneDist = findMoveTargetDist;
  7239. }
  7240. else if ( IsSwimming() )
  7241. {
  7242. coneDist = theGame.params.MAX_THROW_RANGE;
  7243. }
  7244. else if ( ( GetPlayerCombatStance() == PCS_AlertNear ) && ( ( playerMoveType == PMT_Walk ) || ( playerMoveType == PMT_Idle ) ) )
  7245. {
  7246. coneDist = softLockDist;
  7247. }
  7248. else
  7249. {
  7250. coneDist = findMoveTargetDist;
  7251. }
  7252.  
  7253. targetingIn.canFindTarget = this.bCanFindTarget;
  7254. targetingIn.playerHasBlockingBuffs = thePlayer.HasBuff( EET_Confusion ) || thePlayer.HasBuff( EET_Hypnotized ) || thePlayer.HasBuff( EET_Blindness ) || thePlayer.HasBuff( EET_WraithBlindness );
  7255. targetingIn.isHardLockedToTarget = this.IsHardLockEnabled();
  7256. targetingIn.isActorLockedToTarget = this.IsActorLockedToTarget();
  7257. targetingIn.isCameraLockedToTarget = this.IsCameraLockedToTarget();
  7258. targetingIn.actionCheck = actionCheck;
  7259. targetingIn.actionInput = actionInput;
  7260. targetingIn.isInCombatAction = this.IsInCombatAction();
  7261. targetingIn.isLAxisReleased = this.bLAxisReleased;
  7262. targetingIn.isLAxisReleasedAfterCounter = this.lAxisReleasedAfterCounter;
  7263. targetingIn.isLAxisReleasedAfterCounterNoCA = this.lAxisReleasedAfterCounterNoCA;
  7264. targetingIn.lastAxisInputIsMovement = this.lastAxisInputIsMovement;
  7265. targetingIn.isAiming = this.playerAiming.GetCurrentStateName() == 'Aiming';
  7266. targetingIn.isSwimming = this.IsSwimming();
  7267. targetingIn.isDiving = this.IsSwimming() && OnCheckDiving();
  7268. targetingIn.isThreatened = this.IsThreatened();
  7269. targetingIn.isCombatMusicEnabled = this.IsCombatMusicEnabled();
  7270. targetingIn.isPcModeEnabled = this.IsPCModeEnabled();
  7271. targetingIn.isInParryOrCounter = this.isInParryOrCounter;
  7272. targetingIn.shouldUsePcModeTargeting = this.ShouldUsePCModeTargeting();
  7273. targetingIn.bufferActionType = bufferActionType;
  7274. targetingIn.orientationTarget = this.GetOrientationTarget();
  7275. targetingIn.coneDist = coneDist; // computed few lines above
  7276. targetingIn.findMoveTargetDist = this.findMoveTargetDist;
  7277. targetingIn.cachedRawPlayerHeading = this.cachedRawPlayerHeading;
  7278. targetingIn.combatActionHeading = this.GetCombatActionHeading();
  7279. targetingIn.rawPlayerHeadingVector = VecFromHeading( this.rawPlayerHeading );
  7280. targetingIn.lookAtDirection = VecNormalize2D( this.GetLookAtPosition() - GetWorldPosition() );
  7281. targetingIn.moveTarget = this.moveTarget;
  7282. targetingIn.aimingTarget = this.playerAiming.GetAimedTarget();
  7283. targetingIn.displayTarget = (CActor)this.displayTarget;
  7284. targetingIn.finishableEnemies = this.finishableEnemiesList;
  7285. targetingIn.hostileEnemies = this.hostileEnemies;
  7286. targetingIn.defaultSelectionWeights = ProcessSelectionWeights();
  7287. }
  7288.  
  7289. function ResetTargetingOut()
  7290. {
  7291. targetingOut.target = NULL;
  7292. targetingOut.result = false;
  7293. targetingOut.confirmNewTarget = false;
  7294. targetingOut.forceDisableUpdatePosition = false;
  7295. }
  7296.  
  7297. function MakeFindTargetPrecalcs()
  7298. {
  7299. var mpac : CMovingPhysicalAgentComponent;
  7300.  
  7301. targetingPrecalcs.playerPosition = thePlayer.GetWorldPosition();
  7302. targetingPrecalcs.playerHeading = thePlayer.GetHeading();
  7303. targetingPrecalcs.playerHeadingVector = thePlayer.GetHeadingVector();
  7304. targetingPrecalcs.playerHeadingVector.Z = 0;
  7305. targetingPrecalcs.playerHeadingVector = VecNormalize2D( targetingPrecalcs.playerHeadingVector );
  7306.  
  7307. targetingPrecalcs.playerRadius = 0.5f;
  7308. mpac = (CMovingPhysicalAgentComponent)thePlayer.GetMovingAgentComponent();
  7309. if ( mpac )
  7310. {
  7311. targetingPrecalcs.playerRadius = mpac.GetCapsuleRadius();
  7312. }
  7313.  
  7314. targetingPrecalcs.cameraPosition = theCamera.GetCameraPosition();
  7315. targetingPrecalcs.cameraDirection = theCamera.GetCameraDirection();
  7316. targetingPrecalcs.cameraHeadingVector = targetingPrecalcs.cameraDirection;
  7317. targetingPrecalcs.cameraHeadingVector.Z = 0;
  7318. targetingPrecalcs.cameraHeadingVector = VecNormalize2D( targetingPrecalcs.cameraHeadingVector );
  7319. targetingPrecalcs.cameraHeading = VecHeading( targetingPrecalcs.cameraHeadingVector );
  7320. }
  7321.  
  7322. public function GetForceDisableUpdatePosition() : bool
  7323. {
  7324. return targetingOut.forceDisableUpdatePosition;
  7325. }
  7326.  
  7327. public function SetUseNativeTargeting( use : bool )
  7328. {
  7329. useNativeTargeting = use;
  7330. }
  7331.  
  7332. protected function FindTarget( optional actionCheck : bool, optional action : EBufferActionType, optional actionInput : bool ) : CActor
  7333. {
  7334. if ( IsCombatMusicEnabled() && !IsInCombat() && reachableEnemyWasTooFar )
  7335. {
  7336. playerMode.UpdateCombatMode();
  7337. }
  7338.  
  7339. PrepareTargetingIn( actionCheck, action, actionInput );
  7340. if ( useNativeTargeting )
  7341. {
  7342. targeting.BeginFindTarget( targetingIn );
  7343. targeting.FindTarget();
  7344. targeting.EndFindTarget( targetingOut );
  7345. }
  7346. else
  7347. {
  7348. UpdateVisibleActors();
  7349. MakeFindTargetPrecalcs();
  7350. ResetTargetingOut();
  7351. FindTarget_Scripted();
  7352. }
  7353. if ( targetingOut.result )
  7354. {
  7355. if ( targetingOut.confirmNewTarget )
  7356. {
  7357. ConfirmNewTarget( targetingOut.target );
  7358. }
  7359. return targetingOut.target;
  7360. }
  7361. return NULL;
  7362. }
  7363.  
  7364. protected function FindTarget_Scripted()
  7365. {
  7366. var currentTarget : CActor;
  7367. var newTarget : CActor;
  7368. var selectedTarget : CActor;
  7369. var displayTargetActor : CActor;
  7370. var playerPosition : Vector;
  7371. var playerHeadingVector : Vector;
  7372. var cameraPosition : Vector;
  7373. var cameraHeadingVector : Vector;
  7374. var selectionHeadingVector : Vector;
  7375. var targetingInfo : STargetingInfo;
  7376. var selectionWeights : STargetSelectionWeights;
  7377. var targets : array< CActor >;
  7378. var isMoveTargetTargetable : bool;
  7379. var targetChangeFromActionInput : bool;
  7380. var retainCurrentTarget : bool;
  7381.  
  7382. // caching data
  7383.  
  7384. playerPosition = this.GetWorldPosition();
  7385. playerHeadingVector = targetingPrecalcs.playerHeadingVector;
  7386. cameraPosition = theCamera.GetCameraPosition();
  7387. cameraHeadingVector = targetingPrecalcs.cameraHeadingVector;
  7388.  
  7389. currentTarget = GetTarget();
  7390. if ( currentTarget )
  7391. {
  7392. if ( IsHardLockEnabled() && currentTarget.IsAlive() && !currentTarget.IsKnockedUnconscious() )
  7393. {
  7394. if ( VecDistanceSquared( playerPosition, currentTarget.GetWorldPosition() ) > 50.f * 50.0f )
  7395. {
  7396. HardLockToTarget( false );
  7397. }
  7398. else
  7399. {
  7400. targetingOut.target = currentTarget;
  7401. targetingOut.result = true;
  7402. return;
  7403. }
  7404. }
  7405. GetVisualDebug().AddSphere('target', 1.0f, currentTarget.GetWorldPosition(), true, Color( 255, 255, 0 ), 1.0f );
  7406. }
  7407.  
  7408. if ( bCanFindTarget && !IsActorLockedToTarget() )
  7409. {
  7410. if ( !targetingIn.playerHasBlockingBuffs )
  7411. {
  7412. InternalFindTargetsInCone( targets, selectionHeadingVector, true );
  7413. }
  7414.  
  7415. targetingInfo.source = this;
  7416. targetingInfo.canBeTargetedCheck = true;
  7417. targetingInfo.coneCheck = false;
  7418. targetingInfo.coneHalfAngleCos = 1.0f;
  7419. targetingInfo.coneDist = targetingIn.coneDist;
  7420. targetingInfo.distCheck = true;
  7421. targetingInfo.invisibleCheck = true;
  7422. targetingInfo.navMeshCheck = false; //true;
  7423.  
  7424. if ( ShouldUsePCModeTargeting() )
  7425. targetingInfo.inFrameCheck = false;
  7426. else
  7427. targetingInfo.inFrameCheck = true;
  7428.  
  7429. targetingInfo.frameScaleX = 1.0f;
  7430. targetingInfo.frameScaleY = 1.0f;
  7431. targetingInfo.knockDownCheck = false;
  7432. targetingInfo.knockDownCheckDist = 1.5f;
  7433. targetingInfo.rsHeadingCheck = false;
  7434. targetingInfo.rsHeadingLimitCos = 1.0f;
  7435.  
  7436. if ( currentTarget )
  7437. {
  7438. targetingInfo.targetEntity = currentTarget;
  7439. if ( !IsEntityTargetable( targetingInfo, true ) )
  7440. {
  7441. currentTarget = NULL;
  7442. }
  7443. if ( currentTarget && !CanBeTargetedIfSwimming( currentTarget, true ) )
  7444. {
  7445. currentTarget = NULL;
  7446. }
  7447. }
  7448.  
  7449. isMoveTargetTargetable = false;
  7450. if ( moveTarget )
  7451. {
  7452. if ( CanBeTargetedIfSwimming( moveTarget, true ) )
  7453. {
  7454. targetingInfo.targetEntity = moveTarget;
  7455. targetingInfo.coneDist = findMoveTargetDist;
  7456. targetingInfo.inFrameCheck = false;
  7457. if ( IsEntityTargetable( targetingInfo, true ) )
  7458. {
  7459. isMoveTargetTargetable = true;
  7460. }
  7461. }
  7462. }
  7463.  
  7464. // checking "standard" cone dist again
  7465. targetingInfo.coneDist = targetingIn.coneDist;
  7466.  
  7467. if ( !targetingIn.playerHasBlockingBuffs )
  7468. {
  7469. RemoveNonTargetable( targets, targetingInfo, selectionHeadingVector );
  7470. }
  7471.  
  7472. newTarget = NULL;
  7473. if ( this.playerAiming.GetCurrentStateName() == 'Aiming' )
  7474. {
  7475. newTarget = this.playerAiming.GetAimedTarget();
  7476. if ( !newTarget )
  7477. {
  7478. selectionWeights.angleWeight = 1.f;
  7479. selectionWeights.distanceWeight = 0.f;
  7480. selectionWeights.distanceRingWeight = 0.f;
  7481.  
  7482. selectedTarget = SelectTarget( targets, false, cameraPosition, cameraHeadingVector, selectionWeights, true );
  7483. newTarget = selectedTarget;
  7484. }
  7485. }
  7486. else if ( IsSwimming() )
  7487. {
  7488. selectionWeights.angleWeight = 0.9f;
  7489. selectionWeights.distanceWeight = 0.1f;
  7490. selectionWeights.distanceRingWeight = 0.f;
  7491.  
  7492. selectedTarget = SelectTarget( targets, true, cameraPosition, cameraHeadingVector, selectionWeights, true );
  7493. newTarget = selectedTarget;
  7494. }
  7495. else if ( IsThreatened() )
  7496. {
  7497. // Change locked enemy when the current one becomes invisible
  7498. if ( IsCameraLockedToTarget() )
  7499. {
  7500. if ( currentTarget && !currentTarget.GetGameplayVisibility() )
  7501. {
  7502. ForceSelectLockTarget();
  7503. }
  7504. }
  7505.  
  7506. displayTargetActor = (CActor)displayTarget;
  7507. selectedTarget = SelectTarget( targets, true, playerPosition, selectionHeadingVector, targetingIn.defaultSelectionWeights, true );
  7508.  
  7509. if ( !selectedTarget )
  7510. {
  7511. targetingOut.forceDisableUpdatePosition = true;
  7512. }
  7513.  
  7514. targetChangeFromActionInput = targetingIn.actionInput && !lAxisReleasedAfterCounter;
  7515. if ( selectedTarget &&
  7516. ( !IsThreat( currentTarget, true ) || ShouldUsePCModeTargeting() || ( !IsInCombatAction() && !lAxisReleasedAfterCounterNoCA ) || targetChangeFromActionInput ) )
  7517. {
  7518. newTarget = selectedTarget;
  7519. }
  7520. else if ( displayTargetActor &&
  7521. ( ( bLAxisReleased && !ShouldUsePCModeTargeting() )|| IsInCombatAction() ) &&
  7522. ( displayTargetActor.IsAlive() || finishableEnemiesList.Contains( displayTargetActor ) ) &&
  7523. displayTargetActor.GetGameplayVisibility() &&
  7524. ( IsEnemyVisible( displayTargetActor ) || finishableEnemiesList.Contains( displayTargetActor ) ) &&
  7525. this.CanBeTargetedIfSwimming( displayTargetActor, true ) &&
  7526. IsThreat( displayTargetActor, true ) &&
  7527. WasVisibleInScaledFrame( displayTargetActor, 1.f, 1.f ) )
  7528. {
  7529. newTarget = displayTargetActor;
  7530. }
  7531. // target closest enemy immediately when transitioning from running/sprint to walk/idle,
  7532. // 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
  7533. else if ( moveTarget &&
  7534. isMoveTargetTargetable &&
  7535. ( !IsInCombatAction() || isInParryOrCounter || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Roll ) )
  7536. {
  7537. newTarget = moveTarget;
  7538. }
  7539. else
  7540. {
  7541. newTarget = NULL;
  7542. }
  7543. }
  7544. else
  7545. {
  7546. retainCurrentTarget = false;
  7547. if ( lAxisReleasedAfterCounterNoCA )
  7548. {
  7549. if ( lastAxisInputIsMovement && !this.IsSwimming())
  7550. {
  7551. selectionWeights.angleWeight = 0.375f;
  7552. selectionWeights.distanceWeight = 0.275f;
  7553. selectionWeights.distanceRingWeight = 0.35f;
  7554. selectedTarget = SelectTarget( targets, false, playerPosition, playerHeadingVector, selectionWeights, true );
  7555.  
  7556. if ( currentTarget != selectedTarget )
  7557. {
  7558. targetingInfo.targetEntity = currentTarget;
  7559. if ( IsEntityTargetable( targetingInfo, true ) && currentTarget.IsAlive() )
  7560. {
  7561. retainCurrentTarget = true;
  7562. }
  7563. }
  7564. }
  7565. else
  7566. {
  7567. selectionWeights.angleWeight = 0.75f;
  7568. selectionWeights.distanceWeight = 0.125f;
  7569. selectionWeights.distanceRingWeight = 0.125f;
  7570. selectedTarget = SelectTarget( targets, false, cameraPosition, cameraHeadingVector, selectionWeights, true );
  7571. }
  7572. }
  7573. else
  7574. {
  7575. selectionWeights.angleWeight = 0.6f;
  7576. selectionWeights.distanceWeight = 0.4f;
  7577. selectionWeights.distanceRingWeight = 0.f;
  7578. selectedTarget = SelectTarget( targets, true, playerPosition, targetingIn.rawPlayerHeadingVector, selectionWeights, true );
  7579. }
  7580.  
  7581. if ( retainCurrentTarget )
  7582. {
  7583. newTarget = currentTarget;
  7584. }
  7585. else if ( IsInCombatAction() && GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.0f )
  7586. {
  7587. newTarget = moveTarget;
  7588. }
  7589. else if ( selectedTarget )
  7590. {
  7591. newTarget = selectedTarget;
  7592. }
  7593. else
  7594. {
  7595. newTarget = NULL;
  7596. }
  7597. }
  7598.  
  7599. targetingOut.confirmNewTarget = true;
  7600. }
  7601. else
  7602. {
  7603. newTarget = NULL;
  7604. }
  7605.  
  7606. targetingOut.result = true;
  7607. targetingOut.target = newTarget;
  7608. }
  7609.  
  7610. function UpdateVisibleActors()
  7611. {
  7612. var i : int;
  7613. var now : float;
  7614.  
  7615. now = theGame.GetEngineTimeAsSeconds();
  7616. for ( i = visibleActors.Size() - 1; i >= 0; i-=1 )
  7617. {
  7618. // wasn't visible for more than 1 second
  7619. if ( ( now - visibleActorsTime[i] ) > 1.0f )
  7620. {
  7621. visibleActors.EraseFast( i );
  7622. visibleActorsTime.EraseFast( i );
  7623. }
  7624. }
  7625. }
  7626.  
  7627. function RemoveNonTargetable( out targets : array< CActor >, out info : STargetingInfo, selectionHeadingVector : Vector )
  7628. {
  7629. var i : int;
  7630. var cameraPosition : Vector;
  7631. var cameraDirection : Vector;
  7632. var nonCombatCheck : bool;
  7633. var playerToCamPlaneDist : float;
  7634. var targetToCamPlaneDist : float;
  7635.  
  7636. if ( targets.Size() == 0 )
  7637. {
  7638. return;
  7639. }
  7640.  
  7641. nonCombatCheck = bLAxisReleased && !IsInCombat();
  7642.  
  7643. // first, let's prepare targeting info (so that we don't need to do it in each loop step)
  7644. if ( nonCombatCheck )
  7645. {
  7646. info.coneHeadingVector = targetingPrecalcs.playerHeadingVector;
  7647. if ( lastAxisInputIsMovement )
  7648. {
  7649. info.coneHeadingVector = selectionHeadingVector;
  7650. info.invisibleCheck = false;
  7651. info.coneCheck = true;
  7652. info.coneHalfAngleCos = 0.76604444311f; // = CosF( Deg2Rad( 80.0f * 0.5f ) )
  7653. }
  7654. else
  7655. {
  7656. info.invisibleCheck = false;
  7657. info.frameScaleX = 0.9f;
  7658. info.frameScaleY = 0.9f;
  7659. }
  7660. }
  7661. else
  7662. {
  7663. info.coneHeadingVector = Vector( 0.0f, 0.0f, 0.0f );
  7664.  
  7665. //MS: ConeCheck is false because it's already been filtered by InternalFindTargetsInCone
  7666. if ( IsInCombat() )
  7667. {
  7668. info.inFrameCheck = false;
  7669. }
  7670. else
  7671. {
  7672. if ( !bLAxisReleased )
  7673. {
  7674. info.coneCheck = true;
  7675.  
  7676. if ( this.IsSwimming() )
  7677. info.coneHalfAngleCos = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) )
  7678. else
  7679. info.coneHalfAngleCos = 0.86602540378f; // = CosF( Deg2Rad( 60.0f * 0.5f ) )
  7680.  
  7681. info.coneHeadingVector = targetingIn.rawPlayerHeadingVector;
  7682. }
  7683. }
  7684. }
  7685.  
  7686. cameraPosition = theCamera.GetCameraPosition();
  7687. cameraDirection = targetingPrecalcs.cameraDirection;
  7688. playerToCamPlaneDist = VecDot2D( cameraDirection, this.GetWorldPosition() - cameraPosition );
  7689.  
  7690. // then, using prepared info let's filter out invalid targets
  7691. for( i = targets.Size() - 1; i >= 0; i -= 1 )
  7692. {
  7693. info.targetEntity = targets[i];
  7694.  
  7695. if ( !CanBeTargetedIfSwimming( targets[i], true ) )
  7696. {
  7697. targets.EraseFast( i );
  7698. }
  7699. else if ( !IsEntityTargetable( info, true ) )
  7700. {
  7701. targets.EraseFast( i );
  7702. }
  7703. else
  7704. {
  7705. if ( nonCombatCheck && !lastAxisInputIsMovement )
  7706. {
  7707. // removing targets between camera and player
  7708. targetToCamPlaneDist = VecDot2D( cameraDirection, targets[i].GetWorldPosition() - cameraPosition );
  7709. if ( targetToCamPlaneDist < playerToCamPlaneDist )
  7710. {
  7711. targets.EraseFast( i );
  7712. }
  7713. }
  7714. }
  7715. }
  7716. }
  7717.  
  7718. var combatModeColor : Color;
  7719. public function CombatModeDebug()
  7720. {
  7721. var visualDebug : CVisualDebug = GetVisualDebug();
  7722.  
  7723. var naviQueryMsg : string;
  7724. var naviQueryMsg1 : string;
  7725. var naviQueryMsg2 : string;
  7726.  
  7727. var navSnapMsg : string;
  7728. var i : int;
  7729.  
  7730. if ( IsCombatMusicEnabled() )
  7731. visualDebug.AddText( 'CombatMusic', "CombatMusic : On", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.7f ), true, , Color( 255, 255, 255 ) );
  7732. else
  7733. visualDebug.AddText( 'CombatMusic', "CombatMusic : Off", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.7f ), true, , Color( 0, 0, 0 ) );
  7734.  
  7735. if ( GetPlayerMode().GetForceCombatMode() )
  7736. visualDebug.AddText( 'ForcedCombatMode', "ForcedCombatMode : TRUE", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.6f ), true, , Color( 255, 255, 255 ) );
  7737. else
  7738. visualDebug.AddText( 'ForcedCombatMode', "ForcedCombatMode : FALSE", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.6f ), true, , Color( 0, 0, 0 ) );
  7739.  
  7740.  
  7741. if ( IsThreatened() )
  7742. {
  7743. if ( IsInCombat() )
  7744. visualDebug.AddText( 'CombatMode', "CombatMode : AlertNear/Far", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 255, 0, 0 ) );
  7745. else
  7746. visualDebug.AddText( 'CombatMode', "CombatMode : CombatExploration", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 255, 255, 0 ) );
  7747. }
  7748. else
  7749. visualDebug.AddText( 'CombatMode', "CombatMode : NormalExploration", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 0, 255, 0 ) );
  7750.  
  7751. visualDebug.AddText( 'NaviQuery', naviQueryMsg, combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7752. visualDebug.AddText( 'NaviQuery1', naviQueryMsg1, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7753. visualDebug.AddText( 'NaviQuery2', naviQueryMsg2, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7754.  
  7755. if ( isInCombatReason == 0 )
  7756. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : ", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 125, 125, 125 ) );
  7757. else if ( isInCombatReason == 1 )
  7758. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : Geralt CAN pathfind to NPC", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) );
  7759. else if ( isInCombatReason == 2 )
  7760. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : An NPC is flying or ranged", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) );
  7761. else if ( isInCombatReason == 2 )
  7762. visualDebug.AddText( 'CombatModeReason', "CombatModeReason : Forced Combat Mode", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) );
  7763.  
  7764. if ( reachableEnemyWasTooFar )
  7765. {
  7766. combatModeColor.Red = 255;
  7767. combatModeColor.Green = 255;
  7768. combatModeColor.Blue = 0;
  7769. }
  7770. else
  7771. {
  7772. combatModeColor.Red = 0;
  7773. combatModeColor.Green = 255;
  7774. combatModeColor.Blue = 0;
  7775. }
  7776.  
  7777. if ( IsThreatened() )
  7778. {
  7779. switch ( navQuery.GetLastOutput( 2.0 ) )
  7780. {
  7781. case EAsyncTastResult_Failure:
  7782. {
  7783. if ( this.playerMode.GetForceCombatMode() )
  7784. {
  7785. if ( isSnappedToNavMesh )
  7786. {
  7787. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7788. visualDebug.AddText( 'NaviQuery1', "Naviquery : Snapped So no need for query", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7789. visualDebug.AddText( 'NaviQuery2', "Naviquery : Snapped So no need for query", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7790. }
  7791. else
  7792. {
  7793. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7794. visualDebug.AddText( 'NaviQuery1', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7795. visualDebug.AddText( 'NaviQuery2', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7796. }
  7797. }
  7798. else
  7799. {
  7800. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7801. visualDebug.AddText( 'NaviQuery1', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7802. visualDebug.AddText( 'NaviQuery2', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7803. }
  7804. break;
  7805. }
  7806. case EAsyncTastResult_Success:
  7807. {
  7808. visualDebug.AddText( 'NaviQuery', combatModeEnt.GetName(), combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7809. visualDebug.AddText( 'NaviQuery1', "Naviquery : Success (navDist: " + navDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7810. visualDebug.AddText( 'NaviQuery2', "Naviquery : Success (directDist: " + directDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7811. break;
  7812. }
  7813. case EAsyncTastResult_Pending:
  7814. {
  7815. visualDebug.AddText( 'NaviQuery', combatModeEnt.GetName(), combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7816. visualDebug.AddText( 'NaviQuery1', "Naviquery : Pending (navDist: " + navDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7817. visualDebug.AddText( 'NaviQuery2', "Naviquery : Pending (directDist: " + directDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7818. break;
  7819. }
  7820. case EAsyncTastResult_Invalidated:
  7821. {
  7822. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7823. visualDebug.AddText( 'NaviQuery1', "Naviquery : Invalidated", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7824. visualDebug.AddText( 'NaviQuery2', "Naviquery : Invalidated", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7825. break;
  7826. }
  7827. }
  7828. }
  7829. else
  7830. {
  7831. visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7832. visualDebug.AddText( 'NaviQuery1', "", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor );
  7833. visualDebug.AddText( 'NaviQuery2', "", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor );
  7834. }
  7835.  
  7836. if ( navMeshSnapInfoStack.Size() > 0 )
  7837. {
  7838. for ( i = navMeshSnapInfoStack.Size()-1; i >= 0; i -= 1 )
  7839. {
  7840. navSnapMsg = navSnapMsg + navMeshSnapInfoStack[i] + " ";
  7841. }
  7842.  
  7843. visualDebug.AddText( 'NavMeshSnap', "NavMeshSnap: Enabled, Sources : " + navSnapMsg, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.1f ), true, , Color( 255, 255, 255 ) );
  7844. }
  7845. else
  7846. visualDebug.AddText( 'NavMeshSnap', "NavMeshSnap: Disabled" , thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.1f ), true, , Color( 0, 0, 0 ) );
  7847.  
  7848. }
  7849.  
  7850. function IsCombatMusicEnabled() : bool
  7851. {
  7852. if ( theSound.GetCurrentGameState() == ESGS_UnderwaterCombat
  7853. || theSound.GetCurrentGameState() == ESGS_Combat
  7854. || theSound.GetCurrentGameState() == ESGS_CombatMonsterHunt
  7855. || theSound.GetCurrentGameState() == ESGS_FocusUnderwaterCombat )
  7856. return true;
  7857. else
  7858. return false;
  7859. }
  7860.  
  7861. function IsSoundStateCombatMusic( gameState : ESoundGameState ) : bool
  7862. {
  7863. if ( gameState == ESGS_UnderwaterCombat
  7864. || gameState == ESGS_Combat
  7865. || gameState == ESGS_CombatMonsterHunt
  7866. || gameState == ESGS_FocusUnderwaterCombat )
  7867. return true;
  7868. else
  7869. return false;
  7870. }
  7871.  
  7872. private function ConfirmNewTarget( actorToConfirm : CActor )
  7873. {
  7874. var leftJoyRotLimit : float = 1.f;
  7875.  
  7876. var target : CActor;
  7877.  
  7878. target = GetTarget();
  7879.  
  7880. //MS: When Player pushes stick in npcs direction, he needs to push the stick beyond leftJoyRotLimit in order to change targets
  7881. if ( !target
  7882. || !moveTarget
  7883. || ( target && ( !IsThreat( target ) || !target.IsAlive() ) )
  7884. || VecLength( rawLeftJoyVec ) < 0.7f
  7885. || ( 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 ) ) ) )
  7886. || ( !IsInCombatAction() && ( !rangedWeapon || ( rangedWeapon.GetCurrentStateName() != 'State_WeaponHolster' ) ) ))//&& rangedWeapon.GetCurrentStateName() != 'State_WeaponShoot' ) && rangedWeapon.GetCurrentStateName() != 'State_WeaponAim' ) )
  7887. {
  7888. SetPrevRawLeftJoyRot();
  7889.  
  7890. if ( actorToConfirm != target )
  7891. {
  7892. SetTarget( actorToConfirm );
  7893. }
  7894. }
  7895. }
  7896.  
  7897. protected function SelectTarget( targets : array< CActor >, useVisibilityCheck : bool, sourcePosition : Vector, headingVector : Vector, selectionWeights : STargetSelectionWeights, optional usePrecalcs : bool ) : CActor
  7898. {
  7899. var i : int;
  7900. var target : CActor;
  7901. var selectedTarget : CActor;
  7902. var currentTarget : CActor;
  7903. var playerPosition : Vector;
  7904. var distanceToPlayer : float;
  7905. var priority : float;
  7906. var maxPriority : float;
  7907. var now : float;
  7908. var remove : bool;
  7909. var visibleActorIndex : int;
  7910.  
  7911. if ( useVisibilityCheck )
  7912. {
  7913. currentTarget = this.GetTarget();
  7914. playerPosition = this.GetWorldPosition();
  7915. now = theGame.GetEngineTimeAsSeconds();
  7916.  
  7917. for ( i = targets.Size() - 1; i >= 0; i-=1 )
  7918. {
  7919. target = targets[ i ];
  7920. if ( target != currentTarget && ( !IsPCModeEnabled() && !WasVisibleInScaledFrame( target, softLockFrameSize, softLockFrameSize ) ) )
  7921. {
  7922. remove = true;
  7923. visibleActorIndex = visibleActors.FindFirst( target );
  7924. if ( visibleActorIndex != -1 )
  7925. {
  7926. if ( usePrecalcs )
  7927. {
  7928. distanceToPlayer = Distance2DBetweenCapsuleAndPoint( target, this ) - targetingPrecalcs.playerRadius;
  7929. }
  7930. else
  7931. {
  7932. distanceToPlayer = Distance2DBetweenCapsules( this, target );
  7933. }
  7934. // if within soft lock distance and soft lock visibility duration -> don't remove yet
  7935. if ( distanceToPlayer < this.softLockDist && ( now - visibleActorsTime[ i ] ) < 1.0f )
  7936. {
  7937. remove = false;
  7938. }
  7939. }
  7940. if ( remove )
  7941. {
  7942. targets.EraseFast( i );
  7943. }
  7944. }
  7945. else
  7946. {
  7947. visibleActorIndex = visibleActors.FindFirst( target );
  7948. if ( visibleActorIndex == -1 )
  7949. {
  7950. visibleActors.PushBack( target );
  7951. visibleActorsTime.PushBack( now );
  7952. }
  7953. else
  7954. {
  7955. visibleActorsTime[ visibleActorIndex ] = now;
  7956. }
  7957. }
  7958. }
  7959. }
  7960.  
  7961. selectedTarget = NULL;
  7962. maxPriority = -1.0f;
  7963. for( i = targets.Size() - 1; i >= 0; i-=1 )
  7964. {
  7965. priority = CalcSelectionPriority( targets[ i ], selectionWeights, sourcePosition, headingVector );
  7966. if ( priority > maxPriority )
  7967. {
  7968. maxPriority = priority;
  7969. selectedTarget = targets[ i ];
  7970. }
  7971. }
  7972.  
  7973. //LogChannel( 'selectedTarget', selectedTarget );
  7974. return selectedTarget;
  7975. }
  7976.  
  7977. function Distance2DBetweenCapsuleAndPoint( actor : CActor, entity : CEntity ) : float
  7978. {
  7979. var distance : float;
  7980. var mpac : CMovingPhysicalAgentComponent;
  7981.  
  7982. distance = VecDistance2D( actor.GetWorldPosition(), entity.GetWorldPosition() );
  7983.  
  7984. mpac = (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent();
  7985. if ( mpac )
  7986. {
  7987. distance -= mpac.GetCapsuleRadius();
  7988. }
  7989.  
  7990. return distance;
  7991. }
  7992.  
  7993.  
  7994. function Distance2DBetweenCapsules( actor1 : CActor, actor2 : CActor ) : float
  7995. {
  7996. var distance : float;
  7997. var mpac : CMovingPhysicalAgentComponent;
  7998.  
  7999. distance = VecDistance2D( actor1.GetWorldPosition(), actor2.GetWorldPosition() );
  8000.  
  8001. mpac = (CMovingPhysicalAgentComponent)actor1.GetMovingAgentComponent();
  8002. if ( mpac )
  8003. {
  8004. distance -= mpac.GetCapsuleRadius();
  8005. }
  8006.  
  8007. mpac = (CMovingPhysicalAgentComponent)actor2.GetMovingAgentComponent();
  8008. if ( mpac )
  8009. {
  8010. distance -= mpac.GetCapsuleRadius();
  8011. }
  8012.  
  8013. return distance;
  8014. }
  8015.  
  8016. protected function ProcessSelectionWeights() : STargetSelectionWeights
  8017. {
  8018. var selectionWeights : STargetSelectionWeights;
  8019.  
  8020. if ( ShouldUsePCModeTargeting() )
  8021. {
  8022. selectionWeights.angleWeight = 0.75f;
  8023. selectionWeights.distanceWeight = 0.25f;
  8024. selectionWeights.distanceRingWeight = 0.f;
  8025. return selectionWeights;
  8026. }
  8027.  
  8028. if ( IsInCombatAction() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Roll ) )
  8029. {
  8030. selectionWeights.angleWeight = 0.575f;
  8031. selectionWeights.distanceWeight = 0.175f;
  8032. selectionWeights.distanceRingWeight = 0.25f;
  8033. }
  8034. if ( !lAxisReleasedAfterCounter || IsInCombatAction() ) // !bLAxisReleased ||
  8035. {
  8036. if ( theInput.GetActionValue( 'ThrowItem' ) == 1.f || ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) )
  8037. {
  8038. selectionWeights.angleWeight = 1.f;
  8039. selectionWeights.distanceWeight = 0.f;
  8040. selectionWeights.distanceRingWeight = 0.f;
  8041. }
  8042. else if ( !lAxisReleasedAfterCounter ) // !bLAxisReleased )
  8043. {
  8044. selectionWeights.angleWeight = 0.55f;//0.75f;
  8045. selectionWeights.distanceWeight = 0.45f;//0.25f;
  8046. selectionWeights.distanceRingWeight = 0.f;//0.3f;
  8047. }
  8048. else
  8049. {
  8050. selectionWeights.angleWeight = 0.75f;
  8051. selectionWeights.distanceWeight = 0.25f;
  8052. selectionWeights.distanceRingWeight = 0.f;//0.3f;
  8053. }
  8054. }
  8055. else if( !IsCurrentSignChanneled() )
  8056. {
  8057. selectionWeights.angleWeight = 0.35f;
  8058. selectionWeights.distanceWeight = 0.65f;
  8059. selectionWeights.distanceRingWeight = 0.f;
  8060. }
  8061. else
  8062. {
  8063. selectionWeights.angleWeight = 0.275f;
  8064. selectionWeights.distanceWeight = 0.375f;
  8065. selectionWeights.distanceRingWeight = 0.35f;
  8066. }
  8067.  
  8068. return selectionWeights;
  8069. }
  8070.  
  8071. protected function CalcSelectionPriority( target : CEntity, selectionWeights : STargetSelectionWeights, sourcePosition : Vector, headingVector : Vector ) : float
  8072. {
  8073. var sourceToTarget : Vector;
  8074. var sourceToTargetDist : float;
  8075. var sourceToTargetAngleDiff : float;
  8076. var selectionPriority : float;
  8077.  
  8078. sourceToTarget = target.GetWorldPosition() - sourcePosition;
  8079. sourceToTargetDist = VecLength2D( sourceToTarget );
  8080. // normalize2D sourcetoTarget
  8081. if ( sourceToTargetDist < 0.0001f )
  8082. {
  8083. sourceToTarget = Vector( 0.0f, 0.0f, 0.0f );
  8084. }
  8085. else
  8086. {
  8087. sourceToTarget *= ( 1.0f / sourceToTargetDist );
  8088. }
  8089. sourceToTargetAngleDiff = AbsF( Rad2Deg( AcosF( VecDot2D( sourceToTarget, headingVector ) ) ) );
  8090.  
  8091. selectionPriority = ( selectionWeights.angleWeight * ( ( 180 - sourceToTargetAngleDiff ) / 180 ) );
  8092. selectionPriority += selectionWeights.distanceWeight * ( ( softLockDist - sourceToTargetDist ) / softLockDist );
  8093.  
  8094. if ( sourceToTargetDist > 0.f && sourceToTargetDist <= 6.f )
  8095. {
  8096. selectionPriority += selectionWeights.distanceRingWeight * 1.0f;
  8097. }
  8098. else if ( sourceToTargetDist > 6.f && sourceToTargetDist <= softLockDist )
  8099. {
  8100. selectionPriority += selectionWeights.distanceRingWeight * 0.4f;
  8101. }
  8102.  
  8103. return selectionPriority;
  8104. }
  8105.  
  8106. protected function SetTarget( targetActor : CActor, optional forceSetTarget : bool )
  8107. {
  8108. var playerToTargetDistance : float;
  8109. var target : CActor;
  8110. var allow : bool;
  8111.  
  8112. target = GetTarget();
  8113.  
  8114. if ( !IsInNonGameplayCutscene() )
  8115. allow = true;
  8116.  
  8117. if ( allow )
  8118. {
  8119. if ( targetActor )
  8120. {
  8121. if ( ( targetActor.IsAlive() && !targetActor.IsKnockedUnconscious() ) || finishableEnemiesList.Contains( targetActor ) )
  8122. allow = true;
  8123. else
  8124. allow = false;
  8125. }
  8126. else
  8127. allow = true;
  8128. }
  8129.  
  8130. if ( forceSetTarget )
  8131. allow = true;
  8132.  
  8133. if ( allow && target != targetActor )
  8134. allow = true;
  8135. else
  8136. allow = false;
  8137.  
  8138. if ( allow )
  8139. {
  8140. SetPlayerTarget( targetActor );
  8141.  
  8142. //playerToTargetDistance = VecDistance( GetWorldPosition(), targetActor.GetNearestPointInBothPersonalSpaces( GetWorldPosition() ) );
  8143. //LogChannel( 'Targeting', "selection " + playerToTargetDistance );
  8144. }
  8145. }
  8146.  
  8147. /*
  8148. protected function SetTarget( targetActor : CActor, optional forceSetTarget : bool )
  8149. {
  8150. var playerToTargetDistance : float;
  8151. var target : CActor;
  8152. //var gec : CGameplayEffectsComponent;
  8153.  
  8154.  
  8155. if ( !IsInNonGameplayCutscene()
  8156. && ( ( ( !targetActor || ( ( targetActor.IsAlive() || finishableEnemiesList.Contains( targetActor ) ) && !targetActor.IsKnockedUnconscious() ) ) && !IsActorLockedToTarget() ) || forceSetTarget ) )
  8157. {
  8158. target = GetTarget();
  8159.  
  8160. if ( target != targetActor )
  8161. {
  8162. if( target )
  8163. {
  8164. target.StopEffect( 'select_character' );
  8165. //gec = GetGameplayEffectsComponent( target );
  8166. //if(gec)
  8167. // gec.SetGameplayEffectFlag( EGEF_OutlineTarget, 0 );
  8168. }
  8169.  
  8170. SetPlayerTarget( targetActor );
  8171. target = targetActor;
  8172.  
  8173. if(target)
  8174. {
  8175. playerToTargetDistance = VecDistance( GetWorldPosition(), target.GetNearestPointInBothPersonalSpaces( GetWorldPosition() ) );
  8176. }
  8177.  
  8178. //LogChannel( 'Targeting', "selection " + playerToTargetDistance );
  8179. }
  8180. }
  8181. }
  8182. */
  8183. public function SetSlideTarget( actor : CGameplayEntity )
  8184. {
  8185. //if ( slideTarget != actor && slideTarget )
  8186. // EnableCloseCombatCharacterRadius( false );
  8187.  
  8188. slideTarget = actor;
  8189.  
  8190. if ( slideTarget )
  8191. SetPlayerCombatTarget((CActor)slideTarget);
  8192. else
  8193. Log( "slideTarget = NULL" );
  8194.  
  8195. if ( slideTarget == nonActorTarget )
  8196. UpdateDisplayTarget( true, true );
  8197. else
  8198. UpdateDisplayTarget();
  8199.  
  8200. ConfirmDisplayTargetTimer(0.f);
  8201. }
  8202.  
  8203. event OnForceSelectLockTarget()
  8204. {
  8205. ForceSelectLockTarget();
  8206. }
  8207.  
  8208. private function ForceSelectLockTarget()
  8209. {
  8210. var newMoveTarget : CActor;
  8211. var target : CActor;
  8212.  
  8213. newMoveTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, 90 );
  8214.  
  8215. if ( !newMoveTarget )
  8216. newMoveTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, -90 );
  8217.  
  8218. if ( newMoveTarget )
  8219. {
  8220. thePlayer.ProcessLockTarget( newMoveTarget );
  8221.  
  8222. target = GetTarget();
  8223. if ( target )
  8224. {
  8225. thePlayer.SetSlideTarget( target );
  8226.  
  8227. if ( IsHardLockEnabled() )
  8228. thePlayer.HardLockToTarget( true );
  8229. }
  8230. }
  8231. else
  8232. {
  8233. thePlayer.HardLockToTarget( false );
  8234. }
  8235. }
  8236.  
  8237. public function SetFinisherVictim( actor : CActor )
  8238. {
  8239. finisherVictim = actor;
  8240. }
  8241.  
  8242. public function GetFinisherVictim() : CActor
  8243. {
  8244. return finisherVictim;
  8245. }
  8246.  
  8247. protected function SetNonActorTarget( actor : CGameplayEntity )
  8248. {
  8249. if ( nonActorTarget != actor )
  8250. nonActorTarget = actor;
  8251. }
  8252.  
  8253. timer function DisableTargetHighlightTimer( time : float , id : int)
  8254. {
  8255. var target : CActor;
  8256. target = GetTarget();
  8257.  
  8258. if( target )
  8259. {
  8260. target.StopEffect( 'select_character' );
  8261. }
  8262. }
  8263.  
  8264. public function WasVisibleInScaledFrame( entity : CEntity, frameSizeX : float, frameSizeY : float ) : bool
  8265. {
  8266. var position : Vector;
  8267. var positionFound : bool;
  8268. var inFront : bool;
  8269. var x, y : float;
  8270. var boneIndex : int;
  8271. var actor : CActor;
  8272. var gameplayEntity : CGameplayEntity;
  8273. var gameplayEntityMatrix : Matrix;
  8274. var drawableComp : CDrawableComponent;
  8275. var box : Box;
  8276. var ok : bool;
  8277.  
  8278. if ( !entity )
  8279. {
  8280. return false;
  8281. }
  8282. if ( frameSizeX <= 0.0f && frameSizeY <= 0.0f )
  8283. {
  8284. LogChannel( 'WasVisibleInScaledFrame', "ERROR: WasVisibleInScaledFrame: frameSizeX && frameSizeY are both negative!!!" );
  8285. return false;
  8286. }
  8287.  
  8288. if ( useNativeTargeting )
  8289. {
  8290. return targeting.WasVisibleInScaledFrame( entity, frameSizeX, frameSizeY );
  8291. }
  8292.  
  8293. position = entity.GetWorldPosition();
  8294.  
  8295. actor = (CActor)entity;
  8296. if ( actor )
  8297. {
  8298. boneIndex = entity.GetBoneIndex( 'pelvis' );
  8299. if ( boneIndex == -1 )
  8300. {
  8301. boneIndex = entity.GetBoneIndex( 'k_pelvis_g' ); // not hack at all. DONE !*100000000000000000000
  8302. }
  8303.  
  8304. if ( boneIndex != -1 )
  8305. {
  8306. position = MatrixGetTranslation( entity.GetBoneWorldMatrixByIndex( boneIndex ) );
  8307. }
  8308. else
  8309. {
  8310. position = entity.GetWorldPosition();
  8311. position.Z += ( (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent() ).GetCapsuleHeight() * 0.5;
  8312. }
  8313. positionFound = true;
  8314. }
  8315. else
  8316. {
  8317. gameplayEntity = (CGameplayEntity)entity;
  8318. if ( gameplayEntity && !( gameplayEntity.aimVector.X == 0 && gameplayEntity.aimVector.Y == 0 && gameplayEntity.aimVector.Z == 0 ) )
  8319. {
  8320. gameplayEntityMatrix = gameplayEntity.GetLocalToWorld();
  8321. position = VecTransform( gameplayEntityMatrix, gameplayEntity.aimVector );
  8322. positionFound = true;
  8323. }
  8324. }
  8325.  
  8326. // if still not found proper position for test
  8327. if ( !positionFound )
  8328. {
  8329. drawableComp = (CDrawableComponent)entity.GetComponentByClassName( 'CDrawableComponent' );
  8330. if ( drawableComp && drawableComp.GetObjectBoundingVolume( box ) )
  8331. {
  8332. position.Z += ( ( box.Max.Z - box.Min.Z ) * 0.66f );
  8333. }
  8334. }
  8335.  
  8336. inFront = theCamera.WorldVectorToViewRatio( position, x, y );
  8337. if ( !inFront )
  8338. {
  8339. return false;
  8340. }
  8341. x = AbsF( x );
  8342. y = AbsF( y );
  8343.  
  8344. ok = true;
  8345. ok = ok && ( frameSizeX <= 0.0f || x < frameSizeX );
  8346. ok = ok && ( frameSizeY <= 0.0f || y < frameSizeY );
  8347.  
  8348. return ok;
  8349. }
  8350.  
  8351. public function HardLockToTarget( flag : bool )
  8352. {
  8353. if( flag && GetTarget().HasTag( 'NoHardLock' ) )
  8354. return;
  8355.  
  8356. EnableHardLock( flag );
  8357. LockToTarget( flag );
  8358. }
  8359.  
  8360. public function LockToTarget( flag : bool )
  8361. {
  8362. if ( IsHardLockEnabled() && !flag )
  8363. return;
  8364.  
  8365. LockCameraToTarget( flag );
  8366. LockActorToTarget( flag );
  8367. }
  8368.  
  8369. public function LockCameraToTarget( flag : bool )
  8370. {
  8371. if ( flag && !IsCameraLockedToTarget() )
  8372. {
  8373. thePlayer.EnableManualCameraControl( false, 'LockCameraToTarget' );
  8374. //((CCustomCamera)theCamera.GetTopmostCameraObject()).EnableManualControl( false );
  8375. SetIsCameraLockedToTarget( flag );
  8376. }
  8377. else if ( !flag && IsCameraLockedToTarget() )
  8378. {
  8379. thePlayer.EnableManualCameraControl( true, 'LockCameraToTarget' );
  8380. //((CCustomCamera)theCamera.GetTopmostCameraObject()).EnableManualControl( true );
  8381. SetIsCameraLockedToTarget( flag );
  8382. }
  8383. }
  8384.  
  8385. public function LockActorToTarget( flag : bool, optional withoutIcon : bool )
  8386. {
  8387. var displayTargetActor : CActor;
  8388.  
  8389. if ( flag )
  8390. {
  8391. if ( !IsActorLockedToTarget() )
  8392. {
  8393. //SetSlideTarget( target );
  8394. SetIsActorLockedToTarget( flag );
  8395. SetMoveTargetChangeAllowed( true );
  8396. SetMoveTarget( GetTarget() );
  8397. SetMoveTargetChangeAllowed( false );
  8398. SetTarget( GetTarget() );
  8399. SetSlideTarget( GetTarget() );
  8400. AddTimer( 'CheckLockTargetIsAlive', 0.5, true );
  8401. }
  8402.  
  8403. if ( IsActorLockedToTarget() )
  8404. {
  8405. displayTargetActor = (CActor)( GetDisplayTarget() );
  8406.  
  8407. if ( displayTargetActor && IsThreat( displayTargetActor ) && !withoutIcon )
  8408. EnableHardLockIcon( flag );
  8409. }
  8410. }
  8411. else if ( !flag && IsActorLockedToTarget() )
  8412. {
  8413. SetIsActorLockedToTarget( flag );
  8414. SetMoveTargetChangeAllowed( true );
  8415. RemoveTimer( 'CheckLockTargetIsAlive' );
  8416. EnableHardLockIcon( flag );
  8417. }
  8418. }
  8419.  
  8420. private function EnableHardLockIcon( flag : bool )
  8421. {
  8422. var hud : CR4ScriptedHud;
  8423. var module : CR4HudModuleEnemyFocus;
  8424.  
  8425. if( GetTarget().HasTag( 'NoHardLockIcon' ) )
  8426. return;
  8427.  
  8428. hud = (CR4ScriptedHud)theGame.GetHud();
  8429. module = (CR4HudModuleEnemyFocus)hud.GetHudModule("EnemyFocusModule");
  8430. module.SetShowHardLock( flag );
  8431. }
  8432.  
  8433. private timer function CheckLockTargetIsAlive( time : float , id : int)
  8434. {
  8435. var vitality : float;
  8436. var essence : float;
  8437. var actor : CActor;
  8438. var target : CActor;
  8439.  
  8440. target = (CActor)GetDisplayTarget();
  8441.  
  8442. if( !target
  8443. || !target.IsAlive()
  8444. || ( !target.GetGameplayVisibility() )
  8445. || !CanBeTargetedIfSwimming( target )
  8446. || (!target.UsesVitality() && !target.UsesEssence()))
  8447. {
  8448. if ( !ProcessLockTarget() )
  8449. HardLockToTarget( false );
  8450. }
  8451. }
  8452.  
  8453. //////////////////////////////////////////////////////////////////////////////////////////
  8454. //
  8455. // @Damage
  8456. //
  8457. //////////////////////////////////////////////////////////////////////////////////////////
  8458. protected function PlayHitAnimation(damageAction : W3DamageAction, animType : EHitReactionType)
  8459. {
  8460. var hitRotation : float;
  8461. var onHitCounter : SAbilityAttributeValue;
  8462. var counter : int;
  8463.  
  8464. if( damageAction.HasAnyCriticalEffect() )
  8465. return;
  8466.  
  8467. if( !substateManager.ReactOnBeingHit() && !IsUsingVehicle() )
  8468. {
  8469. return;
  8470. }
  8471.  
  8472. if ( damageAction.GetHitReactionType() == EHRT_Reflect )
  8473. SetBehaviorVariable( 'isAttackReflected', 1.f );
  8474. else
  8475. SetBehaviorVariable( 'isAttackReflected', 0.f );
  8476.  
  8477. SetBehaviorVariable( 'HitReactionType',(int)animType);
  8478. SetBehaviorVariable( 'HitReactionWeapon', ProcessSwordOrFistHitReaction( this, (CActor)damageAction.attacker ) );
  8479.  
  8480. if (damageAction.attacker)
  8481. {
  8482. super.PlayHitAnimation( damageAction, animType );
  8483. if ( damageAction.attacker.HasAbility( 'IncreaseHitReactionSeverityWithHitCounter' ) )
  8484. {
  8485. counter = GetHitCounter();
  8486. switch ( counter )
  8487. {
  8488. case 2 :
  8489. SetBehaviorVariable( 'HitReactionType', 2 );
  8490. break;
  8491.  
  8492. case 3 :
  8493. AddEffectDefault( EET_Stagger, damageAction.attacker, damageAction.attacker.GetName() );
  8494. break;
  8495.  
  8496. case 4 :
  8497. AddEffectDefault( EET_Knockdown, damageAction.attacker, damageAction.attacker.GetName() );
  8498. break;
  8499.  
  8500. default :
  8501. break;
  8502. }
  8503. }
  8504. SetHitReactionDirection(damageAction.attacker);
  8505. SetDetailedHitReaction(damageAction.GetSwingType(), damageAction.GetSwingDirection());
  8506. }
  8507.  
  8508. RaiseForceEvent( 'Hit' );
  8509. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'ActorInHitReaction', -1, 30.0f, -1.f, -1, true ); //reactionSystemSearch
  8510.  
  8511. if ( IsUsingBoat() )
  8512. {
  8513. SoundEvent("cmb_play_hit_light");
  8514. return;
  8515. }
  8516.  
  8517. if ( IsUsingVehicle() )
  8518. return;
  8519.  
  8520. if(damageAction.attacker)
  8521. {
  8522. hitRotation = VecHeading( damageAction.attacker.GetWorldPosition() - GetWorldPosition() );
  8523. if ( this.GetBehaviorVariable( 'HitReactionDirection' ) == (float)( (int)EHRD_Back ) )
  8524. hitRotation += 180.f;
  8525.  
  8526. //GetVisualDebug().AddArrow( 'temp', GetWorldPosition(), GetWorldPosition() + VecFromHeading( hitRotation )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f );
  8527. SetCustomRotation( 'Hit', hitRotation, 1080.f, 0.1f, false );
  8528. }
  8529.  
  8530. CriticalEffectAnimationInterrupted("PlayHitAnimation");
  8531. }
  8532.  
  8533. public function ReduceDamage( out damageData : W3DamageAction)
  8534. {
  8535. super.ReduceDamage(damageData);
  8536.  
  8537. //halve damage if from your own bomb
  8538. if(damageData.attacker == this && (damageData.GetBuffSourceName() == "petard" || (W3Petard)damageData.causer) )
  8539. {
  8540. if ( theGame.CanLog() )
  8541. {
  8542. LogDMHits("CR4Player.ReduceDamage: hitting self with own bomb - damage reduced by 50%", damageData );
  8543. }
  8544. damageData.processedDmg.vitalityDamage = damageData.processedDmg.vitalityDamage / 2;
  8545. damageData.processedDmg.essenceDamage = damageData.processedDmg.essenceDamage / 2;
  8546. }
  8547. }
  8548.  
  8549. //crit hit chance 0-1
  8550. public function GetCriticalHitChance( isLightAttack : bool, isHeavyAttack : bool, target : CActor, victimMonsterCategory : EMonsterCategory, isBolt : bool ) : float
  8551. {
  8552. var critChance : float;
  8553. var oilChanceAttribute : name;
  8554. var weapons : array< SItemUniqueId >;
  8555. var i : int;
  8556. var holdsCrossbow : bool;
  8557. var critVal : SAbilityAttributeValue;
  8558.  
  8559. critChance = 0;
  8560.  
  8561. //cheats
  8562. if( FactsQuerySum( 'debug_fact_critical_boy' ) > 0 )
  8563. {
  8564. critChance += 1;
  8565. }
  8566.  
  8567. if( IsInState( 'HorseRiding' ) && ( ( CActor )GetUsedVehicle() ).GetMovingAgentComponent().GetRelativeMoveSpeed() >= 4.0 )
  8568. {
  8569. critChance += 1;
  8570. }
  8571.  
  8572. //normal case
  8573. critChance += CalculateAttributeValue( GetAttributeValue( theGame.params.CRITICAL_HIT_CHANCE ) );
  8574.  
  8575. //fix cases when we calculate change for crossbow but have sword bonus and vice-versa
  8576. weapons = inv.GetHeldWeapons();
  8577. for( i=0; i<weapons.Size(); i+=1 )
  8578. {
  8579. holdsCrossbow = ( inv.IsItemCrossbow( weapons[i] ) || inv.IsItemBolt( weapons[i] ) );
  8580. if( holdsCrossbow != isBolt )
  8581. {
  8582. critVal = inv.GetItemAttributeValue( weapons[i], theGame.params.CRITICAL_HIT_CHANCE );
  8583. critChance -= CalculateAttributeValue( critVal );
  8584. }
  8585. }
  8586.  
  8587. //active skills bonus
  8588. if( isHeavyAttack && CanUseSkill( S_Sword_s08 ) )
  8589. {
  8590. critChance += CalculateAttributeValue( GetSkillAttributeValue( S_Sword_s08, theGame.params.CRITICAL_HIT_CHANCE, false, true ) ) * GetSkillLevel( S_Sword_s08 );
  8591. }
  8592. else if( isLightAttack && CanUseSkill( S_Sword_s17 ) )
  8593. {
  8594. critChance += CalculateAttributeValue( GetSkillAttributeValue( S_Sword_s17, theGame.params.CRITICAL_HIT_CHANCE, false, true ) ) * GetSkillLevel( S_Sword_s17 );
  8595. }
  8596.  
  8597. if( target && target.HasBuff( EET_Confusion ) )
  8598. {
  8599. critChance += ( ( W3ConfuseEffect )target.GetBuff( EET_Confusion ) ).GetCriticalHitChanceBonus();
  8600. }
  8601.  
  8602. //oils
  8603. oilChanceAttribute = MonsterCategoryToCriticalChanceBonus( victimMonsterCategory );
  8604. if( IsNameValid( oilChanceAttribute ) )
  8605. {
  8606. critChance += CalculateAttributeValue( GetAttributeValue( oilChanceAttribute ) );
  8607. }
  8608.  
  8609. return critChance;
  8610. }
  8611.  
  8612. //gets damage bonus for critical hit
  8613. public function GetCriticalHitDamageBonus(weaponId : SItemUniqueId, victimMonsterCategory : EMonsterCategory, isStrikeAtBack : bool) : SAbilityAttributeValue
  8614. {
  8615. var bonus, oilBonus : SAbilityAttributeValue;
  8616. var vsAttributeName : name;
  8617.  
  8618. bonus = super.GetCriticalHitDamageBonus(weaponId, victimMonsterCategory, isStrikeAtBack);
  8619.  
  8620. //oil bonus
  8621. if( inv.ItemHasActiveOilApplied( weaponId, victimMonsterCategory ) )
  8622. {
  8623. vsAttributeName = MonsterCategoryToCriticalDamageBonus(victimMonsterCategory);
  8624. oilBonus = inv.GetItemAttributeValue(weaponId, vsAttributeName);
  8625. bonus += oilBonus;
  8626. }
  8627.  
  8628. return bonus;
  8629. }
  8630.  
  8631. /**
  8632. Called when we want to play hit animation
  8633. */
  8634. public function ReactToBeingHit(damageAction : W3DamageAction, optional buffNotApplied : bool) : bool
  8635. {
  8636. var strength : float;
  8637. var animType : EHitReactionType;
  8638. var sup : bool;
  8639. var boat : CBoatComponent;
  8640. var combatActionType : int;
  8641. var attackAction : W3Action_Attack;
  8642. var npc : CNewNPC;
  8643. var shakeCam : bool;
  8644.  
  8645. attackAction = (W3Action_Attack)damageAction;
  8646. //not parried, not countered, not dot, not dodged
  8647. if(!damageAction.IsDoTDamage() && (!attackAction || (!attackAction.IsParried() && !attackAction.IsCountered() && !attackAction.WasDodged()) ) )
  8648. {
  8649. npc = (CNewNPC)attackAction.attacker;
  8650. if(npc && npc.IsHeavyAttack(attackAction.GetAttackName()))
  8651. theGame.VibrateControllerVeryHard();//player got heavy hit
  8652. else
  8653. theGame.VibrateControllerHard();//player got hit
  8654. }
  8655.  
  8656. if ( (CActor)GetUsedVehicle() && this.playerAiming.GetCurrentStateName() == 'Aiming' )
  8657. {
  8658. OnRangedForceHolster( true, true );
  8659. }
  8660.  
  8661. combatActionType = (int)GetBehaviorVariable( 'combatActionType' );
  8662.  
  8663. if ( thePlayer.IsCurrentlyDodging() && ( combatActionType == (int)CAT_Roll || combatActionType == (int)CAT_CiriDodge ) )
  8664. sup = false;
  8665. else if ( this.GetCurrentStateName() == 'DismountHorse' )
  8666. sup = false;
  8667. else
  8668. sup = super.ReactToBeingHit(damageAction, buffNotApplied);
  8669. sup = false;
  8670. //telemetry
  8671. if(damageAction.attacker)
  8672. theTelemetry.LogWithLabelAndValue( TE_FIGHT_HERO_GETS_HIT, damageAction.attacker.ToString(), (int)damageAction.processedDmg.vitalityDamage );
  8673.  
  8674. //camera shake
  8675. if(damageAction.DealsAnyDamage())
  8676. {
  8677. if( ((W3PlayerWitcher)this) && GetWitcherPlayer().IsAnyQuenActive() && damageAction.IsDoTDamage())
  8678. {
  8679. shakeCam = false;
  8680. }
  8681. else
  8682. {
  8683. shakeCam = true;
  8684. }
  8685.  
  8686. if(shakeCam)
  8687. {
  8688. animType = ModifyHitSeverityReaction(this, damageAction.GetHitReactionType());
  8689.  
  8690. if(animType == EHRT_Light || animType == EHRT_LightClose)
  8691. strength = 0.1;
  8692. else if(animType == EHRT_Heavy || animType == EHRT_Igni)
  8693. strength = 0.2;
  8694.  
  8695. GCameraShakeLight(strength, false, GetWorldPosition(), 10.0);
  8696. }
  8697.  
  8698. this.HitReactionEffect( 0.25 );
  8699.  
  8700. //reset uninterrupted hits
  8701. ResetUninterruptedHitsCount();
  8702. }
  8703.  
  8704. //pause health regen
  8705. if(!damageAction.IsDoTDamage() && IsThreatened() && ShouldPauseHealthRegenOnHit() && damageAction.DealsAnyDamage() && !damageAction.WasDodged() && attackAction.CanBeParried() && !attackAction.IsParried())
  8706. {
  8707. PauseHPRegenEffects('being_hit', theGame.params.ON_HIT_HP_REGEN_DELAY);
  8708. }
  8709.  
  8710. //if player is on a boat and not moving then force dismount
  8711. /*if(usedVehicle)
  8712. {
  8713. boat = (CBoatComponent) usedVehicle.GetComponentByClassName('CBoatComponent');
  8714. if(boat && boat.GetLinearVelocityXY() < boat.IDLE_SPEED_THRESHOLD)
  8715. {
  8716. boat.StopAndDismountBoat();
  8717. }
  8718. }*/
  8719.  
  8720. //finesse achievement fail
  8721. if(damageAction.processedDmg.vitalityDamage > 0 && !((W3Effect_Toxicity)damageAction.causer))
  8722. ReceivedCombatDamage();
  8723.  
  8724. //tutorial
  8725. if(FactsQuerySum("tut_fight_use_slomo") > 0)
  8726. {
  8727. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) );
  8728. FactsRemove("tut_fight_slomo_ON");
  8729. }
  8730.  
  8731. // State
  8732. if( !substateManager.ReactOnBeingHit( damageAction ) )
  8733. {
  8734. GoToCombatIfNeeded();
  8735. //PushState( 'CombatFists' );
  8736. }
  8737.  
  8738. return sup;
  8739. }
  8740.  
  8741. protected function ShouldPauseHealthRegenOnHit() : bool
  8742. {
  8743. return true;
  8744. }
  8745.  
  8746. public function PlayHitEffect(damageAction : W3DamageAction)
  8747. {
  8748. super.PlayHitEffect(damageAction);
  8749.  
  8750. //fullscreen hit fx
  8751. if(damageAction.DealsAnyDamage() && !damageAction.IsDoTDamage())
  8752. PlayEffect('hit_screen');
  8753. }
  8754.  
  8755. function HitReactionEffect( interval : float )
  8756. {
  8757. if ( hitReactionEffect )
  8758. {
  8759. PlayEffect( 'radial_blur' );
  8760. hitReactionEffect = false;
  8761. }
  8762. else
  8763. {
  8764. AddTimer( 'HitReactionEffectCooldown', interval, false );
  8765. }
  8766. }
  8767.  
  8768. timer function HitReactionEffectCooldown( td : float , id : int)
  8769. {
  8770. hitReactionEffect = true;
  8771. }
  8772. //////////////////////////////////////////////////////////////////////////////////////////
  8773. //
  8774. // @Parry
  8775. //
  8776. //////////////////////////////////////////////////////////////////////////////////////////
  8777.  
  8778. function PerformParryCheck( parryInfo : SParryInfo) : bool
  8779. {
  8780. var mult : float;
  8781. var parryType : EParryType;
  8782. var parryDir : EPlayerParryDirection;
  8783. var parryHeading : float;
  8784. var fistFightParry : bool;
  8785. var action : W3DamageAction;
  8786. var xmlStaminaDamage : float;
  8787. var xmlStaminaDamageName : name = 'stamina_damage' ;
  8788. var counter : int;
  8789. var onHitCounter : SAbilityAttributeValue;
  8790.  
  8791. // if ( !parryInfo.canBeParried )
  8792. // return false;
  8793.  
  8794. if(CanParryAttack() && /*parryInfo.targetToAttackerAngleAbs < theGame.params.PARRY_HALF_ANGLE &&*/ FistFightCheck( parryInfo.target, parryInfo.attacker, fistFightParry ) )
  8795. {
  8796. parryHeading = GetParryHeading( parryInfo, parryDir ) ;
  8797. //GetVisualDebug().AddArrow( 'CombatActionHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( GetParryHeading( parryInfo, parryDir ) )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f );
  8798. SetBehaviorVariable( 'parryDirection', (float)( (int)( parryDir ) ) );
  8799. SetBehaviorVariable( 'parryDirectionOverlay', (float)( (int)( parryDir ) ) );
  8800. SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) );
  8801.  
  8802. if ( IsInCombatActionFriendly() )
  8803. RaiseEvent('CombatActionFriendlyEnd');
  8804.  
  8805. if ( HasStaminaToParry(parryInfo.attackActionName) )
  8806. {
  8807. this.SetBehaviorVariable( 'combatActionType', (int)CAT_Parry );
  8808.  
  8809. if ( parryInfo.targetToAttackerDist > 3.f && !bLAxisReleased && !thePlayer.IsCiri() )
  8810. {
  8811. if ( !RaiseForceEvent( 'PerformParryOverlay' ) )
  8812. return false;
  8813. else
  8814. {
  8815. ClearCustomOrientationInfoStack();
  8816. IncDefendCounter();
  8817. }
  8818. }
  8819. else
  8820. {
  8821. counter = GetDefendCounter();
  8822. onHitCounter = parryInfo.attacker.GetAttributeValue( 'break_through_parry_on_hit_counter' );
  8823. if ( onHitCounter.valueBase > 0 && counter == onHitCounter.valueBase )
  8824. {
  8825. AddEffectDefault( EET_Stagger, parryInfo.attacker, "Break through parry" );
  8826. }
  8827. else if ( RaiseForceEvent( 'PerformParry' ) )
  8828. {
  8829. OnCombatActionStart();
  8830. ClearCustomOrientationInfoStack();
  8831. SetSlideTarget( parryInfo.attacker );
  8832. SetCustomRotation( 'Parry', parryHeading, 1080.f, 0.1f, false );
  8833. IncDefendCounter();
  8834. }
  8835. else
  8836. return false;
  8837. }
  8838. }
  8839. else
  8840. {
  8841. AddEffectDefault(EET_Stagger, parryInfo.attacker, "Parry");
  8842. return true;
  8843. }
  8844. //parryTarget := this
  8845. if ( parryInfo.attacker.IsWeaponHeld( 'fist' ) && !parryInfo.target.IsWeaponHeld( 'fist' ) )
  8846. {
  8847. parryInfo.attacker.ReactToReflectedAttack(parryInfo.target);
  8848. }
  8849. else
  8850. {
  8851. if ( this.IsInFistFightMiniGame() && fistFightParry )
  8852. {
  8853. if ( IsNameValid(xmlStaminaDamageName) )
  8854. {
  8855. xmlStaminaDamage = CalculateAttributeValue(parryInfo.attacker.GetAttributeValue( xmlStaminaDamageName ));
  8856. DrainStamina(ESAT_FixedValue, xmlStaminaDamage);
  8857. }
  8858. }
  8859. else
  8860. {
  8861. DrainStamina(ESAT_Parry, 0, 0, '', 0, mult);
  8862. }
  8863. if(IsLightAttack(parryInfo.attackActionName))
  8864. parryInfo.target.PlayEffectOnHeldWeapon('light_block');
  8865. else
  8866. parryInfo.target.PlayEffectOnHeldWeapon('heavy_block');
  8867. }
  8868. return true;
  8869. }
  8870.  
  8871. return false;
  8872. }
  8873.  
  8874. protected function GetParryHeading( parryInfo : SParryInfo, out parryDir : EPlayerParryDirection ) : float
  8875. {
  8876. var targetToAttackerHeading : float;
  8877. var currToTargetAttackerAngleDiff : float;
  8878.  
  8879. targetToAttackerHeading = VecHeading( parryInfo.attacker.GetWorldPosition() - parryInfo.target.GetWorldPosition() );
  8880. currToTargetAttackerAngleDiff = AngleDistance( VecHeading( parryInfo.target.GetHeadingVector() ), targetToAttackerHeading );
  8881.  
  8882. if ( !parryInfo.target.IsWeaponHeld( 'fist' ) )
  8883. {
  8884. if( currToTargetAttackerAngleDiff > -45 && currToTargetAttackerAngleDiff < 45 )
  8885. {
  8886. parryDir = PPD_Forward;
  8887. return targetToAttackerHeading;
  8888. }
  8889. else if( currToTargetAttackerAngleDiff >= 45 && currToTargetAttackerAngleDiff < 135 )
  8890. {
  8891. parryDir = PPD_Right;
  8892. //return targetToAttackerHeading;
  8893. return targetToAttackerHeading + 90;
  8894. }
  8895. else if( currToTargetAttackerAngleDiff <= -45 && currToTargetAttackerAngleDiff > -135 )
  8896. {
  8897. parryDir = PPD_Left;
  8898. //return targetToAttackerHeading;
  8899. return targetToAttackerHeading - 90;
  8900. }
  8901. else
  8902. {
  8903. parryDir = PPD_Back;
  8904. //return targetToAttackerHeading;
  8905. return targetToAttackerHeading + 180;
  8906. }
  8907. }
  8908. else
  8909. {
  8910. if( currToTargetAttackerAngleDiff > -45 && currToTargetAttackerAngleDiff < 45 )
  8911. {
  8912. parryDir = PPD_Forward;
  8913. return targetToAttackerHeading;
  8914. }
  8915. else if( currToTargetAttackerAngleDiff >= 45 && currToTargetAttackerAngleDiff < 180 )
  8916. {
  8917. parryDir = PPD_Right;
  8918. return targetToAttackerHeading + 90;
  8919. }
  8920. else if( currToTargetAttackerAngleDiff <= -45 && currToTargetAttackerAngleDiff >= -180 )
  8921. {
  8922. parryDir = PPD_Left;
  8923. return targetToAttackerHeading - 90;
  8924. }
  8925. else
  8926. {
  8927. parryDir = PPD_Back;
  8928. return targetToAttackerHeading + 180;
  8929. }
  8930. }
  8931. }
  8932.  
  8933. function ProcessLockTarget( optional newLockTarget : CActor, optional checkLeftStickHeading : bool ) : bool
  8934. {
  8935. var attackerNearestPoint : Vector;
  8936. var playerNearestPoint : Vector;
  8937. var incomingAttacker : CActor;
  8938. var tempLockTarget : CActor;
  8939. var target : CActor;
  8940. var useIncomingAttacker : bool;
  8941.  
  8942. if( newLockTarget.HasTag( 'NoHardLock' ) )
  8943. return false;
  8944.  
  8945. if ( newLockTarget )
  8946. tempLockTarget = newLockTarget;
  8947. else
  8948. {
  8949. incomingAttacker = GetClosestIncomingAttacker();
  8950. if ( incomingAttacker && incomingAttacker.IsAlive() && IsUsingVehicle() )
  8951. {
  8952. tempLockTarget = incomingAttacker;
  8953. useIncomingAttacker = false;
  8954. }
  8955.  
  8956. if ( !useIncomingAttacker )
  8957. {
  8958. target = GetTarget();
  8959. if( target.HasTag('ForceHardLock'))
  8960. {
  8961. return true;
  8962. }
  8963. else if ( target && target.IsAlive() && target.GetGameplayVisibility() && IsEnemyVisible( target ) && IsThreat( target ) && CanBeTargetedIfSwimming( target ) )
  8964. tempLockTarget = FindTarget();
  8965. else
  8966. {
  8967. tempLockTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, 0.f );
  8968. }
  8969. }
  8970. }
  8971.  
  8972. if( tempLockTarget.HasTag( 'NoHardLock' ) )
  8973. return false;
  8974.  
  8975. if ( tempLockTarget )
  8976. {
  8977. if ( IsCombatMusicEnabled() || hostileEnemies.Size() > 0 )
  8978. {
  8979. if ( !IsThreat( tempLockTarget ) )
  8980. tempLockTarget = NULL;
  8981. }
  8982. }
  8983.  
  8984. SetTarget( tempLockTarget, true );
  8985. SetMoveTargetChangeAllowed( true );
  8986. SetMoveTarget( tempLockTarget );
  8987. SetMoveTargetChangeAllowed( false );
  8988. SetSlideTarget( tempLockTarget );
  8989.  
  8990. if ( tempLockTarget )
  8991. {
  8992. if ( this.IsActorLockedToTarget() )
  8993. EnableHardLockIcon( true );
  8994.  
  8995. return true;
  8996. }
  8997. else
  8998. return false;
  8999. }
  9000.  
  9001. //////////////////////////////////////////////////////////////////////////////////////////
  9002. //////////////////////// @COMBAT ///////////////////////////////////////////////////////
  9003. //////////////////////////////////////////////////////////////////////////////////////////
  9004.  
  9005. event OnTaskSyncAnim( npc : CNewNPC, animNameLeft : name ) {}
  9006.  
  9007. //checks if player is doing special attack light/heavy
  9008. public function IsDoingSpecialAttack(heavy : bool) : bool
  9009. {
  9010. var pat : EPlayerAttackType;
  9011.  
  9012. if(IsInCombatAction() && ( (int)GetBehaviorVariable('combatActionType')) == CAT_SpecialAttack)
  9013. {
  9014. pat = (int)GetBehaviorVariable('playerAttackType');
  9015.  
  9016. if(heavy && pat == PAT_Heavy)
  9017. {
  9018. return true;
  9019. }
  9020. else if(!heavy && pat == PAT_Light)
  9021. {
  9022. return true;
  9023. }
  9024. }
  9025.  
  9026. return false;
  9027. }
  9028.  
  9029. public function SetIsCurrentlyDodging(enable : bool, optional isRolling : bool)
  9030. {
  9031. super.SetIsCurrentlyDodging(enable, isRolling);
  9032.  
  9033. if ( isRolling )
  9034. {
  9035. SetCanPlayHitAnim( false );
  9036. this.AddBuffImmunity( EET_KnockdownTypeApplicator, 'Roll', false );
  9037. this.AddBuffImmunity( EET_Knockdown, 'Roll', false );
  9038. this.AddBuffImmunity( EET_HeavyKnockdown, 'Roll', false );
  9039. this.AddBuffImmunity( EET_Stagger, 'Roll', false );
  9040. }
  9041. else
  9042. {
  9043. SetCanPlayHitAnim( true );
  9044. this.RemoveBuffImmunity( EET_KnockdownTypeApplicator, 'Roll' );
  9045. this.RemoveBuffImmunity( EET_Knockdown, 'Roll' );
  9046. this.RemoveBuffImmunity( EET_HeavyKnockdown, 'Roll' );
  9047. this.RemoveBuffImmunity( EET_Stagger, 'Roll' );
  9048. }
  9049. }
  9050.  
  9051. public function EnableHardLock( flag : bool )
  9052. {
  9053. super.EnableHardLock(flag);
  9054.  
  9055. if(flag && ShouldProcessTutorial('TutorialTargettingWaiting'))
  9056. {
  9057. FactsAdd("tut_hardlocked");
  9058. }
  9059. }
  9060.  
  9061. protected function TestParryAndCounter(data : CPreAttackEventData, weaponId : SItemUniqueId, out parried : bool, out countered : bool) : array<CActor>
  9062. {
  9063. var ret : array<CActor>;
  9064.  
  9065. //cheat for QA tests - NPCs won't parry/counter
  9066. if(FactsQuerySum('player_is_the_boss') > 0)
  9067. {
  9068. //---------------- DEBUG
  9069. //draw debug AR
  9070. SetDebugAttackRange(data.rangeName);
  9071. RemoveTimer('PostAttackDebugRangeClear'); //disable AR clearing since we've just set a new one
  9072.  
  9073. return ret;
  9074. }
  9075.  
  9076. ret = super.TestParryAndCounter(data, weaponId, parried, countered);
  9077.  
  9078. //achievement
  9079. if(parried)
  9080. theGame.GetGamerProfile().ResetStat(ES_CounterattackChain);
  9081.  
  9082. return ret;
  9083. }
  9084.  
  9085. public function SetSpecialAttackTimeRatio(f : float)
  9086. {
  9087. LogSpecialHeavy(f);
  9088. specialAttackTimeRatio = f;
  9089. }
  9090.  
  9091. public function GetSpecialAttackTimeRatio() : float
  9092. {
  9093. return specialAttackTimeRatio;
  9094. }
  9095.  
  9096. //called when we processed special heavy attack action - either from hit or from CombatActionEnd()
  9097. public function OnSpecialAttackHeavyActionProcess()
  9098. {
  9099. //clear ration after attack performed
  9100. SetSpecialAttackTimeRatio(0.f);
  9101. }
  9102.  
  9103. protected function DoAttack(animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array<CActor>, attackAnimationName : name, hitTime : float)
  9104. {
  9105. var shakeStr : float;
  9106. var weapon : EPlayerWeapon;
  9107. var targetActor : CActor;
  9108.  
  9109. //cam shake for player's heavy attacks
  9110. if ( animData.attackName == 'attack_heavy_special' )
  9111. {
  9112. if( specialAttackTimeRatio != 1 )
  9113. shakeStr = (specialAttackTimeRatio / 3.333) + 0.2;
  9114. else
  9115. shakeStr = 0.5;
  9116.  
  9117. GCameraShake( shakeStr, false, GetWorldPosition(), 10);
  9118. }
  9119. else if ( IsHeavyAttack(attackActionName) )
  9120. {
  9121. if(parriedBy.Size() > 0)
  9122. shakeStr = 0.2;
  9123. else
  9124. shakeStr = 0.1;
  9125.  
  9126. GCameraShake(shakeStr, false, GetWorldPosition(), 10);
  9127. }
  9128.  
  9129. targetActor = (CActor)slideTarget;
  9130. if ( targetActor && hitTargets.Contains(targetActor) )
  9131. {
  9132. weapon = this.GetMostConvenientMeleeWeapon(targetActor,true);
  9133. if ( this.GetCurrentMeleeWeaponType() != PW_Fists && weapon != this.GetCurrentMeleeWeaponType() )
  9134. {
  9135. if ( weapon == PW_Steel )
  9136. {
  9137. thePlayer.OnEquipMeleeWeapon(PW_Steel,true);
  9138. }
  9139. else if ( weapon == PW_Silver )
  9140. {
  9141. thePlayer.OnEquipMeleeWeapon(PW_Silver,true);
  9142. }
  9143.  
  9144. }
  9145. }
  9146.  
  9147. super.DoAttack(animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime);
  9148. }
  9149.  
  9150. //var delayCombatStanceTimeStamp : float;
  9151.  
  9152. private var confirmCombatStanceTimeStamp : float;
  9153. private var isConfirmingCombatStance : bool;
  9154. final function SetPlayerCombatStance(stance : EPlayerCombatStance, optional force : bool )
  9155. {
  9156. var stanceInt : int;
  9157.  
  9158. if ( !CanChangeCombatStance( stance, force ) )
  9159. return;
  9160.  
  9161. combatStance = stance;
  9162. stanceInt = (int)stance;
  9163.  
  9164. SetBehaviorVariable( 'playerCombatStance' , (float)stanceInt);
  9165. SetBehaviorVariable( 'playerCombatStanceForOverlay' , (float)stanceInt);
  9166. if ( force )
  9167. SetBehaviorVariable( 'forceCombatStance' , 1.f);
  9168. else
  9169. SetBehaviorVariable( 'forceCombatStance' , 0.f);
  9170.  
  9171. if ( stance == PCS_AlertNear )
  9172. this.SetBehaviorVariable('isInCombatForOverlay',1.f);
  9173. else
  9174. this.SetBehaviorVariable('isInCombatForOverlay',0.f);
  9175. }
  9176.  
  9177. private function CanChangeCombatStance( stance : EPlayerCombatStance, optional force : bool ) : bool
  9178. {
  9179. var currTime : float;
  9180.  
  9181. if ( force )
  9182. return true;
  9183.  
  9184. if ( IsInFistFightMiniGame() )
  9185. return true;
  9186.  
  9187. if ( isInHolsterAnim )
  9188. return false;
  9189.  
  9190. if ( ( combatStance == PCS_Normal || combatStance == PCS_AlertFar ) && stance == PCS_AlertNear )
  9191. {
  9192. currTime = theGame.GetEngineTimeAsSeconds();
  9193. if ( !isConfirmingCombatStance )
  9194. {
  9195. isConfirmingCombatStance = true;
  9196. confirmCombatStanceTimeStamp = currTime;
  9197.  
  9198. return false;
  9199. }
  9200. else if ( currTime < confirmCombatStanceTimeStamp + 1.f )
  9201. {
  9202. if ( stance == PCS_AlertNear )
  9203. return false;
  9204. }
  9205. else
  9206. isConfirmingCombatStance = false;
  9207. }
  9208. else
  9209. isConfirmingCombatStance = false;
  9210.  
  9211. return true;
  9212. }
  9213.  
  9214. private var isInHolsterAnim : bool;
  9215. event OnHolsterWeaponStart()
  9216. {
  9217. isInHolsterAnim = true;
  9218. }
  9219.  
  9220. event OnHolsterWeaponEnd()
  9221. {
  9222. isInHolsterAnim = false;
  9223. }
  9224.  
  9225. final function GetPlayerCombatStance() : EPlayerCombatStance
  9226. {
  9227. return combatStance;
  9228. }
  9229.  
  9230. timer function DelayedDisableFindTarget( time : float , id : int)
  9231. {
  9232. if ( GetTarget().IsAlive() )
  9233. {
  9234. EnableFindTarget( false );
  9235. }
  9236. else
  9237. {
  9238. EnableFindTarget( true );
  9239. }
  9240. }
  9241.  
  9242. ///////////////////////////////////////////////////////////////////////////
  9243. // @BUFFER @COMBATACTIONBUFFER
  9244. ///////////////////////////////////////////////////////////////////////////
  9245.  
  9246. private var dodgeTimerRunning : bool;
  9247.  
  9248. function StartDodgeTimer()
  9249. {
  9250. dodgeTimerRunning = true;
  9251. thePlayer.AddTimer('DodgeTimer',0.2,false);
  9252. }
  9253.  
  9254. function StopDodgeTimer()
  9255. {
  9256. this.RemoveTimer('DodgeTimer');
  9257. dodgeTimerRunning = false;
  9258. }
  9259.  
  9260. function IsDodgeTimerRunning() : bool
  9261. {
  9262. return dodgeTimerRunning;
  9263. }
  9264.  
  9265. timer function DodgeTimer( dt : float, id : int )
  9266. {
  9267. dodgeTimerRunning = false;
  9268. }
  9269.  
  9270. public function EvadePressed( bufferAction : EBufferActionType )
  9271. {
  9272. }
  9273.  
  9274. public function PerformingCombatAction() : EBufferActionType
  9275. {
  9276. return BufferCombatAction;
  9277. }
  9278.  
  9279. public function PushCombatActionOnBuffer( action : EBufferActionType, stage : EButtonStage, optional allSteps : bool )
  9280. {
  9281. BufferButtonStage = stage;
  9282. BufferCombatAction = action;
  9283. BufferAllSteps = allSteps;
  9284. }
  9285.  
  9286. protected function ProcessCombatActionHeading( action : EBufferActionType ) : float
  9287. {
  9288. var processedActionHeading : float;
  9289.  
  9290. HandleMovement( 0.f );
  9291.  
  9292. if ( ShouldUsePCModeTargeting() )
  9293. return theGame.GetGameCamera().GetHeading();
  9294.  
  9295. if ( lAxisReleasedAfterCounter ) // && IsInCombatAction() )
  9296. ResetCachedRawPlayerHeading();
  9297.  
  9298. processedActionHeading = cachedRawPlayerHeading;
  9299.  
  9300. return processedActionHeading;
  9301. }
  9302. /*
  9303. private function ProcessCombatActionHeading( action : EBufferActionType ) : float
  9304. {
  9305. var processedActionHeading : float;
  9306. var unusedActor : CActor; //MS: placeholder variable to fix memory error
  9307.  
  9308. if ( IsUsingVehicle() )
  9309. {
  9310. processedActionHeading = theGame.GetGameCamera().GetHeading();
  9311. return processedActionHeading;
  9312. }
  9313.  
  9314. if ( !bLAxisReleased || lAxisPushedTimeStamp + 0.5f > theGame.GetEngineTimeAsSeconds() )
  9315. processedActionHeading = cachedRawPlayerHeading;
  9316. else
  9317. {
  9318. if ( GetDisplayTarget() )
  9319. {
  9320. if ( cachedCombatActionHeading == cachedRawPlayerHeading )
  9321. ResetCachedRawPlayerHeading();
  9322. else
  9323. {
  9324. cachedRawPlayerHeading = cachedCombatActionHeading;
  9325. canResetCachedCombatActionHeading = true;
  9326. }
  9327.  
  9328. processedActionHeading = cachedRawPlayerHeading;
  9329. }
  9330. else
  9331. {
  9332. if ( lAxisReleasedAfterCounterNoCA )
  9333. ResetRawPlayerHeading();
  9334.  
  9335. cachedRawPlayerHeading = rawPlayerHeading;
  9336.  
  9337. if ( lAxisReleasedAfterCounterNoCA )
  9338. processedActionHeading = GetHeading();
  9339. else
  9340. processedActionHeading = cachedRawPlayerHeading;
  9341. }
  9342. }
  9343.  
  9344. if ( this.IsCameraLockedToTarget() && this.IsActorLockedToTarget() && action != EBAT_Dodge && action != EBAT_Roll )
  9345. processedActionHeading = theGame.GetGameCamera().GetHeading();
  9346.  
  9347. if ( lAxisReleasedAfterCounterNoCA )
  9348. {
  9349. if ( action == EBAT_Dodge || action == EBAT_Roll )
  9350. {
  9351. if ( ( !IsEnemyInCone( this, GetHeadingVector(), softLockDist, 60.f, unusedActor ) || !IsEnemyInCone( this, GetHeadingVector() + 180, softLockDist, 60.f, unusedActor ) ) && moveTarget )
  9352. processedActionHeading = VecHeading( moveTarget.GetWorldPosition() - GetWorldPosition() ) + 180;
  9353. else
  9354. processedActionHeading = GetHeading() + 180;
  9355. }
  9356. }
  9357.  
  9358. //GetVisualDebug().AddArrow( 'cachedRawPlayerHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( cachedRawPlayerHeading ), 1.f, 0.2f, 0.2f, true, Color(0,255,128), true, 5.f );
  9359. //GetVisualDebug().AddArrow( 'CombatActionHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( GetCombatActionHeading() )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f );
  9360.  
  9361. return processedActionHeading;
  9362. }*/
  9363.  
  9364. function ResetRawPlayerHeading()
  9365. {
  9366. if ( GetDisplayTarget() )
  9367. rawPlayerHeading = VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() );
  9368. else
  9369. rawPlayerHeading = GetHeading();
  9370.  
  9371. //LogChannel('ResetRawPlayerHeading',"ResetRawPlayerHeading" );
  9372. }
  9373.  
  9374. function ResetCachedRawPlayerHeading()
  9375. {
  9376. cachedRawPlayerHeading = rawPlayerHeading;
  9377. if ( GetDisplayTarget() && IsDisplayTargetTargetable() && AbsF( AngleDistance( VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() ), this.GetHeading() ) ) < 90.f )
  9378. cachedRawPlayerHeading = VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() );
  9379. else
  9380. cachedRawPlayerHeading = this.GetHeading();
  9381.  
  9382. if ( canResetCachedCombatActionHeading )
  9383. cachedCombatActionHeading = cachedRawPlayerHeading;
  9384. }
  9385.  
  9386. public function GetCombatActionTarget( action : EBufferActionType ) : CGameplayEntity
  9387. {
  9388. var selectedTargetableEntity : CGameplayEntity;
  9389.  
  9390. if ( !this.IsUsingVehicle() )
  9391. selectedTargetableEntity = FindNonActorTarget( true, action );
  9392.  
  9393. if ( selectedTargetableEntity )
  9394. {
  9395. return selectedTargetableEntity;
  9396. }
  9397. else
  9398. {
  9399. /*if ( !IsCombatMusicEnabled() && displayTarget )
  9400. {
  9401. if ( !( (CActor)displayTarget ) )
  9402. return NULL;
  9403. else
  9404. return displayTarget;
  9405. }*/
  9406.  
  9407. if ( !this.IsUsingVehicle() )
  9408. FindTarget( true, action, true );
  9409. else
  9410. ((CR4PlayerStateUseGenericVehicle)this.GetState( 'UseGenericVehicle' )).FindTarget();
  9411.  
  9412. return GetTarget();
  9413. }
  9414. }
  9415.  
  9416. //MS: FindNonActorTarget may or may not have an interaction component, which is why it is separate from ProcessInteraction
  9417. private function FindNonActorTarget( actionCheck : bool, optional action : EBufferActionType ) : CGameplayEntity
  9418. {
  9419. var targetableEntities : array<CGameplayEntity>;
  9420. var selectedTargetableEntity : CGameplayEntity;
  9421. var selectionPriority : array< float >;
  9422. var selectionWeights : STargetSelectionWeights;
  9423. var findEntityDist : float;
  9424. var i, size : int;
  9425. var playerHeading : float;
  9426. var playerInventory : CInventoryComponent;
  9427. var castSignType : ESignType;
  9428. var targetingInfo : STargetingInfo;
  9429. var playerPosition : Vector;
  9430. var cameraPosition : Vector;
  9431. var playerHeadingVector : Vector;
  9432. var rawPlayerHeadingVector : Vector;
  9433.  
  9434. playerPosition = this.GetWorldPosition();
  9435. cameraPosition = theCamera.GetCameraPosition();
  9436. rawPlayerHeadingVector = VecFromHeading( rawPlayerHeading );
  9437.  
  9438. if ( bCanFindTarget && !IsHardLockEnabled() )
  9439. {
  9440. if ( actionCheck && IsInCombat() && action == EBAT_CastSign )
  9441. {
  9442. findEntityDist = 6.f;
  9443. selectionWeights.angleWeight = 0.375f;
  9444. selectionWeights.distanceWeight = 0.275f;
  9445. selectionWeights.distanceRingWeight = 0.35f;
  9446. }
  9447. else if ( !IsInCombat() && lastAxisInputIsMovement )
  9448. {
  9449. findEntityDist = softLockDist;
  9450. selectionWeights.angleWeight = 0.375f;
  9451. selectionWeights.distanceWeight = 0.275f;
  9452. selectionWeights.distanceRingWeight = 0.35f;
  9453. }
  9454. else
  9455. {
  9456. findEntityDist = softLockDist;
  9457. selectionWeights.angleWeight = 0.75f;
  9458. selectionWeights.distanceWeight = 0.125f;
  9459. selectionWeights.distanceRingWeight = 0.125f;
  9460. }
  9461.  
  9462. //MSTODO : Ask programmers for filter for interactive entities
  9463. if ( !IsInCombat() || !bLAxisReleased )
  9464. {
  9465. FindGameplayEntitiesInRange( targetableEntities, this, findEntityDist, 10, theGame.params.TAG_SOFT_LOCK );
  9466. }
  9467.  
  9468. if ( targetableEntities.Size() > 0 )
  9469. {
  9470. playerInventory = this.GetInventory();
  9471. castSignType = this.GetEquippedSign();
  9472.  
  9473. if ( !bLAxisReleased )
  9474. {
  9475. targetingInfo.source = this;
  9476. targetingInfo.canBeTargetedCheck = false;
  9477. targetingInfo.coneCheck = true;
  9478. targetingInfo.coneHalfAngleCos = 0.5f; // = CosF( Deg2Rad( 120.0f * 0.5f ) )
  9479. targetingInfo.coneDist = softLockDist;
  9480. targetingInfo.coneHeadingVector = rawPlayerHeadingVector;
  9481. targetingInfo.distCheck = true;
  9482. targetingInfo.invisibleCheck = false;
  9483. targetingInfo.navMeshCheck = false;
  9484. targetingInfo.frameScaleX = 1.0f;
  9485. targetingInfo.frameScaleY = 1.0f;
  9486. targetingInfo.knockDownCheck = false;
  9487. targetingInfo.knockDownCheckDist = 0.0f;
  9488. targetingInfo.rsHeadingCheck = false;
  9489. targetingInfo.rsHeadingLimitCos = 1.0f;
  9490. }
  9491.  
  9492. for( i = targetableEntities.Size()-1; i>=0; i-=1 )
  9493. {
  9494. if ( bLAxisReleased )
  9495. {
  9496. if ( !lastAxisInputIsMovement )
  9497. {
  9498. if ( !WasVisibleInScaledFrame( targetableEntities[i], 0.9f, 0.9f ) )
  9499. {
  9500. targetableEntities.Erase(i);
  9501. continue;
  9502. }
  9503. }
  9504. else if ( !WasVisibleInScaledFrame( targetableEntities[i], 1.f, 1.f ) )
  9505. {
  9506. targetableEntities.Erase(i);
  9507. continue;
  9508. }
  9509. }
  9510. else
  9511. {
  9512. targetingInfo.targetEntity = targetableEntities[i];
  9513. if ( actionCheck && moveTarget )
  9514. {
  9515. targetingInfo.inFrameCheck = false;
  9516. if ( !IsEntityTargetable( targetingInfo ) )
  9517. {
  9518. targetableEntities.Erase(i);
  9519. continue;
  9520. }
  9521. }
  9522. else
  9523. {
  9524. targetingInfo.inFrameCheck = true;
  9525. if ( !IsEntityTargetable( targetingInfo ) )
  9526. {
  9527. targetableEntities.Erase(i);
  9528. continue;
  9529. }
  9530. }
  9531. }
  9532.  
  9533. if ( actionCheck )
  9534. {
  9535. if ( action == EBAT_ItemUse )
  9536. {
  9537. if ( ( playerInventory.IsItemBomb( this.GetSelectedItemId() ) && !targetableEntities[i].HasTag( 'softLock_Bomb' ) )
  9538. || ( playerInventory.IsItemCrossbow( this.GetSelectedItemId() ) && !targetableEntities[i].HasTag( 'softLock_Bolt' ) ) )
  9539. {
  9540. targetableEntities.Erase(i);
  9541. continue;
  9542. }
  9543. }
  9544. else if ( action == EBAT_CastSign )
  9545. {
  9546. if ( ( castSignType == ST_Aard && !targetableEntities[i].HasTag( 'softLock_Aard' ) )
  9547. || ( castSignType == ST_Igni && !targetableEntities[i].HasTag( 'softLock_Igni' ) )
  9548. || ( castSignType == ST_Axii && !targetableEntities[i].HasTag( 'softLock_Axii' ) )
  9549. || castSignType == ST_Yrden
  9550. || castSignType == ST_Quen )
  9551. {
  9552. targetableEntities.Erase(i);
  9553. continue;
  9554. }
  9555. }
  9556. else if ( action == EBAT_LightAttack || action == EBAT_HeavyAttack || action == EBAT_SpecialAttack_Heavy )
  9557. {
  9558. if ( ( IsWeaponHeld( 'fist' ) && !targetableEntities[i].HasTag( 'softLock_Fist' ) ) || ( !IsWeaponHeld( 'fist' ) && !targetableEntities[i].HasTag( 'softLock_Weapon' ) ) )
  9559. {
  9560. targetableEntities.Erase(i);
  9561. continue;
  9562. }
  9563. }
  9564. else
  9565. {
  9566. targetableEntities.Erase(i);
  9567. continue;
  9568. }
  9569. }
  9570. }
  9571. }
  9572.  
  9573. if ( targetableEntities.Size() > 0)
  9574. {
  9575. playerHeading = this.GetHeading();
  9576. playerHeadingVector = this.GetHeadingVector();
  9577. if ( IsInCombat() )
  9578. {
  9579. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9580. {
  9581. if ( bLAxisReleased )
  9582. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, cameraPosition, rawPlayerHeadingVector ) );
  9583. else
  9584. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, rawPlayerHeadingVector ) );
  9585. }
  9586.  
  9587. if ( selectionPriority.Size() > 0 )
  9588. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9589. }
  9590. else
  9591. {
  9592. if ( bLAxisReleased )
  9593. {
  9594. if ( !lastAxisInputIsMovement )
  9595. {
  9596. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9597. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, cameraPosition, rawPlayerHeadingVector ) );
  9598.  
  9599. if ( selectionPriority.Size() > 0 )
  9600. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9601. }
  9602. else
  9603. {
  9604. if ( IsInCombatAction() )
  9605. selectedTargetableEntity = nonActorTarget;
  9606. else
  9607. {
  9608. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9609. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, playerHeadingVector ) );
  9610.  
  9611. if ( selectionPriority.Size() > 0 )
  9612. {
  9613. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9614.  
  9615. targetingInfo.source = this;
  9616. targetingInfo.targetEntity = selectedTargetableEntity;
  9617. targetingInfo.canBeTargetedCheck = false;
  9618. targetingInfo.coneCheck = true;
  9619. targetingInfo.coneHalfAngleCos = 0.0f; // = CosF( Deg2Rad( 180.0f * 0.5f ) )
  9620. targetingInfo.coneDist = softLockDist;
  9621. targetingInfo.coneHeadingVector = this.GetHeadingVector();
  9622. targetingInfo.distCheck = true;
  9623. targetingInfo.invisibleCheck = false;
  9624. targetingInfo.navMeshCheck = false;
  9625. targetingInfo.inFrameCheck = false;
  9626. targetingInfo.frameScaleX = 1.0f;
  9627. targetingInfo.frameScaleY = 1.0f;
  9628. targetingInfo.knockDownCheck = false;
  9629. targetingInfo.knockDownCheckDist = 0.0f;
  9630. targetingInfo.rsHeadingCheck = false;
  9631. targetingInfo.rsHeadingLimitCos = 1.0f;
  9632.  
  9633. if ( !IsEntityTargetable( targetingInfo ) )
  9634. selectedTargetableEntity = NULL;
  9635. }
  9636. }
  9637. }
  9638. }
  9639. else
  9640. {
  9641. for( i = 0; i < targetableEntities.Size(); i += 1 )
  9642. selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, rawPlayerHeadingVector ) );
  9643.  
  9644. if ( selectionPriority.Size() > 0 )
  9645. selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ];
  9646. }
  9647. }
  9648. }
  9649. else
  9650. selectedTargetableEntity = NULL;
  9651. }
  9652.  
  9653. SetNonActorTarget( selectedTargetableEntity );
  9654. return selectedTargetableEntity;
  9655. }
  9656. /*
  9657. timer function IsItemUseInputHeld ( time : float , id : int)
  9658. {
  9659. if ( GetBIsInputAllowed()
  9660. && GetBIsCombatActionAllowed()
  9661. && IsActionAllowed( EIAB_Crossbow )
  9662. && inv.IsIdValid( GetSelectedItemId() )
  9663. && inv.IsItemCrossbow( GetSelectedItemId()En )
  9664. && rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' )
  9665. {
  9666. SetIsAimingCrossbow( true );
  9667. PushCombatActionOnBuffer( EBAT_ItemUse, BS_Pressed );
  9668. ProcessCombatActionBuffer();
  9669. }
  9670.  
  9671. if ( theInput.GetActionValue( 'ThrowItem' ) == 0.f )
  9672. {
  9673. if ( GetBIsCombatActionAllowed() )
  9674. {
  9675. PushCombatActionOnBuffer( EBAT_ItemUse, BS_Pressed );
  9676. ProcessCombatActionBuffer();
  9677. }
  9678.  
  9679. SetIsAimingCrossbow( false );
  9680. RemoveTimer( 'IsItemUseInputHeld' );
  9681. }
  9682. }*/
  9683.  
  9684. public function SetupCombatAction( action : EBufferActionType, stage : EButtonStage )
  9685. {
  9686. var weaponType : EPlayerWeapon;
  9687. var canAttackTarget : CGameplayEntity;
  9688. var target : CActor;
  9689.  
  9690. /*if( thePlayer.substateManager.GetStateCur() == 'Slide' )
  9691. {
  9692. return;
  9693. }*/
  9694. if ( !IsCombatMusicEnabled() )
  9695. {
  9696. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  9697. FindTarget();
  9698. UpdateDisplayTarget( true );
  9699. }
  9700.  
  9701. if ( displayTarget && IsDisplayTargetTargetable() )
  9702. canAttackTarget = displayTarget;
  9703. else if ( GetTarget() )
  9704. canAttackTarget = GetTarget();
  9705. else if( !target && IsCombatMusicEnabled() )
  9706. canAttackTarget = moveTarget;
  9707.  
  9708. target = (CActor)canAttackTarget;
  9709.  
  9710. if ( !AllowAttack( target, action ) )
  9711. return;
  9712.  
  9713. if( ( action != EBAT_ItemUse ) && ( action != EBAT_CastSign ) )
  9714. {
  9715. weaponType = weaponHolster.GetCurrentMeleeWeapon();
  9716. PrepareToAttack( target, action );
  9717.  
  9718. //Do not automatically attack when drawing sword
  9719. if ( weaponType != weaponHolster.GetCurrentMeleeWeapon() )
  9720. {
  9721. //Check if switching from PW_None to PW_Fists. If so, allow the attack
  9722. if ( !( weaponType == PW_None && weaponHolster.GetCurrentMeleeWeapon() == PW_Fists ) )
  9723. return;
  9724. }
  9725. }
  9726.  
  9727. //geralt's special attack heavy
  9728. if(action == EBAT_SpecialAttack_Heavy && !((W3ReplacerCiri)this) )
  9729. thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s02));
  9730.  
  9731. CriticalEffectAnimationInterrupted("SetupCombatAction " + action);
  9732. PushCombatActionOnBuffer( action, stage );
  9733.  
  9734. if( GetBIsCombatActionAllowed() )
  9735. {
  9736. ProcessCombatActionBuffer();
  9737. }
  9738. }
  9739.  
  9740. public function AllowAttack( target : CActor, action : EBufferActionType ) : bool
  9741. {
  9742. var newTarget : CActor;
  9743. var canAttackWhenNotInCombat : bool;
  9744. var messageDisplayed : bool;
  9745.  
  9746. var itemId : SItemUniqueId;
  9747. var isShootingCrossbow : bool;
  9748.  
  9749. var isInCorrectState : bool;
  9750.  
  9751. if ( target )
  9752. {
  9753. if ( target.IsTargetableByPlayer())
  9754. {
  9755. if ( !target.IsAttackableByPlayer() )
  9756. {
  9757. DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_cant_attack_this_target"));
  9758. return false;
  9759. }
  9760. }
  9761. }
  9762.  
  9763. if ( this.GetCurrentStateName() == 'Exploration' )
  9764. isInCorrectState = true;
  9765.  
  9766. if ( action == EBAT_ItemUse )
  9767. {
  9768. itemId = thePlayer.GetSelectedItemId();
  9769. if ( inv.IsIdValid(itemId) && inv.IsItemCrossbow(itemId) )
  9770. isShootingCrossbow = true;
  9771.  
  9772. if ( !isInCorrectState )
  9773. {
  9774. if ( this.GetCurrentStateName() == 'AimThrow' && !isShootingCrossbow )
  9775. {
  9776. isInCorrectState = true;
  9777. }
  9778. }
  9779. }
  9780.  
  9781. if ( isInCorrectState )
  9782. canAttackWhenNotInCombat = thePlayer.CanAttackWhenNotInCombat( action, false, newTarget, target );
  9783.  
  9784. if( !target )
  9785. {
  9786. if ( isInCorrectState )
  9787. {
  9788. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  9789. target = newTarget;
  9790. }
  9791. }
  9792.  
  9793. if ( isInCorrectState )
  9794. {
  9795. if ( !canAttackWhenNotInCombat )
  9796. {
  9797. if ( DisplayCannotAttackMessage( target ) )
  9798. messageDisplayed = true;
  9799. else if ( ( action == EBAT_LightAttack || action == EBAT_HeavyAttack )
  9800. && !RaiseAttackFriendlyEvent( target ) )
  9801. messageDisplayed = true;
  9802. else
  9803. {
  9804. if ( !CanRaiseCombatActionFriendlyEvent( isShootingCrossbow ) )
  9805. messageDisplayed = true;
  9806. }
  9807. }
  9808.  
  9809. if ( messageDisplayed )
  9810. {
  9811. theInput.ForceDeactivateAction('ThrowItem');
  9812. theInput.ForceDeactivateAction('ThrowItemHold');
  9813. this.SignalGameplayEvent( 'FriendlyAttackAction' );
  9814. return false;
  9815. }
  9816. }
  9817.  
  9818. return true;
  9819. }
  9820.  
  9821.  
  9822. //returns true if processed
  9823. public function ProcessCombatActionBuffer() : bool
  9824. {
  9825. var actionResult : bool;
  9826. var action : EBufferActionType = this.BufferCombatAction;
  9827. var stage : EButtonStage = this.BufferButtonStage;
  9828. var s : SNotWorkingOutFunctionParametersHackStruct1;
  9829. var allSteps : bool = this.BufferAllSteps;
  9830.  
  9831. if ( IsInCombatActionFriendly() )
  9832. {
  9833. RaiseEvent('CombatActionFriendlyEnd');
  9834. }
  9835.  
  9836. //Disable any npcs that are set to unpushable when Player performs another combat action
  9837. if ( ( action != EBAT_SpecialAttack_Heavy && action != EBAT_ItemUse )
  9838. || ( action == EBAT_SpecialAttack_Heavy && stage == BS_Pressed )
  9839. || ( action == EBAT_ItemUse && stage != BS_Released ) )
  9840. {
  9841. GetMovingAgentComponent().GetMovementAdjustor().CancelAll();
  9842. SetUnpushableTarget( NULL );
  9843. }
  9844.  
  9845. //if ( !( action == EBAT_Dodge && stage == BS_Pressed && IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge ) )
  9846. if ( !( action == EBAT_Dodge || action == EBAT_Roll ) )
  9847. {
  9848. SetIsCurrentlyDodging(false);
  9849. }
  9850. //-- init
  9851. SetCombatActionHeading( ProcessCombatActionHeading( action ) );
  9852.  
  9853. //theGame.GetSyncAnimManager().OnRemoveFinisherCameraAnimation();
  9854.  
  9855. if ( action == EBAT_ItemUse && GetInventory().IsItemCrossbow( selectedItemId ) )
  9856. {
  9857. //stage == BS_Pressed &&
  9858. if ( rangedWeapon
  9859. && ( ( rangedWeapon.GetCurrentStateName() != 'State_WeaponShoot' && rangedWeapon.GetCurrentStateName() != 'State_WeaponAim' ) || GetIsShootingFriendly() ) )
  9860. {
  9861. SetSlideTarget( GetCombatActionTarget( action ) );
  9862. }
  9863. }
  9864. else if ( !( ( action == EBAT_SpecialAttack_Heavy && stage == BS_Released ) || GetCurrentStateName() == 'AimThrow' ) )
  9865. {
  9866. SetSlideTarget( GetCombatActionTarget( action ) );
  9867. }
  9868.  
  9869. if( !slideTarget )
  9870. LogChannel( 'Targeting', "NO SLIDE TARGET" );
  9871.  
  9872. //-- process
  9873. actionResult = true;
  9874.  
  9875. switch ( action )
  9876. {
  9877. case EBAT_EMPTY :
  9878. {
  9879. this.BufferAllSteps = false;
  9880. return true;
  9881. } break;
  9882.  
  9883. case EBAT_LightAttack :
  9884. {
  9885. if ( IsCiri() )
  9886. return false;
  9887.  
  9888. switch ( stage )
  9889. {
  9890. case BS_Pressed ://BS_Released :
  9891. {
  9892. // early out, stamina drain etc
  9893. //if( HasStaminaToUseAction(ESAT_LightAttack) )
  9894. //{
  9895.  
  9896. // replacing stamina lock with stamina drain - change in design
  9897. /*
  9898. s = LockStamina(ESAT_LightAttack);
  9899. if(s.retValue)
  9900. {
  9901. AddCombatActionStaminaLock(s.outValue);
  9902. }
  9903. */
  9904. DrainStamina(ESAT_LightAttack);
  9905. //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack );
  9906.  
  9907. thePlayer.BreakPheromoneEffect();
  9908. actionResult = OnPerformAttack(theGame.params.ATTACK_NAME_LIGHT);
  9909. //}
  9910. } break;
  9911.  
  9912. default :
  9913. {
  9914. actionResult = false;
  9915. }break;
  9916. }
  9917. }break;
  9918.  
  9919. case EBAT_HeavyAttack :
  9920. {
  9921. if ( IsCiri() )
  9922. return false;
  9923.  
  9924. switch ( stage )
  9925. {
  9926. case BS_Released :
  9927. {
  9928. // early out, stamina drain etc
  9929. //if( HasStaminaToUseAction(ESAT_HeavyAttack) )
  9930. //{
  9931. // replacing stamina lock with stamina drain - change in design
  9932. /*
  9933. s = LockStamina(ESAT_HeavyAttack);
  9934. if(s.retValue)
  9935. {
  9936. AddCombatActionStaminaLock(s.outValue);
  9937. }
  9938. */
  9939. DrainStamina(ESAT_HeavyAttack);
  9940.  
  9941. //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack );
  9942.  
  9943. thePlayer.BreakPheromoneEffect();
  9944. actionResult = this.OnPerformAttack(theGame.params.ATTACK_NAME_HEAVY);
  9945. //}
  9946. } break;
  9947.  
  9948. case BS_Pressed :
  9949. {
  9950. if ( this.GetCurrentStateName() == 'CombatFists' )
  9951. {
  9952. // early out, stamina drain etc
  9953. //if( HasStaminaToUseAction(ESAT_HeavyAttack) )
  9954. //{
  9955. // replacing stamina lock with stamina drain - change in design
  9956. /*
  9957. s = LockStamina(ESAT_HeavyAttack);
  9958. if(s.retValue)
  9959. {
  9960. AddCombatActionStaminaLock(s.outValue);
  9961. }
  9962. */
  9963. DrainStamina(ESAT_HeavyAttack);
  9964.  
  9965. //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack );
  9966.  
  9967. thePlayer.BreakPheromoneEffect();
  9968. actionResult = this.OnPerformAttack(theGame.params.ATTACK_NAME_HEAVY);
  9969. //}
  9970. }
  9971. } break;
  9972.  
  9973. default :
  9974. {
  9975. actionResult = false;
  9976.  
  9977. } break;
  9978. }
  9979. } break;
  9980.  
  9981. case EBAT_ItemUse : //this gets called only for bombs. No usable items use this!
  9982. {
  9983. switch ( stage )
  9984. {
  9985. case BS_Pressed :
  9986. {
  9987. if ( !( (W3PlayerWitcher)this ) ||
  9988. ( !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) ) ) )
  9989. //( !IsCastingSign() && !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) ) )
  9990. {
  9991. if ( inv.IsItemCrossbow( selectedItemId ) )
  9992. {
  9993. rangedWeapon = ( Crossbow )( inv.GetItemEntityUnsafe( selectedItemId ) );
  9994. rangedWeapon.OnRangedWeaponPress();
  9995. GetTarget().SignalGameplayEvent( 'Approach' );
  9996. GetTarget().SignalGameplayEvent( 'ShootingCrossbow' );
  9997. }
  9998. else if(inv.IsItemBomb(selectedItemId) && this.inv.SingletonItemGetAmmo(selectedItemId) > 0 )
  9999. {
  10000. if( ((W3PlayerWitcher)this).GetBombDelay( ((W3PlayerWitcher)this).GetItemSlot( selectedItemId ) ) <= 0.0f )
  10001. {
  10002. BombThrowStart();
  10003. GetTarget().SignalGameplayEvent( 'Approach' );
  10004. }
  10005. }
  10006. else
  10007. {
  10008. DrainStamina(ESAT_UsableItem);
  10009. UsableItemStart();
  10010. }
  10011. }
  10012.  
  10013. } if (!allSteps) break;
  10014.  
  10015. case BS_Released:
  10016. {
  10017. if ( !( (W3PlayerWitcher)this ) ||
  10018. ( !IsInCombatActionFriendly() && ( GetBIsCombatActionAllowed() || !( !GetBIsCombatActionAllowed() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) ) ) ) )
  10019. //( !IsCastingSign() && !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) ) )
  10020. {
  10021. if ( inv.IsItemCrossbow( selectedItemId ) )
  10022. {
  10023. /*if ( rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' )
  10024. {
  10025. rangedWeapon = ( Crossbow )( inv.GetItemEntityUnsafe( selectedItemId ) );
  10026. rangedWeapon.OnRangedWeaponPress();
  10027. }*/
  10028. rangedWeapon.OnRangedWeaponRelease();
  10029. }
  10030. else if(inv.IsItemBomb(selectedItemId))
  10031. {
  10032. BombThrowRelease();
  10033. }
  10034. else
  10035. {
  10036. UsableItemRelease();
  10037. }
  10038. }
  10039. } break;
  10040.  
  10041. default :
  10042. {
  10043. actionResult = false;
  10044. break;
  10045. }
  10046. }
  10047. } break;
  10048.  
  10049. case EBAT_Dodge :
  10050. {
  10051. switch ( stage )
  10052. {
  10053. case BS_Released :
  10054. {
  10055. theGame.GetBehTreeReactionManager().CreateReactionEvent( this, 'PlayerEvade', 1.0f, 10.0f, -1.0f, -1 );
  10056. thePlayer.BreakPheromoneEffect();
  10057. actionResult = this.OnPerformEvade( PET_Dodge );
  10058. } break;
  10059.  
  10060. /*case BS_Pressed :
  10061. {
  10062. actionResult = this.OnPerformEvade( PET_Roll );
  10063. } break;*/
  10064.  
  10065. default :
  10066. {
  10067. actionResult = false;
  10068. } break;
  10069. }
  10070. } break;
  10071.  
  10072. case EBAT_Roll :
  10073. {
  10074. if ( IsCiri() )
  10075. return false;
  10076.  
  10077. switch ( stage )
  10078. {
  10079. case BS_Released :
  10080. {
  10081. theGame.GetBehTreeReactionManager().CreateReactionEvent( this, 'PlayerEvade', 1.0f, 10.0f, -1.0f, -1 );
  10082. thePlayer.BreakPheromoneEffect();
  10083. actionResult = this.OnPerformEvade( PET_Roll );
  10084. } break;
  10085.  
  10086. case BS_Pressed :
  10087. {
  10088. if ( this.GetBehaviorVariable( 'combatActionType' ) == 2.f )
  10089. {
  10090. if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' )
  10091. actionResult = this.OnPerformEvade( PET_Pirouette );
  10092. else
  10093. actionResult = this.OnPerformEvade( PET_Roll );
  10094. }
  10095. else
  10096. {
  10097. if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' )
  10098. {
  10099. actionResult = this.OnPerformEvade( PET_Dodge );
  10100. actionResult = this.OnPerformEvade( PET_Pirouette );
  10101. }
  10102. else
  10103. {
  10104. actionResult = this.OnPerformEvade( PET_Dodge );
  10105. actionResult = this.OnPerformEvade( PET_Roll );
  10106. }
  10107. }
  10108.  
  10109.  
  10110. } break;
  10111.  
  10112. default :
  10113. {
  10114. actionResult = false;
  10115. } break;
  10116. }
  10117. } break;
  10118.  
  10119. case EBAT_Draw_Steel :
  10120. {
  10121. switch ( stage )
  10122. {
  10123. case BS_Pressed :
  10124. {
  10125. if( !IsActionAllowed(EIAB_DrawWeapon) )
  10126. {
  10127. thePlayer.DisplayActionDisallowedHudMessage(EIAB_DrawWeapon);
  10128. actionResult = false;
  10129. break;
  10130. }
  10131. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'steelsword' ) )
  10132. {
  10133. OnEquipMeleeWeapon( PW_Steel, false, true );
  10134. }
  10135.  
  10136. actionResult = false;
  10137.  
  10138. } break;
  10139.  
  10140. default :
  10141. {
  10142. actionResult = false;
  10143. } break;
  10144. }
  10145. } break;
  10146.  
  10147. case EBAT_Draw_Silver :
  10148. {
  10149. switch ( stage )
  10150. {
  10151. case BS_Pressed :
  10152. {
  10153. if( !IsActionAllowed(EIAB_DrawWeapon) )
  10154. {
  10155. thePlayer.DisplayActionDisallowedHudMessage(EIAB_DrawWeapon);
  10156. actionResult = false;
  10157. break;
  10158. }
  10159. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'silversword' ) )
  10160. {
  10161. OnEquipMeleeWeapon( PW_Silver, false, true );
  10162. }
  10163.  
  10164. actionResult = false;
  10165.  
  10166. } break;
  10167.  
  10168. default :
  10169. {
  10170. actionResult = false;
  10171. } break;
  10172. }
  10173. } break;
  10174.  
  10175. case EBAT_Sheathe_Sword :
  10176. {
  10177. switch ( stage )
  10178. {
  10179. case BS_Pressed :
  10180. {
  10181. if( GetCurrentMeleeWeaponType() == PW_Silver )
  10182. {
  10183. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'silversword' ) )
  10184. {
  10185. OnEquipMeleeWeapon( PW_Silver, false, true );
  10186. }
  10187. }
  10188. else if( GetCurrentMeleeWeaponType() == PW_Steel )
  10189. {
  10190. if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'steelsword' ) )
  10191. {
  10192. OnEquipMeleeWeapon( PW_Steel, false, true );
  10193. }
  10194. }
  10195.  
  10196. actionResult = false;
  10197.  
  10198. } break;
  10199.  
  10200. default :
  10201. {
  10202. actionResult = false;
  10203. } break;
  10204. }
  10205. } break;
  10206.  
  10207. default:
  10208. return false; //not processed
  10209. }
  10210.  
  10211. //if here then buffer was processed
  10212. CleanCombatActionBuffer();
  10213.  
  10214. if (actionResult)
  10215. {
  10216. SetCombatAction( action ) ;
  10217.  
  10218. if(GetWitcherPlayer().IsInFrenzy())
  10219. GetWitcherPlayer().SkillFrenzyFinish(0);
  10220. }
  10221.  
  10222. return true;
  10223. }
  10224.  
  10225. public function CleanCombatActionBuffer()
  10226. {
  10227. BufferCombatAction = EBAT_EMPTY;
  10228. BufferAllSteps = false;
  10229. }
  10230.  
  10231. public function CancelHoldAttacks()
  10232. {
  10233. RemoveTimer( 'IsSpecialLightAttackInputHeld' );
  10234. RemoveTimer( 'IsSpecialHeavyAttackInputHeld' );
  10235. RemoveTimer( 'SpecialAttackLightSustainCost' );
  10236. RemoveTimer( 'SpecialAttackHeavySustainCost' );
  10237. RemoveTimer( 'UpdateSpecialAttackLightHeading' );
  10238. UnblockAction( EIAB_Crossbow, 'SpecialAttack' );
  10239.  
  10240. ResumeStaminaRegen('WhirlSkill');
  10241.  
  10242. if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_SpecialAttack && GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.f )
  10243. {
  10244. if( GetBehaviorVariable( 'playerAttackType' ) == (int)PAT_Light )
  10245. {
  10246. SetAttackActionName(SkillEnumToName(S_Sword_s01));
  10247. PushCombatActionOnBuffer( EBAT_SpecialAttack_Light, BS_Released );
  10248. ProcessCombatActionBuffer();
  10249. //SetupCombatAction( EBAT_SpecialAttack_Light, BS_Released );
  10250. ((W3PlayerWitcherStateCombatFists) GetState('Combat')).ResetTimeToEndCombat();
  10251.  
  10252. }
  10253. else if( GetBehaviorVariable( 'playerAttackType' ) == (int)PAT_Heavy )
  10254. {
  10255. SetAttackActionName(SkillEnumToName(S_Sword_s02));
  10256. PushCombatActionOnBuffer( EBAT_SpecialAttack_Heavy, BS_Released );
  10257. ProcessCombatActionBuffer();
  10258. //SetupCombatAction( EBAT_SpecialAttack_Heavy, BS_Released );
  10259. }
  10260. }
  10261. }
  10262.  
  10263. public function RaiseAttackFriendlyEvent( actor : CActor ) : bool
  10264. {
  10265. var playerToTargetHeading : float;
  10266.  
  10267. if ( actor && RaiseCombatActionFriendlyEvent() )
  10268. {
  10269. SetBehaviorVariable( 'tauntTypeForOverlay', 0.f );
  10270. SetBehaviorVariable( 'combatActionTypeForOverlay', (int)CAT_Attack );
  10271.  
  10272. if ( actor )
  10273. actor.SignalGameplayEvent('PersonalTauntAction');
  10274. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'TauntAction', -1.0, 4.5f, -1, 9999, true ); //reactionSystemSearch
  10275.  
  10276. OnCombatActionStart();
  10277.  
  10278. playerToTargetHeading = VecHeading( actor.GetWorldPosition() - GetWorldPosition() );
  10279.  
  10280. SetCustomRotation( 'Attack', playerToTargetHeading, 0.0f, 0.3f, false );
  10281.  
  10282. return true;
  10283. }
  10284.  
  10285. return false;
  10286. }
  10287.  
  10288. public function SendAttackReactionEvent()
  10289. {
  10290. var reactionName : name;
  10291.  
  10292. /*switch ( action )
  10293. {
  10294. case EBAT_LightAttack :
  10295. reactionName = 'AttackAction';
  10296. break;
  10297. case EBAT_HeavyAttack :
  10298. reactionName = 'AttackAction';
  10299. break;
  10300. case EBAT_SpecialAttack_Light :
  10301. reactionName = 'AttackAction';
  10302. break;
  10303. case EBAT_SpecialAttack_Heavy :
  10304. reactionName = 'AttackAction';
  10305. break;
  10306. case EBAT_Ciri_SpecialAttack :
  10307. reactionName = 'AttackAction';
  10308. break;
  10309. default:
  10310. return;
  10311. }*/
  10312.  
  10313. reactionName = 'AttackAction';
  10314.  
  10315. if ( IsNameValid(reactionName) )
  10316. {
  10317. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, reactionName, -1.0, 8.0f, -1, 5, true ); //reactionSystemSearch
  10318. }
  10319.  
  10320. // event for horse - trigger running away
  10321. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'outOfMyWay', -1.0, 2.0f, -1, 5, true ); //reactionSystemSearch
  10322. }
  10323.  
  10324. var forceCanAttackWhenNotInCombat : int; // 0 = NoForce, 1 = ForceWhenNoDisplayTarget 2 = ForceEvenWithDisplayTarget
  10325. public function SetForceCanAttackWhenNotInCombat( forceMode : int )
  10326. {
  10327. forceCanAttackWhenNotInCombat = forceMode;
  10328. }
  10329.  
  10330. public function CanAttackWhenNotInCombat( actionType : EBufferActionType, altCast : bool, out newTarget : CActor, optional target : CGameplayEntity ) : bool
  10331. {
  10332. var localTargets : array<CActor>;
  10333. var i, size : int;
  10334. var inputHeading : float;
  10335. var clearanceMin, clearanceMax : float;
  10336. var attackLength : float;
  10337. var attackAngle : float;
  10338. var npc : CNewNPC;
  10339. var canAttackTarget : CGameplayEntity;
  10340. var canAttackTargetActor : CActor;
  10341.  
  10342. if ( target )
  10343. canAttackTarget = target;
  10344. else if ( displayTarget && IsDisplayTargetTargetable() )
  10345. canAttackTarget = displayTarget;
  10346. else
  10347. canAttackTarget = slideTarget;
  10348.  
  10349. canAttackTargetActor = (CActor)canAttackTarget;
  10350.  
  10351. if ( forceCanAttackWhenNotInCombat == 2 )
  10352. return true;
  10353. else if ( forceCanAttackWhenNotInCombat == 1 && ( !canAttackTarget || !canAttackTargetActor.IsHuman() ) )
  10354. return true;
  10355.  
  10356. if ( actionType == EBAT_CastSign )
  10357. {
  10358. if ( thePlayer.GetEquippedSign() != ST_Quen && thePlayer.GetEquippedSign() != ST_Axii )
  10359. {
  10360. if ( CanUseSkill( S_Magic_s20 ) )
  10361. {
  10362. if ( thePlayer.GetEquippedSign() == ST_Aard )
  10363. attackLength = 6.f;
  10364. else if ( thePlayer.GetEquippedSign() == ST_Igni )
  10365. attackLength = 4.f;
  10366. else
  10367. attackLength = 6.f;
  10368. }
  10369. else
  10370. {
  10371. if ( thePlayer.GetEquippedSign() == ST_Aard )
  10372. attackLength = 9.f;
  10373. else if ( thePlayer.GetEquippedSign() == ST_Igni )
  10374. attackLength = 6.f;
  10375. else
  10376. attackLength = 6.f;
  10377. }
  10378.  
  10379. if ( altCast )
  10380. attackAngle = 180.f;
  10381. else
  10382. // sign cone angle / 2 with a bonus for safetey
  10383. attackAngle = 90.f;
  10384.  
  10385. if ( !lastAxisInputIsMovement )
  10386. inputHeading = VecHeading( theCamera.GetCameraDirection() );
  10387. else if ( lAxisReleasedAfterCounter )
  10388. inputHeading = GetHeading();
  10389. else
  10390. inputHeading = GetCombatActionHeading();
  10391.  
  10392. clearanceMin = 1.f;
  10393. clearanceMax = attackLength + 1.f;
  10394. }
  10395. else if ( thePlayer.GetEquippedSign() == ST_Axii )
  10396. {
  10397. npc = (CNewNPC)canAttackTarget;
  10398. if ( npc && npc.GetNPCType() == ENGT_Quest && !npc.HasTag(theGame.params.TAG_AXIIABLE_LOWER_CASE) && !npc.HasTag(theGame.params.TAG_AXIIABLE))
  10399. return false;
  10400. else if ( npc && npc.IsUsingHorse() )
  10401. return false;
  10402. else
  10403. return true;
  10404. }
  10405. else
  10406. return true;
  10407. }
  10408. else if ( actionType == EBAT_ItemUse )
  10409. {
  10410. attackLength = theGame.params.MAX_THROW_RANGE;
  10411. attackAngle = 90.f;
  10412.  
  10413. if ( thePlayer.lastAxisInputIsMovement )
  10414. inputHeading = GetCombatActionHeading();
  10415. else
  10416. inputHeading = VecHeading( theCamera.GetCameraDirection() );
  10417.  
  10418. clearanceMin = 0.8f;
  10419. clearanceMax = attackLength + 3.f;
  10420. }
  10421. else
  10422. {
  10423. if ( actionType == EBAT_SpecialAttack_Light || actionType == EBAT_SpecialAttack_Heavy )
  10424. {
  10425. attackLength = 1.9f;
  10426. attackAngle = 90.f;
  10427. }
  10428. else
  10429. {
  10430. if( thePlayer.GetCurrentMeleeWeaponType() == PW_Fists || thePlayer.GetCurrentMeleeWeaponType() == PW_None )
  10431. attackLength = 1.2f;
  10432. else
  10433. attackLength = 1.9f;
  10434.  
  10435. attackAngle = 90.f;
  10436. }
  10437.  
  10438. if ( lastAxisInputIsMovement )
  10439. inputHeading = GetCombatActionHeading();
  10440. else
  10441. inputHeading = VecHeading( theCamera.GetCameraDirection() );
  10442.  
  10443. clearanceMin = attackLength / 2.f;
  10444. clearanceMax = attackLength + 3.f;
  10445. }
  10446.  
  10447. //Use slideTarget first if it's NULL, then we try other npcs in the area
  10448. if ( canAttackTarget )
  10449. {
  10450. if ( ( canAttackTargetActor && canAttackTargetActor.IsHuman() ) || canAttackTargetActor.HasTag( 'softLock_Friendly' ) )
  10451. {
  10452. if ( ShouldPerformFriendlyAction( canAttackTargetActor, inputHeading, attackAngle, clearanceMin, clearanceMax ) )
  10453. {
  10454. SetSlideTarget( canAttackTargetActor );
  10455. newTarget = canAttackTargetActor;
  10456. return false;
  10457. }
  10458. }
  10459.  
  10460. //return true;
  10461. }
  10462.  
  10463. return true;
  10464.  
  10465. thePlayer.GetVisibleEnemies( localTargets );
  10466. size = localTargets.Size();
  10467.  
  10468. if ( size > 0 )
  10469. {
  10470. for ( i = size-1; i>=0; i-=1 )
  10471. {
  10472. /*
  10473. Andrzej: Geralt's friendly combat action - taunting actors with a sword or playing with Signs is set to work only for humans.
  10474. 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.
  10475. If you want Geralt to play friendly combat action when targeting monsters, add tag softLock_Friendly to monster's entity.
  10476. */
  10477. if ( !localTargets[i].IsHuman() && !localTargets[i].HasTag( 'softLock_Friendly' ) )
  10478. localTargets.Erase(i);
  10479. }
  10480. }
  10481.  
  10482. size = localTargets.Size();
  10483. if ( size > 0 )
  10484. {
  10485. for ( i = 0; i < localTargets.Size(); i += 1 )
  10486. {
  10487. if ( ShouldPerformFriendlyAction( localTargets[i], inputHeading, attackAngle, clearanceMin, clearanceMax ) )
  10488. {
  10489. SetSlideTarget( localTargets[i] );
  10490. newTarget = localTargets[i];
  10491. return false;
  10492. }
  10493. }
  10494. }
  10495.  
  10496. newTarget = NULL;
  10497.  
  10498. return true;
  10499. }
  10500.  
  10501. private function ShouldPerformFriendlyAction( actor : CActor, inputHeading, attackAngle, clearanceMin, clearanceMax : float ) : bool
  10502. {
  10503. var npc : CNewNPC;
  10504. var argh : float;
  10505. var playerToTargetDist : float;
  10506.  
  10507. npc = (CNewNPC)actor;
  10508.  
  10509. if ( npc &&
  10510. ( GetAttitudeBetween(thePlayer, npc) == AIA_Hostile || ( GetAttitudeBetween(thePlayer, npc) == AIA_Neutral && npc.GetNPCType() != ENGT_Guard ) ) )
  10511. {
  10512. }
  10513. else
  10514. {
  10515. playerToTargetDist = VecDistance( this.GetWorldPosition(), actor.PredictWorldPosition( 0.5f ) ); //actor.GetNearestPointInPersonalSpace( this.GetWorldPosition() ) );
  10516.  
  10517. argh = AbsF( AngleDistance( inputHeading, VecHeading( actor.GetWorldPosition() - thePlayer.GetWorldPosition() ) ) );
  10518.  
  10519. if ( AbsF( AngleDistance( inputHeading, VecHeading( actor.GetWorldPosition() - thePlayer.GetWorldPosition() ) ) ) < attackAngle )
  10520. {
  10521. if ( playerToTargetDist < clearanceMax )
  10522. {
  10523. return true;
  10524. }
  10525. }
  10526. else
  10527. {
  10528. if ( playerToTargetDist < clearanceMin )
  10529. {
  10530. return true;
  10531. }
  10532. }
  10533. }
  10534.  
  10535. return false;
  10536. }
  10537.  
  10538. ///////////////////////////////////////////////////////////////////////////
  10539. // HUD //#B
  10540. ///////////////////////////////////////////////////////////////////////////
  10541.  
  10542. public function GetHudMessagesSize() : int
  10543. {
  10544. return HudMessages.Size();
  10545. }
  10546.  
  10547. public function GetHudPendingMessage() : string
  10548. {
  10549. return HudMessages[0];
  10550. }
  10551.  
  10552. public function DisplayHudMessage( value : string ) : void
  10553. {
  10554. if (value == "")
  10555. {
  10556. return;
  10557. }
  10558.  
  10559. if( GetHudMessagesSize() > 0 )
  10560. {
  10561. if( HudMessages[HudMessages.Size()-1] == value )
  10562. {
  10563. return;
  10564. }
  10565. }
  10566. HudMessages.PushBack(value);
  10567. }
  10568.  
  10569. //hacks for review requests
  10570. private final function DisallowedActionDontShowHack(action : EInputActionBlock, isTimeLock : bool) : bool
  10571. {
  10572. var locks : array< SInputActionLock >;
  10573. var i : int;
  10574.  
  10575. //no info if we're trying to attack while staggered
  10576. 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)) )
  10577. {
  10578. return true;
  10579. }
  10580.  
  10581. //display message if trying to throw bombs while hypnotized by bies or blinded by water hag
  10582. if( action == EIAB_ThrowBomb && ( HasBuff( EET_Hypnotized ) || HasBuff( EET_Confusion ) ) )
  10583. {
  10584. return false;
  10585. }
  10586.  
  10587. //show if locked temporarily
  10588. if(isTimeLock)
  10589. return false;
  10590.  
  10591. //always show meditation message
  10592. if(action == EIAB_OpenMeditation)
  10593. return false;
  10594.  
  10595. //if there's at least one lock from quest or from location fine
  10596. locks = GetActionLocks(action);
  10597. for(i=0; i<locks.Size(); i+=1)
  10598. {
  10599. if(locks[i].isFromQuest || locks[i].isFromPlace)
  10600. return false;
  10601. }
  10602.  
  10603. if ( this.IsCurrentlyUsingItemL() )
  10604. {
  10605. if ( action == EIAB_HeavyAttacks || action == EIAB_Parry )
  10606. return false;
  10607. }
  10608.  
  10609. //otherwise we don't display locks
  10610. return true;
  10611. }
  10612.  
  10613. public final function DisplayActionDisallowedHudMessage(action : EInputActionBlock, optional isCombatLock : bool, optional isPlaceLock : bool, optional isTimeLock : bool, optional isDangerous : bool)
  10614. {
  10615. var lockType : name;
  10616.  
  10617. if(action != EIAB_Undefined && DisallowedActionDontShowHack(action, isTimeLock))
  10618. return;
  10619.  
  10620. //combat lock is strongest - overrides all
  10621. if(IsInCombat() && !IsActionCombat(action))
  10622. isCombatLock = true;
  10623.  
  10624. //if no specific lock set, check based on action
  10625. if(!isCombatLock && !isPlaceLock && !isTimeLock && action != EIAB_Undefined)
  10626. {
  10627. lockType = inputHandler.GetActionBlockedHudLockType(action);
  10628.  
  10629. if(lockType == 'combat')
  10630. isCombatLock = true;
  10631. else if(lockType == 'place')
  10632. isPlaceLock = true;
  10633. else if(lockType == 'time')
  10634. isTimeLock = true;
  10635. }
  10636.  
  10637. if(isDangerous)
  10638. {
  10639. DisplayHudMessage(GetLocStringByKeyExt( "message_meditation_too_dangerous" ));
  10640. }
  10641. else if(isCombatLock)
  10642. {
  10643. DisplayHudMessage(GetLocStringByKeyExt( "panel_hud_message_actionnotallowed_combat" ));
  10644. }
  10645. else if(isPlaceLock)
  10646. {
  10647. DisplayHudMessage(GetLocStringByKeyExt( "menu_cannot_perform_action_here" ));
  10648. }
  10649. else if(isTimeLock)
  10650. {
  10651. DisplayHudMessage(GetLocStringByKeyExt( "menu_cannot_perform_action_now" ));
  10652. }
  10653. }
  10654.  
  10655. //removes first or all instances of given message
  10656. public function RemoveHudMessageByString(msg : string, optional allQueuedInstances : bool)
  10657. {
  10658. var i, j : int;
  10659.  
  10660. for(i=0; i<HudMessages.Size(); i+=1)
  10661. {
  10662. if(HudMessages[i] == msg)
  10663. {
  10664. HudMessages.EraseFast(i);
  10665.  
  10666. if(!allQueuedInstances)
  10667. return;
  10668.  
  10669. break;
  10670. }
  10671. }
  10672.  
  10673. //if here then we want all remaining instances as well
  10674. for(j=HudMessages.Size()-1; j >= i; j-=1)
  10675. {
  10676. if(HudMessages[i] == msg)
  10677. {
  10678. HudMessages.EraseFast(i);
  10679. }
  10680. }
  10681. }
  10682.  
  10683. public function RemoveHudMessageByIndex(idx : int)
  10684. {
  10685. if(idx >= 0 && idx < HudMessages.Size())
  10686. HudMessages.Erase(idx);
  10687. }
  10688.  
  10689. function SetSettlementBlockCanter( valueAdd : int ) // #B
  10690. {
  10691. m_SettlementBlockCanter += valueAdd;
  10692. }
  10693.  
  10694. var countDownToStart : int;
  10695. default countDownToStart = 0;
  10696.  
  10697. function DisplayRaceStart( countDownSecondsNumber : int ) // #B
  10698. {
  10699. var i : int;
  10700. countDownToStart = countDownSecondsNumber;
  10701. for( i = countDownSecondsNumber; i > 0; i -= 1 )
  10702. {
  10703. DisplayHudMessage(IntToString(i));
  10704. }
  10705. DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_race_start"));
  10706. AddTimer('RaceCountdown',1,true);
  10707. }
  10708.  
  10709. timer function RaceCountdown(dt : float, id : int) // #B
  10710. {
  10711. var hud : CR4ScriptedHud;
  10712. var messageModule : CR4HudModuleMessage;
  10713.  
  10714. countDownToStart -= 1;
  10715. hud = (CR4ScriptedHud)theGame.GetHud();
  10716.  
  10717. if( hud )
  10718. {
  10719. messageModule = (CR4HudModuleMessage)hud.GetHudModule("MessageModule");
  10720. if( messageModule )
  10721. {
  10722. messageModule.OnMessageHidden(); // to force show next messeage
  10723. }
  10724. }
  10725.  
  10726. if( countDownToStart <= 0 )
  10727. {
  10728. RemoveTimer('RaceCountdown');
  10729. }
  10730. }
  10731.  
  10732. public function GetCountDownToStart() : int // #B
  10733. {
  10734. return countDownToStart;
  10735. }
  10736.  
  10737. public function HAXE3GetContainer() : W3Container //#B temp for E3
  10738. {
  10739. return HAXE3Container;
  10740. }
  10741.  
  10742. public function HAXE3SetContainer( container : W3Container) : void //#B temp for E3
  10743. {
  10744. HAXE3Container = container;
  10745. }
  10746.  
  10747. public function HAXE3GetAutoLoot() : bool //#B temp for E3
  10748. {
  10749. return HAXE3bAutoLoot;
  10750. }
  10751.  
  10752. public function HAXE3SetAutoLoot( value : bool ) : void //#B temp for E3
  10753. {
  10754. HAXE3bAutoLoot = value;
  10755. }
  10756.  
  10757. public function GetShowHud() : bool
  10758. {
  10759. return bShowHud;
  10760. }
  10761.  
  10762. public function SetShowHud( value : bool ) : void
  10763. {
  10764. bShowHud = value;
  10765. }
  10766.  
  10767. public function DisplayItemRewardNotification( itemName : name, optional quantity : int ) : void
  10768. {
  10769. var hud : CR4ScriptedHud;
  10770. hud = (CR4ScriptedHud)theGame.GetHud();
  10771. hud.OnItemRecivedDuringScene(itemName, quantity); // #B because our default currency are Crowns !!!
  10772. }
  10773.  
  10774. function IsNewQuest( questGuid : CGUID ) : bool // #B
  10775. {
  10776. var i : int;
  10777. for(i = 0; i < displayedQuestsGUID.Size(); i += 1 )
  10778. {
  10779. if( displayedQuestsGUID[i] == questGuid )
  10780. {
  10781. return false;
  10782. }
  10783. }
  10784. displayedQuestsGUID.PushBack(questGuid);
  10785. return true;
  10786. }
  10787.  
  10788. function GetRewardMultiplierData( rewardName : name ) : SRewardMultiplier
  10789. {
  10790. var defaultReward : SRewardMultiplier;
  10791. var i : int;
  10792.  
  10793. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10794. {
  10795. if( rewardsMultiplier[i].rewardName == rewardName )
  10796. {
  10797. return rewardsMultiplier[i];
  10798. }
  10799. }
  10800.  
  10801. defaultReward.rewardName = rewardName;
  10802. defaultReward.rewardMultiplier = 1.0;
  10803. defaultReward.isItemMultiplier = false;
  10804.  
  10805. return defaultReward;
  10806. }
  10807.  
  10808. function GetRewardMultiplier( rewardName : name ) : float // #B
  10809. {
  10810. var i : int;
  10811. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10812. {
  10813. if( rewardsMultiplier[i].rewardName == rewardName )
  10814. {
  10815. return rewardsMultiplier[i].rewardMultiplier;
  10816. }
  10817. }
  10818. return 1.0;
  10819. }
  10820.  
  10821. function GetRewardMultiplierExists( rewardName : name ) : bool // #B
  10822. {
  10823. var i : int;
  10824. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10825. {
  10826. if( rewardsMultiplier[i].rewardName == rewardName )
  10827. {
  10828. return true;
  10829. }
  10830. }
  10831. return false;
  10832. }
  10833.  
  10834. function SetRewardMultiplier( rewardName : name, value : float, optional isItemMultiplier : bool ) : void // #B
  10835. {
  10836. var i : int;
  10837. var rewardMultiplier : SRewardMultiplier;
  10838.  
  10839. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10840. {
  10841. if( rewardsMultiplier[i].rewardName == rewardName )
  10842. {
  10843. rewardsMultiplier[i].rewardMultiplier = value;
  10844. rewardsMultiplier[i].isItemMultiplier = isItemMultiplier;
  10845. return;
  10846. }
  10847. }
  10848.  
  10849. rewardMultiplier.rewardName = rewardName;
  10850. rewardMultiplier.rewardMultiplier = value;
  10851. rewardMultiplier.isItemMultiplier = isItemMultiplier;
  10852.  
  10853. rewardsMultiplier.PushBack(rewardMultiplier);
  10854. }
  10855.  
  10856. function RemoveRewardMultiplier( rewardName : name ) : void // #B
  10857. {
  10858. var i : int;
  10859. for(i = 0; i < rewardsMultiplier.Size(); i += 1 )
  10860. {
  10861. if( rewardsMultiplier[i].rewardName == rewardName )
  10862. {
  10863. rewardsMultiplier.Erase(i);
  10864. return;
  10865. }
  10866. }
  10867. }
  10868.  
  10869. ////////////////////////////////////////////////////////////////////////////////
  10870. //
  10871. // @Items
  10872. //
  10873. ////////////////////////////////////////////////////////////////////////////////
  10874.  
  10875. public final function TissueExtractorDischarge() : bool
  10876. {
  10877. var ids : array<SItemUniqueId>;
  10878. var chargesLeft, uses, curr, max, red, blue, green : int;
  10879. var i : int;
  10880. var text : string;
  10881.  
  10882. ids = thePlayer.inv.GetItemsByName( 'q705_tissue_extractor' );
  10883. if( ids.Size() == 0 )
  10884. {
  10885. return false;
  10886. }
  10887.  
  10888. curr = GetTissueExtractorChargesCurr();
  10889. max = GetTissueExtractorChargesMax();
  10890.  
  10891. if( curr >= max )
  10892. {
  10893. //calculate how many times the effect will work
  10894. uses = FloorF( ( ( float ) curr ) / ( ( float ) max ) );
  10895. chargesLeft = Max( 0, curr - uses * max );
  10896.  
  10897. //update charges
  10898. inv.SetItemModifierInt( ids[0], 'charges', chargesLeft );
  10899.  
  10900. //add items
  10901. blue = 0;
  10902. green = 0;
  10903. red = 0;
  10904. for( i=0; i<uses; i+=1 )
  10905. {
  10906. switch( RandRange( 3 ) )
  10907. {
  10908. case 0:
  10909. blue += 1;
  10910. break;
  10911. case 1:
  10912. green += 1;
  10913. break;
  10914. case 2:
  10915. red += 1;
  10916. }
  10917. }
  10918.  
  10919. text = GetLocStringByKeyExt( "message_q705_extractor_extracted" );
  10920.  
  10921. if( blue > 0 )
  10922. {
  10923. inv.AddAnItem( 'Greater mutagen blue', blue, false, true );
  10924. text += "<br/>" + blue + "x " + GetLocStringByKey( inv.GetItemLocalizedNameByName( 'Greater mutagen blue' ) );
  10925. }
  10926. if( green > 0 )
  10927. {
  10928. inv.AddAnItem( 'Greater mutagen green', green, false, true );
  10929. text += "<br/>" + green + "x " + GetLocStringByKey( inv.GetItemLocalizedNameByName( 'Greater mutagen green' ) );
  10930. }
  10931. if( red > 0 )
  10932. {
  10933. inv.AddAnItem( 'Greater mutagen red', red, false, true );
  10934. text += "<br/>" + red + "x " + GetLocStringByKey( inv.GetItemLocalizedNameByName( 'Greater mutagen red' ) );
  10935. }
  10936.  
  10937. //popup to inform player
  10938. theGame.GetGuiManager().ShowNotification( text );
  10939.  
  10940. //clear flag for UI notification when item becomes charged
  10941. inv.SetItemModifierInt( ids[0], 'ui_notified', 0 );
  10942.  
  10943. return true;
  10944. }
  10945. else
  10946. {
  10947. //popup to inform player
  10948. theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt( "message_q705_extractor_too_few_charges" ) );
  10949. }
  10950.  
  10951. return false;
  10952. }
  10953.  
  10954. public final function TissueExtractorIncCharge()
  10955. {
  10956. var ids : array<SItemUniqueId>;
  10957. var uiData : SInventoryItemUIData;
  10958. var curr : int;
  10959.  
  10960. ids = thePlayer.inv.GetItemsByName( 'q705_tissue_extractor' );
  10961. if( ids.Size() == 0 )
  10962. {
  10963. return;
  10964. }
  10965.  
  10966. curr = GetTissueExtractorChargesCurr() + 1;
  10967. inv.SetItemModifierInt( ids[0], 'charges', curr );
  10968.  
  10969. //mark as new in inventory
  10970. if( curr >= GetTissueExtractorChargesMax() )
  10971. {
  10972. uiData = inv.GetInventoryItemUIData( ids[0] );
  10973. uiData.isNew = true;
  10974. inv.SetInventoryItemUIData( ids[0], uiData );
  10975.  
  10976. //show popup ingame
  10977. if( inv.GetItemModifierInt( ids[0], 'ui_notified', 0 ) == 0 )
  10978. {
  10979. inv.SetItemModifierInt( ids[0], 'ui_notified', 1 );
  10980. theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt( "message_q705_extractor_charged" ), , true );
  10981. }
  10982. }
  10983. }
  10984.  
  10985. public final function GetTissueExtractorChargesCurr() : int
  10986. {
  10987. var ids : array<SItemUniqueId>;
  10988.  
  10989. ids = thePlayer.inv.GetItemsByName( 'q705_tissue_extractor' );
  10990. if( ids.Size() == 0 )
  10991. {
  10992. return 0;
  10993. }
  10994.  
  10995. return inv.GetItemModifierInt( ids[0], 'charges', 0 );
  10996. }
  10997.  
  10998. public final function GetTissueExtractorChargesMax() : int
  10999. {
  11000. var ids : array<SItemUniqueId>;
  11001. var val : SAbilityAttributeValue;
  11002.  
  11003. ids = thePlayer.inv.GetItemsByName( 'q705_tissue_extractor' );
  11004. if( ids.Size() == 0 )
  11005. {
  11006. return 0;
  11007. }
  11008.  
  11009. val = inv.GetItemAttributeValue( ids[0], 'maxCharges' );
  11010.  
  11011. return FloorF( val.valueBase );
  11012. }
  11013.  
  11014. public function GetEquippedSword(steel : bool) : SItemUniqueId;
  11015.  
  11016. public final function HasRequiredLevelToEquipItem(item : SItemUniqueId) : bool
  11017. {
  11018. if(HasBuff(EET_WolfHour))
  11019. {
  11020. if((inv.GetItemLevel(item) - 2) > GetLevel() )
  11021. return false;
  11022. }
  11023. else
  11024. {
  11025. if(inv.GetItemLevel(item) > GetLevel() )
  11026. return false;
  11027. }
  11028.  
  11029. return true;
  11030. }
  11031.  
  11032. public function SkillReduceBombAmmoBonus()
  11033. {
  11034. var i, ammo, maxAmmo : int;
  11035. var items : array<SItemUniqueId>;
  11036.  
  11037. items = inv.GetSingletonItems();
  11038.  
  11039. for(i=0; i<items.Size(); i+=1)
  11040. {
  11041. ammo = inv.GetItemModifierInt(items[i], 'ammo_current');
  11042.  
  11043. //if doesn't have infinite ammo
  11044. if(ammo > 0)
  11045. {
  11046. maxAmmo = inv.SingletonItemGetMaxAmmo(items[i]);
  11047.  
  11048. //if current ammo > max ammo, set current ammo to max ammo
  11049. if(ammo > maxAmmo)
  11050. {
  11051. inv.SetItemModifierInt(items[i], 'ammo_current', maxAmmo);
  11052. }
  11053. }
  11054. }
  11055. theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnAmmoChanged );
  11056. }
  11057.  
  11058. public function ConsumeItem( itemId : SItemUniqueId ) : bool
  11059. {
  11060. var params : SCustomEffectParams;
  11061. var buffs : array<SEffectInfo>;
  11062. var i : int;
  11063. var category : name;
  11064. var potionToxicity : float;
  11065.  
  11066. if(!inv.IsIdValid(itemId))
  11067. return false;
  11068.  
  11069. //apply buff
  11070. category = inv.GetItemCategory(itemId);
  11071. if(category == 'edibles' || inv.ItemHasTag(itemId, 'Drinks') || ( category == 'alchemy_ingredient' && inv.ItemHasTag(itemId, 'Alcohol')) )
  11072. {
  11073. //cannot eat in fistfights
  11074. if(IsFistFightMinigameEnabled())
  11075. {
  11076. DisplayActionDisallowedHudMessage(EIAB_Undefined, false, false, true);
  11077. return false;
  11078. }
  11079.  
  11080. //edible buff
  11081. inv.GetItemBuffs(itemId, buffs);
  11082.  
  11083. for(i=0; i<buffs.Size(); i+=1)
  11084. {
  11085. params.effectType = buffs[i].effectType;
  11086. params.creator = this;
  11087. params.sourceName = "edible";
  11088. params.customAbilityName = buffs[i].effectAbilityName;
  11089. AddEffectCustom(params);
  11090. }
  11091.  
  11092. //custom hack
  11093. if ( inv.ItemHasTag(itemId, 'Alcohol') )
  11094. {
  11095. potionToxicity = CalculateAttributeValue(inv.GetItemAttributeValue(itemId, 'toxicity'));
  11096. abilityManager.GainStat(BCS_Toxicity, potionToxicity );
  11097. AddEffectDefault(EET_Drunkenness, NULL, inv.GetItemName(itemId));
  11098. }
  11099. PlayItemConsumeSound( itemId );
  11100. }
  11101.  
  11102. if(inv.IsItemFood(itemId))
  11103. FactsAdd("consumed_food_cnt");
  11104.  
  11105. //remove item
  11106. if(!inv.ItemHasTag(itemId, theGame.params.TAG_INFINITE_USE) && !inv.RemoveItem(itemId))
  11107. {
  11108. LogAssert(false,"Failed to remove consumable item from player inventory!" + inv.GetItemName( itemId ) );
  11109. return false;
  11110. }
  11111.  
  11112. return true;
  11113. }
  11114.  
  11115. public function MountVehicle( vehicleEntity : CEntity, mountType : EVehicleMountType, optional vehicleSlot : EVehicleSlot )
  11116. {
  11117. var vehicle : CVehicleComponent;
  11118. vehicle = (CVehicleComponent)(vehicleEntity.GetComponentByClassName('CVehicleComponent'));
  11119.  
  11120. if ( vehicle )
  11121. vehicle.Mount( this, mountType, vehicleSlot );
  11122. }
  11123.  
  11124. public function DismountVehicle( vehicleEntity : CEntity, dismountType : EDismountType )
  11125. {
  11126. var vehicle : CVehicleComponent;
  11127. vehicle = (CVehicleComponent)(vehicleEntity.GetComponentByClassName('CVehicleComponent'));
  11128.  
  11129. if ( vehicle )
  11130. vehicle.IssueCommandToDismount( dismountType );
  11131. }
  11132.  
  11133. ////////////////
  11134. // @stamina @stats
  11135. ////////////////
  11136.  
  11137. protected function ShouldDrainStaminaWhileSprinting() : bool
  11138. {
  11139. if( HasBuff( EET_PolishedGenitals ) && !IsInCombat() && !IsThreatened() )
  11140. {
  11141. return false;
  11142. }
  11143.  
  11144. return super.ShouldDrainStaminaWhileSprinting();
  11145. }
  11146.  
  11147. //Returns true if actor has enough stamina to perform given action type (refer to DrainStamina for more info).
  11148. //If there is not enough stamina and actor is a player character then a insufficient stamina indication is shown on HUD
  11149. public function HasStaminaToUseAction(action : EStaminaActionType, optional abilityName : name, optional dt :float, optional multiplier : float) : bool
  11150. {
  11151. var cost : float;
  11152. var ret : bool;
  11153.  
  11154. ret = super.HasStaminaToUseAction(action, abilityName, dt, multiplier);
  11155.  
  11156. if(!ret)
  11157. {
  11158. SetCombatActionHeading( GetHeading() );
  11159.  
  11160. if(multiplier == 0)
  11161. multiplier = 1;
  11162.  
  11163. cost = multiplier * GetStaminaActionCost(action, abilityName, dt);
  11164. SetShowToLowStaminaIndication(cost);
  11165. }
  11166.  
  11167. return ret;
  11168. }
  11169.  
  11170. //since we cannot add timer on abilityManager...
  11171. timer function AbilityManager_FloorStaminaSegment(dt : float, id : int)
  11172. {
  11173. ((W3PlayerAbilityManager)abilityManager).FloorStaminaSegment();
  11174. }
  11175.  
  11176. public function DrainToxicity(amount : float )
  11177. {
  11178. if(abilityManager && abilityManager.IsInitialized() && IsAlive())
  11179. abilityManager.DrainToxicity(amount);
  11180. }
  11181.  
  11182. public function DrainFocus(amount : float )
  11183. {
  11184. if(abilityManager && abilityManager.IsInitialized() && IsAlive())
  11185. abilityManager.DrainFocus(amount);
  11186. }
  11187.  
  11188. public function GetOffenseStat():int
  11189. {
  11190. if(abilityManager && abilityManager.IsInitialized())
  11191. return ((W3PlayerAbilityManager)abilityManager).GetOffenseStat();
  11192.  
  11193. return 0;
  11194. }
  11195.  
  11196. public function GetDefenseStat():int
  11197. {
  11198. if(abilityManager && abilityManager.IsInitialized())
  11199. return ((W3PlayerAbilityManager)abilityManager).GetDefenseStat();
  11200.  
  11201. return 0;
  11202. }
  11203.  
  11204. public function GetSignsStat():float
  11205. {
  11206. if(abilityManager && abilityManager.IsInitialized())
  11207. return ((W3PlayerAbilityManager)abilityManager).GetSignsStat();
  11208.  
  11209. return 0;
  11210. }
  11211.  
  11212. ////////////////
  11213. // water
  11214. ////////////////
  11215.  
  11216. private var inWaterTrigger : bool;
  11217.  
  11218. event OnOceanTriggerEnter()
  11219. {
  11220. inWaterTrigger = true;
  11221. }
  11222.  
  11223. event OnOceanTriggerLeave()
  11224. {
  11225. inWaterTrigger = false;
  11226. }
  11227.  
  11228. public function IsInWaterTrigger() : bool
  11229. {
  11230. return inWaterTrigger;
  11231. }
  11232.  
  11233. //////////////////////////////////////////////////////////////////////////////////////////
  11234. // @Skills @Perks
  11235. //////////////////////////////////////////////////////////////////////////////////////////
  11236.  
  11237. public function GetSkillColor(skill : ESkill) : ESkillColor
  11238. {
  11239. if(abilityManager && abilityManager.IsInitialized())
  11240. return ((W3PlayerAbilityManager)abilityManager).GetSkillColor(skill);
  11241.  
  11242. return SC_None;
  11243. }
  11244.  
  11245. public function GetSkillSlotIndexFromSkill(skill : ESkill) : int
  11246. {
  11247. if(abilityManager && abilityManager.IsInitialized())
  11248. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIndexFromSkill(skill);
  11249.  
  11250. return -1;
  11251. }
  11252.  
  11253. public final function GetSkillSlotIndex(slotID : int, checkIfUnlocked : bool) : int
  11254. {
  11255. if(abilityManager && abilityManager.IsInitialized())
  11256. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIndex(slotID, checkIfUnlocked);
  11257.  
  11258. return -1;
  11259. }
  11260.  
  11261. public final function GetSkillSlotIDFromIndex(skillSlotIndex : int) : int
  11262. {
  11263. if(abilityManager && abilityManager.IsInitialized())
  11264. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIDFromIndex(skillSlotIndex);
  11265.  
  11266. return -1;
  11267. }
  11268.  
  11269. public function GetSkillSlotID(skill : ESkill) : int
  11270. {
  11271. if(abilityManager && abilityManager.IsInitialized())
  11272. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotID(skill);
  11273.  
  11274. return -1;
  11275. }
  11276.  
  11277. public function GetSkillGroupBonus(groupID : int) : name
  11278. {
  11279. if(abilityManager && abilityManager.IsInitialized())
  11280. return ((W3PlayerAbilityManager)abilityManager).GetGroupBonus(groupID);
  11281.  
  11282. return '';
  11283. }
  11284.  
  11285. public function GetGroupBonusCount(commonColor : ESkillColor,groupID : int) : int
  11286. {
  11287. if(abilityManager && abilityManager.IsInitialized())
  11288. return ((W3PlayerAbilityManager)abilityManager).GetSkillGroupColorCount(commonColor, groupID);
  11289.  
  11290. return 0;
  11291. }
  11292.  
  11293. public function GetMutagenSlotIDFromGroupID(groupID : int) : int
  11294. {
  11295. if(abilityManager && abilityManager.IsInitialized())
  11296. return ((W3PlayerAbilityManager)abilityManager).GetMutagenSlotIDFromGroupID(groupID);
  11297.  
  11298. return -1;
  11299. }
  11300.  
  11301. public function GetSkillLevel(skill : ESkill) : int
  11302. {
  11303. if(abilityManager && abilityManager.IsInitialized())
  11304. return ((W3PlayerAbilityManager)abilityManager).GetSkillLevel(skill);
  11305.  
  11306. return -1;
  11307. }
  11308.  
  11309. public function GetBoughtSkillLevel(skill : ESkill) : int
  11310. {
  11311. if(abilityManager && abilityManager.IsInitialized())
  11312. return ((W3PlayerAbilityManager)abilityManager).GetBoughtSkillLevel(skill);
  11313.  
  11314. return -1;
  11315. }
  11316.  
  11317. public function AddSkill(skill : ESkill, optional isTemporary : bool)
  11318. {
  11319. if(abilityManager && abilityManager.IsInitialized())
  11320. ((W3PlayerAbilityManager)abilityManager).AddSkill(skill, isTemporary);
  11321. }
  11322.  
  11323. public function AddMultipleSkills(skill : ESkill, optional number : int, optional isTemporary : bool)
  11324. {
  11325. var i : int;
  11326.  
  11327. if(number)
  11328. {
  11329. for( i=0; i<number; i+=1)
  11330. {
  11331. AddSkill(skill,isTemporary);
  11332. }
  11333. }
  11334. else
  11335. {
  11336. AddSkill(skill,isTemporary);
  11337. }
  11338. }
  11339.  
  11340. public function GetSkillAbilityName(skill : ESkill) : name
  11341. {
  11342. if(abilityManager && abilityManager.IsInitialized())
  11343. return ((W3PlayerAbilityManager)abilityManager).GetSkillAbilityName(skill);
  11344.  
  11345. return '';
  11346. }
  11347.  
  11348. public function HasStaminaToUseSkill(skill : ESkill, optional perSec : bool, optional signHack : bool) : bool
  11349. {
  11350. var ret : bool;
  11351. var cost : float;
  11352.  
  11353. cost = GetSkillStaminaUseCost(skill, perSec);
  11354.  
  11355. ret = ( CanUseSkill(skill) && (abilityManager.GetStat(BCS_Stamina, signHack) >= cost) );
  11356.  
  11357. //perk, using adrenaline instead of stamina when out of stamina
  11358. if(!ret && IsSkillSign(skill) && CanUseSkill(S_Perk_09) && GetStat(BCS_Focus) >= 1)
  11359. {
  11360. ret = true;
  11361. }
  11362.  
  11363. //Gryphon Armor Set Bonus 1 - next basic sign is being cast for free
  11364. if( !ret && IsSkillSign( skill ) && GetWitcherPlayer().HasBuff( EET_GryphonSetBonus ) )
  11365. {
  11366. ret = true;
  11367. }
  11368.  
  11369. if(!ret)
  11370. {
  11371. SetCombatActionHeading( GetHeading() );
  11372. SetShowToLowStaminaIndication(cost);
  11373. }
  11374.  
  11375. return ret;
  11376. }
  11377.  
  11378. protected function GetSkillStaminaUseCost(skill : ESkill, optional perSec : bool) : float
  11379. {
  11380. if(abilityManager && abilityManager.IsInitialized())
  11381. return ((W3PlayerAbilityManager)abilityManager).GetSkillStaminaUseCost(skill, perSec);
  11382.  
  11383. return 0;
  11384. }
  11385.  
  11386. //works for perks and bookperks as well
  11387. public function GetSkillAttributeValue(skill : ESkill, attributeName : name, addBaseCharAttribute : bool, addSkillModsAttribute : bool) : SAbilityAttributeValue
  11388. {
  11389. var null : SAbilityAttributeValue;
  11390.  
  11391. if(abilityManager && abilityManager.IsInitialized())
  11392. return abilityManager.GetSkillAttributeValue(SkillEnumToName(skill), attributeName, addBaseCharAttribute, addSkillModsAttribute);
  11393.  
  11394. return null;
  11395. }
  11396.  
  11397. public function GetSkillLocalisationKeyName(skill : ESkill) : string // #B
  11398. {
  11399. if(abilityManager && abilityManager.IsInitialized())
  11400. return ((W3PlayerAbilityManager)abilityManager).GetSkillLocalisationKeyName(skill);
  11401.  
  11402. return "";
  11403. }
  11404.  
  11405. public function GetSkillLocalisationKeyDescription(skill : ESkill) : string // #B
  11406. {
  11407. if(abilityManager && abilityManager.IsInitialized())
  11408. return ((W3PlayerAbilityManager)abilityManager).GetSkillLocalisationKeyDescription(skill);
  11409.  
  11410. return "";
  11411. }
  11412.  
  11413. public function GetSkillIconPath(skill : ESkill) : string // #B
  11414. {
  11415. if(abilityManager && abilityManager.IsInitialized())
  11416. return ((W3PlayerAbilityManager)abilityManager).GetSkillIconPath(skill);
  11417.  
  11418. return "";
  11419. }
  11420.  
  11421. public function HasLearnedSkill(skill : ESkill) : bool
  11422. {
  11423. if(abilityManager && abilityManager.IsInitialized())
  11424. return ((W3PlayerAbilityManager)abilityManager).HasLearnedSkill(skill);
  11425.  
  11426. return false;
  11427. }
  11428.  
  11429. public function IsSkillEquipped(skill : ESkill) : bool
  11430. {
  11431. if(abilityManager && abilityManager.IsInitialized())
  11432. return ((W3PlayerAbilityManager)abilityManager).IsSkillEquipped(skill);
  11433.  
  11434. return false;
  11435. }
  11436.  
  11437. public function CanUseSkill(skill : ESkill) : bool
  11438. {
  11439. if(abilityManager && abilityManager.IsInitialized())
  11440. return ((W3PlayerAbilityManager)abilityManager).CanUseSkill(skill);
  11441.  
  11442. return false;
  11443. }
  11444.  
  11445. public function CanLearnSkill(skill : ESkill) : bool //#B
  11446. {
  11447. if(abilityManager && abilityManager.IsInitialized())
  11448. return ((W3PlayerAbilityManager)abilityManager).CanLearnSkill(skill);
  11449.  
  11450. return false;
  11451. }
  11452.  
  11453. public function HasSpentEnoughPoints(skill : ESkill) : bool //#J
  11454. {
  11455. if(abilityManager && abilityManager.IsInitialized())
  11456. return ((W3PlayerAbilityManager)abilityManager).HasSpentEnoughPoints(skill);
  11457.  
  11458. return false;
  11459. }
  11460.  
  11461. public function PathPointsForSkillsPath(skill : ESkill) : int //#J
  11462. {
  11463. if(abilityManager && abilityManager.IsInitialized())
  11464. return ((W3PlayerAbilityManager)abilityManager).PathPointsSpentInSkillPathOfSkill(skill);
  11465.  
  11466. return -1;
  11467. }
  11468.  
  11469. public function GetPlayerSkills() : array<SSkill> // #B
  11470. {
  11471. var null : array<SSkill>;
  11472.  
  11473. if(abilityManager && abilityManager.IsInitialized())
  11474. return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkills();
  11475.  
  11476. return null;
  11477. }
  11478.  
  11479. public function GetPlayerSkill(s : ESkill) : SSkill // #B
  11480. {
  11481. var null : SSkill;
  11482.  
  11483. if(abilityManager && abilityManager.IsInitialized())
  11484. return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkill(s);
  11485.  
  11486. return null;
  11487. }
  11488.  
  11489. public function GetSkillSubPathType(s : ESkill) : ESkillSubPath // #B
  11490. {
  11491. if(abilityManager && abilityManager.IsInitialized())
  11492. return ((W3PlayerAbilityManager)abilityManager).GetSkillSubPathType(s);
  11493.  
  11494. return ESSP_NotSet;
  11495. }
  11496.  
  11497. public function GetSkillSlotsCount() : int
  11498. {
  11499. if(abilityManager && abilityManager.IsInitialized())
  11500. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotsCount();
  11501.  
  11502. return 0;
  11503. }
  11504.  
  11505. public function GetSkillSlots() : array<SSkillSlot>
  11506. {
  11507. var null : array<SSkillSlot>;
  11508.  
  11509. if(abilityManager && abilityManager.IsInitialized())
  11510. return ((W3PlayerAbilityManager)abilityManager).GetSkillSlots();
  11511.  
  11512. return null;
  11513. }
  11514.  
  11515. public function GetPlayerSkillMutagens() : array<SMutagenSlot>
  11516. {
  11517. var null : array<SMutagenSlot>;
  11518.  
  11519. if(abilityManager && abilityManager.IsInitialized())
  11520. return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkillMutagens();
  11521.  
  11522. return null;
  11523. }
  11524.  
  11525. // mutagens
  11526. //public function OnSkillMutagenEquipped()
  11527.  
  11528. public function BlockSkill(skill : ESkill, block : bool, optional cooldown : float) : bool
  11529. {
  11530. if(abilityManager && abilityManager.IsInitialized())
  11531. return ((W3PlayerAbilityManager)abilityManager).BlockSkill(skill, block, cooldown);
  11532.  
  11533. return false;
  11534. }
  11535.  
  11536. public function IsSkillBlocked(skill : ESkill) : bool
  11537. {
  11538. if(abilityManager && abilityManager.IsInitialized())
  11539. return ((W3PlayerAbilityManager)abilityManager).IsSkillBlocked(skill);
  11540.  
  11541. return false;
  11542. }
  11543.  
  11544. //returns true if succeeded
  11545. public function EquipSkill(skill : ESkill, slotID : int) : bool
  11546. {
  11547. var ret : bool;
  11548. var groupID : int;
  11549. var pam : W3PlayerAbilityManager;
  11550.  
  11551. if(abilityManager && abilityManager.IsInitialized())
  11552. {
  11553. pam = (W3PlayerAbilityManager)abilityManager;
  11554. ret = pam.EquipSkill(skill, slotID);
  11555. if(ret)
  11556. {
  11557. groupID = pam.GetSkillGroupIdFromSkillSlotId(slotID);
  11558. LogSkillColors("Equipped <<" + GetSkillColor(skill) + ">> skill <<" + skill + ">> to group <<" + groupID + ">>");
  11559. LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>");
  11560. LogSkillColors("");
  11561. }
  11562.  
  11563. return ret;
  11564. }
  11565.  
  11566. return false;
  11567. }
  11568.  
  11569. //returns true if succeeded
  11570. public function UnequipSkill(slotID : int) : bool
  11571. {
  11572. var ret : bool;
  11573. var groupID : int;
  11574. var skill : ESkill;
  11575. var pam : W3PlayerAbilityManager;
  11576.  
  11577. if(abilityManager && abilityManager.IsInitialized())
  11578. {
  11579. pam = (W3PlayerAbilityManager)abilityManager;
  11580. GetSkillOnSlot(slotID, skill);
  11581. ret = pam.UnequipSkill(slotID);
  11582. if(ret)
  11583. {
  11584. groupID = pam.GetSkillGroupIdFromSkillSlotId(slotID);
  11585. LogSkillColors("Unequipped <<" + GetSkillColor(skill) + ">> skill <<" + skill + ">> from group <<" + groupID + ">>");
  11586. LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>");
  11587. LogSkillColors("");
  11588. }
  11589. return ret;
  11590. }
  11591.  
  11592. return false;
  11593. }
  11594.  
  11595. //returns true if succeeded
  11596. public function GetSkillOnSlot(slotID : int, out skill : ESkill) : bool
  11597. {
  11598. if(abilityManager && abilityManager.IsInitialized())
  11599. return ((W3PlayerAbilityManager)abilityManager).GetSkillOnSlot(slotID, skill);
  11600.  
  11601. skill = S_SUndefined;
  11602. return false;
  11603. }
  11604.  
  11605. //returns random free skill slot (if any, otherwise -1)
  11606. public function GetFreeSkillSlot() : int
  11607. {
  11608. var i, size : int;
  11609. var skill : ESkill;
  11610.  
  11611. size = ((W3PlayerAbilityManager)abilityManager).GetSkillSlotsCount();
  11612. for(i=1; i<size; i+=1)
  11613. {
  11614. if(!GetSkillOnSlot(i, skill))
  11615. continue; //if slot locked
  11616.  
  11617. if(skill == S_SUndefined) //empty unlocked slot
  11618. return i;
  11619. }
  11620.  
  11621. return -1;
  11622. }
  11623.  
  11624. //////////////////
  11625. // @attacks
  11626. //////////////////
  11627.  
  11628. //performs an attack (mechanics wise) on given target and using given attack data
  11629. protected function Attack( hitTarget : CGameplayEntity, animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array<CActor>, attackAnimationName : name, hitTime : float, weaponEntity : CItemEntity)
  11630. {
  11631. var attackAction : W3Action_Attack;
  11632.  
  11633. if(!PrepareAttackAction(hitTarget, animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime, weaponEntity, attackAction))
  11634. return; //failed to create a valid attack action
  11635.  
  11636. if ( attackAction.IsParried() && ( ((CNewNPC)attackAction.victim).IsShielded(attackAction.attacker) || ((CNewNPC)attackAction.victim).SignalGameplayEventReturnInt('IsDefending',0) == 1 ) )
  11637. {
  11638. thePlayer.SetCanPlayHitAnim(true);
  11639. thePlayer.ReactToReflectedAttack(attackAction.victim);
  11640. }
  11641.  
  11642. theTelemetry.LogWithLabel( TE_FIGHT_PLAYER_ATTACKS, attackAction.GetAttackName() );
  11643.  
  11644. //process action
  11645. theGame.damageMgr.ProcessAction(attackAction);
  11646.  
  11647. delete attackAction;
  11648. }
  11649.  
  11650. public function IsHeavyAttack(attackName : name) : bool
  11651. {
  11652. var skill : ESkill;
  11653. var sup : bool;
  11654.  
  11655. sup = super.IsHeavyAttack(attackName);
  11656. if(sup)
  11657. return true;
  11658.  
  11659. if ( attackName == 'attack_heavy_special' )
  11660. return true;
  11661.  
  11662. skill = SkillNameToEnum(attackName);
  11663.  
  11664. return skill == S_Sword_2 || skill == S_Sword_s02;
  11665. }
  11666.  
  11667. public function IsLightAttack(attackName : name) : bool
  11668. {
  11669. var skill : ESkill;
  11670. var sup : bool;
  11671.  
  11672. sup = super.IsLightAttack(attackName);
  11673. if(sup)
  11674. return true;
  11675.  
  11676. skill = SkillNameToEnum(attackName);
  11677.  
  11678. return skill == S_Sword_1 || skill == S_Sword_s01;
  11679. }
  11680.  
  11681. public final function ProcessWeaponCollision()
  11682. {
  11683. var l_stateName : name;
  11684.  
  11685. var l_weaponPosition : Vector;
  11686. var l_weaponTipPos : Vector;
  11687. var l_collidingPosition : Vector;
  11688. var l_offset : Vector;
  11689. var l_normal : Vector;
  11690.  
  11691. var l_slotMatrix : Matrix;
  11692.  
  11693. var l_distance : float;
  11694.  
  11695. var l_materialName : name;
  11696. var l_hitComponent : CComponent;
  11697. var l_destructibleCmp : CDestructionSystemComponent;
  11698. var barrel : COilBarrelEntity;
  11699.  
  11700. //return;
  11701.  
  11702. if( isCurrentlyDodging )
  11703. return;
  11704.  
  11705. l_stateName = GetCurrentStateName();
  11706.  
  11707. if( !attackEventInProgress && l_stateName == 'CombatFists' )
  11708. return;
  11709.  
  11710. CalcEntitySlotMatrix('r_weapon', l_slotMatrix);
  11711.  
  11712. l_weaponPosition = MatrixGetTranslation( l_slotMatrix );
  11713.  
  11714. // Finding weapon's tip
  11715. switch( l_stateName )
  11716. {
  11717. case 'CombatFists':
  11718. l_offset = MatrixGetAxisX( l_slotMatrix );
  11719. l_offset = VecNormalize( l_offset ) * 0.25f;
  11720. break;
  11721. // sword
  11722. default:
  11723. l_offset = MatrixGetAxisZ( l_slotMatrix );
  11724. l_offset = VecNormalize( l_offset ) * 1.f;
  11725. break;
  11726. }
  11727.  
  11728. l_weaponTipPos = l_weaponPosition + l_offset;
  11729.  
  11730.  
  11731.  
  11732. if( !attackEventInProgress )
  11733. {
  11734. // If the weapon is not moving fast enough, do not play collision fx
  11735. if( m_LastWeaponTipPos == Vector ( 0, 0, 0 ) )
  11736. l_distance = 0;
  11737. else
  11738. l_distance = VecDistance( l_weaponTipPos, m_LastWeaponTipPos ) ;
  11739.  
  11740. //GetVisualDebug().AddText( 'LastWeaponTipText', "Last - dist: " + l_distance, m_LastWeaponTipPos, true, , Color( 249, 98, 158 ) );
  11741. //GetVisualDebug().AddArrow( 'OldDirectArrow', l_weaponPosition, m_LastWeaponTipPos , 0.8f, 0.1f, 0.2f, true, Color( 249, 98, 158 ) );
  11742.  
  11743. m_LastWeaponTipPos = l_weaponTipPos;
  11744. if( l_distance < 0.35f )
  11745. return;
  11746.  
  11747. }
  11748.  
  11749. /*GetVisualDebug().AddSphere( 'WeaponPosition', 0.1f, l_weaponPosition, true, Color( 249, 98, 158 ) );
  11750. GetVisualDebug().AddText( 'WeaponTipText', "Weapon Tip", l_weaponTipPos, true, , Color( 249, 98, 158 ) );
  11751. GetVisualDebug().AddArrow( 'CollisionArrow', l_weaponPosition, l_weaponTipPos , 0.8f, 0.1f, 0.2f, true, Color( 249, 98, 158 ) );*/
  11752.  
  11753. m_LastWeaponTipPos = l_weaponTipPos;
  11754.  
  11755. if ( !theGame.GetWorld().StaticTraceWithAdditionalInfo( l_weaponPosition, l_weaponTipPos, l_collidingPosition, l_normal, l_materialName, l_hitComponent, m_WeaponFXCollisionGroupNames ) )
  11756. {
  11757. // Test left fist
  11758. if( l_stateName == 'CombatFists' )
  11759. {
  11760. CalcEntitySlotMatrix('l_weapon', l_slotMatrix);
  11761. l_weaponPosition = MatrixGetTranslation( l_slotMatrix );
  11762. l_offset = MatrixGetAxisX( l_slotMatrix );
  11763. l_offset = VecNormalize( l_offset ) * 0.25f;
  11764. l_weaponTipPos = l_weaponPosition + l_offset;
  11765. if( !theGame.GetWorld().StaticTrace( l_weaponPosition, l_weaponTipPos, l_collidingPosition, l_normal, m_WeaponFXCollisionGroupNames ) )
  11766. {
  11767. return;
  11768. }
  11769. }
  11770. else
  11771. {
  11772. return;
  11773. }
  11774. }
  11775.  
  11776. if( !m_CollisionEffect )
  11777. {
  11778. m_CollisionEffect = theGame.CreateEntity( m_CollisionFxTemplate, l_collidingPosition, EulerAngles(0,0,0) );
  11779. }
  11780.  
  11781. m_CollisionEffect.Teleport( l_collidingPosition );
  11782.  
  11783. // Play hit effect
  11784. switch( l_stateName )
  11785. {
  11786. case 'CombatFists':
  11787. m_CollisionEffect.PlayEffect('fist');
  11788. break;
  11789. default:
  11790. // Optimisation because IsSwordWooden() is heavy (around 0.13 ms)
  11791. if( m_RefreshWeaponFXType )
  11792. {
  11793. m_PlayWoodenFX = IsSwordWooden();
  11794. m_RefreshWeaponFXType = false;
  11795. }
  11796.  
  11797. if( m_PlayWoodenFX )
  11798. {
  11799. m_CollisionEffect.PlayEffect('wood');
  11800. }
  11801. else
  11802. {
  11803. switch( l_materialName )
  11804. {
  11805. case 'wood_hollow':
  11806. case 'wood_debris':
  11807. case 'wood_solid':
  11808. m_CollisionEffect.PlayEffect('wood');
  11809. break;
  11810. case 'dirt_hard':
  11811. case 'dirt_soil':
  11812. case 'hay':
  11813. m_CollisionEffect.PlayEffect('fist');
  11814. break;
  11815. case 'stone_debris':
  11816. case 'stone_solid':
  11817. case 'clay_tile':
  11818. case 'gravel_large':
  11819. case 'gravel_small':
  11820. case 'metal':
  11821. case 'custom_sword':
  11822. m_CollisionEffect.PlayEffect('sparks');
  11823. break;
  11824. case 'flesh':
  11825. m_CollisionEffect.PlayEffect('blood');
  11826. break;
  11827. default:
  11828. m_CollisionEffect.PlayEffect('wood');
  11829. break;
  11830. }
  11831.  
  11832. }
  11833. break;
  11834. }
  11835.  
  11836. //don't ask...
  11837. if(l_hitComponent)
  11838. {
  11839. barrel = (COilBarrelEntity)l_hitComponent.GetEntity();
  11840. if(barrel)
  11841. {
  11842. barrel.OnFireHit(NULL); //sets barrel on fire so that it explodes in a few sec
  11843. return;
  11844. }
  11845. }
  11846.  
  11847. // Destroy destructibles
  11848. l_destructibleCmp = (CDestructionSystemComponent) l_hitComponent;
  11849. if( l_destructibleCmp && l_stateName != 'CombatFists' )
  11850. {
  11851. l_destructibleCmp.ApplyFracture();
  11852. }
  11853.  
  11854.  
  11855. //GetVisualDebug().AddText( 'collisionText', "Collision Here", l_collidingPosition, true, , Color( 249, 98, 158 ) );
  11856. }
  11857.  
  11858. public function ReactToReflectedAttack( target : CGameplayEntity)
  11859. {
  11860.  
  11861. var hp, dmg : float;
  11862. var action : W3DamageAction;
  11863.  
  11864. super.ReactToReflectedAttack(target);
  11865.  
  11866. if ( !((CNewNPC)target).IsShielded(this) )
  11867. {
  11868. action = new W3DamageAction in this;
  11869. action.Initialize(target,this,NULL,'',EHRT_Reflect,CPS_AttackPower,true,false,false,false);
  11870. action.AddEffectInfo(EET_Stagger);
  11871. action.SetProcessBuffsIfNoDamage(true);
  11872.  
  11873. theGame.damageMgr.ProcessAction( action );
  11874. delete action;
  11875. }
  11876.  
  11877. theGame.VibrateControllerLight();//player attack was reflected
  11878. }
  11879.  
  11880. //////////////////
  11881. // falling damage
  11882. //////////////////
  11883.  
  11884. //return false when not falling
  11885. function GetFallDist( out fallDist : float ) : bool
  11886. {
  11887. var fallDiff, jumpTotalDiff : float;
  11888.  
  11889. // Get the falling height
  11890. substateManager.m_SharedDataO.CalculateFallingHeights( fallDiff, jumpTotalDiff );
  11891.  
  11892. if ( fallDiff <= 0 )
  11893. return false;
  11894.  
  11895. fallDist = fallDiff;
  11896. return true;
  11897. }
  11898.  
  11899. function ApplyFallingDamage(heightDiff : float, optional reducing : bool) : float
  11900. {
  11901. var hpPerc : float;
  11902. var tut : STutorialMessage;
  11903.  
  11904. if ( IsSwimming() || FactsQuerySum("block_falling_damage") >= 1 )
  11905. return 0.0f;
  11906.  
  11907. hpPerc = super.ApplyFallingDamage( heightDiff, reducing );
  11908.  
  11909. if(hpPerc > 0)
  11910. {
  11911. theGame.VibrateControllerHard();//player falling damage
  11912.  
  11913. if(IsAlive())
  11914. {
  11915. if(ShouldProcessTutorial('TutorialFallingDamage'))
  11916. {
  11917. FactsSet( "tutorial_falling_damage", 1 );
  11918. }
  11919.  
  11920. if(FactsQuerySum("tutorial_falling_damage") > 1 && ShouldProcessTutorial('TutorialFallingRoll'))
  11921. {
  11922. //fill tutorial object data
  11923. tut.type = ETMT_Hint;
  11924. tut.tutorialScriptTag = 'TutorialFallingRoll';
  11925. tut.hintPositionType = ETHPT_DefaultGlobal;
  11926. tut.hintDurationType = ETHDT_Long;
  11927. tut.canBeShownInMenus = false;
  11928. tut.glossaryLink = false;
  11929. tut.markAsSeenOnShow = true;
  11930.  
  11931. //show tutorial
  11932. theGame.GetTutorialSystem().DisplayTutorial(tut);
  11933. }
  11934. }
  11935. }
  11936.  
  11937. return hpPerc;
  11938. }
  11939.  
  11940. //--------------------------------- STAMINA INDICATOR #B --------------------------------------
  11941.  
  11942. public function SetShowToLowStaminaIndication( value : float ) : void
  11943. {
  11944. fShowToLowStaminaIndication = value;
  11945. }
  11946.  
  11947. public function GetShowToLowStaminaIndication() : float
  11948. {
  11949. return fShowToLowStaminaIndication;
  11950. }
  11951.  
  11952. public final function IndicateTooLowAdrenaline()
  11953. {
  11954. SoundEvent("gui_no_adrenaline");
  11955. showTooLowAdrenaline = true;
  11956. }
  11957.  
  11958. /////////////////////////////////
  11959.  
  11960. protected function GotoCombatStateWithAction( initialAction : EInitialAction, optional initialBuff : CBaseGameplayEffect )
  11961. {
  11962. if ( this.GetCurrentActionType() == ActorAction_Exploration )
  11963. ActionCancelAll();
  11964.  
  11965. ((W3PlayerWitcherStateCombatFists)this.GetState('CombatFists')).SetupState( initialAction, initialBuff );
  11966. this.GotoState( 'CombatFists' );
  11967.  
  11968. }
  11969. ///////////////////////////////////////////////////////////////////////////////////////////
  11970. // COMBAT
  11971. public function IsThreat( actor : CActor, optional usePrecalcs : bool ) : bool
  11972. {
  11973. var npc : CNewNPC;
  11974. var dist : float;
  11975. var targetCapsuleHeight : float;
  11976. var isDistanceExpanded : bool;
  11977. var distanceToTarget : float;
  11978. var attitude : EAIAttitude;
  11979.  
  11980. if (!actor)
  11981. {
  11982. return false;
  11983. }
  11984.  
  11985. if ( finishableEnemiesList.Contains( actor ) )
  11986. {
  11987. return true;
  11988. }
  11989.  
  11990. if ( !actor.IsAlive() || actor.IsKnockedUnconscious() )
  11991. {
  11992. return false;
  11993. }
  11994.  
  11995. npc = (CNewNPC)actor;
  11996. if (npc && npc.IsHorse() )
  11997. {
  11998. return false;
  11999. }
  12000.  
  12001. if ( hostileEnemies.Contains( actor ) )
  12002. {
  12003. return true;
  12004. }
  12005.  
  12006. //MS: We add a tolerance to make geralt go to alertfar everytime he runs away from npc
  12007. if ( GetAttitudeBetween( this, actor ) == AIA_Hostile )
  12008. {
  12009. if ( usePrecalcs )
  12010. {
  12011. distanceToTarget = Distance2DBetweenCapsuleAndPoint( actor, this ) - targetingPrecalcs.playerRadius;
  12012. }
  12013. else
  12014. {
  12015. distanceToTarget = Distance2DBetweenCapsules( this, actor );
  12016. }
  12017.  
  12018. // shortDistance = findMoveTargetDist + 5.0f;
  12019. if ( distanceToTarget < findMoveTargetDist + 5.0f )
  12020. {
  12021. return true;
  12022. }
  12023.  
  12024. if ( actor.IsInCombat() || this.IsHardLockEnabled() )
  12025. {
  12026. targetCapsuleHeight = ( (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent() ).GetCapsuleHeight();
  12027. if ( targetCapsuleHeight >= 2.0f || npc.GetCurrentStance() == NS_Fly )
  12028. {
  12029. // expandedDistance = 40.f;
  12030. if ( distanceToTarget < 40.0f )
  12031. {
  12032. return true;
  12033. }
  12034. }
  12035. }
  12036. }
  12037.  
  12038. if ( actor.GetAttitudeGroup() == 'npc_charmed' )
  12039. {
  12040. if ( theGame.GetGlobalAttitude( GetBaseAttitudeGroup(), actor.GetBaseAttitudeGroup() ) == AIA_Hostile )
  12041. {
  12042. return true;
  12043. }
  12044. }
  12045.  
  12046. return false;
  12047. }
  12048.  
  12049. function SetBIsCombatActionAllowed ( flag : bool )
  12050. {
  12051. bIsCombatActionAllowed = flag;
  12052.  
  12053. if ( !flag )
  12054. {
  12055. SetBIsInCombatAction(true);
  12056. }
  12057. else
  12058. {
  12059. this.ProcessLAxisCaching();
  12060. //UnblockAction(EIAB_Interactions, 'InsideCombatAction' );
  12061. }
  12062.  
  12063. //LogChannel('combatActionAllowed', "Is SET TO: " + flag );
  12064. }
  12065.  
  12066. function GetBIsCombatActionAllowed() : bool
  12067. {
  12068. return bIsCombatActionAllowed;
  12069. }
  12070.  
  12071. function SetCombatAction( action : EBufferActionType )
  12072. {
  12073. currentCombatAction = action;
  12074. }
  12075.  
  12076. function GetCombatAction() : EBufferActionType
  12077. {
  12078. return currentCombatAction;
  12079. }
  12080.  
  12081. protected function WhenCombatActionIsFinished()
  12082. {
  12083. if(IsThrowingItem() || IsThrowingItemWithAim() )
  12084. {
  12085. if(inv.IsItemBomb(selectedItemId))
  12086. {
  12087. BombThrowAbort();
  12088. }
  12089. else
  12090. {
  12091. ThrowingAbort();
  12092. }
  12093. }
  12094.  
  12095. if ( this.GetCurrentStateName() != 'DismountHorse' )
  12096. OnRangedForceHolster( true );
  12097.  
  12098. //SetBehaviorVariable( 'combatActionType', (int)CAT_None2);
  12099. }
  12100.  
  12101. public function IsInCombatAction_Attack(): bool
  12102. {
  12103. if ( IsInCombatAction_NonSpecialAttack() || IsInCombatAction_SpecialAttack() )
  12104. return true;
  12105. else
  12106. return false;
  12107. }
  12108.  
  12109. public function IsInCombatAction_NonSpecialAttack(): bool
  12110. {
  12111. if ( IsInCombatAction() && ( GetCombatAction() == EBAT_LightAttack || GetCombatAction() == EBAT_HeavyAttack ) )
  12112. return true;
  12113. else
  12114. return false;
  12115. }
  12116.  
  12117. public function IsInSpecificCombatAction ( specificCombatAction : EBufferActionType ) : bool
  12118. {
  12119. if ( IsInCombatAction() && GetCombatAction() == specificCombatAction )
  12120. return true;
  12121. else
  12122. return false;
  12123. }
  12124.  
  12125. public function IsInRunAnimation() : bool
  12126. {
  12127. return isInRunAnimation;
  12128. }
  12129.  
  12130. //I need to call it after scene ends thats why it's public. PF
  12131. public function SetCombatIdleStance( stance : float )
  12132. {
  12133. SetBehaviorVariable( 'combatIdleStance', stance );
  12134. SetBehaviorVariable( 'CombatStanceForOverlay', stance );
  12135.  
  12136. if ( stance == 0.f )
  12137. LogChannel( 'ComboInput', "combatIdleStance = Left" );
  12138. else
  12139. LogChannel( 'ComboInput', "combatIdleStance = Right" );
  12140. }
  12141.  
  12142. public function GetCombatIdleStance() : float
  12143. {
  12144. // 0.f == Left
  12145. return GetBehaviorVariable( 'combatIdleStance' );
  12146. }
  12147.  
  12148. protected var isRotatingInPlace : bool;
  12149. event OnRotateInPlaceStart()
  12150. {
  12151. isRotatingInPlace = true;
  12152. }
  12153.  
  12154. event OnRotateInPlaceEnd()
  12155. {
  12156. isRotatingInPlace = false;
  12157. }
  12158.  
  12159. event OnFullyBlendedIdle()
  12160. {
  12161. if ( bLAxisReleased )
  12162. {
  12163. ResetRawPlayerHeading();
  12164. ResetCachedRawPlayerHeading();
  12165. defaultLocomotionController.ResetMoveDirection();
  12166. }
  12167. }
  12168.  
  12169. private var isInIdle : bool;
  12170.  
  12171. event OnPlayerIdleStart()
  12172. {
  12173. isInIdle = true;
  12174. }
  12175.  
  12176. event OnPlayerIdleEnd()
  12177. {
  12178. isInIdle = false;
  12179. }
  12180.  
  12181. public function IsInIdle() : bool
  12182. {
  12183. return isInIdle;
  12184. }
  12185.  
  12186. event OnRunLoopStart()
  12187. {
  12188. EnableRunCamera( true );
  12189. }
  12190.  
  12191. event OnRunLoopEnd()
  12192. {
  12193. EnableRunCamera( false );
  12194. }
  12195.  
  12196. event OnCombatActionStartBehgraph()
  12197. {
  12198. var action : EBufferActionType;
  12199. var cost, delay : float;
  12200.  
  12201. // Block saves
  12202. //theGame.CreateNoSaveLock( noSaveLockCombatActionName, noSaveLockCombatAction, true );
  12203.  
  12204. OnCombatActionStart();
  12205.  
  12206. action = PerformingCombatAction();
  12207. switch ( action )
  12208. {
  12209. case EBAT_LightAttack :
  12210. {
  12211. abilityManager.GetStaminaActionCost(ESAT_LightAttack, cost, delay);
  12212. } break;
  12213. case EBAT_HeavyAttack :
  12214. {
  12215. abilityManager.GetStaminaActionCost(ESAT_HeavyAttack, cost, delay);
  12216. } break;
  12217. case EBAT_ItemUse :
  12218. {
  12219. abilityManager.GetStaminaActionCost(ESAT_UsableItem, cost, delay);
  12220. } break;
  12221. case EBAT_Parry :
  12222. {
  12223. abilityManager.GetStaminaActionCost(ESAT_Parry, cost, delay);
  12224. } break;
  12225. case EBAT_Dodge :
  12226. {
  12227. abilityManager.GetStaminaActionCost(ESAT_Dodge, cost, delay);
  12228. } break;
  12229. case EBAT_Roll :
  12230. abilityManager.GetStaminaActionCost(ESAT_Roll, cost, delay);
  12231. break;
  12232. case EBAT_SpecialAttack_Light :
  12233. {
  12234. abilityManager.GetStaminaActionCost(ESAT_Ability, cost, delay, 0,0, GetSkillAbilityName(S_Sword_s01));
  12235. } break;
  12236. case EBAT_SpecialAttack_Heavy :
  12237. {
  12238. abilityManager.GetStaminaActionCost(ESAT_Ability, cost, delay, 0,0, GetSkillAbilityName(S_Sword_s02));
  12239. } break;
  12240. case EBAT_Roll :
  12241. {
  12242. abilityManager.GetStaminaActionCost(ESAT_Evade, cost, delay);
  12243. } break;
  12244. /*
  12245. case EBAT_Ciri_SpecialAttack :
  12246. {
  12247. cost = GetStaminaActionCost();
  12248. } break;
  12249. */
  12250. default :
  12251. ;
  12252. }
  12253.  
  12254. //Pause the stamina regen for as long as we're doing combat actions.
  12255. //Pause only once to avoid the pause counter from increasing with each lock
  12256. if( delay > 0 )
  12257. PauseStaminaRegen( 'InsideCombatAction' );
  12258. }
  12259.  
  12260. public function HolsterUsableItem() : bool
  12261. {
  12262. return holsterUsableItem;
  12263. }
  12264.  
  12265. private var isInGuardedState : bool;
  12266. public function IsInGuardedState() : bool
  12267. {
  12268. return isInGuardedState;
  12269. }
  12270.  
  12271. event OnGuardedStart()
  12272. {
  12273. isInParryOrCounter = true;
  12274. isInGuardedState = true;
  12275. }
  12276.  
  12277. event OnGuardedEnd()
  12278. {
  12279. isInParryOrCounter = false;
  12280. isInGuardedState = false;
  12281. }
  12282.  
  12283. private var restoreUsableItem : bool;
  12284. private var holsterUsableItem : bool;
  12285. event OnCombatActionStart()
  12286. {
  12287. //Block Actions
  12288. //BlockAction( EIAB_DrawWeapon, 'OnCombatActionStart' );
  12289. BlockAction( EIAB_UsableItem, 'OnCombatActionStart' );
  12290. BlockAction( EIAB_CallHorse, 'OnCombatActionStart' );
  12291.  
  12292. /*if ( !IsGuarded() )
  12293. SetParryTarget( NULL );*/
  12294.  
  12295. LogChannel('combatActionAllowed',"FALSE OnCombatActionStart");
  12296. SetBIsCombatActionAllowed( false );
  12297. SetBIsInputAllowed( false, 'OnCombatActionStart' );
  12298. //lastAxisInputIsMovement = true;
  12299.  
  12300. ClearFinishableEnemyList( 0.f, 0 );
  12301.  
  12302. bIsInHitAnim = false;
  12303.  
  12304. //Holster Crossbow if it's held
  12305. //if ( inv.IsItemCrossbow( inv.GetItemFromSlot( 'l_weapon' ) ) )//&& GetBehaviorVariable( 'combatActionType' ) != (int)CAT_Crossbow )
  12306. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' )
  12307. {
  12308. CleanCombatActionBuffer();
  12309. SetIsAimingCrossbow( false );
  12310. OnRangedForceHolster( false, true );
  12311. }
  12312.  
  12313. //Holster UsableItem if it's held
  12314. holsterUsableItem = false;
  12315. if ( thePlayer.IsHoldingItemInLHand() ) // && !thePlayer.IsUsableItemLBlocked() )
  12316. {
  12317. if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign )
  12318. holsterUsableItem = false;
  12319. else if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack )
  12320. {
  12321. if ( this.GetCurrentStateName() == 'CombatFists' )
  12322. holsterUsableItem = false;
  12323. }
  12324. }
  12325.  
  12326. if ( holsterUsableItem )
  12327. {
  12328. thePlayer.SetPlayerActionToRestore ( PATR_None );
  12329. thePlayer.OnUseSelectedItem( true );
  12330.  
  12331. restoreUsableItem = true;
  12332. }
  12333.  
  12334. //Stop Geralt from automatically attacking while in AttackApproach when Player performs a non-attack combat action
  12335. if ( GetBehaviorVariable( 'combatActionType' ) != (int)CAT_Attack && GetBehaviorVariable( 'combatActionType' ) != (int)CAT_PreAttack )
  12336. {
  12337. RemoveTimer( 'ProcessAttackTimer' );
  12338. RemoveTimer( 'AttackTimerEnd' );
  12339. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12340. }
  12341. else
  12342. {
  12343. //MS: Do not remove this!! The attack to idle transition states will not work correctly if you change weapon mid-attack.
  12344. BlockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12345. }
  12346.  
  12347. //GetMovingAgentComponent().SnapToNavigableSpace(true);
  12348. }
  12349.  
  12350. var isInParryOrCounter : bool;
  12351. event OnParryOrCounterStart()
  12352. {
  12353. isInParryOrCounter = true;
  12354. OnCombatActionStartBehgraph();
  12355. }
  12356.  
  12357. event OnParryOrCounterEnd()
  12358. {
  12359. isInParryOrCounter = false;
  12360. OnCombatActionEnd();
  12361. SetBIsInCombatAction( false );
  12362. }
  12363.  
  12364. //called when a combat action is completed (e.g. single hit in a combo sequence)
  12365. event OnCombatActionEnd()
  12366. {
  12367. var item : SItemUniqueId;
  12368. var combatActionType : float;
  12369.  
  12370. super.OnCombatActionEnd();
  12371.  
  12372.  
  12373. //Unblock Actions
  12374. BlockAllActions( 'OnCombatActionStart', false );
  12375.  
  12376. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12377.  
  12378. // failsafe
  12379. UnblockAction( EIAB_Movement, 'CombatActionFriendly' );
  12380.  
  12381. //why? this way after EACH attack you reset it - what's the point then?
  12382. //ResetUninterruptedHitsCount();
  12383.  
  12384. oTCameraOffset = 0.f;
  12385. oTCameraPitchOffset = 0.f;
  12386.  
  12387. //LogChannel('combatActionAllowed',"TRUE OnCombatActionEnd");
  12388. SetBIsCombatActionAllowed( true );
  12389. //reapply critical buff if any
  12390. //ReapplyCriticalBuff();
  12391. SetBIsInputAllowed( true, 'OnCombatActionEnd' );
  12392. SetCanPlayHitAnim( true );
  12393. EnableFindTarget( true );
  12394.  
  12395. //AK: commented out because it sets dodging flag to false right after dodging starts when we chain multiple dodges
  12396. //IsCurrentlyDodging returned false in the middle of dodge anim
  12397. //SetIsCurrentlyDodging( false );
  12398. SetFinisherVictim( NULL );
  12399.  
  12400. OnBlockAllCombatTickets( false );
  12401.  
  12402. LogStamina("CombatActionEnd");
  12403.  
  12404. //GetMovingAgentComponent().SnapToNavigableSpace(false);
  12405.  
  12406. SetAttackActionName('');
  12407. combatActionType = GetBehaviorVariable('combatActionType');
  12408.  
  12409. //clean-up after special attack heavy finishes
  12410. if(GetBehaviorVariable('combatActionType') == (int)CAT_SpecialAttack)
  12411. {
  12412. theGame.GetGameCamera().StopAnimation( 'camera_shake_loop_lvl1_1' );
  12413. OnSpecialAttackHeavyActionProcess();
  12414. }
  12415. // Do we need to interrupt?
  12416. substateManager.ReactToChanceToFallAndSlide();
  12417. }
  12418.  
  12419. event OnCombatActionFriendlyStart()
  12420. {
  12421. SetBIsInCombatActionFriendly(true);
  12422. BlockAction( EIAB_Movement, 'CombatActionFriendly', false, false, false );
  12423. OnCombatActionStart();
  12424. }
  12425.  
  12426. event OnCombatActionFriendlyEnd()
  12427. {
  12428. SetBIsInCombatActionFriendly(false);
  12429. UnblockAction( EIAB_Movement, 'CombatActionFriendly' );
  12430. OnCombatActionEnd();
  12431. SetBIsInCombatAction(false);
  12432. //RaiseForceEvent( 'ForceIdle' );
  12433. }
  12434.  
  12435. event OnHitStart()
  12436. {
  12437. var timeLeft : float;
  12438. var currentEffects : array<CBaseGameplayEffect>;
  12439. var none : SAbilityAttributeValue;
  12440.  
  12441. CancelHoldAttacks();
  12442. WhenCombatActionIsFinished();
  12443. if ( isInFinisher )
  12444. {
  12445. if ( finisherTarget )
  12446. ( (CNewNPC)finisherTarget ).SignalGameplayEvent( 'FinisherInterrupt' );
  12447. isInFinisher = false;
  12448. finisherTarget = NULL;
  12449. SetBIsCombatActionAllowed( true );
  12450. }
  12451.  
  12452. bIsInHitAnim = true;
  12453.  
  12454. OnCombatActionStart(); //"because it's needed"
  12455.  
  12456. //OnCombatActionStart pauses the regen and we don't want that
  12457. ResumeStaminaRegen( 'InsideCombatAction' );
  12458.  
  12459. if( GetHealthPercents() < 0.3f )
  12460. {
  12461. PlayBattleCry('BattleCryBadSituation', 0.10f, true );
  12462. }
  12463. else
  12464. {
  12465. PlayBattleCry('BattleCryBadSituation', 0.05f, true );
  12466. }
  12467. }
  12468.  
  12469. event OnHitStartSwimming()
  12470. {
  12471. OnRangedForceHolster( true, true, false );
  12472. }
  12473.  
  12474. private var finisherSaveLock : int;
  12475. event OnFinisherStart()
  12476. {
  12477. var currentEffects : array<CBaseGameplayEffect>;
  12478.  
  12479. theGame.CreateNoSaveLock("Finisher",finisherSaveLock,true,false);
  12480.  
  12481. isInFinisher = true;
  12482.  
  12483. finisherTarget = slideTarget;
  12484. OnCombatActionStart();
  12485.  
  12486. CancelHoldAttacks();
  12487.  
  12488. PlayFinisherCameraAnimation( theGame.GetSyncAnimManager().GetFinisherCameraAnimName() );
  12489. this.AddAnimEventCallback('SyncEvent','OnFinisherAnimEvent_SyncEvent');
  12490. SetImmortalityMode( AIM_Invulnerable, AIC_SyncedAnim );
  12491. }
  12492.  
  12493. public function IsPerformingFinisher() : bool
  12494. {
  12495. return isInFinisher;
  12496. }
  12497.  
  12498. private function PlayFinisherCameraAnimation( cameraAnimName : name )
  12499. {
  12500. var camera : CCustomCamera = theGame.GetGameCamera();
  12501. var animation : SCameraAnimationDefinition;
  12502.  
  12503. if( IsLastEnemyKilled() && theGame.GetWorld().NavigationCircleTest( this.GetWorldPosition(), 3.f ) )
  12504. {
  12505. camera.StopAnimation('camera_shake_hit_lvl3_1' );
  12506.  
  12507. animation.animation = cameraAnimName;
  12508. animation.priority = CAP_Highest;
  12509. animation.blendIn = 0.15f;
  12510. animation.blendOut = 1.0f;
  12511. animation.weight = 1.f;
  12512. animation.speed = 1.0f;
  12513. animation.reset = true;
  12514.  
  12515. camera.PlayAnimation( animation );
  12516. //thePlayer.AddTimer( 'RemoveFinisherCameraAnimationCheck', 0.01, true );
  12517.  
  12518. thePlayer.EnableManualCameraControl( false, 'Finisher' );
  12519. }
  12520. }
  12521.  
  12522. public function IsLastEnemyKilled() : bool
  12523. {
  12524. var tempMoveTargets : array<CActor>;
  12525.  
  12526. FindMoveTarget();
  12527. tempMoveTargets = GetMoveTargets();
  12528. if ( tempMoveTargets.Size() <= 0 || !thePlayer.IsThreat( tempMoveTargets[0] ) )
  12529. return true;
  12530.  
  12531. return false;
  12532. }
  12533.  
  12534. event OnFinisherAnimEvent_SyncEvent( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo )
  12535. {
  12536. if ( finisherTarget )
  12537. ( (CNewNPC)finisherTarget ).SignalGameplayEvent('FinisherKill');
  12538. finisherTarget = NULL;
  12539. }
  12540.  
  12541. event OnFinisherEnd()
  12542. {
  12543. isInFinisher = false;
  12544. finisherTarget = NULL;
  12545.  
  12546. theGame.ReleaseNoSaveLock(finisherSaveLock);
  12547.  
  12548. this.RemoveAnimEventCallback('SyncEvent');
  12549.  
  12550. //SetIsPerformingPhaseChangeAnimation( false ); // for eredin fight
  12551. SetImmortalityMode( AIM_None, AIC_SyncedAnim );
  12552. theGame.RemoveTimeScale( 'AnimEventSlomoMo' );
  12553. AddTimer( 'FinisherEndEnableCamera', 0.5f );
  12554. //OnBlockAllCombatTickets( false );
  12555. OnCombatActionEnd();
  12556. OnCombatActionEndComplete();
  12557. }
  12558.  
  12559. private timer function FinisherEndEnableCamera( dt : float, id : int )
  12560. {
  12561. thePlayer.EnableManualCameraControl( true, 'Finisher' );
  12562. }
  12563.  
  12564. public function SpawnFinisherBlood()
  12565. {
  12566. var weaponEntity : CEntity;
  12567. var weaponSlotMatrix : Matrix;
  12568. var bloodFxPos : Vector;
  12569. var bloodFxRot : EulerAngles;
  12570. var tempEntity : CEntity;
  12571.  
  12572. weaponEntity = this.GetInventory().GetItemEntityUnsafe( GetInventory().GetItemFromSlot('r_weapon') );
  12573. weaponEntity.CalcEntitySlotMatrix( 'blood_fx_point', weaponSlotMatrix );
  12574. bloodFxPos = MatrixGetTranslation( weaponSlotMatrix );
  12575. bloodFxRot = this.GetWorldRotation();//MatrixGetRotation( weaponSlotMatrix );
  12576. tempEntity = theGame.CreateEntity( (CEntityTemplate)LoadResource('finisher_blood'), bloodFxPos, bloodFxRot);
  12577. tempEntity.PlayEffect('crawl_blood');
  12578. }
  12579.  
  12580. //called when all combat actions have ended (e.g. whole combo)
  12581. event OnCombatActionEndComplete()
  12582. {
  12583. var buff : CBaseGameplayEffect;
  12584.  
  12585. buff = ChooseCurrentCriticalBuffForAnim();
  12586. SetCombatAction( EBAT_EMPTY );
  12587.  
  12588. //Unblock Actions what you wann
  12589. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart' );
  12590. UnblockAction( EIAB_OpenInventory, 'OnCombatActionStart' );
  12591. UnblockAction( EIAB_UsableItem, 'OnCombatActionStart' );
  12592.  
  12593. UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' );
  12594.  
  12595. SetUnpushableTarget( NULL );
  12596. SetBIsInCombatAction(false);
  12597. SetIsCurrentlyDodging(false);
  12598. SetMoveTargetChangeAllowed( true );
  12599. SetCanPlayHitAnim( true );
  12600.  
  12601. SetFinisherVictim( NULL );
  12602.  
  12603. this.RemoveBuffImmunity(EET_Burning, 'AnimEvent_RemoveBurning');
  12604.  
  12605. if ( rangedWeapon && rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' && !buff )
  12606. {
  12607. ClearCustomOrientationInfoStack();
  12608. SetSlideTarget( NULL );
  12609. }
  12610.  
  12611. UnblockAction( EIAB_Crossbow, 'OnForceHolster' );
  12612.  
  12613. specialAttackCamera = false;
  12614.  
  12615. bIsRollAllowed = false;
  12616.  
  12617. if ( bLAxisReleased )
  12618. {
  12619. ResetRawPlayerHeading();
  12620. ResetCachedRawPlayerHeading();
  12621. }
  12622.  
  12623. //reapply critical buff if any
  12624. ReapplyCriticalBuff();
  12625. SetBIsInputAllowed( true, 'OnCombatActionEndComplete' );
  12626.  
  12627. //stamina regen is paused as long as we are doing some combat actions
  12628. ResumeStaminaRegen( 'InsideCombatAction' );
  12629.  
  12630. bIsInHitAnim = false;
  12631.  
  12632. SetBIsCombatActionAllowed( true );
  12633.  
  12634. m_LastWeaponTipPos = Vector(0, 0, 0, 0 );
  12635.  
  12636. //free tickets
  12637. this.AddTimer('FreeTickets',3.f,false);
  12638.  
  12639. // remove save lock
  12640. //theGame.ReleaseNoSaveLockByName( noSaveLockCombatActionName );
  12641. }
  12642.  
  12643. event OnMovementFullyBlended()
  12644. {
  12645. SetBehaviorVariable( 'isPerformingSpecialAttack', 0.f );
  12646.  
  12647. if ( restoreUsableItem )
  12648. {
  12649. restoreUsableItem = false;
  12650. SetPlayerActionToRestore ( PATR_Default );
  12651. OnUseSelectedItem();
  12652. }
  12653. }
  12654.  
  12655. event OnCombatMovementStart()
  12656. {
  12657. SetCombatIdleStance( 1.f );
  12658. OnCombatActionEndComplete();
  12659. }
  12660.  
  12661. timer function FreeTickets( dt : float, id : int )
  12662. {
  12663. FreeTicketAtCombatTarget();
  12664. }
  12665.  
  12666.  
  12667. /*
  12668. These declarations are needed here only to call event with the same name inside combat state (there's no other way to call it!).
  12669. */
  12670. event OnGuardedReleased(){}
  12671. event OnPerformAttack( playerAttackType : name ){}
  12672. event OnPerformEvade( playerEvadeType : EPlayerEvadeType ){}
  12673. event OnInterruptAttack(){}
  12674. event OnPerformGuard(){}
  12675. event OnSpawnHorse(){}
  12676. event OnDismountActionScriptCallback(){}
  12677.  
  12678. event OnHorseSummonStart()
  12679. {
  12680. thePlayer.BlockAction(EIAB_CallHorse, 'HorseSummon');
  12681. thePlayer.BlockAction(EIAB_Signs, 'HorseSummon');
  12682. thePlayer.BlockAction(EIAB_Crossbow, 'HorseSummon');
  12683. thePlayer.BlockAction(EIAB_UsableItem, 'HorseSummon');
  12684. thePlayer.BlockAction(EIAB_ThrowBomb, 'HorseSummon');
  12685. thePlayer.BlockAction(EIAB_SwordAttack, 'HorseSummon');
  12686. thePlayer.BlockAction(EIAB_Jump, 'HorseSummon');
  12687. thePlayer.BlockAction(EIAB_Dodge, 'HorseSummon');
  12688. thePlayer.BlockAction(EIAB_LightAttacks, 'HorseSummon');
  12689. thePlayer.BlockAction(EIAB_HeavyAttacks, 'HorseSummon');
  12690. thePlayer.BlockAction(EIAB_SpecialAttackLight, 'HorseSummon');
  12691. thePlayer.BlockAction(EIAB_SpecialAttackHeavy, 'HorseSummon');
  12692.  
  12693. horseSummonTimeStamp = theGame.GetEngineTimeAsSeconds();
  12694. }
  12695.  
  12696. event OnHorseSummonStop()
  12697. {
  12698. thePlayer.BlockAllActions('HorseSummon',false);
  12699. }
  12700.  
  12701. /*
  12702. CombatAction events when on vehicles
  12703. */
  12704. event OnCombatActionStartVehicle( action : EVehicleCombatAction )
  12705. {
  12706. this.SetBIsCombatActionAllowed( false );
  12707.  
  12708. if ( action != EHCA_ShootCrossbow )
  12709. {
  12710. SetIsAimingCrossbow( false );
  12711. OnRangedForceHolster();
  12712. }
  12713. }
  12714.  
  12715. event OnCombatActionEndVehicle()
  12716. {
  12717. this.SetBIsCombatActionAllowed( true );
  12718. }
  12719.  
  12720. ////////////////////////////////////////////////////////////////////////////////////////////
  12721. /////////////////////////// @CRITICAL STATES /////////////////////////////////////////////
  12722. ////////////////////////////////////////////////////////////////////////////////////////////
  12723.  
  12724. protected function CriticalBuffInformBehavior(buff : CBaseGameplayEffect)
  12725. {
  12726. /*if ( this.GetCurrentStateName() == 'Exploration' || this.GetCurrentStateName() == 'AimThrow' )
  12727. GotoCombatStateWithAction( IA_CriticalState, buff );
  12728. else
  12729. {*/
  12730. if( !CanAnimationReactToCriticalState( buff ) )
  12731. {
  12732. return;
  12733. }
  12734.  
  12735. // if ( IsInCombatAction() )
  12736. // RaiseEvent('ForceBlendOut');
  12737.  
  12738. SetBehaviorVariable( 'CriticalStateType', (int)GetBuffCriticalType(buff) );
  12739. SetBehaviorVariable( 'bCriticalState', 1);
  12740.  
  12741. if(CriticalBuffUsesFullBodyAnim(buff))
  12742. RaiseEvent('CriticalState');
  12743.  
  12744. SetBehaviorVariable( 'IsInAir', (int)IsInAir());
  12745.  
  12746. LogCritical("Sending player critical state event for <<" + buff.GetEffectType() + ">>");
  12747.  
  12748. //}
  12749. }
  12750.  
  12751. private function CanAnimationReactToCriticalState( buff : CBaseGameplayEffect ) : bool
  12752. {
  12753. var buffCritical : W3CriticalEffect;
  12754. var buffCriticalDOT : W3CriticalDOTEffect;
  12755. var isHeavyCritical : bool;
  12756.  
  12757. isHeavyCritical = false;
  12758.  
  12759. // Find out if it is a heavy critical state
  12760. buffCritical = ( W3CriticalEffect ) buff;
  12761. if( buffCritical )
  12762. {
  12763. isHeavyCritical = buffCritical.explorationStateHandling == ECH_HandleNow;
  12764. }
  12765. else
  12766. {
  12767. buffCriticalDOT = ( W3CriticalDOTEffect ) buff;
  12768. if( buffCriticalDOT )
  12769. {
  12770. isHeavyCritical = buffCriticalDOT.explorationStateHandling == ECH_HandleNow;
  12771. }
  12772. }
  12773.  
  12774. // If it is not, we may skip it
  12775. if( !isHeavyCritical )
  12776. {
  12777. if( !CanReactToCriticalState() )
  12778. {
  12779. return false;
  12780. }
  12781. }
  12782.  
  12783. return true;
  12784. }
  12785.  
  12786. public function CanReactToCriticalState() : bool
  12787. {
  12788. return substateManager.CanReactToHardCriticalState();
  12789. }
  12790.  
  12791. event OnCriticalStateAnimStart()
  12792. {
  12793. var heading : float;
  12794. var newCritical : ECriticalStateType;
  12795. var newReqCS : CBaseGameplayEffect;
  12796.  
  12797. OnCombatActionEndComplete();
  12798.  
  12799. //abort throwing if super was processed properly
  12800. newReqCS = newRequestedCS;
  12801. if(super.OnCriticalStateAnimStart())
  12802. {
  12803. //WhenCombatActionIsFinished();
  12804. RemoveTimer( 'IsItemUseInputHeld' );
  12805. keepRequestingCriticalAnimStart = false;
  12806. CancelHoldAttacks();
  12807.  
  12808. //knockdown direction
  12809. // No knockdown when using a vehicule: the vehicule will handle the knock down logic
  12810. //PFTODO
  12811. //we need this for NPCs also (knockdown dir)
  12812. if(!IsUsingVehicle())
  12813. {
  12814. newCritical = GetBuffCriticalType(newReqCS);
  12815. if(newCritical == ECST_HeavyKnockdown
  12816. || newCritical == ECST_Knockdown
  12817. || newCritical == ECST_Stagger
  12818. || newCritical == ECST_Ragdoll
  12819. || newCritical == ECST_LongStagger )
  12820. {
  12821. if(newReqCS.GetCreator())
  12822. heading = VecHeading(newReqCS.GetCreator().GetWorldPosition() - GetWorldPosition());
  12823. else
  12824. heading = GetHeading();
  12825.  
  12826. //this.GetMovingAgentComponent().GetMovementAdjustor().CancelAll();
  12827. SetCustomRotation( 'Knockdown', heading, 2160.f, 0.1f, true );
  12828.  
  12829. if ( newCritical != ECST_Stagger && newCritical != ECST_LongStagger )
  12830. substateManager.ReactOnCriticalState( true );
  12831. }
  12832. }
  12833.  
  12834. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'CriticalEffectStart', -1, 30.0f, -1.f, -1, true ); //reactionSystemSearch
  12835. return true;
  12836. }
  12837.  
  12838. //SetBehaviorVariable( 'bCriticalStopped', 1);
  12839. return false;
  12840. }
  12841.  
  12842. /*
  12843. Called when new critical effect has started
  12844. This will interrupt current critical state
  12845.  
  12846. returns true if the effect got fired properly
  12847. */
  12848. public function StartCSAnim(buff : CBaseGameplayEffect) : bool
  12849. {
  12850. SetBehaviorVariable( 'bCriticalStopped', 0 );
  12851.  
  12852. if(super.StartCSAnim(buff))
  12853. {
  12854. if(!CriticalBuffUsesFullBodyAnim(buff))
  12855. {
  12856. OnCriticalStateAnimStart();
  12857. }
  12858.  
  12859. ResumeStaminaRegen( 'InsideCombatAction' );
  12860.  
  12861. keepRequestingCriticalAnimStart = true;
  12862. AddTimer('RequestCriticalAnimStart', 0, true);
  12863. //RequestCriticalAnimStart(0);
  12864.  
  12865. return true;
  12866. }
  12867.  
  12868. return false;
  12869. }
  12870.  
  12871. public function CriticalEffectAnimationInterrupted(reason : string) : bool
  12872. {
  12873. var ret : bool; //for debug
  12874.  
  12875. LogCriticalPlayer("R4Player.CriticalEffectAnimationInterrupted() - because: " + reason);
  12876.  
  12877. ret = super.CriticalEffectAnimationInterrupted(reason);
  12878.  
  12879. if(ret)
  12880. {
  12881. keepRequestingCriticalAnimStart = false;
  12882. }
  12883.  
  12884. substateManager.ReactOnCriticalState( false );
  12885.  
  12886. return ret;
  12887. }
  12888.  
  12889. public function CriticalStateAnimStopped(forceRemoveBuff : bool)
  12890. {
  12891. LogCriticalPlayer("R4Player.CriticalStateAnimStopped() - forced: " + forceRemoveBuff);
  12892.  
  12893. theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'RecoveredFromCriticalEffect', -1, 30.0f, -1.f, -1, true ); //reactionSystemSearch
  12894. super.CriticalStateAnimStopped(forceRemoveBuff);
  12895.  
  12896. substateManager.ReactOnCriticalState( false );
  12897. }
  12898.  
  12899. // keeps requesting (sending event) to enter critical states anim state in behavior
  12900. timer function RequestCriticalAnimStart(dt : float, id : int)
  12901. {
  12902. if(keepRequestingCriticalAnimStart)
  12903. {
  12904. if(newRequestedCS && newRequestedCS.GetDurationLeft() > 0)
  12905. {
  12906. CriticalBuffInformBehavior(newRequestedCS);
  12907. }
  12908. else
  12909. {
  12910. keepRequestingCriticalAnimStart = false;
  12911. RemoveTimer('RequestCriticalAnimStart');
  12912. }
  12913. }
  12914. else
  12915. {
  12916. RemoveTimer('RequestCriticalAnimStart');
  12917. }
  12918. }
  12919.  
  12920. event OnRagdollUpdate(progress : float)
  12921. {
  12922. //super.OnRagdollUpdate(progress);
  12923.  
  12924. SetIsInAir(progress == 0);
  12925. }
  12926.  
  12927. // getting from ragdoll after certain time has passed
  12928. event OnRagdollOnGround()
  12929. {
  12930. // try to getup immediately as currently when laying on ground we might be constantly switched between on ground and in air
  12931. TryToEndRagdollOnGround( 0.0f );
  12932. }
  12933.  
  12934. event OnRagdollInAir()
  12935. {
  12936. RemoveTimer('TryToEndRagdollOnGround');
  12937. }
  12938.  
  12939. event OnNoLongerInRagdoll()
  12940. {
  12941. RemoveTimer('TryToEndRagdollOnGround');
  12942. }
  12943.  
  12944. timer function TryToEndRagdollOnGround( td : float, optional id : int)
  12945. {
  12946. var critical : CBaseGameplayEffect;
  12947. var type : EEffectType;
  12948.  
  12949. critical = GetCurrentlyAnimatedCS();
  12950. if(critical)
  12951. {
  12952. type = critical.GetEffectType();
  12953. if(type == EET_Knockdown || type == EET_HeavyKnockdown || type == EET_Ragdoll)
  12954. {
  12955. // 2.5 seconds is not that long but this is not ragdoll simulator :)
  12956. if (critical.GetTimeActive() >= 2.5f)
  12957. {
  12958. SetIsInAir(false);
  12959. RequestCriticalAnimStop();
  12960. RemoveTimer('TryToEndRagdollOnGround');
  12961. }
  12962. else
  12963. {
  12964. AddTimer('TryToEndRagdollOnGround', 0.2f, true);
  12965. }
  12966. return;
  12967. }
  12968. }
  12969.  
  12970. // not in critical or type differs
  12971. RemoveTimer('TryToEndRagdollOnGround');
  12972. }
  12973.  
  12974. public function RequestCriticalAnimStop(optional dontSetCriticalToStopped : bool)
  12975. {
  12976. var buff : CBaseGameplayEffect;
  12977.  
  12978. buff = GetCurrentlyAnimatedCS();
  12979. if(buff && !CriticalBuffUsesFullBodyAnim(buff))
  12980. {
  12981. CriticalStateAnimStopped(false);
  12982. }
  12983.  
  12984. if(!buff || !CriticalBuffUsesFullBodyAnim(buff))
  12985. {
  12986. SetBehaviorVariable( 'bCriticalState', 0);
  12987. }
  12988.  
  12989. super.RequestCriticalAnimStop(dontSetCriticalToStopped);
  12990. }
  12991. ////////////////////////////////////////////////////////////////////////////////////////////
  12992. // @Buffs @Effects
  12993. ////////////////////////////////////////////////////////////////////////////////////////////
  12994.  
  12995. public function SimulateBuffTimePassing(simulatedTime : float)
  12996. {
  12997. effectManager.SimulateBuffTimePassing(simulatedTime);
  12998. }
  12999.  
  13000. public function AddEffectDefault(effectType : EEffectType, creat : CGameplayEntity, srcName : string, optional isSignEffect : bool) : EEffectInteract
  13001. {
  13002. var params : SCustomEffectParams;
  13003.  
  13004. /*
  13005. Welcome to the Ancient Pit. If you're here reading this then you're doomed...
  13006.  
  13007. You're probably asking why someone is overriding default effect durations with some custom arbitrary numbers...
  13008.  
  13009. The thuth is: noone remembers...
  13010.  
  13011. But we need this and you cannot remove it or shit will start falling apart.
  13012. */
  13013. if(effectType == EET_Stagger || effectType == EET_LongStagger || effectType == EET_Knockdown || effectType == EET_HeavyKnockdown)
  13014. {
  13015. params.effectType = effectType;
  13016. params.creator = creat;
  13017. params.sourceName = srcName;
  13018. params.isSignEffect = isSignEffect;
  13019.  
  13020. if ( effectType == EET_Stagger )
  13021. params.duration = 1.83;
  13022. else if ( effectType == EET_LongStagger )
  13023. params.duration = 4;
  13024. else if ( effectType == EET_Knockdown )
  13025. params.duration = 2.5;
  13026. else if ( effectType == EET_HeavyKnockdown )
  13027. params.duration = 4;
  13028.  
  13029. return super.AddEffectCustom(params);
  13030. }
  13031. else
  13032. {
  13033. return super.AddEffectDefault(effectType, creat, srcName, isSignEffect);
  13034. }
  13035. }
  13036.  
  13037.  
  13038. ////////////////////////////////////////////////////////////////////////////////////////////
  13039.  
  13040. //a cheat to ressurect player
  13041. public function CheatResurrect()
  13042. {
  13043. var items : array< SItemUniqueId >;
  13044. var i, size, itemLevel, maxPrice, itemPrice : int;
  13045. var itemToEquip : SItemUniqueId;
  13046.  
  13047. if(IsAlive())
  13048. return;
  13049.  
  13050.  
  13051. if ( !theGame.GetGuiManager().GetRootMenu() )
  13052. {
  13053. Log(" *** Call this function after DeathScreen appears *** ");
  13054. return;
  13055. }
  13056.  
  13057. SetAlive(true);
  13058.  
  13059. SetKinematic(true);
  13060.  
  13061. EnableFindTarget( true );
  13062. SetBehaviorVariable( 'Ragdoll_Weight', 0.f );
  13063. RaiseForceEvent( 'RecoverFromRagdoll' );
  13064. SetCanPlayHitAnim( true );
  13065. SetBehaviorVariable( 'CriticalStateType', (int)ECST_None );
  13066. GoToStateIfNew('Exploration');
  13067.  
  13068. ( (CDismembermentComponent)this.GetComponent( 'Dismemberment' ) ).ClearVisibleWound();
  13069.  
  13070. SetIsInAir(false); //might block getup from ragdol in knockdown
  13071.  
  13072. theInput.SetContext('Exploration');
  13073.  
  13074. ResetDeathType();
  13075.  
  13076. ForceUnlockAllInputActions(false);
  13077.  
  13078. theGame.CloseMenu('DeathScreenMenu');
  13079.  
  13080. //restore sounds
  13081. theSound.LeaveGameState(ESGS_Death);
  13082.  
  13083. //need to call stop/start functions, otherwise no auto HP regen, tox drain, etc. ever again
  13084. abilityManager.ForceSetStat(BCS_Vitality, GetStatMax(BCS_Vitality));
  13085. effectManager.StopVitalityRegen();
  13086. abilityManager.ForceSetStat( BCS_Air , 100.f );
  13087. effectManager.StopAirRegen();
  13088. abilityManager.ForceSetStat( BCS_Stamina , 100.f );
  13089. effectManager.StopStaminaRegen();
  13090. abilityManager.ForceSetStat( BCS_Toxicity , 0.f );
  13091. abilityManager.ForceSetStat( BCS_Focus , 0.f );
  13092. GetWitcherPlayer().UpdateEncumbrance();
  13093.  
  13094. //equip highest level sword in inventory that can be equipped
  13095. if ( !inv.IsThereItemOnSlot( EES_SteelSword ) )
  13096. {
  13097. items = inv.GetItemsByCategory( 'steelsword' );
  13098. }
  13099. else if ( !inv.IsThereItemOnSlot( EES_SilverSword ) )
  13100. {
  13101. items = inv.GetItemsByCategory( 'silversword' );
  13102. }
  13103.  
  13104. size = items.Size();
  13105. maxPrice = -1;
  13106. for ( i = 0; i < size; i += 1 )
  13107. {
  13108. itemPrice = inv.GetItemPrice(items[i]);
  13109. itemLevel = inv.GetItemLevel(items[i]);
  13110. if ( itemLevel <= GetLevel() && itemPrice > maxPrice )
  13111. {
  13112. maxPrice = itemPrice;
  13113. itemToEquip = items[i];
  13114. }
  13115. }
  13116. if( inv.IsIdValid( itemToEquip ) )
  13117. {
  13118. EquipItem( itemToEquip , , true );
  13119. }
  13120.  
  13121. theGame.ReleaseNoSaveLock(deathNoSaveLock);
  13122. }
  13123.  
  13124. ////////////////////////////////////////////////////////////////////////////////////////////
  13125.  
  13126. public function SetIsInsideInteraction(b : bool) {isInsideInteraction = b;}
  13127. public function IsInsideInteraction() : bool {return isInsideInteraction;}
  13128.  
  13129. public function SetIsInsideHorseInteraction( b : bool, horse : CEntity )
  13130. {
  13131. isInsideHorseInteraction = b;
  13132. horseInteractionSource = horse;
  13133. }
  13134. public function IsInsideHorseInteraction() : bool {return isInsideHorseInteraction;}
  13135.  
  13136.  
  13137. event OnInteractionActivationTest( interactionComponentName : string, activator : CEntity )
  13138. {
  13139. if ( interactionComponentName == "ClimbLadder" )
  13140. {
  13141. if( PlayerHasLadderExplorationReady() )
  13142. {
  13143. return true;
  13144. }
  13145. }
  13146.  
  13147. return false;
  13148. }
  13149.  
  13150. private function PlayerHasLadderExplorationReady() : bool
  13151. {
  13152. if( !substateManager.CanInteract() )
  13153. {
  13154. return false;
  13155. }
  13156.  
  13157. if( !substateManager.m_SharedDataO.HasValidLadderExploration() )
  13158. {
  13159. return false;
  13160. }
  13161.  
  13162. return true;
  13163. }
  13164.  
  13165. ////////////////////////////////////////////////////////////////////////////////////////////
  13166. ////////////////////////////// @COMBAT /////////////////////////////////////////////////
  13167. ////////////////////////////////////////////////////////////////////////////////////////////
  13168.  
  13169. public function SetGuarded(flag : bool)
  13170. {
  13171. super.SetGuarded(flag);
  13172.  
  13173. if(flag && FactsQuerySum("tut_fight_use_slomo") > 0)
  13174. {
  13175. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) );
  13176. FactsRemove("tut_fight_slomo_ON");
  13177. }
  13178. }
  13179.  
  13180.  
  13181. public function IsGuarded() : bool
  13182. {
  13183. return super.IsGuarded() && ( !rangedWeapon || rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' );
  13184. }
  13185. ////////////////////////////////////////////////////////////////////////////////////////////
  13186. ///////////////////// @THROWABLE @BOMBS @PETARDS @Usable ///////////////////////////////////
  13187. ////////////////////////////////////////////////////////////////////////////////////////////
  13188.  
  13189. public function GetSelectedItemId() : SItemUniqueId {return selectedItemId;}
  13190. public function ClearSelectedItemId() {selectedItemId = GetInvalidUniqueId();}
  13191.  
  13192. public function IsHoldingItemInLHand() : bool
  13193. {
  13194. return currentlyEquipedItemL != GetInvalidUniqueId();
  13195. }
  13196.  
  13197. public function GetCurrentlyUsedItemL () : W3UsableItem
  13198. {
  13199. return currentlyUsedItemL;
  13200. }
  13201.  
  13202. public function SetPlayerActionToRestore ( actionToRestoreType : EPlayerActionToRestore )
  13203. {
  13204. playerActionToRestore = actionToRestoreType;
  13205. }
  13206.  
  13207. public function IsCurrentlyUsingItemL () : bool
  13208. {
  13209. return currentlyUsingItem;
  13210. }
  13211.  
  13212. function BlockSlotsOnLItemUse ()
  13213. {
  13214. var slotsToBlock : array<name>;
  13215.  
  13216. slotsToBlock.PushBack( 'Slot1' );
  13217. slotsToBlock.PushBack( 'Slot2' );
  13218. slotsToBlock.PushBack( 'Slot3' );
  13219. slotsToBlock.PushBack( 'Slot4' );
  13220. slotsToBlock.PushBack( 'Slot5' );
  13221. slotsToBlock.PushBack( 'Yrden' );
  13222. slotsToBlock.PushBack( 'Quen' );
  13223. slotsToBlock.PushBack( 'Igni' );
  13224. slotsToBlock.PushBack( 'Axii' );
  13225. slotsToBlock.PushBack( 'Aard' );
  13226.  
  13227.  
  13228. EnableRadialSlotsWithSource ( false, slotsToBlock, 'usableItemL' );
  13229. }
  13230.  
  13231. function UnblockSlotsOnLItemUse ()
  13232. {
  13233. var slotsToBlock : array<name>;
  13234.  
  13235. slotsToBlock.PushBack( 'Slot1' );
  13236. slotsToBlock.PushBack( 'Slot2' );
  13237. slotsToBlock.PushBack( 'Slot3' );
  13238. slotsToBlock.PushBack( 'Slot4' );
  13239. slotsToBlock.PushBack( 'Slot5' );
  13240. slotsToBlock.PushBack( 'Yrden' );
  13241. slotsToBlock.PushBack( 'Quen' );
  13242. slotsToBlock.PushBack( 'Igni' );
  13243. slotsToBlock.PushBack( 'Axii' );
  13244. slotsToBlock.PushBack( 'Aard' );
  13245.  
  13246.  
  13247. EnableRadialSlotsWithSource ( true, slotsToBlock, 'usableItemL' );
  13248. }
  13249.  
  13250. function IsUsableItemLBlocked () : bool
  13251. {
  13252. return isUsableItemBlocked;
  13253. }
  13254. function HideUsableItem( optional force : bool )
  13255. {
  13256. if( currentlyEquipedItemL != GetInvalidUniqueId() )
  13257. {
  13258. if( force )
  13259. {
  13260. if( !RaiseForceEvent( 'ItemEndL' ) )
  13261. {
  13262.  
  13263. OnUsingItemsReset();
  13264. }
  13265. return;
  13266.  
  13267. }
  13268. RaiseEvent( 'ItemUseL' );
  13269. }
  13270. }
  13271. function ProcessUsableItemsTransition ( actionToRestore : EPlayerActionToRestore )
  13272. {
  13273. var category : name;
  13274. var signSkill : ESkill;
  13275.  
  13276. category = inv.GetItemCategory ( selectedItemId );
  13277. signSkill = SignEnumToSkillEnum( GetEquippedSign());
  13278.  
  13279. switch ( actionToRestore )
  13280. {
  13281. case PATR_None:
  13282. if ( currentlyUsedItemL )
  13283. {
  13284. inv.UnmountItem( currentlyEquipedItemL, true );
  13285. }
  13286. currentlyEquipedItemL = GetInvalidUniqueId();
  13287. return;
  13288.  
  13289. case PATR_Default:
  13290. if ( IsSlotQuickslot( inv.GetSlotForItemId ( selectedItemId )) && category == 'usable' && currentlyEquipedItemL != selectedItemId )
  13291. {
  13292. if ( currentlyUsedItemL )
  13293. {
  13294. inv.UnmountItem( currentlyEquipedItemL, true );
  13295. }
  13296. currentlyEquipedItemL = GetInvalidUniqueId();
  13297. OnUseSelectedItem();
  13298. return;
  13299. }
  13300. break;
  13301. case PATR_Crossbow:
  13302. if ( inv.IsItemCrossbow ( selectedItemId ) )
  13303. {
  13304. if ( currentlyUsedItemL )
  13305. {
  13306. inv.UnmountItem( currentlyEquipedItemL, true );
  13307. }
  13308. currentlyEquipedItemL = GetInvalidUniqueId();
  13309. SetIsAimingCrossbow( true );
  13310.  
  13311. if ( theInput.IsActionPressed( 'ThrowItem' ) )
  13312. SetupCombatAction( EBAT_ItemUse, BS_Pressed );
  13313. else
  13314. {
  13315. SetupCombatAction( EBAT_ItemUse, BS_Pressed );
  13316. SetupCombatAction( EBAT_ItemUse, BS_Released );
  13317. }
  13318. return;
  13319. }
  13320. break;
  13321. case PATR_CastSign:
  13322. if( signSkill != S_SUndefined && playerActionToRestore == PATR_CastSign )
  13323. {
  13324. if ( currentlyUsedItemL )
  13325. {
  13326. inv.UnmountItem( currentlyEquipedItemL, true );
  13327. }
  13328. currentlyEquipedItemL = GetInvalidUniqueId();
  13329.  
  13330. if( HasStaminaToUseSkill( signSkill, false ) )
  13331. {
  13332. if( GetInvalidUniqueId() != inv.GetItemFromSlot( 'l_weapon' ) )
  13333. PushCombatActionOnBuffer( EBAT_CastSign, BS_Pressed );
  13334. else
  13335. SetupCombatAction( EBAT_CastSign, BS_Pressed );
  13336. }
  13337. else
  13338. {
  13339. thePlayer.SoundEvent("gui_no_stamina");
  13340. }
  13341. return;
  13342. }
  13343. break;
  13344. case PATR_ThrowBomb:
  13345. if ( inv.IsItemBomb ( selectedItemId ) )
  13346. {
  13347. if ( currentlyUsedItemL )
  13348. {
  13349. inv.UnmountItem( currentlyEquipedItemL, true );
  13350. }
  13351. currentlyEquipedItemL = GetInvalidUniqueId();
  13352. PrepareToAttack();
  13353. SetupCombatAction( EBAT_ItemUse, BS_Pressed );
  13354. return;
  13355. }
  13356. break;
  13357. case PATR_CallHorse:
  13358. theGame.OnSpawnPlayerHorse();
  13359. break;
  13360. default:
  13361. if ( currentlyUsedItemL )
  13362. {
  13363. inv.UnmountItem( currentlyEquipedItemL, true );
  13364. }
  13365. currentlyEquipedItemL = GetInvalidUniqueId();
  13366. return;
  13367. }
  13368. if ( currentlyUsedItemL )
  13369. {
  13370. inv.UnmountItem( currentlyEquipedItemL, true );
  13371. }
  13372. currentlyEquipedItemL = GetInvalidUniqueId();
  13373. }
  13374.  
  13375. function GetUsableItemLtransitionAllowed () : bool
  13376. {
  13377. return isUsableItemLtransitionAllowed;
  13378. }
  13379.  
  13380. function SetUsableItemLtransitionAllowed ( isAllowed : bool)
  13381. {
  13382. isUsableItemLtransitionAllowed = isAllowed;
  13383. }
  13384.  
  13385. event OnItemUseLUnBlocked ()
  13386. {
  13387. if ( isUsableItemBlocked )
  13388. {
  13389. isUsableItemBlocked = false;
  13390. UnblockSlotsOnLItemUse ();
  13391. }
  13392. }
  13393.  
  13394. event OnItemUseLBlocked ()
  13395. {
  13396. if ( !isUsableItemBlocked )
  13397. {
  13398. isUsableItemBlocked = true;
  13399. BlockSlotsOnLItemUse ();
  13400. }
  13401. }
  13402.  
  13403. event OnUsingItemsReset()
  13404. {
  13405. if ( currentlyUsingItem )
  13406. {
  13407. OnItemUseLUnBlocked ();
  13408. OnUsingItemsComplete();
  13409. }
  13410. }
  13411. event OnUsingItemsComplete ()
  13412. {
  13413. if ( isUsableItemBlocked )
  13414. {
  13415. OnItemUseLUnBlocked ();
  13416. }
  13417. currentlyUsingItem = false;
  13418. if ( GetUsableItemLtransitionAllowed () )
  13419. {
  13420. ProcessUsableItemsTransition( playerActionToRestore );
  13421. }
  13422. else
  13423. {
  13424. if ( currentlyUsedItemL )
  13425. {
  13426. inv.UnmountItem( currentlyEquipedItemL, true );
  13427. }
  13428. currentlyEquipedItemL = GetInvalidUniqueId();
  13429. }
  13430.  
  13431. SetPlayerActionToRestore ( PATR_Default );
  13432. }
  13433.  
  13434. event OnUseSelectedItem( optional force : bool )
  13435. {
  13436. var category : name;
  13437. var itemEntity : W3UsableItem;
  13438.  
  13439. if ( isUsableItemBlocked && !force )
  13440. {
  13441. return false;
  13442. }
  13443. if ( IsCastingSign() )
  13444. return false;
  13445.  
  13446. if ( currentlyEquipedItemL != GetInvalidUniqueId() )
  13447. {
  13448. SetBehaviorVariable( 'SelectedItemL', (int)GetUsableItemTypeById( currentlyEquipedItemL ), true );
  13449. if ( force )
  13450. {
  13451. if ( RaiseEvent( 'ItemEndL' ) )
  13452. {
  13453. SetUsableItemLtransitionAllowed ( true );
  13454. return true;
  13455. }
  13456. }
  13457. else
  13458. {
  13459. if ( RaiseEvent( 'ItemUseL' ) )
  13460. {
  13461. SetUsableItemLtransitionAllowed ( true );
  13462. return true;
  13463. }
  13464. }
  13465. }
  13466. else
  13467. {
  13468. category = inv.GetItemCategory( selectedItemId );
  13469. if( category != 'usable' )
  13470. {
  13471. return false;
  13472. }
  13473. SetBehaviorVariable( 'SelectedItemL', (int)GetUsableItemTypeById( selectedItemId ), true );
  13474. if( RaiseEvent( 'ItemUseL' ) )
  13475. {
  13476. currentlyEquipedItemL = selectedItemId;
  13477. SetUsableItemLtransitionAllowed ( false );
  13478. currentlyUsingItem = true;
  13479.  
  13480. return true;
  13481. }
  13482. inv.UnmountItem( selectedItemId, true );
  13483. }
  13484. }
  13485.  
  13486. protected saved var currentlyUsingItem : bool;
  13487.  
  13488. public function ProcessUseSelectedItem( itemEntity : W3UsableItem, optional shouldCallOnUsed : bool )
  13489. {
  13490. currentlyUsedItemL = itemEntity;
  13491. DrainStamina(ESAT_UsableItem);
  13492.  
  13493. if ( shouldCallOnUsed )
  13494. {
  13495. currentlyUsedItemL.OnUsed( thePlayer );
  13496. }
  13497. }
  13498.  
  13499. function GetUsableItemTypeById ( itemId : SItemUniqueId ) : EUsableItemType
  13500. {
  13501. var itemName : name;
  13502.  
  13503. itemName = inv.GetItemName ( itemId );
  13504.  
  13505. return theGame.GetDefinitionsManager().GetUsableItemType ( itemName );
  13506.  
  13507. }
  13508.  
  13509. // Starts the 'WaitForItemSpawnAndProccesTask' task
  13510. public function StartWaitForItemSpawnAndProccesTask()
  13511. {
  13512. AddTimer( 'WaitForItemSpawnAndProccesTask', 0.001f, true,,,,true );
  13513. }
  13514.  
  13515. // Kills the 'WaitForItemSpawnAndProccesTask' task
  13516. public function KillWaitForItemSpawnAndProccesTask()
  13517. {
  13518. RemoveTimer ( 'WaitForItemSpawnAndProccesTask' );
  13519. }
  13520.  
  13521. // Informs the 'WaitForItemSpawnAndProccesTask' task, that selected item should be used ASAP.
  13522. // Flag will be reset by the task itself
  13523. public function AllowUseSelectedItem()
  13524. {
  13525. m_useSelectedItemIfSpawned = true;
  13526. }
  13527.  
  13528. // Task waits for inventory to created selected item. Item will be used ASAP as the task is allowed to do so.
  13529. // Right after that - it kills itself.
  13530. timer function WaitForItemSpawnAndProccesTask( timeDelta : float , id : int )
  13531. {
  13532. var itemEntity : W3UsableItem;
  13533. var canTaskBeKilled : bool;
  13534. canTaskBeKilled = false;
  13535.  
  13536. if ( IsCastingSign() )
  13537. {
  13538. return;
  13539. }
  13540.  
  13541. // selectad item is wrong!
  13542. if ( selectedItemId == GetInvalidUniqueId() )
  13543. {
  13544. canTaskBeKilled = true;
  13545. }
  13546.  
  13547. itemEntity = (W3UsableItem)inv.GetItemEntityUnsafe( selectedItemId );
  13548. if ( itemEntity && m_useSelectedItemIfSpawned )
  13549. {
  13550. // we have selected item and we are allowed to use it, so to it and kill itself.
  13551. canTaskBeKilled = true;
  13552. m_useSelectedItemIfSpawned = false; // reset flag
  13553. ProcessUseSelectedItem( itemEntity, true );
  13554. }
  13555.  
  13556. if ( canTaskBeKilled )
  13557. {
  13558. KillWaitForItemSpawnAndProccesTask();
  13559. }
  13560. }
  13561.  
  13562. event OnBombProjectileReleased()
  13563. {
  13564. ResetRawPlayerHeading();
  13565. UnblockAction(EIAB_ThrowBomb, 'BombThrow');
  13566. UnblockAction(EIAB_Crossbow, 'BombThrow');
  13567.  
  13568. if(GetCurrentStateName() == 'AimThrow')
  13569. PopState();
  13570.  
  13571. FactsAdd("ach_bomb", 1, 4 );
  13572. theGame.GetGamerProfile().CheckLearningTheRopes();
  13573. }
  13574.  
  13575. public function SetIsThrowingItemWithAim(b : bool)
  13576. {
  13577. isThrowingItemWithAim = b;
  13578. }
  13579.  
  13580. public function SetIsThrowingItem( flag : bool ) {isThrowingItem = flag;}
  13581. public function IsThrowingItem() : bool {return isThrowingItem;}
  13582. public function IsThrowingItemWithAim() : bool {return isThrowingItemWithAim;}
  13583. public function SetThrowHold(b : bool) {isThrowHoldPressed = b;}
  13584. public function IsThrowHold() : bool {return isThrowHoldPressed;}
  13585. public function SetIsAimingCrossbow( flag : bool ) {isAimingCrossbow = flag;}
  13586. public function GetIsAimingCrossbow() : bool {return isAimingCrossbow;}
  13587.  
  13588. event OnThrowAnimLeave()
  13589. {
  13590. var throwStage : EThrowStage;
  13591. var thrownEntity : CThrowable;
  13592.  
  13593. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  13594.  
  13595. if(thrownEntity && !thrownEntity.WasThrown())
  13596. {
  13597. throwStage = (int)GetBehaviorVariable( 'throwStage', (int)TS_Stop);
  13598. if(inv.IsItemBomb(selectedItemId))
  13599. {
  13600. BombThrowCleanUp();
  13601. }
  13602. else
  13603. {
  13604. ThrowingAbort();
  13605. }
  13606. }
  13607.  
  13608. thrownEntity = NULL;
  13609. SetIsThrowingItem( false );
  13610. SetIsThrowingItemWithAim( false );
  13611.  
  13612. this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' );
  13613. UnblockAction(EIAB_ThrowBomb, 'BombThrow');
  13614. UnblockAction(EIAB_Crossbow, 'BombThrow');
  13615. }
  13616.  
  13617. //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
  13618. protected function BombThrowStart()
  13619. {
  13620. var slideTargetActor : CActor;
  13621.  
  13622. BlockAction( EIAB_ThrowBomb, 'BombThrow' );
  13623. BlockAction(EIAB_Crossbow, 'BombThrow');
  13624.  
  13625. SetBehaviorVariable( 'throwStage', (int)TS_Start );
  13626. SetBehaviorVariable( 'combatActionType', (int)CAT_ItemThrow );
  13627.  
  13628. if ( slideTarget )
  13629. {
  13630. AddCustomOrientationTarget( OT_Actor, 'BombThrow' );
  13631.  
  13632. slideTargetActor = (CActor)( slideTarget );
  13633.  
  13634. //AK BOMB: moved rotation from anim event to scripts to prevent rotation to friendly and neutral npcs.
  13635. // removed the check after commenting out ProcessCanAttackWhenNotInCombatBomb
  13636. //if( !slideTargetActor || ( slideTargetActor && GetAttitudeBetween(this, slideTarget) == AIA_Hostile ) )
  13637. // SetCustomRotation( 'Throw', VecHeading( slideTarget.GetWorldPosition() - GetWorldPosition() ), 0.0f, 0.3f, false );
  13638. }
  13639. else
  13640. {
  13641. if ( lastAxisInputIsMovement )
  13642. AddCustomOrientationTarget( OT_Actor, 'BombThrow' );
  13643. else
  13644. AddCustomOrientationTarget( OT_Camera, 'BombThrow' );
  13645. }
  13646.  
  13647. UpdateLookAtTarget();
  13648. SetCustomRotation( 'Throw', VecHeading( this.GetLookAtPosition() - GetWorldPosition() ), 0.0f, 0.3f, false );
  13649.  
  13650. SetBehaviorVariable( 'itemType', (int)IT_Petard );
  13651.  
  13652. ProcessCanAttackWhenNotInCombatBomb();
  13653.  
  13654. if ( RaiseForceEvent('CombatAction') )
  13655. OnCombatActionStart();
  13656.  
  13657. //FIXME might be aborted afterwards and no bomb would be thrown actually
  13658. theTelemetry.LogWithLabel(TE_FIGHT_HERO_THROWS_BOMB, inv.GetItemName( selectedItemId ));
  13659. }
  13660.  
  13661. //from animation
  13662. event OnThrowAnimStart()
  13663. {
  13664. var itemId : SItemUniqueId;
  13665. var thrownEntity : CThrowable;
  13666. //Disable slots on radial menu
  13667. this.radialSlots.Clear();
  13668. GetWitcherPlayer().GetItemEquippedOnSlot(EES_Petard1, itemId );
  13669.  
  13670. if( GetSelectedItemId() == itemId )
  13671. {
  13672. this.radialSlots.PushBack( 'Slot2' );
  13673. }
  13674. else
  13675. {
  13676. this.radialSlots.PushBack( 'Slot1' );
  13677. }
  13678. this.radialSlots.PushBack( 'Slot3' );
  13679. this.radialSlots.PushBack( 'Slot4' );
  13680. this.radialSlots.PushBack( 'Slot5' );
  13681. this.EnableRadialSlotsWithSource( false, this.radialSlots, 'throwBomb' );
  13682.  
  13683. thrownEntity = (CThrowable)inv.GetDeploymentItemEntity( selectedItemId,,,true );
  13684. thrownEntity.Initialize( this, selectedItemId );
  13685. EntityHandleSet( thrownEntityHandle, thrownEntity );
  13686. SetIsThrowingItem( true );
  13687. }
  13688.  
  13689. public function BombThrowAbort()
  13690. {
  13691. BombThrowCleanUp();
  13692. UnblockAction( EIAB_ThrowBomb, 'BombThrow' );
  13693. UnblockAction(EIAB_Crossbow, 'BombThrow');
  13694. }
  13695.  
  13696. private function BombThrowCleanUp()
  13697. {
  13698. var throwStage : EThrowStage;
  13699. var thrownEntity : CThrowable;
  13700. var vehicle : CVehicleComponent;
  13701.  
  13702. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  13703.  
  13704. this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' );
  13705. throwStage = (int)GetBehaviorVariable( 'throwStage', (int)TS_Stop);
  13706.  
  13707. SetBehaviorVariable( 'throwStage', (int)TS_Stop );
  13708.  
  13709. if( GetCurrentStateName() == 'AimThrow')
  13710. {
  13711. PopState();
  13712. thrownEntity.StopAiming( true );
  13713. }
  13714. else if ( this.IsUsingHorse() )
  13715. {
  13716. vehicle = (CVehicleComponent)(GetUsedVehicle().GetComponentByClassName('CVehicleComponent'));
  13717. vehicle.GetUserCombatManager().OnForceItemActionAbort();
  13718. }
  13719.  
  13720. //if bomb was not detached yet (is not flying)
  13721. if(thrownEntity && !thrownEntity.WasThrown())
  13722. {
  13723. thrownEntity.BreakAttachment();
  13724. thrownEntity.Destroy();
  13725. }
  13726.  
  13727. thrownEntity = NULL;
  13728. SetIsThrowingItem( false );
  13729. SetIsThrowingItemWithAim( false );
  13730. RemoveCustomOrientationTarget( 'BombThrow' );
  13731. }
  13732.  
  13733. public function ProcessCanAttackWhenNotInCombatBomb()
  13734. {
  13735. var targets : array< CGameplayEntity >;
  13736. var temp, throwVector, throwFrom, throwTo, throwVectorU : Vector;
  13737. var temp_n : name;
  13738. var throwVecLen : float;
  13739. var component : CComponent;
  13740. /* //AK BOMB: keeping it just in case we need to bring it back
  13741. var impactRange : float;
  13742. var entities : array<CGameplayEntity>;
  13743. var ent : CEntity;
  13744. var actor : CActor;
  13745. var petard : W3Petard;
  13746. var vehicle : CEntity;
  13747. var slotMatrix : Matrix;
  13748. var isShootingFriendly : bool;
  13749.  
  13750.  
  13751. if ( thrownEntity )
  13752. {
  13753. petard = (W3Petard)( thrownEntity );
  13754.  
  13755. if ( !IsThreatened() )
  13756. {
  13757. if ( this.playerAiming.GetCurrentStateName() == 'Aiming' )
  13758. ent = playerAiming.GetSweptFriendly();
  13759. else
  13760. actor = (CActor)GetDisplayTarget();
  13761.  
  13762. if( ent || ( actor && actor.IsHuman() && !IsThreat( actor ) ) )
  13763. SetIsShootingFriendly( true );
  13764. else
  13765. SetIsShootingFriendly( false );
  13766. }
  13767. else
  13768. SetIsShootingFriendly( false );
  13769. }
  13770. else
  13771. SetIsShootingFriendly( false );
  13772. */
  13773.  
  13774. //Quest can lock bomb throwing to allow bombs to throw only at specific targets
  13775. if( FactsQuerySum( "BombThrowSpecificTargets" ) > 0 )
  13776. {
  13777. //more optimal but less accurate version
  13778. //FindGameplayEntitiesCloseToPoint( targets, playerAiming.GetThrowPosition(), 2.f, 20, 'BombThrowSpecificTarget' );
  13779. //SetIsShootingFriendly( targets.Size() == 0 );
  13780.  
  13781. //fun fact - without breaking all calculations into separate variables this code doesn't work...
  13782. throwFrom = playerAiming.GetThrowStartPosition();
  13783. throwTo = playerAiming.GetThrowPosition();
  13784. throwVector = throwTo - throwFrom;
  13785. throwVecLen = VecDistance( throwFrom, throwTo );
  13786. throwVectorU = throwVector / throwVecLen;
  13787. if( theGame.GetWorld().StaticTraceWithAdditionalInfo( throwFrom, throwTo + throwVectorU, temp, temp, temp_n, component ) && component && component.GetEntity().HasTag( 'BombThrowSpecificTarget' ) )
  13788. {
  13789. SetIsShootingFriendly( false );
  13790. }
  13791. else
  13792. {
  13793. SetIsShootingFriendly( true );
  13794. }
  13795. }
  13796. else if( FactsQuerySum( "BombThrowDisallowSpecificTargets" ) > 0 )
  13797. {
  13798. //fun fact - without breaking all calculations into separate variables this code doesn't work...
  13799. throwFrom = playerAiming.GetThrowStartPosition();
  13800. throwTo = playerAiming.GetThrowPosition();
  13801. throwVector = throwTo - throwFrom;
  13802. throwVecLen = VecDistance( throwFrom, throwTo );
  13803. throwVectorU = throwVector / throwVecLen;
  13804. if( theGame.GetWorld().StaticTraceWithAdditionalInfo( throwFrom, throwTo + throwVectorU, temp, temp, temp_n, component ) && component && component.GetEntity().HasTag( 'BombThrowDisallowedTarget' ) )
  13805. {
  13806. SetIsShootingFriendly( true );
  13807. }
  13808. else
  13809. {
  13810. SetIsShootingFriendly( false );
  13811. }
  13812. }
  13813. else
  13814. {
  13815. SetIsShootingFriendly( false );
  13816. }
  13817.  
  13818. SetBehaviorVariable( 'isShootingFriendly', (float)( GetIsShootingFriendly() ) );
  13819. }
  13820.  
  13821. public function SetIsShootingFriendly( flag : bool )
  13822. {
  13823. isShootingFriendly = flag;
  13824. }
  13825.  
  13826. public function GetIsShootingFriendly() : bool
  13827. {
  13828. return isShootingFriendly;
  13829. }
  13830.  
  13831. //only for usable items
  13832. protected function UsableItemStart()
  13833. {
  13834. var thrownEntity : CThrowable;
  13835.  
  13836. //this seems like bullshit but it's because usable items use the same code as throwing bombs and shooting crossbow
  13837. thrownEntity = (CThrowable)inv.GetDeploymentItemEntity( selectedItemId,,,true );
  13838. thrownEntity.Initialize( this, selectedItemId );
  13839. EntityHandleSet( thrownEntityHandle, thrownEntity );
  13840. SetBehaviorVariable( 'throwStage', (int)TS_Start );
  13841. SetIsThrowingItem( true );
  13842. SetBehaviorVariable( 'combatActionType', (int)CAT_ItemThrow );
  13843.  
  13844. if ( slideTarget )
  13845. {
  13846. AddCustomOrientationTarget( OT_Actor, 'UsableItems' );
  13847. }
  13848. else
  13849. {
  13850. if ( lastAxisInputIsMovement )
  13851. AddCustomOrientationTarget( OT_Actor, 'UsableItems' );
  13852. else
  13853. AddCustomOrientationTarget( OT_Camera, 'UsableItems' );
  13854. }
  13855.  
  13856. SetBehaviorVariable( 'itemType', (int)(-1) );
  13857.  
  13858. if ( RaiseForceEvent('CombatAction') )
  13859. OnCombatActionStart();
  13860. }
  13861.  
  13862. protected function BombThrowRelease()
  13863. {
  13864. var stateName : name;
  13865.  
  13866. stateName = playerAiming.GetCurrentStateName();
  13867. OnDelayOrientationChangeOff();
  13868.  
  13869. if( GetIsShootingFriendly() || ( FactsQuerySum( "BombThrowSpecificTargets" ) > 0 && stateName != 'Aiming' ) )
  13870. {
  13871. BombThrowAbort();
  13872. }
  13873. else
  13874. {
  13875. SetBehaviorVariable( 'throwStage', (int)TS_End );
  13876.  
  13877. if ( stateName == 'Aiming' )
  13878. {
  13879. SetCustomRotation( 'Throw', VecHeading( this.GetLookAtPosition() - GetWorldPosition() ), 0.0f, 0.2f, false );
  13880. }
  13881. }
  13882. }
  13883.  
  13884. protected function UsableItemRelease()
  13885. {
  13886. OnDelayOrientationChangeOff();
  13887. SetBehaviorVariable( 'throwStage', (int)TS_End );
  13888. RemoveCustomOrientationTarget( 'UsableItems' );
  13889. }
  13890.  
  13891. // Called when usable item use or crossbow shot was aborted (bombs use different function)
  13892. public function ThrowingAbort()
  13893. {
  13894. var thrownEntity : CThrowable;
  13895.  
  13896. thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle );
  13897.  
  13898. SetBehaviorVariable( 'throwStage', (int)TS_Stop );
  13899. RaiseEvent( 'actionStop' );
  13900.  
  13901. if( GetCurrentStateName() == 'AimThrow')
  13902. {
  13903. PopState();
  13904. thrownEntity.StopAiming( true );
  13905. }
  13906.  
  13907. //if bomb was not detached yet (is not flying)
  13908. if(thrownEntity && !thrownEntity.WasThrown())
  13909. {
  13910. thrownEntity.BreakAttachment();
  13911. thrownEntity.Destroy();
  13912. }
  13913. this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' );
  13914. }
  13915.  
  13916. public function CanSetupCombatAction_Throw() : bool
  13917. {
  13918. //if has item selected
  13919. if(!inv.IsIdValid( selectedItemId ))
  13920. return false;
  13921.  
  13922. //if not a throwable item
  13923. if(!inv.IsItemSingletonItem(selectedItemId))
  13924. return false;
  13925.  
  13926. //if input is not blocked
  13927. if(!GetBIsInputAllowed())
  13928. return false;
  13929.  
  13930. //if has ammo
  13931. if(inv.GetItemQuantity(GetSelectedItemId()) <= 0 && !inv.ItemHasTag(selectedItemId, theGame.params.TAG_INFINITE_AMMO))
  13932. return false;
  13933.  
  13934. //if action is not blocked or (HACK) we're in swimming
  13935. if(!inputHandler.IsActionAllowed(EIAB_ThrowBomb) && GetCurrentStateName() != 'Swimming')
  13936. return false;
  13937.  
  13938. return true;
  13939. }
  13940.  
  13941. public function GetThrownEntity() : CThrowable
  13942. {
  13943. return (CThrowable)EntityHandleGet( thrownEntityHandle );
  13944. }
  13945.  
  13946. // Crossbow events and functions
  13947. event OnWeaponWait() { rangedWeapon.OnWeaponWait(); }
  13948. event OnWeaponDrawStart() { rangedWeapon.OnWeaponDrawStart(); }
  13949. event OnWeaponReloadStart() { rangedWeapon.OnWeaponReloadStart(); }
  13950. event OnWeaponReloadEnd() { rangedWeapon.OnWeaponReloadEnd(); }
  13951. event OnWeaponAimStart() { rangedWeapon.OnWeaponAimStart(); }
  13952. event OnWeaponShootStart() { rangedWeapon.OnWeaponShootStart(); }
  13953. event OnWeaponShootEnd() { rangedWeapon.OnWeaponShootEnd(); }
  13954. event OnWeaponAimEnd() { rangedWeapon.OnWeaponAimEnd(); }
  13955. event OnWeaponHolsterStart() { rangedWeapon.OnWeaponHolsterStart(); }
  13956. event OnWeaponHolsterEnd() { rangedWeapon.OnWeaponHolsterEnd(); }
  13957. event OnWeaponToNormalTransStart() { rangedWeapon.OnWeaponToNormalTransStart(); }
  13958. event OnWeaponToNormalTransEnd() { rangedWeapon.OnWeaponToNormalTransEnd(); }
  13959.  
  13960. event OnEnableAimingMode( enable : bool )
  13961. {
  13962. if( !crossbowDontPopStateHack )
  13963. {
  13964. if ( enable )
  13965. PushState( 'AimThrow' );
  13966. else if ( GetCurrentStateName() == 'AimThrow' )
  13967. PopState();
  13968. }
  13969. }
  13970.  
  13971. event OnRangedForceHolster( optional forceUpperBodyAnim, instant, dropItem : bool )
  13972. {
  13973. if(rangedWeapon)
  13974. rangedWeapon.OnForceHolster( forceUpperBodyAnim, instant, dropItem );
  13975. }
  13976.  
  13977.  
  13978. public function IsCrossbowHeld() : bool
  13979. {
  13980. if (rangedWeapon)
  13981. return rangedWeapon.GetCurrentStateName() != 'State_WeaponWait';
  13982. return false;
  13983. }
  13984.  
  13985. // Tickets
  13986. event OnBlockAllCombatTickets( release : bool )
  13987. {
  13988. if (!release )
  13989. ((CR4PlayerStateCombat)GetState('Combat')).OnBlockAllCombatTickets(false);
  13990. }
  13991. event OnForceTicketUpdate() {}
  13992.  
  13993. ////////////////////////////////////////////////////////////////////////////////////////////
  13994. /////////////////////////// @ATTACKS /////////////////////////////////////////////
  13995. ////////////////////////////////////////////////////////////////////////////////////////////
  13996.  
  13997. /*script*/ event OnProcessActionPost(action : W3DamageAction)
  13998. {
  13999. var npc : CNewNPC;
  14000. var attackAction : W3Action_Attack;
  14001. var lifeLeech : float;
  14002.  
  14003. super.OnProcessActionPost(action);
  14004.  
  14005. attackAction = (W3Action_Attack)action;
  14006.  
  14007. if(attackAction)
  14008. {
  14009. npc = (CNewNPC)action.victim;
  14010.  
  14011. if(npc && npc.IsHuman() )
  14012. {
  14013. PlayBattleCry('BattleCryHumansHit', 0.05f );
  14014. }
  14015. else
  14016. {
  14017. PlayBattleCry('BattleCryMonstersHit', 0.05f );
  14018. }
  14019.  
  14020. if(attackAction.IsActionMelee())
  14021. {
  14022. //uninterrupted hits counting
  14023. IncreaseUninterruptedHitsCount();
  14024.  
  14025. //camera shake
  14026. if( IsLightAttack( attackAction.GetAttackName() ) )
  14027. {
  14028. GCameraShake(0.1, false, GetWorldPosition(), 10);
  14029. }
  14030.  
  14031. //Caretaker Shovel life steal
  14032. if(npc && inv.GetItemName(attackAction.GetWeaponId()) == 'PC Caretaker Shovel')
  14033. {
  14034. //inv.PlayItemEffect( items[i], 'stab_attack' );
  14035. lifeLeech = CalculateAttributeValue(inv.GetItemAttributeValue(attackAction.GetWeaponId() ,'lifesteal'));
  14036. if (npc.UsesVitality())
  14037. lifeLeech *= action.processedDmg.vitalityDamage;
  14038. else if (UsesEssence())
  14039. lifeLeech *= action.processedDmg.essenceDamage;
  14040. else
  14041. lifeLeech = 0;
  14042.  
  14043. if ( lifeLeech > 0 )
  14044. {
  14045. inv.PlayItemEffect( attackAction.GetWeaponId(), 'stab_attack' );
  14046. PlayEffect('drain_energy_caretaker_shovel');
  14047. GainStat(BCS_Vitality, lifeLeech);
  14048. }
  14049. }
  14050. }
  14051. }
  14052. }
  14053.  
  14054. public function SetHitReactTransScale(f : float) {hitReactTransScale = f;}
  14055. public function GetHitReactTransScale() : float
  14056. {
  14057. if ( ( (CNewNPC)slideTarget ).GetIsTranslationScaled() )
  14058. return hitReactTransScale;
  14059. else
  14060. return 1.f;
  14061. }
  14062.  
  14063. ////////////////////////////////////////////////////////////////////////////////////////////
  14064. /////////////////////////// @HORSE /////////////////////////////////////////////
  14065. ////////////////////////////////////////////////////////////////////////////////////////////
  14066.  
  14067. public function GetHorseWithInventory() : CNewNPC
  14068. {
  14069. return (CNewNPC)EntityHandleGet( horseWithInventory );
  14070. }
  14071. public function GetHorseCurrentlyMounted() : CNewNPC
  14072. {
  14073. return currentlyMountedHorse;
  14074. }
  14075. // Do not use outside of vehicle component
  14076. public function _SetHorseCurrentlyMounted( horse : CNewNPC )
  14077. {
  14078. currentlyMountedHorse = horse;
  14079. }
  14080.  
  14081. public function WasHorseRecentlySummoned() : bool
  14082. {
  14083. if ( horseSummonTimeStamp + 5.f > theGame.GetEngineTimeAsSeconds() )
  14084. return true;
  14085.  
  14086. return false;
  14087. }
  14088.  
  14089. private const var MOUNT_DISTANCE_CBT : float;
  14090. default MOUNT_DISTANCE_CBT = 3.0;
  14091.  
  14092. private const var MOUNT_ANGLE_CBT : float;
  14093. default MOUNT_ANGLE_CBT = 35.0;
  14094.  
  14095. private const var MOUNT_ANGLE_EXP : float;
  14096. default MOUNT_ANGLE_EXP = 45.0;
  14097.  
  14098. public function IsMountingHorseAllowed( optional alwaysAllowedInExploration : bool ) : bool
  14099. {
  14100. var angle : float;
  14101. var distance : float;
  14102.  
  14103. if( IsInsideHorseInteraction() )
  14104. {
  14105. angle = AngleDistance( thePlayer.rawPlayerHeading, VecHeading( thePlayer.horseInteractionSource.GetWorldPosition() - thePlayer.GetWorldPosition() ) );
  14106.  
  14107. if( thePlayer.IsInCombat() )
  14108. {
  14109. if( AbsF( angle ) < MOUNT_ANGLE_CBT )
  14110. {
  14111. distance = VecDistance( thePlayer.GetWorldPosition(), thePlayer.horseInteractionSource.GetWorldPosition() );
  14112.  
  14113. if( distance < MOUNT_DISTANCE_CBT )
  14114. {
  14115. return true;
  14116. }
  14117. else
  14118. {
  14119. return false;
  14120. }
  14121. }
  14122. else
  14123. {
  14124. return false;
  14125. }
  14126.  
  14127. }
  14128. else
  14129. {
  14130. if( alwaysAllowedInExploration )
  14131. {
  14132. return true;
  14133. }
  14134. else
  14135. {
  14136. if( AbsF( angle ) < MOUNT_ANGLE_EXP )
  14137. {
  14138. return true;
  14139. }
  14140. else
  14141. {
  14142. return false;
  14143. }
  14144. }
  14145. }
  14146. }
  14147. else
  14148. {
  14149. return false;
  14150. }
  14151. }
  14152.  
  14153. public function FollowActor( actor : CActor )
  14154. {
  14155. var l_aiTreeDecorator : CAIPlayerActionDecorator;
  14156. var l_aiTree_onFoot : CAIFollowSideBySideAction;
  14157. var l_aiTree_onHorse : CAIRiderFollowSideBySideAction;
  14158. var l_success : bool = false;
  14159.  
  14160. actor.AddTag( 'playerFollowing' );
  14161.  
  14162. if( thePlayer.IsUsingHorse() )
  14163. {
  14164. l_aiTree_onHorse = new CAIRiderFollowSideBySideAction in this;
  14165. l_aiTree_onHorse.OnCreated();
  14166.  
  14167. l_aiTree_onHorse.params.targetTag = 'playerFollowing';
  14168. }
  14169. else
  14170. {
  14171. l_aiTree_onFoot = new CAIFollowSideBySideAction in this;
  14172. l_aiTree_onFoot.OnCreated();
  14173.  
  14174. l_aiTree_onFoot.params.targetTag = 'playerFollowing';
  14175. }
  14176.  
  14177. l_aiTreeDecorator = new CAIPlayerActionDecorator in this;
  14178. l_aiTreeDecorator.OnCreated();
  14179. l_aiTreeDecorator.interruptOnInput = false;
  14180.  
  14181. if( thePlayer.IsUsingHorse() )
  14182. l_aiTreeDecorator.scriptedAction = l_aiTree_onHorse;
  14183. else
  14184. l_aiTreeDecorator.scriptedAction = l_aiTree_onFoot;
  14185.  
  14186. if( l_aiTreeDecorator )
  14187. l_success = ForceAIBehavior( l_aiTreeDecorator, BTAP_Emergency );
  14188. else if( thePlayer.IsUsingHorse() )
  14189. l_success = ForceAIBehavior( l_aiTree_onHorse, BTAP_Emergency );
  14190. else
  14191. l_success = ForceAIBehavior( l_aiTree_onFoot, BTAP_Emergency );
  14192.  
  14193. if ( l_success )
  14194. {
  14195. GetMovingAgentComponent().SetGameplayRelativeMoveSpeed( 0.0f );
  14196. }
  14197. }
  14198.  
  14199. public function SetCanFollowNpc( val : bool, actor : CActor ) { canFollowNpc = val; actorToFollow = actor; }
  14200. public function CanFollowNpc() : bool { return canFollowNpc; }
  14201. public function GetActorToFollow() : CActor { return actorToFollow; }
  14202.  
  14203. /*public function SetIsFollowing( val : bool )
  14204. {
  14205. isFollowing = val;
  14206.  
  14207. if( val )
  14208. followingStartTime = theGame.GetEngineTimeAsSeconds();
  14209. else
  14210. followingStartTime = 0.0;
  14211. }
  14212. public function GetFollowingStartTime() : float { return followingStartTime; }
  14213. public function IsFollowing() : bool { return isFollowing; }
  14214.  
  14215. timer function ResetIsFollowing( td : float, id : int )
  14216. {
  14217. isFollowing = false;
  14218. }*/
  14219.  
  14220. ////////////////////////////////////////////////////////////////////////////////////////////
  14221. ///////////////////// @SWIMMING ////////////////////////////////////////////////////////
  14222. ////////////////////////////////////////////////////////////////////////////////////////////
  14223.  
  14224. public function SetIsSwimming ( toggle : bool )
  14225. {
  14226. if( isSwimming != toggle )
  14227. {
  14228. thePlayer.substateManager.SetBehaviorParamBool( 'isSwimmingForOverlay', toggle );
  14229. isSwimming = toggle;
  14230. }
  14231. }
  14232. //public function IsSwimming () : bool { return isSwimming; }
  14233.  
  14234. ////////////////////////////////////////////////////////////////////////////////////////////
  14235. /////////////////////////// @DURABILITY //////////////////////////////////////////////////
  14236. ////////////////////////////////////////////////////////////////////////////////////////////
  14237.  
  14238. //returns true if repaired
  14239. public function RepairItemUsingConsumable(item, consumable : SItemUniqueId) : bool
  14240. {
  14241. var curr, max, repairValue, itemValue, repairBonus, newDurability : float;
  14242.  
  14243. //basic check
  14244. if(!inv.IsIdValid(item) || !inv.IsIdValid(consumable) || !inv.HasItemDurability(item))
  14245. return false;
  14246.  
  14247. curr = inv.GetItemDurability(item);
  14248. max = inv.GetItemMaxDurability(item);
  14249.  
  14250. //check durability level
  14251. if(curr > max)
  14252. return false;
  14253.  
  14254. //check consumable type
  14255. if( (inv.IsItemAnyArmor(item) && inv.ItemHasTag(consumable, theGame.params.TAG_REPAIR_CONSUMABLE_ARMOR)) ||
  14256. (inv.IsItemSilverSwordUsableByPlayer(item) && inv.ItemHasTag(consumable, theGame.params.TAG_REPAIR_CONSUMABLE_SILVER)) ||
  14257. (inv.IsItemSteelSwordUsableByPlayer(item) && inv.ItemHasTag(consumable, theGame.params.TAG_REPAIR_CONSUMABLE_STEEL)) )
  14258. {
  14259. //item stats
  14260. itemValue = CalculateAttributeValue(inv.GetItemAttributeValue(consumable, 'durabilityRepairValue'));
  14261. if(itemValue <= 0)
  14262. {
  14263. LogAssert(false, "CR4Player.RepairItemUsingConsumable: consumable <<" + inv.GetItemName(consumable) + ">> has <=0 durabilityRepairValue!!!");
  14264. return false;
  14265. }
  14266. repairBonus = CalculateAttributeValue(inv.GetItemAttributeValue(consumable, 'durabilityBonusValue'));
  14267.  
  14268. //calculate
  14269. repairValue = max * itemValue /100;
  14270.  
  14271. /* disabled repairing over 100%
  14272. if(HasBookPerk(S_Book_28))
  14273. max = max * (1 + (repairBonus + perkValue) /100);
  14274. */
  14275.  
  14276. newDurability = MinF(max, curr + repairValue);
  14277.  
  14278. inv.SetItemDurabilityScript(item, newDurability);
  14279.  
  14280. //consume
  14281. inv.RemoveItem(consumable);
  14282.  
  14283. return true;
  14284. }
  14285. return false;
  14286. }
  14287.  
  14288. ////////////////////////////////////////////////////////////////////////////////////////////
  14289. /////////////////////////// @PushingObject /////////////////////////////////////////////
  14290. ///////////////////////////////////////////////////////////////////////////////////////////
  14291. /*
  14292. event OnRigidBodyCollision( component : CComponent, actorIndex : int, shapeIndex : int )
  14293. {
  14294. pushableComponent = component;
  14295. if ( pushableComponent )
  14296. this.RaiseEvent('PushObject');
  14297.  
  14298. //component.ApplyForceAtPointToPhysicalObject
  14299. }
  14300.  
  14301. event OnRigidBodyExit( component : CComponent )
  14302. {
  14303. this.RaiseEvent('PushObjectEnd');
  14304. pushableComponent = NULL;
  14305. }
  14306.  
  14307. event OnPushObjectStart()
  14308. {
  14309. moveAdj = GetMovingAgentComponent().GetMovementAdjustor();
  14310. moveAdj.CancelAll();
  14311. pushRotTicket = moveAdj.CreateNewRequest( 'RotateToObject' );
  14312. moveAdj.MaxRotationAdjustmentSpeed(pushRotTicket,30);
  14313. moveAdj.Continuous(pushRotTicket);
  14314. moveAdj.DontEnd(pushRotTicket);
  14315. this.AddTimer('PushObjectUpdate',0.01,true, , , true);
  14316.  
  14317. }
  14318.  
  14319. event OnPushObjectStop()
  14320. {
  14321. this.RemoveTimer('PushObjectUpdate');
  14322. moveAdj.CancelByName('RotateToObject');
  14323. moveAdj = NULL;
  14324. }
  14325.  
  14326. timer function PushObjectUpdate( dt : float , id : int)
  14327. {
  14328. var impulse : Vector;
  14329. moveAdj.RotateTo( pushRotTicket, rawPlayerHeading );
  14330. impulse = this.GetHeadingVector()*10.0;
  14331. //impulse.Z += 0.5;
  14332. //pushableComponent.ApplyLocalImpulseToPhysicalObject(impulse);
  14333. }
  14334. */
  14335.  
  14336. //Shaedhen - Atmospheric Nights - Starts here
  14337. //Most of the functions of @DAY @NIGHT CYCLE CHECK have been heavily modified so I didn't specify each change because it would means pretty much everything
  14338. //I don't think there is a lot of other mods modifying this so it shouldn't cause much trouble.
  14339. //If it does, feel free to contact me either on Nexus or CDProjekt Forums and I'll assist with the merge. =)
  14340. public function InitAtmosphericNights()
  14341. {
  14342. var i : int;
  14343. inGameConfigWrapperDN = theGame.GetInGameConfigWrapper();
  14344. listOfStartTimesDK.PushBack(1080);
  14345. listOfStartTimesDK.PushBack(1140);
  14346. listOfStartTimesDK.PushBack(1200);
  14347. listOfStartTimesDK.PushBack(1260);
  14348. listOfStartTimesDK.PushBack(1320);
  14349. listOfStartDurationTimesDK.PushBack(60);
  14350. listOfStartDurationTimesDK.PushBack(120);
  14351. listOfStartDurationTimesDK.PushBack(180);
  14352. listOfStartDurationTimesDK.PushBack(240);
  14353. listOfEndTimesDK.PushBack(120);
  14354. listOfEndTimesDK.PushBack(180);
  14355. listOfEndTimesDK.PushBack(240);
  14356. listOfEndTimesDK.PushBack(300);
  14357. listOfEndTimesDK.PushBack(360);
  14358. listOfEndDurationTimesDK.PushBack(60);
  14359. listOfEndDurationTimesDK.PushBack(120);
  14360. listOfEndDurationTimesDK.PushBack(180);
  14361. listOfEndDurationTimesDK.PushBack(240);
  14362. for(i = 0; i < 12; i+=1)
  14363. intensityDN.PushBack(0.75f);
  14364. }
  14365.  
  14366.  
  14367.  
  14368. public function UpdateValuesDK()
  14369. {
  14370. var oldIntensity : array<float>;
  14371. var i : int;
  14372. var changeHours : bool;
  14373. var oldStart, oldStartTime, oldEndTime,oldEnd : int;
  14374. var change : bool;
  14375. change = false;
  14376. changeHours = false;
  14377. for(i = 0; i < 12; i+=1)
  14378. oldIntensity[i] = intensityDN[i];
  14379. oldStart = startDN;
  14380. oldStartTime = startTimeDN;
  14381. oldEnd = endDN;
  14382. oldEndTime = endTimeDN;
  14383. intensityDN[0] = 0.5f; //Default - shouldn't be used
  14384. intensityDN[1] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensityNovi'))/100;
  14385. intensityDN[2] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensitySkel'))/100;
  14386. intensityDN[3] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensityKaer'))/100;
  14387. intensityDN[4] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensityOrchard'))/100;
  14388. intensityDN[5] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensityWyzima'))/100;
  14389. intensityDN[6] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensityMyst'))/100;
  14390. intensityDN[7] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensitySpiral'))/100;
  14391. intensityDN[8] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensityWinter'))/100;
  14392. intensityDN[11] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensityTous'))/100;
  14393. // intensityDN[9] = StringToFloat (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkIntensityInterior'))/100;
  14394. changeHours = inGameConfigWrapperDN.GetVarValue('DNMenu', 'customHours');
  14395. startDN = listOfStartTimesDK[StringToInt (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkStart'))];
  14396. startTimeDN = listOfStartDurationTimesDK[StringToInt (inGameConfigWrapperDN.GetVarValue('DNMenu', 'fullDark'))];
  14397. endDN = listOfEndTimesDK[StringToInt (inGameConfigWrapperDN.GetVarValue('DNMenu', 'darkEnd'))];
  14398. endTimeDN = listOfEndDurationTimesDK[StringToInt (inGameConfigWrapperDN.GetVarValue('DNMenu', 'noDark'))];
  14399. if(changeHours)
  14400. {
  14401. theGame.envMgr.SetDayStartAt(endDN/60);
  14402. theGame.envMgr.SetNightStart((startDN+startTimeDN)/60);
  14403. }else
  14404. {
  14405. theGame.envMgr.SetDayStartAt(3);
  14406. theGame.envMgr.SetNightStart(22);
  14407. startDN = 1200;
  14408. endTimeDN = 180;
  14409. }
  14410. for(i = 0; i < 12; i+=1)
  14411. if(oldIntensity[i] != intensityDN[i])
  14412. change = true;
  14413. if(oldStart != startDN)
  14414. change = true;
  14415. if(oldStartTime != startTimeDN)
  14416. change = true;
  14417. if(oldEnd != endDN)
  14418. change = true;
  14419. if(oldEndTime != endTimeDN)
  14420. change = true;
  14421.  
  14422. if(change && !justSpawnedDN)
  14423. CheckDayNightCycle();
  14424. }
  14425.  
  14426. ///////////////////////////////////////////////////////////////////////////////////////////
  14427. /////////////////////////// @DAY @NIGHT CYCLE CHECK /////////////////////////////////////
  14428. ///////////////////////////////////////////////////////////////////////////////////////////
  14429.  
  14430. public function CheckDayNightCycle()
  14431. {
  14432. var time : GameTime;
  14433. var nextCallTime : int;
  14434. var isNight : bool;
  14435. var isDay : bool;
  14436. var isAlmostNight : bool;
  14437. var isStartingDay : bool;
  14438.  
  14439. //if changed
  14440. isNight = theGame.envMgr.IsNight();
  14441. isDay = theGame.envMgr.IsDay(); //Might return true also if starting day or almost night but it's ok because it is not really used
  14442. isStartingDay = theGame.envMgr.IsStartingDay(endTimeDN); // 120 / 60 = 2 for 2hours
  14443. isAlmostNight = theGame.envMgr.IsAlmostNight(startTimeDN); // 180 / 60 = 3 for 3 hours
  14444.  
  14445. if(isNight)
  14446. {
  14447. OnNightStarted();
  14448. nextCallTime = endDN/60;
  14449. if(nextCallTime < 0 || nextCallTime > 24)
  14450. nextCallTime = 1;
  14451. time = theGame.envMgr.GetGameTimeTillNextHour(nextCallTime);
  14452. }else if(isAlmostNight)
  14453. {
  14454. OnNightAlmostStarted();
  14455. nextCallTime = (startDN+startTimeDN)/60;
  14456. if(nextCallTime < 0 || nextCallTime > 24)
  14457. nextCallTime = 1;
  14458. time = theGame.envMgr.GetGameTimeTillNextHour(nextCallTime);
  14459. }else if(isStartingDay)
  14460. {
  14461. OnDayJustStarted();
  14462. nextCallTime = (endDN+endTimeDN)/60;
  14463. if(nextCallTime < 0 || nextCallTime > 24)
  14464. nextCallTime = 1;
  14465. time = theGame.envMgr.GetGameTimeTillNextHour(nextCallTime);
  14466. }else if(isDay)
  14467. {
  14468.  
  14469. OnDayStarted();
  14470. nextCallTime = startDN/60;
  14471. if(nextCallTime < 0 || nextCallTime > 24)
  14472. nextCallTime = 1;
  14473. time = theGame.envMgr.GetGameTimeTillNextHour(nextCallTime);
  14474. }
  14475.  
  14476. AddGameTimeTimer('DayNightCycle', time);
  14477. }
  14478.  
  14479. timer function DayNightCycle(dt : GameTime, id : int)
  14480. {
  14481. CheckDayNightCycle();
  14482. }
  14483.  
  14484. /*script*/ event OnNightStarted()
  14485. {
  14486. var pam : W3PlayerAbilityManager;
  14487. var l_currentArea : EAreaName;
  14488. var intensity1 : float;
  14489. var intensity2 : float;
  14490. //EAreaName is an enum and intensityDN array follows the same value so value of l_currentArea will get the right area.
  14491. l_currentArea = theGame.GetCommonMapManager().GetCurrentArea();
  14492. intensity1 = intensityDN[l_currentArea];
  14493. if(intensity1 < 0 || intensity1 > 1)
  14494. intensity1 = 0.7f;
  14495. intensity2 = intensityDN[l_currentArea]*0.5;
  14496. if(intensity2 < 0 || intensity2 > 1)
  14497. intensity2 = 0.375f;
  14498. if(CanUseSkill(S_Perk_01))
  14499. {
  14500. pam = (W3PlayerAbilityManager)abilityManager;
  14501. pam.SetPerk01Abilities(false, true);
  14502. }
  14503. //Deactivating if already there
  14504. if(envIdDN > -1)
  14505. DeactivateEnvironment(envIdDN,0.0f);
  14506. if(envIdDN2 > -1)
  14507. DeactivateEnvironment(envIdDN2,0.0f);
  14508. if(envIdDNegated > -1)
  14509. DeactivateEnvironment(envIdDNegated, 0.0f);
  14510. envIdDN = -1;
  14511. envIdDN2 = -1;
  14512. envIdDNegated = -1;
  14513. //Loading it again with full darkness
  14514. // if(thePlayer.IsInInterior())
  14515. // {
  14516. // envIdDN = ActivateEnvironmentDefinition( environmentDN, 99999, intensityDN[9], 0.0f );
  14517. // envIdDN2 = ActivateEnvironmentDefinition( environmentDN2, 99999, intensityDN[9]*0.5, 0.0f );
  14518. // }else{
  14519. // }
  14520. //GetWitcherPlayer().DisplayHudMessage("Goes into is Night int is : " + intensity1);
  14521. if(environmentDN && environmentDN2)
  14522. {
  14523. envIdDN = ActivateEnvironmentDefinition( environmentDN, 99999, intensity1, 0.0f );
  14524. envIdDN2 = ActivateEnvironmentDefinition( environmentDN2, 99999, intensity2, 0.0f );
  14525. }
  14526. }
  14527.  
  14528. /*script*/ event OnNightAlmostStarted()
  14529. {
  14530. var hoursAndMins : int;
  14531. var timeToBlend : float;
  14532. var l_currentArea : EAreaName;
  14533.  
  14534. var intensity1 : float;
  14535. var intensity2 : float;
  14536. //EAreaName is an enum and intensityDN array follows the same value so value of l_currentArea will get the right area.
  14537. l_currentArea = theGame.GetCommonMapManager().GetCurrentArea();
  14538. intensity1 = intensityDN[l_currentArea];
  14539. if(intensity1 < 0 || intensity1 > 1)
  14540. intensity1 = 0.7f;
  14541. intensity2 = intensityDN[l_currentArea]*0.5;
  14542. if(intensity2 < 0 || intensity2 > 1)
  14543. intensity2 = 0.375f;
  14544.  
  14545. hoursAndMins = theGame.envMgr.GetTimeInMinutes();
  14546. timeToBlend = (( (float)(startDN+startTimeDN-hoursAndMins)) *(1.0/theGame.GetHoursPerMinute())) - 10.0f;
  14547. if(timeToBlend < 0)
  14548. timeToBlend = 1.0f;
  14549. if(envIdDN > -1)
  14550. DeactivateEnvironment( envIdDN,0);
  14551. if(envIdDN2 > -1)
  14552. DeactivateEnvironment( envIdDN2,0);
  14553. if(envIdDNegated > -1)
  14554. DeactivateEnvironment(envIdDNegated, 0.0f);
  14555. envIdDN = -1;
  14556. envIdDN2 = -1;
  14557. envIdDNegated = -1;
  14558.  
  14559. // if(thePlayer.IsInInterior())
  14560. // {
  14561. // if (envIdDN2 < 0 ){
  14562. // if((justSpawnedDN || theGame.GetHoursPerMinute() != realHoursPerMinutesDN)){
  14563. // envIdDN2 = ActivateEnvironmentDefinition( environmentDN2, 99999, intensityDN[9]*0.5, 0 );
  14564. // }else{
  14565. // envIdDN2 = ActivateEnvironmentDefinition( environmentDN2, 99999, intensityDN[9]*0.5, timeToBlend );
  14566. // }
  14567. // }
  14568. // envIdDN = ActivateEnvironmentDefinition( environmentDN, 99999, intensityDN[9], timeToBlend );
  14569. //}else{
  14570. //}
  14571. //GetWitcherPlayer().DisplayHudMessage("Goes into is AlmostNight int is : " + intensity1 + "ttb " + timeToBlend);
  14572. if (envIdDN2 < 0 && environmentDN2){
  14573. if((justSpawnedDN || theGame.GetHoursPerMinute() != realHoursPerMinutesDN)){
  14574. envIdDN2 = ActivateEnvironmentDefinition( environmentDN2, 99999, intensity2, 0.0f );
  14575. }else{
  14576. envIdDN2 = ActivateEnvironmentDefinition( environmentDN2, 99999, intensity2, timeToBlend );
  14577. }
  14578. }
  14579. if(environmentDN)
  14580. {
  14581. envIdDN = ActivateEnvironmentDefinition( environmentDN, 99999, intensity1, timeToBlend );
  14582. }
  14583. }
  14584.  
  14585. /*script*/ event OnDayStarted()
  14586. {
  14587. var pam : W3PlayerAbilityManager;
  14588. var hoursAndMins : int;
  14589.  
  14590. hoursAndMins = theGame.envMgr.GetTimeInMinutes();
  14591. if(CanUseSkill(S_Perk_01))
  14592. {
  14593. pam = (W3PlayerAbilityManager)abilityManager;
  14594. pam.SetPerk01Abilities(true, false);
  14595. }
  14596. //Deactivate it if time is appropriate
  14597. if((hoursAndMins >= (endDN+endTimeDN)))
  14598. {
  14599. if(envIdDN >= 0)
  14600. DeactivateEnvironment( envIdDN,0.0f);
  14601. if(envIdDN2 >= 0)
  14602. DeactivateEnvironment( envIdDN2,0.0f);
  14603. if(envIdDNegated >= 0)
  14604. DeactivateEnvironment(envIdDNegated, 0.0f);
  14605. envIdDN = -1;
  14606. envIdDN2 = -1;
  14607. envIdDNegated = -1;
  14608. }
  14609. }
  14610. /*script*/ event OnDayJustStarted()
  14611. {
  14612. var pam : W3PlayerAbilityManager;
  14613. var hoursAndMins : int;
  14614. var l_currentArea : EAreaName;
  14615. var timeToBlend : float;
  14616. var timeToDeBlend : float;
  14617. var adaptFactor : float;
  14618. var intensity1 : float;
  14619. hoursAndMins = theGame.envMgr.GetTimeInMinutes();
  14620. if(CanUseSkill(S_Perk_01))
  14621. {
  14622. pam = (W3PlayerAbilityManager)abilityManager;
  14623. pam.SetPerk01Abilities(true, false);
  14624. }
  14625. timeToBlend = (( (float)(endDN+endTimeDN-hoursAndMins)) *(1.0/theGame.GetHoursPerMinute()));
  14626. if(timeToBlend < 0)
  14627. timeToBlend = 1.0f;
  14628. if(envIdDN > -1)
  14629. DeactivateEnvironment( envIdDN,timeToBlend);
  14630. if(envIdDN2 > -1)
  14631. DeactivateEnvironment( envIdDN2,timeToBlend);
  14632. envIdDN2 = -1;
  14633.  
  14634. if((endDN+endTimeDN-hoursAndMins) <= 30 )
  14635. {
  14636. adaptFactor = 1.0f;
  14637. }else if((endDN+endTimeDN-hoursAndMins) <= 60 )
  14638. {
  14639. adaptFactor = 0.85f;
  14640. }else if((startDN+startTimeDN-hoursAndMins) <= 120 )
  14641. {
  14642. adaptFactor = 0.7f;
  14643. }else if((startDN+startTimeDN-hoursAndMins) <= 180 )
  14644. {
  14645. adaptFactor = 0.6f;
  14646. }else
  14647. {
  14648. adaptFactor = 0.4f;
  14649. }
  14650. l_currentArea = theGame.GetCommonMapManager().GetCurrentArea();
  14651. intensity1 = intensityDN[l_currentArea]*adaptFactor;
  14652. if(intensity1 < 0 || intensity1 > 1)
  14653. intensity1 = 0.4f;
  14654.  
  14655. timeToDeBlend = timeToBlend*8.0f; //TODO : Get this value right... Whatever is set doesn't seems to change much
  14656. if(timeToDeBlend < 0)
  14657. timeToDeBlend = 1.0f;
  14658.  
  14659.  
  14660. if(envIdDN < 0){
  14661. // if(thePlayer.IsInInterior())
  14662. // {
  14663. // envIdDN = ActivateEnvironmentDefinition( environmentDN, 99999, intensityDN[9]*adaptFactor, 0 );
  14664. // }else{
  14665. // }
  14666. if(environmentDN)
  14667. {
  14668. envIdDN = ActivateEnvironmentDefinition( environmentDN, 99999, intensity1, 0 );
  14669. }
  14670. }
  14671. if(environmentDNegated)
  14672. {
  14673. envIdDNegated = ActivateEnvironmentDefinition( environmentDNegated, 99999, -0.0001f, timeToDeBlend );
  14674. }
  14675. }
  14676.  
  14677. public function SetRealHoursPerMinutesDN(hpm : float)
  14678. {
  14679. realHoursPerMinutesDN = hpm;
  14680. }
  14681.  
  14682. public function OnMeditateStopDN(simulatedTime : float)
  14683. {
  14684. GetWitcherPlayer().MeditationRestoring(simulatedTime);
  14685. CheckDayNightCycle();
  14686. }
  14687.  
  14688. public function DeactivateDN()
  14689. {
  14690. if(envIdDN > -1)
  14691. DeactivateEnvironment( envIdDN,0.0f);
  14692. if(envIdDN2 > -1)
  14693. DeactivateEnvironment( envIdDN2,0.0f);
  14694. if(envIdDNegated > -1)
  14695. DeactivateEnvironment(envIdDNegated, 0.0f);
  14696. }
  14697. //Shaedhen - Atmospheric Nights - Ends here
  14698.  
  14699.  
  14700.  
  14701.  
  14702.  
  14703.  
  14704. ///////////////////////////////////////////////////////////////////////////////////////////
  14705. /////////////////////////// @INPUT //////////////////////////////////////////////////////
  14706. ///////////////////////////////////////////////////////////////////////////////////////////
  14707.  
  14708. public function ForceUnlockAllInputActions(alsoQuestLocks : bool)
  14709. {
  14710. if ( inputHandler )
  14711. inputHandler.ForceUnlockAllInputActions(alsoQuestLocks);
  14712. }
  14713.  
  14714. public function SetPrevRawLeftJoyRot()
  14715. {
  14716. prevRawLeftJoyRot = rawLeftJoyRot;
  14717. }
  14718.  
  14719. public function GetPrevRawLeftJoyRot() : float
  14720. {
  14721. return prevRawLeftJoyRot;
  14722. }
  14723.  
  14724. public function GetExplorationInputContext() : name
  14725. {
  14726. return explorationInputContext;
  14727. }
  14728.  
  14729. public function GetCombatInputContext() : name
  14730. {
  14731. return combatInputContext;
  14732. }
  14733.  
  14734. ///////////////////////////////////////////////////////////////////////////////////////////
  14735. /////////////////////////// @EXPLORATION ////////////////////////////////////////////////
  14736. ///////////////////////////////////////////////////////////////////////////////////////////
  14737.  
  14738. public function SetIsOnBoat(b : bool)
  14739. {
  14740. isOnBoat = b;
  14741. }
  14742.  
  14743. public function IsOnBoat() : bool
  14744. {
  14745. return isOnBoat;
  14746. }
  14747.  
  14748. public function IsInShallowWater() : bool
  14749. {
  14750. return isInShallowWater;
  14751. }
  14752.  
  14753. event OnEnterShallowWater()
  14754. {
  14755. if ( isInShallowWater )
  14756. return false;
  14757.  
  14758. isInShallowWater = true;
  14759. BlockAction( EIAB_Dodge,'ShallowWater', false, false, true );
  14760. BlockAction( EIAB_Sprint,'ShallowWater', false, false, true );
  14761. BlockAction( EIAB_Crossbow,'ShallowWater', false, false, true );
  14762. BlockAction( EIAB_Jump,'ShallowWater', false, false, true );
  14763. SetBehaviorVariable( 'shallowWater',1.0);
  14764. }
  14765. event OnExitShallowWater()
  14766. {
  14767. if ( !isInShallowWater )
  14768. return false;
  14769.  
  14770. isInShallowWater = false;
  14771. BlockAllActions('ShallowWater',false);
  14772. SetBehaviorVariable( 'shallowWater',0.0);
  14773. }
  14774.  
  14775. public function TestIsInSettlement() : bool
  14776. {
  14777. return IsInSettlement();
  14778. }
  14779.  
  14780. ///////////////////////////////////////////////////////////////////////////////////////////
  14781. /////////////////////////// GLOSSARY ////////////////////////////////////////////////
  14782. ///////////////////////////////////////////////////////////////////////////////////////////
  14783.  
  14784. //Processes glossary image filename and exchanges it with override if provided
  14785. public function ProcessGlossaryImageOverride( defaultImage : string, uniqueTag : name ) : string
  14786. {
  14787. var size : int;
  14788. var i : int;
  14789.  
  14790. size = glossaryImageOverride.Size();
  14791.  
  14792. if( size == 0 )
  14793. return defaultImage;
  14794.  
  14795. for( i = 0; i < size; i += 1 )
  14796. {
  14797. if( glossaryImageOverride[i].uniqueTag == uniqueTag )
  14798. return glossaryImageOverride[i].imageFileName;
  14799.  
  14800. }
  14801.  
  14802. return defaultImage;
  14803. }
  14804.  
  14805. //Adds glossary image override filename to array
  14806. public function EnableGlossaryImageOverride( uniqueTag : name, imageFileName : string, enable : bool )
  14807. {
  14808. var imageData : SGlossaryImageOverride;
  14809. var size : int;
  14810. var i : int;
  14811.  
  14812. for( i = 0; i < glossaryImageOverride.Size(); i += 1 )
  14813. {
  14814. if( glossaryImageOverride[i].uniqueTag == uniqueTag )
  14815. {
  14816. glossaryImageOverride.Remove(glossaryImageOverride[i]);
  14817. }
  14818. }
  14819.  
  14820. if( enable )
  14821. {
  14822. if( IsNameValid(uniqueTag) && imageFileName != "" )
  14823. {
  14824. glossaryImageOverride.PushBack( SGlossaryImageOverride( uniqueTag, imageFileName ) );
  14825. }
  14826. }
  14827. }
  14828. ///////////////////////////////////////////////////////////////////////////////////////////
  14829. /////////////////////////// WEATHER DISPLAY /////////////////////////////
  14830. ///////////////////////////////////////////////////////////////////////////////////////////
  14831. public function SetWeatherDisplayDisabled( disable : bool )
  14832. {
  14833. disableWeatherDisplay = disable;
  14834. }
  14835.  
  14836. public function GetWeatherDisplayDisabled() : bool
  14837. {
  14838. return disableWeatherDisplay;
  14839. }
  14840.  
  14841. ///////////////////////////////////////////////////////////////////////////////////////////
  14842. /////////////////////////// MONSTER HUNT INVESTIGATION AREAS /////////////////////////////
  14843. ///////////////////////////////////////////////////////////////////////////////////////////
  14844.  
  14845. public function SetCurrentMonsterHuntInvestigationArea ( area : W3MonsterHuntInvestigationArea )
  14846. {
  14847. currentMonsterHuntInvestigationArea = area;
  14848. }
  14849.  
  14850.  
  14851. ///////////////////////////////////////////////////////////////////////////////////////////
  14852. /////////////////////////// BARBER SYSTEM CUSTOM HEAD /////////////////////////////
  14853. ///////////////////////////////////////////////////////////////////////////////////////////
  14854.  
  14855. public function RememberCustomHead( headName : name )
  14856. {
  14857. rememberedCustomHead = headName;
  14858. }
  14859.  
  14860. public function GetRememberedCustomHead() : name
  14861. {
  14862. return rememberedCustomHead;
  14863. }
  14864.  
  14865. public function ClearRememberedCustomHead()
  14866. {
  14867. rememberedCustomHead = '';
  14868. }
  14869.  
  14870. ///////////////////////////////////////////////////////////////////////////////////////////
  14871. /////////////////////////// @TUTORIAL ////////////////////////////////////////////////
  14872. ///////////////////////////////////////////////////////////////////////////////////////////
  14873.  
  14874. public function CreateTutorialInput()
  14875. {
  14876. var prevInputHandler : CPlayerInput;
  14877.  
  14878. prevInputHandler = inputHandler;
  14879. inputHandler = new W3PlayerTutorialInput in this;
  14880. inputHandler.Initialize(false, prevInputHandler);
  14881.  
  14882. if(prevInputHandler)
  14883. delete prevInputHandler;
  14884. }
  14885.  
  14886. public function CreateInput()
  14887. {
  14888. var oldInputHandler : CPlayerInput;
  14889.  
  14890. oldInputHandler = inputHandler;
  14891. inputHandler = new CPlayerInput in this;
  14892. inputHandler.Initialize(false, oldInputHandler);
  14893. }
  14894.  
  14895. timer function TutorialSilverCombat(dt : float, id : int)
  14896. {
  14897. var i : int;
  14898. var actors : array<CActor>;
  14899.  
  14900. if(IsInCombat())
  14901. {
  14902. actors = GetNPCsAndPlayersInRange(20, 1000000, ,FLAG_ExcludePlayer + FLAG_OnlyAliveActors);
  14903. for(i=0; i<actors.Size(); i+=1)
  14904. {
  14905. if(actors[i] && IsRequiredAttitudeBetween(this, actors[i], true) && actors[i].UsesEssence())
  14906. {
  14907. FactsAdd("TutorialShowSilver");
  14908.  
  14909. RemoveTimer('TutorialSilverCombat');
  14910. break;
  14911. }
  14912. }
  14913. }
  14914. }
  14915.  
  14916. private saved var m_bossTag : name;
  14917.  
  14918. public function GetBossTag() : name
  14919. {
  14920. return m_bossTag;
  14921. }
  14922.  
  14923. public function SetBossTag( bossTag : name )
  14924. {
  14925. m_bossTag = bossTag;
  14926. }
  14927.  
  14928. private saved var m_usingCoatOfArms : bool; default m_usingCoatOfArms = false;
  14929.  
  14930. public function IsUsingCoatOfArms() : bool
  14931. {
  14932. return m_usingCoatOfArms;
  14933. }
  14934.  
  14935. public function SetUsingCoatOfArms( using : bool)
  14936. {
  14937. m_usingCoatOfArms = using;
  14938. }
  14939.  
  14940. private saved var m_initialTimeOut : float;
  14941. private saved var m_currentTimeOut : float;
  14942.  
  14943. public function GetInitialTimeOut() : float
  14944. {
  14945. return m_initialTimeOut;
  14946. }
  14947.  
  14948. public function SetInitialTimeOut( timeOut : float )
  14949. {
  14950. m_initialTimeOut = timeOut;
  14951. }
  14952.  
  14953. public function GetCurrentTimeOut() : float
  14954. {
  14955. return m_currentTimeOut;
  14956. }
  14957.  
  14958. public function SetCurrentTimeOut( timeOut : float )
  14959. {
  14960. m_currentTimeOut = timeOut;
  14961. }
  14962.  
  14963.  
  14964. ///////////////////////////////////////////////////////////////////////////////////////////
  14965. /////////////////////////// @FINISHERS ////////////////////////////////////////////
  14966. ///////////////////////////////////////////////////////////////////////////////////////////
  14967.  
  14968. timer function DelayedFinisherInputTimer(dt : float, id : int)
  14969. {
  14970. //theGame.SetTimeScale( 0.1, theGame.GetTimescaleSource(ETS_FinisherInput), theGame.GetTimescalePriority(ETS_FinisherInput) );
  14971. //GetFinisherVictim().EnableFinishComponent( true );
  14972. }
  14973.  
  14974. timer function RemoveFinisherCameraAnimationCheck(dt : float, id : int)
  14975. {
  14976. if ( !isInFinisher && !bLAxisReleased )
  14977. {
  14978. theGame.GetSyncAnimManager().OnRemoveFinisherCameraAnimation();
  14979. RemoveTimer( 'RemoveFinisherCameraAnimationCheck' );
  14980. }
  14981. }
  14982.  
  14983. ///////////////////////////////////////////////////////////////////////////////////////////
  14984. /////////////////////////// @DEBUG @TIMERS ////////////////////////////////////////////
  14985. ///////////////////////////////////////////////////////////////////////////////////////////
  14986.  
  14987. timer function GameplayFactRemove(dt : float, timerId : int)
  14988. {
  14989. theGame.GameplayFactRemoveFromTimer(timerId);
  14990. }
  14991.  
  14992. //gives NORMAL starting inventory
  14993. timer function GiveStartingItems(dt : float, timerId : int)
  14994. {
  14995. var template : CEntityTemplate;
  14996. var invEntity : CInventoryComponent;
  14997. var entity : CEntity;
  14998. var items : array<SItemUniqueId>;
  14999. var id : SItemUniqueId;
  15000. var i : int;
  15001.  
  15002. //wait for inventory to init
  15003. if(inv)
  15004. {
  15005. inv.GetAllItems(items);
  15006. if(items.Size() <= 0)
  15007. {
  15008. return;
  15009. }
  15010. }
  15011. else
  15012. {
  15013. return;
  15014. }
  15015.  
  15016. //add items
  15017. template = (CEntityTemplate)LoadResource("geralt_inventory_release");
  15018. entity = theGame.CreateEntity(template, Vector(0,0,0));
  15019. invEntity = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent');
  15020.  
  15021. invEntity.GetAllItems(items);
  15022. for(i=0; i<items.Size(); i+=1)
  15023. {
  15024. id = invEntity.GiveItemTo(inv, items[i], 0, false, true);
  15025. if ( inv.ItemHasTag(id,'Scabbard') )
  15026. {
  15027. inv.MountItem(id);
  15028. }
  15029. else if(!inv.IsItemFists(id) && inv.GetItemName(id) != 'Cat 1') //hack for cat potion - don't equip!
  15030. {
  15031. EquipItem(id);
  15032. }
  15033. else if(inv.IsItemSingletonItem(id))
  15034. {
  15035. inv.SingletonItemSetAmmo(id, inv.SingletonItemGetMaxAmmo(id));
  15036. }
  15037. }
  15038.  
  15039. entity.Destroy();
  15040.  
  15041. //remove timer
  15042. RemoveTimer('GiveStartingItems');
  15043. }
  15044.  
  15045. //Adds items used for testing. Won't be called in final release. Items are added from geralt_inventory entity.
  15046. //Works as a timer since we need to wait for inventory to init and there is no such event.
  15047. timer function Debug_GiveTestingItems(dt : float, optional id : int)
  15048. {
  15049. var template : CEntityTemplate;
  15050. var invTesting : CInventoryComponent;
  15051. var entity : CEntity;
  15052. var items : array<SItemUniqueId>;
  15053. var i : int;
  15054. var slot : EEquipmentSlots;
  15055.  
  15056. //wait for inventory to init
  15057. if(inv)
  15058. {
  15059. inv.GetAllItems(items);
  15060. if(items.Size() <= 0)
  15061. {
  15062. return;
  15063. }
  15064. }
  15065. else
  15066. {
  15067. return;
  15068. }
  15069.  
  15070. template = (CEntityTemplate)LoadResource("geralt_inventory_internal");
  15071. entity = theGame.CreateEntity(template, Vector(0,0,0));
  15072. invTesting = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent');
  15073. invTesting.GiveAllItemsTo(inv, true);
  15074. entity.Destroy();
  15075.  
  15076. //once called remove the timer
  15077. RemoveTimer('Debug_GiveTestingItems');
  15078.  
  15079. //equip crossbow, bombs and bolts, select bolts
  15080. inv.GetAllItems(items);
  15081.  
  15082. for(i=0; i<items.Size(); i+=1)
  15083. {
  15084. if( inv.IsItemCrossbow(items[i]) || inv.IsItemBomb(items[i]) )
  15085. {
  15086. slot = inv.GetSlotForItemId(items[i]);
  15087. EquipItem(items[i], slot);
  15088.  
  15089. if( (W3PlayerWitcher)this && inv.IsItemCrossbow(items[i]) )
  15090. GetWitcherPlayer().SelectQuickslotItem(slot);
  15091. }
  15092. else if(inv.IsItemBolt(items[i]))
  15093. {
  15094. slot = inv.GetSlotForItemId(items[i]);
  15095. EquipItem(items[i], slot);
  15096. }
  15097.  
  15098. if(inv.IsItemSingletonItem(items[i]))
  15099. {
  15100. inv.SingletonItemSetAmmo(items[i], inv.SingletonItemGetMaxAmmo(items[i]));
  15101. }
  15102. }
  15103. }
  15104.  
  15105. //called in tutorial in not final version to remove testing items
  15106. timer function Debug_RemoveTestingItems(dt : float, id : int)
  15107. {
  15108. var template : CEntityTemplate;
  15109. var entity : CEntity;
  15110. var invTesting : CInventoryComponent;
  15111. var ids : array<SItemUniqueId>;
  15112. var i : int;
  15113.  
  15114. template = (CEntityTemplate)LoadResource("geralt_inventory_internal");
  15115. entity = theGame.CreateEntity(template, Vector(0,0,0));
  15116. invTesting = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent');
  15117. invTesting.GetAllItems(ids);
  15118.  
  15119. for(i=0; i<ids.Size(); i+=1)
  15120. inv.RemoveItemByName(invTesting.GetItemName(ids[i]), invTesting.GetItemQuantity(ids[i]));
  15121.  
  15122. entity.Destroy();
  15123. RemoveTimer('Debug_RemoveTestingItems');
  15124. }
  15125.  
  15126. timer function Debug_DelayedConsoleCommand(dt : float, id : int)
  15127. {
  15128. //inv.AddAnItem('Recipe for Mutagen 23');
  15129. inv.AddAnItem('Boots 2 schematic');
  15130. }
  15131.  
  15132. function DBG_SkillSlots()
  15133. {
  15134. ((W3PlayerAbilityManager)abilityManager).DBG_SkillSlots();
  15135. }
  15136.  
  15137. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  15138. //////////////////////////////// @BACKLIGHT COLOR ////////////////////////////////////////////////////////////////////
  15139. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  15140.  
  15141. public final function SetPadBacklightColor(r, g, b : int)
  15142. {
  15143. var padBacklightColor : Vector;
  15144.  
  15145. padBacklightColor.X = r / 255;
  15146. padBacklightColor.Y = g / 255;
  15147. padBacklightColor.Z = b / 255;
  15148.  
  15149. SetBacklightColor(padBacklightColor);
  15150. }
  15151.  
  15152. public final function SetPadBacklightColorFromSign(signType : ESignType)
  15153. {
  15154. LogPS4Light("SetPadBacklightColorFromSign... " + signType);
  15155.  
  15156. switch(signType)
  15157. {
  15158. case ST_Yrden: SetPadBacklightColor( 200 , 81 , 255 ); break; // Violet
  15159. case ST_Quen: SetPadBacklightColor( 255 , 205 , 68 ); break; // Yellow
  15160. case ST_Igni: SetPadBacklightColor( 255 , 79 , 10 ); break; // Orange
  15161. case ST_Axii: SetPadBacklightColor( 255 , 255 , 255 ); break; // White
  15162. case ST_Aard: SetPadBacklightColor( 158 , 214 , 255 ); break; // Blue
  15163. }
  15164. }
  15165.  
  15166. timer function ResetPadBacklightColorTimer(dt : float, id : int)
  15167. {
  15168. ResetPadBacklightColor();
  15169. }
  15170.  
  15171. public final function ResetPadBacklightColor(optional skipHeldWeapon : bool)
  15172. {
  15173. var weapons : array<SItemUniqueId>;
  15174. var sword : CWitcherSword;
  15175. var healthPercentage : float;
  15176. var tmpBacklight : Vector;
  15177.  
  15178. if(!skipHeldWeapon)
  15179. {
  15180. weapons = inv.GetHeldWeapons();
  15181.  
  15182. //if holding a sword the default backlight color matches the one set in sword entity
  15183. if(weapons.Size() > 0)
  15184. {
  15185. sword = (CWitcherSword)inv.GetItemEntityUnsafe(weapons[0]);
  15186. if(sword)
  15187. {
  15188. tmpBacklight.X = sword.padBacklightColor.X / 255.0f;
  15189. tmpBacklight.Y = sword.padBacklightColor.Y / 255.0f;
  15190. tmpBacklight.Z = sword.padBacklightColor.Z / 255.0f;
  15191. tmpBacklight.W = 1.0f;
  15192. SetBacklightColor( tmpBacklight );
  15193. LogPS4Light("Setting light from sword template: " + NoTrailZeros(sword.padBacklightColor.X) + ", " + NoTrailZeros(sword.padBacklightColor.Y) + ", " + NoTrailZeros(sword.padBacklightColor.Z) );
  15194. return;
  15195. }
  15196. }
  15197. }
  15198.  
  15199. healthPercentage = GetStatPercents( BCS_Vitality );
  15200. SetBacklightFromHealth( healthPercentage );
  15201. LogPS4Light("Setting light from health, " + NoTrailZeros(RoundMath(healthPercentage*100)) + "%");
  15202. }
  15203.  
  15204. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  15205.  
  15206. event OnOpenningDoor()
  15207. {
  15208. if( !thePlayer.IsUsingHorse() )
  15209. RaiseEvent('OpenDoor');
  15210. }
  15211.  
  15212. public final function SetLoopingCameraShakeAnimName( n : name )
  15213. {
  15214. loopingCameraShakeAnimName = n;
  15215. }
  15216.  
  15217. public var loopingCameraShakeAnimName : name;
  15218. timer function RemoveQuestCameraShakeTimer( dt : float , id : int)
  15219. {
  15220. RemoveQuestCameraShake( loopingCameraShakeAnimName );
  15221. }
  15222.  
  15223. public function RemoveQuestCameraShake( animName : name )
  15224. {
  15225. var camera : CCustomCamera = theGame.GetGameCamera();
  15226. var animation : SCameraAnimationDefinition;
  15227.  
  15228. camera.StopAnimation( animName );
  15229. }
  15230.  
  15231. public function GetCameraPadding() : float
  15232. {
  15233. if( theGame.IsFocusModeActive() )
  15234. {
  15235. return 0.25; // Tweaked for [108933] Geralt is being clipped when using focus mode while running towards camera.
  15236. }
  15237. else
  15238. {
  15239. return 0.02f; // Tweaked for [114907] Player dissolving while aiming crossbow.
  15240. }
  15241. }
  15242.  
  15243. public function IsPerformingPhaseChangeAnimation() : bool { return isPerformingPhaseChangeAnimation; }
  15244. public function SetIsPerformingPhaseChangeAnimation( val : bool ) { isPerformingPhaseChangeAnimation = val; }
  15245.  
  15246. private function DealCounterDamageToOlgierd()
  15247. {
  15248. var damage : W3DamageAction;
  15249.  
  15250. damage = new W3DamageAction in this;
  15251.  
  15252. damage.Initialize( thePlayer.GetTarget(), thePlayer.GetTarget(), NULL, this, EHRT_None, CPS_Undefined, false, false, false, true );
  15253. damage.AddDamage( theGame.params.DAMAGE_NAME_DIRECT, thePlayer.GetTarget().GetStatMax( BCS_Vitality ) * 3 / 100 );
  15254. theGame.damageMgr.ProcessAction( damage );
  15255.  
  15256. delete damage;
  15257. }
  15258.  
  15259. timer function PlayDelayedCounterDamageEffect( dt : float, id : int )
  15260. {
  15261. thePlayer.GetTarget().PlayEffect( 'olgierd_energy_blast' );
  15262. }
  15263.  
  15264. // TEST
  15265. public function SetTestAdjustRequestedMovementDirection( val : bool )
  15266. {
  15267. testAdjustRequestedMovementDirection = val;
  15268. }
  15269.  
  15270. event OnVisualDebug( frame : CScriptedRenderFrame, flag : EShowFlags )
  15271. {
  15272. var boneFollow : int;
  15273. var bonePosition : Vector;
  15274. var yrdenEntity : W3YrdenEntity;
  15275.  
  15276. substateManager.OnVisualDebug( frame, flag );
  15277.  
  15278. boneFollow = thePlayer.GetBoneIndex( 'Reference' );
  15279. bonePosition = MatrixGetTranslation( thePlayer.GetBoneWorldMatrixByIndex( boneFollow ) );
  15280. frame.DrawText( "R", bonePosition, Color( 50, 200, 70 ) );
  15281. //frame.DrawText( "R", bonePositionCam, Color( 200, 50, 70 ) );
  15282.  
  15283. boneFollow = thePlayer.GetBoneIndex( 'Trajectory' );
  15284. bonePosition = MatrixGetTranslation( thePlayer.GetBoneWorldMatrixByIndex( boneFollow ) );
  15285. frame.DrawSphere( bonePosition, 0.1f, Color( 200, 50, 70 ) );
  15286. frame.DrawText( "T", bonePosition, Color( 200, 50, 70 ) );
  15287.  
  15288. //frame.DrawSphere( lastSafePosition, 1.0f, Color( 50, 200, 70 ) );
  15289. //frame.DrawText( "SavePos", lastSafePosition, Color( 50, 200, 70 ) );
  15290.  
  15291. yrdenEntity = (W3YrdenEntity)GetWitcherPlayer().GetSignEntity(ST_Yrden);
  15292. yrdenEntity.OnVisualDebug(frame, flag, false);
  15293.  
  15294. return true;
  15295. }
  15296.  
  15297. timer function PotDrinkTimer(dt : float, id : int)
  15298. {
  15299. inputHandler.PotDrinkTimer(false);
  15300. }
  15301.  
  15302. public function SetIsHorseRacing( val : bool )
  15303. {
  15304. isHorseRacing = val;
  15305. }
  15306.  
  15307. public function GetIsHorseRacing() : bool
  15308. {
  15309. return isHorseRacing;
  15310. }
  15311.  
  15312. public function SetHorseCombatSlowMo( val : bool )
  15313. {
  15314. horseCombatSlowMo = val;
  15315. }
  15316.  
  15317. public function GetHorseCombatSlowMo() : bool
  15318. {
  15319. return horseCombatSlowMo;
  15320. }
  15321.  
  15322. public function SetItemsPerLevelGiven( id : int )
  15323. {
  15324. itemsPerLevelGiven[id] = true;
  15325. }
  15326.  
  15327. private function AddItemPerLevelList()
  15328. {
  15329. var i : int;
  15330.  
  15331. itemsPerLevel.Clear();
  15332. itemsPerLevel.PushBack('O');
  15333. itemsPerLevel.PushBack('No Mans Land sword 2');
  15334. itemsPerLevel.PushBack('No Mans Land sword 3');
  15335. itemsPerLevel.PushBack('Silver sword 2');
  15336. itemsPerLevel.PushBack('Boots 01');
  15337. itemsPerLevel.PushBack('Novigraadan sword 2');
  15338. itemsPerLevel.PushBack('Light armor 01');
  15339. itemsPerLevel.PushBack('Heavy boots 01');
  15340. itemsPerLevel.PushBack('Nilfgaardian sword 3');
  15341. itemsPerLevel.PushBack('Silver sword 3');
  15342. itemsPerLevel.PushBack('Heavy gloves 01');
  15343. itemsPerLevel.PushBack('Skellige sword 2');
  15344. itemsPerLevel.PushBack('Heavy pants 01');
  15345. itemsPerLevel.PushBack('Silver sword 4');
  15346. itemsPerLevel.PushBack('No Mans Land sword 4');
  15347. itemsPerLevel.PushBack('Heavy armor 01');
  15348. itemsPerLevel.PushBack('Heavy boots 02');
  15349. itemsPerLevel.PushBack('Skellige sword 3');
  15350. itemsPerLevel.PushBack('Silver sword 5');
  15351. itemsPerLevel.PushBack('Heavy pants 02');
  15352. itemsPerLevel.PushBack('Heavy gloves 02');
  15353. itemsPerLevel.PushBack('Heavy gloves 02');
  15354. itemsPerLevel.PushBack('Heavy armor 02');
  15355. itemsPerLevel.PushBack('Scoiatael sword 1');
  15356.  
  15357. if ( itemsPerLevelGiven.Size() < 49 )
  15358. {
  15359. itemsPerLevelGiven.Clear();
  15360. for (i = 0; i < itemsPerLevel.Size(); i += 1) { itemsPerLevelGiven.PushBack( false ); }
  15361. }
  15362. }
  15363.  
  15364. // TEMP
  15365. public function DealDamageToBoat( dmg : float, index : int, optional globalHitPos : Vector )
  15366. {
  15367. var boat : CBoatDestructionComponent;
  15368.  
  15369. if(usedVehicle)
  15370. {
  15371. boat = (CBoatDestructionComponent) usedVehicle.GetComponentByClassName( 'CBoatDestructionComponent' );
  15372. if( boat )
  15373. {
  15374. boat.DealDamage( dmg, index, globalHitPos );
  15375. }
  15376. }
  15377. }
  15378.  
  15379. ////////////////////////////////////////////////////////////////////////////////
  15380. //
  15381. // PLAYABLE AREA
  15382. //
  15383. public function OnStartTeleportingPlayerToPlayableArea()
  15384. {
  15385. var FADEOUT_INTERVAL : float = 0.5;
  15386.  
  15387. // if we jumped on horse right before being teleported, we need to disable falling damage because height difference may kill us
  15388. if ( thePlayer.IsUsingHorse() )
  15389. {
  15390. if ( thePlayer.GetUsedHorseComponent().OnCheckHorseJump() )
  15391. {
  15392. thePlayer.GetUsedHorseComponent().SetCanTakeDamageFromFalling( false );
  15393. }
  15394. }
  15395.  
  15396. if ( thePlayer.IsActionAllowed( EIAB_FastTravel ) )
  15397. {
  15398. OnOpenMapToLetPlayerGoBackToPlayableArea();
  15399. }
  15400. else
  15401. {
  15402. theGame.FadeOutAsync( FADEOUT_INTERVAL );
  15403. thePlayer.AddTimer( 'BorderTeleportFadeOutTimer', FADEOUT_INTERVAL, false );
  15404. }
  15405. }
  15406.  
  15407. timer function BorderTeleportFadeOutTimer( dt : float, id : int )
  15408. {
  15409. OnTeleportPlayerToPlayableArea( false );
  15410. }
  15411.  
  15412. public function OnOpenMapToLetPlayerGoBackToPlayableArea()
  15413. {
  15414. var initData : W3MapInitData;
  15415.  
  15416. initData = new W3MapInitData in this;
  15417. initData.SetTriggeredExitEntity( true );
  15418. initData.ignoreSaveSystem = true;
  15419. initData.setDefaultState('FastTravel');
  15420. theGame.RequestMenuWithBackground( 'MapMenu', 'CommonMenu', initData );
  15421. }
  15422.  
  15423. public function OnTeleportPlayerToPlayableArea( afterClosingMap : bool )
  15424. {
  15425. var BLACKSCREEN_INTERVAL : float = 0.1;
  15426. var manager : CCommonMapManager = theGame.GetCommonMapManager();
  15427.  
  15428. thePlayer.TeleportWithRotation( manager.GetBorderTeleportPosition(), manager.GetBorderTeleportRotation() );
  15429. thePlayer.AddTimer( 'BorderTeleportFadeInTimer', BLACKSCREEN_INTERVAL, false );
  15430.  
  15431. theGame.FadeOutAsync( 0 );
  15432. theGame.SetFadeLock('PlayerTeleportation');
  15433. }
  15434.  
  15435. timer function BorderTeleportFadeInTimer( dt : float, id : int )
  15436. {
  15437. theGame.ResetFadeLock('PlayerTeleportation');
  15438. theGame.FadeOutAsync( 0 );
  15439. theGame.FadeInAsync( 2.0f );
  15440. }
  15441.  
  15442. public final function SetLastInstantKillTime(g : GameTime)
  15443. {
  15444. lastInstantKillTime = g;
  15445. }
  15446. //
  15447. //
  15448. //
  15449. ////////////////////////////////////////////////////////////////////////////////
  15450.  
  15451. timer function TestTimer(dt : float, id : int )
  15452. {
  15453. LogChannel('asdf', "asdf");
  15454. theGame.FadeOutAsync( 5 );
  15455. }
  15456.  
  15457. public final function Debug_ReleaseCriticalStateSaveLocks()
  15458. {
  15459. effectManager.Debug_ReleaseCriticalStateSaveLocks();
  15460. }
  15461.  
  15462. timer function Debug_SpamSpeed(dt : float, id : int)
  15463. {
  15464. if(currentlyMountedHorse)
  15465. {
  15466. LogSpeed("curr player's horse speed: " + NoTrailZeros(currentlyMountedHorse.GetMovingAgentComponent().GetSpeed())) ;
  15467. }
  15468. else
  15469. {
  15470. LogSpeed("curr player speed: " + NoTrailZeros(GetMovingAgentComponent().GetSpeed())) ;
  15471. }
  15472. }
  15473.  
  15474. timer function RemoveInstantKillSloMo(dt : float, id : int)
  15475. {
  15476. theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_InstantKill) );
  15477. }
  15478.  
  15479. timer function RemoveForceFinisher(dt : float, id : int)
  15480. {
  15481. forceFinisher = false;
  15482. }
  15483.  
  15484. public final function Debug_ClearAllActionLocks(optional action : EInputActionBlock, optional all : bool)
  15485. {
  15486. inputHandler.Debug_ClearAllActionLocks(action, all);
  15487. }
  15488.  
  15489. function OnFocusedCameraBlendBegin() {}
  15490. function OnFocusedCameraBlendUpdate( progress : float ) {}
  15491. function OnFocusedCameraBlendEnd() {}
  15492.  
  15493. public function GetEtherealCount() : int { return etherealCount; }
  15494. public function IncrementEtherealCount()
  15495. {
  15496. etherealCount += 1;
  15497. if( etherealCount == 6 )
  15498. ResetEtherealCount();
  15499. }
  15500. public function ResetEtherealCount() { etherealCount = 0; }
  15501.  
  15502. public function SetInsideDiveAttackArea( val : bool ) { insideDiveAttackArea = val; }
  15503. public function IsInsideDiveAttackArea() : bool { return insideDiveAttackArea; }
  15504. public function SetDiveAreaNumber( val : int ) { diveAreaNumber = val; }
  15505. public function GetDiveAreaNumber() : int { return diveAreaNumber; }
  15506.  
  15507. // PHANTOM WEAPON
  15508. //------------------------------------------------------------------------------------------------------------------
  15509. public function InitPhantomWeaponMgr()
  15510. {
  15511. if( !phantomWeaponMgr )
  15512. {
  15513. phantomWeaponMgr = new CPhantomWeaponManager in this;
  15514. phantomWeaponMgr.Init( this.GetInventory() );
  15515. }
  15516. }
  15517.  
  15518. public function DestroyPhantomWeaponMgr()
  15519. {
  15520. if( phantomWeaponMgr )
  15521. {
  15522. delete phantomWeaponMgr;
  15523. }
  15524. }
  15525.  
  15526. public function GetPhantomWeaponMgr() : CPhantomWeaponManager
  15527. {
  15528. if( phantomWeaponMgr )
  15529. {
  15530. return phantomWeaponMgr;
  15531. }
  15532. else
  15533. {
  15534. return NULL;
  15535. }
  15536. }
  15537.  
  15538. public timer function DischargeWeaponAfter( td : float, id : int )
  15539. {
  15540. GetPhantomWeaponMgr().DischargeWeapon();
  15541. }
  15542. //------------------------------------------------------------------------------------------------------------------
  15543. // FORCED FINISHER - mutation8
  15544. //------------------------------------------------------------------------------------------------------------------
  15545.  
  15546. private var forcedFinisherVictim : CActor;
  15547.  
  15548. timer function PerformFinisher( time : float , id : int )
  15549. {
  15550. var combatTarget : CActor;
  15551. var i : int;
  15552.  
  15553. combatTarget = thePlayer.GetTarget();
  15554.  
  15555. if( combatTarget )
  15556. {
  15557. combatTarget.Kill( 'AutoFinisher', false, thePlayer );
  15558. thePlayer.SetFinisherVictim( combatTarget );
  15559. forcedFinisherVictim = combatTarget;
  15560. thePlayer.CleanCombatActionBuffer();
  15561. thePlayer.OnBlockAllCombatTickets( true );
  15562. moveTargets = thePlayer.GetMoveTargets();
  15563.  
  15564. for( i = 0; i < moveTargets.Size(); i += 1 )
  15565. {
  15566. if( combatTarget != moveTargets[i] )
  15567. moveTargets[i].SignalGameplayEvent( 'InterruptChargeAttack' );
  15568. }
  15569.  
  15570. if( theGame.GetInGameConfigWrapper().GetVarValue( 'Gameplay', 'AutomaticFinishersEnabled' ) == "true" )
  15571. combatTarget.AddAbility( 'ForceFinisher', false );
  15572.  
  15573. if( combatTarget.HasTag( 'ForceFinisher' ) )
  15574. combatTarget.AddAbility( 'ForceFinisher', false );
  15575.  
  15576. combatTarget.SignalGameplayEvent( 'ForceFinisher' );
  15577.  
  15578. thePlayer.FindMoveTarget();
  15579.  
  15580. thePlayer.AddTimer( 'SignalFinisher', 0.2, false );
  15581. }
  15582. }
  15583.  
  15584. timer function SignalFinisher( time : float , id : int )
  15585. {
  15586. forcedFinisherVictim.SignalGameplayEvent( 'Finisher' );
  15587. forcedFinisherVictim = NULL;
  15588. }
  15589. }
  15590.  
  15591. exec function ttt()
  15592. {
  15593. thePlayer.AddTimer( 'TestTimer', 5, false );
  15594. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement