Author Topic: Effects  (Read 705 times)

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Effects
« on: January 30, 2012, 11:52:02 pm »


               I am a little confused with effects and their usage.

While lexicons says:

A common mistake with this function is to use the following approach to remove, say, a sleep effect:





effect eSleep=EffectSleep();


RemoveEffect(oPC, eSleep);

Some time ago, Whizard showed an example script that is removing the effect via this method and it works. However I was trying to use effect on PC as track for my new poison system I am working on and it didn't worked how I supposed it will.

When I passed the effect eTrack = EffectVisualEffect(666); into my delay function, the effect was never valid in the time of function executed (although the type/subtype was correct but even when the effect was removed from PC). Then I tried
to pass into the function last effect from GetFirst/Next, this time the effect was always valid even when the effect was removed from PC before function executed.

Why it doesn't work? I thought that the effect declared in spellscript is reference same as object. If this is not true why the Whizard's sample code works?

EDIT: finally seems I found out way how to use effect to track something, but that doesnt answer my questions
               
               

               


                     Modifié par ShaDoOoW, 31 janvier 2012 - 12:04 .
                     
                  


            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
Effects
« Reply #1 on: January 31, 2012, 12:06:28 am »


               Without seeing exactly how you set up your code, it's hard to guess.
But, here is why that trick tends to fail:

object oPC = OBJECT_SELF;
//We are creating a NEW EffectSleep object
effect eSleep=EffectSleep();
//Applying the EffectSleep object
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSleep, oPC);

Then, later:

object oPC = OBJECT_SELF;
//Creating a NEW EffectSleep. This is not the same effect as above.
//Similar to spawning a new goblin and expecting it to be the old goblin.
effect eSleep=EffectSleep();
RemoveEffect(oPC, eSleep); //This effect was never applied to oPC


               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Effects
« Reply #2 on: January 31, 2012, 12:20:32 am »


               

ShaDoOoW wrote...

I am a little confused with effects and their usage.

While lexicons says:

A common mistake with this function is to use the following approach to remove, say, a sleep effect:





effect eSleep=EffectSleep();


RemoveEffect(oPC, eSleep);

Some time ago, Whizard showed an example script that is removing the effect via this method and it works. However I was trying to use effect on PC as track for my new poison system I am working on and it didn't worked how I supposed it will.

When I passed the effect eTrack = EffectVisualEffect(666); into my delay function, the effect was never valid in the time of function executed (although the type/subtype was correct but even when the effect was removed from PC). Then I tried
to pass into the function last effect from GetFirst/Next, this time the effect was always valid even when the effect was removed from PC before function executed.

Why it doesn't work? I thought that the effect declared in spellscript is reference same as object. If this is not true why the Whizard's sample code works?

EDIT: finally seems I found out way how to use effect to track something, but that doesnt answer my questions


Yes, This confused me also at the time.  In fact the standard boiware scripts does it the same way.  You just got two thing wrong in your post.  First it was not Whizard that posted the example, though he did confirm the script that AD posted.   Second and more inportant it was not effects that where being dealt with, It was Item Props.

I do not think the method will ever work with effects.
I was suprised however that it worked with iProps.

Here is the thread for refreance.

Stuck on conversation conditional check - help!
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Effects
« Reply #3 on: January 31, 2012, 12:22:12 am »


               what I did was this

effect eTrack = EffectVisualEffect(666);
eTrack = ExtraordinaryEffect(eTrack);
ApplyEffectToObject(PERMANENT,eTrack,oTarget);
DelayCommand(60.0,CheckEffect(oTarget,eTrack));


and

void CheckEffect(object oTarget, effect eTrack)
{
 if(!GetIsEffectValid(eTrack))
 {
 return;
}
//DO something
}

but effect wasn't valid in CheckEffect, if I pushed the last effect found by GetFirst/NextEffect then I get opposite results, effect was always valid

I just found out a way that works when I edited first post:

void CheckEffect(object oTarget, effect eTrack)
{
int bValid = FALSE;
 effect e = GetFirstEffect(oTarget);
  while(GetIsEffectValid(e))
  {
   if(e == eTrack)
   {
   bValid = TRUE;
   break;
   }
  e = GetNextEffect(oTarget);
  }
 if(!bValid) return;
//DO something
}

just doesn't undetstand why
               
               

               


                     Modifié par ShaDoOoW, 31 janvier 2012 - 12:27 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Effects
« Reply #4 on: January 31, 2012, 12:24:19 am »


               

Lightfoot8 wrote...

Yes, This confused me also at the time.  In fact the standard boiware scripts does it the same way.  You just got two thing wrong in your post.  First it was not Whizard that posted the example, though he did confirm the script that AD posted.   Second and more inportant it was not effects that where being dealt with, It was Item Props.

I do not think the method will ever work with effects.
I was suprised however that it worked with iProps.

Here is the thread for refreance.

Stuck on conversation conditional check - help!

It works. Try this function that I created to handle AB bonuses: And it was really Whizard fe months back who came with similar code sample.

//nDurationType - only permanent and temporary, its logical
//may not work properly with linked effect, proper testing is recommended
void ApplyEffectToPCAndHideIcon(int nDurationType, effect eEffect, object oPC, float fDuration=0.0);
void ApplyEffectToPCAndHideIcon(int nDurationType, effect eEffect, object oPC, float fDuration=0.0)
{
ApplyEffectToObject(nDurationType,eEffect,oPC,fDuration);
eEffect = EffectLinkEffects(eEffect,EffectTurnResistanceIncrease(1));
ApplyEffectToObject(nDurationType,eEffect,oPC,fDuration);
RemoveEffect(oPC,eEffect);
}


               
               

               


                     Modifié par ShaDoOoW, 31 janvier 2012 - 12:25 .
                     
                  


            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
Effects
« Reply #5 on: January 31, 2012, 12:36:59 am »


               <painting...>

*Big* difference between effects and visual effects...
As I found out in My very surprised thread

Basically, you can *not* retrieve a visual effect with GetIsEffectValid
(See note in function GetEffectType RemoveEffect). You have to use the *effect creator* to retrieve the effect.

<...outside the lines>
               
               

               


                     Modifié par Rolo Kipp, 31 janvier 2012 - 12:41 .
                     
                  


            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
Effects
« Reply #6 on: January 31, 2012, 12:40:01 am »


               My guess is that it has something to do with the
DelayCommand();
part.

I'd be curious to see if this would still work:

effect eTrack = EffectVisualEffect(666);
eTrack = ExtraordinaryEffect(eTrack);
ApplyEffectToObject(PERMANENT,eTrack,oTarget);
if(!GetIsEffectValid(eTrack))
{
return;
}
//DO something


My guess is that something concerning the effect changes after the script ends.

EDIT: Rolo seems to have figured it out while I was posting.
               
               

               


                     Modifié par wyldhunt1, 31 janvier 2012 - 12:41 .
                     
                  


            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
Effects
« Reply #7 on: January 31, 2012, 12:43:29 am »


               <grinning...>

wyldhunt1 wrote...
...
EDIT: Rolo seems to have figured it out while I was posting.

*Maybe*...
Don't actually know if GetIsEffectValid has the same limitations as GetEffectType :-P

<...ruefully>
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Effects
« Reply #8 on: January 31, 2012, 12:48:08 am »


               

Rolo Kipp wrote...

<painting...>

*Big* difference between effects and visual effects...
As I found out in My very surprised thread

Basically, you can *not* retrieve a visual effect with GetIsEffectValid
(See note in function GetEffectType RemoveEffect). You have to use the *effect creator* to retrieve the effect.

<...outside the lines>

I don't think so. The first link shows that GetIsEffectValid normally returns TRUE for visual effects, GetEffectType also works correctly (even in my sample code unlike GetIsEffectValid).

Effect creator is when you want to know where is this visual effect from. I know that in my scenario as I used special effect creator.
               
               

               


                     Modifié par ShaDoOoW, 31 janvier 2012 - 12:48 .
                     
                  


            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Effects
« Reply #9 on: January 31, 2012, 01:02:12 am »


               I'm not sure on this one, but you might want to check which object was used in the last calling of GetFirstEffect() and GetNextEffect(), these functions may set an object to which GetIsEffectValid() refers.
               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
Effects
« Reply #10 on: January 31, 2012, 01:04:33 am »


               <lighting a...>

