• 🏆 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!

Beacon

Beacon by Ciebron 1.0

I know THW dont accept zinc but i made this spell to try it out and it was great :)

Beacon is a mix between damage and healing
When cast it will check the units around the hero if they are an enemy or ally

If there are mostly friendlys it will heal the ally with lowest hp in range

If there are mostly enemys it will damage the the target with least health

If there are equally ally and enemys it will heal

This spell where mostly made cause i wanted too try zinc
Which i enjoy more then Jass since it more flexible


Enjoy


JASS:
//! zinc
/***************************************************************************************************/
/* Beacon by 'Ciebron' v1.0 ************************************************************************/
/***************************************************************************************************/
/***************************************************************************************************/
/***************************************************************************************************/
/* Beacon is a mix between damage and healing ******************************************************/
/* When cast it will check the units around the hero if they are an enemy or ally ******************/
/* If there are mostly friendlys it will heal the ally with lowest hp in range *********************/
/* If there are mostly enemys it will damage the the target with least health **********************/
/* If there are equally ally and enemys it will heal ***********************************************/
/***************************************************************************************************/
/* This spell where mostly made cause i wanted too try zinc ****************************************/
/* Which i enjoy more then Jass since it more flexible *********************************************/
/* Enjoy *******************************************************************************************/
/***************************************************************************************************/
    library Beacon requires TimerUtils, Table
    {
    
        private
        {
            /* RawCode of the spell */
            constant integer Abil_Id = 'A000';
            
            /* How many levels the spell have (you need to setup them in the setup function if you add more) */
            constant integer Levels = 3;
            
            /* Effect on the hero when he heals */
            constant string HealSfx = "Abilities\\Spells\\NightElf\\Rejuvenation\\RejuvenationTarget.mdl";
            
            /* Effect on the hero when he damages */
            constant string DmgSfx = "war3mapImported\\GrudgeAura.mdx";
            
            /* Effect on the targets of the heal */
            constant string HealHitSfx = "Abilities\\Spells\\Items\\ResourceItems\\ResourceEffectTarget.mdl";
            
            /* Effect on the targets when it damages */
            constant string DmgHitSfx = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl";
            
            /* Where on the caster the heal effect will attach */
            constant string HealAttachPoint = "overhead";
            
            /* Where on the caster the dmg effect will attach */
            constant string DmgAttachPoint = "origin";
            
            /* Damagetype it will deal (Duh!) */
            constant damagetype DamageType = DAMAGE_TYPE_MAGIC;
            
            /* AttackType it will deal */
            constant attacktype AttackType = ATTACK_TYPE_MAGIC;
            
            
            /* Dont touch these if you dont know what you are doing */
            real Amount[Levels], Radius[Levels], Interval[Levels];
            integer Count[Levels];
        }
    
        function Setup()
        {
            /* Amount it will heal and damage */
            Amount[1] = 35;
            Amount[2] = 50;
            Amount[3] = 65;
            
            /* The radius it will heal and damage in */
            Radius[1] = 450;
            Radius[2] = 500;
            Radius[3] = 550;
            
            /* How often it will heal or damage */
            Interval[1] = 0.75;
            Interval[2] = 0.65;
            Interval[3] = 0.55;
            
            /* how many times it will damage or heal before it ends */
            Count[1] = 12;
            Count[2] = 15;
            Count[3] = 20;
        }
        /* Below this line its the filterfunction for the units it will effect */
        
        /* This filter check when the spell is cast (when check how many enemys and friendlys there are */
        function Match() -> boolean
        {
            unit f = GetFilterUnit();
            unit t = GetTriggerUnit();
            
            boolean ok = f != t && ! IsUnitType(f,UNIT_TYPE_STRUCTURE);
            
            f = null;
            t = null;
            return ok;
        }
        
        /* This filter check which units too heal */
        function HealMatch() -> boolean
        {
            unit f = GetFilterUnit();
            Data this = Dat;
            
            boolean ok = GetWidgetLife(f) > .305 && IsUnitAlly(f,this.Player) && ! IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE) && ! IsUnitType(f,UNIT_TYPE_STRUCTURE) && GetWidgetLife(f) != GetUnitState(f,UNIT_STATE_MAX_LIFE);
            
            f = null;
            return ok;
        }
        
        /* This filter check which units too damage */
        function DmgMatch() -> boolean
        {
            unit f = GetFilterUnit();
            Data this = Dat;
            
            boolean ok = GetWidgetLife(f) > .305 && IsUnitEnemy(f,this.Player) && ! IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE) && ! IsUnitType(f,UNIT_TYPE_STRUCTURE);
            
            f = null;
            return ok;
        }
        
        /***************************************/
        /******* Here does the Setup end *******/
        /***************************************/
        
        private
        {
            boolexpr Bool, HealBool, DmgBool;
            integer Enemy_Count, Friendly_Count;
            player Player_Pass;
            unit TempU, TempLow;
            real TempR, TempRLow;
            Data Dat;
            HandleTable Table;
        }
        
        private struct Data
        {
            unit caster;
            
            integer lvl, count;
                        
            effect Sfx;
            
            player Player;
            
            timer Timer;
            
            static group Grp = CreateGroup();
            
            static method create(unit u) -> thistype
            {
                thistype this = thistype.allocate();
                
                this.caster = u;
                this.Player = GetOwningPlayer(this.caster);
                this.lvl = GetUnitAbilityLevel(this.caster,Abil_Id);
                this.Timer = CreateTimer();
                this.count = Count[this.lvl];

                GroupEnumUnitsInRange(Grp,GetUnitX(this.caster),GetUnitY(this.caster),Radius[this.lvl],Bool);
                
                Player_Pass = this.Player;
                Enemy_Count = 0;
                Friendly_Count = 0;
                
                /* Kinde droped my jaw when i figured out this, so easy to read then ^^ */
                ForGroup(Grp,function()
                {
                
                    if (IsUnitEnemy(GetEnumUnit(),Player_Pass))
                    {
                        Enemy_Count = Enemy_Count + 1;
                    }
                    else
                    {
                        Friendly_Count = Friendly_Count + 1;
                    }
                    
                } );
                
                SetTimerData(this.Timer,this);
                
                if (Friendly_Count >= Enemy_Count)
                {
                    TimerStart(this.Timer,Interval[this.lvl],true,function thistype.HealLoop);
                    
                    this.Sfx = AddSpecialEffectTarget(HealSfx,this.caster,HealAttachPoint);
                }
                else
                {
                    TimerStart(this.Timer,Interval[this.lvl],true,function thistype.DmgLoop);
                    
                    this.Sfx = AddSpecialEffectTarget(DmgSfx,this.caster,DmgAttachPoint);
                }
                
                Table[this.caster] = this;
                
                return this;
            }
            
            static method HealLoop()
            {
                timer Timer = GetExpiredTimer();
                thistype this = GetTimerData(Timer);
                
                Dat = this;
                
                GroupEnumUnitsInRange(Grp,GetUnitX(this.caster),GetUnitY(this.caster),Radius[this.lvl],HealBool);
                
                TempLow = FirstOfGroup(Grp);
                TempRLow = GetWidgetLife(TempLow);
                
                ForGroup(Grp,function()
                {
                    unit Enum = GetEnumUnit();
                    
                    TempR = GetWidgetLife(Enum);
                    
                    if (TempR < TempRLow)
                    {
                        TempRLow = TempR;
                        TempLow = Enum;
                    }
                    
                    Enum = null;
                    
                });
                
                SetWidgetLife(TempLow,GetWidgetLife(TempLow)+Amount[this.lvl]);
                DestroyEffect(AddSpecialEffectTarget(HealHitSfx,TempLow,"origin"));

                this.count = this.count - 1;
                
                if (this.count <= 0)
                {
                    this.destroy();
                }
            }
            
            static method DmgLoop()
            {
                timer Timer = GetExpiredTimer();
                thistype this = GetTimerData(Timer);
                
                Dat = this;
                
                GroupEnumUnitsInRange(Grp,GetUnitX(this.caster),GetUnitY(this.caster),Radius[this.lvl],DmgBool);
                
                TempLow = FirstOfGroup(Grp);
                TempRLow = GetWidgetLife(TempLow);
                
                ForGroup(Grp,function()
                {
                    unit Enum = GetEnumUnit();
                    
                    TempR = GetWidgetLife(Enum);
                    
                    if (TempR < TempRLow)
                    {
                        TempRLow = TempR;
                        TempLow = Enum;
                    }
                    
                    Enum = null;
                    
                });
                
                UnitDamageTarget(this.caster,TempLow,Amount[this.lvl],false,false,AttackType,DamageType,null);
                DestroyEffect(AddSpecialEffectTarget(DmgHitSfx,TempLow,"origin"));

                this.count = this.count - 1;
                
                if (this.count <= 0)
                {
                    this.destroy();
                }
            }
            
            method onDestroy()
            {
                DestroyEffect(this.Sfx);
                PauseTimer(this.Timer);
                DestroyTimer(this.Timer);
                
                Table.flush(this.caster);
            }
        }
        
        function OnCast() -> boolean
        {
            Data this;
            unit caster;
            
            if (GetSpellAbilityId()==Abil_Id)
            {
                caster = GetTriggerUnit();
                
                if (Table.exists(caster))
                {
                    this = Table[caster];
                    this.destroy();
                }
                
                Data.create(caster);
                
                caster = null;
            }
            
            return false;
        }
        
        function onInit()
        {
            trigger trig = CreateTrigger();
            
            TriggerAddCondition(trig,Condition(function OnCast));
            TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_SPELL_EFFECT);
            
            Bool = Filter(function Match);
            DmgBool = Filter(function DmgMatch);
            HealBool = Filter(function HealMatch);
            
            static if(LIBRARY_Table)
            {
                Table = HandleTable.create();
            }
            Setup();
        }
    }
//! endzinc





*1.0: First Release



Keywords:
Damage, Heal, Healing, Aoe, Area of effect
Contents

Just another Warcraft III map (Map)

Reviews
19:19, 4th Jan 2010 The_Reborn_Devil: The code looks good, but boolean ok = GetWidgetLife(f) > .305 ... should be boolean ok = GetWidgetLife(f) > 0.405 or boolean ok = UnitAlive(f) :D Status: Approved Rating: Useful

Moderator

M

Moderator

19:19, 4th Jan 2010
The_Reborn_Devil:
The code looks good, but boolean ok = GetWidgetLife(f) > .305 ...
should be
boolean ok = GetWidgetLife(f) > 0.405

or
boolean ok = UnitAlive(f)
:D

Status: Approved
Rating: Useful
 
Top