//:: Retriever onHeartbeat //:: //:: retriever_onhb.nss //:: //:: // Define constants for each ray type const int FIRE = 1; const int COLD = 2; const int ELECTRICITY = 3; const int PETRIFICATION = 4; // Define cooldowns for rays in seconds const float COOLDOWN = 24.0; // Cooldown period in seconds void FireEyeRay(object oTarget, int nRayType); void CheckAndFireRay(object oRetriever); // Main Heartbeat function void main() { object oRetriever = OBJECT_SELF; CheckAndFireRay(oRetriever); DelayCommand(0.0f, ExecuteScript("codi_heartbeat")); } // Function to check cooldowns and fire a ray if possible void CheckAndFireRay(object oRetriever) { object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oRetriever, 1); if (!GetIsObjectValid(oTarget)) { PrintString("No valid target found."); return; // No valid target found } float fDistance = GetDistanceBetween(oRetriever, oTarget); PrintString("Distance to target: " + FloatToString(fDistance)); if (fDistance > 100.0) { PrintString("Target out of range."); return; // Target is out of range } float fCurrentTime = IntToFloat(GetTimeSecond()); float fLastUsed = IntToFloat(GetLocalInt(oRetriever, "LAST_USED_TIME")); int nRayType = Random(4) + 1; // Randomly select a ray type if (fLastUsed == 0.0 || fCurrentTime - fLastUsed >= COOLDOWN) { FireEyeRay(oTarget, nRayType); SetLocalInt(oRetriever, "LAST_USED_TIME", FloatToInt(fCurrentTime)); } else { PrintString("Cooldown active. Time left: " + FloatToString(fLastUsed + COOLDOWN - fCurrentTime) + " seconds."); } } // Function to handle the firing of a specific ray void FireEyeRay(object oTarget, int nRayType) { int nDC = 18; effect eVisual; effect eDamage; switch (nRayType) { case FIRE: eVisual = EffectVisualEffect(VFX_COM_HIT_FIRE); eDamage = EffectDamage(d6(12), DAMAGE_TYPE_FIRE); break; case COLD: eVisual = EffectVisualEffect(VFX_COM_HIT_FROST); eDamage = EffectDamage(d6(12), DAMAGE_TYPE_COLD); break; case ELECTRICITY: eVisual = EffectVisualEffect(VFX_COM_HIT_ELECTRICAL); eDamage = EffectDamage(d6(12), DAMAGE_TYPE_ELECTRICAL); break; case PETRIFICATION: eVisual = EffectVisualEffect(VFX_DUR_PETRIFY); if (!FortitudeSave(oTarget, nDC, FALSE)) { effect ePetrify = EffectPetrify(); ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePetrify, oTarget); } return; } // Apply visual effects and damage ApplyEffectToObject(DURATION_TYPE_INSTANT, eVisual, oTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget); if (ReflexSave(oTarget, nDC, TRUE) == TRUE) // TRUE for half damage { ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(6), DAMAGE_TYPE_FIRE), oTarget); } }