• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[Solved] Difficulties making MUI ability

Status
Not open for further replies.
Level 13
Joined
Mar 24, 2013
Messages
1,105
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.

JASS:
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
 

Attachments

  • Predator_Reforged.w3x
    88.8 KB · Views: 22
Last edited:
Level 12
Joined
Feb 22, 2010
Messages
1,115
For start, in your cancel function, these:

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

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

Did not check whether there are any other mistakes or not.
 
Level 13
Joined
Mar 24, 2013
Messages
1,105
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.

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.

For start, in your cancel function, these:

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

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

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

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

Thank you!
 
Last edited:
Status
Not open for further replies.
Top