Difference between revisions of "Combat HandleAttackImpact"

From Dragon Age Toolset Wiki
Jump to: navigation, search
(Created page with "Called by: Parameters: Variables: Used for: <dascript> /** * @brief Handles processing an Attack Command * * @param oAttacker The command owner, usually OBJEC_TSE * @...")
 
Line 8: Line 8:
 
<dascript>
 
<dascript>
 
/**
 
/**
*  @brief Handles processing an Attack Command
+
*  @brief Handles processing an attack impact event
 
*
 
*
*  @param oAttacker      The command owner, usually OBJEC_TSE
+
*  @param oAttacker      The command owner, usually OBJECT_SELF
 
*  @param oTarget        The Target of the command
 
*  @param oTarget        The Target of the command
*  @param nCommandId      The command Id
+
*  @param nAttackResult  The result of the attack (COMBAT_RESULT_*)
*  @param nCommandSubType The command subtype
+
*  @param eImpactEffect  The attack's impact effect.
 
*
 
*
 
*  @returns COMBAT_RESULT_* constant
 
*  @returns COMBAT_RESULT_* constant
Line 19: Line 19:
 
*  @author Georg Zoeller
 
*  @author Georg Zoeller
 
**/
 
**/
int  Combat_HandleCommandAttack(object oAttacker, object oTarget, int nCommandSubType);
+
void Combat_HandleAttackImpact(object oAttacker, object oTarget, int nAttackResult, effect eImpactEffect);
int  Combat_HandleCommandAttack(object oAttacker, object oTarget, int nCommandSubType)
+
void Combat_HandleAttackImpact(object oAttacker, object oTarget, int nAttackResult, effect eImpactEffect)
 
