Aller au contenu

Photo

Script not moving to next target


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

#1
Kurziel

Kurziel
  • Members
  • 14 messages
I'm working on a spell that is supposed to place an effect on all qualifying creatures within range of the caster. By ample use of FloatingTextString I have narrowed my problem down to GetNextOjectInShape does not seem to be moving on to the next target.  It reselects the same target.  Here's a stripped down version of my script:

    object oTarget;
    int nElf;
    effect eVis = EffectVisualEffect(VFX_COM_SPECIAL_RED_WHITE);
    
    oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, GetLocation(OBJECT_SELF));
    while(GetIsObjectValid(oTarget))
    {
  nElf = GetRacialType (oTarget);
        if(nElf == RACIAL_TYPE_ELF)
        {
     FloatingTextStringOnCreature ("Test",oTarget);
            ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget, 3.0);
        }
         oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, GetLocation(OBJECT_SELF));
     }


Where have I gone wrong? Should I be using something other than OBJECT_SELF to define the center of the sphere?

Thank you,

Kurziel

#2
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
You could see if it is GetNextObjectInShape() that is truly your problem by switching the definitions of oTarget to

GetFirstObjectInArea() and GetNextObjectInArea()

That will let you know if you are using the function improperly or perhaps one of your arguments does not fit.

It also may help if you posted the entire script.


You also could try to change the location to GetLocation(GetLastCaster()); That should not be any different than OBJECT_SELF, but you could check.


I have also heard that there are sometimes problems with using OBJECT_SELF. Some of the more experienced scripters recommend that you define a variable object oSelf=OBJECT_SELF;
and use oSelf instead of OBJECT_SELF. You could try that.

Nothing serious popped out at me though.

#3
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
You could also spawn an object at location GetLocation(OBJECT_SELF) to make sure it is where you think it is.

#4
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
Does GetRacialType still work well? I know NWN2 added those subtypes, and complicated the whole scheme.

#5
Kurziel

Kurziel
  • Members
  • 14 messages
Thank you for the suggestions,

That is the entire script for the spell at this point, I've only removed the commented out lines and the FloatingText lines I've been using for debugging.

I will try setting the center to a variable and not rely on OBJECT_SELF in the check itself.  If that doesn't work I will try the GetFirstOjectInArea.

The GetLocation(OBJECT_SELF) does seem to be where I think it is, the caster of the spell. What seems to be happening is the GetFirstObjectInShape pulls the caster of the spell, that processes. Then the GetNextObjectInShape pulls the caster of the spell again, processes it again, then exits the loop.

I have tried adjusting the size of the radius. It hasn't made any difference, even while standing right next to other targets (valid and invalid targets). The other targets are never getting selected as oTarget, so they never get processed by the RacialType check.

I will do some testing to make sure GetRacialType is working the way I think it is. But, the truth is, the GetRacialType portion of the script is just a placeholder for what I will be using once I have the "checking everybody in range" portion of it working right.


--Kurziel


edit:  The more I think about it, I bet what's happening is the OBJECT_SELF in the GetNextObject is referring to the object that was just checked, not the original caster of the spell.  I'll let you guys know how it turns out after I get home this evening.

Modifié par Kurziel, 09 février 2012 - 02:48 .


#6
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 598 messages

Kurziel wrote...

Thank you for the suggestions,

That is the entire script for the spell at this point, I've only removed the commented out lines and the FloatingText lines I've been using for debugging.

I will try setting the center to a variable and not rely on OBJECT_SELF in the check itself.  If that doesn't work I will try the GetFirstOjectInArea.

The GetLocation(OBJECT_SELF) does seem to be where I think it is, the caster of the spell. What seems to be happening is the GetFirstObjectInShape pulls the caster of the spell, that processes. Then the GetNextObjectInShape pulls the caster of the spell again, processes it again, then exits the loop.

I have tried adjusting the size of the radius. It hasn't made any difference, even while standing right next to other targets (valid and invalid targets). The other targets are never getting selected as oTarget, so they never get processed by the RacialType check.

I will do some testing to make sure GetRacialType is working the way I think it is. But, the truth is, the GetRacialType portion of the script is just a placeholder for what I will be using once I have the "checking everybody in range" portion of it working right.


--Kurziel


edit:  The more I think about it, I bet what's happening is the OBJECT_SELF in the GetNextObject is referring to the object that was just checked, not the original caster of the spell.  I'll let you guys know how it turns out after I get home this evening.


I think your edit comment is correct. Set lTarget to the location of the caster at the top of the script and use that rather than GetLocation(OBJECT_SELF) inside the loop.

If you want to see a working script I have one here from my Harvest of Chaos campaign:

// i_bb_it_bswd_chaotic_ac
// by Brendan Bellina
// May, 2010

// bb_it_bswd_chaotic OnActivate handler
// This script is executed automatically when the item is activated
// To trigger properly the name of the script MUST be "i_" + itemtag + "_ac"
// Also to make the item usable set Item Property to Cast Spell: Unique Power Self Only

// This will cause all goblinoids within a colossal radius to be charmed for 12 rounds.

// Note: this script runs on the module object, an important consideration for assigning actions.

#include "NW_I0_SPELLS"
#include "x2_inc_spellhook"

void main()
{
object oPC = GetItemActivator();
object oItem = GetItemActivated();

location lTarget = GetLocation(oPC);

object oTarget;
effect eCharm = EffectCharmed();
effect eMind = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_NEGATIVE);
// effect eImpact = EffectVisualEffect(VFX_FNF_LOS_NORMAL_20);
effect eMagExplosion = EffectNWN2SpecialEffectFile("fx_magical_explosion.sef");
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);

effect eLink = EffectLinkEffects(eMind, eCharm);
eLink = EffectLinkEffects(eLink, eDur);

effect eVis = EffectVisualEffect(VFX_IMP_CHARM);

int nRacial;
float fDelay;

int nDuration = 8;

// ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpact, lTarget);
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eMagExplosion, lTarget);

// Declare the spell shape, size and the location. Capture the first target object in the shape.
oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lTarget);
while (GetIsObjectValid(oTarget))
{
if (GetIsEnemy(oTarget, oPC))
{
nRacial = GetRacialType(oTarget);
//Check that the target is a goblin
if (nRacial == RACIAL_TYPE_HUMANOID_GOBLINOID)
{
fDelay = GetDistanceBetweenLocations(lTarget, GetLocation(oTarget))/20;
//Fire cast spell at event for the specified target
SignalEvent(oTarget, EventSpellCastAt(oPC, SPELL_CHARM_PERSON, FALSE));
// NO SPELL RESISTANCE POSSIBLE - Make an SR check
//if (!MyResistSpell(oPC, oTarget))
//{
// NO WILL SAVE POSSIBLE - Make a Will save to negate
//if (!MySavingThrow(SAVING_THROW_WILL, oTarget, GetSpellSaveDC(), SAVING_THROW_TYPE_MIND_SPELLS))
//{
//Apply the linked effects and the VFX impact
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nDuration)));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
//}
//}
}
}
//Get next target in spell area
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_COLOSSAL, lTarget);
}
}

Regards

Modifié par Kaldor Silverwand, 09 février 2012 - 04:55 .


#7
Kurziel

Kurziel
  • Members
  • 14 messages
Well, tried it last night, and I'm completely stumped now. Set the location of the caster to lTarget, and used that to define the shape. Still no go.

Something I realized, based off of my FloatingText debugging comments, it looks like nothing is getting processed through the script until it does the GetNextOjectInShape. Then it marks the caster as the next object, processes him, then drops out of the loop and the script.

I copied and pasted Kaldor's script in place of mine, and that did not function either.

This weekend I'm going to strip everything out of my override directory and retest to make sure I don't have something else causing changes in functionality. My override is mostly models and Racial changes, so I wouldn't think it should be affecting it.

Kurziel

#8
Lugaid of the Red Stripes

Lugaid of the Red Stripes
  • Members
  • 955 messages
I don't know if it's related, but the only time I managed to get a fullstop, do not pass go, crash to desktop, was when I tried to use a GetDistanceBetweenLocations function with a new location I had created from a vector. The new location was good enough to spawn an object, but not to figure distance (so now I spawn a placeable there first, and figure distance from that).

So maybe your 'OBJECT_SELF', whatever that might be, is causing some problem under the hood, so to speak. Try testing it with a more standard object, and see if that works.

#9
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
Fireburst is another spell that is centered on the caster. I looked at the code and the only difference I noticed is that the location of the shape is defined outside of the shape function. Below is the code for reference:

//////////////////////////////
#include "nwn2_inc_spells"


#include "X0_I0_SPELLS"
#include "x2_inc_spellhook"

void main()
{

/*
Spellcast Hook Code
Added 2003-06-20 by Georg
If you want to make changes to all spells,
check x2_inc_spellhook.nss to find out more

*/

if (!X2PreSpellCastCode())
{
// If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
return;
}

// End of Spell Cast Hook


//Declare major variables
object oCaster = OBJECT_SELF;
int nCasterLvl = GetCasterLevel(oCaster);
int nMaxLvl;
if ( nCasterLvl > 5 )
{
nMaxLvl = 5;
}
else
{
nMaxLvl = nCasterLvl;
}
int nDamage;
int nDamage2;
float fDelay;
effect eVis = EffectVisualEffect(VFX_HIT_SPELL_FIRE);
effect eDam,eDam2, eDam3;
//Get the spell target location as opposed to the spell target.
location lTarget = GetSpellTargetLocation();
//Apply the ice storm VFX at the location captured above.
//Declare the spell shape, size and the location. Capture the first target object in the shape.
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lTarget, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
//Cycle through the targets within the spell shape until an invalid object is captured.
while (GetIsObjectValid(oTarget))
{
if (spellsIsTarget(oTarget, SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF) && oTarget != oCaster) //Additional target check to make sure that the caster cannot be harmed by this spell
{
fDelay = GetRandomDelay(0.15, 0.35);
//Fire cast spell at event for the specified target
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_FIREBURST));
if (!MyResistSpell(OBJECT_SELF, oTarget, fDelay))
{

nDamage = d8(nMaxLvl);
nDamage = ApplyMetamagicVariableMods(nDamage, nMaxLvl * 8);
nDamage = GetReflexAdjustedDamage(nDamage, oTarget, GetSpellSaveDC(), SAVING_THROW_TYPE_FIRE);
/*int nSave = ReflexSave(oTarget, GetSpellSaveDC(), SAVING_THROW_TYPE_FIRE, OBJECT_SELF);

if (nSave == 2)
{
return;
}
else if (nSave == 1)
{
nDamage = nDamage/2;
}
else
{
nDamage = nDamage;
}*/

if ( nDamage > 0 )
{
//Set the damage effect
eDam = EffectDamage(nDamage, DAMAGE_TYPE_FIRE);
// Apply effects to the currently selected target.
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
//This visual effect is applied to the target object not the location as above. This visual effect
//represents the impact that erupts on the target not on the ground.
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
}
/*//Roll damage for each target
nDamage = d8(nMaxLvl);
//Resolve metamagic
nDamage = ApplyMetamagicVariableMods(nDamage, nMaxLvl * 8);
nDamage2 = nDamage;
nDamage2 = GetReflexAdjustedDamage(nDamage/2, oTarget, GetSpellSaveDC(), SAVING_THROW_TYPE_FIRE);
nDamage = nDamage/2 + nDamage2;
if ( nDamage > 0 )
{
//Set the damage effect
eDam = EffectDamage(nDamage, DAMAGE_TYPE_FIRE);
// Apply effects to the currently selected target.
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
//This visual effect is applied to the target object not the location as above. This visual effect
//represents the impact that erupts on the target not on the ground.
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
} */
}
}
//Select the next target within the spell shape.
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lTarget, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
}
}

#10
Kurziel

Kurziel
  • Members
  • 14 messages
*sigh*

Well, I feel like a ****** now. While going over everything with a fine tooth comb, I found part of my problem. I completely spaced out that the FloatingTextStringOnCreature I was using as a debug aid, by default is only visible to the same faction.

So, my while loop, location definition, target choices, and use of GetFirst/NextObjectInShape is all working as intended. I just have to figure out why it's not applying the effect I want.

Thanks for the help and suggestions everybody offered.

--Kurziel

Modifié par Kurziel, 12 février 2012 - 12:22 .


#11
M. Rieder

M. Rieder
  • Members
  • 2 530 messages
Is it just a visual effect or something else? If it is just a visual effect, try some of the special effect files with the function EffectNWN2SpecialEffectFile(). If you have powerbar you can just browse the VFX and copy and paste into code. If you don't have powerbar, just look at the visual effects field in properties tab of a creature and mess with what is there, then copy into code.

#12
Kurziel

Kurziel
  • Members
  • 14 messages
Ah... wonderful. Got it, now I can move on to the next step.

Thank you very much.