Advertisement
lufusol

damageManagerProcessor.ws for Holy Sword Aerondight for Witcher 3 4.01

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