Author Topic: vfx_persistent  (Read 701 times)

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
vfx_persistent
« on: June 16, 2011, 06:23:56 pm »


               Ok is there a way to find the vfx persistent ID?

Is it possible to run all the heartbeat, enter, exit scripts through say with only three scripts? One for each type.
Just trying to save on resources of having the edited scripts.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
vfx_persistent
« Reply #1 on: June 16, 2011, 06:43:18 pm »


               no but AOE tag = LABEL collumn in 2da

It is possible but might not be very safe. I mean you would have to differ the scripts somehow, that is check for getisvalid - entering/exiting if entering -> enter if exiting -> exit if none -> heartbeat but im not very sure if really both wont be valid in heartbeat. If that would be the case you would have to run heartbeat via ExecuteScript.

So you should try to download my patch, all AOEs there are running the heartbeat script via ExecuteScript already (to work on servers with HB/clock issues).
               
               

               
            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
vfx_persistent
« Reply #2 on: June 16, 2011, 07:02:26 pm »


               Well I know about the tag check, that what I was experimenting with. I was going to run them as custom functions. Well if I point to the three seperate scripts in the 2da that cuts down the checks. Right? I more worried about multiple effect running in a area getting mixed up. Have you tested multiple effects with your patch? Thanks you for the information. I take a look at your patch also when I get some time. '<img'>
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
vfx_persistent
« Reply #3 on: June 16, 2011, 07:05:48 pm »


               

ShadowM wrote...

I more worried about multiple effect running in a area getting mixed
up. Have you tested multiple effects with your patch?

I dont know what you mean.
               
               

               
            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
vfx_persistent
« Reply #4 on: June 16, 2011, 07:20:54 pm »


               Sorry it hard for me to explain, but I figure it out sorry for the trouble.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
vfx_persistent
« Reply #5 on: June 16, 2011, 07:29:15 pm »


               

ShadowM wrote...

Ok is there a way to find the vfx persistent ID?

vfx_persistent.2da, the LABEL column:

                                                                                                                                                                                                                                                                                                                                                                                                                                                               
           LABEL                            SHAPE   RADIUS   WIDTH  
LENGTH   ONENTER            ONEXIT             HEARTBEAT         
OrientWithGround   DurationVFX   MODEL01            MODEL02           
MODEL03            NUMACT01   NUMACT02   NUMACT03   DURATION01  
DURATION02   DURATION03   EDGEWGHT01   EDGEWGHT02   EDGEWGHT03  
SoundImpact    SoundDuration    SoundCessation   SoundOneShot  
SoundOneShotPercentage   MODELMIN01       MODELMIN02      
MODELMIN03         

0          VFX_PER_FOGACID                  C       5        ****   
****     NW_S0_AcidFogA     NW_S0_AcidFogB     NW_S0_AcidFogC    
0                  ****          vps_fogacid        vps_fogacid       
vps_fogacid        5          10         5          3400        
1100         1900         0            0.25         0.25        
****           sps_fog_loop     ****             sps_fog       
0.3                      vps_fogacid_L    vps_fogacid_L   
vps_fogacid_L      

1          VFX_PER_FOGFIRE                  C       5        ****   
****     NW_S0_IncCloudA    NW_S0_IncCloudB    NW_S0_IncCloudC   
0                  ****          vps_fogfire        vps_fogfire       
vps_fogfire        5          5          5          3400        
1100         1900         0            0            0.25        
****           sps_fog_loop     ****             sps_fogfire   
0.3                      vps_fogfire_L    vps_fogfire_L   
vps_fogfire_L      

2          VFX_PER_FOGSTINK                 C       6.7      ****   
****     NW_S0_StinkCldA    ****               NW_S0_StinkCldC   
0                  ****          vps_fogstink       vps_fogstink      
vps_fogstink       5          5          5          3400        
1100         1900         0            0            0.25        
****           sps_fog_loop     ****             sps_fog       
0.3                      vps_fogstink_L   vps_fogstink_L  
vps_fogstink_L     

3          VFX_PER_FOGKILL     
*snip*

Occasionally more than one spell will use the same paoe object tag, so you'll want to set spell id on them after they're cast, searching for the nearest aoe of the proper tag without a set spell id.

