Aller au contenu

Photo

AOE Heartbeat Script Not firing - this one is either simple or whacked out (Solved)


  • Veuillez vous connecter pour répondre
8 réponses à ce sujet

#1
Morbane

Morbane
  • Members
  • 1 883 messages
 I have a custom AOE defined in VFX_Persistent.2da - the AOE enter script fires just fine and so does the exit script - but the HB fizzles :pinched:

Script in next post to avoid the paste/format mess.

(It was the simple path)=]

Modifié par Morbane, 27 avril 2012 - 07:55 .


#2
Morbane

Morbane
  • Members
  • 1 883 messages
#include "a_const_include"
#include "nw_i0_spells"
void main()
{
object oTarget = GetFirstInPersistentObject();
object oCaster = GetAreaOfEffectCreator();

if(GetLocalInt(oTarget, "resisted") == TRUE)
{
SendMessageToPC(GetFirstPC(), GetName(oTarget) + " Is Not Enthralled");
return;
}
int nDC = 24;

while(GetIsObjectValid(oTarget))
{
if(GetIsEnemy(oTarget, oCaster))
{

SendMessageToPC(GetFirstPC(), GetName(oTarget) + " HB Fired");

if(spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, oCaster))
{
SignalEvent(oTarget, EventSpellCastAt(oCaster, Spell_Draining_Melody));

if(MySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_MIND_SPELLS))
{
SendMessageToPC(GetFirstPC(), GetName(oTarget) + " Resisted AOE");
SetLocalInt(oTarget, "resisted", TRUE);
return;
}

effect eDazed = EffectDazed();
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDazed, oTarget, RoundsToSeconds(9));

int nNeg = d2();

if(!MySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_MIND_SPELLS))
{
SendMessageToPC(GetFirstPC(), GetName(oTarget) + " Is Enthralled");
effect eThrall = EffectNegativeLevel(nNeg);
eThrall = SupernaturalEffect(eThrall);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eThrall, oTarget);
SendMessageToPC(GetFirstPC(), GetName(oTarget) + " Suffers a Level Drain :" + IntToString(nNeg));
}
SendMessageToPC(GetFirstPC(), GetName(oCaster) + " Pre Soak HP :" + IntToString(GetMaxHitPoints(oCaster)));

effect eSoak = EffectBonu****points(nNeg * 5);
effect eBal = EffectHeal(nNeg * 5);
effect eLink = EffectLinkEffects(eBal, eSoak);

ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oCaster, HoursToSeconds(1));

SendMessageToPC(GetFirstPC(), GetName(oCaster) + " Post Soak HP :" + IntToString(GetMaxHitPoints(oCaster)));

if(GetTotalLevels(oTarget, TRUE) <= 1)
{
effect eZero = EffectDeath();
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eZero, oTarget);
SendMessageToPC(GetFirstPC(), GetName(oTarget) + " has been Drained of all Life.");
}
}
}
oTarget = GetNextInPersistentObject(oTarget);
}
}

Modifié par Morbane, 26 avril 2012 - 09:00 .


#3
kevL

kevL
  • Members
  • 4 078 messages
uh, might be

