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

[JASS] Mass Teleport via Blink Spell

Status
Not open for further replies.
Level 13
Joined
Jul 26, 2008
Messages
1,009
Alright, I'm trying to create a Mass Teleport spell using blink and trigger based special effects. Also, instead of normal mass teleport that only moves your units, this can move allied units as well.

The blink has a 1.2 second cast time, to allow the special effects to do what they need to do.

My biggest problem here is that I have issues with Wait type commands and Select every unit in location.

I wanted to set pick every unit in location and attach them to a local variable, then refer to that variable afterward, but the pick every unit in location I know how to do creates a new function, which doesn't work with local variables. I was thinking of placing them in a struct, but I'm only on the fringe of knowledge with structs and am not sure if this'd work or exactly how to set it up.

Right now, it's a single unit blink spell with special effects.

The spell HAS to be MUI/MPI. Anyways, here it is:

JASS:
function Trig_Blink_Copy_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'Blin' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Blink_Copy_Actions takes nothing returns nothing
    local effect SFX
    local effect SFX2
    call AddSpecialEffectLocBJ( GetUnitLoc(GetTriggerUnit()), "Abilities\\Spells\\Undead\\Darksummoning\\DarkSummonTarget.mdl" )
    set SFX = GetLastCreatedEffectBJ()
    call PolledWait( 0.60 )
    call AddSpecialEffectLocBJ( GetSpellTargetLoc(), "Abilities\\Spells\\Undead\\Darksummoning\\DarkSummonTarget.mdl" )
    set SFX2 = GetLastCreatedEffectBJ()
    call PolledWait( 0.30 )
    call DestroyEffect( SFX )
    call PolledWait( 1.20 )
    call DestroyEffect( SFX2 )
endfunction

//===========================================================================
function InitTrig_Blink_Copy takes nothing returns nothing
    set gg_trg_Blink_Copy = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Blink_Copy, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
    call TriggerAddCondition( gg_trg_Blink_Copy, Condition( function Trig_Blink_Copy_Conditions ) )
    call TriggerAddAction( gg_trg_Blink_Copy, function Trig_Blink_Copy_Actions )
endfunction
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
What you'd want to do is group all the units in your <radius> around your caster that match <parameters> (such as allied, etc), then move them all to the new location (move the caster first so he will always be in the middle) and simply add in-between a blink special effect on each of them.
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
To Ghostwolf:

Yes, I'm well aware of what I have to do and have already attempted that, knowing full and well that it wouldn't work. I'm mentioned structs, so you have to figure I'm a bit above being told what the spell needs to work.

However, placing a [Pick Every Unit] function into the mix up along with Sleep Trigger/PolledWait causes huge problems. (I figured at this point that would be common knowledge)
Mainly everything after the wait fails in a trigger that has Pick Every Unit. The special effects don't get destroyed. So, you end up with these FX that just sit there in your map and can never be removed.
Fail.
If the teleportation bit happens after the wait, then the units don't get moved either.
Bigger fail.

To Day-Elven: That's nice and all, but Mass Teleport doesn't fit these spell paramaters. Mass Teleport can't move allied. It only moves your own units. Plus if you had taken a look at the spell, it's not the mass teleport art I was after, but a the dark summoning animation. Not to mention you would STILL get the rune beneath the heroe's feet if you did do that.

Anyone else? Because the suggestions I've just heard do not solve the problem, but I know I've seen this spell executed before, and I know I've seen spells work that include multiple units and time initiated commands. Do I have to use a timer here? Is that it?
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
To Ghostwolf:

Yes, I"m well aware of what I have to do and have already attempted that. However, placing such a function into the mix up along with waits causes huge problems. Mainly everything after the wait fails. The special effects don't get destroyed. So, you end up with these FX that just sit there in your map and can never be removed.
Fail.
If the teleportation bit happens after the wait, then the units don't get moved either.
Bigger fail.

That's just because you don't know how to do it :p

[edit for the lulz]

Here, I even took my time (2 minutes) to make it for you.