Is it possible to run all the heartbeat, enter, exit scripts through say with only three scripts? One for each type.
Just trying to save on resources of having the edited scripts.


Yes, though you're likely going to be better off with a more nuanced approach, depending on your needs. Here's our centralized paoe include, which at least keeps script sizes down, and eliminates duplicative code. Unlike most include scripts you'll see on these boards, the main() function is in the include, and the spell scripts contain plug-in functions - I'll show you a sample one. Also, I should note that this approach makes the aoe scripts unnecessary, because everything is handled in the pseudoheartbeat. First, the include:


#include "hg_inc"

#include "ac_spell_inc"



int GetIsHeraldAoE(object oAoE) {

    string sTag = GetTag(oAoE);

    if (sTag == "VFX_PER_FOGFREEZE"     ||

        sTag == "VFX_AOE_CONSECRATE_20" ||

        sTag == "VFX_PER_FOGACID"       ||

        sTag == "VFX_PER_FOGKILL"       ||

        sTag == "VFX_PER_FOGMIND"       ||

        sTag == "VFX_PER_FOGSTINK")

        return TRUE;



    return FALSE;

}



struct SpellInfo GetPersistentAoESpellInfo ();



int GetPersistentAoELimit (struct SpellInfo si);

int GetPersistentAoEEffect (struct SpellInfo si);

string GetPersistentAoETag (struct SpellInfo si);

string GetPersistentAoEName (struct SpellInfo si);

int GetPersistentAoETargetMask (struct SpellInfo si);

int GetPersistentAoETargetType (struct SpellInfo si);



float GetPersistentAoEDuration (struct SpellInfo si);



effect GetPersistentAoEImpactEffect (struct SpellInfo si);

effect GetPersistentAoEDurationEffect (struct SpellInfo si);

effect GetPersistentAoEVisualEffect (struct SpellInfo si);



void ApplyAoEEffect (struct SpellInfo si, object oAoE, object oTarget, effect eEff, effect eDur, effect eVis);





float GetPersistentAoERemaining (object oAoE) {

    int nRemaining = GetLocalInt(oAoE, "AoEExpires") - GetLocalInt(GetModule(), "uptime");



    return IntToFloat(nRemaining < 1 ? 1 : nRemaining);

}





void DoAoEHeartbeat (struct SpellInfo si, object oAoE, effect eEff, effect eDur, effect eVis) {

    int bDestroy = FALSE, bAllPCs = FALSE;



    if (!GetIsObjectValid(oAoE))

        return;





    /* Storm of Vengeance doesn't destroy properly sometimes */

    if (GetPersistentAoEEffect(si) == AOE_PER_STORM) {

        if (si.id == SPELL_STORM_OF_VENGEANCE && GetLocalInt(GetArea(oAoE), "Area_Underwater"))

            bAllPCs = TRUE;



        if (GetLocalInt(GetModule(), "uptime") > GetLocalInt(oAoE, "AoEExpires"))

            bDestroy = TRUE;

    }



    if (bDestroy                     ||

        !GetIsObjectValid(si.caster) ||

        GetIsDead(si.caster)         ||

        GetArea(si.caster) != si.area) {



        SetPlotFlag(oAoE, FALSE);

        DestroyObject(oAoE);

        return;

    }



    DelayCommand(6.0, DoAoEHeartbeat(si, oAoE, eEff, eDur, eVis));

    AddLocalInt(oAoE, "AoERounds", 1);



    if (!LineOfSightObject(oAoE, si.caster))//PAoEs have no effect when caster out of LoS

        return;





    si.target = oAoE;

    int nMask = GetPersistentAoETargetMask(si);

    int nType = GetPersistentAoETargetType(si);



    for (si.target = GetFirstInPersistentObject(oAoE, nMask);

         GetIsObjectValid(si.target);

         si.target = GetNextInPersistentObject(oAoE, nMask)) {



        if (GetIsSpellTarget(si, si.target, nType) || (bAllPCs && GetIsPC(si.target))) {

            SignalEvent(si.target, EventSpellCastAt(si.caster, si.id));



            AssignCommand(si.caster, DelayCommand(GetRandomDelay(0.5,
4.5), ApplyAoEEffect(si, oAoE, si.target, eEff, eDur, eVis)));

        }

    }

}



