Author Topic: Effects  (Read 706 times)

Legacy_Shadooow

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


               Thanks for clarification LightFoot8, that makes sense.

WhiZard wrote...

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
}


just tried, still invalid
               
               

               


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


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Effects
« Reply #16 on: January 31, 2012, 01:31:56 am »


               

ShaDoOoW wrote...

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.


They're structs. Take a look at nwnx_structs. DelayCommanding them, among other things, strips their spell ids.

Why are you trying to do what you're doing in the OP, anyway?

Funky
               
               

               
            

Legacy_Lightfoot8

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


               One clairification on my post above.  I should have said that all custom functions pass arguments by value.   The internal functions play by there own rules.
               
               

               
            

Legacy_Shadooow

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


               

FunkySwerve wrote...

ShaDoOoW wrote...

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.


They're structs. Take a look at nwnx_structs. DelayCommanding them, among other things, strips their spell ids.

Why are you trying to do what you're doing in the OP, anyway?

Funky

This is part of my new poison system to be included with next Patch beta version. This system allows to stack poisons as by default when there is poison effect no other poisons can be applied anymore. I don't think its possible to do without passing the poison effect applied to PC as its possible to heal poison effects.

void SecondaryDamage(object oTarget, int nPoisonID, effect eTrack)
{
 if(GetIsObjectValid(oTarget))
 {
 int bCured = TRUE;
 effect e = GetFirstEffect(oTarget);
  while(GetIsEffectValid(e))
  {
   if(e == eTrack)
   {
   bCured = FALSE;
   break;
   }
  e = GetNextEffect(oTarget);
  }
  if(bCured)
  {
  return;
  }
 int nDC = StringToInt(Get2DAString("poison","Save_DC",nPoisonID));
  if(!FortitudeSave(oTarget,nDC,SAVING_THROW_TYPE_POISON,OBJECT_INVALID))
  {
  SendMessageToPCByStrRef(oTarget,66947);
  int nVFX = VFX_IMP_POISON_S;
  if(Get2DAString("poison","VFX_Impact",nPoisonID) == "VFX_IMP_POISON_L")
   {
   nVFX = VFX_IMP_POISON_L;
   }
  ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectVisualEffect(nVFX),oTarget);
  string s2DA = Get2DAString("poison","Default2",nPoisonID);
   if(s2DA == "" || s2DA == "****")
   {
   s2DA = Get2DAString("poison","Script_2",nPoisonID);
   ExecuteScript(s2DA,oTarget);
   return;
   }
  int nAbility = ABILITY_CONSTITUTION;
   if(s2DA == "DEX") nAbility = ABILITY_DEXTERITY;
   else if(s2DA == "STR") nAbility = ABILITY_STRENGTH;
   else if(s2DA == "WIS") nAbility = ABILITY_WISDOM;
   else if(s2DA == "INT") nAbility = ABILITY_INTELLIGENCE;
   else if(s2DA == "CHA") nAbility = ABILITY_CHARISMA;
  int nDice = StringToInt(Get2DAString("poison","Dice2",nPoisonID));
  int nDamage, nDam = StringToInt(Get2DAString("poison","Dam2",nPoisonID));
   do
   {
   nDamage+= Random(nDice)+1;
   }while(--nDam > 0);
   if(nDamage < 1) nDamage = 0;//sanity check
  ApplyEffectToObject(DURATION_TYPE_PERMANENT,ExtraordinaryEffect(EffectAbilityDecrease(nAbility,nDamage)),oTarget);
  }
 }
 else
 {
 DelayCommand(60.0,SecondaryDamage(oTarget,nPoisonID,eTrack));
 }
}

