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

Fiery Slash v1.2

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Description
    Move towards the targeted unit over 0.50 second, dealing damage and DPS for 5 seconds to nearby enemy ground units in line. The caster will slash the target when reach and causing damage and DPS for 8 seconds.

    Level 1 - 50 damage and 5 DPS to nearby enemy, 100 damage and 10 DPS to target.
    Level 2 - 60 damage and 10 DPS to nearby enemy, 125 damage and 20 DPS to target.
    Level 3 - 70 damage and 15 DPS to nearby enemy, 150 damage and 30 DPS to target.
  • Code
    JASS:
    //***************************************************************************
    //*    Fiery Slash
    //*
    //*  Created by: Ofel The Editor
    //*  Version: 1.2
    //*
    //* =========================================================================
    //*  
    //*   Credits :
    //*  - Tank-Commander: Basic indexing.
    //*
    //* =========================================================================
    //*
    //*   Changelog :
    //*  - v1.0: Initial version.
    //*  - v1.1: More configurables, fixed some things.
    //*  - v1.2: Fixed more things.
    //*
    //***************************************************************************
    
    //***************************************************************************
    //*
    //*  Configuration
    //*
    //***************************************************************************
    //---- Ability raw code (Ctrl + D on Object Editor to display) ----\\
    constant function FS_AbilityID takes nothing returns integer
        return 'A000'
    endfunction
    //---- Loop interval ----\\
    constant function FS_Interval takes nothing returns real
        return 0.03125
    endfunction
    //---- Travelling time to target (in second) ----\\
    constant function FS_TravelTime takes nothing returns real
        return 0.45
    endfunction
    //---- Animation index played when moving to target ----\\
    constant function FS_AnimationIndex takes nothing returns integer
        return 2
    endfunction
    //---- Minimum distance between caster and target ----\\
    constant function FS_SlashDistance takes nothing returns real
        return 100.00
    endfunction
    //---- Damage range when moving ----\\
    constant function FS_Collision takes nothing returns real
        return 75.00
    endfunction
    //---- Damage per second duration to unit that hitted by caster when moving ----\\
    constant function FS_HitDPSDuration takes nothing returns real
        return 5.00
    endfunction
    //---- Damage per second duration to target ----\\
    constant function FS_SlashDPSDuration takes nothing returns real
        return 8.00
    endfunction
    //---- Effect attached to caster when moving ----\\
    constant function FS_WeaponSFX takes nothing returns string
        return "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl"
    endfunction
    //---- Attachment point for FS_WeaponSFX ----\\
    constant function FS_WeaponSFXAttach takes nothing returns string
        return "weapon"
    endfunction
    //---- Effect attached to unit that hitted by caster when moving ----\\
    constant function FS_HitSFX takes nothing returns string
        return "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
    endfunction
    //---- Attachment point for FS_HitSFX ----\\
    constant function FS_HitSFXAttach takes nothing returns string
        return "chest"
    endfunction
    //---- Effect attached to target when slashed ----\\
    constant function FS_SlashSFX takes nothing returns string
        return "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"
    endfunction
    //---- Attachment point for FS_SlashSFX ----\\
    constant function FS_SlashSFXAttach takes nothing returns string
        return "origin"
    endfunction
    //---- Effect attached to burning unit ----\\
    constant function FS_BurnSFX takes nothing returns string
        return "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"
    endfunction
    //---- Attachment point for FS_BurnSFX ----\\
    constant function FS_BurnSFXAttach takes nothing returns string
        return "chest"
    endfunction
    //---- Attack-type ----\\
    constant function FS_HitAttackType takes nothing returns attacktype
        return ATTACK_TYPE_NORMAL
    endfunction
    //---- Damage-type ----\\
    constant function FS_HitDamageType takes nothing returns damagetype
        return DAMAGE_TYPE_FIRE
    endfunction
    //---- Attack-type ----\\
    constant function FS_SlashAttackType takes nothing returns attacktype
        return ATTACK_TYPE_NORMAL
    endfunction
    //---- Damage-type ----\\
    constant function FS_SlashDamageType takes nothing returns damagetype
        return DAMAGE_TYPE_FIRE
    endfunction
    //---- Attack-type ----\\
    constant function FS_BurnAttackType takes nothing returns attacktype
        return ATTACK_TYPE_NORMAL
    endfunction
    //---- Damage-type ----\\
    constant function FS_BurnDamageType takes nothing returns damagetype
        return DAMAGE_TYPE_FIRE
    endfunction
    //---- Damage dealt to unit hitted by caster when moving ----\\
    function FS_HitDamage takes real level returns real
        return level * 10 + 40
    endfunction
    //---- Damage per second dealt to unit hitted by caster when moving ----\\
    function FS_HitDPS takes real level returns real
        return level * 5
    endfunction
    //---- Damage dealt to target when slashed ----\\
    function FS_SlashDamage takes real level returns real
        return level * 25 + 75
    endfunction
    //---- Damage per second dealt to target when slashed ----\\
    function FS_SlashDPS takes real level returns real
        return level * 10
    endfunction
    //---- Checker to units that are going to be damaged if all the conditions are true ----\\
    function FS_FilterUnit takes unit u, integer index returns boolean
        if (IsUnitEnemy(u, udg_FS_Owner[index]) and IsUnitType(u, UNIT_TYPE_FLYING) == false and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) == false) then
            return true
        endif
        return false
    endfunction
    
    //***************************************************************************
    //*
    //*  End of Configuration
    //*
    //***************************************************************************
    
    //***************************************************************************
    //*
    //*  Periodic Function
    //*
    //***************************************************************************
    
    function FS_Periodic takes nothing returns nothing
        local real x
        local real y
        local real x2
        local real y2
        local real angle
        local real dist
        local real speed
        local unit u
        local integer index = 1
        loop
            exitwhen index > udg_FS_MaxIndex
            if (udg_FS_Stage[index] == 1) then
                if (GetWidgetLife(udg_FS_Unit[index]) > 0.405 and GetWidgetLife(udg_FS_Target[index]) > 0.405 and udg_FS_Active[index]) then
                    set x = GetUnitX(udg_FS_Unit[index])
                    set y = GetUnitY(udg_FS_Unit[index])
                    set x2 = GetUnitX(udg_FS_Target[index])
                    set y2 = GetUnitY(udg_FS_Target[index])
                    set angle = Atan2(y2 - y, x2 - x)
                    set x2 = x2 - FS_SlashDistance() * Cos(angle)
                    set y2 = y2 - FS_SlashDistance() * Sin(angle)
                    set dist = SquareRoot((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y))
                    set udg_FS_Counter[index] = udg_FS_Counter[index] - FS_Interval()
                    if (udg_FS_Counter[index] > 0.05) then
                        set speed = dist / (udg_FS_Counter[index] / FS_Interval())
                        set x = x + speed * Cos(angle)
                        set y = y + speed * Sin(angle)
                        call SetUnitX(udg_FS_Unit[index], x)
                        call SetUnitY(udg_FS_Unit[index], y)
                        call GroupEnumUnitsInRange(udg_FS_TempGroup, x, y, FS_Collision(), null)
                        loop
                            set u = FirstOfGroup(udg_FS_TempGroup)
                            exitwhen u == null
                            if (FS_FilterUnit(u, index) and IsUnitInGroup(u, udg_FS_DamagedGroup[index]) == false and u != udg_FS_Target[index]) then
                                call DestroyEffect(AddSpecialEffectTarget(FS_HitSFX(), u, FS_HitSFXAttach()))
                                call UnitDamageTarget(udg_FS_Unit[index], u, FS_HitDamage(udg_FS_Level[index]), true, false, FS_HitAttackType(), FS_HitDamageType(), null)
                                call GroupAddUnit(udg_FS_DamagedGroup[index], u)
                                if (GetWidgetLife(u) > 0.405) then
                                    set udg_FS_MaxIndex = udg_FS_MaxIndex + 1
                                    set udg_FS_Target[udg_FS_MaxIndex] = udg_FS_Unit[index]
                                    set udg_FS_Unit[udg_FS_MaxIndex] = u
                                    set udg_FS_Duration[udg_FS_MaxIndex] = FS_HitDPSDuration()
                                    set udg_FS_DPS[udg_FS_MaxIndex] = FS_HitDPS(udg_FS_Level[index])
                                    set udg_FS_Counter[udg_FS_MaxIndex] = 0
                                    set udg_FS_ModelFX[udg_FS_MaxIndex] = AddSpecialEffectTarget(FS_BurnSFX(), udg_FS_Unit[udg_FS_MaxIndex], FS_BurnSFXAttach())
                                    set udg_FS_Stage[udg_FS_MaxIndex] = 2
                                endif
                            endif
                            call GroupRemoveUnit(udg_FS_TempGroup, u)
                        endloop
                        call GroupClear(udg_FS_TempGroup)
                    else
                        call SetUnitX(udg_FS_Unit[index], x2)
                        call SetUnitY(udg_FS_Unit[index], y2)
                        call UnitDamageTarget(udg_FS_Unit[index], udg_FS_Target[index], FS_SlashDamage(udg_FS_Level[index]), true, false, FS_SlashAttackType(), FS_SlashDamageType(), null)
                        call DestroyEffect(AddSpecialEffectTarget(FS_SlashSFX(), udg_FS_Target[index], FS_SlashSFXAttach()))
                        set udg_FS_MaxIndex = udg_FS_MaxIndex + 1
                        set udg_FS_Target[udg_FS_MaxIndex] = udg_FS_Unit[index]
                        set udg_FS_Unit[udg_FS_MaxIndex] = udg_FS_Target[index]
                        set udg_FS_Duration[udg_FS_MaxIndex] = FS_SlashDPSDuration()
                        set udg_FS_DPS[udg_FS_MaxIndex] = FS_SlashDPS(udg_FS_Level[index])
                        set udg_FS_Counter[udg_FS_MaxIndex] = 0
                        set udg_FS_ModelFX[udg_FS_MaxIndex] = AddSpecialEffectTarget(FS_BurnSFX(), udg_FS_Unit[udg_FS_MaxIndex], FS_BurnSFXAttach())
                        set udg_FS_Stage[udg_FS_MaxIndex] = 2
                        set udg_FS_Active[index] = false
                    endif
                else
                    call DestroyEffect(udg_FS_ModelFX[index])
                    call DestroyGroup(udg_FS_DamagedGroup[index])
                    set udg_FS_Stage[index] = 3
                endif
            endif
            if (udg_FS_Stage[index] == 2) then
                if (GetWidgetLife(udg_FS_Unit[index]) > 0.405 and udg_FS_Duration[index] > 0) then
                    set udg_FS_Counter[index] = udg_FS_Counter[index] + FS_Interval()
                    if (udg_FS_Counter[index] > 1) then
                        call UnitDamageTarget(udg_FS_Target[index], udg_FS_Unit[index], udg_FS_DPS[index], true, false, FS_BurnAttackType(), FS_BurnDamageType(), null)
                        set udg_FS_Counter[index] = 0
                    endif
                    set udg_FS_Duration[index] = udg_FS_Duration[index] - FS_Interval()
                else
                    call DestroyEffect(udg_FS_ModelFX[index])
                    call DestroyGroup(udg_FS_DamagedGroup[index])
                    set udg_FS_Stage[index] = 3
                endif
            endif
            if (udg_FS_Stage[index] == 3) then
                set udg_FS_Active[index] = udg_FS_Active[udg_FS_MaxIndex]
                set udg_FS_Counter[index] = udg_FS_Counter[udg_FS_MaxIndex]
                set udg_FS_DamagedGroup[index] = udg_FS_DamagedGroup[udg_FS_MaxIndex]
                set udg_FS_DPS[index] = udg_FS_DPS[udg_FS_MaxIndex]
                set udg_FS_Duration[index] = udg_FS_Duration[udg_FS_MaxIndex]
                set udg_FS_Level[index] = udg_FS_Level[udg_FS_MaxIndex]
                set udg_FS_ModelFX[index] = udg_FS_ModelFX[udg_FS_MaxIndex]
                set udg_FS_Owner[index] = udg_FS_Owner[udg_FS_MaxIndex]
                set udg_FS_Stage[index] = udg_FS_Stage[udg_FS_MaxIndex]
                set udg_FS_Target[index] = udg_FS_Target[udg_FS_MaxIndex]
                set udg_FS_Unit[index] = udg_FS_Unit[udg_FS_MaxIndex]
                set udg_FS_MaxIndex = udg_FS_MaxIndex - 1
                if (udg_FS_MaxIndex == 0) then
                    call PauseTimer(udg_FS_Timer)
                endif
                set index = index - 1
            endif
            set index = index + 1
        endloop
    endfunction
    
    //***************************************************************************
    //*
    //*  Starter Function
    //*
    //***************************************************************************
    
    function FS_Cast takes nothing returns boolean
        if (GetSpellAbilityId() == FS_AbilityID()) then
            set udg_FS_MaxIndex = udg_FS_MaxIndex + 1
            set udg_FS_Unit[udg_FS_MaxIndex] = GetTriggerUnit()
            set udg_FS_Target[udg_FS_MaxIndex] = GetSpellTargetUnit()
            set udg_FS_Owner[udg_FS_MaxIndex] = GetTriggerPlayer()
            set udg_FS_Level[udg_FS_MaxIndex] = I2R(GetUnitAbilityLevel(udg_FS_Unit[udg_FS_MaxIndex], FS_AbilityID()))
            set udg_FS_Counter[udg_FS_MaxIndex] = FS_TravelTime()
            set udg_FS_ModelFX[udg_FS_MaxIndex] = AddSpecialEffectTarget(FS_WeaponSFX(), udg_FS_Unit[udg_FS_MaxIndex], FS_WeaponSFXAttach())
            set udg_FS_DamagedGroup[udg_FS_MaxIndex] = CreateGroup()
            set udg_FS_Active[udg_FS_MaxIndex] = true
            set udg_FS_Stage[udg_FS_MaxIndex] = 1
            call SetUnitAnimationByIndex(udg_FS_Unit[udg_FS_MaxIndex], FS_AnimationIndex())
            if (udg_FS_MaxIndex == 1) then
                call TimerStart(udg_FS_Timer, FS_Interval(), true, function FS_Periodic)
            endif
        endif
        return false
    endfunction
    
    //***************************************************************************
    //*
    //*  Initializer Function
    //*
    //***************************************************************************
    
    function InitTrig_Fiery_Slash takes nothing returns nothing
        set gg_trg_Fiery_Slash = CreateTrigger()
        if (udg_FS_Timer == null) then
            set udg_FS_Timer = CreateTimer()
        endif
        set udg_FS_TempGroup = CreateGroup()
        call TriggerRegisterAnyUnitEventBJ(gg_trg_Fiery_Slash, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(gg_trg_Fiery_Slash, Filter(function FS_Cast))
    endfunction
  • Credits
    - Tank-Commander: Basic indexing.
  • Changelog
    - v1.0: Initial version.
    - v1.1: More configurables, fixed some things.
    - v1.2: Fixed some things.

Keywords:
Fire, Slash, Burn, DPS, Time Travel.
Contents

Test Map (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 19:30, 29th Jun 2013 Magtheridon96: Review Don't use life to determine if a unit is alive or not. It is possible for me to have a dead unit with 400 life. Check not IsUnitType(u...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.

19:30, 29th Jun 2013
Magtheridon96:

Review

  • Don't use life to determine if a unit is alive or not. It is possible for me to have a dead unit with 400 life. Check not IsUnitType(u, UNIT_TYPE_DEAD) and GetUnitTypeId(u) != 0 to determine if a unit is alive. It's about as close as you can get without using UnitEvent by Nestharus (a vJASS resource).
  • You don't need to call GroupClear after you enumerate the units in the group. GroupEnumUnitsInRange does that for you before it adds units to the group.
  • The Filter function must contain the boolean expression that assures a unit can only be damaged once and the expression that assures that the enumerated unit is not the target. This makes it explicit for the user. If he wants to change the mechanics of the spell, this makes it easier for him.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
u should change this.
JASS:
function FS_FilterUnit takes unit u, integer index returns boolean
    if (IsUnitEnemy(u, udg_FS_Owner[index]) and IsUnitType(u, UNIT_TYPE_FLYING) == false and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) == false) then
        return true
    endif
    return false
endfunction
to this
JASS:
function FS_FilterUnit takes unit u, integer index returns boolean
    return IsUnitEnemy(u, udg_FS_Owner[index]) and not IsUnitType(u, UNIT_TYPE_FLYING) and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)
endfunction
for this u should also check if the unit type is dead. u can still heal dead units which will increase there health over .405 even tho they r still dead
JASS:
(GetWidgetLife(udg_FS_Unit[index]) > 0.405 and GetWidgetLife(udg_FS_Target[index]) > 0.405 and udg_FS_Active[index])
change this
JASS:
if (FS_FilterUnit(u, index) and IsUnitInGroup(u, udg_FS_DamagedGroup[index]) == false and u != udg_FS_Target[index]) then
to this
JASS:
if (FS_FilterUnit(u, index) and not IsUnitInGroup(u, udg_FS_DamagedGroup[index]) and u != udg_FS_Target[index]) then
u should use one global group rather than the group array like almia said
 
Top