JASS:
function Blabla takes nothing returns nothing
    local unit Shishkebab = GetTriggerUnit()
    local unit LOL
    local player LMAO = GetOwningPlayer(Shishkebab)
    local location I_AM_COOL = GetSpellTargetLoc()
    local real Awesome = GetLocationX(I_AM_COOL)
    local real This_Isnt_Funny = GetLocationY(I_AM_COOL)
    local group Actually_It_Is
    local string YESSSSSSSSSS = "Abilities\\Spells\\NightElf\\Blink\\BlinkTarget.mdl"
    
    // do whatever waits or things you want to do

    call GroupEnumUnitsInRange(Actually_It_Is,GetUnitX(Shishkebab),GetUnitY(Shishkebab),500,null)
    
    call DestroyEffect(AddSpecialEffectTarget(YESSSSSSSSSS,Shishkebab,"Origin"))
    call SetUnitX(Shishkebab,Awesome)
    call SetUnitY(Shishkebab,This_Isnt_Funny)
                    
    loop
        set LOL = FirstOfGroup(Actually_It_Is)
        exitwhen LOL == null
        call GroupRemoveUnit(Actually_It_Is,LOL)
        if IsPlayerAlly(GetOwningPlayer(LOL),LMAO) then
            call DestroyEffect(AddSpecialEffectTarget(YESSSSSSSSSS,LOL,"Origin"))
            call SetUnitX(LOL,Awesome)
            call SetUnitY(LOL,This_Isnt_Funny)
        endif
    endloop
    
    set Shishkebab = null
    call RemoveLocation(I_AM_COOL)
    set I_AM_COOL = null  
    call DestroyGroup(Actually_It_Is)
    set Actually_It_Is = null    
endfunction
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
Awesome! Now that is what I needed.
And you were quiet right, I didn't know how to do it.

I was only aware of the primitive way via GUI and manipulated JASS. I wasn't sure how to do pick every unit in range without using a seperate function for conditions. In other words, the GUI conversion way. What you've showed me fixes so many of my dilemmas with AoE spells that have waits in them and wouldn't work :D

I didn't realize I'd have to declare so many local variables, but it's not a big deal so long as I destroy them. I'll be sure to make a habit of doing this instead of the manner I have been :3 Much appreciated.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I was only aware of the primitive way via GUI and manipulated JASS. I wasn't sure how to do pick every unit in range without using a seperate function for conditions.

You can do it also with that.

JASS:
function meh takes nothing returns boolean
    return IsPlayerAlly(GetOwningPlayer(GetEnumUnit()),GetOwningPlayer(GetTriggerUnit()))
endfunction

...

call GroupEnumUnitsInRange(group,x,y,radius,Condition(function meh))

I just never liked using separate functions without having to.
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
Hmm, doesn't seem to work :\ I placed what I needed within the code, but it doesn't even start.

JASS:
function Trig_Blink_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'Blin' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Blink_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local unit u2
    local player p = GetOwningPlayer(u)
    local location loc = GetSpellTargetLoc()
    local real r1 = GetLocationX(loc)
    local real r2 = GetLocationY(loc)
    local group g
    local string str = "Abilities\\Spells\\Undead\\Darksummoning\\DarkSummonTarget.mdl"
    call AddSpecialEffectTarget(str,u,"Origin")
    call PolledWait( 0.60 )
    call AddSpecialEffectLocBJ( GetSpellTargetLoc(), str )
    call GroupEnumUnitsInRange(g,GetUnitX(u),GetUnitY(u),750,null)
    call PolledWait( 0.30 )
    call DestroyEffect(AddSpecialEffectTarget(str,u,"Origin"))
    call SetUnitX(u,r1)
    call SetUnitY(u,r2)
    loop
        set u2 = FirstOfGroup(g)
        exitwhen u2 == null
        call GroupRemoveUnit(g,u2)
            if IsPlayerAlly(GetOwningPlayer(u2),p) then
            call DestroyEffect(AddSpecialEffectTarget(str,u2,"Origin"))
            call SetUnitX(u2,r1)
            call SetUnitY(u2,r2)
        endif
    endloop
    call PolledWait( 1.20 )
    call DestroyEffect(AddSpecialEffectLocBJ( GetSpellTargetLoc(), str))
    set u = null
    call RemoveLocation(loc)
    set loc = null
    call DestroyGroup(g)
    set g = null
    endfunction
//===========================================================================
function InitTrig_Blink takes nothing returns nothing
    set gg_trg_Blink = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Blink, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
    call TriggerAddCondition( gg_trg_Blink, Condition( function Trig_Blink_Conditions ) )
    call TriggerAddAction( gg_trg_Blink, function Trig_Blink_Actions )
endfunction
 
Last edited:
Level 13
Joined
Jul 26, 2008
Messages
1,009
For the most part yes, because the spell has a 1.2 cast time. The point of the 1.2 cast time is so that the spell initiates it's special effects in the proper order and so the effects have a chance to go off.

So begins channeling does what it needs to. On the original spell that was a single person blink spell with special effects, it worked properly.
 
Status
Not open for further replies.
Top