Combat HandleAttackImpact

From Dragon Age Toolset Wiki
Jump to: navigation, search

Called by:

Calls:

Parameters:

Variables:

Returns:

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);
}