#include "x2_inc_spellhook" #include "prc_inc_combmove" #include "inc_utility" // Constants for tracking steps const int STEP_SUNBEAM_MOST_POWERFUL = 1; const int STEP_TRUE_STRIKE_AND_ATTACK = 2; const int STEP_MOVE_TO_NEAREST = 3; const int STEP_TRUE_STRIKE_SELF = 4; const int STEP_ATTACK_NEAREST = 5; const int STEP_SUNBEAM_OR_TRUE_STRIKE = 6; void DoAwesomeBlow(object oTarget, object oNPC = OBJECT_SELF) { int nHP = GetCurrentHitPoints(oTarget); int nSizeBonus; effect eNone; // Apply the VFX ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_REFLEX_SAVE_THROW_USE), oTarget); PerformAttack(oTarget, oNPC, eNone, 0.0, -4); if (GetLocalInt(oTarget, "PRCCombat_StruckByAttack")) { int nDC = nHP - GetCurrentHitPoints(oTarget); // This should be the amount caused by the attack if ((PRCGetCreatureSize(oNPC) + nSizeBonus) > PRCGetCreatureSize(oTarget)) { if (!PRCMySavingThrow(SAVING_THROW_REFLEX, oTarget, nDC, SAVING_THROW_TYPE_NONE)) { _DoBullRushKnockBack(oTarget, oNPC, 10.0); // Apply knockdown effect after the knockback with a slight delay DelayCommand(0.1, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectKnockdown(), oTarget, 6.0)); // Trigger dust explosion when the target stops moving DelayCommand(0.6, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_DUST_EXPLOSION), oTarget)); } } } } // Function to get the most powerful opponent object GetMostPowerfulOpponent(object oCaster) { float fRadius = 40.0f; // Limit of perception in NWN int nShape = SHAPE_SPHERE; // Shape type location lCasterLocation = GetLocation(oCaster); // Correct location type object oTarget = GetFirstObjectInShape(nShape, fRadius, lCasterLocation, TRUE); object oStrongest = OBJECT_INVALID; float fHighestCR = -1.0f; while (oTarget != OBJECT_INVALID) { // Check if the target is a creature and hostile to the caster if (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE && GetIsReactionTypeHostile(oTarget, oCaster)) { float fCR = GetChallengeRating(oTarget); if (fCR > fHighestCR) { fHighestCR = fCR; oStrongest = oTarget; } } oTarget = GetNextObjectInShape(nShape, fRadius, lCasterLocation, TRUE); } return oStrongest; } // Function to get the weakest enemy object GetWeakestEnemy(object oCaster) { float fRadius = 40.0f; // Limit of perception in NWN int nShape = SHAPE_SPHERE; // Shape type location lCasterLocation = GetLocation(oCaster); // Correct location type object oTarget = GetFirstObjectInShape(nShape, fRadius, lCasterLocation, TRUE); object oWeakest = OBJECT_INVALID; float fLowestCR = 9999.0f; while (oTarget != OBJECT_INVALID) { // Check if the target is a creature and hostile to the caster if (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE && GetIsReactionTypeHostile(oTarget, oCaster)) { float fCR = GetChallengeRating(oTarget); if (fCR < fLowestCR) { fLowestCR = fCR; oWeakest = oTarget; } } oTarget = GetNextObjectInShape(nShape, fRadius, lCasterLocation, TRUE); } return oWeakest; } // Function to get the nearest enemy object GetNearestEnemy(object oCaster) { object oTarget = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oCaster, 1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY); return oTarget; } void main() { object oCaster = OBJECT_SELF; object oNearestEnemy = GetNearestEnemy(oCaster); // Retrieve or initialize the current step int nStep = GetLocalInt(oCaster, "CURRENT_STEP"); if (nStep == 0) { nStep = STEP_SUNBEAM_MOST_POWERFUL; } switch (nStep) { case STEP_SUNBEAM_MOST_POWERFUL: { // 100% chance to use Sunbeam, if memorized, on the most powerful opponent object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN); if (oTarget != OBJECT_INVALID && GetHasSpell(SPELL_SUNBEAM, oCaster)) { AssignCommand(oCaster, ActionCastSpellAtObject(SPELL_SUNBEAM, oTarget)); } SetLocalInt(oCaster, "CURRENT_STEP", STEP_TRUE_STRIKE_AND_ATTACK); break; } case STEP_TRUE_STRIKE_AND_ATTACK: { // If nearest enemy is within 10 meters, cast True Strike on self & attack nearest enemy if (oNearestEnemy != OBJECT_INVALID && GetDistanceToObject(oNearestEnemy) <= 10.0f) { AssignCommand(oCaster, ActionCastSpellAtObject(SPELL_TRUE_STRIKE, oCaster)); AssignCommand(oCaster, ActionAttack(oNearestEnemy)); } SetLocalInt(oCaster, "CURRENT_STEP", STEP_MOVE_TO_NEAREST); break; } case STEP_MOVE_TO_NEAREST: { // If nearest enemy is over 10 meters away, move to nearest enemy if (oNearestEnemy != OBJECT_INVALID && GetDistanceToObject(oNearestEnemy) > 10.0f) { AssignCommand(oCaster, ActionMoveToObject(oNearestEnemy)); } SetLocalInt(oCaster, "CURRENT_STEP", STEP_TRUE_STRIKE_SELF); break; } case STEP_TRUE_STRIKE_SELF: { // 100% to cast True Strike on self AssignCommand(oCaster, ActionCastSpellAtObject(SPELL_TRUE_STRIKE, oCaster)); SetLocalInt(oCaster, "CURRENT_STEP", STEP_ATTACK_NEAREST); break; } case STEP_ATTACK_NEAREST: { // Attack nearest enemy if (oNearestEnemy != OBJECT_INVALID) { AssignCommand(oCaster, ActionAttack(oNearestEnemy)); } SetLocalInt(oCaster, "CURRENT_STEP", STEP_SUNBEAM_OR_TRUE_STRIKE); break; } case STEP_SUNBEAM_OR_TRUE_STRIKE: { // 50% to cast Sunbeam, if memorized, on weakest enemy, else cast True Strike object oWeakestEnemy = GetWeakestEnemy(oCaster); if (Random(2) == 0 && GetHasSpell(SPELL_SUNBEAM, oCaster) && oWeakestEnemy != OBJECT_INVALID) { AssignCommand(oCaster, ActionCastSpellAtObject(SPELL_SUNBEAM, oWeakestEnemy)); } else { AssignCommand(oCaster, ActionCastSpellAtObject(SPELL_TRUE_STRIKE, oCaster)); } // If under the effects of True Strike, attack nearest enemy, else cast True Strike if (GetHasSpellEffect(SPELL_TRUE_STRIKE, oCaster) && oNearestEnemy != OBJECT_INVALID) { AssignCommand(oCaster, ActionAttack(oNearestEnemy)); } else { AssignCommand(oCaster, ActionCastSpellAtObject(SPELL_TRUE_STRIKE, oCaster)); } SetLocalInt(oCaster, "CURRENT_STEP", STEP_SUNBEAM_MOST_POWERFUL); break; } } }