• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Convert to vJass

Status
Not open for further replies.
Level 16
Joined
May 1, 2008
Messages
1,605
Moin moin =)

Ok after I created my first MUI spell ( not very special but I'm proud ) I want to recreate the same spell without using those GUI-Variables.

After I search a while I find you that I need vJass to do this. So my question is if someone can help me with that? The best is if someone just convert this fast and post it, because I looked in the tutorials and thanks to my bad english - I don't understand a word.


  • TB Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to (==) Thunderball
    • Actions
      • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • TB_MUI[2] Equal to (==) 0
        • Then - Actions
          • Trigger - Turn on TB Loop <gen>
        • Else - Actions
      • Set TB_MUI[1] = (TB_MUI[1] + 1)
      • Set TB_Caster[TB_MUI[1]] = (Triggering unit)
      • Set TB_Level[TB_MUI[1]] = (Level of (Ability being cast) for TB_Caster[TB_MUI[1]])
      • Set TB_Player[TB_MUI[1]] = (Owner of TB_Caster[TB_MUI[1]])
      • Set TB_Loc1[TB_MUI[1]] = (Position of TB_Caster[TB_MUI[1]])
      • Set TB_Loc2[TB_MUI[1]] = (Position of TB_Caster[TB_MUI[1]])
      • Set TB_Loc3[TB_MUI[1]] = (Position of TB_Caster[TB_MUI[1]])
      • Set TB_Face[TB_MUI[1]] = (Facing of TB_Caster[TB_MUI[1]])
      • Set TB_SwitchHigh[TB_MUI[1]] = 0
      • Set TB_High[TB_MUI[1]] = 150.00
      • Set TB_Ball[TB_MUI[1]] = (For TB_Player[TB_MUI[1]] create a unit of type MyDummy2 at location TB_Loc1[TB_MUI[1]] facing (Facing of TB_Caster[TB_MUI[1]]) degrees)
      • Unit - Turn collision for TB_Ball[TB_MUI[1]] Off
  • TB Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Set TB_MUI[2] = 0
        • Do Multiple ActionsFor each (Integer TB_MUI[3]) from 1 to TB_MUI[1], do (Actions)
          • Loop - Actions
            • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • TB_High[TB_MUI[3]] Greater than or equal to (>=) 350.00
              • Then - Actions
                • Set TB_SwitchHigh[TB_MUI[3]] = 1
              • Else - Actions
                • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • TB_High[TB_MUI[3]] Less than or equal to (<=) 150.00
                  • Then - Actions
                    • Set TB_SwitchHigh[TB_MUI[3]] = 0
                    • Set TB_Dummy[TB_MUI[3]] = (For TB_Player[TB_MUI[3]] create a unit of type MyDummy at location TB_Loc1[TB_MUI[3]] facing 0.00 degrees)
                    • Unit - Add a 2.00 second Generic expiration timer to TB_Dummy[TB_MUI[3]]
                    • Unit - Add TB Dummy to TB_Dummy[TB_MUI[3]]
                    • Unit - Set level of TB Dummy for TB_Dummy[TB_MUI[3]] to TB_Level[TB_MUI[3]]
                    • Unit - Order TB_Dummy[TB_MUI[3]] to Orc Tauren Chieftain - War Stomp
                    • Custom script: call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", udg_TB_Loc1[udg_TB_MUI[3]]))
                  • Else - Actions
            • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • TB_SwitchHigh[TB_MUI[3]] Equal to (==) 0
              • Then - Actions
                • Set TB_MUI[2] = (TB_MUI[2] + 1)
                • Set TB_Loc1[TB_MUI[3]] = (TB_Loc2[TB_MUI[3]] offset by 10.00 towards TB_Face[TB_MUI[3]] degrees)
                • Set TB_Loc2[TB_MUI[3]] = TB_Loc1[TB_MUI[3]]
                • Unit - Move TB_Ball[TB_MUI[3]] instantly to TB_Loc1[TB_MUI[3]]
                • Animation - Change TB_Ball[TB_MUI[3]] flying height to (TB_High[TB_MUI[3]] + 8.00) at TB_High[TB_MUI[3]]
                • Set TB_High[TB_MUI[3]] = (TB_High[TB_MUI[3]] + 8.00)
              • Else - Actions
                • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • TB_SwitchHigh[TB_MUI[3]] Equal to (==) 1
                  • Then - Actions
                    • Set TB_MUI[2] = (TB_MUI[2] + 1)
                    • Set TB_Loc1[TB_MUI[3]] = (TB_Loc2[TB_MUI[3]] offset by 10.00 towards TB_Face[TB_MUI[3]] degrees)
                    • Set TB_Loc2[TB_MUI[3]] = TB_Loc1[TB_MUI[3]]
                    • Unit - Move TB_Ball[TB_MUI[3]] instantly to TB_Loc1[TB_MUI[3]]
                    • Animation - Change TB_Ball[TB_MUI[3]] flying height to (TB_High[TB_MUI[3]] - 8.00) at TB_High[TB_MUI[3]]
                    • Set TB_High[TB_MUI[3]] = (TB_High[TB_MUI[3]] - 8.00)
                  • Else - Actions
            • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • (Integer((Distance between TB_Loc1[TB_MUI[3]] and TB_Loc3[TB_MUI[3]]))) Greater than or equal to (>=) 2050
              • Then - Actions
                • Unit - Remove TB_Ball[TB_MUI[3]] from the game
                • Custom script: call RemoveLocation(udg_TB_Loc1[udg_TB_MUI[3]])
                • Custom script: call RemoveLocation(udg_TB_Loc2[udg_TB_MUI[3]])
                • Custom script: call RemoveLocation(udg_TB_Loc3[udg_TB_MUI[3]])
              • Else - Actions
        • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • TB_MUI[2] Equal to (==) 0
          • Then - Actions
            • Trigger - Turn off (This trigger)
            • Set TB_MUI[1] = 0
          • Else - Actions


I know this isn't a super spell but it's my first and now I want do the next step to vJass. Problem is I don't understand a word in the tutorial - there's to much text anyway I get so confused.

So if someone have a little bit time, can you help me plz or give me a "point - to - point - help so I get this and try myself? =)

Greetings
~ The Bomb King > Dr. Boom
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
1,084
Before I start trying to recode this into vJass, I would like you to post any of your attempts to make this spell into vJass. (That way, I can also point out any things that can be improved with your code. You could also get more out of trying to experiment by yourself then someone providing everything for you.)
 
Level 16
Joined
May 1, 2008
Messages
1,605
Moin moin =)