Ahh, you are asking why the warning on RemoveEffect?

Your function CheckEffect works because you are passing in the original effect handle eTrack and then comparing it one by one to the list of all effects on the object.

The caution was aimed (if I understand it) at preventing people from creating *new* effect handles and expecting those to equate with a previously applied equivalent effect (i.e. creating a SleepEffect to check if SleepEffect is already on the object.
But each effect object is unique, so it doesn't work.

If that wasn't your question, could you clarify it for me?

And, yes. Visual effects do return as valid effects. That was a silly slip on my part. :-P

<...small taper in his mind>
               
               

               


                     Modifié par Rolo Kipp, 31 janvier 2012 - 01:10 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Effects
« Reply #11 on: January 31, 2012, 01:10:48 am »


               Whizard: GetFirst/NextEffect doesnt ran on anyone else in my testing mod, so this won't be probably it.

Rolo Kipp: I think I know the answer. It seems that both itemproperties and effects are indeed "object constructors". But there is some bug in engine that makes them invalid when passed into delayed function. I just wasn't sure if they ARE constructors because of this bug, but since the workaround check against all effects on PC works, I guess they really ARE. Problem solved.
               
               

               


                     Modifié par ShaDoOoW, 31 janvier 2012 - 01:11 .
                     
                  


            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Effects
« Reply #12 on: January 31, 2012, 01:17:34 am »


               Try adding the bolded line into your previous attempt


void CheckEffect(object oTarget, effect eTrack)
{
effect eWhatever = GetFirstEffect(oTarget);
if(!GetIsEffectValid(eTrack))
 {
 return;
}
//DO something
}


               
               

               
            

Legacy_Rolo Kipp

  • Hero Member
  • *****
  • Posts: 4349
  • Karma: +0/-0
Effects
« Reply #13 on: January 31, 2012, 01:20:46 am »


               <the taper glows...>

Odd.
Wonder what DelayCommand *does* pass and how it differs.
And what else is affected by this besides effects and itemprops.

Thanks for clarifying :-)

<...a little brighter>
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Effects
« Reply #14 on: January 31, 2012, 01:22:27 am »


               Ok, Without tracing it out in the VM,  something I just do not have time to do right now. 

So here are My guess.  

First an effect is nothing more then a structure.  
The Lable for the Effect is nothing more then a pointer that holds the location in memory fo where the first data field is in the Effect Structure.   All other Field entrys will be found from an offset from the begining of the effect structure.
When the Effect is first created several of the Fields are blank.  And do not get filed in untill it is applyed.  i.e. Duration, ExpireDay, ExpireTime.

When you first create the Effect it is located on the stack.

When you Apply the Effect it gets added to the structure of the object you are applying it to. (most likely indirectly)

At this point the Effect is valid. It has not yet expired and is on an object.

Now the Compairison operator does not care where the effects are located and most likely only checks a sub set of the structures fields to see if they match. I dout for one that it checks the lists in the structure to see if the are the same.

Now the GetIsEffectValid would for sure check if the Effect has expired yet of not. I dout the compairson (==) would.

Also the newly created effect is on the stack where the applyed effect is on an object.

For you function passing the effect, well, NWScript only passes Argument by value. so even if you effect is on an object you have just pusjed it right back to the stack with the function call.


Now to you code snipit.

ApplyEffectToObject(nDurationType,eEffect,oPC,fDuration);
eEffect = EffectLinkEffects(eEffect,EffectTurnResistanceIncrease(1));
ApplyEffectToObject(nDurationType,eEffect,oPC,fDuration);
RemoveEffect(oPC,eEffect);


Not suprision that it works you are removing the same effect that you applyed.

Question is would

ApplyEffectToObject(nDurationType,eEffect,oPC,fDuration);
eEffect1 = EffectLinkEffects(eEffect,EffectTurnResistanceIncrease(1));
ApplyEffectToObject(nDurationType,eEffect1,oPC,fDuration);
eEffect2 = EffectLinkEffects(eEffect,EffectTurnResistanceIncrease(1));
RemoveEffect(oPC,eEffect2);

I dout it.
In effect (heh) what you are asking it to do is remove eEffect2 from the stack.
               
               

               


                     Modifié par Lightfoot8, 31 janvier 2012 - 01:27 .