1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  4. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  5. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  6. The results are out! Check them out.
    Dismiss Notice
  7. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  8. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  9. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[Solved] Difficulties making MUI ability

Discussion in 'Triggers & Scripts' started by pOke, Jul 27, 2019.

  1. pOke

    pOke

    Joined:
    Mar 24, 2013
    Messages:
    1,102
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Hello, I have made plenty of MUI abilities in the past, however, this one I am changing up the casting behavior which has caused me to run into some problems.

    The ability is based on channel and has a follow through time of 1.5 seconds.

    So basically, the ability will channel for 1.5 seconds then fire.

    I am saving the coordinates of the spell target with Starts the Effect of an Ability in GravityGunDetect

    I try to cancel/unsave any instances that are canceled prior to the full channel in GravityGunCancel (probably the issue)

    I am catching the finish of the channel with Finishes casting an ability in GravityGunFire.

    If I shift queue multiple units to cast this ability with no cd over and over, I have no issues. However, if I shift queue one or more, and then spam stop casts with intermittent full casts I inevitably break one or more.

    Cannot seem to figure out where I am going wrong, any help would be great. I've also attached a test map if it helps to visualize it.

    Code (vJASS):

    library Spaceman2 initializer init requires TimedEffect, Generic


            globals
        private unit array u
        private effect array e
        private real array d
        private real array pulse
        private boolean array b
        private boolean array cancelCast
        private real array gAngle
        private player array p
        private integer index = 0
     
        private constant group GG_GROUP = CreateGroup()
        private constant real TIMEOUT = .03125
        private timer t = CreateTimer()
        private timer t2 = CreateTimer()
        private constant integer GRAVITY_GUN = 'A001'
        private constant real DURATION = 5.
     
        private constant string EFFECT = "Abilities\\Spells\\Undead\\DarkSummoning\\DarkSummonMissile.mdl"
        private constant real OFFSET = 200.
        private constant real OFFSET2 = 11. // Gravity MS (1000/3 * .03125)
     
        private constant string PULSE_EFFECT = "Abilities\\Spells\\Demon\\DemonBoltImpact\\DemonBoltImpact.mdl"
        private constant real PULSE_TIMEOUT = 1.5
        private constant real PULSE_AOE_CHECK = 500.
        private constant real PULSE_EFFECT_SCALE = 2.4
        private constant real PULSE_EFFECT_DURATION = .8
        private constant real PULSE_DAMAGE = 150.
     
        private boolean timerOn = false
         
            endglobals

    private function GGLoop takes nothing returns nothing
        local integer i = 0
        local group g = GG_GROUP
        local real x
        local real y
        local real x2
        local real y2
        local real angle
        local unit tU
        local effect tE

            loop
                exitwhen i >= index
         
            if not cancelCast[i] then
                set d[i] = d[i] - TIMEOUT
                set pulse[i] = pulse[i] - TIMEOUT
             
                set x = BlzGetLocalSpecialEffectX(e[i])
                set y = BlzGetLocalSpecialEffectY(e[i])
             
                set angle = OFFSET2 * Cos(gAngle[i])
                set x = x + angle
                set angle = OFFSET2 * Sin(gAngle[i])
                set y = y + angle

                call BlzSetSpecialEffectX(e[i], x)
                call BlzSetSpecialEffectY(e[i], y)
                call BlzSetSpecialEffectHeight( e[i], 100.00 )
                call BlzSetSpecialEffectOrientation(e[i], gAngle[i],0,0) // probably do not need.
             
                if pulse[i] <= 0. then
                    set tE = AddSpecialEffect(PULSE_EFFECT, x,y)
                    call BlzSetSpecialEffectScale(tE, PULSE_EFFECT_SCALE)
                    call BlzSetSpecialEffectColor(tE, 0, 255, 0)
                    call EffectApplyTimedLife(tE, PULSE_EFFECT_DURATION)            
             
                    call GroupEnumUnitsInRange(g, x, y, PULSE_AOE_CHECK, null)
                 
                    loop
                        set tU = FirstOfGroup(g)
                        exitwhen tU == null
                     
                        call GroupRemoveUnit(g, tU)
                        if UnitAlive(tU) and IsUnitEnemy(tU, GetOwningPlayer(u[i])) then
                       
                         // call UnitDamageTarget(u[i], tU, PULSE_DAMAGE, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)              
                        endif
                     
                    endloop
                 
                    call GroupClear(g)
                 
                    set pulse[i] = PULSE_TIMEOUT
                endif

                if d[i] <= 0. then
                    call DestroyEffect(e[i])
                    set index = index - 1
                    set u[i] = u[index]
                    set d[i] = d[index]
                    set e[i] = e[index]
                    set pulse[i] = pulse[index]
                    set cancelCast[i] = cancelCast[index]
                    set gAngle[i] = gAngle[index]
                    set e[index] = null
                    set u[index] = null          
                    set i = i - 1
                    if index == 0 then
                        call PauseTimer(t)
                        set timerOn = false
                    endif
                endif
            endif
            set i = i + 1
            endloop
         
        set g = null
        set tU = null
        set tE = null
    endfunction

    private function GravityGunFire takes nothing returns boolean
        local integer i = 0
     
        if GetSpellAbilityId() == GRAVITY_GUN then
     
            loop
                exitwhen i >= index
                if GetTriggerUnit() == u[i] and cancelCast[i] then
                    set cancelCast[i] = false
                    set d[i] = DURATION
                    set pulse[i] = .4
                    set e[i] = AddSpecialEffect(EFFECT, GetUnitX(u[i]), GetUnitY(u[i]))
                    call BlzSetSpecialEffectOrientation(e[i], gAngle[i],0,0)
                    call BlzSetSpecialEffectHeight( e[i], 50.00 )
                 
                    if index >= 1 and not timerOn then
                        call TimerStart(t, TIMEOUT, true, function GGLoop)
                        set timerOn = true
                    endif
                endif
         
            set i = i + 1
         
            endloop
        endif

        return false

    endfunction

    private function GravityGunCancel takes nothing returns boolean
        local integer i = 0
     
        if GetSpellAbilityId() == GRAVITY_GUN then
            loop
                exitwhen i >= index
             
                if GetTriggerUnit() == u[i] and cancelCast[i] then
                    set index = index - 1
                    set u[i] = u[index]
                    set d[i] = d[index]
                    set e[i] = e[index]
                    set pulse[i] = pulse[index]
                    set cancelCast[i] = cancelCast[index]
                    set gAngle[i] = gAngle[index]
                    set e[i] = null
                    set u[i] = null  
                    call BJDebugMsg("cast stopped, deindex")
                    return false
                endif
         
            set i = i + 1
         
            endloop
        endif

        return false

    endfunction

    private function GravityGunDetect takes nothing returns boolean
        local real x
        local real y
        local real x2
        local real y2
        if GetSpellAbilityId() == GRAVITY_GUN then
            set u[index] = GetTriggerUnit()
            set x = GetUnitX(u[index])
            set y = GetUnitY(u[index])
            set x2 = GetSpellTargetX()
            set y2 = GetSpellTargetY()
            set gAngle[index] = Atan2(y2-y,x2-x)
            set cancelCast[index] = true
            set d[index] = 0.
            set e[index] = null
            set pulse[index] = 0.    
            set index = index + 1
            call BJDebugMsg("cast primed")

        endif

        return false

    endfunction

    private function init takes nothing returns nothing
        local trigger t10 = CreateTrigger()
        local trigger t11 = CreateTrigger()
        local trigger t12 = CreateTrigger()
     
        call TriggerRegisterAnyUnitEventBJ( t10, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t10, Condition(function GravityGunDetect))
     
        call TriggerRegisterAnyUnitEventBJ( t11, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
        call TriggerAddCondition(t11, Condition(function GravityGunCancel))
     
       call TriggerRegisterAnyUnitEventBJ( t12, EVENT_PLAYER_UNIT_SPELL_FINISH)
        call TriggerAddCondition(t12, Condition(function GravityGunFire))

    endfunction

    endlibrary


     
     

    Attached Files:

    Last edited: Jul 27, 2019
  2. Chaosy

    Chaosy

    Joined:
    Jun 9, 2011
    Messages:
    10,621
    Resources:
    18
    Maps:
    1
    Spells:
    11
    Tutorials:
    6
    Resources:
    18
    Sooo, why bother with vjass unless you use structs? seems like a huge waste which complicates things needlessly.

    Pretty sure it would slim down the code considerably which makes it easier to debug in turn.
     
  3. Ceday

    Ceday

    Joined:
    Feb 22, 2010
    Messages:
    1,077
    Resources:
    0
    Resources:
    0
    For start, in your cancel function, these:

    Code (vJASS):

    set e[i] = null
    set u[i] = null  
    call BJDebugMsg("cast stopped, deindex")
     


    should be:
    Code (vJASS):

    set e[index] = null
    set u[index] = null  
    call BJDebugMsg("cast stopped, deindex")
     


    Did not check whether there are any other mistakes or not.
     
  4. pOke

    pOke

    Joined:
    Mar 24, 2013
    Messages:
    1,102
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Yeah, it's just regular JASS using the globals and library components of vJass. I will see if I can learn structs to better utilize available methods.

    This is probably it, I have not been able to get it to break after the tweak.

    Thank you!
     
    Last edited: Jul 27, 2019