if(GetIsEnemy(oTarget, oCaster))
{
//  oTarget = GetNextInPersistentObject(oTarget);


( then oTarget repeats again down at the bottom )

#4
Morbane

Morbane
  • Members
  • 1 883 messages
I threw that in because I was thinking that the oCaster was somehow registering as oTarget as well - but either way with or without oTarget = GetNextInPersistentObject(oTarget); near the top, the HB does not work correctly/ does not fire - my first message never comes up...SendMessageToPC(GetFirstPC(), GetName(oTarget) + " HB Fired");

Also I am testing with a low level PC so I can be sure the save will always fail.

Edit: Removed the oTarget = GetNextInPersistentObject(oTarget); from the top section and retested - no go...

Modifié par Morbane, 26 avril 2012 - 09:02 .


#5
kevL

kevL
  • Members
  • 4 078 messages
okay ... uh, GetIsEnemy(oTarget, oCaster) should prevent the caster from being affected.

and, I think GetFirst/NextInPersistentObject( ) should be left with the default values, not (oTarget) ..


Next, set your first debug message to the very top w/ no conditions, use like

object oDebug = GetFirstPC(FALSE);
SendMessageToPC(oDebug, "The script fires!!");

right after void main(){

- other than that, check vfx_persistent.2da for a typo .... :\\

#6
Dann-J

Dann-J
  • Members
  • 3 161 messages
I've never used the persistent object functions. I prefer to use spell shape (sphere) in my custom AOE scripts. Mostly because I'm more familiar with it though. It does however let you determine the search radius, whether or not you want to use line-of-sight, and you can use an object filter.

Most spell scripts I've looked at check both for GetIsEnemy AND not-caster. I don't know if that's overly cautious, but I usually follow the trend.

#7
kevL

kevL
  • Members
  • 4 078 messages

DannJ wrote...

Most spell scripts I've looked at check both for GetIsEnemy AND not-caster. I don't know if that's overly cautious, but I usually follow the trend.

it's a good idea, i've seen anomalies too when not doing !Caster on that if()

Modifié par kevL, 26 avril 2012 - 10:38 .


#8
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
object oTarget = GetFirstInPersistentObject();
while(GetIsObjectValid(oTarget))
{ 

oTarget = GetNextInPersistentObject();
}

Like kevl says the parameter should be the object, which is the AOE, not the target or the caster. ( OBJECT_SELF is the AOE, which is what is used when nothing is entered, you have oTarget which is borking it out on the second pass, which only works IF the oTarget is another AOE )

Above code is copied from entangle which I KNOW is working fine. Never seen an issue with it, but it might have issues if it's not created from a spell - i redid a lot of the engine functions which might be getting wonky on you.

It will include the caster and everything else, so != oCaster and Enemy checks as needed ( if you are set to easy difficulty functions deal with that so it can hurt allies as well ).

Here is my doxygen for it

/** 
* Get the first object within oPersistentObject.
* @onerror Returns OBJECT_INVALID if no object is found.
* @param oPersistentObject ( DEFAULT: OBJECT_SELF  )
* @param nResidentObjectType OBJECT_TYPE_* ( DEFAULT: OBJECT_TYPE_CREATURE  )
* @param nPersistentZone PERSISTENT_ZONE_ACTIVE. This could also take the value PERSISTENT_ZONE_FOLLOW, but this is no longer used. ( DEFAULT: PERSISTENT_ZONE_ACTIVE )
* @return 
*/
object GetFirstInPersistentObject(object oPersistentObject=OBJECT_SELF, int nResidentObjectType=OBJECT_TYPE_CREATURE, int nPersistentZone=PERSISTENT_ZONE_ACTIVE);


/** 
* Get the next object within oPersistentObject.
* @onerror Returns OBJECT_INVALID if no object is found.
* @param oPersistentObject ( DEFAULT: OBJECT_SELF  )
* @param nResidentObjectType OBJECT_TYPE_* ( DEFAULT: OBJECT_TYPE_CREATURE  )
* @param nPersistentZone PERSISTENT_ZONE_ACTIVE. This could also take the value PERSISTENT_ZONE_FOLLOW, but this is no longer used. ( DEFAULT: PERSISTENT_ZONE_ACTIVE )
* @return 
*/
object GetNextInPersistentObject(object oPersistentObject=OBJECT_SELF, int nResidentObjectType=OBJECT_TYPE_CREATURE, int nPersistentZone=PERSISTENT_ZONE_ACTIVE);


Modifié par painofdungeoneternal, 26 avril 2012 - 10:53 .


#9
Morbane

Morbane
  • Members
  • 1 883 messages
YEP! passing oTarget was the borker! Dont know why I did that in the while loop when I did not do it in the original assignment of oTarget...

Thanks KevL and Pain