Combat HandleCommandAttack

From Dragon Age Toolset Wiki
Jump to: navigation, search

Called by:

Calls: Combat_GetAttackHand

Parameters:

Variables:

Returns:

Used for:

/**
*  @brief Handles processing an Attack Command
*
*  @param oAttacker       The command owner, usually OBJEC_TSE
*  @param oTarget         The Target of the command
*  @param nCommandId      The command Id
*  @param nCommandSubType The command subtype
*
*  @returns COMBAT_RESULT_* constant
*
*  @author Georg Zoeller
**/
int  Combat_HandleCommandAttack(object oAttacker, object oTarget, int nCommandSubType);
int  Combat_HandleCommandAttack(object oAttacker, object oTarget, int nCommandSubType)
{
 
    struct CombatAttackResultStruct stAttack1;
    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.
    // -------------------------------------------------------------------------
    if (IsModalAbilityActive(oAttacker, ABILITY_TALENT_DUAL_WEAPON_DOUBLE_STRIKE))
    {
        nHand=HAND_BOTH;
        oWeapon = GetItemInEquipSlot(INVENTORY_SLOT_MAIN);
        oWeapon2 = GetItemInEquipSlot(INVENTORY_SLOT_OFFHAND);
    }
 
 
    int nAttackType = Combat_GetAttackType(oAttacker, oWeapon);
 
 
 
    // -------------------------------------------------------------------------
    // Handle Attack #1
    // -------------------------------------------------------------------------
    stAttack1 = Combat_PerformAttack(oAttacker, oTarget, oWeapon);
 
    if (nHand == HAND_BOTH)
    {
           stAttack2 = Combat_PerformAttack(oAttacker, oTarget, oWeapon2);
 
           if (stAttack1.nAttackResult != COMBAT_RESULT_DEATHBLOW &&  stAttack2.nAttackResult == COMBAT_RESULT_DEATHBLOW)
           {
                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
    // seconds and apply the deathblow command
    // -------------------------------------------------------------------------
    if (stAttack1.nAttackResult == COMBAT_RESULT_DEATHBLOW)
    {
 
        // ----------------------------------------------------------------------
        // Georg: Do Not Modify the following section.
        // START >>
        // GM - Adding the deathblow should be the last thing done because it
        // will clear the attack command.
        // Specifically, SetAttackResult MUST be executed before adding the deathblow.
        // ----------------------------------------------------------------------
        SetAttackResult(oAttacker,  stAttack1.nAttackResult, stAttack1.eImpactEffect,
                                    COMBAT_RESULT_INVALID, Effect()  );
 
 
        WR_AddCommand(oAttacker, CommandDeathBlow(oTarget, stAttack1.nDeathblowType), TRUE, TRUE);
 
        return COMMAND_RESULT_SUCCESS;
        // ----------------------------------------------------------------------
        // << END
        // ----------------------------------------------------------------------
    }
 
 
    // -------------------------------------------------------------------------
    // SetAttackResult requires a result in either the first or second result
    // field to determine which hand should attack.
    // -------------------------------------------------------------------------
    if (nHand == HAND_MAIN || stAttack1.nAttackResult == COMBAT_RESULT_BACKSTAB)
    {
          SetAttackResult(oAttacker,  stAttack1.nAttackResult, stAttack1.eImpactEffect,
                                    COMBAT_RESULT_INVALID, Effect()  );
 
    }
    else if (nHand == HAND_OFFHAND)
    {
          SetAttackResult(oAttacker,  COMBAT_RESULT_INVALID, Effect(),
                                        stAttack1.nAttackResult, stAttack1.eImpactEffect );
    }
    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))
        {
 
            if(nAttackType == ATTACK_TYPE_RANGED)
            {
                // the "attack duration" for ranged weapons actually overrides
                // the time spent drawing and preparing to aim
                if ( GetBaseItemType(oWeapon) == BASE_ITEM_TYPE_STAFF )
                {
                    SetAttackDuration(oAttacker, 0.30);
                }
                else
                {
                    object oArmor =GetItemInEquipSlot(INVENTORY_SLOT_CHEST);
                    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 );
 
                #ifdef DEBUG
                Log_Trace(LOG_CHANNEL_COMBAT,"combat_h.HandleCommandAttack","RangedAim Loop Duration set to " + FloatToString(stAttack1.fAttackDuration));
                #endif
            }
            else if (nAttackType == ATTACK_TYPE_MELEE)
            {
 
                SetAttackDuration(oAttacker,stAttack1.fAttackDuration);
 
            }
        }
    }
 
 
    return COMMAND_RESULT_SUCCESS;
}