Advertisement
lufusol

effectManager.ws

Dec 26th, 2022 (edited)
1,448
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. // THIS VERSION IS ONLY FOR COMPATIBILITY WHEN ALSO USING THE MOD "IMPROVED TIME SKIP (MEDITATION AND FAST TRAVEL) - NEXT GEN COMPATIBLE" v1.2
  7. // ++modImprovedTimeSkip
  8. struct STempRegenEffectsContainer
  9. {
  10.     var autoRegen : CBaseGameplayEffect;
  11.     var autoRegen_timeLeft : float;
  12.     var effects : array<CBaseGameplayEffect>;
  13.  
  14.     default autoRegen_timeLeft = 0.f;
  15. }
  16. // --modImprovedTimeSkip
  17.  
  18.  
  19. class W3EffectManager
  20. {
  21.     private var owner : CActor;                                        
  22.     private saved var effects : array< CBaseGameplayEffect >;          
  23.     private saved var statDeltas : array<float>;                       
  24.     private saved var cachedDamages : array<SEffectCachedDamage>;      
  25.     private var isReady : bool;                                        
  26.     private saved var currentlyAnimatedCS : CBaseGameplayEffect;       
  27.     private var currentlyPlayedFX : array<SCurrentBuffFX>;             
  28.     private saved var pausedEffects : array<STemporarilyPausedEffect>; 
  29.     private saved var pausedNotAppliedAutoBuffs : array<SPausedAutoEffect>;
  30.     private var ownerIsWitcher : bool;                                 
  31.     private var isInitializingAutobuffs : bool;                        
  32.     private var hasCriticalStateSaveLock : bool;                       
  33.     private var criticalStateSaveLockId : int;                         
  34.    
  35.     private var vitalityAutoRegenOn         : bool;     default vitalityAutoRegenOn         = false;
  36.     private var essenceAutoRegenOn          : bool;     default essenceAutoRegenOn          = false;
  37.     private var staminaAutoRegenOn          : bool;     default staminaAutoRegenOn          = false;
  38.     private var moraleAutoRegenOn           : bool;     default moraleAutoRegenOn           = false;
  39.     private var panicAutoRegenOn            : bool;     default panicAutoRegenOn            = false;
  40.     private var airAutoRegenOn              : bool;     default airAutoRegenOn              = false;
  41.     private var swimmingStaminaAutoRegenOn  : bool;     default swimmingStaminaAutoRegenOn  = false;
  42.     private var adrenalineAutoRegenOn       : bool;     default adrenalineAutoRegenOn       = false;
  43.    
  44.         default isReady = false;
  45.         default isInitializingAutobuffs = false;
  46.        
  47.    
  48.    
  49.     public final function Initialize( actor : CActor )
  50.     {
  51.         var i : int;
  52.         var effect : CBaseGameplayEffect;
  53.         var overridenEffectsIdxs : array<int>;
  54.         var autoEffects : array<name>;
  55.         var type : EEffectType;
  56.         var tmpName : name;
  57.         var npc : CNewNPC;
  58.  
  59.         owner = actor;
  60.         ownerIsWitcher = (W3PlayerWitcher)owner;
  61.         hasCriticalStateSaveLock = false;
  62.         statDeltas.Grow(EnumGetMax('EBaseCharacterStats')+1);
  63.         for(i=0; i<statDeltas.Size(); i+=1)
  64.             statDeltas[i] = 0;
  65.        
  66.        
  67.         npc = (CNewNPC)actor;
  68.         if( npc )
  69.         {
  70.             if( npc.GetNPCType() != ENGT_Commoner )
  71.             {
  72.                 autoEffects = PrepareAutoBuffs();
  73.             }
  74.         }
  75.         else if ( (CR4Player)actor )
  76.             autoEffects = PrepareAutoBuffs();
  77.        
  78.         FilterOutExactly( autoEffects, EET_AutoVitalityRegen );
  79.         FilterOutExactly( autoEffects, EET_AutoEssenceRegen );
  80.         FilterOutExactly( autoEffects, EET_AutoStaminaRegen );
  81.         FilterOutExactly( autoEffects, EET_AutoMoraleRegen );
  82.         FilterOutExactly( autoEffects, EET_AutoPanicRegen );
  83.         FilterOutExactly( autoEffects, EET_AutoAirRegen );
  84.         FilterOutExactly( autoEffects, EET_AutoSwimmingStaminaRegen );
  85.         FilterOutExactly( autoEffects, EET_AdrenalineDrain );
  86.        
  87.        
  88.         if(autoEffects.Size() > 0 && !theGame.IsEffectManagerInitialized())
  89.             theGame.InitializeEffectManager();
  90.        
  91.         isInitializingAutobuffs = true;
  92.         for(i=0; i<autoEffects.Size(); i+=1)
  93.         {
  94.             EffectNameToType(autoEffects[i], type, tmpName);
  95.             InternalAddEffect(type,owner,'autobuff');          
  96.         }
  97.         isInitializingAutobuffs = false;
  98.                
  99.         isReady = true;
  100.     }
  101.    
  102.    
  103.     public final function PerformUpdate(deltaTime : float)
  104.     {
  105.         var i, size : int;
  106.         var delta : float;
  107.         var action : W3DamageAction;
  108.         var wasPaused : bool;
  109.         var carrier, pausedBuff : CBaseGameplayEffect;
  110.         var cachedDeltaRemoved : bool;
  111.            
  112.        
  113.         size = effects.Size();     
  114.         for(i=size-1; i>=0; i -= 1 )
  115.         {
  116.            
  117.             if( effects[ i ].IsPausedDuringDialogAndCutscene() )
  118.             {
  119.                 if( theGame.IsDialogOrCutscenePlaying() && !effects[i].IsPaused('dialogOrCutscene'))
  120.                 {
  121.                     if(IsCriticalEffect(effects[i]))
  122.                         RemoveEffect(effects[i], true);
  123.                     else
  124.                         effects[i].Pause( 'dialogOrCutscene', true );
  125.                 }
  126.                 else if( !theGame.IsDialogOrCutscenePlaying() && effects[i].IsPaused('dialogOrCutscene'))
  127.                 {
  128.                     effects[i].Resume( 'dialogOrCutscene' );
  129.                 }
  130.             }
  131.        
  132.            
  133.             if( effects[i].IsPaused() )
  134.             {
  135.                 continue;
  136.             }
  137.                
  138.            
  139.             if(effects[i].IsActive())
  140.             {
  141.                 effects[i].OnTimeUpdated(deltaTime);       
  142.             }
  143.             else
  144.             {
  145.                 RemoveEffectOnIndex( i );
  146.             }
  147.         }
  148.  
  149.        
  150.        
  151.        
  152.        
  153.        
  154.        
  155.        
  156.        
  157.         size = statDeltas.Size();
  158.         cachedDeltaRemoved = false;
  159.         for(i=0; i<size; i+=1)
  160.         {
  161.             delta = statDeltas[i];
  162.             if(delta == 0)
  163.             {
  164.                 continue;
  165.             }
  166.             else
  167.             {
  168.                 UpdateStatValueChange(i, delta);               
  169.                 statDeltas[i] = 0; 
  170.                 cachedDeltaRemoved = true;
  171.                
  172.                 if(i == BCS_Vitality || i == BCS_Essence)
  173.                     owner.ShowFloatingValue(EFVT_Heal, delta, true);
  174.             }
  175.         }
  176.                
  177.        
  178.         size = cachedDamages.Size();
  179.         if( size > 0 )
  180.         {
  181.             action = new W3DamageAction in theGame.damageMgr;
  182.            
  183.             for(i=0; i<size; i+=1)
  184.             {
  185.                 action.Initialize( (CGameplayEntity)EntityHandleGet(cachedDamages[i].attacker), owner, cachedDamages[i].carrier, cachedDamages[i].sourceName, EHRT_None, cachedDamages[i].powerStatType, false, false, false, cachedDamages[i].isEnvironment);
  186.                 action.AddDamage(cachedDamages[i].dmgType, cachedDamages[i].dmgVal);
  187.                 action.SetHitAnimationPlayType(EAHA_ForceNo);
  188.                 if(cachedDamages[i].dt > 0)
  189.                 {
  190.                     action.SetPointResistIgnored(true);
  191.                     action.SetIsDoTDamage(cachedDamages[i].dt);
  192.                 }
  193.                
  194.                 if(cachedDamages[i].dontShowHitParticle)
  195.                 {
  196.                     action.SetCanPlayHitParticle(false);
  197.                 }
  198.                
  199.                 theGame.damageMgr.ProcessAction(action);
  200.  
  201.                
  202.                 carrier = cachedDamages[i].carrier;
  203.                 if(carrier && carrier.GetEffectType() == EET_Bleeding)
  204.                 {
  205.                     ((W3Effect_Bleeding)carrier).OnDamageDealt( action.DealsAnyDamage() ); 
  206.                 }
  207.                
  208.                
  209.                 if(carrier && carrier.GetEffectType() == EET_Bleeding1)
  210.                 {
  211.                     ((W3Effect_Bleeding1)carrier).OnDamageDealt( action.DealsAnyDamage() );
  212.                 }
  213.                 if(carrier && carrier.GetEffectType() == EET_Bleeding2)
  214.                 {
  215.                     ((W3Effect_Bleeding2)carrier).OnDamageDealt( action.DealsAnyDamage() );
  216.                 }
  217.                 if(carrier && carrier.GetEffectType() == EET_Bleeding3)
  218.                 {
  219.                     ((W3Effect_Bleeding3)carrier).OnDamageDealt( action.DealsAnyDamage() );
  220.                 }
  221.                
  222.             }
  223.  
  224.             delete action;
  225.             cachedDamages.Clear();
  226.             owner.SetEffectsUpdateTicking( false );
  227.         }
  228.        
  229.        
  230.         for(i=pausedEffects.Size()-1; i>=0; i-=1)
  231.         {
  232.             if(pausedEffects[i].timeLeft > -1)
  233.             {
  234.                 pausedEffects[i].timeLeft -= deltaTime;
  235.                 if(pausedEffects[i].timeLeft <= 0)
  236.                 {
  237.                     pausedEffects[i].buff.Resume(pausedEffects[i].source);
  238.                     pausedEffects.Erase(i);
  239.                 }
  240.             }
  241.         }
  242.        
  243.        
  244.         for(i=pausedNotAppliedAutoBuffs.Size()-1; i>=0; i-=1)
  245.         {
  246.             if(pausedNotAppliedAutoBuffs[i].timeLeft > -1)
  247.             {
  248.                 pausedNotAppliedAutoBuffs[i].timeLeft -= deltaTime;
  249.                 if(pausedNotAppliedAutoBuffs[i].timeLeft <= 0)
  250.                 {
  251.                     pausedNotAppliedAutoBuffs.Erase(i);
  252.                 }
  253.             }
  254.         }
  255.        
  256.        
  257.         owner.SetEffectsUpdateTicking( false );
  258.     }
  259.    
  260.    
  261.     private final function PrepareAutoBuffs() : array<name>
  262.     {
  263.         var autoEffects : array<name>;
  264.        
  265.        
  266.         owner.GetAutoEffects(autoEffects);
  267.        
  268.        
  269.        
  270.         FilterAutoBuff(autoEffects, CRS_Vitality, EET_AutoVitalityRegen);
  271.         FilterAutoBuff(autoEffects, CRS_Essence, EET_AutoEssenceRegen);
  272.         FilterAutoBuff(autoEffects, CRS_Stamina, EET_AutoStaminaRegen);
  273.         FilterAutoBuff(autoEffects, CRS_Morale, EET_AutoMoraleRegen);
  274.        
  275.         return autoEffects;
  276.     }
  277.    
  278.    
  279.    
  280.     private final function FilterAutoBuff(out autoEffects : array<name>, regenStat : ECharacterRegenStats, effectType : EEffectType)
  281.     {
  282.         var autoName : name;
  283.         var effectValue, null : SAbilityAttributeValue;
  284.        
  285.         effectValue = owner.GetAttributeValue( RegenStatEnumToName(regenStat) );   
  286.         autoName = EffectTypeToName(effectType);       
  287.        
  288.         if(!autoEffects.Contains(autoName) && effectValue != null)
  289.         {
  290.             autoEffects.PushBack(autoName);
  291.         }
  292.         else if(autoEffects.Contains(autoName) && effectValue == null)
  293.         {
  294.             autoEffects.Remove(autoName);
  295.         }
  296.     }
  297.    
  298.     private final function FilterOutAllApart( out autoEffects : array< name >, effectType : EEffectType )
  299.     {
  300.         var i           : int;
  301.         var autoName    : name;
  302.  
  303.         autoName = EffectTypeToName(effectType);
  304.         for( i = autoEffects.Size()-1; i >= 0; i -= 1 )
  305.         {
  306.             if( autoEffects[ i ] != autoName )
  307.             {
  308.                 autoEffects.Erase( i );
  309.             }
  310.         }
  311.     }
  312.    
  313.     private final function FilterOutExactly( out autoEffects : array< name >, effectType : EEffectType )
  314.     {
  315.         var i           : int;
  316.         var autoName    : name;
  317.  
  318.         autoName = EffectTypeToName( effectType );
  319.         for( i = autoEffects.Size()-1; i >= 0; i -= 1 )
  320.         {
  321.             if( autoEffects[ i ] == autoName )
  322.             {
  323.                 autoEffects.Erase( i );
  324.             }
  325.         }
  326.     }
  327.    
  328.     public final function StartVitalityRegen() : bool
  329.     {
  330.         if( vitalityAutoRegenOn )
  331.         {
  332.             return false;
  333.         }
  334.        
  335.         vitalityAutoRegenOn = StartRegenInternal( CRS_Vitality, EET_AutoVitalityRegen );
  336.         return vitalityAutoRegenOn;
  337.     }
  338.    
  339.     public final function StopVitalityRegen()
  340.     {
  341.         if( !vitalityAutoRegenOn )
  342.         {
  343.             return;
  344.         }
  345.        
  346.         StopRegenInternal( EET_AutoVitalityRegen );
  347.         vitalityAutoRegenOn = false;
  348.     }
  349.    
  350.     public final function StartEssenceRegen() : bool
  351.     {
  352.         if( essenceAutoRegenOn )
  353.         {
  354.             return false;
  355.         }
  356.        
  357.         essenceAutoRegenOn = StartRegenInternal( CRS_Essence, EET_AutoEssenceRegen );
  358.         return essenceAutoRegenOn;
  359.     }
  360.    
  361.     public final function StopEssenceRegen()
  362.     {
  363.         if( !essenceAutoRegenOn )
  364.         {
  365.             return;
  366.         }
  367.        
  368.         StopRegenInternal( EET_AutoEssenceRegen );
  369.         essenceAutoRegenOn = false;
  370.     }
  371.    
  372.     public final function StartStaminaRegen() : bool
  373.     {
  374.         if( staminaAutoRegenOn )
  375.         {
  376.             return false;
  377.         }
  378.        
  379.         staminaAutoRegenOn = StartRegenInternal( CRS_Stamina, EET_AutoStaminaRegen );
  380.         return staminaAutoRegenOn;
  381.     }
  382.    
  383.     public final function StopStaminaRegen()
  384.     {
  385.         if( !staminaAutoRegenOn )
  386.         {
  387.             return;
  388.         }
  389.        
  390.         StopRegenInternal( EET_AutoStaminaRegen );
  391.         staminaAutoRegenOn = false;
  392.     }
  393.    
  394.     public final function StartMoraleRegen() : bool
  395.     {
  396.         if( moraleAutoRegenOn )
  397.         {
  398.             return false;
  399.         }
  400.        
  401.         moraleAutoRegenOn = StartRegenInternal( CRS_Morale, EET_AutoMoraleRegen );
  402.         return moraleAutoRegenOn;
  403.     }
  404.    
  405.     public final function StopMoraleRegen()
  406.     {
  407.         if( !moraleAutoRegenOn )
  408.         {
  409.             return;
  410.         }
  411.        
  412.         StopRegenInternal( EET_AutoMoraleRegen );
  413.         moraleAutoRegenOn = false;
  414.     }
  415.    
  416.     public final function StartPanicRegen() : bool
  417.     {
  418.         if( panicAutoRegenOn )
  419.         {
  420.             return false;
  421.         }
  422.        
  423.         panicAutoRegenOn = StartRegenInternal( CRS_Panic, EET_AutoPanicRegen );
  424.         return panicAutoRegenOn;
  425.     }
  426.    
  427.     public final function StopPanicRegen()
  428.     {
  429.         if( !panicAutoRegenOn )
  430.         {
  431.             return;
  432.         }
  433.        
  434.         StopRegenInternal( EET_AutoPanicRegen );
  435.         panicAutoRegenOn = false;
  436.     }
  437.    
  438.     public final function StartAirRegen() : bool
  439.     {
  440.         if( airAutoRegenOn )
  441.         {
  442.             return false;
  443.         }
  444.        
  445.         airAutoRegenOn = StartRegenInternal( CRS_Air, EET_AutoAirRegen );
  446.         return airAutoRegenOn;
  447.     }
  448.    
  449.     public final function StopAirRegen()
  450.     {
  451.         if( !airAutoRegenOn )
  452.         {
  453.             return;
  454.         }
  455.        
  456.         StopRegenInternal( EET_AutoAirRegen );
  457.         airAutoRegenOn = false;
  458.     }
  459.    
  460.     public final function StartSwimmingStaminaRegen() : bool
  461.     {
  462.         if( swimmingStaminaAutoRegenOn )
  463.         {
  464.             return false;
  465.         }
  466.        
  467.         swimmingStaminaAutoRegenOn = StartRegenInternal( CRS_SwimmingStamina, EET_AutoSwimmingStaminaRegen );
  468.         return airAutoRegenOn;
  469.     }
  470.    
  471.     public final function StopSwimmingStaminaRegen()
  472.     {
  473.         if( !airAutoRegenOn )
  474.         {
  475.             return;
  476.         }
  477.        
  478.         StopRegenInternal( EET_AutoSwimmingStaminaRegen );
  479.         airAutoRegenOn = false;
  480.     }
  481.    
  482.     private final function StopRegenInternal( effectType : EEffectType )
  483.     {
  484.         var effect : CBaseGameplayEffect;
  485.         effect = GetEffect( effectType );
  486.         RemoveEffect( effect, true );
  487.     }
  488.    
  489.     private final function StartRegenInternal( regenStat : ECharacterRegenStats, effectType : EEffectType ) : bool
  490.     {
  491.         var autoEffects     : array<name>;
  492.         var npc             : CNewNPC;
  493.         var i               : int;
  494.         var addResult       : EEffectInteract;
  495.        
  496.         npc = (CNewNPC)owner;
  497.         if( ( npc && ( npc.GetNPCType() == ENGT_Commoner ) ) || ( !npc && !( (CR4Player )owner ) ) )
  498.         {
  499.             return false;
  500.         }
  501.        
  502.         owner.GetAutoEffects( autoEffects );
  503.         FilterOutAllApart( autoEffects, effectType );
  504.        
  505.         if( regenStat != CRS_UNUSED )
  506.         {
  507.             FilterAutoBuff( autoEffects, regenStat, effectType );
  508.         }
  509.        
  510.         if( autoEffects.Size() > 0 )
  511.         {
  512.             addResult = InternalAddEffect( effectType, owner, 'autobuff' );
  513.            
  514.             if(addResult == EI_Pass)
  515.             {
  516.                 return true;       
  517.             }
  518.             else if(addResult == EI_Cumulate)
  519.             {
  520.                 owner.SetEffectsUpdateTicking(true);
  521.                 return true;
  522.             }              
  523.         }
  524.        
  525.         return false;
  526.     }
  527.    
  528.    
  529.     public final function OnLoad(own : CActor)
  530.     {
  531.         var i : int;
  532.        
  533.         owner = own;
  534.         hasCriticalStateSaveLock = false;
  535.         ownerIsWitcher = (W3PlayerWitcher)owner;
  536.         for(i=0; i<effects.Size(); i+=1)
  537.             effects[i].OnLoad(owner, this);
  538.            
  539.        
  540.         staminaAutoRegenOn = false;    
  541.         essenceAutoRegenOn = false;    
  542.         staminaAutoRegenOn = false;    
  543.         moraleAutoRegenOn = false;     
  544.         panicAutoRegenOn = false;      
  545.         airAutoRegenOn = false;    
  546.         swimmingStaminaAutoRegenOn = false;    
  547.         adrenalineAutoRegenOn = false;     
  548.                
  549.        
  550.         owner.SetEffectsUpdateTicking(true);
  551.         isReady = true;
  552.     }
  553.    
  554.     public final function IsReady() : bool {return isReady;}       
  555.     public final function GetCurrentlyAnimatedCS() : CBaseGameplayEffect            {return currentlyAnimatedCS;}
  556.     public final function SetCurrentlyAnimatedCS(buff : CBaseGameplayEffect)
  557.     {
  558.         if(owner == thePlayer)
  559.             LogCriticalPlayer("** EffectManager.SetCurrentlyAnimatedCS() - current is now <<" + buff + ">>");
  560.            
  561.         if(!buff)
  562.             Log("");
  563.            
  564.         currentlyAnimatedCS = buff;
  565.     }
  566.    
  567.    
  568.     public final function GetCurrentEffects(optional type : EEffectType, optional sourceName : string, optional partialSourceNameSearch : bool) : array< CBaseGameplayEffect >
  569.     {
  570.         var i : int;
  571.         var ret : array< CBaseGameplayEffect >;
  572.         var buffOk, sourceNameSet : bool;
  573.        
  574.         sourceNameSet = (sourceName != "" && sourceName != "None" && sourceName != "none");
  575.        
  576.         if(type == EET_Undefined && !sourceNameSet)
  577.             return effects;
  578.        
  579.         for(i=0; i<effects.Size(); i+=1)
  580.         {
  581.            
  582.             if(effects[i])
  583.             {
  584.                 buffOk = true;
  585.                
  586.                
  587.                 if(type != EET_Undefined)
  588.                 {
  589.                     if(type != effects[i].GetEffectType())
  590.                         buffOk = false;
  591.                 }
  592.                
  593.                 if(buffOk)
  594.                 {
  595.                     if(partialSourceNameSearch)
  596.                     {
  597.                         buffOk = (StrFindFirst(effects[i].GetSourceName(), sourceName) != -1);
  598.                     }
  599.                     else
  600.                     {
  601.                         if(!sourceNameSet)
  602.                         {
  603.                             buffOk = true;
  604.                         }  
  605.                         else
  606.                         {
  607.                             buffOk = (effects[i].GetSourceName() == sourceName);
  608.                         }
  609.                     }
  610.                    
  611.                     if(buffOk)
  612.                         ret.PushBack(effects[i]);
  613.                 }
  614.             }
  615.         }
  616.        
  617.         return ret;
  618.     }
  619.            
  620.    
  621.     private final function ApplyEffect( effect : CBaseGameplayEffect, overridenEffectsIdxs : array<int>, cumulateIdx : int, customParams : W3BuffCustomParams) : EEffectInteract
  622.     {
  623.         var i, size : int;     
  624.         var effectType : EEffectType;
  625.        
  626.        
  627.         size = overridenEffectsIdxs.Size();
  628.         for(i=size-1; i>=0; i-=1)
  629.         {
  630.             RemoveEffectOnIndex( overridenEffectsIdxs[ i ], true );
  631.         }
  632.        
  633.        
  634.         if(cumulateIdx >= 0)
  635.         {
  636.             effects[cumulateIdx].CumulateWith(effect);
  637.             delete effect;
  638.             return EI_Cumulate;
  639.         }
  640.        
  641.         else
  642.         {
  643.             effect.OnEffectAdded(customParams);
  644.                        
  645.            
  646.             if(!effect.IsActive())
  647.             {
  648.                 LogAssert(false, "W3EffectManager.ApplyEffect: effect <<" + effect + ">> did not add properly (is inactive just after added) to <<" + owner + ">> and is removed!");
  649.                 effect.OnEffectRemoved();
  650.                 return EI_Undefined;
  651.             }
  652.            
  653.            
  654.             effectType = effect.GetEffectType();
  655.             if(pausedNotAppliedAutoBuffs.Size() > 0 && IsBuffAutoBuff(effectType))
  656.             {          
  657.                 for(i=pausedNotAppliedAutoBuffs.Size()-1; i>=0; i-=1)
  658.                 {
  659.                     if(pausedNotAppliedAutoBuffs[i].effectType == effectType)
  660.                     {
  661.                         PauseEffect(effect, pausedNotAppliedAutoBuffs[i].sourceName, pausedNotAppliedAutoBuffs[i].singleLock, pausedNotAppliedAutoBuffs[i].duration, pausedNotAppliedAutoBuffs[i].useMaxDuration);
  662.                         pausedNotAppliedAutoBuffs.EraseFast(i);
  663.                     }
  664.                 }
  665.             }
  666.            
  667.             effects.PushBack( effect );
  668.             owner.SetEffectsUpdateTicking( true, isInitializingAutobuffs );        
  669.             OnBuffAdded(effect);
  670.            
  671.             effect.OnEffectAddedPost();
  672.            
  673.            
  674.             if(size > 0)
  675.                 return EI_Override;
  676.             else
  677.                 return EI_Pass;
  678.         }
  679.     }
  680.    
  681.    
  682.     private final function OnBuffRemoved()
  683.     {
  684.         if(hasCriticalStateSaveLock && GetCriticalBuffsCount() == 0)
  685.         {
  686.             theGame.ReleaseNoSaveLock(criticalStateSaveLockId);
  687.             hasCriticalStateSaveLock = false;
  688.         }
  689.     }
  690.    
  691.    
  692.     private final function OnBuffAdded(effect : CBaseGameplayEffect)
  693.     {
  694.         var signEffects : array < CBaseGameplayEffect >;
  695.         var npcOwner : CNewNPC;
  696.         var mutagen : W3Mutagen13_Effect;
  697.         var i, doneBuffs : int;
  698.         var effectType : EEffectType;
  699.        
  700.         effectType = effect.GetEffectType();
  701.        
  702.         if(!hasCriticalStateSaveLock && owner == thePlayer && IsCriticalEffectType(effectType) )
  703.         {
  704.              theGame.CreateNoSaveLock("critical_state", criticalStateSaveLockId);
  705.              hasCriticalStateSaveLock = true;
  706.         }
  707.        
  708.        
  709.         npcOwner = (CNewNPC)owner;
  710.         if(npcOwner && (effectType == EET_Burning || effectType == EET_Bleeding || effectType == EET_Poison || effectType == EET_PoisonCritical) && !npcOwner.WasBurnedBleedingPoisoned())
  711.         {
  712.             if( owner.HasBuff(EET_Burning) && owner.HasBuff(EET_Bleeding) && (owner.HasBuff(EET_Poison) || owner.HasBuff(EET_PoisonCritical)) )
  713.             {
  714.                 theGame.GetGamerProfile().IncStat(ES_BleedingBurnedPoisoned);
  715.                 npcOwner.SetBleedBurnPoison();
  716.             }
  717.         }
  718.        
  719.        
  720.         if(owner == thePlayer && IsBuffShrine(effectType))
  721.         {
  722.             doneBuffs = CountShrineBuffs();
  723.             if (doneBuffs >= 5)
  724.             {
  725.                 theGame.GetGamerProfile().AddAchievement(EA_PowerOverwhelming);
  726.             }
  727.             else
  728.             {
  729.                 theGame.GetGamerProfile().NoticeAchievementProgress(EA_PowerOverwhelming, doneBuffs);
  730.             }
  731.         }
  732.        
  733.        
  734.         mutagen = (W3Mutagen13_Effect)owner.GetBuff(EET_Mutagen13);
  735.         if(mutagen && mutagen.IsEffectTypeAffected(effectType))
  736.         {                  
  737.             effect.SetTimeLeft(mutagen.GetForcedDuration());
  738.         }      
  739.     }
  740.    
  741.    
  742.     public final function UpdateLocalBuffsArray(out localArray : array<CBaseGameplayEffect>)
  743.     {
  744.         var i : int;
  745.        
  746.         for(i=localArray.Size()-1; i>=0; i-=1)
  747.             if(!effects.Contains(localArray[i]))
  748.                 localArray.Erase(i);
  749.     }
  750.            
  751.     public final function AddEffectCustom(params : SCustomEffectParams) : EEffectInteract
  752.     {
  753.         return InternalAddEffect(
  754.             params.effectType,
  755.             params.creator,
  756.             params.sourceName,
  757.             params.duration,
  758.             params.effectValue,
  759.             params.customAbilityName,
  760.             params.customFXName,
  761.             params.isSignEffect,
  762.             params.customPowerStatValue,
  763.             params.buffSpecificParams,
  764.             params.vibratePadLowFreq,
  765.             params.vibratePadHighFreq
  766.         );
  767.     }
  768.    
  769.    
  770.     public final function AddEffectDefault(effectType : EEffectType, creat : CGameplayEntity, optional srcName : string, optional signEffect : bool) : EEffectInteract
  771.     {
  772.         var none : SAbilityAttributeValue;
  773.         var noneParams : W3BuffCustomParams;
  774.        
  775.         return InternalAddEffect(effectType, creat, srcName, 0, none, '', '', signEffect, none, noneParams);
  776.     }
  777.    
  778.    
  779.     private final function InternalAddEffect(effectType : EEffectType, creat : CGameplayEntity, srcName : string, optional inDuration : float, optional customVal : SAbilityAttributeValue, optional customAbilityName : name, optional customFXName : name, optional signEffect : bool, optional powerStatValue : SAbilityAttributeValue, optional customParams : W3BuffCustomParams, optional vibratePadLowFreq : float, optional vibratePadHighFreq : float) : EEffectInteract
  780.     {
  781.         var effect : CBaseGameplayEffect;
  782.         var overridenEffectsIdxs : array<int>;
  783.         var cumulateIdx, i : int;
  784.         var npc : CNewNPC;
  785.         var actorCreator : CActor;
  786.         var action : W3DamageAction;
  787.         var hasQuen : bool;
  788.         var damages : array<SRawDamage>;
  789.         var forceOnNpc : bool;
  790.         var npcStorage : CBaseAICombatStorage;
  791.        
  792.        
  793.         var j, focus : int;
  794.         var woundsAll : array<EEffectType>;
  795.         var woundsToAdd : array<EEffectType>;
  796.        
  797.        
  798.         if(effectType == EET_Undefined)
  799.         {
  800.             LogAssert(false, "EffectManager.AddEffectByType: trying to add effect of undefined type!");
  801.             return EI_Undefined;
  802.         }
  803.        
  804.        
  805.         if(effectType == EET_Burning)
  806.         {
  807.             if( ((CMovingPhysicalAgentComponent)owner.GetMovingAgentComponent()).GetSubmergeDepth() <= -1)
  808.             {
  809.                 LogEffects("EffectManager.InternalAddEffect: unit <<" + owner + ">> will not get burning effect since it's underwater!");
  810.                 return EI_Deny;
  811.             }
  812.         }      
  813.        
  814.         else if( effectType == EET_Frozen )
  815.         {
  816.             npc = (CNewNPC)owner;
  817.             if ( npc )
  818.             {
  819.                 npcStorage = (CBaseAICombatStorage)npc.GetScriptStorageObject('CombatData');
  820.                 if ( npc.IsFlying() )
  821.                 {
  822.                     LogEffects("EffectManager.InternalAddEffect: unit <<" + owner + ">> will not get frozen effect since it's currently flying!");
  823.                     return EI_Deny;
  824.                 }
  825.                 else if ( npcStorage.GetIsInImportantAnim() )
  826.                 {
  827.                     LogEffects("EffectManager.InternalAddEffect: unit <<" + owner + ">> will not get frozen effect since it's in an uninterruptable animation!");
  828.                     return EI_Deny;
  829.                 }
  830.             }
  831.         }
  832.        
  833.        
  834.         if( owner == thePlayer && thePlayer.HasBuff( EET_Mutagen08 ) )
  835.         {
  836.             if( effectType == EET_Knockdown )
  837.             {
  838.                 LogEffects( "EffectManager.InternalAddEffect: changing EET_Knockdown to EET_Stagger due to Mutagen 8 in effect" );
  839.                 effectType = EET_Stagger;
  840.             }
  841.             else if( effectType == EET_LongStagger || effectType == EET_Stagger )
  842.             {
  843.                 LogEffects( "EffectManager.InternalAddEffect: denying " + effectType + " due to Mutagen 8 in effect" );
  844.                 return EI_Deny;
  845.             }
  846.         }
  847.        
  848.        
  849.         if( ((W3PlayerWitcher)owner) && GetWitcherPlayer().IsAnyQuenActive())
  850.         {
  851.             hasQuen = true;
  852.            
  853.             if(effectType == EET_Stagger || effectType == EET_LongStagger || effectType == EET_CounterStrikeHit)
  854.             {
  855.                 GetWitcherPlayer().FinishQuen(false);
  856.                 LogEffects("EffectManager.InternalAddEffect: Geralt has active quen so it breaks and we don't stagger.");
  857.                 return EI_Deny;
  858.             }
  859.         }
  860.        
  861.        
  862.        
  863.        
  864.         if( owner == thePlayer && effectType == EET_HeavyKnockdown )
  865.         {
  866.             LogEffects( "EffectManager.InternalAddEffect: changing EET_HeavyKnockdown to EET_Knockdown, general rule for player character" );
  867.             effectType = EET_Knockdown;
  868.         }
  869.        
  870.        
  871.         if(srcName == "" && creat)
  872.             srcName = creat.GetName();
  873.        
  874.        
  875.        
  876.         if( effectType == EET_Bleeding && (CNewNPC)owner && GetWitcherPlayer().IsSetBonusActive( EISB_Wolf_2 ) )
  877.         {
  878.             focus = (int) thePlayer.GetStat(BCS_Focus);
  879.            
  880.             woundsAll.PushBack( EET_Bleeding1 );
  881.             woundsAll.PushBack( EET_Bleeding2 );
  882.             woundsAll.PushBack( EET_Bleeding3 );
  883.            
  884.             if( !owner.HasBuff( EET_Bleeding ) )
  885.             {
  886.                
  887.             }
  888.             else
  889.             {
  890.                 woundsToAdd = woundsAll;
  891.                 woundsAll.PushBack( EET_Bleeding );
  892.                
  893.                 if( owner.HasBuff( EET_Bleeding1 ) ) { woundsToAdd.Remove( EET_Bleeding1 ); j += 1; }
  894.                 if( owner.HasBuff( EET_Bleeding2 ) ) { woundsToAdd.Remove( EET_Bleeding2 ); j += 1; }
  895.                 if( owner.HasBuff( EET_Bleeding3 ) ) { woundsToAdd.Remove( EET_Bleeding3 ); j += 1; }
  896.                
  897.                
  898.                 if( focus > j )
  899.                 {
  900.                     effectType = woundsToAdd[ RandRange( woundsToAdd.Size() ) ];
  901.                 }
  902.                
  903.                
  904.                
  905.                 else
  906.                 {
  907.                     effectType = woundsAll[ RandRange( focus, 0 ) ];
  908.                 }
  909.                
  910.             }
  911.         }
  912.        
  913.        
  914.        
  915.        
  916.        
  917.        
  918.        
  919.        
  920.        
  921.        
  922.        
  923.        
  924.         if(!owner.IsAlive() && !effect.CanBeAppliedOnDeadTarget())
  925.             return EI_Deny;
  926.            
  927.         actorCreator = (CActor)creat;
  928.        
  929.        
  930.         if ( actorCreator.HasAbility('ForceCriticalEffectsAnim') )
  931.         {
  932.             forceOnNpc = true;
  933.         }
  934.         else if ( actorCreator.HasAbility('ForceCriticalEffectsAnimNPCOnly') && owner != thePlayer )
  935.         {
  936.             forceOnNpc = true;
  937.         }
  938.        
  939.         if ( owner.HasTag('vampire') && effectType == EET_SilverDust )
  940.         {
  941.             forceOnNpc = true;
  942.         }
  943.        
  944.        
  945.        
  946.         if(owner.IsImmuneToBuff(effectType) && !forceOnNpc && (!actorCreator.HasAbility('ForceCriticalEffects') || IsCriticalEffectType(effectType)) )
  947.         {
  948.             LogEffects("EffectManager.InternalAddEffect: unit <<" + owner + ">> is immune to effect of this type (" + effectType + ")");
  949.             return EI_Deny;
  950.         }      
  951.        
  952.        
  953.         if( actorCreator && GetAttitudeBetween( actorCreator, owner ) == AIA_Friendly && creat != owner && IsNegativeEffectType( effectType ) && effectType != EET_Confusion && effectType != EET_AxiiGuardMe )
  954.         {
  955.             LogAssert(false, "EffectManager.InternalAddEffect: unit <<" + owner + ">> is friendly to buff creator: <<" + creat + ">> negative buff cannot be added");
  956.             return EI_Deny;
  957.         }
  958.        
  959.        
  960.         effect = theGame.effectMgr.MakeNewEffect(effectType, creat, owner, this, inDuration, srcName, powerStatValue, customVal, customAbilityName, customFXName, signEffect, vibratePadLowFreq, vibratePadHighFreq);
  961.        
  962.         if(effect)
  963.         {
  964.             if((actorCreator &&
  965.                 (((W3PlayerWitcher)owner) &&
  966.                 (effectType == EET_Stagger || effectType == EET_LongStagger)) &&
  967.                 (StrBeginsWith(actorCreator.GetName(), "q701_giant") ||
  968.                     StrBeginsWith(actorCreator.GetName(), "scolopendromorph"))) ||
  969.                 (srcName == "debuff_projectile"))
  970.             {
  971.                 if(effectType == EET_Stagger)
  972.                 {
  973.                     theSound.TimedSoundEvent(1.5f, "start_stagger", "stop_stagger");
  974.                 }
  975.                 else if(effectType == EET_LongStagger)
  976.                 {
  977.                     theSound.TimedSoundEvent(2.f, "start_stagger", "stop_stagger");
  978.                 }
  979.             }
  980.             else if(((W3PlayerWitcher)owner) && actorCreator && (effectType == EET_Stagger || effectType == EET_LongStagger))
  981.             {
  982.                 theSound.TimedSoundEvent(1.f, "start_small_stagger", "stop_small_stagger");
  983.             }
  984.            
  985.            
  986.             if( (hasQuen || (((W3PlayerWitcher)owner) && FactsQuerySum("player_had_quen") > 0)) && IsDoTEffect(effect))
  987.             {
  988.                 FactsRemove("player_had_quen");
  989.                
  990.                 if((W3DamageOverTimeEffect)effect)
  991.                     damages = ((W3DamageOverTimeEffect)effect).GetDamages();
  992.                 else if((W3CriticalDOTEffect)effect)
  993.                     damages = ((W3CriticalDOTEffect)effect).GetDamages();
  994.                
  995.                 action = new W3DamageAction in theGame;
  996.                 action.Initialize(creat, owner, effect, srcName, EHRT_None, CPS_Undefined, false, false, false, true);
  997.                 action.SetHitAnimationPlayType(EAHA_ForceNo);
  998.                
  999.                 for(i=0; i<damages.Size(); i+=1)
  1000.                 {
  1001.                    
  1002.                     action.AddDamage(damages[i].dmgType, damages[i].dmgVal);
  1003.                 }
  1004.                
  1005.                 action.SetPointResistIgnored(true);
  1006.                 action.SetIsDoTDamage(0.1f);
  1007.                
  1008.                 theGame.damageMgr.ProcessAction(action);
  1009.                 delete action;
  1010.                
  1011.                 LogEffects("EffectManager.InternalAddEffect: applying DoT when having quen: dealing 0.1s of damage and aborting");
  1012.                 return EI_Deny;
  1013.             }
  1014.            
  1015.            
  1016.             if(effect.GetDurationLeft() == 0)
  1017.             {
  1018.                 LogEffects("EffectManager.InternalAddEffect: unit <<" + owner + ">>: effect <<" + effectType + ">> cannot be added as its final duration is 0.");
  1019.                 LogEffects("EffectManager.InternalAddEffect: this can be due to high unit's resist, which is " + NoTrailZeros(effect.GetBuffResist()*100) + "%.");
  1020.                 return EI_Deny;
  1021.             }
  1022.            
  1023.            
  1024.             if(signEffect && (effectType == EET_Confusion || effectType == EET_Hypnotized) && creat == thePlayer && thePlayer.CanUseSkill(S_Magic_s17) && thePlayer.GetSkillLevel(S_Magic_s17) == 3 && effect.GetDurationLeft() < CalculateAttributeValue(thePlayer.GetSkillAttributeValue(S_Magic_s17, 'duration_to_force_stagger', false, true)) )
  1025.             {              
  1026.                 LogEffects("EffectManager.InternalAddEffect: Axii effect is blocked, will be stagger from S_Magic_s17 skill");
  1027.                 return EI_Deny;
  1028.             }
  1029.            
  1030.            
  1031.             if( theGame.effectMgr.CheckInteractionWith(this, effect, effects, overridenEffectsIdxs, cumulateIdx) )
  1032.                 return ApplyEffect(effect, overridenEffectsIdxs, cumulateIdx, customParams);
  1033.             else
  1034.                 return EI_Deny;
  1035.         }
  1036.        
  1037.         return EI_Undefined;
  1038.     }
  1039.    
  1040.     public final function GetDrunkMutagens( optional sourceName : string ) : array<CBaseGameplayEffect>
  1041.     {
  1042.         var i : int;
  1043.         var ret : array<CBaseGameplayEffect>;
  1044.         var mutagen : W3Mutagen_Effect;
  1045.        
  1046.         for(i=0; i<effects.Size(); i+=1)
  1047.         {
  1048.             mutagen = (W3Mutagen_Effect)effects[i];
  1049.             if(mutagen)
  1050.             {
  1051.                 if( sourceName == "" || mutagen.GetSourceName() == sourceName )
  1052.                 {
  1053.                     ret.PushBack(mutagen);
  1054.                 }
  1055.             }
  1056.         }
  1057.        
  1058.         return ret;
  1059.     }
  1060.    
  1061.     public final function GetMutagenBuffs() : array< W3Mutagen_Effect >
  1062.     {
  1063.         var i : int;
  1064.         var ret : array< W3Mutagen_Effect >;
  1065.         var mutagen : W3Mutagen_Effect;
  1066.        
  1067.         for(i=0; i<effects.Size(); i+=1)
  1068.         {
  1069.             mutagen = (W3Mutagen_Effect) effects[i];
  1070.             if( mutagen )
  1071.             {
  1072.                 ret.PushBack( mutagen );
  1073.             }
  1074.         }
  1075.        
  1076.         return ret;
  1077.     }
  1078.    
  1079.     public final function GetPotionBuffs() : array<CBaseGameplayEffect>
  1080.     {
  1081.         var i : int;
  1082.         var ret : array<CBaseGameplayEffect>;
  1083.        
  1084.         for(i=0; i<effects.Size(); i+=1)
  1085.         {
  1086.             if(effects[i].IsPotionEffect())
  1087.                 ret.PushBack(effects[i]);
  1088.         }
  1089.        
  1090.         return ret;
  1091.     }
  1092.    
  1093.     public final function GetPotionBuffsCount() : int
  1094.     {
  1095.         var i, cnt : int;
  1096.        
  1097.         cnt = 0;
  1098.         for(i=0; i<effects.Size(); i+=1)
  1099.         {
  1100.             if(effects[i].IsPotionEffect())
  1101.                 cnt += 1;
  1102.         }
  1103.        
  1104.         return cnt;
  1105.     }  
  1106.    
  1107.    
  1108.     public final function GetEffect(effectType : EEffectType, optional sourceName : string) : CBaseGameplayEffect
  1109.     {
  1110.         var i,size : int;
  1111.    
  1112.         size = effects.Size();
  1113.         for(i=0; i<size; i+=1)
  1114.         {
  1115.             if(effects[i].GetEffectType() == effectType)
  1116.             {
  1117.                 if(StrLen(sourceName) == 0 || sourceName == effects[i].GetSourceName())
  1118.                     return effects[i];
  1119.             }
  1120.         }
  1121.        
  1122.         return NULL;
  1123.     }
  1124.    
  1125.    
  1126.     public final function RemoveEffect(effect : CBaseGameplayEffect, optional csForcedRemove : bool)
  1127.     {
  1128.         var witcher : W3PlayerWitcher;
  1129.         var i : int;
  1130.         var autoBuffPause : SPausedAutoEffect;
  1131.         var isCritical : bool;
  1132.        
  1133.         if(!effect || !effects.Contains(effect))
  1134.             return;
  1135.            
  1136.         isCritical = IsCriticalEffect(effect);
  1137.        
  1138.         if(owner == thePlayer && isCritical)
  1139.             LogCriticalPlayer("EffectManager.RemoveEffect() | " + effect + " - forced: " + csForcedRemove);
  1140.            
  1141.         if(!csForcedRemove && isCritical && currentlyAnimatedCS == effect)
  1142.         {              
  1143.             if(effect.IsActive())
  1144.             {
  1145.                
  1146.                 effect.SetTimeLeft(0);
  1147.                 return;
  1148.             }
  1149.         }
  1150.        
  1151.        
  1152.         if(isCritical && effect == owner.GetNewRequestedCS())
  1153.             owner.SetNewRequestedCS(NULL);
  1154.        
  1155.         effects.Remove(effect);
  1156.        
  1157.         if( effects.Size() == 0 )
  1158.         {
  1159.             owner.SetEffectsUpdateTicking( false );
  1160.         }
  1161.        
  1162.         effect.OnEffectRemoved();
  1163.         OnBuffRemoved();
  1164.        
  1165.         if(ownerIsWitcher)     
  1166.         {
  1167.             witcher = GetWitcherPlayer();
  1168.             if(witcher.GetSkillBonusPotionEffect() == effect)
  1169.                 witcher.ClearSkillBonusPotionEffect();
  1170.         }      
  1171.  
  1172.         if(isCritical && currentlyAnimatedCS == effect)
  1173.         {
  1174.             owner.RaiseEvent( 'CriticalStateEnded' );
  1175.  
  1176.             SetCurrentlyAnimatedCS(NULL);
  1177.         }  
  1178.        
  1179.        
  1180.         for(i=pausedEffects.Size()-1; i>=0; i-=1)
  1181.         {
  1182.             if(pausedEffects[i].buff != effect)
  1183.                 continue;
  1184.                
  1185.             if(IsBuffAutoBuff(pausedEffects[i].buff.GetEffectType()))
  1186.             {
  1187.                
  1188.                 autoBuffPause.effectType = effect.GetEffectType();
  1189.                 autoBuffPause.duration = pausedEffects[i].duration;
  1190.                 autoBuffPause.timeLeft = pausedEffects[i].timeLeft;
  1191.                 autoBuffPause.sourceName = pausedEffects[i].source;
  1192.                 autoBuffPause.singleLock = pausedEffects[i].singleLock;
  1193.                 autoBuffPause.useMaxDuration = pausedEffects[i].useMaxDuration;
  1194.                
  1195.                 pausedNotAppliedAutoBuffs.PushBack(autoBuffPause);
  1196.             }
  1197.            
  1198.            
  1199.             pausedEffects.EraseFast(i);
  1200.             break;
  1201.         }
  1202.        
  1203.         delete effect;
  1204.     }
  1205.    
  1206.     private final function RemoveEffectOnIndex( index : int , optional csForcedRemove : bool)
  1207.     {
  1208.         RemoveEffect(effects[index], csForcedRemove);
  1209.     }
  1210.        
  1211.    
  1212.     public final function RemoveAllPotionEffects(optional skip : array<CBaseGameplayEffect>)
  1213.     {
  1214.         var size,i : int;
  1215.    
  1216.         size = effects.Size();
  1217.         for(i=size-1; i>=0; i-=1)
  1218.         {
  1219.             if(effects[i].IsPotionEffect() && (skip.Size() == 0 || !skip.Contains(effects[i])) )
  1220.             {
  1221.                 RemoveEffectOnIndex( i );
  1222.             }
  1223.         }
  1224.     }
  1225.    
  1226.    
  1227.     public final function RemoveAllEffectsOfType(type : EEffectType, optional forced : bool)
  1228.     {
  1229.         var i : int;
  1230.        
  1231.         for(i=effects.Size()-1; i>=0; i-=1)
  1232.         {
  1233.             if( effects[i].GetEffectType() == type )
  1234.             {
  1235.                 RemoveEffectOnIndex( i, forced );
  1236.             }
  1237.         }
  1238.     }
  1239.    
  1240.     public function RemoveAllBuffsWithSource( source : string )
  1241.     {
  1242.         var i : int;
  1243.        
  1244.         for(i=effects.Size()-1; i>=0; i-=1)
  1245.         {
  1246.             if( effects[i].GetSourceName() == source )
  1247.             {
  1248.                 RemoveEffectOnIndex( i, false );
  1249.             }
  1250.         }
  1251.     }
  1252.    
  1253.    
  1254.     public final function RemoveAllNonAutoEffects( optional removeOils : bool, optional skipPerk14 : bool )
  1255.     {
  1256.         var autoEffects : array<name>;
  1257.         var i : int;
  1258.         var type : EEffectType;
  1259.         var tmpName : name;
  1260.         var autos : array<EEffectType>;
  1261.                
  1262.        
  1263.         owner.GetAutoEffects(autoEffects);
  1264.         for(i=0; i<autoEffects.Size(); i+=1)       
  1265.         {
  1266.             EffectNameToType(autoEffects[i], type, tmpName);
  1267.             autos.PushBack(type);
  1268.         }
  1269.        
  1270.        
  1271.         if(!autos.Contains(EET_AutoVitalityRegen))
  1272.             autos.PushBack(EET_AutoVitalityRegen);
  1273.         if(!autos.Contains(EET_AutoStaminaRegen))
  1274.             autos.PushBack(EET_AutoStaminaRegen);
  1275.         if(!autos.Contains(EET_AutoEssenceRegen))
  1276.             autos.PushBack(EET_AutoEssenceRegen);
  1277.         if(!autos.Contains(EET_AutoMoraleRegen))
  1278.             autos.PushBack(EET_AutoMoraleRegen);
  1279.        
  1280.        
  1281.         for(i=effects.Size()-1; i>=0; i-=1)
  1282.         {
  1283.             type = effects[i].GetEffectType();
  1284.             if(!autos.Contains(type))
  1285.             {
  1286.                 if( removeOils || ! ( (W3Effect_Oil)effects[i] ) )
  1287.                 {
  1288.                    
  1289.                     if( skipPerk14 && (W3PlayerWitcher)owner && GetWitcherPlayer().CanUseSkill( S_Perk_14 ) && (W3Effect_Shrine) effects[i] )
  1290.                     {
  1291.                         continue;
  1292.                     }
  1293.                    
  1294.                     RemoveEffectOnIndex( i, true );
  1295.                 }
  1296.             }
  1297.         }
  1298.     }
  1299.    
  1300.    
  1301.     public final function OwnerHasDied()
  1302.     {
  1303.         var i : int;
  1304.        
  1305.         for(i=effects.Size()-1; i>=0; i-=1)
  1306.             effects[i].OnTargetDeath();
  1307.     }
  1308.    
  1309.     public final function OwnerHasEnteredUnconscious()
  1310.     {
  1311.         var i : int;
  1312.        
  1313.         for(i=effects.Size()-1; i>=0; i-=1)
  1314.             effects[i].OnTargetUnconscious();
  1315.     }
  1316.    
  1317.     public final function OnOwnerRevived()
  1318.     {
  1319.         var i : int;
  1320.    
  1321.         RemoveAllNonAutoEffects();     
  1322.         cachedDamages.Clear();
  1323.         SetCurrentlyAnimatedCS(NULL);
  1324.        
  1325.         for(i=0; i<statDeltas.Size(); i+=1)
  1326.             statDeltas[i] = 0;
  1327.        
  1328.         ResumeAllBuffsForced();
  1329.        
  1330.        
  1331.         vitalityAutoRegenOn = false;
  1332.         essenceAutoRegenOn          = false;
  1333.         staminaAutoRegenOn          = false;
  1334.         moraleAutoRegenOn           = false;
  1335.         panicAutoRegenOn            = false;
  1336.         airAutoRegenOn              = false;
  1337.         swimmingStaminaAutoRegenOn  = false;
  1338.         adrenalineAutoRegenOn       = false;
  1339.    
  1340.         StartStaminaRegen();
  1341.         StartVitalityRegen();
  1342.         StartEssenceRegen();
  1343.         StartMoraleRegen();
  1344.         StartPanicRegen();
  1345.         StartAirRegen();
  1346.         StartSwimmingStaminaRegen();
  1347.     }
  1348.    
  1349.    
  1350.     public final function OwnerHasFinishedDeathAnim()
  1351.     {
  1352.         var i : int;
  1353.        
  1354.         for(i=effects.Size()-1; i>=0; i-=1)
  1355.             effects[i].OnTargetDeathAnimFinished();
  1356.     }
  1357.        
  1358.     private final function UpdateStatValueChange(stat : EBaseCharacterStats, val : float)
  1359.     {
  1360.         var playerOwner : CR4Player;
  1361.    
  1362.         if(val > 0)
  1363.         {
  1364.             owner.GainStat(stat, val);
  1365.             return;
  1366.         }
  1367.         else if (val == 0)
  1368.         {
  1369.             return;
  1370.         }
  1371.        
  1372.         val = -val;
  1373.         playerOwner = (CR4Player)owner;
  1374.        
  1375.         switch(stat)
  1376.         {
  1377.             case BCS_Stamina :
  1378.                 owner.DrainStamina(ESAT_FixedValue, val, 1);
  1379.                 break;
  1380.             case BCS_Toxicity :        
  1381.                 if(playerOwner)
  1382.                     playerOwner.DrainToxicity(val);
  1383.                 else
  1384.                     LogAssert(false, "W3EffectManager.UpdateStatValueChange: trying to drain Toxicity points on non-player!");
  1385.                 break;         
  1386.             case BCS_Focus :
  1387.                 if(playerOwner)
  1388.                     playerOwner.DrainFocus(val);
  1389.                 else
  1390.                     LogAssert(false, "W3EffectManager.UpdateStatValueChange: trying to drain Focus points on non-player!");
  1391.                 break;
  1392.             case BCS_Morale :
  1393.                 owner.DrainMorale(val);
  1394.                 break;
  1395.             case BCS_Panic :
  1396.                 owner.AddPanic(val);
  1397.                 break;
  1398.             case BCS_Air :
  1399.                 owner.DrainAir(val);
  1400.                 break;
  1401.             case BCS_SwimmingStamina :
  1402.                 owner.DrainSwimmingStamina(val);
  1403.                 break;
  1404.             default:
  1405.                 LogAssert(false, "W3EffectManager.UpdateStatValueChange: trying to drain invalid stat <<" + stat + ">>!");
  1406.                 break;
  1407.         }
  1408.     }
  1409.  
  1410.     public final function HasEffect(effectType : EEffectType) : bool
  1411.     {
  1412.         var i,size : int;
  1413.        
  1414.         if(effectType != EET_Undefined)
  1415.         {
  1416.             size = effects.Size();
  1417.             for( i = 0; i < size; i += 1 )
  1418.             {
  1419.                 if(effects[i] && effects[i].GetEffectType() == effectType)
  1420.                     return true;
  1421.             }
  1422.         }
  1423.        
  1424.         return false;
  1425.     }
  1426.  
  1427.     public final function GetEffectTimePercentageByType(effectType : EEffectType) : int
  1428.     {
  1429.         var i, size : int; 
  1430.        
  1431.         if ( effectType != EET_Undefined )
  1432.         {
  1433.             size = effects.Size();
  1434.             for( i = 0; i < size; i += 1 )
  1435.                 if( effects[i].GetEffectType() == effectType )
  1436.                     return GetEffectTimePercentage(effects[i]);                
  1437.         }      
  1438.         return 0;
  1439.     }
  1440.    
  1441.     public final function GetEffectTimePercentage(buff : CBaseGameplayEffect) : int
  1442.     {
  1443.         var maxDur : float;
  1444.        
  1445.         if (buff)
  1446.         {
  1447.             maxDur = buff.GetInitialDurationAfterResists();
  1448.             if(maxDur > 0)
  1449.             {
  1450.                 return RoundMath( 100.0f * buff.GetDurationLeft() / maxDur );
  1451.             }
  1452.             else if( maxDur <= -1 )
  1453.             {
  1454.                 return 100;
  1455.             }
  1456.         }
  1457.         return 0;
  1458.     }
  1459.  
  1460.    
  1461.     public final function AddEffectsFromAction( action : W3DamageAction ) : bool
  1462.     {
  1463.         var i, size : int;
  1464.         var effectInfos : array< SEffectInfo >;
  1465.         var ret : EEffectInteract;
  1466.         var signProjectile : W3SignProjectile;
  1467.         var attackerPowerStatValue : SAbilityAttributeValue;
  1468.         var retB, applyBuff : bool;
  1469.         var signEntity : W3SignEntity;
  1470.         var canLog : bool;
  1471.        
  1472.         canLog = theGame.CanLog();
  1473.         size = action.GetEffects( effectInfos );
  1474.         signProjectile = (W3SignProjectile)action.causer;
  1475.         attackerPowerStatValue = action.GetPowerStatValue();
  1476.         retB = true;
  1477.        
  1478.        
  1479.         signEntity = (W3SignEntity)action.causer;
  1480.         if(!signEntity && signProjectile)
  1481.             signEntity = signProjectile.GetSignEntity();
  1482.            
  1483.         for( i = 0; i < size; i += 1 )
  1484.         {      
  1485.             if ( canLog )
  1486.             {
  1487.                 LogDMHits("Trying to add buff <<" + effectInfos[i].effectType + ">> on target...", action);
  1488.             }
  1489.            
  1490.            
  1491.             if(signEntity)
  1492.             {
  1493.                 applyBuff = GetSignApplyBuffTest(signEntity.GetSignType(), effectInfos[i].effectType, attackerPowerStatValue, signEntity.IsAlternateCast(), (CActor)action.attacker, action.GetBuffSourceName() );
  1494.             }
  1495.             else
  1496.             {
  1497.                 applyBuff = GetNonSignApplyBuffTest(effectInfos[i].applyChance);
  1498.             }
  1499.            
  1500.             if(applyBuff)
  1501.             {
  1502.                
  1503.                 ret = InternalAddEffect(effectInfos[i].effectType, action.attacker, action.GetBuffSourceName(), effectInfos[i].effectDuration, effectInfos[i].effectCustomValue, effectInfos[i].effectAbilityName, effectInfos[i].customFXName, signEntity, attackerPowerStatValue, effectInfos[i].effectCustomParam );
  1504.             }
  1505.             else
  1506.             {
  1507.                
  1508.                 if( signEntity && signEntity.GetSignType() == ST_Aard )
  1509.                 {
  1510.                    
  1511.                     ret = InternalAddEffect(EET_Stagger, action.attacker, action.GetBuffSourceName(), effectInfos[i].effectDuration, effectInfos[i].effectCustomValue, effectInfos[i].customFXName, effectInfos[i].effectAbilityName, signEntity, attackerPowerStatValue, effectInfos[i].effectCustomParam );
  1512.                 }
  1513.             }
  1514.            
  1515.             if ( theGame.CanLog() )
  1516.             {
  1517.                 if(ret == EI_Undefined)
  1518.                 {
  1519.                     retB = false;
  1520.                     LogDMHits("... not valid effect!", action);
  1521.                 }
  1522.                 else if(!applyBuff)
  1523.                     LogDMHits("... failed randomization test.", action);
  1524.                 else if(ret == EI_Deny)
  1525.                     LogDMHits("... denied.", action);
  1526.                 else if(ret == EI_Override)
  1527.                     LogDMHits("... overriden by other effect already on target.", action);
  1528.                 else if(ret == EI_Pass)
  1529.                     LogDMHits("... added.", action);
  1530.                 else if(ret == EI_Cumulate)
  1531.                     LogDMHits("... cumulated with existing effect on target.", action);        
  1532.             }
  1533.             else
  1534.             {
  1535.                 if ( ret == EI_Undefined )
  1536.                 {
  1537.                     retB = false;
  1538.                 }
  1539.             }
  1540.            
  1541.         }
  1542.        
  1543.         return retB;
  1544.     }
  1545.    
  1546.    
  1547.     private final function GetNonSignApplyBuffTest(applyChance : float) : bool
  1548.     {
  1549.         return RandF() < applyChance;
  1550.     }
  1551.    
  1552.    
  1553.     private final function GetSignApplyBuffTest(signType : ESignType, effectType : EEffectType, powerStatValue : SAbilityAttributeValue, isAlternate : bool, caster : CActor, sourceName : string ) : bool
  1554.     {
  1555.         var sp, res, chance, tempF : float;
  1556.         var chanceBonus : SAbilityAttributeValue;
  1557.         var witcher : W3PlayerWitcher;
  1558.  
  1559.        
  1560.         witcher = (W3PlayerWitcher)caster;
  1561.         if(witcher && witcher.GetPotionBuffLevel(EET_PetriPhiltre) == 3)
  1562.             return true;
  1563.    
  1564.        
  1565.         sp = powerStatValue.valueMultiplicative;
  1566.         owner.GetResistValue(theGame.effectMgr.GetBuffResistStat(effectType), tempF, res);
  1567.         chance = sp / theGame.params.MAX_SPELLPOWER_ASSUMED - res;
  1568.        
  1569.         if( signType == ST_Yrden || signType == ST_Axii || sourceName == "mutation11" )
  1570.         {
  1571.             chance = 1;
  1572.         }
  1573.         else if(signType == ST_Igni)
  1574.         {
  1575.             chance = ( 1 + LogF( sp ) ) / theGame.params.MAX_SPELLPOWER_ASSUMED - res;
  1576.        
  1577.             if(witcher)
  1578.             {
  1579.                 if(witcher.CanUseSkill(S_Magic_s09))
  1580.                 {
  1581.                     chanceBonus = witcher.GetSkillAttributeValue(S_Magic_s09, 'chance_bonus', false, true);
  1582.                     chance += chance * chanceBonus.valueMultiplicative * witcher.GetSkillLevel(S_Magic_s09) + chanceBonus.valueAdditive * witcher.GetSkillLevel(S_Magic_s09);
  1583.                 }          
  1584.                 if(witcher.CanUseSkill(S_Perk_03))
  1585.                     chance += CalculateAttributeValue(witcher.GetSkillAttributeValue(S_Perk_03, 'burning_chance', false, true));
  1586.             }
  1587.         }
  1588.         else if(signType == ST_Quen && effectType == EET_KnockdownTypeApplicator)
  1589.         {
  1590.             witcher = (W3PlayerWitcher)caster;
  1591.             if(witcher)
  1592.             {
  1593.                 chanceBonus = witcher.GetSkillAttributeValue(S_Magic_s13, 'chance_multiplier', false, true);
  1594.                 chance *= CalculateAttributeValue(chanceBonus);
  1595.             }
  1596.             if( owner.HasAbility('WeakToAard') )
  1597.             {
  1598.                 chance = 1;
  1599.             }
  1600.         }
  1601.         else if( signType == ST_Aard && owner.HasAbility('WeakToAard') )
  1602.         {
  1603.             chance = 1;
  1604.         }
  1605.                
  1606.         chance = ClampF(chance, 0, 1);
  1607.            
  1608.         LogEffects("Buff <<" + effectType + ">> is from sign, chance = " + NoTrailZeros(100*chance) + "%, spell_power = " + NoTrailZeros(sp) + ", resist=" + NoTrailZeros(res));       
  1609.         if(RandF() >= chance)
  1610.         {
  1611.             if ( theGame.CanLog() )
  1612.             {
  1613.                 LogEffects("Sign buff chance failed - no effect applied");
  1614.             }
  1615.             return false;
  1616.         }
  1617.         else
  1618.         {
  1619.             LogEffects("Sign buff chance succeeded!");
  1620.         }
  1621.        
  1622.         return true;
  1623.     }
  1624.    
  1625.    
  1626.     public final function ProcessOnHitEffects(victim : CActor, silverSword : bool, steelSword : bool, sign : bool)
  1627.     {
  1628.         var i : int;
  1629.         var applicator : W3Effect_ApplicatorOnHit;
  1630.    
  1631.         for(i=0; i<effects.Size(); i+=1)
  1632.         {
  1633.             applicator = (W3Effect_ApplicatorOnHit)effects[i];
  1634.             if(applicator)
  1635.             {
  1636.                 applicator.ProcessOnHit(victim, silverSword, steelSword, sign);
  1637.             }
  1638.         }
  1639.     }
  1640.    
  1641.    
  1642.    
  1643.    
  1644.     public final function PauseEffects(effectType : EEffectType, sourceName : name, optional singleLock : bool, optional duration : float, optional useMaxDuration : bool)
  1645.     {
  1646.         var i : int;
  1647.         var pausedAnyBuff : bool;
  1648.         var pause : SPausedAutoEffect;
  1649.    
  1650.        
  1651.         if(duration == 0)
  1652.             duration = -1;
  1653.            
  1654.        
  1655.         for(i=0; i<effects.Size(); i+=1)
  1656.         {
  1657.             if(effects[i].GetEffectType() == effectType)
  1658.             {  
  1659.                 PauseEffect(effects[i], sourceName, singleLock, duration,useMaxDuration);
  1660.                 pausedAnyBuff = true;
  1661.             }
  1662.         }
  1663.        
  1664.        
  1665.         if(!pausedAnyBuff && IsBuffAutoBuff(effectType))
  1666.         {
  1667.             pause.effectType = effectType;
  1668.             pause.sourceName = sourceName;
  1669.             pause.singleLock = singleLock;
  1670.             pause.duration = duration;
  1671.             pause.useMaxDuration = useMaxDuration;
  1672.             pause.timeLeft = duration;
  1673.            
  1674.             pausedNotAppliedAutoBuffs.PushBack(pause);
  1675.         }
  1676.     }
  1677.    
  1678.    
  1679.    
  1680.     private final function PauseEffect(buff : CBaseGameplayEffect, sourceName : name, optional singleLock : bool, optional duration : float, optional useMaxDuration : bool)
  1681.     {
  1682.         var tpe : STemporarilyPausedEffect;
  1683.         var j : int;
  1684.         var processed : bool;
  1685.        
  1686.         processed = false;
  1687.        
  1688.        
  1689.         for(j=0; j<pausedEffects.Size(); j+=1)
  1690.         {
  1691.             if(pausedEffects[j].buff == buff && pausedEffects[j].source == sourceName)
  1692.             {
  1693.                
  1694.                 if(duration > 0)
  1695.                 {
  1696.                    
  1697.                     if(useMaxDuration)
  1698.                         pausedEffects[j].timeLeft = MaxF(pausedEffects[j].timeLeft, duration);
  1699.                     else
  1700.                         pausedEffects[j].timeLeft = duration;
  1701.                 }
  1702.                 else if(pausedEffects[j].timeLeft >= 0)
  1703.                 {
  1704.                    
  1705.                     pausedEffects[j].timeLeft = -1;
  1706.                 }
  1707.                
  1708.                 processed = true;
  1709.                 buff = pausedEffects[j].buff;
  1710.                 break;
  1711.             }
  1712.         }
  1713.        
  1714.        
  1715.         if(!processed)
  1716.         {
  1717.             tpe.buff = buff;   
  1718.             tpe.timeLeft = duration;
  1719.             tpe.duration = duration;
  1720.             tpe.source = sourceName;
  1721.             tpe.singleLock = singleLock;
  1722.             tpe.useMaxDuration = useMaxDuration;
  1723.        
  1724.             pausedEffects.PushBack(tpe);           
  1725.         }
  1726.        
  1727.         buff.Pause(sourceName, singleLock);
  1728.     }
  1729.  
  1730.     public final function PauseAllRegenEffects(sourceName : name, optional singleLock : bool, optional duration : float, optional useMaxDuration : bool)
  1731.     {
  1732.         var i : int;
  1733.         var regenEffect : W3RegenEffect;
  1734.    
  1735.         for(i=0; i<effects.Size(); i+=1)
  1736.         {
  1737.             regenEffect = (W3RegenEffect)effects[i];
  1738.             if(regenEffect)
  1739.                 PauseEffects(regenEffect.GetEffectType(), sourceName, singleLock, duration, useMaxDuration);
  1740.         }
  1741.     }
  1742.    
  1743.     public final function ResumeAllRegenEffects(sourceName : name)
  1744.     {
  1745.         var i : int;
  1746.         var regenEffect : W3RegenEffect;
  1747.    
  1748.         for(i=0; i<effects.Size(); i+=1)
  1749.         {
  1750.             regenEffect = (W3RegenEffect)effects[i];
  1751.             if(regenEffect)
  1752.                 ResumeEffects(regenEffect.GetEffectType(), sourceName);
  1753.         }
  1754.     }
  1755.    
  1756.    
  1757.     private final function ResumeAllBuffsForced()
  1758.     {
  1759.         var i : int;
  1760.    
  1761.         for(i=0; i<effects.Size(); i+=1)
  1762.         {
  1763.             ResumeEffectsInternal(effects[i].GetEffectType(), '', true);
  1764.         }
  1765.     }
  1766.    
  1767.     public final function PauseHPRegenEffects(sourceName : name, optional duration : float)
  1768.     {      
  1769.         var i : int;
  1770.         var regenEffect : W3RegenEffect;
  1771.        
  1772.         for(i=0; i<effects.Size(); i+=1)
  1773.         {
  1774.             regenEffect = (W3RegenEffect)effects[i];
  1775.             if(regenEffect)
  1776.             {
  1777.                 if(regenEffect.GetRegenStat() == CRS_Vitality || regenEffect.GetRegenStat() == CRS_Essence)
  1778.                 {
  1779.                     PauseEffects(effects[i].GetEffectType(), sourceName, true, duration);
  1780.                 }
  1781.             }
  1782.         }
  1783.     }
  1784.    
  1785.     public final function PauseStaminaRegen(sourceName : name, optional duration : float)
  1786.     {
  1787.         var i : int;
  1788.         var regenEffect : W3RegenEffect;
  1789.        
  1790.         for(i=0; i<effects.Size(); i+=1)
  1791.         {
  1792.             regenEffect = (W3RegenEffect)effects[i];
  1793.             if(regenEffect)
  1794.             {
  1795.                 if(regenEffect.GetRegenStat() == CRS_Stamina)
  1796.                 {
  1797.                     PauseEffects(effects[i].GetEffectType(), sourceName, true, duration, true);
  1798.                 }
  1799.             }
  1800.         }
  1801.     }
  1802.    
  1803.     public final function ResumeStaminaRegen(sourceName : name)
  1804.     {
  1805.         var i : int;
  1806.         var regenEffect : W3RegenEffect;
  1807.        
  1808.         for(i=0; i<effects.Size(); i+=1)
  1809.         {
  1810.             regenEffect = (W3RegenEffect)effects[i];
  1811.             if(regenEffect)
  1812.             {
  1813.                 if(regenEffect.GetRegenStat() == CRS_Stamina)
  1814.                 {
  1815.                     ResumeEffects(effects[i].GetEffectType(), sourceName);
  1816.                 }
  1817.             }
  1818.         }
  1819.     }
  1820.    
  1821.     public final function ResumeHPRegenEffects( sourceName : name, optional forceAll : bool )
  1822.     {      
  1823.         var i : int;
  1824.         var regenEffect : W3RegenEffect;
  1825.        
  1826.         for(i=0; i<effects.Size(); i+=1)
  1827.         {
  1828.             regenEffect = (W3RegenEffect)effects[i];
  1829.             if(regenEffect)
  1830.             {
  1831.                 if(regenEffect.GetRegenStat() == CRS_Vitality || regenEffect.GetRegenStat() == CRS_Essence)
  1832.                 {
  1833.                     ResumeEffects( effects[i].GetEffectType(), sourceName, forceAll );
  1834.                 }
  1835.             }
  1836.         }
  1837.     }
  1838.    
  1839.    
  1840.     public final function ResumeEffects( effectType : EEffectType, sourceName : name, optional forced : bool )
  1841.     {
  1842.         ResumeEffectsInternal( effectType, sourceName, forced );
  1843.     }
  1844.    
  1845.    
  1846.     private final function ResumeEffectsInternal(effectType : EEffectType, optional sourceName : name, optional forced : bool)
  1847.     {
  1848.         var i, j : int;
  1849.         var removedOneLock : bool;
  1850.        
  1851.         for(i=0; i<effects.Size(); i+=1)
  1852.         {
  1853.             if(effects[i].GetEffectType() == effectType && (forced || effects[i].IsPaused(sourceName)) )
  1854.             {
  1855.                 if(forced)
  1856.                     effects[i].ResumeForced();
  1857.                 else
  1858.                     effects[i].Resume(sourceName);
  1859.                
  1860.                
  1861.                 for(j=0; j<pausedEffects.Size(); j+=1)
  1862.                 {
  1863.                     if(pausedEffects[j].buff == effects[i] && (forced || sourceName == pausedEffects[j].source) )
  1864.                     {
  1865.                         pausedEffects.EraseFast(j);
  1866.                     }                      
  1867.                 }                  
  1868.             }
  1869.         }
  1870.                
  1871.        
  1872.         removedOneLock = false;
  1873.         for(i=pausedNotAppliedAutoBuffs.Size()-1; i>=0; i-=1)
  1874.         {
  1875.             if(pausedNotAppliedAutoBuffs[i].effectType == effectType && (forced || pausedNotAppliedAutoBuffs[i].sourceName == sourceName) )
  1876.             {
  1877.                
  1878.                 if(pausedNotAppliedAutoBuffs[i].singleLock)
  1879.                 {
  1880.                     pausedNotAppliedAutoBuffs.Erase(i);
  1881.                     continue;
  1882.                 }
  1883.                
  1884.                 else if(!removedOneLock)
  1885.                 {
  1886.                     pausedNotAppliedAutoBuffs.Erase(i);
  1887.                     removedOneLock = true;
  1888.                     continue;
  1889.                 }
  1890.             }
  1891.         }
  1892.     }
  1893.        
  1894.    
  1895.     public final function GetCriticalBuffsCount() : int
  1896.     {
  1897.         var i, cnt : int;
  1898.    
  1899.         cnt = 0;
  1900.         for(i=0; i<effects.Size(); i+=1)
  1901.             if(IsCriticalEffect(effects[i]))
  1902.                 cnt += 1;
  1903.        
  1904.         return cnt;
  1905.     }
  1906.    
  1907.     public final function GetCriticalBuffs() : array<CBaseGameplayEffect>
  1908.     {
  1909.         var i : int;
  1910.         var ret : array<CBaseGameplayEffect>;
  1911.    
  1912.         for(i=0; i<effects.Size(); i+=1)
  1913.             if(IsCriticalEffect(effects[i]))
  1914.                 ret.PushBack(effects[i]);
  1915.        
  1916.         return ret;
  1917.     }
  1918.    
  1919.     public final function HasPotionBuff() : bool
  1920.     {
  1921.         var i : int;
  1922.    
  1923.         for(i=0; i<effects.Size(); i+=1)
  1924.             if(effects[i].IsPotionEffect() && effects[i].IsActive())
  1925.                 return true;
  1926.                
  1927.         return false;
  1928.     }
  1929.    
  1930.    
  1931.     public final function CacheStatUpdate(stat : EBaseCharacterStats, value : float)
  1932.     {
  1933.         if(value == 0)
  1934.         {
  1935.             LogAssert(false, "EffectManager.CacheStatUpdate: value is 0 for <<" + owner + ">> and stat <<" + stat + ">> !!!");
  1936.             return;
  1937.         }
  1938.        
  1939.         statDeltas[stat] += value;
  1940.         owner.SetEffectsUpdateTicking( true );
  1941.     }
  1942.    
  1943.    
  1944.     public final function CacheDamage(damageTypeName : name, val : float, attacker : CGameplayEntity, carrier : CBaseGameplayEffect, DoTdt : float, dontShowHitParticle : bool, pwrStatType : ECharacterPowerStats, isEnvironment : bool)
  1945.     {
  1946.         var dmg : SEffectCachedDamage;
  1947.         var eh : EntityHandle;
  1948.    
  1949.         if(val <= 0)
  1950.         {
  1951.             LogAssert(false, "EffectManager.CacheDamage: value is <= 0!");
  1952.             return;
  1953.         }
  1954.        
  1955.         EntityHandleSet(eh, attacker);
  1956.        
  1957.         dmg.dmgType = damageTypeName;
  1958.         dmg.dmgVal = val;
  1959.         dmg.attacker = eh;
  1960.         dmg.carrier = carrier;
  1961.         dmg.dt = DoTdt;
  1962.         dmg.dontShowHitParticle = dontShowHitParticle;
  1963.         dmg.powerStatType = pwrStatType;
  1964.         dmg.isEnvironment = isEnvironment;
  1965.        
  1966.         if(carrier)
  1967.             dmg.sourceName = carrier.GetSourceName();
  1968.            
  1969.         cachedDamages.PushBack(dmg);
  1970.         owner.SetEffectsUpdateTicking( true );
  1971.     }
  1972.    
  1973.    
  1974.     public final function RecalcEffectDurations()
  1975.     {
  1976.         var i : int;
  1977.        
  1978.         for(i=0; i<effects.Size(); i+=1)
  1979.             effects[i].RecalcDuration();
  1980.     }
  1981.    
  1982.    
  1983.     public final function GetPotionBuffLevel(effectType : EEffectType) : int
  1984.     {
  1985.         var buff : CBaseGameplayEffect;
  1986.        
  1987.         buff = GetEffect(effectType);
  1988.        
  1989.         if(buff && buff.IsPotionEffect())
  1990.             return buff.GetBuffLevel();
  1991.            
  1992.         return 0;
  1993.     }
  1994.    
  1995.     public final function CanBeRemoved() : bool
  1996.     {
  1997.         var i : int;
  1998.        
  1999.         if( effects.Size() > 0 )
  2000.         {
  2001.             return false;
  2002.         }
  2003.    
  2004.         if( cachedDamages.Size() > 0 )
  2005.         {
  2006.             return false;
  2007.         }
  2008.    
  2009.         for( i = 0; i < statDeltas.Size(); i += 1 )
  2010.         {
  2011.             if( statDeltas[ i ] != 0 )
  2012.             {
  2013.                 return false;
  2014.             }
  2015.         }
  2016.        
  2017.        
  2018.         for(i=0; i<pausedEffects.Size(); i+=1)
  2019.         {
  2020.             if(pausedEffects[i].duration != -1)
  2021.                 return false;
  2022.         }
  2023.        
  2024.        
  2025.         for(i=0; i<pausedNotAppliedAutoBuffs.Size(); i+=1)
  2026.         {
  2027.             if(pausedNotAppliedAutoBuffs[i].duration != -1)
  2028.                 return false;
  2029.         }
  2030.        
  2031.         return true;
  2032.     }
  2033.    
  2034.     public final function ShouldStopFx(fx : name) : bool
  2035.     {
  2036.         var i : int;
  2037.        
  2038.         for(i=0; i<currentlyPlayedFX.Size(); i+=1)
  2039.         {
  2040.             if(currentlyPlayedFX[i].fx == fx)
  2041.                 return currentlyPlayedFX[i].sources.Size() == 1;   
  2042.         }
  2043.        
  2044.        
  2045.         return false;
  2046.     }
  2047.    
  2048.     public final function IsPlayingFX(fx : name) : bool
  2049.     {
  2050.         var i : int;
  2051.        
  2052.         for(i=0; i<currentlyPlayedFX.Size(); i+=1)
  2053.         {
  2054.             if(currentlyPlayedFX[i].fx == fx)
  2055.                 return true;
  2056.         }
  2057.        
  2058.         return false;
  2059.     }
  2060.    
  2061.     public final function AddPlayedFX(fx : name, sourceName : string)
  2062.     {
  2063.         var i : int;
  2064.         var f : SCurrentBuffFX;
  2065.        
  2066.         for(i=0; i<currentlyPlayedFX.Size(); i+=1)
  2067.         {
  2068.             if(currentlyPlayedFX[i].fx == fx)
  2069.             {
  2070.                 if(!currentlyPlayedFX[i].sources.Contains(sourceName))
  2071.                     currentlyPlayedFX[i].sources.PushBack(sourceName);
  2072.                    
  2073.                 return;
  2074.             }
  2075.         }
  2076.  
  2077.        
  2078.         f.fx = fx;
  2079.         f.sources.PushBack(sourceName);
  2080.        
  2081.         currentlyPlayedFX.PushBack(f);
  2082.     }
  2083.    
  2084.     public final function RemovePlayedFX(fx : name, sourceName : string)
  2085.     {
  2086.         var i : int;
  2087.        
  2088.         for(i=0; i<currentlyPlayedFX.Size(); i+=1)
  2089.         {
  2090.             if(currentlyPlayedFX[i].fx == fx)
  2091.             {
  2092.                 currentlyPlayedFX[i].sources.Remove(sourceName);
  2093.                
  2094.                 if(currentlyPlayedFX[i].sources.Size() == 0)
  2095.                     currentlyPlayedFX.EraseFast(i);
  2096.                    
  2097.                 return;
  2098.             }
  2099.         }
  2100.     }
  2101.    
  2102.     // ++modImprovedTimeSkip
  2103.     private function ArraySortEffectsByTimeLeft(out effects : array<CBaseGameplayEffect>)
  2104.     {
  2105.         var i, j, size: int;
  2106.         var temp : CBaseGameplayEffect;
  2107.  
  2108.         size = effects.Size();
  2109.  
  2110.         for (i=0;i<size-1;i+=1)
  2111.         {
  2112.             for (j=i+1;j<size;j+=1)
  2113.             {
  2114.                 if (effects[j].GetTimeLeft() < effects[i].GetTimeLeft())
  2115.                 {
  2116.                     temp = effects[i];
  2117.                     effects[i] = effects[j];
  2118.                     effects[j] = temp;
  2119.                 }
  2120.             }
  2121.         }
  2122.     }
  2123.     // --modImprovedTimeSkip
  2124.    
  2125.     public final function SimulateBuffTimePassing(simulatedTime : float)
  2126.     {
  2127.         var i : int;
  2128.        
  2129.         // ++Buff Charges - Grindstone and Workbench Only
  2130.         var buff : CBaseGameplayEffect;
  2131.         var timeLeft : float;
  2132.         // --Buff Charges - Grindstone and Workbench Only\
  2133.        
  2134.         // ++modImprovedTimeSkip
  2135.         var regenEffectContainers : array<STempRegenEffectsContainer>;
  2136.         var tempContainer : STempRegenEffectsContainer;
  2137.  
  2138.         var regenStat : ECharacterRegenStats;
  2139.  
  2140.         var j, size:int;
  2141.  
  2142.         regenEffectContainers.Resize(CRS_SwimmingStamina+1);
  2143.         // --modImprovedTimeSkip
  2144.        
  2145.         for(i=effects.Size()-1; i>=0; i-=1)
  2146.         {
  2147.             // ++modImprovedTimeSkip
  2148.             if(owner == GetWitcherPlayer() && (!IsNegativeEffectType(effects[i].GetEffectType()) || (GetWitcherPlayer().HasRunewordActive('Runeword 5 _Stats'))))
  2149.             {
  2150.                 if ((W3RegenEffect)effects[i])
  2151.                 {
  2152.                     // save regen effects into an array to be processed later
  2153.                     regenStat = ((W3RegenEffect)effects[i]).GetRegenStat();
  2154.                     if ((W3AutoRegenEffect)effects[i])
  2155.                     {
  2156.                         // save auto regen
  2157.                         regenEffectContainers[regenStat].autoRegen = effects[i];
  2158.                     }
  2159.                     else
  2160.                     {
  2161.                         if (effects[i].GetTimeLeft() > simulatedTime || effects[i].GetTimeLeft() == -1) // effects that won't be removed can be processed right now
  2162.                             effects[i].OnTimeUpdated(simulatedTime);
  2163.                         else
  2164.                             regenEffectContainers[regenStat].effects.PushBack(effects[i]); // save effect to be processed later
  2165.                     }
  2166.                     continue;
  2167.                 }
  2168.                 effects[i].OnTimeUpdated(simulatedTime);
  2169.                 continue;
  2170.             }
  2171.             // --modImprovedTimeSkip
  2172.            
  2173.             // ++Buff Charges - Grindstone and Workbench Only
  2174.             if(owner == GetWitcherPlayer() && (W3RepairObjectEnhancement)effects[i])
  2175.             {
  2176.                 effects[i].OnTimeUpdated(simulatedTime);
  2177.                 continue;
  2178.             }
  2179.             // --Buff Charges - Grindstone and Workbench Only
  2180.            
  2181.             if(effects[i].GetTimeLeft() != -1)
  2182.             {
  2183.                 RemoveEffectOnIndex(i, true);
  2184.             }
  2185.         }
  2186.  
  2187.         // ++modImprovedTimeSkip
  2188.  
  2189.         // process auto regens and remaining regen effects
  2190.         // all the remaining non-auto effects in here would wear out within time passed
  2191.         for (i=0;i<=CRS_SwimmingStamina;i+=1)
  2192.         {
  2193.             tempContainer = regenEffectContainers[i];
  2194.             size = tempContainer.effects.Size();
  2195.             if (tempContainer.autoRegen)
  2196.             {
  2197.                 // sort the effects from shortest to longest
  2198.                 ArraySortEffectsByTimeLeft(tempContainer.effects);
  2199.                 for (j=0;j<size;j+=1)
  2200.                 {
  2201.                     // update auto regen for as long as this effect should work
  2202.                     if (tempContainer.effects[j].GetTimeLeft() - tempContainer.autoRegen_timeLeft > 0)
  2203.                     {
  2204.                         tempContainer.autoRegen.OnTimeUpdated(tempContainer.effects[j].GetTimeLeft() - tempContainer.autoRegen_timeLeft);
  2205.                         tempContainer.autoRegen_timeLeft = tempContainer.effects[j].GetTimeLeft();
  2206.                     }
  2207.  
  2208.                     // update the effect itself and remove it
  2209.                     tempContainer.effects[j].OnTimeUpdated(simulatedTime);
  2210.                     if (tempContainer.effects[j].GetTimeLeft() <= 0) // this check is needed for Tawny Owl Level 3
  2211.                         RemoveEffect(tempContainer.effects[j], true);
  2212.                 }
  2213.                 // update auto regen for the time it has left without other regen effects
  2214.                 if (simulatedTime - tempContainer.autoRegen_timeLeft > 0)
  2215.                     tempContainer.autoRegen.OnTimeUpdated(simulatedTime - tempContainer.autoRegen_timeLeft);
  2216.             }
  2217.             else
  2218.             {
  2219.                 // no autoregen, process as is
  2220.                 for (j=0;j<size;j+=1)
  2221.                 {
  2222.                     // update the effect itself and remove it
  2223.                     tempContainer.effects[j].OnTimeUpdated(simulatedTime);
  2224.                     if (tempContainer.effects[j].GetTimeLeft() <= 0) // this check is needed for Tawny Owl Level 3
  2225.                         RemoveEffect(tempContainer.effects[j], true);
  2226.                 }
  2227.             }
  2228.         }
  2229.         // --modImprovedTimeSkip
  2230.     }
  2231.    
  2232.     public final function Debug_ReleaseCriticalStateSaveLocks()
  2233.     {
  2234.         if(hasCriticalStateSaveLock)
  2235.             theGame.ReleaseNoSaveLock(criticalStateSaveLockId);
  2236.     }
  2237.    
  2238.     private final function CountShrineBuffs() : int
  2239.     {
  2240.         var i, doneBuffs : int;
  2241.         var type : EEffectType;
  2242.        
  2243.         doneBuffs = 0;
  2244.         for(i=0; i<effects.Size(); i+=1)
  2245.         {
  2246.             type = effects[i].GetEffectType();
  2247.            
  2248.             switch(type)
  2249.             {
  2250.                 case EET_ShrineAard:
  2251.                     doneBuffs += 1;
  2252.                     break;
  2253.                 case EET_ShrineAxii:
  2254.                     doneBuffs += 1;
  2255.                     break;
  2256.                 case EET_ShrineIgni:
  2257.                     doneBuffs += 1;
  2258.                     break;
  2259.                 case EET_ShrineQuen:
  2260.                     doneBuffs += 1;
  2261.                     break;
  2262.                 case EET_ShrineYrden:
  2263.                     doneBuffs += 1;
  2264.                     break;                 
  2265.                 default:
  2266.                     break;
  2267.             }          
  2268.         }
  2269.  
  2270.         return doneBuffs;
  2271.     }
  2272.    
  2273.     public final function HasAnyMutagen23ShrineBuff() : bool
  2274.     {
  2275.         var i : int;
  2276.         var shrineBuff : W3Effect_Shrine;
  2277.        
  2278.         for(i=0; i<effects.Size(); i+=1)
  2279.         {
  2280.             shrineBuff = (W3Effect_Shrine) effects[i];
  2281.             if(shrineBuff && shrineBuff.IsFromMutagen23())
  2282.                 return true;
  2283.         }
  2284.        
  2285.         return false;
  2286.     }
  2287.    
  2288.     public final function HasAnyShrineBuff() : bool
  2289.     {
  2290.         var i : int;
  2291.         var shrineBuff : W3Effect_Shrine;
  2292.        
  2293.         for(i=0; i<effects.Size(); i+=1)
  2294.         {
  2295.             shrineBuff = (W3Effect_Shrine) effects[i];
  2296.             if(shrineBuff)
  2297.                 return true;
  2298.         }
  2299.        
  2300.         return false;
  2301.     }
  2302.    
  2303.     public final function GetShrineBuffs() : array<CBaseGameplayEffect>
  2304.     {
  2305.         var i : int;
  2306.         var shrineBuff : W3Effect_Shrine;
  2307.         var ret : array<CBaseGameplayEffect>;
  2308.        
  2309.         for(i=0; i<effects.Size(); i+=1)
  2310.         {
  2311.             shrineBuff = (W3Effect_Shrine) effects[i];
  2312.             if(shrineBuff)
  2313.                 ret.PushBack(effects[i]);
  2314.         }
  2315.        
  2316.         return ret;
  2317.     }
  2318. }
  2319.  
Advertisement
Comments
  • lufusol
    1 year (edited)
    # text 0.72 KB | 0 0
    1. ScriptMerger is not able to automatically merge both versions of this file when you have the mods "Improved Time Skip" and "Buff Charges (Grindstone and Workbench Only)" installed, nor is it simple for your average-to-advanced end user in kdiff3 when it comes up, so I pored over the two scripts in Notepad++ until I had a handle on it, and made the necessary changes so that now you get the best of both mods.
    2.  
    3. To use this, first install both of those mods, find the "effectManager.ws" script in each of the mod subfolders, and either replace both of them with this file, or else delete one and replace the other (doesn't matter which). Make sure and re-merge your scripts if you had previous merges which affected this script.
  • lufusol
    1 year
    # text 0.28 KB | 0 0
    1. P.S. this is only for Witcher 3 Next Gen Update (4.0+) and the corresponding mod versions.
    2.  
    3. Improved Time Skip:
    4. https://www.nexusmods.com/witcher3/mods/6317
    5.  
    6. Buff Charges (this is only for the "Grindstone and Workbench Only" download):
    7. https://www.nexusmods.com/witcher3/mods/7383
Add Comment
Please, Sign In to add comment
Advertisement