100 lines
3.0 KiB
Plaintext
100 lines
3.0 KiB
Plaintext
//:: 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);
|
|
}
|
|
}
|