• 🏆 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] Need help with ability

Status
Not open for further replies.
Level 10
Joined
Sep 29, 2006
Messages
447
I'm making an ability that picks every unit in front of the caster and casts storm bolt on that unit. With my trigger I can enable it in the editor, but when I go to save it I get an "Expected a name" error on the "loop" line, and I can't figure out why. Can anyone help? Also, can anyone see if this trigger will even work?

Here's the trigger:
JASS:
function ClusterRocketsConditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A009'
endfunction

function DummyActions takes unit u, real x, real y returns nothing
    local unit u2 = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 'h008', x, y, 0)
    call UnitAddAbility( u2, 'A00C' )
    call UnitApplyTimedLife( u2, 'BTLF', 2.00 )
    call IssueTargetOrder( u2, "thunderbolt", u )
    set u2 = null
endfunction

function GroupConditions takes nothing returns boolean
    local unit f = GetFilterUnit()
    local player p = GetOwningPlayer(GetTriggerUnit())
    return ( IsUnitEnemy(f, p) == true ) and ( IsUnitType(f, UNIT_TYPE_MECHANICAL) == true )
endfunction

function GetTargets takes unit u, real r returns nothing
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real xx
    local real yy
    local real angle
    local real face = GetUnitFacing(u)
    local real absmod
    local group g = CreateGroup()
    local unit u2
    call GroupEnumUnitsInRange(g, x, y, r, Condition(function GroupConditions))
    loop
        set u2 = FirstOfGroup(g)
        exitwhen u2 == null
        call GroupRemoveUnit(g,u2)
        set xx = GetUnitX(u2)
        set yy = GetUnitY(u2)
        set angle = Atan2(y-yy,x-xx) * bj_RADTODEG
        set absmod = ModuloReal(RAbsBJ(angle-face), 360)
        if absmod > 65 and absmod < 255 then
           call DummyActions(u2, x, y)
        endif 
    endloop
    call DestroyGroup(g)
    set g = null
endfunction

function ClusterRocketsActions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real r = 20000.00
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local player p = GetOwningPlayer(u)
    local integer i = GetConvertedPlayerId(GetOwningPlayer(u))
    call UnitRemoveAbility( u, GetSpellAbilityId() )
    set udg_AbilityInteger[i] = ( udg_AbilityInteger[i] - 1 )
    call GetTargets(u, r)
    call ResetAnim(u)
    set u = null
endfunction

//===========================================================================
function InitTrig_cluster_rockets_2 takes nothing returns nothing
    set gg_trg_cluster_rockets_2 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_cluster_rockets_2, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_cluster_rockets_2, Condition( function ClusterRocketsConditions ) )
    call TriggerAddAction( gg_trg_cluster_rockets_2, function ClusterRocketsActions )
endfunction

EDIT: Just as a heads up. The ResetAnim() function is a function in the map header and it works fine.
 
Last edited:
Level 16
Joined
Jun 9, 2008
Messages
734
should be like this?

JASS:
function ClusterRocketsConditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A009'
endfunction

function DummyActions takes unit u, real x, real y returns nothing
    local unit u2 = CreateUnit(GetOwningPlayer(u), 'h008', x, y, 0)
    call UnitAddAbilityBJ( 'A00C', u2 )
    call UnitApplyTimedLife( u2, 'BTLF', 2.00 )
    call IssueTargetOrder( u2, "thunderbolt", u )
    set u2 = null
endfunction

function GroupConditions takes nothing returns boolean
    local unit f = GetFilterUnit()
    local player p = GetOwningPlayer(GetTriggerUnit())
    return ( IsUnitEnemy(f, p) == true ) and ( IsUnitType(f, UNIT_TYPE_MECHANICAL) == true )
endfunction

function GetTargets takes unit u, real r returns nothing
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real xx
    local real yy
    local real angle
    local real face = GetUnitFacing(u)
    local real absmod
    local group g = CreateGroup()
    local unit u2
    call GroupEnumUnitsInRange(g, x, y, r, Condition(function GroupConditions))
    loop
        set u2 = FirstOfGroup(g)
        exitwhen u == null
        call GroupRemoveUnit(g,u2)
        set xx = GetUnitX(u2)
        set yy = GetUnitY(u2)
        set angle = Atan2(y-yy,x-xx) * bj_RADTODEG
        set absmod = ModuloReal(RAbsBJ(angle-face), 360)
        if absmod > 65 and absmod < 255 then
           call DummyActions(u2, x, y)
        endif
    endloop
    call DestroyGroup(g)
    set g = null
endfunction

function ClusterRocketsActions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local real r = 20000.00
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local player p = GetOwningPlayer(u)
    local integer i = GetConvertedPlayerId(GetOwningPlayer(u))
    call UnitRemoveAbility( u, GetSpellAbilityId() )
    set udg_AbilityInteger[i] = ( udg_AbilityInteger[i] - 1 )
    call GetTargets(u, r)
    call SetUnitAnimation(u,"stand")
    set u = null
endfunction

//===========================================================================
function InitTrig_cluster_rockets_2 takes nothing returns nothing
    set gg_trg_cluster_rockets_2 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_cluster_rockets_2, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_cluster_rockets_2, Condition( function ClusterRocketsConditions ) )
    call TriggerAddAction( gg_trg_cluster_rockets_2, function ClusterRocketsActions )
endfunction
 
Level 5
Joined
Dec 18, 2007
Messages
205
should be like this?

