The script I posted before wasn't meant for a heartbeat script, it was meant to go in the script that spawns the barrel.
Here's a revised script to replace your onPerception one. It should cause the calling NPC to try to run to the PC, 5 seconds later stop and do an animation, dropping the barrel a few seconds later. 10 seconds after it's spawned, then it explodes. It's set to run once, but your can change that number if your NPC is meant to drop more than one barrel...in which case you'll need a way to keep him from running off to plant another while in the process of planting the first if he perceives another PC during that time.
// Use for gnome's onPerception to place 1 exploding barrel.
// - The Amethyst Dragon
void DropTheBoomer(location lTarget, object oDropper)
{
// This function lets the spawning of the barrel be delayed.
object oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE, "engineeredexplo", lTarget);
SetLocalObject(oDropper, "theboom", oSpawn);
}
void TenNineBoom(object oDropper)
{
object oBarrel = GetLocalObject(oDropper, "theboom");
DeleteLocalObject(oDropper, "theboom");
if (GetCurrentHitPoints(oBarrel) < 1) { return; } // Don't run if barrel is destroyed before time runs out
location lBarrel = GetLocation(oBarrel);
int nDamage;
effect eVis = EffectVisualEffect(VFX_IMP_FLAME_M);
int nDC = 14; // save DC
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_FIREBALL), lBarrel);
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_HUGE, lBarrel, TRUE);
while (oTarget != OBJECT_INVALID)
{
nDamage = d6(10); // generic big boom damage
nDamage = GetReflexAdjustedDamage(nDamage, oTarget, nDC, SAVING_THROW_TYPE_FIRE, oBarrel);
if (nDamage > 0)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage, DAMAGE_TYPE_FIRE), oTarget);
}
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_HUGE, lBarrel, TRUE);
}
}
void main()
{
object oPC = GetLastPerceived();
if (!GetIsPC(oPC)) return;
if (!GetLastPerceptionSeen()) return;
if (GetLocalInt(OBJECT_SELF, "droppedtheboom") != 1)
{
ClearAllActions();
ActionMoveToObject(oPC, TRUE);
DelayCommand(5.0, ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0f, 4.0f));
location lTarget = GetLocation(OBJECT_SELF); // get location to drop barrel
DelayCommand(9.0, DropTheBoomer(lTarget, OBJECT_SELF)); // drop it like it's hot!
DelayCommand(9.0, SetLocalInt(OBJECT_SELF, "droppedtheboom", 1)); // set to only drop 1 barrel
DelayCommand(9.1, ClearAllActions());
DelayCommand(9.2, ActionMoveAwayFromObject(oPC, TRUE, 20.0)); // run away! run away!
DelayCommand(19.0, TenNineBoom(OBJECT_SELF)); // start the timer
}
}