{
 
{
  
    struct CombatAttackResultStruct stAttack1;
+
     int nUIMessage = UI_MESSAGE_MISSED;
    struct CombatAttackResultStruct stAttack2;
+
 
+
 
+
    object oWeapon;
+
    object oWeapon2;
+
 
+
     int nHand = Combat_GetAttackHand(oAttacker);
+
 
+
    if (nHand == HAND_MAIN)
+
    {
+
        oWeapon = GetItemInEquipSlot(INVENTORY_SLOT_MAIN);
+
    }
+
    else if (nHand == HAND_OFFHAND)
+
    {
+
        oWeapon = GetItemInEquipSlot(INVENTORY_SLOT_OFFHAND);
+
    }
+
  
 
     // -------------------------------------------------------------------------
 
     // -------------------------------------------------------------------------
     // Double Weapon Strike.
+
     // We retired combat result blocked, so we treat it as a miss here.
 +
    // Might be back in DA2
 
     // -------------------------------------------------------------------------
 
     // -------------------------------------------------------------------------
     if (IsModalAbilityActive(oAttacker, ABILITY_TALENT_DUAL_WEAPON_DOUBLE_STRIKE))
+
     if (nAttackResult == COMBAT_RESULT_BLOCKED)
 
     {
 
     {
         nHand=HAND_BOTH;
+
         nAttackResult = COMBAT_RESULT_MISS;
         oWeapon = GetItemInEquipSlot(INVENTORY_SLOT_MAIN);
+
         nUIMessage = UI_MESSAGE_BLOCKED;
        oWeapon2 = GetItemInEquipSlot(INVENTORY_SLOT_OFFHAND);
+
 
     }
 
     }
  
  
    int nAttackType = Combat_GetAttackType(oAttacker, oWeapon);
+
     // -----------------------------------------------------------------
 
+
     // If the target managed to stealth, we're converting it into a miss
 
+
     // -----------------------------------------------------------------
 
+
     if (nAttackResult != COMBAT_RESULT_DEATHBLOW && nAttackResult != COMBAT_RESULT_MISS && IsInvisible(oTarget) )
     // -------------------------------------------------------------------------
+
     // Handle Attack #1
+
     // -------------------------------------------------------------------------
+
     stAttack1 = Combat_PerformAttack(oAttacker, oTarget, oWeapon);
+
 
+
    if (nHand == HAND_BOTH)
+
 
     {
 
     {
          stAttack2 = Combat_PerformAttack(oAttacker, oTarget, oWeapon2);
+
        #ifdef DEBUG
 
+
        Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","Target turned invisible - hit converted to miss");
          if (stAttack1.nAttackResult != COMBAT_RESULT_DEATHBLOW &&  stAttack2.nAttackResult == COMBAT_RESULT_DEATHBLOW)
+
        #endif
          {
+
        nAttackResult = COMBAT_RESULT_MISS;
                stAttack1 = stAttack2;
+
                nHand = HAND_MAIN; // Deathblows just use the main hand.
+
          }
+
 
+
 
     }
 
     }
  
    // -------------------------------------------------------------------------
+
 
    // If we execute a deathblow, we gain the death fury effect for a couple of
+
     if (nAttackResult != COMBAT_RESULT_MISS)
    // seconds and apply the deathblow command
+
    // -------------------------------------------------------------------------
+
     if (stAttack1.nAttackResult == COMBAT_RESULT_DEATHBLOW)
+
 
     {
 
     {
 +
        // -------------------------------------------------------------
 +
        // Tell the damage effect to update gore and by how much...
 +
        // see gore_h for details or ask georg.
 +
        // -------------------------------------------------------------
 +
        object oWeapon = GetEffectObject(eImpactEffect,0);
 +
        int nApp = GetAppearanceType(oAttacker);
 +
        int nAbility = GetEffectInteger(eImpactEffect,1);
  
         // ----------------------------------------------------------------------
+
         float fPerSpace = GetM2DAFloat(TABLE_APPEARANCE, "PERSPACE", nApp);
         // Georg: Do Not Modify the following section.
+
         // Skipping range check if the creature is large (personal space greater or equal to one)
         // START >>
+
         if (IsObjectValid(oWeapon) && IsUsingMeleeWeapon(oAttacker, oWeapon) && fPerSpace < 1.0)
         // GM - Adding the deathblow should be the last thing done because it
+
         {
        // will clear the attack command.
+
            if (GetDistanceBetween(oTarget, oAttacker) > 5.0f)
        // Specifically, SetAttackResult MUST be executed before adding the deathblow.
+
            {
        // ----------------------------------------------------------------------
+
                #ifdef DEBUG
        SetAttackResult(oAttacker, stAttack1.nAttackResult, stAttack1.eImpactEffect,
+
                Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","Melee attack impact from past 5m found, changed to COMBAT_RESULT_MISS");
                                    COMBAT_RESULT_INVALID, Effect()  );
+
                #endif
 +
                nAttackResult = COMBAT_RESULT_MISS;
 +
            }
  
 +
        }
  
        WR_AddCommand(oAttacker, CommandDeathBlow(oTarget, stAttack1.nDeathblowType), TRUE, TRUE);
 
  
        return COMMAND_RESULT_SUCCESS;
+
    // -----------------------------------------------------------------
        // ----------------------------------------------------------------------
+
    // The attack was successful, ...
        // << END
+
    // -----------------------------------------------------------------
        // ----------------------------------------------------------------------
+
      float fDamage = GetEffectFloat(eImpactEffect,0);
    }
+
      int nVfx = GetEffectInteger(eImpactEffect,0);
 +
      int nDamageType = GetEffectInteger(eImpactEffect, 2);
  
 +
        // special damage type override for Shale, filtered for performance reasons
 +
        int nAppearanceType = GetAppearanceType(oAttacker);
 +
        #ifdef DEBUG
 +
        Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","Attacker appearance type = " + ToString(nAppearanceType));
 +
        #endif
 +
        if (nAppearanceType == 10100) // new shale type
 +
        {
 +
            // check for damage type modifying effect
 +
            effect[] eModifiers = GetEffects(oAttacker, 10000);
 +
            #ifdef DEBUG
 +
            Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","  Modifier effects present = " + ToString(GetArraySize(eModifiers)));
 +
            #endif
 +
            if (IsEffectValid(eModifiers[0]) == TRUE)
 +
            {
 +
                int nOverrideDamageType = GetEffectInteger(eModifiers[0], 0);
 +
                nDamageType = nOverrideDamageType;
  
    // -------------------------------------------------------------------------
+
                #ifdef DEBUG
    // SetAttackResult requires a result in either the first or second result
+
                Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact"," First modifier is valid with type " + ToString(nOverrideDamageType));
    // field to determine which hand should attack.
+
                #endif
    // -------------------------------------------------------------------------
+
            }
    if (nHand == HAND_MAIN || stAttack1.nAttackResult == COMBAT_RESULT_BACKSTAB)
+
        }
    {
+
          SetAttackResult(oAttackerstAttack1.nAttackResult, stAttack1.eImpactEffect,
+
                                    COMBAT_RESULT_INVALID, Effect() );
+
  
    }
+
        // -------------------------------------------------------------
    else if (nHand == HAND_OFFHAND)
+
        // If damage was negative, something went wrong and we bail out
    {
+
        // -------------------------------------------------------------
          SetAttackResult(oAttacker,  COMBAT_RESULT_INVALID, Effect(),
+
        if(fDamage < 0.0f)
                                        stAttack1.nAttackResult, stAttack1.eImpactEffect );
+
        {
    }
+
            return;
    else if (nHand == HAND_BOTH)
+
        }
    {
+
        SetAttackResult(oAttacker,  stAttack1.nAttackResult, stAttack1.eImpactEffect,stAttack2.nAttackResult, stAttack2.eImpactEffect );
+
    }
+
    else
+
    {
+
          SetAttackResult(oAttacker,  stAttack1.nAttackResult, stAttack1.eImpactEffect,
+
                                    COMBAT_RESULT_INVALID, Effect()  );
+
    }
+
  
  
    if (stAttack1.fAttackDuration != ATTACK_LOOP_DURATION_INVALID)
 
    {
 
  
         if (IsHumanoid(oAttacker))
+
         int nGore;
        {
+
  
             if(nAttackType == ATTACK_TYPE_RANGED)
+
        // ---------------------------------------------------------------------
 +
        // Only melee weapons update gore.
 +
        // ---------------------------------------------------------------------
 +
        if (IsObjectValid(oWeapon))
 +
        {
 +
             if (GetItemType(oWeapon) == ITEM_TYPE_WEAPON_MELEE)
 
             {
 
             {
                 // the "attack duration" for ranged weapons actually overrides
+
                 // -------------------------------------------------------------
                 // the time spent drawing and preparing to aim
+
                // Attacks that are not deathblows may play an attack grount.
                 if ( GetBaseItemType(oWeapon) == BASE_ITEM_TYPE_STAFF )
+
                 // -------------------------------------------------------------
 +
                 if (nAttackResult != COMBAT_RESULT_DEATHBLOW)
 
                 {
 
                 {
                     SetAttackDuration(oAttacker, 0.30);
+
                     SSPlaySituationalSound(oAttacker, SOUND_SITUATION_ATTACK_IMPACT);
 
                 }
 
                 }
                 else
+
 
 +
                 // only update gore if the target can bleed (PeterT 25/7/08)
 +
                int nTargetAppearance = GetAppearanceType(oTarget);
 +
                if (GetM2DAInt(TABLE_APPEARANCE, "bCanBleed", nTargetAppearance) == TRUE)
 
                 {
 
                 {
                     object oArmor =GetItemInEquipSlot(INVENTORY_SLOT_CHEST);
+
                     nGore = DAMAGE_EFFECT_FLAG_UPDATE_GORE;
                    if ( !IsArmorMassive(oArmor) && HasAbility(oAttacker, ABILITY_TALENT_MASTER_ARCHER))
+
                    {
+
                        if(IsFollower(oAttacker))
+
                            SetAttackDuration(oAttacker, 0.8);
+
                        else
+
                            SetAttackDuration(oAttacker, 1.5);
+
                    }
+
                    else if (IsArmorHeavyOrMassive(oArmor) )
+
                    {
+
                        if(IsFollower(oAttacker))
+
                            SetAttackDuration(oAttacker, 2.0);
+
                        else
+
                            SetAttackDuration(oAttacker, 2.5);
+
                    }
+
                    else
+
                    {
+
                        if(IsFollower(oAttacker))
+
                            SetAttackDuration(oAttacker, 0.8);
+
                        else
+
                            SetAttackDuration(oAttacker, 1.5);
+
                    }
+
 
                 }
 
                 }
 +
            }
 +
        }
  
                SetAimLoopDuration(oAttacker, stAttack1.fAttackDuration );
+
        if ( nAttackResult == COMBAT_RESULT_CRITICALHIT)
 +
        {
  
                #ifdef DEBUG
+
            #ifdef DEBUG
                Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleCommandAttack","RangedAim Loop Duration set to " + FloatToString(stAttack1.fAttackDuration));
+
            Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_CRITICALHIT");
                 #endif
+
            #endif
 +
 
 +
            // -----------------------------------------------------------------
 +
            // Damage below a certain threshold is not displayed as critical
 +
            // -----------------------------------------------------------------
 +
            if (fDamage >= DAMAGE_CRITICAL_DISPLAY_THRESHOLD)
 +
            {
 +
                if (IsPartyMember(oAttacker))
 +
                {
 +
                        Engine_ApplyEffectOnObject(EFFECT_DURATION_TYPE_TEMPORARY,EffectScreenShake( SCREEN_SHAKE_TYPE_CRITICAL_HIT ),oTarget, 1.0f, oAttacker);
 +
                 }
 +
 
 +
                nGore |= DAMAGE_EFFECT_FLAG_CRITICAL;
 
             }
 
             }
             else if (nAttackType == ATTACK_TYPE_MELEE)
+
 
 +
 
 +
        }
 +
        else if ( nAttackResult == COMBAT_RESULT_BACKSTAB)
 +
        {
 +
             #ifdef DEBUG
 +
            Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_BACKSTAB");
 +
            #endif
 +
 
 +
            nGore |= DAMAGE_EFFECT_FLAG_BACKSTAB;
 +
            nGore |= DAMAGE_EFFECT_FLAG_CRITICAL;
 +
          //  UI_DisplayMessage(oAttacker, UI_MESSAGE_BACKSTAB);
 +
 
 +
 
 +
        }
 +
        else if (nAttackResult == COMBAT_RESULT_DEATHBLOW)
 +
        {
 +
              #ifdef DEBUG
 +
              Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_DEATHBLOW");
 +
              #endif
 +
 
 +
              nGore |= DAMAGE_EFFECT_FLAG_CRITICAL;
 +
 
 +
        }
 +
        else
 +
        {
 +
            #ifdef DEBUG
 +
            Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_HIT");
 +
            #endif
 +
 
 +
        }
 +
 
 +
 
 +
        // ---------------------------------------------------------------------
 +
        // Templar's Righteous Strike - 25% mana damage
 +
        // ---------------------------------------------------------------------
 +
        if (IsMagicUser(oTarget))
 +
        {
 +
            if (GetItemType(oWeapon) == ITEM_TYPE_WEAPON_MELEE)
 
             {
 
             {
 +
                if (HasAbility(oAttacker,ABILITY_TALENT_RIGHTEOUS_STRIKE))
 +
                {
 +
                    nGore |= DAMAGE_EFFECT_FLAG_LEECH_MANA;
 +
                    nGore |= DAMAGE_EFFECT_FLAG_LEECH_25;
  
                SetAttackDuration(oAttacker,stAttack1.fAttackDuration);
 
  
 +
                    ApplyEffectVisualEffect(oAttacker, oTarget, 90181, EFFECT_DURATION_TYPE_INSTANT, 0.0f, ABILITY_TALENT_RIGHTEOUS_STRIKE);
 +
                }
 
             }
 
             }
 
         }
 
         }
 +
 +
        // -------------------------------------------------------------
 +
        //            Here is where the actual damage is dealt
 +
        // -------------------------------------------------------------
 +
        Effects_ApplyInstantEffectDamage(oTarget, oAttacker, fDamage, nDamageType, nGore,nAbility,nVfx);
 +
        Combat_Damage_CheckOnImpactAbilities(oTarget, oAttacker, fDamage, nAttackResult, oWeapon, nAbility);
 
     }
 
     }
  
 +
    else  if (nAttackResult == COMBAT_RESULT_MISS)
 +
    {
 +
        #ifdef DEBUG
 +
        Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_MISS");
 +
        #endif
  
     return COMMAND_RESULT_SUCCESS;
+
        UI_DisplayMessage(oAttacker, nUIMessage);
 +
 
 +
     }
 +
    else  if (nAttackResult == COMBAT_RESULT_BLOCKED)
 +
    {
 +
        #ifdef DEBUG
 +
        Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_BLOCKED");
 +
        #endif
 +
 
 +
        // Do something smart here in the future
 +
        //        UI_DisplayMessage(oAttacker, UI_MESSAGE_MISSED);
 +
    }
 +
 
 +
    // Stats - handle hit rate
 +
    STATS_HandleHitRate(oAttacker, nAttackResult);
 
}
 
}
 +
 
