• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • ✅ The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!
  • ✅ The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! 🔗Click here to cast your vote!

Special-effect isn't removed from allies when spell-effect ends.

Level 17
Joined
Jul 19, 2007
Messages
969
Hi. I got a problem with a JASS-triggered spell. It actually works like it is supposed to do except one thing, the special-effect isn't removed from allies when the spell duration ends. It removes special-effect only from the caster but not from allies. I can't see anything wrong with the JASS-trigger and I have imported everything required for it to work but it doesn't remove the special-effect from allies so something must be wrong but I dunno what it is... :-/
JASS:
//TESH.scrollpos=30
//TESH.alwaysfold=0
/*
    **********************************************************************************************************
    
                                        Installation:
        
        1) Copy this trigger and 'DD Library' to your map
        2) Copy Nature Blessing abilitie to your map
        3) Export and Import 'GaiaShield.mdx', 'GaiaMissile.mdx', 'NatureExplosion.mdx' sound from this map to yours
        4) Modify constants to your liking below
        5) Made on Warcraft III v1.30
    
    **********************************************************************************************************
*/

//! zinc
library NatureBlessing requires DDLib
{

        // This is the main raw code of ability Nature Blessing
        // Default: 'Nbls'
        constant    integer            NATURE_BLESSING                    = 'A0S3';
        
        // Natures shield effect model path
        // Default: "Spells\\NatureBlessing\\GaiaShield.mdx"
        constant    string            NATURE_SHIELD_EFFECT            = "war3mapImported\\Stone Shield.mdx";
        
        // Natures missile effect model path
        // Default: "Spells\\NatureBlessing\\GaiaMissle.mdx"
        constant    string            NATURE_MISSILE_EFFECT            = "Spells\\NatureBlessing\\GaiaMissle.mdx";
        
        // Natures explosion model effect path
        // Default: "Spells\\NatureBlessing\\NatureExplosion.mdx"
        constant    string            NATURE_EXPLOSION_EFFECT            = "Spells\\NatureBlessing\\NatureExplosion.mdl";
        
        // Natures missile fire sound path (this sound is played when missiles start to move)
        // Default: "Abilities\\Spells\\NightElf\\Tranquility\\TranquilityTarget1.wav"
        constant    string            NATURE_SHOOT_SOUND                = "Abilities\\Spells\\NightElf\\Tranquility\\TranquilityTarget1.wav";
        constant    real            NATURE_SHOOT_SOUND_VOL            = 100.;
        constant    real            NATURE_SHOOT_SOUND_PITCH        = 1.5;
        constant    real            NATURE_SHOOT_SOUND_MAX_DISTANCE = 3500.;
        
        // Nature explosion sound file path (is played when nature explosion is caused)
        // Default: "Abilities\\Spells\\NightElf\\Tranquility\\Tranquility.wav"
        constant    string            NATURE_EXPLOSION_SOUND            = "Abilities\\Spells\\NightElf\\Tranquility\\Tranquility.wav";
        constant    real            NATURE_EXPLOSION_SOUND_VOL        = 90.;
        
        // This is number of nature missiles created
        // Default: 12
        constant    integer            MISSILES_COUNT                    = 12;
        // Default: 1.2
        constant    real            MISSILE_SIZE                    = 1.2;
        
        // This is min and max distance from caster to missiles start point
        // Default: 400 / 600
        constant    real            MISSILE_MIN_DISTANCE            = 400.;
        constant    real            MISSILE_MAX_DISTANCE            = 600.;
        
        // This is min and max finish height / caster position of missiles
        // Default: 75 / 400
        constant    real            MISSILE_MIN_HEIGHT                = 40.;
        constant    real            MISSILE_MAX_HEIGHT                = 400.;
        
        // This is missiles value which tells how much time they need to reach caster and how long it takse for them to manifest
        // Default: 0.75 / 0.5
        constant    real            MISSILE_TRAVEL_TIME                = .9;
        constant    real            MISSILE_BIRTH_TIME                = 0.5;
        
        // Default: 50
        constant    real            MISSILE_INITIAL_HEIGHT            = 10.;
        
        // Default: 0.2 seconds
        constant    real            HEAL_INTERVAL                    = .2;
        // --------------------------------------------------------------
        //    *** Do not edit level variables here edit them below ***
        real            EXPLOSION_AOE[];
        real            SHIELD_PROTECT[];
        real            HEAL_PERC_AMOUNT[];
        real            SPELL_DURATION[];
    
    // -----------------------------------------------------------------
    //                 *** Edit level data here ***
    function NatureBlessingLevelSetup() {
        // This is AOE of explosion "effect"
        // Default: 410 / 530 / 650
        EXPLOSION_AOE[01] = 650.;
        EXPLOSION_AOE[02] = 650.;
        EXPLOSION_AOE[03] = 650.;
        
        // Shield protection is amount of damage reduced in percentage
        // Default: 15 / 25 / 35
        SHIELD_PROTECT[01] = 25.;
        SHIELD_PROTECT[02] = 35.;
        SHIELD_PROTECT[03] = 45.;
        
        // This is heal amount in percentage per point of life missing
        // Default: 5 / 7 / 9
        HEAL_PERC_AMOUNT[01] = 5.;
        HEAL_PERC_AMOUNT[02] = 7.;
        HEAL_PERC_AMOUNT[03] = 9.;
        
        // This is how long spell lasts in seconds
        // Default: 10 / 10 / 10
        SPELL_DURATION[01] = 15.;
        SPELL_DURATION[02] = 15.;
        SPELL_DURATION[03] = 15.;
    }
    
    function PickUnitsFilter(unit f, player owner) -> boolean {
        return IsUnitAlly(f, owner)                                 &&
               !IsUnitType(f, UNIT_TYPE_DEAD)                         &&
               !IsUnitType(f, UNIT_TYPE_STRUCTURE)                     &&
               !BlzIsUnitInvulnerable(f)                            &&
               !DDIsUnitWard(f)                                        &&
               !IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE)                &&
               !IsUnitType(f, UNIT_TYPE_MECHANICAL);
    }
    
    // #####################################################################################
    // #####################################################################################
    
    timer            Tim = null;
    group            Grp = null;
    
    struct unitdata {
        real dur, heal, shield;
        effect e;
        
        static thistype Att[];
    }
    
    struct missiles {
        ddeffect    m[MISSILES_COUNT];
        p_real         pos[MISSILES_COUNT];
        p_real        spd[MISSILES_COUNT];
        integer     cnt;
        
        real        X, Y;
        player        owner;
        integer     lvl;
        
        
        static method create(unit c) -> thistype {
            thistype this = allocate();
            integer i;
            real x = GetWidgetX(c), y = GetWidgetY(c);
            real rad = 0., d;
            
            X = x; Y = y;
            owner = GetOwningPlayer(c);
            lvl = GetUnitAbilityLevel(c, NATURE_BLESSING);
            
            cnt = R2I((MISSILE_TRAVEL_TIME-.1) / DD_INTERVAL);
            for(i=00; i < MISSILES_COUNT; i+=01) {
                rad += bj_PI/6.;
                d = GetRandomReal(MISSILE_MIN_DISTANCE, MISSILE_MAX_DISTANCE);
                pos[i] = pVector(x + d * Cos(rad), y + d * Sin(rad), MISSILE_INITIAL_HEIGHT);
                spd[i] = pVector(-Cos(rad) * DD_INTERVAL * d / MISSILE_TRAVEL_TIME,
                                 -Sin(rad) * DD_INTERVAL * d / MISSILE_TRAVEL_TIME,
                                 DD_INTERVAL * (GetRandomReal(MISSILE_MIN_HEIGHT, MISSILE_MAX_HEIGHT)-MISSILE_INITIAL_HEIGHT) / MISSILE_TRAVEL_TIME);
                m[i] = ddeffect.createZ(NATURE_MISSILE_EFFECT, pos[i][00], pos[i][01], pos[i][02] + DDTerrZ(pos[i][00], pos[i][01]), rad, MISSILE_SIZE);
            }
            
            return this;
        }
        
        method destroy() {
            integer i;
            
            for(i=00; i < MISSILES_COUNT; i+=01) {
                m[i].destroy();
                pos[i].destroy();
                spd[i].destroy();
            }
            deallocate();
        }
        
        method Step() -> boolean {
            integer i;
            
            for(i=00; i < MISSILES_COUNT; i+=01) {
                pos[i][00] += spd[i][00];
                pos[i][01] += spd[i][01];
                pos[i][02] += spd[i][02];
                
                m[i].PositionZ(pos[i][00], pos[i][01], pos[i][02]);
                //m[i].Y = pos[i][01];
                //m[i].Z = pos[i][02];
            }
            
            cnt -= 01;
            return (cnt == 00);
        }
        
    }
    
    
    // ==========================================================================================
    function onInit() {
        trigger t = CreateTrigger();
        
        Grp = CreateGroup();
        NatureBlessingLevelSetup();
        
        // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        
        TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
        TriggerAddCondition(t, Condition(function() -> boolean {
            missiles ms;
            unit u;
            
            if (GetSpellAbilityId() != NATURE_BLESSING)
                return false;
            
            u = GetTriggerUnit();
            ms = missiles.create(u);
            
            // Play sound and shake camera for players within spell cast range
            DDGenericSound(NATURE_SHOOT_SOUND, NATURE_SHOOT_SOUND_VOL, GetWidgetX(u), GetWidgetY(u), NATURE_SHOOT_SOUND_MAX_DISTANCE, NATURE_SHOOT_SOUND_PITCH);
            
            DDStartTim(MISSILE_BIRTH_TIME, false, ms, function() {
                DDStartTim(DD_INTERVAL, true, DDTimData(), function() {
                    missiles ms = DDTimData();
                    trigger t;
                    
                    if (ms.Step()) {
                        DDGenericSound(NATURE_EXPLOSION_SOUND, NATURE_EXPLOSION_SOUND_VOL, ms.X, ms.Y, NATURE_SHOOT_SOUND_MAX_DISTANCE, 1.8);
                        ddeffect.create(NATURE_EXPLOSION_EFFECT, ms.X, ms.Y, GetRandomReal(0., bj_PI*2.), EXPLOSION_AOE[ms.lvl]/250.).destroyx(3.);
                        
                        DDGroupFilterArea(ms.X, ms.Y, EXPLOSION_AOE[ms.lvl], ms, function() -> boolean {
                            unitdata ud;
                            missiles ms = DDGFilterData();
                            unit f = GetFilterUnit();
                            
                            if (PickUnitsFilter(f, ms.owner)) {
                                if (ud.Att[GetHandleId(f)-0x100000] == p_null) {
                                    ud = unitdata.create();
                                    ud.Att[GetHandleId(f)-0x100000] = ud;
                                    ud.e = AddSpecialEffectTarget(NATURE_SHIELD_EFFECT, f, "origin");
                                    GroupAddUnit(Grp, f);
                                } else
                                    ud = ud.Att[GetHandleId(f)-0x100000];
                                
                                ud.heal         = HEAL_PERC_AMOUNT[ms.lvl] / 100.;
                                ud.shield         = SHIELD_PROTECT[ms.lvl] / 100.;
                                ud.dur             = SPELL_DURATION[ms.lvl];
                            }
                            
                            f = null;
                            return false;
                        });
                        
                        if (Tim == null) {
                            Tim = DDLoadTim();
                        
                        TimerStart(Tim, HEAL_INTERVAL, true, function() {
                            ForGroup(Grp, function() {
                                unit e = GetEnumUnit();
                                unitdata ud = unitdata.Att[GetHandleId(e)-0x100000];
                                
                                SetWidgetLife( e, GetWidgetLife(e) + (HEAL_INTERVAL * ud.heal * (GetUnitState(e, UNIT_STATE_MAX_LIFE)-GetWidgetLife(e))) );
                                
                                ud.dur -= .2;
                                if (ud.dur < 0. || IsUnitType(e, UNIT_TYPE_DEAD)) {
                                    GroupRemoveUnit(Grp, e);
                                    ud.Att[GetHandleId(e)-0x100000] = p_null;
                                    DestroyEffect(ud.e);
                                    ud.e = null;
                                    ud.destroy();
                                    if (FirstOfGroup(Grp) == null) {
                                        DDRecycleTim(Tim);
                                        Tim = null;
                                    }
                                }
                                
                                e = null;
                            });
                        });
                        
                        }
                        
                        ms.destroy();
                        DDQuitTim();
                    }
                });
                DDQuitTim();
            });
            
            u = null;
            return false;
        }));
        
        // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        
        t = CreateTrigger();
        DDTriggerRegisterAnyUnitDamaged(t);
        TriggerAddCondition(t, Condition(function() -> boolean {
            unit u = GetTriggerUnit();
            unitdata ud = unitdata.Att[GetHandleId(u)-0x100000];
                
            if (ud == p_null) {
                u = null;
                return false;
            }
            
            SetWidgetLife(u, GetWidgetLife(u) + (GetEventDamage() * ud.shield));
            
            u = null;
            return false;
        }));
        
        // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        
    }
    
}
//! endzinc
 
Back
Top