void StartAoEHeartbeat (struct SpellInfo si, string sTag, effect eEff, effect eDur, effect eVis, int nUntil) {

    int nCount = 1;

    object oLoc, oAoE;



    do {

        oLoc = GetNearestObjectToLocation(OBJECT_TYPE_ALL, si.loc, nCount++);

    } while (GetTag(oLoc) == sTag);



    nCount = 1;

    oAoE = GetNearestObjectByTag(sTag, oLoc);



    while (GetIsObjectValid(oAoE)) {

        if (GetAreaOfEffectCreator(oAoE) == si.caster && !GetLocalInt(oAoE, "AoEHeartbeat")) {



            SetLocalInt(oAoE, "AoEHeartbeat", 1);

            SetLocalInt(oAoE, "AoEExpires", nUntil);

            SetLocalInt(oAoE, "AoESP", si.sp);



            DelayCommand(0.0, DoAoEHeartbeat(si, oAoE, eEff, eDur, eVis));

            return;

        }



        oAoE = GetNearestObjectByTag(sTag, oLoc, ++nCount);

    }

}



void main () {

    struct SpellInfo si = GetPersistentAoESpellInfo();

    if (si.id < 0)

        return;



    float fDur  = GetPersistentAoEDuration(si);

    string sTag = GetPersistentAoETag(si);

    effect eAoE = EffectAreaOfEffect(GetPersistentAoEEffect(si),

        (si.id == SPELL_GREASE ? "nw_s0_greasea" : "****"), "****", "****");





    int nLimit = GetPersistentAoELimit(si);



    if (nLimit > 0) {

        int nFound = 0, nCount = 1;

        object oOther, oCreator, oArea = GetArea(si.caster);



        while (GetIsObjectValid(oOther = GetNearestObjectByTag(sTag, si.caster, nCount++))) {

            oCreator = GetAreaOfEffectCreator(oOther);

            if (oCreator == oArea                                       ||

                GetLocalInt(oOther, "NoAoEDispel"))

                continue;



            if (GetIsPC(si.caster) && GetIsPC(oCreator)) {

                if (GetIsHeraldAoE(oOther)) {

                    if (!GetIsQuasiclass(QUASIclass_HERALD_OF_STORMS, oCreator))

                        nFound++;

                } else

                    nFound++;

            } else if (GetFactionEqual(si.caster, oCreator)) {

                nFound++;

            }



            if (nFound >= nLimit) {

                SetPlotFlag(oOther, FALSE);

                DestroyObject(oOther);



                if (nFound == nLimit)

                    FloatingTextStringOnCreature("To prevent lag, only " +

                        IntToString(nLimit) + " " + GetPersistentAoEName(si) +

                        " spell" + (nLimit == 1 ? "" : "s") + " may exist in an area at the same time.", si.caster);

            }

        }

    } else if (nLimit == -1) {

        object oAoE, oCreator, oArea = GetArea(si.caster);



        for (oAoE = GetFirstObjectInArea(oArea); GetIsObjectValid(oAoE); oAoE = GetNextObjectInArea(oArea)) {



            oCreator = GetAreaOfEffectCreator(oAoE);

            if (GetObjectType(oAoE) != OBJECT_TYPE_AREA_OF_EFFECT ||

                oCreator != si.caster)

                continue;



            if (GetIsQuasiclass(QUASIclass_HERALD_OF_STORMS, oCreator)
&& //heralds ignore herald spells in this check - that limit
handled in -2

                GetIsHeraldAoE(oAoE))

                continue;



            if (FindSubString(" VFX_PER_FOGACID VFX_PER_FOGFIRE
VFX_PER_FOGFREEZE VFX_PER_STORM VFX_PER_RAINFIRE VFX_PER_RAINFREEZE
VFX_AOE_CONSECRATE_20 ",

                              " " + GetTag(oAoE) + " ") >= 0) {

                SetPlotFlag(oAoE, FALSE);

                DestroyObject(oAoE);



                FloatingTextStringOnCreature("Only one area of effect
damage field may exist per caster in an area at the same time.",
si.caster);

            }

        }

    } else if (nLimit == -2) {

        object oAoE, oArea = GetArea(si.caster);

        int nFound;

        for (oAoE = GetFirstObjectInArea(oArea); GetIsObjectValid(oAoE); oAoE = GetNextObjectInArea(oArea)) {

            if (GetObjectType(oAoE) != OBJECT_TYPE_AREA_OF_EFFECT ||

                !GetIsQuasiclass(QUASIclass_HERALD_OF_STORMS, GetAreaOfEffectCreator(oAoE)))

                continue;



            if (FindSubString(" VFX_PER_FOGACID VFX_PER_FOGSTINK
VFX_PER_FOGKILL VFX_AOE_CONSECRATE_20 VFX_PER_FOGFREEZE VFX_PER_FOGMIND
",

                              " " + GetTag(oAoE) + " ") >= 0) {

                nFound++;

                if (nFound >= 2) {

                    SetPlotFlag(oAoE, FALSE);

                    DestroyObject(oAoE);



                    if (nFound == 2)

                        FloatingTextStringOnCreature("Only two herald of
 storms clouds may exist in an area at the same time.", si.caster);

                }

            }

        }

    }





    effect eEff = GetPersistentAoEImpactEffect(si);

    effect eDur = GetPersistentAoEDurationEffect(si);

    effect eVis = GetPersistentAoEVisualEffect(si);





    AssignCommand(si.area, DelayCommand(2.0, StartAoEHeartbeat(si, sTag, eEff, eDur, eVis,

        GetLocalInt(GetModule(), "uptime") + FloatToInt(fDur))));



    ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eAoE, si.loc, fDur);

}