My first idea was, because I used many variables and I don't like GUI somehow, I made this spell in JASS. Then I found out that this is impossible so I searched and asked around and got the point, that I have to use vJass.

Problem is I can't understand english well, the tutorial hasn't any sense for me, but also I want learn vJass as well.

The best way to learn for me is, to see a spell in GUI oder Jass and then the same spell in vJass. So I an example how it should look like, where to set what and where to do what you know?

Also when you see that ability, I learned MUI spell with that and without tutorial, I just tried it but when I "just try" vJass, I don't get anything =(

Greetings
~ The Bomb King > Dr. Boom
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
Okay, I started trying to recode your spell.
The thing is, GUI makes me have a big headache and I don't understand what some of the variables are used for, particularly since the variable names aren't that helpful.

Perhaps you could give a brief explanation for what some variables do? Or maybe just give me the converted Jass form for the periodic trigger.

Current code:
JASS:
// Okay, I tried to comment as much as I could to explain things.
// Anyway, I won't guarantee that this spell will work correctly.

// Start off by declaring the scope/library. Thunderball is the name of the scope. 
// You can add initializer after Thunderball to call a function that will run at map initialization. 
scope Thunderball initializer Init
    // You declare globals in a global block:
    globals
        private constant integer SPELL_ID = 0   // The raw id of the Thunderball ability. 
                                                // Private can be used inside scopes/libraries to avoid naming conflicts with other globals. 
                                                // Constant makes it so that this value cannot be changed later on.
        private constant real TIMER_LOOP = 0.03 // How often the timer will loop.
        
        private constant integer DUMMY_ID = 0 // Raw id of the MyDummy2 unit.
        private constant integer ANOTHER_DUMMY_ID = 0 // Raw id of the MyDummy unit.
        
        private constant integer WARSTOMP_ID = 0 // Raw id of TB Dummy ability
        private constant string WARSTOMP_ORDER = "stomp" // Order string of TB Dummy ability
    endglobals    
    
    // I decided to use a struct for this instead of creating arrays of all the other variables.
    private struct Data
        // Use of static makes these struct members act like globals
        static timer Tim = CreateTimer() // Use one timer for the entire spell. Make it MUI with indexing.
        static integer Total = 0 // Keeps track of how Thunderballs are active
        static thistype array Index // Used for indexing
        
        unit caster // As the name implies, the unit that casted the spell
        integer lvl // The level of the ability when it was first casted.
        player owner //The owning player of the caster.
        real face // The facing of the caster.
        real x // Stores the x coordinate of the caster when the spell was casted.
        real y // Stores the y coordinate of the caster when the spell was casted.
        integer switchHigh = 0
        real high = 150. // You can initially set values to members without having to do so in the create method.
        unit ball
        
        // Basically starts the spell
        static method create takes unit c returns thistype
            local thistype this = thistype.allocate()
            
            if Total == 0 then
                call TimerStart(Tim,TIMER_LOOP,true,function thistype.onLoop)
            endif            
            
            set .caster = c
            set .lvl = GetUnitAbilityLevel(c,SPELL_ID)
            set .owner = GetOwningPlayer(c)
            set .face = GetUnitFacing(c)
            set .x = GetUnitX(c)
            set .y = GetUnitY(c)
            
            set .ball = CreateUnit(.owner,DUMMY_ID,.x,.y,.face)     
            call SetUnitPathing(.ball,false)
            
            set Index[Total]=this
            set Total = Total + 1
            return this
        endmethod
        
        //Do periodic stuff here.
        static method onLoop takes nothing returns nothing
            local thistype this
            local integer i = 0 // TB_MUI[3]
            local unit dummy
            local integer anotherIndex = 0 // TB_MUI[2]
            loop
                set this = Index[i]
                
                if .high >= 350. then
                    set .switchHigh = 1                
                elseif .high <= 150. then
                    set .switchHigh = 0
                    
                    set dummy = CreateUnit(.owner,ANOTHER_DUMMY_ID,0,0,0)
                    call UnitApplyTimedLife(dummy,'BTLF',2.)
                    call UnitAddAbility(dummy,WARSTOMP_ID)
                    call SetUnitAbilityLevel(dummy,WARSTOMP_ID,.lvl)
                    call IssueImmediateOrder(dummy,WARSTOMP_ORDER)
                    // Make something pretty here:
                    
                    set dummy = null
                endif
                
                if .switchHigh == 0 then
                    set anotherIndex = anotherIndex + 1
                elseif .switchHigh == 1 then
                endif
                
                // Distance check:
                
                exitwhen i >= Total
                set i = i + 1
            endloop
        endmethod
    endstruct
    
    // We use a Trigger Condition thread since it's faster than Trigger actions and removes the need for another thread.
    private function SpellActions takes nothing returns boolean
        if GetSpellAbilityId() == SPELL_ID then
            call Data.create(GetTriggerUnit())
        endif
        return false // Since everything will be done here, there's no need for the trigger actions to be done.
    endfunction
    
    //The function that will be called upon map init.
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t,Condition(function SpellActions))
    endfunction
