Advertisement
Guest User

Untitled

a guest
Jan 18th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 102.07 KB | None | 0 0
  1. /***********************************************************************/
  2. /** © 2015 CD PROJEKT S.A. All rights reserved.
  3. /** THE WITCHER® is a trademark of CD PROJEKT S. A.
  4. /** The Witcher game is based on the prose of Andrzej Sapkowski.
  5. /***********************************************************************/
  6.  
  7.  
  8.  
  9.  
  10.  
  11. class W3DamageManagerProcessor extends CObject
  12. {
  13.  
  14. private var playerAttacker : CR4Player;
  15. private var playerVictim : CR4Player;
  16. private var action : W3DamageAction;
  17. private var attackAction : W3Action_Attack;
  18. private var weaponId : SItemUniqueId;
  19. private var actorVictim : CActor;
  20. private var actorAttacker : CActor;
  21. private var dm : CDefinitionsManagerAccessor;
  22. private var attackerMonsterCategory : EMonsterCategory;
  23. private var victimMonsterCategory : EMonsterCategory;
  24. private var victimCanBeHitByFists : bool;
  25.  
  26.  
  27. public function ProcessAction(act : W3DamageAction)
  28. {
  29. var wasAlive, validDamage, isFrozen, autoFinishersEnabled : bool;
  30. var focusDrain : float;
  31. var npc : CNewNPC;
  32. var buffs : array<EEffectType>;
  33. var arrStr : array<string>;
  34. var aerondight : W3Effect_Aerondight;
  35. var trailFxName : name;
  36.  
  37. wasAlive = act.victim.IsAlive();
  38. npc = (CNewNPC)act.victim;
  39.  
  40.  
  41. InitializeActionVars(act);
  42.  
  43.  
  44.  
  45. if(playerVictim && attackAction && attackAction.IsActionMelee() && !attackAction.CanBeParried() && attackAction.IsParried())
  46. {
  47. action.GetEffectTypes(buffs);
  48.  
  49. if(!buffs.Contains(EET_Knockdown) && !buffs.Contains(EET_HeavyKnockdown))
  50. {
  51.  
  52. action.SetParryStagger();
  53.  
  54.  
  55. action.SetProcessBuffsIfNoDamage(true);
  56.  
  57.  
  58. action.AddEffectInfo(EET_LongStagger);
  59.  
  60.  
  61. action.SetHitAnimationPlayType(EAHA_ForceNo);
  62. action.SetCanPlayHitParticle(false);
  63.  
  64.  
  65. action.RemoveBuffsByType(EET_Bleeding);
  66. }
  67. }
  68.  
  69.  
  70. if(actorAttacker && playerVictim && ((W3PlayerWitcher)playerVictim) && GetWitcherPlayer().IsAnyQuenActive())
  71. FactsAdd("player_had_quen");
  72.  
  73.  
  74. ProcessPreHitModifications();
  75.  
  76.  
  77. ProcessActionQuest(act);
  78.  
  79.  
  80. isFrozen = (actorVictim && actorVictim.HasBuff(EET_Frozen));
  81.  
  82.  
  83. validDamage = ProcessActionDamage();
  84.  
  85.  
  86. if(wasAlive && !action.victim.IsAlive())
  87. {
  88. arrStr.PushBack(action.victim.GetDisplayName());
  89. if(npc && npc.WillBeUnconscious())
  90. {
  91. theGame.witcherLog.AddCombatMessage(GetLocStringByKeyExtWithParams("hud_combat_log_unconscious", , , arrStr), NULL, action.victim);
  92. }
  93. else if(action.attacker && action.attacker.GetDisplayName() != "")
  94. {
  95. arrStr.PushBack(action.attacker.GetDisplayName());
  96. theGame.witcherLog.AddCombatMessage(GetLocStringByKeyExtWithParams("hud_combat_log_killed", , , arrStr), action.attacker, action.victim);
  97. }
  98. else
  99. {
  100. theGame.witcherLog.AddCombatMessage(GetLocStringByKeyExtWithParams("hud_combat_log_dies", , , arrStr), NULL, action.victim);
  101. }
  102. }
  103.  
  104. if( wasAlive && action.DealsAnyDamage() )
  105. {
  106. ((CActor) action.attacker).SignalGameplayEventParamFloat( 'CausesDamage', MaxF( action.processedDmg.vitalityDamage, action.processedDmg.essenceDamage ) );
  107. }
  108.  
  109.  
  110. ProcessActionReaction(isFrozen, wasAlive);
  111.  
  112.  
  113. if(action.DealsAnyDamage() || action.ProcessBuffsIfNoDamage())
  114. ProcessActionBuffs();
  115.  
  116.  
  117. if(theGame.CanLog() && !validDamage && action.GetEffectsCount() == 0)
  118. {
  119. LogAssert(false, "W3DamageManagerProcessor.ProcessAction: action deals no damage and gives no buffs - investigate!");
  120. if ( theGame.CanLog() )
  121. {
  122. LogDMHits("*** Action has no valid damage and no valid buffs - investigate!", action);
  123. }
  124. }
  125.  
  126.  
  127. if( actorAttacker && wasAlive )
  128. actorAttacker.OnProcessActionPost(action);
  129.  
  130.  
  131. if(actorVictim == GetWitcherPlayer() && action.DealsAnyDamage() && !action.IsDoTDamage())
  132. {
  133. if(actorAttacker && attackAction)
  134. {
  135. if(actorAttacker.IsHeavyAttack( attackAction.GetAttackName() ))
  136. focusDrain = CalculateAttributeValue(thePlayer.GetAttributeValue('heavy_attack_focus_drain'));
  137. else if(actorAttacker.IsSuperHeavyAttack( attackAction.GetAttackName() ))
  138. focusDrain = CalculateAttributeValue(thePlayer.GetAttributeValue('super_heavy_attack_focus_drain'));
  139. else
  140. focusDrain = CalculateAttributeValue(thePlayer.GetAttributeValue('light_attack_focus_drain'));
  141. }
  142. else
  143. {
  144.  
  145. focusDrain = CalculateAttributeValue(thePlayer.GetAttributeValue('light_attack_focus_drain'));
  146. }
  147.  
  148.  
  149. if ( GetWitcherPlayer().CanUseSkill(S_Sword_s16) )
  150. focusDrain *= 1 - (CalculateAttributeValue( thePlayer.GetSkillAttributeValue(S_Sword_s16, 'focus_drain_reduction', false, true) ) * thePlayer.GetSkillLevel(S_Sword_s16));
  151.  
  152. thePlayer.DrainFocus(focusDrain);
  153. }
  154.  
  155.  
  156. if(actorAttacker == GetWitcherPlayer() && actorVictim && !actorVictim.IsAlive() && (action.IsActionMelee() || action.GetBuffSourceName() == "Kill"))
  157. {
  158. autoFinishersEnabled = theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'AutomaticFinishersEnabled');
  159.  
  160.  
  161.  
  162.  
  163. if(!autoFinishersEnabled || !thePlayer.GetFinisherVictim())
  164. {
  165. if(thePlayer.HasAbility('Runeword 10 _Stats', true))
  166. GetWitcherPlayer().Runeword10Triggerred();
  167. if(thePlayer.HasAbility('Runeword 12 _Stats', true))
  168. GetWitcherPlayer().Runeword12Triggerred();
  169. }
  170. }
  171.  
  172.  
  173. if(action.EndsQuen() && actorVictim)
  174. {
  175. actorVictim.FinishQuen(false);
  176. }
  177.  
  178.  
  179. if(actorVictim == thePlayer && attackAction && attackAction.IsActionMelee() && (ShouldProcessTutorial('TutorialDodge') || ShouldProcessTutorial('TutorialCounter') || ShouldProcessTutorial('TutorialParry')) )
  180. {
  181. if(attackAction.IsCountered())
  182. {
  183. theGame.GetTutorialSystem().IncreaseCounters();
  184. }
  185. else if(attackAction.IsParried())
  186. {
  187. theGame.GetTutorialSystem().IncreaseParries();
  188. }
  189.  
  190. if(attackAction.CanBeDodged() && !attackAction.WasDodged())
  191. {
  192. GameplayFactsAdd("tut_failed_dodge", 1, 1);
  193. GameplayFactsAdd("tut_failed_roll", 1, 1);
  194. }
  195. }
  196.  
  197. if( playerAttacker && npc && action.IsActionMelee() && action.DealtDamage() && IsRequiredAttitudeBetween( playerAttacker, npc, true ) && !npc.HasTag( 'AerondightIgnore' ) )
  198. {
  199. if( playerAttacker.inv.ItemHasTag( attackAction.GetWeaponId(), 'Aerondight' ) )
  200. {
  201.  
  202. aerondight = (W3Effect_Aerondight)playerAttacker.GetBuff( EET_Aerondight );
  203. aerondight.IncreaseAerondightCharges( attackAction.GetAttackName() );
  204.  
  205.  
  206. if( aerondight.GetCurrentCount() == aerondight.GetMaxCount() )
  207. {
  208. switch( npc.GetBloodType() )
  209. {
  210. case BT_Red :
  211. trailFxName = 'aerondight_blood_red';
  212. break;
  213.  
  214. case BT_Yellow :
  215. trailFxName = 'aerondight_blood_yellow';
  216. break;
  217.  
  218. case BT_Black :
  219. trailFxName = 'aerondight_blood_black';
  220. break;
  221.  
  222. case BT_Green :
  223. trailFxName = 'aerondight_blood_green';
  224. break;
  225. }
  226.  
  227. playerAttacker.inv.GetItemEntityUnsafe( attackAction.GetWeaponId() ).PlayEffect( trailFxName );
  228. }
  229. }
  230. }
  231. }
  232. }
  233. {
  234. private final function InitializeActionVars(act : W3DamageAction)
  235. {
  236. var tmpName : name;
  237. var tmpBool : bool;
  238.  
  239. action = act;
  240. playerAttacker = (CR4Player)action.attacker;
  241. playerVictim = (CR4Player)action.victim;
  242. attackAction = (W3Action_Attack)action;
  243. actorVictim = (CActor)action.victim;
  244. actorAttacker = (CActor)action.attacker;
  245. dm = theGame.GetDefinitionsManager();
  246.  
  247. if(attackAction)
  248. weaponId = attackAction.GetWeaponId();
  249.  
  250. theGame.GetMonsterParamsForActor(actorVictim, victimMonsterCategory, tmpName, tmpBool, tmpBool, victimCanBeHitByFists);
  251.  
  252. if(actorAttacker)
  253. theGame.GetMonsterParamsForActor(actorAttacker, attackerMonsterCategory, tmpName, tmpBool, tmpBool, tmpBool);
  254. }
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261. private function ProcessActionQuest(act : W3DamageAction)
  262. {
  263. var victimTags, attackerTags : array<name>;
  264.  
  265. victimTags = action.victim.GetTags();
  266.  
  267. if(action.attacker)
  268. attackerTags = action.attacker.GetTags();
  269.  
  270. AddHitFacts( victimTags, attackerTags, "_weapon_hit" );
  271.  
  272.  
  273. if ((CGameplayEntity) action.victim) action.victim.OnWeaponHit(act);
  274. }
  275.  
  276.  
  277.  
  278.  
  279.  
  280. private function ProcessActionDamage() : bool
  281. {
  282. var directDmgIndex, size, i : int;
  283. var dmgInfos : array< SRawDamage >;
  284. var immortalityMode : EActorImmortalityMode;
  285. var dmgValue : float;
  286. var anyDamageProcessed, fallingRaffard : bool;
  287. var victimHealthPercBeforeHit, frozenAdditionalDamage : float;
  288. var powerMod : SAbilityAttributeValue;
  289. var witcher : W3PlayerWitcher;
  290. var canLog : bool;
  291. var immortalityChannels : array<EActorImmortalityChanel>;
  292. var boltCauser : W3BoltProjectile; // AeroHD -- TES+
  293.  
  294. canLog = theGame.CanLog();
  295.  
  296.  
  297. action.SetAllProcessedDamageAs(0);
  298. size = action.GetDTs( dmgInfos );
  299. action.SetDealtFireDamage(false);
  300.  
  301. // AeroHD -- TES+
  302. witcher = GetWitcherPlayer();
  303.  
  304. // CrossbowDamageBoost
  305. boltCauser = (W3BoltProjectile)(action.causer);
  306. if (witcher == playerAttacker && action.IsActionRanged() && boltCauser && attackAction && actorVictim)
  307. {
  308. witcher.crossbowDmgProcessor.ProcessBoltDamage(dmgInfos, attackAction, boltCauser, actorVictim);
  309. }
  310.  
  311. if(!actorVictim || (!actorVictim.UsesVitality() && !actorVictim.UsesEssence()) )
  312. {
  313.  
  314. for(i=0; i<size; i+=1)
  315. {
  316. if(dmgInfos[i].dmgType == theGame.params.DAMAGE_NAME_FIRE && dmgInfos[i].dmgVal > 0)
  317. {
  318. action.victim.OnFireHit( (CGameplayEntity)action.causer );
  319. break;
  320. }
  321. }
  322.  
  323. if ( !actorVictim.abilityManager )
  324. actorVictim.OnDeath(action);
  325.  
  326. return false;
  327. }
  328. // AeroHD -- TES-
  329.  
  330. if(actorVictim.UsesVitality())
  331. victimHealthPercBeforeHit = actorVictim.GetStatPercents(BCS_Vitality);
  332. else
  333. victimHealthPercBeforeHit = actorVictim.GetStatPercents(BCS_Essence);
  334.  
  335.  
  336. ProcessDamageIncrease( dmgInfos );
  337.  
  338.  
  339. if ( canLog )
  340. {
  341. LogBeginning();
  342. }
  343.  
  344.  
  345. ProcessCriticalHitCheck();
  346.  
  347.  
  348. ProcessOnBeforeHitChecks();
  349.  
  350.  
  351. powerMod = GetAttackersPowerMod();
  352.  
  353.  
  354. anyDamageProcessed = false;
  355. directDmgIndex = -1;
  356. witcher = GetWitcherPlayer();
  357. size = dmgInfos.Size();
  358. for( i = 0; i < size; i += 1 )
  359. {
  360.  
  361. if(dmgInfos[i].dmgVal == 0)
  362. continue;
  363.  
  364. if(dmgInfos[i].dmgType == theGame.params.DAMAGE_NAME_DIRECT)
  365. {
  366. directDmgIndex = i;
  367. continue;
  368. }
  369.  
  370.  
  371. if(dmgInfos[i].dmgType == theGame.params.DAMAGE_NAME_POISON && witcher == actorVictim && witcher.HasBuff(EET_GoldenOriole) && witcher.GetPotionBuffLevel(EET_GoldenOriole) == 3)
  372. {
  373.  
  374. witcher.GainStat(BCS_Vitality, dmgInfos[i].dmgVal);
  375.  
  376.  
  377. if ( canLog )
  378. {
  379. LogDMHits("", action);
  380. LogDMHits("*** Player absorbs poison damage from level 3 Golden Oriole potion: " + dmgInfos[i].dmgVal, action);
  381. }
  382.  
  383.  
  384. dmgInfos[i].dmgVal = 0;
  385.  
  386. continue;
  387. }
  388.  
  389.  
  390. if ( canLog )
  391. {
  392. LogDMHits("", action);
  393. LogDMHits("*** Incoming " + NoTrailZeros(dmgInfos[i].dmgVal) + " " + dmgInfos[i].dmgType + " damage", action);
  394. if(action.IsDoTDamage())
  395. LogDMHits("DoT's current dt = " + NoTrailZeros(action.GetDoTdt()) + ", estimated dps = " + NoTrailZeros(dmgInfos[i].dmgVal / action.GetDoTdt()), action);
  396. }
  397.  
  398.  
  399. anyDamageProcessed = true;
  400.  
  401.  
  402. dmgValue = MaxF(0, CalculateDamage(dmgInfos[i], powerMod));
  403.  
  404.  
  405. if( DamageHitsEssence( dmgInfos[i].dmgType ) ) action.processedDmg.essenceDamage += dmgValue;
  406. if( DamageHitsVitality( dmgInfos[i].dmgType ) ) action.processedDmg.vitalityDamage += dmgValue;
  407. if( DamageHitsMorale( dmgInfos[i].dmgType ) ) action.processedDmg.moraleDamage += dmgValue;
  408. if( DamageHitsStamina( dmgInfos[i].dmgType ) ) action.processedDmg.staminaDamage += dmgValue;
  409. }
  410.  
  411. if(size == 0 && canLog)
  412. {
  413. LogDMHits("*** There is no incoming damage set (probably only buffs).", action);
  414. }
  415.  
  416. if ( canLog )
  417. {
  418. LogDMHits("", action);
  419. LogDMHits("Processing block, parry, immortality, signs and other GLOBAL damage reductions...", action);
  420. }
  421.  
  422. if (actorVictim && actorAttacker && actorAttacker != GetWitcherPlayer() && actorVictim != GetWitcherPlayer()
  423. && (actorVictim.HasBuff(EET_AxiiGuardMe) || actorAttacker.HasBuff(EET_AxiiGuardMe)))
  424. AdjustDamageAxiiPuppet();
  425.  
  426. if(actorVictim)
  427. actorVictim.ReduceDamage(action);
  428.  
  429.  
  430. if(directDmgIndex != -1)
  431. {
  432. anyDamageProcessed = true;
  433.  
  434.  
  435. immortalityChannels = actorVictim.GetImmortalityModeChannels(AIM_Invulnerable);
  436. fallingRaffard = immortalityChannels.Size() == 1 && immortalityChannels.Contains(AIC_WhiteRaffardsPotion) && action.GetBuffSourceName() == "FallingDamage";
  437.  
  438. if(action.GetIgnoreImmortalityMode() || (!actorVictim.IsImmortal() && !actorVictim.IsInvulnerable() && !actorVictim.IsKnockedUnconscious()) || fallingRaffard)
  439. {
  440. action.processedDmg.vitalityDamage += dmgInfos[directDmgIndex].dmgVal;
  441. action.processedDmg.essenceDamage += dmgInfos[directDmgIndex].dmgVal;
  442. }
  443. else if( actorVictim.IsInvulnerable() )
  444. {
  445.  
  446. }
  447. else if( actorVictim.IsImmortal() )
  448. {
  449.  
  450. action.processedDmg.vitalityDamage += MinF(dmgInfos[directDmgIndex].dmgVal, actorVictim.GetStat(BCS_Vitality)-1 );
  451. action.processedDmg.essenceDamage += MinF(dmgInfos[directDmgIndex].dmgVal, actorVictim.GetStat(BCS_Essence)-1 );
  452. }
  453. }
  454.  
  455.  
  456. if( actorVictim.HasAbility( 'OneShotImmune' ) )
  457. {
  458. if( action.processedDmg.vitalityDamage >= actorVictim.GetStatMax( BCS_Vitality ) )
  459. {
  460. action.processedDmg.vitalityDamage = actorVictim.GetStatMax( BCS_Vitality ) - 1;
  461. }
  462. else if( action.processedDmg.essenceDamage >= actorVictim.GetStatMax( BCS_Essence ) )
  463. {
  464. action.processedDmg.essenceDamage = actorVictim.GetStatMax( BCS_Essence ) - 1;
  465. }
  466. }
  467.  
  468.  
  469. if(action.HasDealtFireDamage())
  470. action.victim.OnFireHit( (CGameplayEntity)action.causer );
  471.  
  472.  
  473. ProcessInstantKill();
  474.  
  475.  
  476. ProcessActionDamage_DealDamage();
  477.  
  478.  
  479. if(playerAttacker && witcher)
  480. witcher.SetRecentlyCountered(false);
  481.  
  482.  
  483. if( attackAction && !attackAction.IsCountered() && playerVictim && attackAction.IsActionMelee())
  484. theGame.GetGamerProfile().ResetStat(ES_CounterattackChain);
  485.  
  486.  
  487. ProcessActionDamage_ReduceDurability();
  488.  
  489.  
  490. if(playerAttacker && actorVictim)
  491. {
  492.  
  493. if(playerAttacker.inv.ItemHasAnyActiveOilApplied(weaponId) && (!playerAttacker.CanUseSkill(S_Alchemy_s06) || (playerAttacker.GetSkillLevel(S_Alchemy_s06) < 3)) )
  494. {
  495. playerAttacker.ReduceAllOilsAmmo( weaponId );
  496.  
  497. if(ShouldProcessTutorial('TutorialOilAmmo'))
  498. {
  499. FactsAdd("tut_used_oil_in_combat");
  500. }
  501. }
  502.  
  503.  
  504. playerAttacker.inv.ReduceItemRepairObjectBonusCharge(weaponId);
  505. }
  506.  
  507.  
  508. if(actorVictim && actorAttacker && !action.GetCannotReturnDamage() )
  509. ProcessActionReturnedDamage();
  510.  
  511. return anyDamageProcessed;
  512. }
  513.  
  514.  
  515. private function ProcessInstantKill()
  516. {
  517. var instantKill, focus : float;
  518.  
  519. if( !actorVictim || !actorAttacker || actorVictim.IsImmuneToInstantKill() )
  520. {
  521. return;
  522. }
  523.  
  524.  
  525. if( action.WasDodged() || ( attackAction && ( attackAction.IsParried() || attackAction.IsCountered() ) ) )
  526. {
  527. return;
  528. }
  529.  
  530. if( actorAttacker.HasAbility( 'ForceInstantKill' ) && actorVictim != thePlayer )
  531. {
  532. action.SetInstantKill();
  533. }
  534.  
  535.  
  536. if( actorAttacker == thePlayer && !action.GetIgnoreInstantKillCooldown() )
  537. {
  538. if( !GameTimeDTAtLeastRealSecs( thePlayer.lastInstantKillTime, theGame.GetGameTime(), theGame.params.INSTANT_KILL_INTERNAL_PLAYER_COOLDOWN ) )
  539. {
  540. return;
  541. }
  542. }
  543.  
  544.  
  545. if( !action.GetInstantKill() )
  546. {
  547.  
  548. instantKill = CalculateAttributeValue( actorAttacker.GetInventory().GetItemAttributeValue( weaponId, 'instant_kill_chance' ) );
  549.  
  550.  
  551. if( ( action.IsActionMelee() || action.IsActionRanged() ) && playerAttacker && action.DealsAnyDamage() && thePlayer.CanUseSkill( S_Sword_s03 ) && !playerAttacker.inv.IsItemFists( weaponId ) )
  552. {
  553. focus = thePlayer.GetStat( BCS_Focus );
  554.  
  555. if( focus >= 1 )
  556. {
  557. instantKill += focus * CalculateAttributeValue( thePlayer.GetSkillAttributeValue( S_Sword_s03, 'instant_kill_chance', false, true ) ) * thePlayer.GetSkillLevel( S_Sword_s03 );
  558. }
  559. }
  560. }
  561.  
  562.  
  563. if( action.GetInstantKill() || ( RandF() < instantKill ) )
  564. {
  565. if( theGame.CanLog() )
  566. {
  567. if( action.GetInstantKill() )
  568. {
  569. instantKill = 1.f;
  570. }
  571. LogDMHits( "Instant kill!! (" + NoTrailZeros( instantKill * 100 ) + "% chance", action );
  572. }
  573.  
  574. action.processedDmg.vitalityDamage += actorVictim.GetStat( BCS_Vitality );
  575. action.processedDmg.essenceDamage += actorVictim.GetStat( BCS_Essence );
  576. action.SetCriticalHit();
  577. action.SetInstantKillFloater();
  578.  
  579.  
  580. if( playerAttacker )
  581. {
  582. thePlayer.SetLastInstantKillTime( theGame.GetGameTime() );
  583. theSound.SoundEvent( 'cmb_play_deadly_hit' );
  584. theGame.SetTimeScale( 0.2, theGame.GetTimescaleSource( ETS_InstantKill ), theGame.GetTimescalePriority( ETS_InstantKill ), true, true );
  585. thePlayer.AddTimer( 'RemoveInstantKillSloMo', 0.2 );
  586. }
  587. }
  588. }
  589.  
  590.  
  591. private function ProcessOnBeforeHitChecks()
  592. {
  593. var effectAbilityName, monsterBonusType : name;
  594. var effectType : EEffectType;
  595. var null, monsterBonusVal : SAbilityAttributeValue;
  596. var oilLevel, skillLevel, i : int;
  597. var baseChance, perOilLevelChance, chance : float;
  598. var buffs : array<name>;
  599.  
  600.  
  601. if( playerAttacker && actorVictim && attackAction && attackAction.IsActionMelee() && playerAttacker.CanUseSkill(S_Alchemy_s12) && playerAttacker.inv.ItemHasActiveOilApplied( weaponId, victimMonsterCategory ) )
  602. {
  603.  
  604. monsterBonusType = MonsterCategoryToAttackPowerBonus(victimMonsterCategory);
  605. monsterBonusVal = playerAttacker.inv.GetItemAttributeValue(weaponId, monsterBonusType);
  606.  
  607. if(monsterBonusVal != null)
  608. {
  609.  
  610. oilLevel = (int)CalculateAttributeValue(playerAttacker.inv.GetItemAttributeValue(weaponId, 'level')) - 1;
  611. skillLevel = playerAttacker.GetSkillLevel(S_Alchemy_s12);
  612. baseChance = CalculateAttributeValue(playerAttacker.GetSkillAttributeValue(S_Alchemy_s12, 'skill_chance', false, true));
  613. perOilLevelChance = CalculateAttributeValue(playerAttacker.GetSkillAttributeValue(S_Alchemy_s12, 'oil_level_chance', false, true));
  614. chance = baseChance * skillLevel + perOilLevelChance * oilLevel;
  615.  
  616.  
  617. if(RandF() < chance)
  618. {
  619.  
  620. dm.GetContainedAbilities(playerAttacker.GetSkillAbilityName(S_Alchemy_s12), buffs);
  621. for(i=0; i<buffs.Size(); i+=1)
  622. {
  623. EffectNameToType(buffs[i], effectType, effectAbilityName);
  624. action.AddEffectInfo(effectType, , , effectAbilityName);
  625. }
  626. }
  627. }
  628. }
  629. }
  630.  
  631.  
  632. private function ProcessCriticalHitCheck()
  633. {
  634. var critChance, critDamageBonus : float;
  635. var canLog, meleeOrRanged, redWolfSet, isLightAttack, isHeavyAttack, signCritical : bool;
  636. var arrStr : array<string>;
  637. var samum : CBaseGameplayEffect;
  638. var signPower, min, max : SAbilityAttributeValue;
  639. var aerondight : W3Effect_Aerondight;
  640. var boltCauser : W3BoltProjectile; // AeroHD -- TES+
  641.  
  642. meleeOrRanged = playerAttacker && attackAction && ( attackAction.IsActionMelee() || attackAction.IsActionRanged() );
  643. redWolfSet = ( W3Petard )action.causer && ( W3PlayerWitcher )actorAttacker && GetWitcherPlayer().IsSetBonusActive( EISB_RedWolf_1 );
  644. signCritical = theGame.GetDLCManager().IsEP2Available() && ( W3PlayerWitcher )actorAttacker
  645. && (GetWitcherPlayer().IsMutationActive(EPMT_Mutation2) || GetWitcherPlayer().CanUseSkill(S_Perk_11) || GetWitcherPlayer().HasBuff(EET_Mutagen01))
  646. && action.IsActionWitcherSign();
  647.  
  648.  
  649. if( meleeOrRanged || redWolfSet || signCritical )
  650. {
  651. canLog = theGame.CanLog();
  652.  
  653.  
  654. if( signCritical )
  655. {
  656. if( FactsQuerySum('debug_fact_critical_boy') > 0 )
  657. {
  658. critChance = 1.f;
  659. }
  660. else
  661. {
  662. critChance = 0;
  663.  
  664. if (GetWitcherPlayer().IsMutationActive(EPMT_Mutation2))
  665. {
  666. signPower = action.GetPowerStatValue();
  667. theGame.GetDefinitionsManager().GetAbilityAttributeValue('Mutation2', 'crit_chance_factor', min, max);
  668. critChance += min.valueAdditive + signPower.valueMultiplicative * min.valueMultiplicative;
  669. }
  670.  
  671. if (GetWitcherPlayer().CanUseSkill(S_Perk_11))
  672. {
  673. critChance += 0.08f;
  674. }
  675.  
  676. if (GetWitcherPlayer().HasBuff(EET_Mutagen01))
  677. {
  678. critChance += 0.08f;
  679. }
  680. }
  681. }
  682. else
  683. {
  684. if( attackAction )
  685. {
  686.  
  687. if( SkillEnumToName(S_Sword_s02) == attackAction.GetAttackTypeName() )
  688. {
  689. critChance += CalculateAttributeValue(playerAttacker.GetSkillAttributeValue(S_Sword_s02, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * playerAttacker.GetSkillLevel(S_Sword_s02);
  690. }
  691.  
  692.  
  693. if(GetWitcherPlayer() && GetWitcherPlayer().HasRecentlyCountered() && playerAttacker.CanUseSkill(S_Sword_s11) && playerAttacker.GetSkillLevel(S_Sword_s11) > 2)
  694. {
  695. critChance += CalculateAttributeValue(playerAttacker.GetSkillAttributeValue(S_Sword_s11, theGame.params.CRITICAL_HIT_CHANCE, false, true));
  696. }
  697.  
  698.  
  699. isLightAttack = playerAttacker.IsLightAttack( attackAction.GetAttackName() );
  700. isHeavyAttack = playerAttacker.IsHeavyAttack( attackAction.GetAttackName() );
  701. // AeroHD -- TES+
  702. boltCauser = (W3BoltProjectile)action.causer;
  703. critChance += playerAttacker.GetCriticalHitChance(isLightAttack, isHeavyAttack, actorVictim, victimMonsterCategory, boltCauser);
  704.  
  705. // CrossbowDamageBoost
  706. if ( ( W3PlayerWitcher )actorAttacker && boltCauser)
  707. {
  708. if (boltCauser.GetWasAimedBolt())
  709. {
  710. // Doubling crit chance for aimed bolt for precision skill and cat eyes mutation
  711. if (playerAttacker.CanUseSkill(S_Sword_s07))
  712. {
  713. critChance += CalculateAttributeValue(playerAttacker.GetSkillAttributeValue(S_Sword_s07, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * playerAttacker.GetSkillLevel(S_Sword_s07);
  714. }
  715.  
  716. if ( ((W3PlayerWitcher)actorAttacker).IsMutationActive( EPMT_Mutation9 ) )
  717. {
  718. theGame.GetDefinitionsManager().GetAbilityAttributeValue('Mutation9', 'critical_hit_chance', min, max);
  719. critChance += 0.75 * min.valueMultiplicative;;
  720. }
  721. }
  722.  
  723. critChance -= GetWitcherPlayer().GetCrossbowCritChanceReduction();
  724. }
  725. // AeroHD -- TES-
  726.  
  727. if(action.GetIsHeadShot())
  728. {
  729. critChance += theGame.params.HEAD_SHOT_CRIT_CHANCE_BONUS;
  730. actorVictim.SignalGameplayEvent( 'Headshot' );
  731. }
  732.  
  733.  
  734. if ( actorVictim && actorVictim.IsAttackerAtBack(playerAttacker) )
  735. {
  736. critChance += theGame.params.BACK_ATTACK_CRIT_CHANCE_BONUS;
  737. }
  738.  
  739.  
  740. if( action.IsActionMelee() && playerAttacker.inv.ItemHasTag( attackAction.GetWeaponId(), 'Aerondight' ) )
  741. {
  742. aerondight = (W3Effect_Aerondight)playerAttacker.GetBuff( EET_Aerondight );
  743.  
  744. if( aerondight && aerondight.IsFullyCharged() )
  745. {
  746.  
  747. min = playerAttacker.GetAbilityAttributeValue( 'AerondightEffect', 'crit_chance_bonus' );
  748. critChance += min.valueAdditive;
  749. }
  750. }
  751. }
  752. else
  753. {
  754.  
  755. critChance += playerAttacker.GetCriticalHitChance(false, false, actorVictim, victimMonsterCategory, (W3BoltProjectile)action.causer );
  756. }
  757.  
  758.  
  759. samum = actorVictim.GetBuff(EET_Blindness, 'petard');
  760. if(samum && samum.GetBuffLevel() == 3)
  761. {
  762. critChance += 1.0f;
  763. }
  764. }
  765.  
  766.  
  767. if ( canLog )
  768. {
  769.  
  770. critDamageBonus = 1 + CalculateAttributeValue(actorAttacker.GetCriticalHitDamageBonus(weaponId, victimMonsterCategory, actorVictim.IsAttackerAtBack(playerAttacker)));
  771. critDamageBonus += CalculateAttributeValue(actorAttacker.GetAttributeValue('critical_hit_chance_fast_style'));
  772. critDamageBonus = 100 * critDamageBonus;
  773.  
  774.  
  775. LogDMHits("", action);
  776. LogDMHits("Trying critical hit (" + NoTrailZeros(critChance*100) + "% chance, dealing " + NoTrailZeros(critDamageBonus) + "% damage)...", action);
  777. }
  778.  
  779.  
  780. if(RandF() < critChance)
  781. {
  782.  
  783. action.SetCriticalHit();
  784.  
  785. if ( canLog )
  786. {
  787. LogDMHits("********************", action);
  788. LogDMHits("*** CRITICAL HIT ***", action);
  789. LogDMHits("********************", action);
  790. }
  791.  
  792. if (!((W3IgniProjectile)action.causer))
  793. {
  794. arrStr.PushBack(action.attacker.GetDisplayName());
  795.  
  796.  
  797. if (GetBossbowConfig().printDamage == false) {
  798. if (!action.IsActionRanged()) {
  799. theGame.witcherLog.AddCombatMessage(theGame.witcherLog.COLOR_GOLD_BEGIN + GetLocStringByKeyExtWithParams("hud_combat_log_critical_hit",,,arrStr) + theGame.witcherLog.COLOR_GOLD_END, action.attacker, NULL);
  800. }
  801. } else {
  802. theGame.witcherLog.AddCombatMessage(theGame.witcherLog.COLOR_GOLD_BEGIN + GetLocStringByKeyExtWithParams("hud_combat_log_critical_hit",,,arrStr) + theGame.witcherLog.COLOR_GOLD_END, action.attacker, NULL);
  803. }
  804. }
  805. else if ( canLog )
  806. {
  807. LogDMHits("... nope", action);
  808. }
  809. }
  810. }
  811.  
  812.  
  813. private function LogBeginning()
  814. {
  815. var logStr : string;
  816.  
  817. if ( !theGame.CanLog() )
  818. {
  819. return;
  820. }
  821.  
  822. LogDMHits("-----------------------------------------------------------------------------------", action);
  823. logStr = "Beginning hit processing from <<" + action.attacker + ">> to <<" + action.victim + ">> via <<" + action.causer + ">>";
  824. if(attackAction)
  825. {
  826. logStr += " using AttackType <<" + attackAction.GetAttackTypeName() + ">>";
  827. }
  828. logStr += ":";
  829. LogDMHits(logStr, action);
  830. LogDMHits("", action);
  831. LogDMHits("Target stats before damage dealt are:", action);
  832. if(actorVictim)
  833. {
  834. if( actorVictim.UsesVitality() )
  835. LogDMHits("Vitality = " + NoTrailZeros(actorVictim.GetStat(BCS_Vitality)), action);
  836. if( actorVictim.UsesEssence() )
  837. LogDMHits("Essence = " + NoTrailZeros(actorVictim.GetStat(BCS_Essence)), action);
  838. if( actorVictim.GetStatMax(BCS_Stamina) > 0)
  839. LogDMHits("Stamina = " + NoTrailZeros(actorVictim.GetStat(BCS_Stamina, true)), action);
  840. if( actorVictim.GetStatMax(BCS_Morale) > 0)
  841. LogDMHits("Morale = " + NoTrailZeros(actorVictim.GetStat(BCS_Morale)), action);
  842. }
  843. else
  844. {
  845. LogDMHits("Undefined - victim is not a CActor and therefore has no stats", action);
  846. }
  847. }
  848.  
  849.  
  850. private function ProcessDamageIncrease(out dmgInfos : array< SRawDamage >)
  851. {
  852. var difficultyDamageMultiplier, rendLoad, rendBonus, overheal, rendRatio, focusCost : float;
  853. var i, bonusCount : int;
  854. var frozenBuff : W3Effect_Frozen;
  855. var frozenDmgInfo : SRawDamage;
  856. var hadFrostDamage : bool;
  857. var mpac : CMovingPhysicalAgentComponent;
  858. var rendBonusPerPoint, staminaRendBonus, perk20Bonus : SAbilityAttributeValue;
  859. var witcherAttacker : W3PlayerWitcher;
  860. var damageVal, damageBonus, min, max : SAbilityAttributeValue;
  861. var npcVictim : CNewNPC;
  862. var sword : SItemUniqueId;
  863. var actionFreeze : W3DamageAction;
  864. var aerondight : W3Effect_Aerondight;
  865.  
  866.  
  867.  
  868. if(actorAttacker && !actorAttacker.IgnoresDifficultySettings() && !action.IsDoTDamage())
  869. {
  870. difficultyDamageMultiplier = CalculateAttributeValue(actorAttacker.GetAttributeValue(theGame.params.DIFFICULTY_DMG_MULTIPLIER));
  871. for(i=0; i<dmgInfos.Size(); i+=1)
  872. {
  873. dmgInfos[i].dmgVal = dmgInfos[i].dmgVal * difficultyDamageMultiplier;
  874. }
  875. }
  876.  
  877.  
  878.  
  879.  
  880. if(actorVictim && playerAttacker && !action.IsDoTDamage() && actorVictim.HasBuff(EET_Frozen) && ( (W3AardProjectile)action.causer || (W3AardEntity)action.causer || action.DealsPhysicalOrSilverDamage()) )
  881. {
  882.  
  883. action.SetWasFrozen();
  884.  
  885.  
  886. if( !( ( W3WhiteFrost )action.causer ) )
  887. {
  888. frozenBuff = (W3Effect_Frozen)actorVictim.GetBuff(EET_Frozen);
  889. frozenDmgInfo.dmgVal = frozenBuff.GetAdditionalDamagePercents() * actorVictim.GetHealth();
  890. }
  891.  
  892.  
  893. actorVictim.RemoveAllBuffsOfType(EET_Frozen);
  894. action.AddEffectInfo(EET_KnockdownTypeApplicator);
  895.  
  896.  
  897. if( !( ( W3WhiteFrost )action.causer ) )
  898. {
  899. actionFreeze = new W3DamageAction in theGame;
  900. actionFreeze.Initialize( actorAttacker, actorVictim, action.causer, action.GetBuffSourceName(), EHRT_None, CPS_Undefined, action.IsActionMelee(), action.IsActionRanged(), action.IsActionWitcherSign(), action.IsActionEnvironment() );
  901. actionFreeze.SetCannotReturnDamage( true );
  902. actionFreeze.SetCanPlayHitParticle( false );
  903. actionFreeze.SetHitAnimationPlayType( EAHA_ForceNo );
  904. actionFreeze.SetWasFrozen();
  905. actionFreeze.AddDamage( theGame.params.DAMAGE_NAME_FROST, frozenDmgInfo.dmgVal );
  906. theGame.damageMgr.ProcessAction( actionFreeze );
  907. delete actionFreeze;
  908. }
  909. }
  910.  
  911.  
  912. if(actorVictim)
  913. {
  914. mpac = (CMovingPhysicalAgentComponent)actorVictim.GetMovingAgentComponent();
  915.  
  916. if(mpac && mpac.IsDiving())
  917. {
  918. mpac = (CMovingPhysicalAgentComponent)actorAttacker.GetMovingAgentComponent();
  919.  
  920. if(mpac && mpac.IsDiving())
  921. {
  922. action.SetUnderwaterDisplayDamageHack();
  923.  
  924. if(playerAttacker && attackAction && attackAction.IsActionRanged())
  925. {
  926. for(i=0; i<dmgInfos.Size(); i+=1)
  927. {
  928. if(FactsQuerySum("NewGamePlus"))
  929. {
  930. dmgInfos[i].dmgVal *= (1 + theGame.params.UNDERWATER_CROSSBOW_DAMAGE_BONUS_NGP);
  931. }
  932. else
  933. {
  934. dmgInfos[i].dmgVal *= (1 + theGame.params.UNDERWATER_CROSSBOW_DAMAGE_BONUS);
  935. }
  936. }
  937. }
  938. }
  939. }
  940. }
  941.  
  942.  
  943. if(playerAttacker && attackAction && SkillNameToEnum(attackAction.GetAttackTypeName()) == S_Sword_s02)
  944. {
  945. witcherAttacker = (W3PlayerWitcher)playerAttacker;
  946.  
  947.  
  948. rendRatio = witcherAttacker.GetSpecialAttackTimeRatio();
  949.  
  950.  
  951. rendLoad = MinF(rendRatio * playerAttacker.GetStatMax(BCS_Focus), playerAttacker.GetStat(BCS_Focus));
  952.  
  953.  
  954. if(rendLoad >= 1)
  955. {
  956. rendBonusPerPoint = witcherAttacker.GetSkillAttributeValue(S_Sword_s02, 'adrenaline_final_damage_bonus', false, true);
  957. rendBonus = FloorF(rendLoad) * rendBonusPerPoint.valueMultiplicative;
  958.  
  959. for(i=0; i<dmgInfos.Size(); i+=1)
  960. {
  961. dmgInfos[i].dmgVal *= (1 + rendBonus);
  962. }
  963. }
  964.  
  965.  
  966. staminaRendBonus = witcherAttacker.GetSkillAttributeValue(S_Sword_s02, 'stamina_max_dmg_bonus', false, true);
  967.  
  968. for(i=0; i<dmgInfos.Size(); i+=1)
  969. {
  970. dmgInfos[i].dmgVal *= (1 + rendRatio * staminaRendBonus.valueMultiplicative);
  971. }
  972. }
  973.  
  974.  
  975. if ( actorAttacker != thePlayer && action.IsActionRanged() && (int)CalculateAttributeValue(actorAttacker.GetAttributeValue('level',,true)) > 31)
  976. {
  977. damageVal = actorAttacker.GetAttributeValue('light_attack_damage_vitality',,true);
  978. for(i=0; i<dmgInfos.Size(); i+=1)
  979. {
  980. dmgInfos[i].dmgVal = dmgInfos[i].dmgVal + CalculateAttributeValue(damageVal) / 2;
  981. }
  982. }
  983.  
  984.  
  985. if ( actorVictim && playerAttacker && attackAction && action.IsActionMelee() && thePlayer.HasAbility('Runeword 4 _Stats', true) && !attackAction.WasDodged() )
  986. {
  987. overheal = thePlayer.abilityManager.GetOverhealBonus() / thePlayer.GetStatMax(BCS_Vitality);
  988.  
  989. if(overheal > 0.005f)
  990. {
  991. for(i=0; i<dmgInfos.Size(); i+=1)
  992. {
  993. dmgInfos[i].dmgVal *= 1.0f + overheal;
  994. }
  995.  
  996. thePlayer.abilityManager.ResetOverhealBonus();
  997.  
  998.  
  999. actorVictim.CreateFXEntityAtPelvis( 'runeword_4', true );
  1000. }
  1001. }
  1002.  
  1003.  
  1004. if( playerAttacker && playerAttacker.IsLightAttack( attackAction.GetAttackName() ) && playerAttacker.HasBuff( EET_LynxSetBonus ) && !attackAction.WasDodged() )
  1005. {
  1006. if( !attackAction.IsParried() && !attackAction.IsCountered() )
  1007. {
  1008.  
  1009. damageBonus = playerAttacker.GetAttributeValue( 'lynx_dmg_boost' );
  1010.  
  1011. damageBonus.valueAdditive *= ((W3PlayerWitcher)playerAttacker).GetSetPartsEquipped( EIST_Lynx );
  1012.  
  1013. for( i=0 ; i<dmgInfos.Size() ; i += 1 )
  1014. {
  1015. dmgInfos[i].dmgVal *= 1 + damageBonus.valueAdditive;
  1016. }
  1017. }
  1018. }
  1019.  
  1020.  
  1021. if( playerAttacker && attackAction.IsActionMelee() && actorVictim.IsAttackerAtBack( playerAttacker ) && !actorVictim.HasAbility( 'CannotBeAttackedFromBehind' ) && ((W3PlayerWitcher)playerAttacker).IsSetBonusActive( EISB_Lynx_2 ) && !attackAction.WasDodged() && ( playerAttacker.inv.IsItemSteelSwordUsableByPlayer( attackAction.GetWeaponId() ) || playerAttacker.inv.IsItemSilverSwordUsableByPlayer( attackAction.GetWeaponId() ) ) )
  1022. {
  1023. if( !attackAction.IsParried() && !attackAction.IsCountered() && playerAttacker.GetStat(BCS_Focus) >= 1.0f )
  1024. {
  1025. theGame.GetDefinitionsManager().GetAbilityAttributeValue( GetSetBonusAbility( EISB_Lynx_2 ), 'lynx_2_dmg_boost', min, max );
  1026. for( i=0; i<dmgInfos.Size() ; i+=1 )
  1027. {
  1028. dmgInfos[i].dmgVal *= 1 + min.valueAdditive;
  1029. }
  1030.  
  1031. if ( !( thePlayer.IsInCombatAction() && ( thePlayer.GetCombatAction() == EBAT_SpecialAttack_Light || thePlayer.GetCombatAction() == EBAT_SpecialAttack_Heavy ) ) )
  1032. {
  1033. theGame.GetDefinitionsManager().GetAbilityAttributeValue( GetSetBonusAbility( EISB_Lynx_2 ), 'lynx_2_adrenaline_cost', min, max );
  1034. focusCost = min.valueAdditive;
  1035. if( GetWitcherPlayer().GetStat( BCS_Focus ) >= focusCost )
  1036. {
  1037. theGame.GetDefinitionsManager().GetAbilityAttributeValue( GetSetBonusAbility( EISB_Lynx_2 ), 'lynx_2_stun_duration', min, max );
  1038. attackAction.AddEffectInfo( EET_Confusion, min.valueAdditive );
  1039. playerAttacker.SoundEvent( "ep2_setskill_lynx_activate" );
  1040. playerAttacker.DrainFocus( focusCost );
  1041. }
  1042. }
  1043. }
  1044. }
  1045.  
  1046.  
  1047. if ( playerAttacker && action.IsActionRanged() && ((W3Petard)action.causer) && GetWitcherPlayer().CanUseSkill(S_Perk_20) )
  1048. {
  1049. perk20Bonus = GetWitcherPlayer().GetSkillAttributeValue( S_Perk_20, 'dmg_multiplier', false, false);
  1050. for( i = 0 ; i < dmgInfos.Size() ; i+=1)
  1051. {
  1052. dmgInfos[i].dmgVal *= ( 1 + perk20Bonus.valueMultiplicative );
  1053. }
  1054. }
  1055. if (playerAttacker && GetWitcherPlayer().IsMutationActive( EPMT_Mutation1 ) )
  1056. {
  1057. if (actorVictim && !action.IsDoTDamage()
  1058. && (!action.IsActionWitcherSign() || !((W3IgniProjectile)action.causer))
  1059. && (actorVictim.HasBuff(EET_Confusion) || actorVictim.HasBuff(EET_AxiiGuardMe)))
  1060. {
  1061. for( i = 0 ; i < dmgInfos.Size() ; i+=1)
  1062. {
  1063. dmgInfos[i].dmgVal *= 2.0f;
  1064. }
  1065. }
  1066.  
  1067. if( action.IsActionWitcherSign() && ((W3IgniProjectile)action.causer) )
  1068. {
  1069. sword = playerAttacker.inv.GetCurrentlyHeldSword();
  1070.  
  1071. damageVal.valueBase = 0;
  1072. damageVal.valueMultiplicative = 0;
  1073. damageVal.valueAdditive = 0;
  1074.  
  1075. if( playerAttacker.inv.GetItemCategory(sword) == 'steelsword' )
  1076. {
  1077. damageVal += playerAttacker.inv.GetItemAttributeValue(sword, theGame.params.DAMAGE_NAME_SLASHING);
  1078. }
  1079. else if( playerAttacker.inv.GetItemCategory(sword) == 'silversword' )
  1080. {
  1081. damageVal += playerAttacker.inv.GetItemAttributeValue(sword, theGame.params.DAMAGE_NAME_SILVER);
  1082. }
  1083. theGame.GetDefinitionsManager().GetAbilityAttributeValue('Mutation1', 'dmg_bonus_factor', min, max);
  1084.  
  1085. damageVal.valueBase *= CalculateAttributeValue(min);
  1086.  
  1087.  
  1088. if( action.IsDoTDamage() )
  1089. {
  1090. damageVal.valueBase *= action.GetDoTdt();
  1091. }
  1092.  
  1093. for( i = 0 ; i < dmgInfos.Size() ; i+=1)
  1094. {
  1095. dmgInfos[i].dmgVal += damageVal.valueBase;
  1096. }
  1097. }
  1098. }
  1099.  
  1100.  
  1101. npcVictim = (CNewNPC) actorVictim;
  1102. if( playerAttacker && npcVictim && attackAction && action.IsActionMelee() && GetWitcherPlayer().IsMutationActive( EPMT_Mutation8 ) && ( victimMonsterCategory != MC_Human || npcVictim.IsImmuneToMutation8Finisher() ) && attackAction.GetWeaponId() == GetWitcherPlayer().GetHeldSword() )
  1103. {
  1104. dm.GetAbilityAttributeValue( 'Mutation8', 'dmg_bonus', min, max );
  1105.  
  1106. for( i = 0 ; i < dmgInfos.Size() ; i+=1)
  1107. {
  1108. dmgInfos[i].dmgVal *= 1 + min.valueMultiplicative;
  1109. }
  1110. }
  1111.  
  1112.  
  1113. if( playerAttacker && actorVictim && attackAction && action.IsActionMelee() && playerAttacker.inv.ItemHasTag( attackAction.GetWeaponId(), 'Aerondight' ) )
  1114. {
  1115. aerondight = (W3Effect_Aerondight)playerAttacker.GetBuff( EET_Aerondight );
  1116.  
  1117. if( aerondight )
  1118. {
  1119. min = playerAttacker.GetAbilityAttributeValue( 'AerondightEffect', 'dmg_bonus' );
  1120. bonusCount = aerondight.GetCurrentCount();
  1121.  
  1122. if( bonusCount > 0 )
  1123. {
  1124. min.valueMultiplicative *= bonusCount;
  1125.  
  1126. for( i = 0 ; i < dmgInfos.Size() ; i += 1 )
  1127. {
  1128. dmgInfos[i].dmgVal *= 1 + min.valueMultiplicative;
  1129. }
  1130. }
  1131. }
  1132. }
  1133. }
  1134.  
  1135.  
  1136. private function ProcessActionReturnedDamage()
  1137. {
  1138. var witcher : W3PlayerWitcher;
  1139. var quen : W3QuenEntity;
  1140. var params : SCustomEffectParams;
  1141. var processFireShield, canBeParried, canBeDodged, wasParried, wasDodged, returned : bool;
  1142. var g5Chance : SAbilityAttributeValue;
  1143. var dist, checkDist : float;
  1144.  
  1145.  
  1146. if((W3PlayerWitcher)playerVictim && !playerAttacker && actorAttacker && !action.IsDoTDamage() && action.IsActionMelee() && (attackerMonsterCategory == MC_Necrophage || attackerMonsterCategory == MC_Vampire) && actorVictim.HasBuff(EET_BlackBlood))
  1147. {
  1148. returned = ProcessActionBlackBloodReturnedDamage();
  1149. }
  1150.  
  1151.  
  1152. if(action.IsActionMelee() && actorVictim.HasAbility( 'Thorns' ) )
  1153. {
  1154. returned = ProcessActionThornDamage() || returned;
  1155. }
  1156.  
  1157. if(actorVictim.HasAbility( 'Glyphword 5 _Stats', true))
  1158. {
  1159. if( GetAttitudeBetween(actorAttacker, actorVictim) == AIA_Hostile)
  1160. {
  1161. if( !action.IsDoTDamage() )
  1162. {
  1163. g5Chance = actorVictim.GetAttributeValue('glyphword5_chance');
  1164.  
  1165. if(RandF() < g5Chance.valueAdditive)
  1166. {
  1167. canBeParried = attackAction.CanBeParried();
  1168. canBeDodged = attackAction.CanBeDodged();
  1169. wasParried = attackAction.IsParried() || attackAction.IsCountered();
  1170. wasDodged = attackAction.WasDodged();
  1171.  
  1172. if(!action.IsActionMelee() || (!canBeParried && canBeDodged && !wasDodged) || (canBeParried && !wasParried && !canBeDodged) || (canBeParried && canBeDodged && !wasDodged && !wasParried))
  1173. {
  1174. returned = ProcessActionReflectDamage() || returned;
  1175. }
  1176. }
  1177. }
  1178. }
  1179.  
  1180. }
  1181.  
  1182.  
  1183. if(playerVictim && !playerAttacker && actorAttacker && attackAction && attackAction.IsActionMelee() && thePlayer.HasBuff(EET_Mutagen26))
  1184. {
  1185. returned = ProcessActionLeshenMutagenDamage() || returned;
  1186. }
  1187.  
  1188.  
  1189. if(action.IsActionMelee() && actorVictim.HasAbility( 'FireShield' ) )
  1190. {
  1191. witcher = GetWitcherPlayer();
  1192. processFireShield = true;
  1193. if(playerAttacker == witcher)
  1194. {
  1195. quen = (W3QuenEntity)witcher.GetSignEntity(ST_Quen);
  1196. if(quen && quen.IsAnyQuenActive())
  1197. {
  1198. processFireShield = false;
  1199. }
  1200. }
  1201.  
  1202. if(processFireShield)
  1203. {
  1204. params.effectType = EET_Burning;
  1205. params.creator = actorVictim;
  1206. params.sourceName = actorVictim.GetName();
  1207.  
  1208. params.effectValue.valueMultiplicative = 0.01;
  1209. actorAttacker.AddEffectCustom(params);
  1210. returned = true;
  1211. }
  1212. }
  1213.  
  1214.  
  1215. if(actorAttacker.UsesEssence())
  1216. {
  1217. returned = ProcessSilverStudsReturnedDamage() || returned;
  1218. }
  1219.  
  1220.  
  1221. if( (W3PlayerWitcher)playerVictim && !playerAttacker && actorAttacker && !playerAttacker.IsInFistFightMiniGame() && !action.IsDoTDamage() && action.IsActionMelee() && GetWitcherPlayer().IsMutationActive( EPMT_Mutation4 ) )
  1222. {
  1223.  
  1224. dist = VecDistance( actorAttacker.GetWorldPosition(), actorVictim.GetWorldPosition() );
  1225. checkDist = 3.f;
  1226. if( actorAttacker.IsHuge() )
  1227. {
  1228. checkDist += 3.f;
  1229. }
  1230.  
  1231. if( dist <= checkDist )
  1232. {
  1233. returned = GetWitcherPlayer().ProcessActionMutation4ReturnedDamage( action.processedDmg.vitalityDamage, actorAttacker, EAHA_ForceYes, action ) || returned;
  1234. }
  1235. }
  1236.  
  1237. action.SetWasDamageReturnedToAttacker( returned );
  1238. }
  1239.  
  1240.  
  1241. private function ProcessActionLeshenMutagenDamage() : bool
  1242. {
  1243. var damageAction : W3DamageAction;
  1244. var returnedDamage, pts, perc : float;
  1245. var mutagen : W3Mutagen26_Effect;
  1246.  
  1247. mutagen = (W3Mutagen26_Effect)playerVictim.GetBuff(EET_Mutagen26);
  1248. mutagen.GetReturnedDamage(pts, perc);
  1249.  
  1250. if(pts <= 0 && perc <= 0)
  1251. return false;
  1252.  
  1253. returnedDamage = pts + perc * action.GetDamageValueTotal();
  1254.  
  1255.  
  1256. damageAction = new W3DamageAction in this;
  1257. damageAction.Initialize( action.victim, action.attacker, NULL, "Mutagen26", EHRT_None, CPS_AttackPower, true, false, false, false );
  1258. damageAction.SetCannotReturnDamage( true );
  1259. damageAction.SetHitAnimationPlayType( EAHA_ForceNo );
  1260. damageAction.AddDamage(theGame.params.DAMAGE_NAME_SILVER, returnedDamage);
  1261. damageAction.AddDamage(theGame.params.DAMAGE_NAME_PHYSICAL, returnedDamage);
  1262.  
  1263. theGame.damageMgr.ProcessAction(damageAction);
  1264. delete damageAction;
  1265.  
  1266. return true;
  1267. }
  1268.  
  1269.  
  1270. private function ProcessSilverStudsReturnedDamage() : bool
  1271. {
  1272. var damageAction : W3DamageAction;
  1273. var returnedDamage : float;
  1274.  
  1275. returnedDamage = CalculateAttributeValue(actorVictim.GetAttributeValue('returned_silver_damage'));
  1276.  
  1277. if(returnedDamage <= 0)
  1278. return false;
  1279.  
  1280. damageAction = new W3DamageAction in this;
  1281. damageAction.Initialize( action.victim, action.attacker, NULL, "SilverStuds", EHRT_None, CPS_AttackPower, true, false, false, false );
  1282. damageAction.SetCannotReturnDamage( true );
  1283. damageAction.SetHitAnimationPlayType( EAHA_ForceNo );
  1284.  
  1285. damageAction.AddDamage(theGame.params.DAMAGE_NAME_SILVER, returnedDamage);
  1286.  
  1287. theGame.damageMgr.ProcessAction(damageAction);
  1288. delete damageAction;
  1289.  
  1290. return true;
  1291. }
  1292.  
  1293.  
  1294. private function ProcessActionBlackBloodReturnedDamage() : bool
  1295. {
  1296. var returnedAction : W3DamageAction;
  1297. var returnVal : SAbilityAttributeValue;
  1298. var bb : W3Potion_BlackBlood;
  1299. var potionLevel : int;
  1300. var returnedDamage : float;
  1301.  
  1302. if(action.processedDmg.vitalityDamage <= 0)
  1303. return false;
  1304.  
  1305. bb = (W3Potion_BlackBlood)actorVictim.GetBuff(EET_BlackBlood);
  1306. potionLevel = bb.GetBuffLevel();
  1307.  
  1308.  
  1309. returnedAction = new W3DamageAction in this;
  1310. returnedAction.Initialize( action.victim, action.attacker, bb, "BlackBlood", EHRT_None, CPS_AttackPower, true, false, false, false );
  1311. returnedAction.SetCannotReturnDamage( true );
  1312.  
  1313. returnVal = bb.GetReturnDamageValue();
  1314.  
  1315. if(potionLevel == 1)
  1316. {
  1317. returnedAction.SetHitAnimationPlayType(EAHA_ForceNo);
  1318. }
  1319. else
  1320. {
  1321. returnedAction.SetHitAnimationPlayType(EAHA_ForceYes);
  1322. returnedAction.SetHitReactionType(EHRT_Reflect);
  1323. }
  1324.  
  1325. returnedDamage = (returnVal.valueBase + action.processedDmg.vitalityDamage) * returnVal.valueMultiplicative + returnVal.valueAdditive;
  1326. returnedAction.AddDamage(theGame.params.DAMAGE_NAME_DIRECT, returnedDamage);
  1327.  
  1328. theGame.damageMgr.ProcessAction(returnedAction);
  1329. delete returnedAction;
  1330. return true;
  1331. }
  1332.  
  1333.  
  1334. private function ProcessActionReflectDamage() : bool
  1335. {
  1336. var returnedAction : W3DamageAction;
  1337. var returnVal, min, max : SAbilityAttributeValue;
  1338. var potionLevel : int;
  1339. var returnedDamage : float;
  1340. var template : CEntityTemplate;
  1341. var fxEnt : CEntity;
  1342. var boneIndex: int;
  1343. var b : bool;
  1344. var component : CComponent;
  1345.  
  1346.  
  1347. if(action.processedDmg.vitalityDamage <= 0)
  1348. return false;
  1349.  
  1350. returnedDamage = CalculateAttributeValue(actorVictim.GetTotalArmor());
  1351. theGame.GetDefinitionsManager().GetAbilityAttributeValue('Glyphword 5 _Stats', 'damage_mult', min, max);
  1352.  
  1353.  
  1354.  
  1355.  
  1356. returnedAction = new W3DamageAction in this;
  1357. returnedAction.Initialize( action.victim, action.attacker, NULL, "Glyphword5", EHRT_None, CPS_AttackPower, true, false, false, false );
  1358. returnedAction.SetCannotReturnDamage( true );
  1359. returnedAction.SetHitAnimationPlayType(EAHA_ForceYes);
  1360. returnedAction.SetHitReactionType(EHRT_Heavy);
  1361.  
  1362. returnedAction.AddDamage(theGame.params.DAMAGE_NAME_DIRECT, returnedDamage * min.valueMultiplicative);
  1363.  
  1364.  
  1365.  
  1366.  
  1367. theGame.damageMgr.ProcessAction(returnedAction);
  1368. delete returnedAction;
  1369.  
  1370. template = (CEntityTemplate)LoadResource('glyphword_5');
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377. component = action.attacker.GetComponent('torso3effect');
  1378. if(component)
  1379. thePlayer.PlayEffect('reflection_damge', component);
  1380. else
  1381. thePlayer.PlayEffect('reflection_damge', action.attacker);
  1382. action.attacker.PlayEffect('yrden_shock');
  1383.  
  1384. return true;
  1385. }
  1386.  
  1387.  
  1388. private function ProcessActionThornDamage() : bool
  1389. {
  1390. var damageAction : W3DamageAction;
  1391. var damageVal : SAbilityAttributeValue;
  1392. var damage : float;
  1393. var inv : CInventoryComponent;
  1394. var damageNames : array < CName >;
  1395.  
  1396. damageAction = new W3DamageAction in this;
  1397.  
  1398. damageAction.Initialize( action.victim, action.attacker, NULL, "Thorns", EHRT_Light, CPS_AttackPower, true, false, false, false );
  1399.  
  1400. damageAction.SetCannotReturnDamage( true );
  1401.  
  1402. damageVal = actorVictim.GetAttributeValue( 'light_attack_damage_vitality' );
  1403.  
  1404.  
  1405.  
  1406.  
  1407.  
  1408. inv = actorAttacker.GetInventory();
  1409. inv.GetWeaponDTNames(weaponId, damageNames );
  1410. damageVal.valueBase = actorAttacker.GetTotalWeaponDamage(weaponId, damageNames[0], GetInvalidUniqueId() );
  1411.  
  1412. damageVal.valueBase *= 0.10f;
  1413.  
  1414. if( damageVal.valueBase == 0 )
  1415. {
  1416. damageVal.valueBase = 10;
  1417. }
  1418.  
  1419. damage = (damageVal.valueBase + action.processedDmg.vitalityDamage) * damageVal.valueMultiplicative + damageVal.valueAdditive;
  1420. damageAction.AddDamage( theGame.params.DAMAGE_NAME_PIERCING, damage );
  1421.  
  1422. damageAction.SetHitAnimationPlayType( EAHA_ForceYes );
  1423. theGame.damageMgr.ProcessAction(damageAction);
  1424. delete damageAction;
  1425.  
  1426. return true;
  1427. }
  1428.  
  1429.  
  1430. private function GetAttackersPowerMod() : SAbilityAttributeValue
  1431. {
  1432. var powerMod, criticalDamageBonus, min, max, critReduction, sp : SAbilityAttributeValue;
  1433. var mutagen : CBaseGameplayEffect;
  1434. var totalBonus : float;
  1435. var playerWitcher : W3PlayerWitcher; // AeroHD -- TES+
  1436.  
  1437.  
  1438. powerMod = action.GetPowerStatValue();
  1439. if ( powerMod.valueAdditive == 0 && powerMod.valueBase == 0 && powerMod.valueMultiplicative == 0 && theGame.CanLog() )
  1440. LogDMHits("Attacker has power stat of 0!", action);
  1441.  
  1442.  
  1443. if(playerAttacker && attackAction && playerAttacker.IsHeavyAttack(attackAction.GetAttackName()))
  1444. powerMod.valueMultiplicative -= 0.833;
  1445.  
  1446. if ( playerAttacker && ((W3IgniProjectile)action.causer) && powerMod.valueMultiplicative > 2.5f)
  1447. {
  1448. powerMod.valueMultiplicative = 2.5f + LogF ((powerMod.valueMultiplicative - 2.5f) + 1);
  1449. }
  1450.  
  1451. if(action.IsCriticalHit())
  1452. {
  1453.  
  1454. if( playerAttacker && action.IsActionWitcherSign() && theGame.GetDLCManager().IsEP2Available() )
  1455. {
  1456. theGame.GetDefinitionsManager().GetAbilityAttributeValue('Mutation2', 'crit_damage_factor', min, max);
  1457. criticalDamageBonus.valueAdditive = powerMod.valueMultiplicative * min.valueMultiplicative;
  1458. }
  1459. else
  1460. {
  1461. criticalDamageBonus = actorAttacker.GetCriticalHitDamageBonus(weaponId, victimMonsterCategory, actorVictim.IsAttackerAtBack(playerAttacker));
  1462.  
  1463. criticalDamageBonus += actorAttacker.GetAttributeValue('critical_hit_chance_fast_style');
  1464.  
  1465. if(attackAction && playerAttacker)
  1466. {
  1467. // AeroHD -- TES+
  1468. // CrossbowDamageBoost
  1469. if (attackAction.IsActionRanged())
  1470. {
  1471. if (playerAttacker.CanUseSkill(S_Sword_s07))
  1472. {
  1473. criticalDamageBonus.valueAdditive += 0.2 * playerAttacker.GetSkillLevel(S_Sword_s07);
  1474. }
  1475.  
  1476. playerWitcher = (W3PlayerWitcher)playerAttacker;
  1477.  
  1478. if (playerWitcher && playerWitcher.IsMutationActive( EPMT_Mutation9 ))
  1479. {
  1480. criticalDamageBonus.valueAdditive += 0.5;
  1481. }
  1482. }
  1483. else
  1484. {
  1485. if(playerAttacker.IsHeavyAttack(attackAction.GetAttackName()) && playerAttacker.CanUseSkill(S_Sword_s08))
  1486. criticalDamageBonus += playerAttacker.GetSkillAttributeValue(S_Sword_s08, theGame.params.CRITICAL_HIT_DAMAGE_BONUS, false, true) * playerAttacker.GetSkillLevel(S_Sword_s08);
  1487. else if (!playerAttacker.IsHeavyAttack(attackAction.GetAttackName()) && playerAttacker.CanUseSkill(S_Sword_s17))
  1488. criticalDamageBonus += playerAttacker.GetSkillAttributeValue(S_Sword_s17, theGame.params.CRITICAL_HIT_DAMAGE_BONUS, false, true) * playerAttacker.GetSkillLevel(S_Sword_s17);
  1489. }
  1490. // AeroHD -- TES-
  1491. }
  1492. }
  1493.  
  1494.  
  1495. totalBonus = CalculateAttributeValue(criticalDamageBonus);
  1496. critReduction = actorVictim.GetAttributeValue(theGame.params.CRITICAL_HIT_REDUCTION);
  1497. totalBonus = totalBonus * ClampF(1 - critReduction.valueMultiplicative, 0.f, 1.f);
  1498.  
  1499.  
  1500. powerMod.valueMultiplicative += totalBonus;
  1501. }
  1502.  
  1503.  
  1504. if (actorVictim && playerAttacker)
  1505. {
  1506. if ( playerAttacker.HasBuff(EET_Mutagen05) && (playerAttacker.GetStat(BCS_Vitality) == playerAttacker.GetStatMax(BCS_Vitality)) )
  1507. {
  1508. mutagen = playerAttacker.GetBuff(EET_Mutagen05);
  1509. dm.GetAbilityAttributeValue(mutagen.GetAbilityName(), 'damageIncrease', min, max);
  1510. powerMod += GetAttributeRandomizedValue(min, max);
  1511. }
  1512. }
  1513.  
  1514. return powerMod;
  1515. }
  1516.  
  1517.  
  1518. private function GetDamageResists(dmgType : name, out resistPts : float, out resistPerc : float)
  1519. {
  1520. var armorReduction, armorReductionPerc, skillArmorReduction : SAbilityAttributeValue;
  1521. var bonusReduct, bonusResist : float;
  1522. var baseResistOnly : bool;
  1523. var mutagenBuff : W3Mutagen28_Effect;
  1524. var appliedOilName, vsMonsterResistReduction : name;
  1525. var oils : array< W3Effect_Oil >;
  1526. var i : int;
  1527.  
  1528.  
  1529. if(attackAction && attackAction.IsActionMelee() && actorAttacker.GetInventory().IsItemFists(weaponId) && !actorVictim.UsesEssence())
  1530. return;
  1531.  
  1532.  
  1533. if(actorVictim)
  1534. {
  1535. actorVictim.GetResistValue( GetResistForDamage(dmgType, action.IsDoTDamage() && !(playerAttacker && ((W3IgniProjectile)action.causer))), resistPts, resistPerc );
  1536.  
  1537.  
  1538. if(playerVictim && actorAttacker && playerVictim.CanUseSkill(S_Alchemy_s05))
  1539. {
  1540. GetOilProtectionAgainstMonster(dmgType, bonusResist, bonusReduct);
  1541.  
  1542. resistPerc += bonusResist * playerVictim.GetSkillLevel(S_Alchemy_s05);
  1543. }
  1544.  
  1545.  
  1546. if(playerVictim && actorAttacker && playerVictim.HasBuff(EET_Mutagen28))
  1547. {
  1548. mutagenBuff = (W3Mutagen28_Effect)playerVictim.GetBuff(EET_Mutagen28);
  1549. mutagenBuff.GetProtection(attackerMonsterCategory, dmgType, action.IsDoTDamage(), bonusResist, bonusReduct);
  1550. resistPts += bonusReduct;
  1551. resistPerc += bonusResist;
  1552. }
  1553.  
  1554.  
  1555. if(actorAttacker)
  1556. {
  1557.  
  1558. armorReduction = actorAttacker.GetAttributeValue('armor_reduction');
  1559. armorReductionPerc = actorAttacker.GetAttributeValue('armor_reduction_perc');
  1560.  
  1561.  
  1562. if(playerAttacker)
  1563. {
  1564. vsMonsterResistReduction = MonsterCategoryToResistReduction(victimMonsterCategory);
  1565. oils = playerAttacker.inv.GetOilsAppliedOnItem( weaponId );
  1566.  
  1567. if( oils.Size() > 0 )
  1568. {
  1569. for( i=0; i<oils.Size(); i+=1 )
  1570. {
  1571. appliedOilName = oils[ i ].GetOilItemName();
  1572.  
  1573.  
  1574. if( oils[ i ].GetAmmoCurrentCount() > 0 && dm.ItemHasAttribute( appliedOilName, true, vsMonsterResistReduction ) )
  1575. {
  1576. armorReductionPerc.valueMultiplicative += oils[ i ].GetAmmoPercentage();
  1577. }
  1578. }
  1579. }
  1580. }
  1581.  
  1582.  
  1583. if(playerAttacker && action.IsActionMelee() && playerAttacker.IsHeavyAttack(attackAction.GetAttackName()) && playerAttacker.CanUseSkill(S_Sword_2))
  1584. armorReduction += playerAttacker.GetSkillAttributeValue(S_Sword_2, 'armor_reduction', false, true);
  1585.  
  1586.  
  1587. if ( playerAttacker &&
  1588. action.IsActionMelee() && playerAttacker.IsHeavyAttack(attackAction.GetAttackName()) &&
  1589. ( dmgType == theGame.params.DAMAGE_NAME_PHYSICAL ||
  1590. dmgType == theGame.params.DAMAGE_NAME_SLASHING ||
  1591. dmgType == theGame.params.DAMAGE_NAME_PIERCING ||
  1592. dmgType == theGame.params.DAMAGE_NAME_BLUDGEONING ||
  1593. dmgType == theGame.params.DAMAGE_NAME_RENDING ||
  1594. dmgType == theGame.params.DAMAGE_NAME_SILVER
  1595. ) &&
  1596. playerAttacker.CanUseSkill(S_Sword_s06)
  1597. )
  1598. {
  1599.  
  1600. skillArmorReduction = playerAttacker.GetSkillAttributeValue(S_Sword_s06, 'armor_reduction_perc', false, true);
  1601. armorReductionPerc += skillArmorReduction * playerAttacker.GetSkillLevel(S_Sword_s06);
  1602. }
  1603. }
  1604. }
  1605.  
  1606.  
  1607. if(!action.GetIgnoreArmor())
  1608. resistPts += CalculateAttributeValue( actorVictim.GetTotalArmor() );
  1609.  
  1610.  
  1611. resistPts = MaxF(0, resistPts - CalculateAttributeValue(armorReduction) );
  1612. resistPerc -= CalculateAttributeValue(armorReductionPerc);
  1613.  
  1614.  
  1615.  
  1616. resistPerc = MaxF(0, resistPerc);
  1617. }
  1618.  
  1619. // Improved Axii begin
  1620. private function AdjustDamageAxiiPuppet()
  1621. {
  1622. var victimNPC, attackerNPC : CNewNPC;
  1623. var victimH, attackerH, damageMult : float;
  1624. var witcher : W3PlayerWitcher;
  1625.  
  1626. witcher = GetWitcherPlayer();
  1627. victimNPC = (CNewNPC)actorVictim;
  1628. attackerNPC = (CNewNPC)actorAttacker;
  1629.  
  1630. if (!victimNPC || !attackerNPC)
  1631. return;
  1632.  
  1633. if (actorVictim.UsesEssence())
  1634. victimH = actorVictim.GetStatMax(BCS_Essence);
  1635. else
  1636. victimH = actorVictim.GetStatMax(BCS_Vitality);
  1637.  
  1638. if (actorAttacker.UsesEssence())
  1639. attackerH = actorAttacker.GetStatMax(BCS_Essence);
  1640. else
  1641. attackerH = actorAttacker.GetStatMax(BCS_Vitality);
  1642.  
  1643. if (witcher && witcher.axiiMods)
  1644. {
  1645. victimH /= witcher.axiiMods.GetHealthMod(victimNPC);
  1646. attackerH /= witcher.axiiMods.GetHealthMod(attackerNPC);
  1647. }
  1648.  
  1649. damageMult = victimH / GetAxiiPuppetReductorDivider(victimNPC.GetLevelFromLocalVar());
  1650. if (victimH > attackerH
  1651. && ( (actorVictim.UsesEssence() && actorAttacker.UsesEssence()) || (!actorVictim.UsesEssence() && !actorAttacker.UsesEssence()) ) )
  1652. damageMult *= attackerH / victimH;
  1653.  
  1654. if (witcher && witcher.axiiMods)
  1655. damageMult *= witcher.axiiMods.GetDamageMod(attackerNPC);
  1656.  
  1657. if (action.IsActionRanged())
  1658. damageMult *= 2.5f;
  1659.  
  1660. if (theGame.GetDifficultyMode() == EDM_Easy)
  1661. damageMult *= 2.5f;
  1662. else if (theGame.GetDifficultyMode() == EDM_Medium)
  1663. damageMult *= 1.5f;
  1664. else if (theGame.GetDifficultyMode() == EDM_Hardcore)
  1665. damageMult *= 0.6667f;
  1666.  
  1667. if (actorVictim.UsesEssence())
  1668. action.processedDmg.essenceDamage *= damageMult;
  1669. else
  1670. action.processedDmg.vitalityDamage *= damageMult;
  1671. }
  1672.  
  1673. private function GetAxiiPuppetReductorDivider(level : int) : float
  1674. {
  1675. var witcherBaseH : float;
  1676.  
  1677. if (level <= 1)
  1678. witcherBaseH = 3500.0f;
  1679. else if (level <= 10)
  1680. witcherBaseH = 3500.0f + 800.0f * (level - 1) / 9.0f;
  1681. else if (level <= 29)
  1682. witcherBaseH = 4300.0f + 1050.0f * (level - 10) / 19.0f;
  1683. else if (level <= 50)
  1684. witcherBaseH = 5350.0f + 575.0f * (level - 29) / 21.0f;
  1685. else
  1686. witcherBaseH = 5925.0f;
  1687.  
  1688. return witcherBaseH * GetAxiiPuppetLevelMult(level);
  1689. }
  1690.  
  1691. private function GetAxiiPuppetLevelMult(level : int) : float
  1692. {
  1693. if (level < 1)
  1694. return 1.0f;
  1695. else if (level <= 50)
  1696. return 1.0f + 2.0f * level / 50.0f;
  1697. else if (level <= 100)
  1698. return 3.0f + 4.0f * (level - 50) / 50.0f;
  1699. else
  1700. return 7.0f;
  1701. }
  1702. // Improved Axii end
  1703.  
  1704. private function CalculateDamage(dmgInfo : SRawDamage, powerMod : SAbilityAttributeValue) : float
  1705. {
  1706. var quen : W3QuenEntity;
  1707. var finalDamage, finalIncomingDamage : float;
  1708. var resistPoints, resistPercents : float;
  1709. var ptsString, percString : string;
  1710. var mutagen : CBaseGameplayEffect;
  1711. var min, max : SAbilityAttributeValue;
  1712. var encumbranceBonus : float;
  1713. var temp : bool;
  1714. var fistfightDamageMult : float;
  1715. var burning : W3Effect_Burning;
  1716.  
  1717.  
  1718. GetDamageResists(dmgInfo.dmgType, resistPoints, resistPercents);
  1719.  
  1720.  
  1721. if( thePlayer.IsFistFightMinigameEnabled() && actorAttacker == thePlayer )
  1722. {
  1723. finalDamage = MaxF(0, (dmgInfo.dmgVal));
  1724. }
  1725. else
  1726. {
  1727. if (theGame.GetInGameConfigWrapper().GetVarValue('GBRRealisticBurning', 'GBRBurningMode'))
  1728. {
  1729. burning = (W3Effect_Burning)action.causer;
  1730. if( burning && burning.IsSignEffect() )
  1731. {
  1732. if ( powerMod.valueMultiplicative > 1.0f )
  1733. {
  1734. powerMod.valueMultiplicative = 1.0f + LogF( (powerMod.valueMultiplicative - 1.0f) + 1 ) / 1.6f;
  1735. }
  1736. }
  1737. } else {
  1738.  
  1739. burning = (W3Effect_Burning)action.causer;
  1740. if( burning && burning.IsSignEffect() )
  1741. {
  1742. if ( powerMod.valueMultiplicative > 2.0f )
  1743. {
  1744. powerMod.valueMultiplicative = 2.0f + LogF( (powerMod.valueMultiplicative - 2.0f) + 1 );
  1745. }
  1746. }
  1747.  
  1748. }
  1749. finalDamage = MaxF(0, (dmgInfo.dmgVal + powerMod.valueBase) * powerMod.valueMultiplicative + powerMod.valueAdditive);
  1750. }
  1751.  
  1752. finalIncomingDamage = finalDamage;
  1753.  
  1754. if(finalDamage > 0.f)
  1755. {
  1756.  
  1757. if(!action.IsPointResistIgnored() && !(dmgInfo.dmgType == theGame.params.DAMAGE_NAME_ELEMENTAL || dmgInfo.dmgType == theGame.params.DAMAGE_NAME_FIRE || dmgInfo.dmgType == theGame.params.DAMAGE_NAME_FROST ))
  1758. {
  1759. finalDamage = MaxF(0, finalDamage - resistPoints);
  1760.  
  1761. if(finalDamage == 0.f)
  1762. action.SetArmorReducedDamageToZero();
  1763. }
  1764. }
  1765.  
  1766. if(finalDamage > 0.f)
  1767. {
  1768.  
  1769. if (playerVictim == GetWitcherPlayer() && playerVictim.HasBuff(EET_Mutagen02))
  1770. {
  1771. encumbranceBonus = 1 - (GetWitcherPlayer().GetEncumbrance() / GetWitcherPlayer().GetMaxRunEncumbrance(temp));
  1772. if (encumbranceBonus < 0)
  1773. encumbranceBonus = 0;
  1774. mutagen = playerVictim.GetBuff(EET_Mutagen02);
  1775. dm.GetAbilityAttributeValue(mutagen.GetAbilityName(), 'resistGainRate', min, max);
  1776. encumbranceBonus *= CalculateAttributeValue(GetAttributeRandomizedValue(min, max));
  1777. resistPercents += encumbranceBonus;
  1778. }
  1779.  
  1780. // Reduce resist with quen active on Witcher for all damage that quen reduces
  1781. if (playerVictim == GetWitcherPlayer() && resistPercents > 0.3f)
  1782. {
  1783. quen = ( W3QuenEntity ) GetWitcherPlayer().GetSignEntity(ST_Quen);
  1784. if (quen && quen.IsAnyQuenActive() && dmgInfo.dmgType != theGame.params.DAMAGE_NAME_DIRECT && dmgInfo.dmgType != theGame.params.DAMAGE_NAME_STAMINA
  1785. && DamageHitsVitality(dmgInfo.dmgType) && !((W3Effect_Bleeding)action.causer) )
  1786. {
  1787. quen.SetLastRealDamageResist(resistPercents);
  1788. resistPercents = 0.3f + (resistPercents - 0.3f) / 2.0f;
  1789. }
  1790. }
  1791.  
  1792. finalDamage *= 1 - resistPercents;
  1793. }
  1794.  
  1795. if(dmgInfo.dmgType == theGame.params.DAMAGE_NAME_FIRE && finalDamage > 0)
  1796. action.SetDealtFireDamage(true);
  1797.  
  1798. if( playerAttacker && thePlayer.IsWeaponHeld('fist') && !thePlayer.IsInFistFightMiniGame() && action.IsActionMelee() )
  1799. {
  1800. if(FactsQuerySum("NewGamePlus") > 0)
  1801. {fistfightDamageMult = thePlayer.GetLevel()* 0.1;}
  1802. else
  1803. {fistfightDamageMult = thePlayer.GetLevel()* 0.05;}
  1804.  
  1805. finalDamage *= ( 1+fistfightDamageMult );
  1806. }
  1807.  
  1808. if(playerAttacker && attackAction && playerAttacker.IsHeavyAttack(attackAction.GetAttackName()))
  1809. finalDamage *= 1.833;
  1810.  
  1811.  
  1812. burning = (W3Effect_Burning)action.causer;
  1813. if(actorVictim && (((W3IgniEntity)action.causer) || ((W3IgniProjectile)action.causer) || ( burning && burning.IsSignEffect())) )
  1814. {
  1815. min = actorVictim.GetAttributeValue('igni_damage_amplifier');
  1816. finalDamage = finalDamage * (1 + min.valueMultiplicative) + min.valueAdditive;
  1817. }
  1818.  
  1819.  
  1820.  
  1821.  
  1822. if ( theGame.CanLog() )
  1823. {
  1824. LogDMHits("Single hit damage: initial damage = " + NoTrailZeros(dmgInfo.dmgVal), action);
  1825. LogDMHits("Single hit damage: attack_power = base: " + NoTrailZeros(powerMod.valueBase) + ", mult: " + NoTrailZeros(powerMod.valueMultiplicative) + ", add: " + NoTrailZeros(powerMod.valueAdditive), action );
  1826. if(action.IsPointResistIgnored())
  1827. LogDMHits("Single hit damage: resistance pts and armor = IGNORED", action);
  1828. else
  1829. LogDMHits("Single hit damage: resistance pts and armor = " + NoTrailZeros(resistPoints), action);
  1830. LogDMHits("Single hit damage: resistance perc = " + NoTrailZeros(resistPercents * 100), action);
  1831. LogDMHits("Single hit damage: final damage to sustain = " + NoTrailZeros(finalDamage), action);
  1832. }
  1833.  
  1834. return finalDamage;
  1835. }
  1836.  
  1837.  
  1838. private function ProcessActionDamage_DealDamage()
  1839. {
  1840. var logStr : string;
  1841. var hpPerc : float;
  1842. var npcVictim : CNewNPC;
  1843.  
  1844.  
  1845. if ( theGame.CanLog() )
  1846. {
  1847. logStr = "";
  1848. if(action.processedDmg.vitalityDamage > 0) logStr += NoTrailZeros(action.processedDmg.vitalityDamage) + " vitality, ";
  1849. if(action.processedDmg.essenceDamage > 0) logStr += NoTrailZeros(action.processedDmg.essenceDamage) + " essence, ";
  1850. if(action.processedDmg.staminaDamage > 0) logStr += NoTrailZeros(action.processedDmg.staminaDamage) + " stamina, ";
  1851. if(action.processedDmg.moraleDamage > 0) logStr += NoTrailZeros(action.processedDmg.moraleDamage) + " morale";
  1852.  
  1853. if(logStr == "")
  1854. logStr = "NONE";
  1855. LogDMHits("Final damage to sustain is: " + logStr, action);
  1856. }
  1857.  
  1858.  
  1859. if(actorVictim)
  1860. {
  1861. hpPerc = actorVictim.GetHealthPercents();
  1862.  
  1863.  
  1864. if(actorVictim.IsAlive())
  1865. {
  1866. npcVictim = (CNewNPC)actorVictim;
  1867. if(npcVictim && npcVictim.IsHorse())
  1868. {
  1869. npcVictim.GetHorseComponent().OnTakeDamage(action);
  1870. }
  1871. else
  1872. {
  1873. actorVictim.OnTakeDamage(action);
  1874. }
  1875. }
  1876.  
  1877. if(!actorVictim.IsAlive() && hpPerc == 1)
  1878. action.SetWasKilledBySingleHit();
  1879. }
  1880.  
  1881. if ( theGame.CanLog() )
  1882. {
  1883. LogDMHits("", action);
  1884. LogDMHits("Target stats after damage dealt are:", action);
  1885. if(actorVictim)
  1886. {
  1887. if( actorVictim.UsesVitality()) LogDMHits("Vitality = " + NoTrailZeros( actorVictim.GetStat(BCS_Vitality)), action);
  1888. if( actorVictim.UsesEssence()) LogDMHits("Essence = " + NoTrailZeros( actorVictim.GetStat(BCS_Essence)), action);
  1889. if( actorVictim.GetStatMax(BCS_Stamina) > 0) LogDMHits("Stamina = " + NoTrailZeros( actorVictim.GetStat(BCS_Stamina, true)), action);
  1890. if( actorVictim.GetStatMax(BCS_Morale) > 0) LogDMHits("Morale = " + NoTrailZeros( actorVictim.GetStat(BCS_Morale)), action);
  1891. }
  1892. else
  1893. {
  1894. LogDMHits("Undefined - victim is not a CActor and therefore has no stats", action);
  1895. }
  1896. }
  1897. }
  1898.  
  1899.  
  1900. private function ProcessActionDamage_ReduceDurability()
  1901. {
  1902. var witcherPlayer : W3PlayerWitcher;
  1903. var dbg_currDur, dbg_prevDur1, dbg_prevDur2, dbg_prevDur3, dbg_prevDur4, dbg_prevDur : float;
  1904. var dbg_armor, dbg_pants, dbg_boots, dbg_gloves, reducedItemId, weapon : SItemUniqueId;
  1905. var slot : EEquipmentSlots;
  1906. var weapons : array<SItemUniqueId>;
  1907. var armorStringName : string;
  1908. var canLog, playerHasSword : bool;
  1909. var i : int;
  1910.  
  1911. canLog = theGame.CanLog();
  1912.  
  1913. witcherPlayer = GetWitcherPlayer();
  1914.  
  1915.  
  1916. if ( playerAttacker && playerAttacker.inv.IsIdValid( weaponId ) && playerAttacker.inv.HasItemDurability( weaponId ) )
  1917. {
  1918. dbg_prevDur = playerAttacker.inv.GetItemDurability(weaponId);
  1919.  
  1920. if ( playerAttacker.inv.ReduceItemDurability(weaponId) && canLog )
  1921. {
  1922. LogDMHits("", action);
  1923. LogDMHits("Player's weapon durability changes from " + NoTrailZeros(dbg_prevDur) + " to " + NoTrailZeros(action.attacker.GetInventory().GetItemDurability(weaponId)), action );
  1924. }
  1925. }
  1926.  
  1927. else if(playerVictim && attackAction && attackAction.IsActionMelee() && (attackAction.IsParried() || attackAction.IsCountered()) )
  1928. {
  1929. weapons = playerVictim.inv.GetHeldWeapons();
  1930. playerHasSword = false;
  1931. for(i=0; i<weapons.Size(); i+=1)
  1932. {
  1933. weapon = weapons[i];
  1934. if(playerVictim.inv.IsIdValid(weapon) && (playerVictim.inv.IsItemSteelSwordUsableByPlayer(weapon) || playerVictim.inv.IsItemSilverSwordUsableByPlayer(weapon)) )
  1935. {
  1936. playerHasSword = true;
  1937. break;
  1938. }
  1939. }
  1940.  
  1941. if(playerHasSword)
  1942. {
  1943. playerVictim.inv.ReduceItemDurability(weapon);
  1944. }
  1945. }
  1946.  
  1947. else if(action.victim == witcherPlayer && (action.IsActionMelee() || action.IsActionRanged()) && action.DealsAnyDamage())
  1948. {
  1949.  
  1950. if ( canLog )
  1951. {
  1952. if ( witcherPlayer.GetItemEquippedOnSlot(EES_Armor, dbg_armor) )
  1953. dbg_prevDur1 = action.victim.GetInventory().GetItemDurability(dbg_armor);
  1954. else
  1955. dbg_prevDur1 = 0;
  1956.  
  1957. if ( witcherPlayer.GetItemEquippedOnSlot(EES_Pants, dbg_pants) )
  1958. dbg_prevDur2 = action.victim.GetInventory().GetItemDurability(dbg_pants);
  1959. else
  1960. dbg_prevDur2 = 0;
  1961.  
  1962. if ( witcherPlayer.GetItemEquippedOnSlot(EES_Boots, dbg_boots) )
  1963. dbg_prevDur3 = action.victim.GetInventory().GetItemDurability(dbg_boots);
  1964. else
  1965. dbg_prevDur3 = 0;
  1966.  
  1967. if ( witcherPlayer.GetItemEquippedOnSlot(EES_Gloves, dbg_gloves) )
  1968. dbg_prevDur4 = action.victim.GetInventory().GetItemDurability(dbg_gloves);
  1969. else
  1970. dbg_prevDur4 = 0;
  1971. }
  1972.  
  1973. slot = GetWitcherPlayer().ReduceArmorDurability();
  1974.  
  1975.  
  1976. if( canLog )
  1977. {
  1978. LogDMHits("", action);
  1979. if(slot != EES_InvalidSlot)
  1980. {
  1981. switch(slot)
  1982. {
  1983. case EES_Armor :
  1984. armorStringName = "chest armor";
  1985. reducedItemId = dbg_armor;
  1986. dbg_prevDur = dbg_prevDur1;
  1987. break;
  1988. case EES_Pants :
  1989. armorStringName = "pants";
  1990. reducedItemId = dbg_pants;
  1991. dbg_prevDur = dbg_prevDur2;
  1992. break;
  1993. case EES_Boots :
  1994. armorStringName = "boots";
  1995. reducedItemId = dbg_boots;
  1996. dbg_prevDur = dbg_prevDur3;
  1997. break;
  1998. case EES_Gloves :
  1999. armorStringName = "gloves";
  2000. reducedItemId = dbg_gloves;
  2001. dbg_prevDur = dbg_prevDur4;
  2002. break;
  2003. }
  2004.  
  2005. dbg_currDur = action.victim.GetInventory().GetItemDurability(reducedItemId);
  2006. LogDMHits("", action);
  2007. LogDMHits("Player's <<" + armorStringName + ">> durability changes from " + NoTrailZeros(dbg_prevDur) + " to " + NoTrailZeros(dbg_currDur), action );
  2008. }
  2009. else
  2010. {
  2011. LogDMHits("Tried to reduce player's armor durability but failed", action);
  2012. }
  2013. }
  2014.  
  2015.  
  2016. if(slot != EES_InvalidSlot)
  2017. thePlayer.inv.ReduceItemRepairObjectBonusCharge(reducedItemId);
  2018. }
  2019. }
  2020.  
  2021.  
  2022.  
  2023.  
  2024.  
  2025.  
  2026. private function ProcessActionReaction(wasFrozen : bool, wasAlive : bool)
  2027. {
  2028. var dismemberExplosion : bool;
  2029. var damageName : name;
  2030. var damage : array<SRawDamage>;
  2031. var points, percents, hp, dmg : float;
  2032. var counterAction : W3DamageAction;
  2033. var moveTargets : array<CActor>;
  2034. var i : int;
  2035. var canPerformFinisher : bool;
  2036. var weaponName : name;
  2037. var npcVictim : CNewNPC;
  2038. var toxicCloud : W3ToxicCloud;
  2039. var playsNonAdditiveAnim : bool;
  2040. var bleedCustomEffect : SCustomEffectParams;
  2041.  
  2042. if(!actorVictim)
  2043. return;
  2044.  
  2045. npcVictim = (CNewNPC)actorVictim;
  2046.  
  2047. canPerformFinisher = CanPerformFinisher(actorVictim);
  2048.  
  2049. if( actorVictim.IsAlive() && !canPerformFinisher )
  2050. {
  2051.  
  2052. if(!action.IsDoTDamage() && action.DealtDamage())
  2053. {
  2054. if ( actorAttacker && npcVictim)
  2055. {
  2056. npcVictim.NoticeActorInGuardArea( actorAttacker );
  2057. }
  2058.  
  2059.  
  2060. if ( !playerVictim )
  2061. actorVictim.RemoveAllBuffsOfType(EET_Confusion);
  2062.  
  2063.  
  2064. if(playerAttacker && action.IsActionMelee() && !playerAttacker.GetInventory().IsItemFists(weaponId) && playerAttacker.IsLightAttack(attackAction.GetAttackName()) && playerAttacker.CanUseSkill(S_Sword_s05))
  2065. {
  2066. bleedCustomEffect.effectType = EET_Bleeding;
  2067. bleedCustomEffect.creator = playerAttacker;
  2068. bleedCustomEffect.sourceName = SkillEnumToName(S_Sword_s05);
  2069. bleedCustomEffect.duration = CalculateAttributeValue(playerAttacker.GetSkillAttributeValue(S_Sword_s05, 'duration', false, true));
  2070. bleedCustomEffect.effectValue.valueAdditive = CalculateAttributeValue(playerAttacker.GetSkillAttributeValue(S_Sword_s05, 'dmg_per_sec', false, true)) * playerAttacker.GetSkillLevel(S_Sword_s05);
  2071. actorVictim.AddEffectCustom(bleedCustomEffect);
  2072. }
  2073. }
  2074.  
  2075.  
  2076. if(actorVictim && wasAlive)
  2077. {
  2078. if (playerAttacker && action.IsActionWitcherSign() && action.GetSignSkill() == S_Magic_s03 && GetWitcherPlayer().IsMutationActive(EPMT_Mutation1) && actorVictim.HasBuff(EET_Blindness))
  2079. {
  2080. action.SetHitAnimationPlayType(EAHA_ForceNo);
  2081. }
  2082. playsNonAdditiveAnim = actorVictim.ReactToBeingHit( action );
  2083. }
  2084. }
  2085. else
  2086. {
  2087.  
  2088. if( !canPerformFinisher && CanDismember( wasFrozen, dismemberExplosion, weaponName ) )
  2089. {
  2090. ProcessDismemberment(wasFrozen, dismemberExplosion);
  2091. toxicCloud = (W3ToxicCloud)action.causer;
  2092.  
  2093. if(toxicCloud && toxicCloud.HasExplodingTargetDamages())
  2094. ProcessToxicCloudDismemberExplosion(toxicCloud.GetExplodingTargetDamages());
  2095.  
  2096.  
  2097. if(IsRequiredAttitudeBetween(thePlayer, action.victim, true))
  2098. {
  2099. moveTargets = thePlayer.GetMoveTargets();
  2100. for ( i = 0; i < moveTargets.Size(); i += 1 )
  2101. {
  2102. if ( moveTargets[i].IsHuman() )
  2103. moveTargets[i].DrainMorale(20.f);
  2104. }
  2105. }
  2106. }
  2107.  
  2108. else if ( canPerformFinisher )
  2109. {
  2110. if ( actorVictim.IsAlive() )
  2111. actorVictim.Kill( 'Finisher', false, thePlayer );
  2112.  
  2113. thePlayer.AddTimer( 'DelayedFinisherInputTimer', 0.1f );
  2114. thePlayer.SetFinisherVictim( actorVictim );
  2115. thePlayer.CleanCombatActionBuffer();
  2116. thePlayer.OnBlockAllCombatTickets( true );
  2117.  
  2118. if( actorVictim.WillBeUnconscious() )
  2119. {
  2120. actorVictim.SetBehaviorVariable( 'prepareForUnconsciousFinisher', 1.0f );
  2121. actorVictim.ActionRotateToAsync( thePlayer.GetWorldPosition() );
  2122. }
  2123.  
  2124. moveTargets = thePlayer.GetMoveTargets();
  2125.  
  2126. for ( i = 0; i < moveTargets.Size(); i += 1 )
  2127. {
  2128. if ( actorVictim != moveTargets[i] )
  2129. moveTargets[i].SignalGameplayEvent( 'InterruptChargeAttack' );
  2130. }
  2131.  
  2132. if ( theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'AutomaticFinishersEnabled' ) == "true"
  2133. || ( (W3PlayerWitcher)playerAttacker && GetWitcherPlayer().IsMutationActive( EPMT_Mutation3 ) )
  2134. || actorVictim.WillBeUnconscious()
  2135. )
  2136. {
  2137. actorVictim.AddAbility( 'ForceFinisher', false );
  2138. }
  2139.  
  2140. if ( actorVictim.HasTag( 'ForceFinisher' ) )
  2141. actorVictim.AddAbility( 'ForceFinisher', false );
  2142.  
  2143. actorVictim.SignalGameplayEvent( 'ForceFinisher' );
  2144. }
  2145. else if ( weaponName == 'fists' && npcVictim )
  2146. {
  2147. npcVictim.DisableAgony();
  2148. }
  2149.  
  2150. thePlayer.FindMoveTarget();
  2151. }
  2152.  
  2153. if( attackAction.IsActionMelee() )
  2154. {
  2155. actorAttacker.SignalGameplayEventParamObject( 'HitActionReaction', actorVictim );
  2156. actorVictim.OnHitActionReaction( actorAttacker, weaponName );
  2157. }
  2158.  
  2159.  
  2160. actorVictim.ProcessHitSound(action, playsNonAdditiveAnim || !actorVictim.IsAlive());
  2161.  
  2162.  
  2163.  
  2164. if(action.IsCriticalHit() && action.DealtDamage() && !actorVictim.IsAlive() && actorAttacker == thePlayer )
  2165. GCameraShake( 0.5, true, actorAttacker.GetWorldPosition(), 10 );
  2166.  
  2167.  
  2168. if( attackAction && npcVictim && npcVictim.IsShielded( actorAttacker ) && attackAction.IsParried() && attackAction.GetAttackName() == 'attack_heavy' && npcVictim.GetStaminaPercents() <= 0.1 )
  2169. {
  2170. npcVictim.ProcessShieldDestruction();
  2171. }
  2172.  
  2173.  
  2174. if( actorVictim && action.CanPlayHitParticle() && ( action.DealsAnyDamage() || (attackAction && attackAction.IsParried()) ) )
  2175. actorVictim.PlayHitEffect(action);
  2176.  
  2177.  
  2178. if( action.victim.HasAbility('mon_nekker_base') && !actorVictim.CanPlayHitAnim() && !((CBaseGameplayEffect) action.causer) )
  2179. {
  2180.  
  2181. actorVictim.PlayEffect(theGame.params.LIGHT_HIT_FX);
  2182. actorVictim.SoundEvent("cmb_play_hit_light");
  2183. }
  2184.  
  2185.  
  2186. if(actorVictim && playerAttacker && action.IsActionMelee() && thePlayer.inv.IsItemFists(weaponId) )
  2187. {
  2188. actorVictim.SignalGameplayEvent( 'wasHitByFists' );
  2189.  
  2190. if(MonsterCategoryIsMonster(victimMonsterCategory))
  2191. {
  2192. if(!victimCanBeHitByFists)
  2193. {
  2194. playerAttacker.ReactToReflectedAttack(actorVictim);
  2195. }
  2196. else
  2197. {
  2198. actorVictim.GetResistValue(CDS_PhysicalRes, points, percents);
  2199.  
  2200. if(percents >= theGame.params.MONSTER_RESIST_THRESHOLD_TO_REFLECT_FISTS)
  2201. playerAttacker.ReactToReflectedAttack(actorVictim);
  2202. }
  2203. }
  2204. }
  2205.  
  2206.  
  2207. ProcessSparksFromNoDamage();
  2208.  
  2209.  
  2210. if(attackAction && attackAction.IsActionMelee() && actorAttacker && playerVictim && attackAction.IsCountered() && playerVictim == GetWitcherPlayer())
  2211. {
  2212. GetWitcherPlayer().SetRecentlyCountered(true);
  2213. }
  2214.  
  2215.  
  2216.  
  2217.  
  2218. if(attackAction && !action.IsDoTDamage() && (playerAttacker || playerVictim) && (attackAction.IsParried() || attackAction.IsCountered()) )
  2219. {
  2220. theGame.VibrateControllerLight();
  2221. }
  2222. }
  2223.  
  2224. private function CanDismember( wasFrozen : bool, out dismemberExplosion : bool, out weaponName : name ) : bool
  2225. {
  2226. var dismember : bool;
  2227. var dismemberChance : int;
  2228. var petard : W3Petard;
  2229. var bolt : W3BoltProjectile;
  2230. var arrow : W3ArrowProjectile;
  2231. var inv : CInventoryComponent;
  2232. var toxicCloud : W3ToxicCloud;
  2233. var witcher : W3PlayerWitcher;
  2234. var i : int;
  2235. var secondaryWeapon : bool;
  2236.  
  2237. petard = (W3Petard)action.causer;
  2238. bolt = (W3BoltProjectile)action.causer;
  2239. arrow = (W3ArrowProjectile)action.causer;
  2240. toxicCloud = (W3ToxicCloud)action.causer;
  2241.  
  2242. dismemberExplosion = false;
  2243.  
  2244. if(playerAttacker)
  2245. {
  2246. secondaryWeapon = playerAttacker.inv.ItemHasTag( weaponId, 'SecondaryWeapon' ) || playerAttacker.inv.ItemHasTag( weaponId, 'Wooden' );
  2247. }
  2248.  
  2249. if( actorVictim.HasAbility( 'DisableDismemberment' ) )
  2250. {
  2251. dismember = false;
  2252. }
  2253. else if( actorVictim.HasTag( 'DisableDismemberment' ) )
  2254. {
  2255. dismember = false;
  2256. }
  2257. else if (actorVictim.WillBeUnconscious())
  2258. {
  2259. dismember = false;
  2260. }
  2261. else if (playerAttacker && secondaryWeapon )
  2262. {
  2263. dismember = false;
  2264. }
  2265. else if( arrow && !wasFrozen )
  2266. {
  2267. dismember = false;
  2268. }
  2269. else if( actorAttacker.HasAbility( 'ForceDismemberment' ) )
  2270. {
  2271. dismember = true;
  2272. dismemberExplosion = action.HasForceExplosionDismemberment();
  2273. }
  2274. else if(wasFrozen)
  2275. {
  2276. dismember = true;
  2277. dismemberExplosion = action.HasForceExplosionDismemberment();
  2278. }
  2279. else if( (petard && petard.DismembersOnKill()) || (bolt && bolt.DismembersOnKill()) )
  2280. {
  2281. dismember = true;
  2282. dismemberExplosion = action.HasForceExplosionDismemberment();
  2283. }
  2284. else if( (W3Effect_YrdenHealthDrain)action.causer )
  2285. {
  2286. dismember = true;
  2287. dismemberExplosion = true;
  2288. }
  2289. else if(toxicCloud && toxicCloud.HasExplodingTargetDamages())
  2290. {
  2291. dismember = true;
  2292. dismemberExplosion = true;
  2293. }
  2294. else
  2295. {
  2296. inv = actorAttacker.GetInventory();
  2297. weaponName = inv.GetItemName( weaponId );
  2298.  
  2299. if( attackAction
  2300. && !inv.IsItemSteelSwordUsableByPlayer(weaponId)
  2301. && !inv.IsItemSilverSwordUsableByPlayer(weaponId)
  2302. && weaponName != 'polearm'
  2303. && weaponName != 'fists_lightning'
  2304. && weaponName != 'fists_fire' )
  2305. {
  2306. dismember = false;
  2307. }
  2308. else if ( action.IsCriticalHit() )
  2309. {
  2310. dismember = true;
  2311. dismemberExplosion = action.HasForceExplosionDismemberment();
  2312. }
  2313. else if ( action.HasForceExplosionDismemberment() )
  2314. {
  2315. dismember = true;
  2316. dismemberExplosion = true;
  2317. }
  2318. else
  2319. {
  2320.  
  2321. dismemberChance = theGame.params.DISMEMBERMENT_ON_DEATH_CHANCE;
  2322.  
  2323.  
  2324. if(playerAttacker && playerAttacker.forceDismember)
  2325. {
  2326. dismemberChance = thePlayer.forceDismemberChance;
  2327. dismemberExplosion = thePlayer.forceDismemberExplosion;
  2328. }
  2329.  
  2330.  
  2331. if(attackAction)
  2332. {
  2333. dismemberChance += RoundMath(100 * CalculateAttributeValue(inv.GetItemAttributeValue(weaponId, 'dismember_chance')));
  2334. dismemberExplosion = attackAction.HasForceExplosionDismemberment();
  2335. }
  2336.  
  2337.  
  2338. witcher = (W3PlayerWitcher)actorAttacker;
  2339. if(witcher && witcher.CanUseSkill(S_Perk_03))
  2340. dismemberChance += RoundMath(100 * CalculateAttributeValue(witcher.GetSkillAttributeValue(S_Perk_03, 'dismember_chance', false, true)));
  2341.  
  2342.  
  2343. if( ( W3PlayerWitcher )playerAttacker && attackAction.IsActionMelee() && GetWitcherPlayer().IsMutationActive(EPMT_Mutation3) )
  2344. {
  2345. if( thePlayer.inv.IsItemSteelSwordUsableByPlayer( weaponId ) || thePlayer.inv.IsItemSilverSwordUsableByPlayer( weaponId ) )
  2346. {
  2347. dismemberChance = 100;
  2348. }
  2349. }
  2350.  
  2351. dismemberChance = Clamp(dismemberChance, 0, 100);
  2352.  
  2353. if (RandRange(100) < dismemberChance)
  2354. dismember = true;
  2355. else
  2356. dismember = false;
  2357. }
  2358. }
  2359.  
  2360. return dismember;
  2361. }
  2362.  
  2363. private function CanPerformFinisher( actorVictim : CActor ) : bool
  2364. {
  2365. var finisherChance : int;
  2366. var areEnemiesAttacking : bool;
  2367. var i : int;
  2368. var victimToPlayerVector, playerPos : Vector;
  2369. var item : SItemUniqueId;
  2370. var moveTargets : array<CActor>;
  2371. var b : bool;
  2372. var size : int;
  2373. var npc : CNewNPC;
  2374.  
  2375. if ( (W3ReplacerCiri)thePlayer || playerVictim || thePlayer.isInFinisher )
  2376. return false;
  2377.  
  2378. if ( actorVictim.IsAlive() && !CanPerformFinisherOnAliveTarget(actorVictim) )
  2379. return false;
  2380.  
  2381.  
  2382. if ( actorVictim.WillBeUnconscious() && !theGame.GetDLCManager().IsEP2Available() )
  2383. return false;
  2384.  
  2385. moveTargets = thePlayer.GetMoveTargets();
  2386. size = moveTargets.Size();
  2387. playerPos = thePlayer.GetWorldPosition();
  2388.  
  2389. if ( size > 0 )
  2390. {
  2391. areEnemiesAttacking = false;
  2392. for(i=0; i<size; i+=1)
  2393. {
  2394. npc = (CNewNPC)moveTargets[i];
  2395. if(npc && VecDistanceSquared(playerPos, moveTargets[i].GetWorldPosition()) < 7 && npc.IsAttacking() && npc != actorVictim )
  2396. {
  2397. areEnemiesAttacking = true;
  2398. break;
  2399. }
  2400. }
  2401. }
  2402.  
  2403. victimToPlayerVector = actorVictim.GetWorldPosition() - playerPos;
  2404.  
  2405. if ( actorVictim.IsHuman() )
  2406. {
  2407. npc = (CNewNPC)actorVictim;
  2408. if ( (actorVictim.HasBuff(EET_Confusion) || actorVictim.HasBuff(EET_AxiiGuardMe)) && actorVictim.IsAlive())
  2409. {
  2410. finisherChance = 100 - RoundF(actorVictim.GetHealthPercents() * 100) + ( - ( npc.currentLevel - thePlayer.GetLevel() ) );
  2411. }
  2412. else if ( ( size <= 1 && theGame.params.FINISHER_ON_DEATH_CHANCE > 0 ) || ( actorVictim.HasAbility('ForceFinisher') ) || ( GetWitcherPlayer().IsMutationActive(EPMT_Mutation3) ) )
  2413. {
  2414. finisherChance = 100;
  2415. }
  2416. else if ( npc.currentLevel - thePlayer.GetLevel() < -5 )
  2417. {
  2418. finisherChance = theGame.params.FINISHER_ON_DEATH_CHANCE + ( - ( npc.currentLevel - thePlayer.GetLevel() ) );
  2419. }
  2420. else
  2421. finisherChance = theGame.params.FINISHER_ON_DEATH_CHANCE;
  2422.  
  2423. finisherChance = Clamp(finisherChance, 0, 100);
  2424. }
  2425. else
  2426. finisherChance = 0;
  2427.  
  2428. if ( actorVictim.HasTag('ForceFinisher') )
  2429. {
  2430. finisherChance = 100;
  2431. areEnemiesAttacking = false;
  2432. }
  2433.  
  2434. item = thePlayer.inv.GetItemFromSlot( 'l_weapon' );
  2435.  
  2436. if ( thePlayer.forceFinisher )
  2437. {
  2438. b = playerAttacker && attackAction && attackAction.IsActionMelee();
  2439. b = b && ( actorVictim.IsHuman() && !actorVictim.IsWoman() );
  2440. b = b && !thePlayer.IsInAir();
  2441. b = b && ( thePlayer.IsWeaponHeld( 'steelsword') || thePlayer.IsWeaponHeld( 'silversword') );
  2442. b = b && !thePlayer.IsSecondaryWeaponHeld();
  2443. b = b && !thePlayer.inv.IsIdValid( item );
  2444. b = b && !actorVictim.IsKnockedUnconscious();
  2445. b = b && !actorVictim.HasBuff( EET_Knockdown );
  2446. b = b && !actorVictim.HasBuff( EET_Ragdoll );
  2447. b = b && !actorVictim.HasBuff( EET_Frozen );
  2448. b = b && !actorVictim.HasAbility( 'DisableFinishers' );
  2449. b = b && !thePlayer.IsUsingVehicle();
  2450. b = b && thePlayer.IsAlive();
  2451. b = b && !thePlayer.IsCurrentSignChanneled();
  2452. }
  2453. else
  2454. {
  2455. b = playerAttacker && attackAction && attackAction.IsActionMelee();
  2456. b = b && ( actorVictim.IsHuman() && !actorVictim.IsWoman() );
  2457. b = b && RandRange(100) < finisherChance;
  2458. b = b && !areEnemiesAttacking;
  2459. b = b && AbsF( victimToPlayerVector.Z ) < 0.4f;
  2460. b = b && !thePlayer.IsInAir();
  2461. b = b && ( thePlayer.IsWeaponHeld( 'steelsword') || thePlayer.IsWeaponHeld( 'silversword') );
  2462. b = b && !thePlayer.IsSecondaryWeaponHeld();
  2463. b = b && !thePlayer.inv.IsIdValid( item );
  2464. b = b && !actorVictim.IsKnockedUnconscious();
  2465. b = b && !actorVictim.HasBuff( EET_Knockdown );
  2466. b = b && !actorVictim.HasBuff( EET_Ragdoll );
  2467. b = b && !actorVictim.HasBuff( EET_Frozen );
  2468. b = b && !actorVictim.HasAbility( 'DisableFinishers' );
  2469. b = b && actorVictim.GetAttitude( thePlayer ) == AIA_Hostile;
  2470. b = b && !thePlayer.IsUsingVehicle();
  2471. b = b && thePlayer.IsAlive();
  2472. b = b && !thePlayer.IsCurrentSignChanneled();
  2473. b = b && ( theGame.GetWorld().NavigationCircleTest( actorVictim.GetWorldPosition(), 2.f ) || actorVictim.HasTag('ForceFinisher') ) ;
  2474.  
  2475. }
  2476.  
  2477. if ( b )
  2478. {
  2479. if ( !actorVictim.IsAlive() && !actorVictim.WillBeUnconscious() )
  2480. actorVictim.AddAbility( 'DisableFinishers', false );
  2481.  
  2482. return true;
  2483. }
  2484.  
  2485. return false;
  2486. }
  2487.  
  2488. private function CanPerformFinisherOnAliveTarget( actorVictim : CActor ) : bool
  2489. {
  2490. return actorVictim.IsHuman()
  2491. && ( actorVictim.HasBuff(EET_Confusion) || actorVictim.HasBuff(EET_AxiiGuardMe) )
  2492. && actorVictim.IsVulnerable()
  2493. && !actorVictim.HasAbility('DisableFinisher')
  2494. && !actorVictim.HasAbility('InstantKillImmune');
  2495. }
  2496.  
  2497.  
  2498.  
  2499.  
  2500.  
  2501.  
  2502. private function ProcessActionBuffs() : bool
  2503. {
  2504. var inv : CInventoryComponent;
  2505. var ret : bool;
  2506.  
  2507. // CrossbowDamageBoost+
  2508. var witcher : W3PlayerWitcher;
  2509. var boltCauser : W3BoltProjectile;
  2510. // CrossbowDamageBoost-
  2511.  
  2512.  
  2513. if(!action.victim.IsAlive() || action.WasDodged() || (attackAction && attackAction.IsActionMelee() && !attackAction.ApplyBuffsIfParried() && attackAction.CanBeParried() && attackAction.IsParried()) )
  2514. return true;
  2515.  
  2516. // CrossbowDamageBoost+
  2517. witcher = (W3PlayerWitcher)actorAttacker;
  2518. boltCauser = (W3BoltProjectile)(action.causer);
  2519. if (witcher && action.IsActionRanged() && boltCauser)
  2520. {
  2521. witcher.crossbowDmgProcessor.ProcessBoltBuffs(action, boltCauser);
  2522. }
  2523. // CrossbowDamageBoost-
  2524.  
  2525. ApplyQuenBuffChanges();
  2526.  
  2527.  
  2528. /*if( actorAttacker == thePlayer && action.IsActionWitcherSign() && action.IsCriticalHit() && theGame.GetDLCManager().IsEP2Available() && action.HasBuff( EET_Burning ) )
  2529. {
  2530. action.SetBuffSourceName( 'Mutation2ExplosionValid' );
  2531. }*/
  2532.  
  2533.  
  2534. if(actorVictim && action.GetEffectsCount() > 0)
  2535. {
  2536. if (playerAttacker && action.IsActionWitcherSign() && action.GetSignSkill() == S_Magic_s02 && actorVictim.IsImmuneToBuff(EET_Burning))
  2537. actorVictim.AddEffectDefault(EET_Stagger, playerAttacker, , true);
  2538. else
  2539. ret = actorVictim.ApplyActionEffects(action);
  2540. }
  2541. else
  2542. ret = false;
  2543.  
  2544.  
  2545. if(actorAttacker && actorVictim)
  2546. {
  2547. inv = actorAttacker.GetInventory();
  2548. actorAttacker.ProcessOnHitEffects(actorVictim, inv.IsItemSilverSwordUsableByPlayer(weaponId), inv.IsItemSteelSwordUsableByPlayer(weaponId), action.IsActionWitcherSign() );
  2549. }
  2550.  
  2551. return ret;
  2552. }
  2553.  
  2554.  
  2555. private function ApplyQuenBuffChanges()
  2556. {
  2557. var npc : CNewNPC;
  2558. var protection : bool;
  2559. var witcher : W3PlayerWitcher;
  2560. var quenEntity : W3QuenEntity;
  2561. var i : int;
  2562. var buffs : array<EEffectType>;
  2563.  
  2564. if(!actorVictim || !actorVictim.HasAlternateQuen())
  2565. return;
  2566.  
  2567. npc = (CNewNPC)actorVictim;
  2568. if(npc)
  2569. {
  2570. if(!action.DealsAnyDamage())
  2571. protection = true;
  2572. }
  2573. else
  2574. {
  2575. witcher = (W3PlayerWitcher)actorVictim;
  2576. if(witcher)
  2577. {
  2578. quenEntity = (W3QuenEntity)witcher.GetCurrentSignEntity();
  2579. if(quenEntity.GetBlockedAllDamage())
  2580. {
  2581. protection = true;
  2582. }
  2583. }
  2584. }
  2585.  
  2586. if(!protection)
  2587. return;
  2588.  
  2589. action.GetEffectTypes(buffs);
  2590. for(i=buffs.Size()-1; i>=0; i -=1)
  2591. {
  2592. if(buffs[i] == EET_KnockdownTypeApplicator || IsKnockdownEffectType(buffs[i]))
  2593. continue;
  2594.  
  2595. action.RemoveBuff(i);
  2596. }
  2597. }
  2598.  
  2599.  
  2600.  
  2601.  
  2602. private function ProcessDismemberment(wasFrozen : bool, dismemberExplosion : bool )
  2603. {
  2604. var hitDirection : Vector;
  2605. var usedWound : name;
  2606. var npcVictim : CNewNPC;
  2607. var wounds : array< name >;
  2608. var i : int;
  2609. var petard : W3Petard;
  2610. var bolt : W3BoltProjectile;
  2611. var forcedRagdoll : bool;
  2612. var isExplosion : bool;
  2613. var dismembermentComp : CDismembermentComponent;
  2614. var specialWounds : array< name >;
  2615. var useHitDirection : bool;
  2616. var fxMask : EDismembermentEffectTypeFlags;
  2617. var template : CEntityTemplate;
  2618. var ent : CEntity;
  2619. var signType : ESignType;
  2620.  
  2621. if(!actorVictim)
  2622. return;
  2623.  
  2624. dismembermentComp = (CDismembermentComponent)(actorVictim.GetComponentByClassName( 'CDismembermentComponent' ));
  2625. if(!dismembermentComp)
  2626. return;
  2627.  
  2628. if(wasFrozen)
  2629. {
  2630. ProcessFrostDismemberment();
  2631. return;
  2632. }
  2633.  
  2634. forcedRagdoll = false;
  2635.  
  2636.  
  2637. petard = (W3Petard)action.causer;
  2638. bolt = (W3BoltProjectile)action.causer;
  2639.  
  2640. if( dismemberExplosion || (attackAction && ( attackAction.GetAttackName() == 'attack_explosion' || attackAction.HasForceExplosionDismemberment() ))
  2641. || (petard && petard.DismembersOnKill()) || (bolt && bolt.DismembersOnKill()) )
  2642. {
  2643. isExplosion = true;
  2644. }
  2645. else
  2646. {
  2647. isExplosion = false;
  2648. }
  2649.  
  2650.  
  2651. if(playerAttacker && thePlayer.forceDismember && IsNameValid(thePlayer.forceDismemberName))
  2652. {
  2653. usedWound = thePlayer.forceDismemberName;
  2654. }
  2655. else
  2656. {
  2657.  
  2658. if(isExplosion)
  2659. {
  2660. dismembermentComp.GetWoundsNames( wounds, WTF_Explosion );
  2661.  
  2662.  
  2663. if( action.IsMutation2PotentialKill() )
  2664. {
  2665.  
  2666. for( i=wounds.Size()-1; i>=0; i-=1 )
  2667. {
  2668. if( !StrContains( wounds[ i ], "_ep2" ) )
  2669. {
  2670. wounds.EraseFast( i );
  2671. }
  2672. }
  2673.  
  2674. signType = action.GetSignType();
  2675. if( signType == ST_Aard )
  2676. {
  2677. fxMask = DETF_Aaard;
  2678. }
  2679. else if( signType == ST_Igni )
  2680. {
  2681. fxMask = DETF_Igni;
  2682. }
  2683. else if( signType == ST_Yrden )
  2684. {
  2685. fxMask = DETF_Yrden;
  2686. }
  2687. else if( signType == ST_Quen )
  2688. {
  2689. fxMask = DETF_Quen;
  2690. }
  2691. }
  2692. else
  2693. {
  2694. fxMask = 0;
  2695. }
  2696.  
  2697. if ( wounds.Size() > 0 )
  2698. usedWound = wounds[ RandRange( wounds.Size() ) ];
  2699.  
  2700. if ( usedWound )
  2701. StopVO( actorVictim );
  2702. }
  2703. else if(attackAction || action.GetBuffSourceName() == "riderHit")
  2704. {
  2705. if ( attackAction.GetAttackTypeName() == 'sword_s2' || thePlayer.isInFinisher )
  2706. useHitDirection = true;
  2707.  
  2708. if ( useHitDirection )
  2709. {
  2710. hitDirection = actorAttacker.GetSwordTipMovementFromAnimation( attackAction.GetAttackAnimName(), attackAction.GetHitTime(), 0.1, attackAction.GetWeaponEntity() );
  2711. usedWound = actorVictim.GetNearestWoundForBone( attackAction.GetHitBoneIndex(), hitDirection, WTF_Cut );
  2712. }
  2713. else
  2714. {
  2715.  
  2716. dismembermentComp.GetWoundsNames( wounds );
  2717.  
  2718.  
  2719. if(wounds.Size() > 0)
  2720. {
  2721. dismembermentComp.GetWoundsNames( specialWounds, WTF_Explosion );
  2722. for ( i = 0; i < specialWounds.Size(); i += 1 )
  2723. {
  2724. wounds.Remove( specialWounds[i] );
  2725. }
  2726.  
  2727. if(wounds.Size() > 0)
  2728. {
  2729.  
  2730. dismembermentComp.GetWoundsNames( specialWounds, WTF_Frost );
  2731. for ( i = 0; i < specialWounds.Size(); i += 1 )
  2732. {
  2733. wounds.Remove( specialWounds[i] );
  2734. }
  2735.  
  2736.  
  2737. if ( wounds.Size() > 0 )
  2738. usedWound = wounds[ RandRange( wounds.Size() ) ];
  2739. }
  2740. }
  2741. }
  2742. }
  2743. }
  2744.  
  2745. if ( usedWound )
  2746. {
  2747. npcVictim = (CNewNPC)action.victim;
  2748. if(npcVictim)
  2749. npcVictim.DisableAgony();
  2750.  
  2751. actorVictim.SetDismembermentInfo( usedWound, actorVictim.GetWorldPosition() - actorAttacker.GetWorldPosition(), forcedRagdoll, fxMask );
  2752. actorVictim.AddTimer( 'DelayedDismemberTimer', 0.05f );
  2753. actorVictim.SetBehaviorVariable( 'dismemberAnim', 1.0 );
  2754.  
  2755.  
  2756. if ( usedWound == 'explode_02' || usedWound == 'explode2' || usedWound == 'explode_02_ep2' || usedWound == 'explode2_ep2')
  2757. {
  2758. ProcessDismembermentDeathAnim( usedWound, true, EFDT_LegLeft );
  2759. actorVictim.SetKinematic( false );
  2760.  
  2761. }
  2762. else
  2763. {
  2764. ProcessDismembermentDeathAnim( usedWound, false );
  2765. }
  2766.  
  2767.  
  2768. if( usedWound == 'explode_01_ep2' || usedWound == 'explode1_ep2' || usedWound == 'explode_02_ep2' || usedWound == 'explode2_ep2' )
  2769. {
  2770. template = (CEntityTemplate) LoadResource( "explosion_dismember_force" );
  2771. ent = theGame.CreateEntity( template, npcVictim.GetWorldPosition(), , , , true );
  2772. ent.DestroyAfter( 5.f );
  2773. }
  2774.  
  2775. DropEquipmentFromDismember( usedWound, true, true );
  2776.  
  2777. if( attackAction && actorAttacker == thePlayer )
  2778. GCameraShake( 0.5, true, actorAttacker.GetWorldPosition(), 10);
  2779.  
  2780. if(playerAttacker)
  2781. theGame.VibrateControllerHard();
  2782.  
  2783.  
  2784. if( dismemberExplosion && (W3AardProjectile)action.causer )
  2785. {
  2786. npcVictim.AddTimer( 'AardDismemberForce', 0.00001f );
  2787. }
  2788. }
  2789. else
  2790. {
  2791. LogChannel( 'Dismemberment', "ERROR: No wound found to dismember on entity but entity supports dismemberment!!!" );
  2792. }
  2793. }
  2794.  
  2795. function ApplyForce()
  2796. {
  2797. var size, i : int;
  2798. var victim : CNewNPC;
  2799. var fromPos, toPos : Vector;
  2800. var comps : array<CComponent>;
  2801. var impulse : Vector;
  2802.  
  2803. victim = (CNewNPC)action.victim;
  2804. toPos = victim.GetWorldPosition();
  2805. toPos.Z += 1.0f;
  2806. fromPos = toPos;
  2807. fromPos.Z -= 2.0f;
  2808. impulse = VecNormalize( toPos - fromPos.Z ) * 10;
  2809.  
  2810. comps = victim.GetComponentsByClassName('CComponent');
  2811. victim.GetVisualDebug().AddArrow( 'applyForce', fromPos, toPos, 1, 0.2f, 0.2f, true, Color( 0,0,255 ), true, 5.0f );
  2812. size = comps.Size();
  2813. for( i = 0; i < size; i += 1 )
  2814. {
  2815. comps[i].ApplyLocalImpulseToPhysicalObject( impulse );
  2816. }
  2817. }
  2818.  
  2819. private function ProcessFrostDismemberment()
  2820. {
  2821. var dismembermentComp : CDismembermentComponent;
  2822. var wounds : array< name >;
  2823. var wound : name;
  2824. var i, fxMask : int;
  2825. var npcVictim : CNewNPC;
  2826.  
  2827. dismembermentComp = (CDismembermentComponent)(actorVictim.GetComponentByClassName( 'CDismembermentComponent' ));
  2828. if(!dismembermentComp)
  2829. return;
  2830.  
  2831. dismembermentComp.GetWoundsNames( wounds, WTF_Frost );
  2832.  
  2833.  
  2834.  
  2835. if( theGame.GetDLCManager().IsEP2Enabled() )
  2836. {
  2837. fxMask = DETF_Mutation6;
  2838.  
  2839.  
  2840. for( i=wounds.Size()-1; i>=0; i-=1 )
  2841. {
  2842. if( !StrContains( wounds[ i ], "_ep2" ) )
  2843. {
  2844. wounds.EraseFast( i );
  2845. }
  2846. }
  2847. }
  2848. else
  2849. {
  2850. fxMask = 0;
  2851. }
  2852.  
  2853. if ( wounds.Size() > 0 )
  2854. {
  2855. wound = wounds[ RandRange( wounds.Size() ) ];
  2856. }
  2857. else
  2858. {
  2859. return;
  2860. }
  2861.  
  2862. npcVictim = (CNewNPC)action.victim;
  2863. if(npcVictim)
  2864. {
  2865. npcVictim.DisableAgony();
  2866. StopVO( npcVictim );
  2867. }
  2868.  
  2869. actorVictim.SetDismembermentInfo( wound, actorVictim.GetWorldPosition() - actorAttacker.GetWorldPosition(), true, fxMask );
  2870. actorVictim.AddTimer( 'DelayedDismemberTimer', 0.05f );
  2871. if( wound == 'explode_02' || wound == 'explode2' || wound == 'explode_02_ep2' || wound == 'explode2_ep2' )
  2872. {
  2873. ProcessDismembermentDeathAnim( wound, true, EFDT_LegLeft );
  2874. npcVictim.SetKinematic(false);
  2875. }
  2876. else
  2877. {
  2878. ProcessDismembermentDeathAnim( wound, false );
  2879. }
  2880. DropEquipmentFromDismember( wound, true, true );
  2881.  
  2882. if( attackAction )
  2883. GCameraShake( 0.5, true, actorAttacker.GetWorldPosition(), 10);
  2884.  
  2885. if(playerAttacker)
  2886. theGame.VibrateControllerHard();
  2887. }
  2888.  
  2889.  
  2890. private function ProcessDismembermentDeathAnim( nearestWound : name, forceDeathType : bool, optional deathType : EFinisherDeathType )
  2891. {
  2892. var dropCurveName : name;
  2893.  
  2894. if ( forceDeathType )
  2895. {
  2896. if ( deathType == EFDT_Head )
  2897. StopVO( actorVictim );
  2898.  
  2899. actorVictim.SetBehaviorVariable( 'FinisherDeathType', (int)deathType );
  2900.  
  2901. return;
  2902. }
  2903.  
  2904. dropCurveName = ( (CDismembermentComponent)(actorVictim.GetComponentByClassName( 'CDismembermentComponent' )) ).GetMainCurveName( nearestWound );
  2905.  
  2906. if ( dropCurveName == 'head' )
  2907. {
  2908. actorVictim.SetBehaviorVariable( 'FinisherDeathType', (int)EFDT_Head );
  2909. StopVO( actorVictim );
  2910. }
  2911. else if ( dropCurveName == 'torso_left' || dropCurveName == 'torso_right' || dropCurveName == 'torso' )
  2912. actorVictim.SetBehaviorVariable( 'FinisherDeathType', (int)EFDT_Torso );
  2913. else if ( dropCurveName == 'arm_right' )
  2914. actorVictim.SetBehaviorVariable( 'FinisherDeathType', (int)EFDT_ArmRight );
  2915. else if ( dropCurveName == 'arm_left' )
  2916. actorVictim.SetBehaviorVariable( 'FinisherDeathType', (int)EFDT_ArmLeft );
  2917. else if ( dropCurveName == 'leg_left' )
  2918. actorVictim.SetBehaviorVariable( 'FinisherDeathType', (int)EFDT_LegLeft );
  2919. else if ( dropCurveName == 'leg_right' )
  2920. actorVictim.SetBehaviorVariable( 'FinisherDeathType', (int)EFDT_LegRight );
  2921. else
  2922. actorVictim.SetBehaviorVariable( 'FinisherDeathType', (int)EFDT_None );
  2923. }
  2924.  
  2925. private function StopVO( actor : CActor )
  2926. {
  2927. actor.SoundEvent( "grunt_vo_death_stop", 'head' );
  2928. }
  2929.  
  2930. private function DropEquipmentFromDismember( nearestWound : name, optional dropLeft, dropRight : bool )
  2931. {
  2932. var dropCurveName : name;
  2933.  
  2934. if( actorVictim.HasAbility( 'DontDropWeaponsOnDismemberment' ) )
  2935. {
  2936. return;
  2937. }
  2938.  
  2939. dropCurveName = ( (CDismembermentComponent)(actorVictim.GetComponentByClassName( 'CDismembermentComponent' )) ).GetMainCurveName( nearestWound );
  2940.  
  2941. if ( ChangeHeldItemAppearance() )
  2942. {
  2943. actorVictim.SignalGameplayEvent('DropWeaponsInDeathTask');
  2944. return;
  2945. }
  2946.  
  2947. if ( dropLeft || dropRight )
  2948. {
  2949.  
  2950. if ( dropLeft )
  2951. actorVictim.DropItemFromSlot( 'l_weapon', true );
  2952.  
  2953. if ( dropRight )
  2954. actorVictim.DropItemFromSlot( 'r_weapon', true );
  2955.  
  2956. return;
  2957. }
  2958.  
  2959. if ( dropCurveName == 'arm_right' )
  2960. actorVictim.DropItemFromSlot( 'r_weapon', true );
  2961. else if ( dropCurveName == 'arm_left' )
  2962. actorVictim.DropItemFromSlot( 'l_weapon', true );
  2963. else if ( dropCurveName == 'torso_left' || dropCurveName == 'torso_right' || dropCurveName == 'torso' )
  2964. {
  2965. actorVictim.DropItemFromSlot( 'l_weapon', true );
  2966. actorVictim.DropItemFromSlot( 'r_weapon', true );
  2967. }
  2968. else if ( dropCurveName == 'head' || dropCurveName == 'leg_left' || dropCurveName == 'leg_right' )
  2969. {
  2970. if( RandRange(100) < 50 )
  2971. actorVictim.DropItemFromSlot( 'l_weapon', true );
  2972.  
  2973. if( RandRange(100) < 50 )
  2974. actorVictim.DropItemFromSlot( 'r_weapon', true );
  2975. }
  2976. }
  2977.  
  2978. function ChangeHeldItemAppearance() : bool
  2979. {
  2980. var inv : CInventoryComponent;
  2981. var weapon : SItemUniqueId;
  2982.  
  2983. inv = actorVictim.GetInventory();
  2984.  
  2985. weapon = inv.GetItemFromSlot('l_weapon');
  2986.  
  2987. if ( inv.IsIdValid( weapon ) )
  2988. {
  2989. if ( inv.ItemHasTag(weapon,'bow') || inv.ItemHasTag(weapon,'crossbow') )
  2990. inv.GetItemEntityUnsafe(weapon).ApplyAppearance("rigid");
  2991. return true;
  2992. }
  2993.  
  2994. weapon = inv.GetItemFromSlot('r_weapon');
  2995.  
  2996. if ( inv.IsIdValid( weapon ) )
  2997. {
  2998. if ( inv.ItemHasTag(weapon,'bow') || inv.ItemHasTag(weapon,'crossbow') )
  2999. inv.GetItemEntityUnsafe(weapon).ApplyAppearance("rigid");
  3000. return true;
  3001. }
  3002.  
  3003. return false;
  3004. }
  3005.  
  3006.  
  3007. private function GetOilProtectionAgainstMonster(dmgType : name, out resist : float, out reduct : float)
  3008. {
  3009. var i : int;
  3010. var heldWeapons : array< SItemUniqueId >;
  3011. var weapon : SItemUniqueId;
  3012.  
  3013. resist = 0;
  3014. reduct = 0;
  3015.  
  3016.  
  3017. heldWeapons = thePlayer.inv.GetHeldWeapons();
  3018.  
  3019.  
  3020. for( i=0; i<heldWeapons.Size(); i+=1 )
  3021. {
  3022. if( !thePlayer.inv.IsItemFists( heldWeapons[ i ] ) )
  3023. {
  3024. weapon = heldWeapons[ i ];
  3025. break;
  3026. }
  3027. }
  3028.  
  3029.  
  3030. if( !thePlayer.inv.IsIdValid( weapon ) )
  3031. {
  3032. return;
  3033. }
  3034.  
  3035.  
  3036. if( !thePlayer.inv.ItemHasActiveOilApplied( weapon, attackerMonsterCategory ) )
  3037. {
  3038. return;
  3039. }
  3040.  
  3041. resist = CalculateAttributeValue( thePlayer.GetSkillAttributeValue( S_Alchemy_s05, 'defence_bonus', false, true ) );
  3042. }
  3043.  
  3044.  
  3045. private function ProcessToxicCloudDismemberExplosion(damages : array<SRawDamage>)
  3046. {
  3047. var act : W3DamageAction;
  3048. var i, j : int;
  3049. var ents : array<CGameplayEntity>;
  3050.  
  3051.  
  3052. if(damages.Size() == 0)
  3053. {
  3054. LogAssert(false, "W3DamageManagerProcessor.ProcessToxicCloudDismemberExplosion: trying to process but no damages are passed! Aborting!");
  3055. return;
  3056. }
  3057.  
  3058.  
  3059. FindGameplayEntitiesInSphere(ents, action.victim.GetWorldPosition(), 3, 1000, , FLAG_OnlyAliveActors);
  3060.  
  3061.  
  3062. for(i=0; i<ents.Size(); i+=1)
  3063. {
  3064. act = new W3DamageAction in this;
  3065. act.Initialize(action.attacker, ents[i], action.causer, 'Dragons_Dream_3', EHRT_Heavy, CPS_Undefined, false, false, false, true);
  3066.  
  3067. for(j=0; j<damages.Size(); j+=1)
  3068. {
  3069. act.AddDamage(damages[j].dmgType, damages[j].dmgVal);
  3070. }
  3071.  
  3072. theGame.damageMgr.ProcessAction(act);
  3073. delete act;
  3074. }
  3075. }
  3076.  
  3077.  
  3078. private final function ProcessSparksFromNoDamage()
  3079. {
  3080. var sparksEntity, weaponEntity : CEntity;
  3081. var weaponTipPosition : Vector;
  3082. var weaponSlotMatrix : Matrix;
  3083.  
  3084.  
  3085. if(!playerAttacker || !attackAction || !attackAction.IsActionMelee() || attackAction.DealsAnyDamage())
  3086. return;
  3087.  
  3088.  
  3089. if( ( !attackAction.DidArmorReduceDamageToZero() && !actorVictim.IsVampire() && ( attackAction.IsParried() || attackAction.IsCountered() ) )
  3090. || ( ( attackAction.IsParried() || attackAction.IsCountered() ) && !actorVictim.IsHuman() && !actorVictim.IsVampire() )
  3091. || actorVictim.IsCurrentlyDodging() )
  3092. return;
  3093.  
  3094.  
  3095. if(actorVictim.HasTag('NoSparksOnArmorDmgReduced'))
  3096. return;
  3097.  
  3098.  
  3099. if (!actorVictim.GetGameplayVisibility())
  3100. return;
  3101.  
  3102.  
  3103. weaponEntity = playerAttacker.inv.GetItemEntityUnsafe(weaponId);
  3104. weaponEntity.CalcEntitySlotMatrix( 'blood_fx_point', weaponSlotMatrix );
  3105. weaponTipPosition = MatrixGetTranslation( weaponSlotMatrix );
  3106.  
  3107.  
  3108. sparksEntity = theGame.CreateEntity( (CEntityTemplate)LoadResource( 'sword_colision_fx' ), weaponTipPosition );
  3109. sparksEntity.PlayEffect('sparks');
  3110. }
  3111.  
  3112. private function ProcessPreHitModifications()
  3113. {
  3114. var fireDamage, totalDmg, maxHealth, currHealth : float;
  3115. var attribute, min, max : SAbilityAttributeValue;
  3116. var infusion : ESignType;
  3117. var hack : array< SIgniEffects >;
  3118. var dmgValTemp : float;
  3119. var igni : W3IgniEntity;
  3120. var quen : W3QuenEntity;
  3121. var pos : Vector;
  3122. var fxEntity : CEntity;
  3123.  
  3124. if( actorVictim.HasAbility( 'HitWindowOpened' ) && !action.IsDoTDamage() )
  3125. {
  3126. if( actorVictim.HasTag( 'fairytale_witch' ) )
  3127. {
  3128.  
  3129.  
  3130.  
  3131.  
  3132.  
  3133.  
  3134. ((CNewNPC)actorVictim).SetBehaviorVariable( 'shouldBreakFlightLoop', 1.0 );
  3135.  
  3136. }
  3137. else
  3138. {
  3139. quen = (W3QuenEntity)action.causer;
  3140.  
  3141. if( !quen )
  3142. {
  3143. if( actorVictim.HasTag( 'dettlaff_vampire' ) )
  3144. {
  3145. actorVictim.StopEffect( 'shadowdash' );
  3146. }
  3147.  
  3148. action.ClearDamage();
  3149. if( action.IsActionMelee() )
  3150. {
  3151. actorVictim.PlayEffect( 'special_attack_break' );
  3152. }
  3153. actorVictim.SetBehaviorVariable( 'repelType', 0 );
  3154.  
  3155. actorVictim.AddEffectDefault( EET_CounterStrikeHit, thePlayer );
  3156. action.RemoveBuffsByType( EET_KnockdownTypeApplicator );
  3157. }
  3158. }
  3159.  
  3160. ((CNewNPC)actorVictim).SetHitWindowOpened( false );
  3161. }
  3162.  
  3163.  
  3164.  
  3165. if(playerAttacker && attackAction && attackAction.IsActionMelee() && (W3PlayerWitcher)thePlayer)// && thePlayer.HasAbility('Runeword 1 _Stats', true))
  3166. {
  3167. infusion = GetWitcherPlayer().GetRunewordInfusionType();
  3168.  
  3169. switch(infusion)
  3170. {
  3171. case ST_Aard:
  3172. action.AddEffectInfo(EET_KnockdownTypeApplicator);
  3173. action.SetProcessBuffsIfNoDamage(true);
  3174. attackAction.SetApplyBuffsIfParried(true);
  3175. actorVictim.CreateFXEntityAtPelvis( 'runeword_1_aard', false );
  3176.  
  3177. totalDmg = action.GetDamageValueTotal();
  3178. fireDamage = totalDmg * 0.25;
  3179. action.AddDamage(theGame.params.DAMAGE_NAME_ELEMENTAL, fireDamage );
  3180.  
  3181. break;
  3182. case ST_Axii:
  3183. //action.AddEffectInfo(EET_Confusion);
  3184. action.AddEffectInfo(EET_Frozen, 1);
  3185. action.SetProcessBuffsIfNoDamage(true);
  3186. attackAction.SetApplyBuffsIfParried(true);
  3187.  
  3188. actorVictim.CreateFXEntityAtPelvis( 'runeword_1_aard', false );
  3189. action.SetCanPlayHitParticle(true);
  3190.  
  3191. fxEntity = GetWitcherPlayer().CreateFXEntityAtPelvis( 'mutation2_critical', false );
  3192. fxEntity.Teleport(action.victim.GetWorldPosition());
  3193. fxEntity.PlayEffect( 'critical_aard' );
  3194. fxEntity.DestroyAfter(0.5);
  3195.  
  3196. pos = action.victim.GetWorldPosition();
  3197. theGame.GetSurfacePostFX().AddSurfacePostFXGroup( pos, 0.f, 3.f, 4.f, 15.f, 0 );
  3198. break;
  3199.  
  3200. case ST_Igni:
  3201. action.SetProcessBuffsIfNoDamage(false);
  3202. totalDmg = action.GetDamageValueTotal();
  3203. fireDamage = totalDmg * 0.02;
  3204. action.AddDamage(theGame.params.DAMAGE_NAME_FIRE, fireDamage);
  3205.  
  3206. action.SetHitReactionType(EHRT_Heavy);
  3207. action.victim.PlayEffect('critical_burning');
  3208. action.victim.AddTimer('Runeword1DisableFireFX', 3.f);
  3209.  
  3210. fxEntity = GetWitcherPlayer().CreateFXEntityAtPelvis( 'mutation2_critical', false );
  3211. fxEntity.Teleport(action.victim.GetWorldPosition());
  3212. fxEntity.PlayEffect( 'critical_quen' );
  3213. fxEntity.DestroyAfter(0.5);
  3214.  
  3215. action.AddEffectInfo(EET_Burning, 3);
  3216. break;
  3217.  
  3218. case ST_Yrden:
  3219. action.SetProcessBuffsIfNoDamage(false);
  3220. totalDmg = action.GetDamageValueTotal();
  3221. fireDamage = totalDmg * 0.35;
  3222. action.AddDamage(theGame.params.DAMAGE_NAME_ELEMENTAL, fireDamage);
  3223.  
  3224. actorVictim.CreateFXEntityAtPelvis( 'runeword_1_aard', false );
  3225. action.SetCanPlayHitParticle(true);
  3226. action.SetHitReactionType(EHRT_Heavy);
  3227. action.victim.PlayEffect('yrden_shock');
  3228. break;
  3229.  
  3230. //case ST_Quen:
  3231. //action.SetProcessBuffsIfNoDamage(false);
  3232. //totalDmg = action.GetDamageValueTotal();
  3233. //fireDamage = totalDmg * 0.20;
  3234. //action.AddDamage(theGame.params.DAMAGE_NAME_POISON, fireDamage);
  3235.  
  3236. //action.SetCanPlayHitParticle(false);
  3237. //action.SetHitReactionType(EHRT_Light);
  3238.  
  3239. //break;
  3240. default:
  3241. break;
  3242. }
  3243. }
  3244.  
  3245.  
  3246. if( playerAttacker && actorVictim && (W3PlayerWitcher)playerAttacker && GetWitcherPlayer().IsMutationActive( EPMT_Mutation9 ) && (W3BoltProjectile)action.causer )
  3247. {
  3248. maxHealth = actorVictim.GetMaxHealth();
  3249. currHealth = actorVictim.GetHealth();
  3250.  
  3251.  
  3252. if( AbsF( maxHealth - currHealth ) < 1.f )
  3253. {
  3254. theGame.GetDefinitionsManager().GetAbilityAttributeValue('Mutation9', 'health_reduction', min, max);
  3255. // CrossbowDamageBoost
  3256. min.valueMultiplicative *= GetWitcherPlayer().crossbowDmgProcessor.GetBoltDamageModCatEyes(((W3BoltProjectile)action.causer).GetBoltName());
  3257. actorVictim.ForceSetStat( actorVictim.GetUsedHealthType(), maxHealth * ( 1 - min.valueMultiplicative ) );
  3258. }
  3259.  
  3260.  
  3261. action.AddEffectInfo( EET_KnockdownTypeApplicator, 0.1f, , , , 1.f );
  3262. }
  3263. }
  3264. }
  3265.  
  3266.  
  3267.  
  3268. exec function ForceDismember( b: bool, optional chance : int, optional n : name, optional e : bool )
  3269. {
  3270. var temp : CR4Player;
  3271.  
  3272. temp = thePlayer;
  3273. temp.forceDismember = b;
  3274. temp.forceDismemberName = n;
  3275. temp.forceDismemberChance = chance;
  3276. temp.forceDismemberExplosion = e;
  3277. }
  3278.  
  3279. exec function ForceFinisher( b: bool, optional n : name, optional rightStance : bool )
  3280. {
  3281. var temp : CR4Player;
  3282.  
  3283. temp = thePlayer;
  3284. temp.forcedStance = rightStance;
  3285. temp.forceFinisher = b;
  3286. temp.forceFinisherAnimName = n;
  3287. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement