Difference between revisions of "Combat HandleAttackImpact"
From Dragon Age Toolset Wiki
Mouser9169 (Talk | contribs) (Created page with "Called by: Parameters: Variables: Used for: <dascript> /** * @brief Handles processing an Attack Command * * @param oAttacker The command owner, usually OBJEC_TSE * @...") |
Mouser9169 (Talk | contribs) |
||
Line 8: | Line 8: | ||
<dascript> | <dascript> | ||
/** | /** | ||
− | * @brief Handles processing an | + | * @brief Handles processing an attack impact event |
* | * | ||
− | * @param oAttacker The command owner, usually | + | * @param oAttacker The command owner, usually OBJECT_SELF |
* @param oTarget The Target of the command | * @param oTarget The Target of the command | ||
− | * @param | + | * @param nAttackResult The result of the attack (COMBAT_RESULT_*) |
− | * @param | + | * @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 | ||
**/ | **/ | ||
− | + | 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; | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | int | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
// ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||
− | // | + | // We retired combat result blocked, so we treat it as a miss here. |
+ | // Might be back in DA2 | ||
// ------------------------------------------------------------------------- | // ------------------------------------------------------------------------- | ||
− | if ( | + | 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) | |
− | + | ||
− | + | ||
− | if ( | + | |
{ | { | ||
+ | // ------------------------------------------------------------- | ||
+ | // 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; | |
− | + | ||
− | if( | + | // --------------------------------------------------------------------- |
+ | // 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 ( | + | // ------------------------------------------------------------- |
+ | 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 ( | + | |
+ | |||
+ | } | ||
+ | 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); | ||
} | } | ||
+ | |||
</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