void Apply1stPoison(object oTarget, int nPoisonID)
{
effect e = GetFirstEffect(oTarget);
 while(GetIsEffectValid(e))
 {
  if(GetEffectType(e) == EFFECT_TYPE_POISON)
  {
  effect ePoison = EffectVisualEffect(VFX_DUR_CESSATE_NEUTRAL);
//  eTrack = ExtraordinaryEffect(eTrack);
//  ApplyEffectToObject(DURATION_TYPE_PERMANENT,eTrack,oTarget);
  string s2DA = Get2DAString("poison","Default1",nPoisonID);
   if(s2DA != "" && s2DA != "****")
   {
   int nAbility = ABILITY_CONSTITUTION;
    if(s2DA == "DEX") nAbility = ABILITY_DEXTERITY;
    else if(s2DA == "STR") nAbility = ABILITY_STRENGTH;
    else if(s2DA == "WIS") nAbility = ABILITY_WISDOM;
    else if(s2DA == "INT") nAbility = ABILITY_INTELLIGENCE;
    else if(s2DA == "CHA") nAbility = ABILITY_CHARISMA;
   int nDice = StringToInt(Get2DAString("poison","Dice1",nPoisonID));
   int nDamage, nDam = StringToInt(Get2DAString("poison","Dam1",nPoisonID));
    do
    {
    nDamage+= Random(nDice)+1;
    }while(--nDam > 0);
    if(nDamage < 1) nDamage = 0;//sanity check
   ePoison = EffectLinkEffects(ePoison,EffectAbilityDecrease(nAbility,nDamage));
   ePoison = ExtraordinaryEffect(ePoison);
   }
  ApplyEffectToObject(DURATION_TYPE_PERMANENT,ePoison,oTarget);
   if(GetLocalInt(GetModule(),"71_ALLOW_POISON_STACKING") == TRUE || GetGameDifficulty() == GAME_DIFFICULTY_DIFFICULT)
   {
   RemoveEffect(oTarget,e);
   DelayCommand(60.0,SecondaryDamage(oTarget,nPoisonID,ePoison));
   }
   else if(GetEffectSubType(e) == SUBTYPE_MAGICAL)
   {
   effect eCopy = ExtraordinaryEffect(e);
   RemoveEffect(oTarget,e);
   AssignCommand(OBJECT_SELF,ApplyEffectToObject(DURATION_TYPE_PERMANENT,eCopy,oTarget));
   }
  return;
  }
 e = GetNextEffect(oTarget);
 }
}


               
               

               


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


            

Legacy_WhiZard

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


               

Lightfoot8 wrote...
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.


I tried a stacking effect as shown below

void main()
{
object oPC = OBJECT_SELF;
effect eEffect = EffectRegenerate(5, 1.0);
eEffect = EffectLinkEffects(eEffect,EffectRegenerate(1, 1.0));
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eEffect,OBJECT_SELF);
//RemoveEffect(oPC,eEffect);
effect eEffect1 = EffectLinkEffects(eEffect,EffectRegenerate(2, 1.0));
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eEffect1,OBJECT_SELF);
effect eEffect2 = EffectLinkEffects(eEffect1,EffectRegenerate(3, 1.0));
//RemoveEffect(oPC,eEffect2);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eEffect2,OBJECT_SELF);
}


This passes three regenerations
1: 5, 1
2: 5, 1, 2
3: 5, 1, 2, 3

When the first remove effect is uncommented the first regeneration only  is stopped.
When the last remove effect is uncommented only the last regeneration is stopped.


EDIT: Last line of code didn't copy
DOUBLE EDIT: The regen icon got lost on the first one, though the regen of 2 and 3 were still in place.
               
               

               


                     Modifié par WhiZard, 31 janvier 2012 - 02:28 .
                     
                  


            

Legacy_Lightfoot8

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


               Interesting, Not sure I can explain that one at the moment.
               
               

               
            

Legacy_WhiZard

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


               Here is actually a good script that demonstrates that RemoveEffect() actually performs a loop removing all effects that are from the same calling.

void main()
{
object oPC = OBJECT_SELF;
effect eEffect = EffectRegenerate(5, 1.0);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eEffect,OBJECT_SELF);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eEffect,OBJECT_SELF);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eEffect,OBJECT_SELF);
DelayCommand(3.0, RemoveEffect(oPC,eEffect));
}
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Effects
« Reply #22 on: January 31, 2012, 02:38:20 am »


               Does it actually apply the effect three times in that case?

[Edit]
The reason I ask is that there is an item property function that will not add similar properties to an item unless you tell it to do so. So I wonder if Apply EffectToObject is similar in that it opts not to add the same effect with same subproperties more than once.
               
               

               


                     Modifié par henesua, 31 janvier 2012 - 02:40 .
                     
                  


            

Legacy_Lightfoot8

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


               I have no problem with that one.
               
               

               
            

Legacy_WhiZard

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


               

henesua wrote...

Does it actually apply the effect three times in that case?

[Edit]
The reason I ask is that there is an item property function that will not add similar properties to an item unless you tell it to do so. So I wonder if Apply EffectToObject is similar in that it opts not to add the same effect with same subproperties more than once.