JASS:
    loop
        set u2 = FirstOfGroup(g)
        exitwhen u == null
        call GroupRemoveUnit(g,u2)
        set xx = GetUnitX(u2)
        set yy = GetUnitY(u2)
        set angle = Atan2(y-yy,x-xx) * bj_RADTODEG
        set absmod = ModuloReal(RAbsBJ(angle-face), 360)
        if absmod > 65 and absmod < 255 then
           call DummyActions(u2, x, y)
        endif
    endloop

when is the loop supposed to end? its infinite. and u does not exist

didnt see u being passed to the trigger, but remember: where is u set to null to exit the loop?
 
Level 8
Joined
Aug 6, 2008
Messages
451
Well, both your group and dummy caster usage are terrible.

You should check this vJass warstomp spell I made to teach one guy how to do Jass,. It shows pretty much nicely how to use GroupEnum and dummy caster to cast stormbolts:

JASS:
scope WarStomp initializer init
//====================================================================================
//ASDASDASDASDASDASDDDDASDASDASDASDASDASDASDDDDASDASDASDASDASDASDASDDDDASDASDASDASDASDASDASDDDDA
//==================================================================================
globals
            private constant integer ABILITY_ID = 'A000'
            private constant integer DEALERS_HAND = 'A001'
            private constant integer DEALER_ID = 'n000'
            private constant real AOE = 250.0
            private constant real DAMAGE = 25.0
            private constant string EFFECT_PATH = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"

//====================================================================================
//ASDASDASDASDASDASDDDDASDASDASDASDASDASDASDDDDASDASDASDASDASDASDASDDDDASDASDASDASDASDASDASDDDDASD
//====================================================================================    
    private group TempG = CreateGroup()
    private unit TempU
    private player TempP
    private integer TempInt
    private filterfunc F
    private unit Dealer
endglobals

private function Filtteri takes nothing returns boolean
    local unit u=GetFilterUnit()
    if not IsUnitAlly(u,TempP) and GetWidgetLife(u) > 0.405 then
         call SetUnitX(Dealer,GetUnitX(u))
         call SetUnitY(Dealer,GetUnitY(u))
         call IssueTargetOrder(Dealer,"thunderbolt",u)
         call UnitDamageTarget(TempU,u,DAMAGE*TempInt,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
    endif
    set u=null
    return false
endfunction

private function YesWeCan takes nothing returns nothing
     local unit u = GetTriggerUnit()
     local real x = GetUnitX(u)
     local real y = GetUnitY(u)
     set TempInt=GetUnitAbilityLevel(u,ABILITY_ID)
     set TempP=GetOwningPlayer(u)
     set TempU=u
     call DestroyEffect(AddSpecialEffect(EFFECT_PATH,x,y))
     call SetUnitAbilityLevel(Dealer,DEALERS_HAND,TempInt)
     call GroupEnumUnitsInRange(TempG,x,y,AOE,F)
     set u = null
endfunction

private function CanWeStomp takes nothing returns boolean
    return GetSpellAbilityId() == ABILITY_ID
endfunction

private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition(function CanWeStomp))
    call TriggerAddAction(t,function YesWeCan)
    set F = Filter(function Filtteri)
    set Dealer = CreateUnit(Player(13),DEALER_ID,0.0,0.0,0.0)
endfunction

endscope

You can find a test map from here: link ( Its mostly there because some noobs dont usually believe that it is better to use one dummy to cast all stormbolts, instead of creating shit loads of them every time the spell is casted. )
 
Level 10
Joined
Sep 29, 2006
Messages
447
Sorry, but I can't use vJASS I'm on a Mac. And the loop ends when "u2 == null" It was originally "u == null" but it was a mistake. It still produces the same error though.



EDIT: I fixed part of it I guess. In the DummyActions function p needed to be GetOwningPlayer(GetTriggerUnit()), but now I'm getting a new error on the "call UnitRemoveAbility(u, GetSpellAbilityId())" line. The error says "Invalid argument type (boolean)".

Help please
 
Level 8
Joined
Aug 6, 2008
Messages
451
Alright, one cant really know who uses mac and who doesnt, so sorry for feeding you this vJass stuff.

You should still use only one global group for all GroupEnums and one global dummy caster for all stormbolts. The way you are doing it now is kinda broken.
 
Level 10
Joined
Sep 29, 2006
Messages
447
Alright, one cant really know who uses mac and who doesnt, so sorry for feeding you this vJass stuff.

You should still use only one global group for all GroupEnums and one global dummy caster for all stormbolts. The way you are doing it now is kinda broken.

Can you please explain how I would do so. Someone helped me with the GroupEnum function I haven't really used it before. Also the global dummy caster needs a bit more of an explanation.
 
Level 8
Joined
Aug 6, 2008
Messages
451
Well, you can for example, copy that dummy caster from that map I linked. ( Dummy must have some animation time thingies in object editor set to 0, so it can cast spells instantly without animation slowing it down ) Then you just have to make sure that stun spell has 0 cooldown and no manacost and do this:

JASS:
// From the code I posted:

call SetUnitX(Dealer,GetUnitX(u))         
call SetUnitY(Dealer,GetUnitY(u))         
call IssueTargetOrder(Dealer,"thunderbolt",u)

For groups, you should create one global EnumGroup and use it to call all GroupEnums. Do your actions in filterfunction and return false, so no units are never really added to group and you dont even have to clean it.
 
Status
Not open for further replies.
Top