And now, a sample aoe spellscript (acid fog, but with our custom edits):


#include "ac_aoeper_inc"





struct SpellInfo GetPersistentAoESpellInfo ()        { return GetSpellInfo(); }



int GetPersistentAoELimit (struct SpellInfo si)      {

    if (GetIsQuasiSpell(si, QUASIclass_HERALD_OF_STORMS))

        return -2;

    return -1;

}

int GetPersistentAoEEffect (struct SpellInfo si)     { return AOE_PER_FOGACID; }

string GetPersistentAoETag (struct SpellInfo si)     { return "VFX_PER_FOGACID"; }

string GetPersistentAoEName (struct SpellInfo si)    { return "Acid Fog"; }

int GetPersistentAoETargetMask (struct SpellInfo si) { return OBJECT_TYPE_CREATURE; }

int GetPersistentAoETargetType (struct SpellInfo si) { return TARGET_TYPE_DEFAULT; }





float GetPersistentAoEDuration (struct SpellInfo si) {

    return MetaDuration(si, si.clevel / 2, DURATION_IN_ROUNDS);

}



effect GetPersistentAoEImpactEffect (struct SpellInfo si) {

    effect eEff;

    return eEff;

}



effect GetPersistentAoEDurationEffect (struct SpellInfo si) {

    effect eDur;



    if (GetIsQuasiSpell(si, QUASIclass_HERALD_OF_STORMS))

        eDur = EffectDamageIncrease(1);

    return eDur;

}



effect GetPersistentAoEVisualEffect (struct SpellInfo si) {

    ApplyVisualAtLocation(VFX_FNF_GAS_EXPLOSION_ACID, si.loc);



    return EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_ACID);

}





