Skip to content

UniquePower : OnHit, targeting problem

badstrrefbadstrref Member Posts: 124
edited May 2019 in Builders - Scripting
I'm trying to build special weapons with unique (scripted) on-hits effects, so far I had not stumbled upon any problem as long as the target was always single, the direct target of the attacker.

I have no idea why, maybe its a small error from me that I cannot understand atm, but in essence : targeting creatures through loops, from tagbased UniquePower-OnHit scripts reveals to be problematic and the list of creatures returned in the map are not always complete, thus not reliable.

This problem specifically happen in on-hit scripts, the very same verbatim script copied and used in a spell script and cast normally, or onActivate item will run without any problem and all creatures will be targeted successfully.

I've tested cursesong, chain lightning on on-hit weapons just for testing purposes, and they had the same targeting problems while working correctly in spells scripts.

This is very strange to me, maybe I'm too close to the thing that I'm blinded and the problem is ridiculously simple?


ckz9jpsvi3ai.jpg

Comments

  • DazDaz Member Posts: 127
    What is the script you are using?
  • badstrrefbadstrref Member Posts: 124
    edited May 2019
    Hi,

    you can try a simple
    ExecuteScript("nw_s0_chlightn", OBJECT_SELF);
    

    and see, as in the picture : a limited amount of target are found and targeted (sometimes just one)

    q278rrvvcet0.jpg

    Another problem I've found but can't reproduce (without on-hit weapons but using simple dev crit), if I attack target A and then cancel and then attack target B, if i dev crit target B, target A dies. not sure if related but all these problems set me off developping further my module.

  • JFKJFK Member Posts: 214
    Forgive me ignorance, but what level PC are you testing this with? Doesn't Chain Lightning determine number of targets possibly hit by caster level?

    1 secondary target per level is struck for 1d6 / 2 caster levels.


    Probably nothing to do with it, but thought I'd throw it out there.


    -JFK
  • badstrrefbadstrref Member Posts: 124
    edited May 2019
    Hi,

    that character is level 31,

    here another test with
    ExecuteScript("x2_s2_cursesong", OBJECT_SELF);
    

    4 out of 6 targets are cursed :

    gvnkxuur9xtm.jpg


    And a simple custom on-hit weapon used in my first post :

    void FrostImpact(object oPC, object oTarget)
    {
            int nDamage = 30 + d6(5);
            effect eSkin   = EffectVisualEffect(VFX_DUR_ICESKIN);
            effect eDamage = EffectDamage(nDamage, DAMAGE_TYPE_COLD);
            effect eBeam   = EffectBeam(VFX_BEAM_SILENT_COLD, oPC, BODY_NODE_CHEST);
    
            ApplyEffectToObject(1, eSkin, oTarget, 2.1);
            ApplyEffectToObject(0, eDamage, oTarget);
            ApplyEffectToObject(1, eBeam, oTarget, 2.1);
    }
    
    void FrostWind(object oPC, object oTarget)
    {
            object oArea = GetArea(oTarget);
    
            object oSeek = GetFirstObjectInArea(oArea);
            while(GetIsObjectValid(oSeek))
            {
    
                if(GetObjectType(oSeek) == OBJECT_TYPE_CREATURE)
                {
    
                     if(oPC != oSeek && GetIsEnemy(oPC, oSeek))
                     {
                         if(GetDistanceBetween(oPC, oSeek) <= 10.0)
                         {
                                FrostImpact(oPC, oSeek);
                         }
                     }
                }
            oSeek = GetNextObjectInArea(oArea);
            }
    }
    
    
    void main()
    {
    
    /*
        <cÿÃ>[Ultimate]</c> <cþþþ>Subzero Katana</c>
        <cÿÃ>Frost Wind :</c> 7% Chance to deal 30+5d6 Ice Damage to all ennemies around.
    */
        if(d100(1) <= 7)
        {
            object oPC      = OBJECT_SELF;
            object oTarget  = GetSpellTargetObject();
            location lLoc   = GetLocation(oPC);
    
            ApplyEffectAtLocation(0, EffectVisualEffect(1030), lLoc);
            FrostWind(oPC, oTarget);
        }
    
    }
    
    Post edited by badstrref on
  • drillerdriller Member Posts: 17
    Here is a work around.
    void FrostWind(object oPC)
    {
            int i = 1;
    
            object oSeek = GetNearestObject(OBJECT_TYPE_CREATURE,oPC,i);
            while(GetIsObjectValid(oSeek))
            {
    
                     if(GetIsEnemy(oPC, oSeek))
                     {
                         if(GetDistanceBetween(oPC, oSeek) <= 10.0)
                         {
                                FrostImpact(oPC, oSeek);
                         }
                     }
    
            oSeek = GetNearestObject(OBJECT_TYPE_CREATURE,oPC,i+=1);
            }
    }
    
    
  • badstrrefbadstrref Member Posts: 124
    edited May 2019

    Thanks for your help!
    Somehow your code gives better results, only 1-2 are avoided now, still the problem persist

    tdvzo8qy7zsp.jpg

  • DazDaz Member Posts: 127
    You can also do:
    void FrostWind(object oPC)
    {
        object oSeek = GetFirstObjectInShape(SHAPE_SPHERE, 10.0f, GetLocation(oPC), FALSE, OBJECT_TYPE_CREATURE);
    
        while(GetIsObjectValid(oSeek))
        {
            if(GetIsEnemy(oPC, oSeek))
            {
                FrostImpact(oPC, oSeek);
            }
    
            oSeek = GetNextObjectInShape(SHAPE_SPHERE, 10.0f, GetLocation(oPC), FALSE, OBJECT_TYPE_CREATURE);
        }
    }
    
  • badstrrefbadstrref Member Posts: 124
    I know this. all variants give the same errors.
  • drillerdriller Member Posts: 17
    That's unfortunate, it worked when I tested it. I only had a few creatures though.

    I noticed that you had a few placeables circled in your screenshots, you will need to change OBJECT_TYPE_CREATURE to OBJECT_TYPE_ALL to include them.

    Where any of the creatures dying? Perhaps that messed it up.

    Try this and let me know what happens.

    void FrostWind(object oPC)
    {
            int i = 1;
            int nMobs;
            object oSeek = GetNearestObject(OBJECT_TYPE_CREATURE,oPC,i);
            while(GetIsObjectValid(oSeek))
            {
    
                     if(GetIsEnemy(oPC, oSeek))
                     {
                         if(GetDistanceBetween(oPC, oSeek) <= 10.0)
                         {
                            SetLocalObject(oPC,"MOBS"+IntToString(nMobs+=1),oSeek);
                         }
                     }
    
            oSeek = GetNearestObject(OBJECT_TYPE_CREATURE,oPC,i+=1);
            }
    
            for(i=1;i<=nMobs;i+=1)
            {
            oSeek = GetLocalObject(oPC,"MOBS"+IntToString(i));
            FrostImpact(oPC, oSeek);
            DeleteLocalObject(oPC,"MOBS"+IntToString(i));
            }
    }
    
    
  • badstrrefbadstrref Member Posts: 124
    edited May 2019
    @Daz your script was my first attempt, before trying other variants :
    Daz wrote: »
    You can also do:
    void FrostWind(object oPC)
    {
        object oSeek = GetFirstObjectInShape(SHAPE_SPHERE, 10.0f, GetLocation(oPC), FALSE, OBJECT_TYPE_CREATURE);
    
        while(GetIsObjectValid(oSeek))
    
            if(GetIsEnemy(oPC, oSeek))
            {
                FrostImpact(oPC, oSeek);
            }
    
            oSeek = GetNextObjectInShape(SHAPE_SPHERE, 10.0f, GetLocation(oPC), FALSE, OBJECT_TYPE_CREATURE);
        }
    }
    

    but that failed for some reason, so i tried with GetFirstObjectInArea & build up

    @driller : results for your script (btw they are not placeables but CEP golems)

    say4ywv2v4u1.jpg


    Here is a version using chat command : (note their scritped on hit (single target) works perfectly)
    eup0ev6fer5k.jpg

    Here using on activate item : (first it finds everything, then fails)
    3tbhod4jrwnu.jpg

    :s:s:s



    Post edited by badstrref on
  • drillerdriller Member Posts: 17
    I tested this in an area with 100 mobs and it fired everytime.
    void FrostImpact(object oPC, object oTarget, int i, int nMobs)
    {
            SendMessageToPC(oPC,"EFFECT APPLIED TO: "+IntToString(i)+" of "+IntToString(nMobs));
            int nDamage = 30 + d6(5);
            effect eSkin   = EffectVisualEffect(VFX_DUR_ICESKIN);
            effect eDamage = EffectDamage(nDamage, DAMAGE_TYPE_COLD);
            effect eBeam   = EffectBeam(VFX_BEAM_SILENT_COLD, oPC, BODY_NODE_CHEST);
    
            ApplyEffectToObject(1, eSkin, oTarget, 2.1);
            ApplyEffectToObject(0, eDamage, oTarget);
            ApplyEffectToObject(1, eBeam, oTarget, 2.1);
    }
    
    void FrostWind(object oPC)
    {
            int i;
            int nMobs;
            object oArea = GetArea(oPC);
            location lLoc = GetLocation(oPC);
            object oSeek = GetFirstObjectInShape(SHAPE_SPHERE,10.0f,lLoc);
    
            while(GetIsObjectValid(oSeek))
            {
            if(oSeek != oPC)
            i+=1;
    
            SendMessageToPC(oPC,"NUMBER OF MOBS IN AREA: "+IntToString(i));
    
                     if(GetIsEnemy(oPC, oSeek))
                     {
    
                         SetLocalObject(oPC,"MOBS"+IntToString(nMobs+=1),oSeek);
    
                     }
    
            oSeek = GetNextObjectInShape(SHAPE_SPHERE,10.0f,lLoc);
            }
    
            SendMessageToPC(oPC,"NUMBER OF MOBS IN 10m RADIUS: "+IntToString(nMobs));
    
            for(i=1;i<=nMobs;i+=1)
            {
            oSeek = GetLocalObject(oPC,"MOBS"+IntToString(i));
            FrostImpact(oPC, oSeek, i, nMobs);
            DeleteLocalObject(oPC,"MOBS"+IntToString(i));
            }
    }
    
    
    void main()
    {
    
    /*
        <cÿÃ>[Ultimate]</c> <cþþþ>Subzero Katana</c>
        <cÿÃ>Frost Wind :</c> 7% Chance to deal 30+5d6 Ice Damage to all ennemies around.
    */
    //    if(d100(1) <= 7)
        {
            object oPC      = OBJECT_SELF;
            object oTarget  = GetSpellTargetObject();
            location lLoc   = GetLocation(oPC);
            SendMessageToPC(oPC,"ON HIT FIRED");
            ApplyEffectAtLocation(0, EffectVisualEffect(1030), lLoc);
            FrostWind(oPC);
        }
    
    }
    
  • badstrrefbadstrref Member Posts: 124
    ah, well thanks for your efforts, I guess my nwn needs an exorcism :)
  • drillerdriller Member Posts: 17
    There is defininently something wrong. When I tried your first script and variations of my own, it would usually but not always just find one object and then the rest of them on the second hit. It was not consistent.

    At one point, I had commented out your function and used my own and it worked. I then changed my function a line at a time(trying to pinpoint the issue) to match yours and it stilled worked and yours wouldn't even though they were identical.

    Very interesting bug going on here.
  • EzRemakeEzRemake Member Posts: 15
    Unique power on hit is really not a great way to do things generally.

    What I like to do, is in the onphysicallyattacked script, have a function that checks the attacker's weapon for a string variable, and if it exists run a script with the corresponding string. That way you can cleanly pass the attacker and the attackee to the script, and then in the script itself you can acquire more targets etc as needed.

    This also allows you to put in a 'chance' of the on hit effect, instead of having super-mega-god-beam-firestorms every single time the player attacks the target. Also allows for instantly easy replacement of onhit skills just by changing the LocalVariableString on the weapon.
  • badstrrefbadstrref Member Posts: 124
    Hi,

    I needed this also for PvP, and it worked before, I didnt bother any further, I will reinstall if I have an interest bump for this game again,

    thanks for your help
Sign In or Register to comment.