Regeneration is nice in that it stack in all sorts of ways.  Regeneration is applied multiple times whether effect or item property.  The IPSafe...() commands are BioWare's way of self cleaning which involve first checking whether there is an item property there that shares certain traits.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Effects
« Reply #25 on: January 31, 2012, 02:52:33 am »


               @henesua  open up   x2_inc_itemprop and you will see that IPSafeAddItemProperty is just a wrapper around AddItemProperty to control how it is added.
               
               

               
            

Legacy_Knight_Shield

  • Hero Member
  • *****
  • Posts: 812
  • Karma: +0/-0
Effects
« Reply #26 on: September 02, 2013, 09:59:26 pm »


               I know its been awhile in this but if you guys could look at how I added haste.



#include "zep_inc_phenos"
#include "x2_inc_switches"
void main()
{
   int nEvent = GetUserDefinedItemEventNumber();
   if (nEvent != X2_ITEM_EVENT_ACTIVATE) return;

   effect eEffect;
   eEffect = EffectHaste();
   object oPC = GetItemActivator();
   int nMount = nCEP_PH_HORSE_BLACK;
   int iMounted = GetLocalInt(oPC, "Mounted");

   if (iMounted == 0)
   {
       zep_Mount(oPC, OBJECT_INVALID, nMount);
       SetLocalInt(oPC, "Mounted", 1);
       ApplyEffectToObject(DURATION_TYPE_PERMANENT,eEffect,oPC);
   }

   else
   {
       zep_Dismount(oPC);
       SetLocalInt(oPC, "Mounted", 0);
       if (GetEffectType(eEffect)==EFFECT_TYPE_HASTE) RemoveEffect(oPC, eEffect);
       eEffect = GetNextEffect(oPC);
   }
}
               
               

               


                     Modifié par Knight_Shield, 02 septembre 2013 - 09:02 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Effects
« Reply #27 on: September 02, 2013, 10:29:02 pm »


               first this line: if (GetEffectType(eEffect)==EFFECT_TYPE_HASTE) will be always true, you just defined the effect as EffectHaste

second this cannot work, or does it work? - to be able to remove effect this way you have to pass the effect variable some way between scripts - like i did in a example few posts back, in your situation, you have to loop all effects and remove haste effect - which will be a problem since it can remove other haste effects the player might have - either make the effect supernatural/extraordinary (which probably should be anyway) and check the duration permanent subtype extra/super or use the item as a creator (remember you cannot define the effect in script but must be in the assigncommand line then) and then check effects for creator of item tag
               
               

               
            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Effects
« Reply #28 on: September 07, 2013, 12:17:01 pm »


               I might be a little late but something like so perhaps?:


#include "zep_inc_phenos"
#include "x2_inc_switches"
void main()
{
       int nEvent = GetUserDefinedItemEventNumber();
       if (nEvent != X2_ITEM_EVENT_ACTIVATE) return;

       effect eEffect;
       object oPC = GetItemActivator();
       object oItem = GetItemActivated();
       int nMount = nCEP_PH_HORSE_BLACK;
       int iMounted = GetLocalInt(oPC, "Mounted");

       if (iMounted == 0)
        {
              zep_Mount(oPC, OBJECT_INVALID, nMount);
              SetLocalInt(oPC, "Mounted", 1);
              AssignCommand(oItem, ApplyEffectToObject(DURATION_TYPE_PERMANENT,EffectHaste(),oPC));
        }

       else
        {
              zep_Dismount(oPC);
              SetLocalInt(oPC, "Mounted", 0);
              eEffect = GetFirstEffect(oPC);
              while (GetIsEffectValid(eEffect))
                {
                     if (GetEffectCreator(eEffect)==oItem)
                     RemoveEffect(oPC, eEffect);
                     eEffect = GetNextEffect(oPC);
                }
        }
}
               
               

               


                     Modifié par GhostOfGod, 07 septembre 2013 - 11:17 .
                     
                  


            

Legacy_Knight_Shield

  • Hero Member
  • *****
  • Posts: 812
  • Karma: +0/-0
Effects
« Reply #29 on: September 07, 2013, 04:19:05 pm »


               Works great.
I have one more question.
How can I force them to dismount and remove effect?

void main()
{

object oPC = GetEnteringObject();

if (!GetIsPC(oPC)) return;

if (GetLocalInt(oPC, "Mounted")== 1)
  {

       //force dismount//
       zep_Dismount(oPC);
        SetLocalInt(oPC, "Mounted", 0);
   }
}