void ApplyAoEEffect (struct SpellInfo si, object oAoE, object oTarget, effect eEff, effect eDur, effect eVis) {

    if (!GetSpellResisted(si, oTarget, 0.0, 2)) {

        int nDamage, nDice = si.clevel, nEffType = GetEffectType(eDur);

        int nDamType = DAMAGE_TYPE_ACID, nSaveType = SAVING_THROW_TYPE_ACID;



        if (nDice < 1)

            nDice = 1;



        nDamage = MetaPower(si, nDice, 6);

        nDamage = GetReflexAdjustedDamage(nDamage, oTarget, si.dc, nSaveType, si.caster);



        if (nDamage > 0) {

            if (nEffType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE) {

                if (!GetHasSpecificEffect(eDur, oTarget))

                    ApplyEffectToObject(DURATION_TYPE_PERMANENT, eDur, oTarget);



                eEff = EffectDamage(nDamage / 2, nDamType);

                DelayCommand(0.1, ApplyEffectToObject(DURATION_TYPE_INSTANT, eEff, oTarget));



                eEff = EffectDamage(nDamage / 2, DAMAGE_TYPE_MAGICAL);

                DelayCommand(0.1, ApplyEffectToObject(DURATION_TYPE_INSTANT, eEff, oTarget));

            } else if (nEffType == EFFECT_TYPE_DAMAGE_INCREASE) {

                if (GetTrueDamageImmunity(oTarget, nDamType) < 100) {

                    int nDecrease = 25 - GetTotalDamageImmunityDecrease(oTarget, nDamType);



                    if (nDecrease > 5)

                        nDecrease = 5;



                    if (nDecrease > 0) {

                        eEff = EffectDamageImmunityDecrease(nDamType, nDecrease);

                        ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEff, oTarget);

                    }

                }



                eEff = EffectDamage(nDamage, nDamType);

                ApplyEffectToObject(DURATION_TYPE_INSTANT, eEff, oTarget);

            } else {

                eEff = EffectDamage(nDamage, nDamType);

                ApplyEffectToObject(DURATION_TYPE_INSTANT, eEff, oTarget);

            }



            ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);

        }

    }

}

Now, you could obviously do the same, but just set all the paoe's to use the same scripts in the 2da, putting a switch in the script, but this way tends to be neater. LMK if you have any questions.

Funky
               
               

               


                     Modifié par FunkySwerve, 16 juin 2011 - 06:38 .
                     
                  


            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
vfx_persistent
« Reply #6 on: June 16, 2011, 07:30:36 pm »


               You're trying to make a generic on enter/ on exit script that will check the type of vfx or AOE that the character entered, and then set the effects to be added or removed based on either the VFX number returned, or AOE type?
If I understood that right, likely the answer is in the NWNX add on functions, which others here are far more adept at using and explaining than I am.
I'll take a look in the toolset, but if that was what you meant hopefully someone else can point you in the right direction for it while I do.

Edit:  FunkySwerve posted his while I was typing.
               
               

               


                     Modifié par Failed.Bard, 16 juin 2011 - 06:31 .
                     
                  


            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
vfx_persistent
« Reply #7 on: June 16, 2011, 09:13:52 pm »


               Wow FunkySwerve great stuff. I take a little time to digest it, not super scripter. Do you run a custom DC or use GetSpellSaveDC? Hmmm is this code kinda messed from the way the forums formats it (wish they fixed that like the old forums)? Maybe I could get a text file of it or something.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
vfx_persistent
« Reply #8 on: June 16, 2011, 09:56:26 pm »


               Anyway if you try my patch then you can set up the AOE id on the AOE in the spell script, you just have to modify function  spellsSetupNewAOE in 70_inc_spells and then recompile spell scripts. Then you will be able to get the VFX id in the AOE script using GetLocalInt.
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
vfx_persistent
« Reply #9 on: June 16, 2011, 10:05:11 pm »


               Here's the include: Download
and the acid fog spell: Download

And, since you asked about custom DCs, here's our spells include, mostly written by acaos:
Download

In the words of a certain former mayor, it's effin golden. Its main function, GetSpellInfo, is included at the top of all our spells, which have all been rewritten to use it (and often consolodated as you were hoping to do with aoe's; all our sphere damage spells, for example, use a single script, hgs_gen_sphere). It's checked in line 4 of the acid fog
script:

nw_s0_acidfog (4): struct SpellInfo GetPersistentAoESpellInfo ()        { return GetSpellInfo(); }

Here's hgs_gen_sphere, in case you're curious:
Download

LMK if you have any questions.

Funky
               
               

               


                     Modifié par FunkySwerve, 16 juin 2011 - 09:08 .
                     
                  


            

Legacy_ShadowM

  • Hero Member
  • *****
  • Posts: 1373
  • Karma: +0/-0
vfx_persistent
« Reply #10 on: June 16, 2011, 10:36:52 pm »


               Thank you to you both, this give me alot of options '<img'>