• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Help with this script

Status
Not open for further replies.
Level 13
Joined
Aug 19, 2014
Messages
1,111
Hello guys I got my hand on one of Mr. Beans spells that was requested to him. I already accomplish on modifying the damage, however there are some problems that I've encountered and I need help from experts.

View attachment Vista sucks - Volcanic Ash Cloud.w3x

The spell is based on the Cloud ability, it deals damage over time on enemies that are inside the AOE, silences and slows them too. I set the duration of the spell to 20 secs. in the object editor and the damage duration in the code to 20 secs. too. The problem is that when an enemy unit that gets out of the AOE it would still take damage because of the 20 secs. damage duration. But when I set the damage duration to 1 sec. only, units stayed on the AOE will only take damage from that time and won't received the damage of the spell even if it last for 20 secs. I want the spell to do a looping damage to enemies inside the AOE for 20 secs., of course if the enemy is not in the AOE it won't take damage anymore. Need help to modify this script guys.

Here's the code......

JASS:
//! zinc

library VolcanicAshCloud requires TimerUtils
{
    /*
        START OF CONFIGURABLES
    */

    // Raw ID of the "Volcanic Ash Cloud" hero ability:
    private constant integer SPELL_ID       = 'A000';
    
    // How often the damage gets dealt:
    private constant real    DAMAGE_FREQ    = 1.0;
    
    // Configure the damage amount to each unit:
     private function GetDamage (integer lvl, unit caster) -> real
    {   
        return 50.0 * lvl + GetHeroInt(caster, true)*1.00;
    }
   
   // Configure the duration of the silence and slow:
    private function GetDuration(integer level) -> real
    {
        if (level == 1)
            return 20.0;
        if (level == 2)
            return 20.0;
        if (level == 3)
            return 20.0;
        if (level == 4)
            return 20.0;
        if (level == 5)
            return 20.0;
            
        return 0.0;
    }
    
    // Configure the duration of the damage:
    private function GetDamageDuration(integer level) -> real
    {
        if (level == 1)
            return 20.0;
        if (level == 2)
            return 20.0;
        if (level == 3)
            return 20.0;
        if (level == 4)
            return 20.0;
        if (level == 5)
            return 20.0;   
        
        return 0.0;
    }
    
    /*
        END OF CONFIGURABLES
    */
    
    private group enumG = CreateGroup();
    private unit enumU;
    
    private function IsUnitTargetable(unit u) -> boolean
    {
        return !IsUnitType(u, UNIT_TYPE_DEAD) && !IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) && !IsUnitType(u, UNIT_TYPE_STRUCTURE);
    }
    
    private struct DamageOverTime
    {
        unit source;
        unit target;
        real timeLeft;
        real damage;
        
        private method destroy()
        {
            source = null;
            target = null;
            deallocate();
        }
        
        private static method dealDamage()
        {
            thistype this = GetTimerData(GetExpiredTimer());
            
            UnitDamageTarget(source, target, damage, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, null);
            timeLeft = timeLeft - 0.1;
            
            if (timeLeft <= 0.0)
            {
                ReleaseTimer(GetExpiredTimer());
                this.destroy();
            }
        }
        
        public static method start(unit t, unit s, real d, integer l) -> thistype
        {
            thistype this = thistype.allocate();
            
            source = s;
            target = t;
            timeLeft = GetDamageDuration(l);
            damage = (d / timeLeft) * 0.1;
            TimerStart(NewTimerEx(this), 0.1, true, function thistype.dealDamage);
            
            return this;
        }
    }
    
    private struct Data
    {
        unit caster;
        player owner;
        group units = CreateGroup();
        integer level;
        real targX;
        real targY;
        real timeLeft;
        
        private method destroy()
        {
            DestroyGroup(units);
            caster = null;
            owner = null;
            units = null;
            deallocate();
        }
        
        private static method damageUnits()
        {
            thistype this = GetTimerData(GetExpiredTimer());
            
            GroupEnumUnitsInRange(enumG, targX, targY, 250.0, null);
            enumU = FirstOfGroup(enumG);
            
            while(enumU != null)
            {
                if (!IsUnitInGroup(enumU, units) && IsUnitTargetable(enumU) && IsUnitEnemy(enumU, owner))
                {
                    GroupAddUnit(units, enumU);
                    DamageOverTime.start(enumU, caster, 140.0, level);
                }
                GroupRemoveUnit(enumG, enumU);
                enumU = FirstOfGroup(enumG);
            }
            
            timeLeft = timeLeft - 0.05;
            
            if (timeLeft <= 0.0)
            {
                ReleaseTimer(GetExpiredTimer());
                destroy();
            }
        }
        
        private static method actions()
        {
            thistype this = thistype.allocate();
            
            caster = GetTriggerUnit();
            owner = GetTriggerPlayer();
            level = GetUnitAbilityLevel(caster, SPELL_ID);
            targX = GetSpellTargetX();
            targY = GetSpellTargetY();
            timeLeft = GetDuration(level);
            TimerStart(NewTimerEx(this), 0.05, true, function thistype.damageUnits);
        }
        
        private static method CheckSpell() -> boolean
        {
            if (GetSpellAbilityId() == SPELL_ID)
                thistype.actions();
                
            return false;
        }
        
        private static method onInit()
        {
            trigger t = CreateTrigger();
            TriggerAddCondition(t, Condition(function thistype.CheckSpell));
            TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
            t = null;
        }
    
    }
}

//! endzinc
 
Status
Not open for further replies.
Top