endscope
 
Level 16
Joined
May 1, 2008
Messages
1,605
Moin moin =)

About the variables: The spell "Thunderball (TB)" is a bouncing ball if you want.

I set in "TB_High" the basic flyhigh of the dummy Thunderball.

Then you see the "TB_SwitchHigh". I used this variable to set if the ball should bounce down or up.

TB_Face: I don't know if that's required but I though it's important because the ball shouldn't switch the way while bouncing.

But hey ok I will just add the map into this post, so you can see the effect of the ball. Also I have a little "problem". If the ball bounce on the ground ( 150 fly high ) a dummy is created with the "warstomp" ability. But this ability doesn't fire directly when the ball is down, there's some delay

But you can see it for you self and you will understand =)

Edit: I have a bug in the GUI Trigger I saw now. If I cast it more times, somehow the effect I created is spawn in the center region of the map =O - don't know why olol

Greetings
~ The Bomb King > Dr. Boom
 

Attachments

  • MyMap20.w3x
    210.7 KB · Views: 42
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
1,084
Hm, you used WEU which makes it kind of annoying to test the map.

Anyway, I finished the vJass code for this. It shouldn't have the same bug as your GUI one since it doesn't rely on locations.

JASS:
// Start off by declaring the scope/library. Thunderball is the name of the scope.
scope Thunderball
    // You declare globals in a global block:
    globals
        private constant integer SPELL_ID = 'A002'   // The raw id of the Thunderball ability.
                                                // Private can be used inside scopes/libraries to avoid naming conflicts with other globals.
                                                // Constant makes it so that this value cannot be changed later on.
                                                
        private constant real TIMER_LOOP = 0.03 // How often the timer will loop.
        
        private constant integer DUMMY_ID = 'h002' // Raw id of the MyDummy2 unit.
        private constant integer ANOTHER_DUMMY_ID = 'h001' // Raw id of the MyDummy unit.
        
        private constant integer WARSTOMP_ID = 'A003' // Raw id of TB Dummy ability
        private constant string WARSTOMP_ORDER = "stomp" // Order string of TB Dummy ability
    endglobals    
    
    // I decided to use a struct for this instead of creating arrays of all the other variables.
    private struct Data    
        // Use of static makes these struct members act like globals
        static timer Tim = CreateTimer() // Use one timer for the entire spell. Make it MUI with indexing.
        static integer Total = 0 // Keeps track of how Thunderballs are active
        static thistype array Index // Used for indexing
        
        //Caster stuff:
        integer lvl // The level of the ability when it was first casted.
        player owner //The owning player of the caster.
        real face // The angle between the caster and the spell target points
        
        unit ball // The ball unit
        real dist = 0 // Stores how far the ball has travelled
        // You can initially set values to members without having to do so in the create method.
        integer switchHigh = 1 // Changed it for easier calculations. 1 means it's going up. -1 means it's going down.
        real high = 150.        
        
        // Basically starts the spell
        static method create takes unit c, real x, real y returns thistype
            local thistype this = thistype.allocate()
            local real cx = GetUnitX(c)
            local real cy = GetUnitY(c)
            
            if Total == 0 then
                call TimerStart(Tim,TIMER_LOOP,true,function thistype.onLoop)
            endif            
            
            set .lvl = GetUnitAbilityLevel(c,SPELL_ID)            
            set .owner = GetOwningPlayer(c)
            set .face = Atan2(y-cy,x-cx)// This is more accurate than GetUnitFacing(c)            
            
            set .ball = CreateUnit(.owner,DUMMY_ID,cx,cy,.face*bj_RADTODEG)     
            call SetUnitPathing(.ball,false)
            
            set Index[Total]=this
            set Total = Total + 1
            return this
        endmethod
        
        //Do periodic stuff here.
        static method onLoop takes nothing returns nothing
            local thistype this
            local integer i = 0 // TB_MUI[3], for looping
            local unit dummy
            // Coordinates of the ball unit
            local real bx
            local real by
            loop
                exitwhen i >= Total
                
                set this = Index[i]
                
                set bx = GetUnitX(.ball)
                set by = GetUnitY(.ball)
                
                if .high >= 350. then
                    set .switchHigh = -1                
                elseif .high <= 150. then
                    set .switchHigh = 1                    
                    
                    set dummy = CreateUnit(.owner,ANOTHER_DUMMY_ID,bx,by,0) 
                    call UnitApplyTimedLife(dummy,'BTLF',2.)
                    call UnitAddAbility(dummy,WARSTOMP_ID)
                    call SetUnitAbilityLevel(dummy,WARSTOMP_ID,.lvl)
                    call IssueImmediateOrder(dummy,WARSTOMP_ORDER)                    
                    set dummy = null
                    
                    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", bx,by))
                endif
                
                // Moving the ball is done regardless of whether it's going up or down.
                call SetUnitX(.ball,bx + 10 * Cos(.face))
                call SetUnitY(.ball,by + 10 * Sin(.face))
                set .dist = .dist + 10 // Something I added to make it simpler to check distance
                
                set.high = .high + .switchHigh*8
                call SetUnitFlyHeight(.ball,.high,0)
                
                // Distance check:
                if .dist >= 2050 then
                    call RemoveUnit(.ball)
                    
                    // Struct indexing stuff:
                    call .destroy() // Destroy since we're basically done with this                    
                    set Total = Total - 1
                    set Index[i] = Index[Total]
                    
                    set i = i - 1
                endif   
                
                set i = i + 1
            endloop
            
            if Total == 0 then
                call PauseTimer(Tim)
            endif
        endmethod
        
        // We use a Trigger Condition thread since it's faster than Trigger actions and removes the need for another thread.
        static method spellActions takes nothing returns boolean
            if GetSpellAbilityId() == SPELL_ID then
                call Data.create(GetTriggerUnit(),GetSpellTargetX(),GetSpellTargetY())
            endif
            return false // Since everything will be done here, there's no need for the trigger actions to be done.
        endmethod
        
        // A method that will be called upon map init.
        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t,Condition(function thistype.spellActions))
        endmethod
    endstruct
endscope
Note I used SetUnitX/Y to move the ball unit. That can crash the game if the unit goes out of bounds so you may want to use SetUnitPosition instead unless you have something like BoundSentinel in your map.
 
Last edited:
Level 16
Joined
May 1, 2008
Messages
1,605
Moin moin =)

I never use WEU ^^ - but I will try your spell now. If you want I got another spell, actually I even can't create this in GUI because it doesn't work and HELL it piss me alot

Edit: IT WORKS - imba vJasser here I think =) - THANKS A LOT MAN! *spread with +reps around*

Edit 2. Even TriggerHappy is proud of you =D

Greetings
~ The Bomb King > Dr. Boom =)
 
Status
Not open for further replies.
Top