</dascript>
 
</dascript>
 
Category: [[Combat_H]]
 
Category: [[Combat_H]]

Revision as of 06:02, 1 August 2011

Called by:

Parameters:

Variables:

Used for:

/**
*  @brief Handles processing an attack impact event
*
*  @param oAttacker       The command owner, usually OBJECT_SELF
*  @param oTarget         The Target of the command
*  @param nAttackResult   The result of the attack (COMBAT_RESULT_*)
*  @param eImpactEffect   The attack's impact effect.
*
*  @returns COMBAT_RESULT_* constant
*
*  @author Georg Zoeller
**/
void Combat_HandleAttackImpact(object oAttacker, object oTarget, int nAttackResult, effect eImpactEffect);
void Combat_HandleAttackImpact(object oAttacker, object oTarget, int nAttackResult, effect eImpactEffect)
{
 
    int nUIMessage = UI_MESSAGE_MISSED;
 
    // -------------------------------------------------------------------------
    // We retired combat result blocked, so we treat it as a miss here.
    // Might be back in DA2
    // -------------------------------------------------------------------------
    if (nAttackResult == COMBAT_RESULT_BLOCKED)
    {
        nAttackResult = COMBAT_RESULT_MISS;
        nUIMessage = UI_MESSAGE_BLOCKED;
    }
 
 
    // -----------------------------------------------------------------
    // If the target managed to stealth, we're converting it into a miss
    // -----------------------------------------------------------------
    if (nAttackResult != COMBAT_RESULT_DEATHBLOW && nAttackResult != COMBAT_RESULT_MISS && IsInvisible(oTarget) )
    {
        #ifdef DEBUG
        Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","Target turned invisible - hit converted to miss");
        #endif
        nAttackResult = COMBAT_RESULT_MISS;
    }
 
 
    if (nAttackResult != COMBAT_RESULT_MISS)
    {
        // -------------------------------------------------------------
        // Tell the damage effect to update gore and by how much...
        // see gore_h for details or ask georg.
        // -------------------------------------------------------------
        object oWeapon = GetEffectObject(eImpactEffect,0);
        int nApp = GetAppearanceType(oAttacker);
        int nAbility = GetEffectInteger(eImpactEffect,1);
 
        float fPerSpace = GetM2DAFloat(TABLE_APPEARANCE, "PERSPACE", nApp);
        // Skipping range check if the creature is large (personal space greater or equal to one)
        if (IsObjectValid(oWeapon) && IsUsingMeleeWeapon(oAttacker, oWeapon) && fPerSpace < 1.0)
        {
            if (GetDistanceBetween(oTarget, oAttacker) > 5.0f)
            {
                #ifdef DEBUG
                Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","Melee attack impact from past 5m found, changed to COMBAT_RESULT_MISS");
                #endif
                nAttackResult = COMBAT_RESULT_MISS;
            }
 
        }
 
 
    // -----------------------------------------------------------------
    // The attack was successful, ...
    // -----------------------------------------------------------------
       float fDamage = GetEffectFloat(eImpactEffect,0);
       int nVfx = GetEffectInteger(eImpactEffect,0);
       int nDamageType = GetEffectInteger(eImpactEffect, 2);
 
        // special damage type override for Shale, filtered for performance reasons
        int nAppearanceType = GetAppearanceType(oAttacker);
        #ifdef DEBUG
        Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","Attacker appearance type = " + ToString(nAppearanceType));
        #endif
        if (nAppearanceType == 10100) // new shale type
        {
            // check for damage type modifying effect
            effect[] eModifiers = GetEffects(oAttacker, 10000);
            #ifdef DEBUG
            Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","  Modifier effects present = " + ToString(GetArraySize(eModifiers)));
            #endif
            if (IsEffectValid(eModifiers[0]) == TRUE)
            {
                int nOverrideDamageType = GetEffectInteger(eModifiers[0], 0);
                nDamageType = nOverrideDamageType;
 
                #ifdef DEBUG
                Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","  First modifier is valid with type " + ToString(nOverrideDamageType));
                #endif
            }
        }
 
        // -------------------------------------------------------------
        // If damage was negative, something went wrong and we bail out
        // -------------------------------------------------------------
        if(fDamage < 0.0f)
        {
            return;
        }
 
 
 
        int nGore;
 
        // ---------------------------------------------------------------------
        // Only melee weapons update gore.
        // ---------------------------------------------------------------------
        if (IsObjectValid(oWeapon))
        {
            if (GetItemType(oWeapon) == ITEM_TYPE_WEAPON_MELEE)
            {
                // -------------------------------------------------------------
                // Attacks that are not deathblows may play an attack grount.
                // -------------------------------------------------------------
                if (nAttackResult != COMBAT_RESULT_DEATHBLOW)
                {
                    SSPlaySituationalSound(oAttacker, SOUND_SITUATION_ATTACK_IMPACT);
                }
 
                // only update gore if the target can bleed (PeterT 25/7/08)
                int nTargetAppearance = GetAppearanceType(oTarget);
                if (GetM2DAInt(TABLE_APPEARANCE, "bCanBleed", nTargetAppearance) == TRUE)
                {
                    nGore =  DAMAGE_EFFECT_FLAG_UPDATE_GORE;
                }
            }
        }
 
        if ( nAttackResult == COMBAT_RESULT_CRITICALHIT)
        {
 
            #ifdef DEBUG
            Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_CRITICALHIT");
            #endif
 
            // -----------------------------------------------------------------
            // Damage below a certain threshold is not displayed as critical
            // -----------------------------------------------------------------
            if (fDamage >= DAMAGE_CRITICAL_DISPLAY_THRESHOLD)
            {
                if (IsPartyMember(oAttacker))
                {
                        Engine_ApplyEffectOnObject(EFFECT_DURATION_TYPE_TEMPORARY,EffectScreenShake( SCREEN_SHAKE_TYPE_CRITICAL_HIT ),oTarget, 1.0f, oAttacker);
                }
 
                nGore |= DAMAGE_EFFECT_FLAG_CRITICAL;
            }
 
 
        }
        else if ( nAttackResult == COMBAT_RESULT_BACKSTAB)
        {
            #ifdef DEBUG
            Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_BACKSTAB");
            #endif
 
             nGore |= DAMAGE_EFFECT_FLAG_BACKSTAB;
             nGore |= DAMAGE_EFFECT_FLAG_CRITICAL;
          //   UI_DisplayMessage(oAttacker, UI_MESSAGE_BACKSTAB);
 
 
        }
        else if (nAttackResult == COMBAT_RESULT_DEATHBLOW)
        {
              #ifdef DEBUG
              Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_DEATHBLOW");
              #endif
 
              nGore |= DAMAGE_EFFECT_FLAG_CRITICAL;
 
        }
        else
        {
            #ifdef DEBUG
            Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_HIT");
            #endif
 
        }
 
 
        // ---------------------------------------------------------------------
        // Templar's Righteous Strike - 25% mana damage
        // ---------------------------------------------------------------------
        if (IsMagicUser(oTarget))
        {
            if (GetItemType(oWeapon) == ITEM_TYPE_WEAPON_MELEE)
            {
                if (HasAbility(oAttacker,ABILITY_TALENT_RIGHTEOUS_STRIKE))
                {
                     nGore |= DAMAGE_EFFECT_FLAG_LEECH_MANA;
                     nGore |= DAMAGE_EFFECT_FLAG_LEECH_25;
 
 
                     ApplyEffectVisualEffect(oAttacker, oTarget, 90181, EFFECT_DURATION_TYPE_INSTANT, 0.0f, ABILITY_TALENT_RIGHTEOUS_STRIKE);
                }
            }
        }
 
        // -------------------------------------------------------------
        //            Here is where the actual damage is dealt
        // -------------------------------------------------------------
        Effects_ApplyInstantEffectDamage(oTarget, oAttacker, fDamage, nDamageType, nGore,nAbility,nVfx);
        Combat_Damage_CheckOnImpactAbilities(oTarget, oAttacker, fDamage, nAttackResult, oWeapon, nAbility);
    }
 
    else  if (nAttackResult == COMBAT_RESULT_MISS)
    {
        #ifdef DEBUG
        Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_MISS");
        #endif
 
        UI_DisplayMessage(oAttacker, nUIMessage);
 
    }
    else  if (nAttackResult == COMBAT_RESULT_BLOCKED)
    {
        #ifdef DEBUG
        Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleAttackImpact","COMBAT_RESULT_BLOCKED");
        #endif
 
        // Do something smart here in the future
        //        UI_DisplayMessage(oAttacker, UI_MESSAGE_MISSED);
    }
 
    // Stats - handle hit rate
    STATS_HandleHitRate(oAttacker, nAttackResult);
}

Category: Combat_H