Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[Spell] jass spell

Discussion in 'World Editor Help Zone' started by masih_julius, Oct 20, 2020.

  1. masih_julius

    masih_julius

    Joined:
    Aug 14, 2020
    Messages:
    100
    Resources:
    0
    Resources:
    0
    this is pyroblast jass spell,it works fine I need some one explain this for me, what is the job of each part.

    Code (Text):
     
    function Pyroblast_Cond takes nothing returns boolean
        return GetSpellAbilityId()=='A005'
    endfunction

    function Pyroblast_Move takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer h = GetHandleId(t)
        local unit pyroblast = LoadUnitHandle(Hash,h,1)
        local unit target = LoadUnitHandle(Hash,h,2)
        local unit caster = LoadUnitHandle(Hash,h,3)
        local real X1 = GetUnitX(pyroblast)
        local real X2 = GetUnitX(target)
        local real Y1 = GetUnitY(pyroblast)
        local real Y2 = GetUnitY(target)
        local real angle = Atan2(Y2 - Y1, X2 - X1)
        local player PlayerCaster = GetOwningPlayer(caster)
        local integer data = GetUnitUserData(caster)
        local real damage = DamagePyroblast[0][data]
        local real damageLow = DamagePyroblastRect[0][data]
        local real dist = SquareRoot((X2 - X1) * (X2 - X1) + (Y2 - Y1) * (Y2 - Y1))
        local real distance = 200
        if GetWidgetLife( target ) >.405 then
        call SetUnitFacing(pyroblast, angle*bj_RADTODEG)
        call SetUnitFlyHeight(pyroblast,GetUnitFlyHeight(target),dist)
        call SetUnitX(pyroblast, X1 + 2.5 * Cos(angle))
        call SetUnitY(pyroblast, Y1 + 2.5 * Sin(angle))
            if dist <= 10.00 then
                local group G = CreateGroup()
                local unit enemy
                local player player1
                call GroupEnumUnitsInRange(G, X1, Y1, distance, null)
                loop
                    set enemy = FirstOfGroup(G)
                    player1 = GetOwningPlayer(enemy)
                    if IsPlayerEnemy(player1, PlayerCaster) and enemy != target then
                        call UnitDamageTarget( caster, enemy, damageLow, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
                    endif
                    call GroupRemoveUnit(G,enemy)
                    exitwhen enemy == null
                endloop
                call UnitDamageTarget( caster, target, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE, null )
                call KillUnit(pyroblast)
                call GroupClear(G)
                call DestroyGroup(G)
                call FlushChildHashtable(Hash,h)
                call PauseTimer(t)
                call DestroyTimer(t)
                set G = null
                set player1 = null
            endif
        else
            call UnitRemoveAbility( caster, 'A005' )
            call UnitAddAbility( caster, 'A005' )
            call KillUnit(pyroblast)
            call FlushChildHashtable(Hash,h)
            call PauseTimer(t)
            call DestroyTimer(t)
        endif
       
        set t = null
        set pyroblast = null
        set caster = null
        set target = null
    endfunction

    function Pyroblast_Scale takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer h = GetHandleId(t)
        local unit pyroblast = LoadUnitHandle(Hash,h,1)
        local unit array dummy
        local unit target = LoadUnitHandle(Hash,h,2)
        local unit caster = LoadUnitHandle(Hash,h,3)
        local real scale = LoadReal(Hash,h,4)
        local real face = GetUnitFacing(caster)
        local real X1 = GetUnitX(caster) + 75 * Cos(face* bj_DEGTORAD)
        local real x1 = GetUnitX(caster)
        local real X2 = GetUnitX(target)
        local real Y1 = GetUnitY(caster) + 75 * Sin(face* bj_DEGTORAD)
        local real Y2 = GetUnitY(target)
        local integer n = 0
        local boolean spell = GetUnitCurrentOrder(caster) == 852119
        if spell == true and IsUnitType(caster, UNIT_TYPE_STUNNED) == false or GetWidgetLife( caster ) >.405  then
            local real dist = 1.50
            set scale = scale + 0.05
            call SetUnitScale( pyroblast, scale, scale, scale )
            call SetUnitPosition(pyroblast, X1, Y1)
            call SetUnitFacing(pyroblast,face)
            if scale >= dist then
                local timer tick = CreateTimer()
                local integer l = GetHandleId(tick)
                call UnitRemoveAbility( caster, 'Amrf' )
                loop
                exitwhen (n == 11)
                    set dummy[n] = LoadUnitHandle(Hash,h,5+n)
                    call KillUnit(dummy[n])
                    set dummy[n] = null
                set n = n + 1
                endloop
                call SaveUnitHandle(Hash,l,1,pyroblast)
                call SaveUnitHandle(Hash,l,2,target)
                call SaveUnitHandle(Hash,l,3,caster)
                call TimerStart(tick,.01,true,function Pyroblast_Move)
                call FlushChildHashtable(Hash,h)
                call PauseTimer(t)
                call DestroyTimer(t)
                set tick = null
            else
                call SaveReal(Hash,h,4,scale)
                if scale == 0.65 then
                    call SetUnitAnimationByIndex(caster,5)
                    QueueUnitAnimation(caster,"stand")
                endif
            endif
           
            set pyroblast = null
            set target = null
            set caster = null
            set t = null
        else
           
            call UnitRemoveAbility( caster, 'A005' )
            call UnitAddAbility( caster, 'A005' )
            loop
            exitwhen (n == 11)
                set dummy[n] = LoadUnitHandle(Hash,h,5+n)
                call KillUnit(dummy[n])
                set dummy[n] = null
            set n = n + 1
            endloop
            call KillUnit(pyroblast)
            call FlushChildHashtable(Hash,h)
            call PauseTimer(t)
            call DestroyTimer(t)
            set pyroblast = null
            set target = null
            set caster = null
            set t = null
        endif
    endfunction

    function Pyroblast takes nothing returns nothing
        local unit caster = GetTriggerUnit()
        local unit target = GetSpellTargetUnit()
        local timer t = CreateTimer()
        local integer h = GetHandleId(t)
        local real face = GetUnitFacing(caster)
        local player PlayerCaster = GetOwningPlayer(caster)
        local real scale = 1.0
        local real x = GetUnitX(caster) + 75 * Cos(face* bj_DEGTORAD)
        local real x1 = GetUnitX(caster)
        local real y = GetUnitY(caster) + 75 * Sin(face* bj_DEGTORAD)
        local real y1 = GetUnitY(caster)
        local unit pyroblast = CreateUnit( PlayerCaster, 'h001', x, y, face )
        local unit array dummy
       
        local integer i = 'h007'
        local integer l = 0
        loop
       exitwhen (l == 11)
            if (l == GetPlayerId(PlayerCaster) and GetLocalPlayer() == PlayerCaster) then
                i = 'h004'
            endif
        set dummy[l] = CreateUnit( Player(l), i, x, y, face )
        call SetUnitTimeScale( dummy[l], 0.50 )
        call SetUnitScale( dummy[l], 1.5, 1, 1 )
        call SaveUnitHandle(Hash,h,5+l,dummy[l])
            set i = 'h007'
        set dummy[l] = null
       set l = l + 1
        endloop
        call SetUnitPathing( pyroblast, false )
        call SetUnitScale( pyroblast, scale, scale, scale )
        call SaveUnitHandle(Hash,h,1,pyroblast)
        call SaveUnitHandle(Hash,h,2,target)
        call SaveUnitHandle(Hash,h,3,caster)
        call TimerStart(t,.05,true,function Pyroblast_Scale)
        set t = null
        set pyroblast = null
        set caster = null
        set target = null
    endfunction

    //===========================================================================
    function InitTrig_Pyroblast takes nothing returns nothing
        set gg_trg_Pyroblast = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( gg_trg_Pyroblast, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
        call TriggerAddCondition( gg_trg_Pyroblast, Condition( function Pyroblast_Cond ) )
        call TriggerAddAction( gg_trg_Pyroblast, function Pyroblast )
    endfunction [\CODE]
     
  2. biridius

    biridius

    Joined:
    Apr 3, 2018
    Messages:
    197
    Resources:
    4
    Maps:
    4
    Resources:
    4
    The very bottom function ("InitTrig_Pyroblast") is the initialization of the trigger done when the map is first loading. It defines the trigger's event, conditions and actions.
    The trigger's first action when the spell is cast is the function "Pyroblast" directly above it.
    "Pyroblast_Cond" (on the very top) is the trigger's condition just checks which spell was cast.

    function Pyroblast (on cast).
    It creates a "projectile" unit of type 'h001' 75 points in front of the caster.
    Then, it also creates a dummy for every player. For the spell's caster, the dummy will have a different type 'h004' (don't know what it is for without objective editor data, probably just has a differet looking model). This will only be seen on that player's computer which is achieved through using GetLocalPlayer() - on everyone else's computers, the function will create unit 'h007'.
    After all this, it saves all those things (caster, target, projectile, dummies) on a timer through the hashtable.

    function Pyroblast_Scale (periodic on timer)
    First it detects if the caster is still channeling an ability with "chainlightning" order, if not, the spell finishes and dummies die.
    It then makes the main "projectile" grow in size while it remains in front of the caster.
    Once its scale reaches 65%, the caster's animation changes to an animation with index 5 (don't know what it is without the model, likely some next stage of casting the spell).
    Once its scale reaches 150%, it kills all the previously created dummies and the timer, and creates a new timer which launches the next function.

    function Pyroblast_Move (next stage timer)
    This function moves the projectile towards the spell's target.
    It uses Atan2 to calculate the angle towards the target, then moves the projectile 2.5 points along that direction.
    If the target dies before the projectile reaches it, the spell ends.
    Once the projectile reaches the target, it damages all enemy units in a 200 radius, and deals different damage to the main target.
    The damage amount itself seems to be kept in some arrays not defined in this trigger.
     
    Last edited: Oct 21, 2020
  3. masih_julius

    masih_julius

    Joined:
    Aug 14, 2020
    Messages:
    100
    Resources:
    0
    Resources:
    0
    Thanks♡, didn't understand all of it BUT must of it is clear now.
    just the hashtables, never used them before, that's the hardest part for me.
     
  4. biridius

    biridius

    Joined:
    Apr 3, 2018
    Messages:
    197
    Resources:
    4
    Maps:
    4
    Resources:
    4
    The hashtables are just a way to get the local variables from one function to work in another.

    So first we need something to tie them to, like a timer, and get its handle
    - integer h = GetHandleId(t)

    You can then attach a unit to that handle
    - SaveUnitHandle(Hash,h,1,pyroblast)
    here h is the handle id of the timer, and 1 is a key you choose for your variable like an array index, it should be different for each attached variable

    Then in your other function you can get the attached unit by using the same timer handle and key
    - local unit pyroblast = LoadUnitHandle(Hash,h,1)

    When the timer is destroyed, you also need to get rid of the data stored for it using
    - FlushChildHastable(Hash,h)
     
  5. Uncle

    Uncle

    Joined:
    Aug 10, 2018
    Messages:
    2,393
    Resources:
    0
    Resources:
    0
    If you're trying to learn Jass then I recommend learning Lua instead (if possible). This same spell would be a lot cleaner in Lua with no need for Hashtables.
     
  6. masih_julius

    masih_julius

    Joined:
    Aug 14, 2020
    Messages:
    100
    Resources:
    0
    Resources:
    0
    biridius
    uhhh,, I see now,so hashtable can carry our variables
    what of this part:

    local real X1 = GetUnitX(pyroblast)
    local real X2 = GetUnitX(target)
    local real Y1 = GetUnitY(pyroblast)
    local real Y2 = GetUnitY(target)
    local real angle = Atan2(Y2 - Y1, X2 - X1)

    uncle

    I can't use lua on P1.29,I guess it doesnt support it.
     
  7. biridius

    biridius

    Joined:
    Apr 3, 2018
    Messages:
    197
    Resources:
    4
    Maps:
    4
    Resources:
    4
    That part calculates an angle from the unit pyroblast to the target.
    It first takes the coordinates of the units, then uses the trigonometry function Arctangent to get the angle from the differences on the Y and X axis. The angle returned is in radians, not degrees. If it was Atan2BJ, it would return degrees.

    This angle is then used to move the projectile
    speed*Cos(angle) - speed on the X axis
    speed*Sin(angle) - speed on the Y axis
     
  8. masih_julius

    masih_julius

    Joined:
    Aug 14, 2020
    Messages:
    100
    Resources:
    0
    Resources:
    0
    thank you biridius for your help♡