• 🏆 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] vJass struct template

Status
Not open for further replies.
Level 14
Joined
Nov 18, 2007
Messages
816
JASS:
library YourLibrary // maybe you need an initializer and requirements; add them here

    globals
        private constant    real                    TICK                    = 1./32
    endglobals
    
    private struct Data
        // your struct members go here
        
        private integer i
        
        private static thistype array Structs
        private static timer T=CreateTimer()
        private static integer Count=0
        
        method onDestroy takes nothing returns nothing
            // clean your struct here
            set thistype.Count=thistype.Count-1
            set thistype.Structs[.i]=thistype.Structs[thistype.Count]
            set thistype.Structs[.i].i=.i
            if thistype.Count==0 then
                call PauseTimer(thistype.T)
            endif
        endmethod
        
        private static method Callback takes nothing returns nothing
        local integer i=thistype.Count-1
        local thistype s
            loop
                exitwhen i<0
                set s=thistype.Structs[i]
                // do your things here, dont forget to call s.destroy() somewhen
                set i=i-1
            endloop
        endmethod
        
        static method create takes nothing returns thistype
        local thistype s=thistype.allocate()
            // initialize the struct here
            set thistype.Structs[thistype.Count]=s
            set s.i=thistype.Count
            if thistype.Count==0 then
                call TimerStart(thistype.T, TICK, true, function thistype.Callback)
            endif
            set thistype.Count=thistype.Count+1
            return s
        endmethod
    endstruct
    
endlibrary

If you are looking for a way to execute code related to structs many times per second, use this template as a base.
 
Last edited:
Level 18
Joined
Oct 18, 2007
Messages
930
This could be useful for some vJass newbies but I have to nitpick this a little.

Why having private members prefix when the struct is private?

You should put this from the onDestroy metod
JASS:
if Data.Count==0 then
    call PauseTimer(Data.T)
endif
in the callback method instead.

And you should really explain the indexer method, how it works etc. instead of implementing it without any description why or how.
 
Level 8
Joined
Aug 6, 2008
Messages
451
I have a template like this too. They can be pretty useful sometimes.

JASS:
scope Template initializer init

globals
    private constant integer ABILITY_ID = 'yepp' // no sweat
    private constant real TIMEOUT = .1
endglobals

private struct ability

    boolean end=false

    group group
    
    static ability array array
    static timer timer=CreateTimer()
    static filterfunc F
    static integer Total=0
    static ability temp
    
    static method onInit takes nothing returns nothing
        set .F=Filter(function ability.Filttemellarung)
    endmethod

    static method Filttemellarung takes nothing returns boolean
         local ability a=ability.temp
          // you might wanna change this     
         return false
    endmethod
    
    static method create takes nothing returns ability
        local ability a=ability.allocate()

        if a.group==null then
             set a.group=CreateGroup()
        else
             call GroupClear(a.group)
        endif 
       
       // do some neat stuff here  
       
        return a
    endmethod
   
    static method periodic takes nothing returns nothing
        local integer i=0
        local ability a
        loop
            exitwhen i>=.Total
            set a=ability.array[i]
            if a.end then
                call a.destroy()
                set .Total=.Total-1
                if .Total>0 then
                    set .array[i]=.array[.Total]
                    set i=i-1
                else
                    call PauseTimer(.timer)
                endif
            else
              
              //  Periodic stuff here  

            endif
            set i=i+1
        endloop
    endmethod
    
endstruct

private function SpellEffect takes nothing returns boolean
    if GetSpellAbilityId()==ABILITY_ID then
         if ability.Total==0 then
             call TimerStart(ability.timer,TIMEOUT,true,function ability.periodic)
         endif
         set ability.array[ability.Total]=ability.create( nothing or something )
         set ability.Total=ability.Total+1
    endif
    return false
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 SpellEffect))
endfunction

endscope
 
Level 8
Joined
Aug 6, 2008
Messages
451
Actually, when .G.0 came out, I was thinking of doing something like this with module.

Wait and see..
 
Level 14
Joined
Nov 18, 2007
Messages
816
wait, ill be right back with an updated version. Let me just test some things.

Yeah, thistype is REALLY handy. Updated first post

Why having private members prefix when the struct is private?
because the struct could still be public or have no prefix at all.

You should put this[...]
Nope, since the only way for Data.Count to become zero is through s.destroy()
 
Level 16
Joined
Feb 22, 2006
Messages
960
so i played around with the new feature "module", I created this template for stacking structs... but I'm not sure if it's similar to the old one ;)

JASS:
module structStack
    boolean active = true
    
    private integer i    
    private static integer Total = 0
    private static thistype array Data
    private static timer Tim = CreateTimer()
    private static method callback takes nothing returns nothing
        local thistype dat
        local integer i = 0
        loop
            exitwhen i >= thistype.Total
            set dat = thistype.Data[i]
            if dat.active == true then
                call dat.actions()
            else                
                call thistype.destroy(dat)
                set i = i - 1
            endif
            set i = i + 1
        endloop
        if thistype.Total == 0 then
            call PauseTimer(thistype.Tim)
        endif           
    endmethod
    
    static method create takes nothing returns thistype
        local thistype dat = thistype.allocate()
        if thistype.Total == 0 then
            call TimerStart(thistype.Tim,0.03125,true,function thistype.callback)
        endif
        set thistype.Data[thistype.Total] = dat
        set dat.i = thistype.Total
        set thistype.Total = thistype.Total + 1
        return dat
    endmethod
    
    private method onDestroy takes nothing returns nothing
        set thistype.Total=thistype.Total-1
        set thistype.Data[.i]=thistype.Data[thistype.Total]
        set thistype.Data[.i].i=.i     
    endmethod
endmodule

struct Data
    private method actions takes nothing returns nothing
        //some actions
    endmethod
    implement structStack
endstruct

you only would need to implement this module in your structs where you need stacking (timed events) and you could start,
but you always need a method called actions

Edit: Reworked mine
 
Last edited:
Level 6
Joined
Apr 16, 2007
Messages
177
A module would be rather awkward for this.

w0rd

I use a superclass though...
Which isn't that much better :D

EDIT:

here is the childclass
JASS:
scope THB
globals
    private constant real PERIOD           = 1
    private constant integer ABIL_ID       = 'A000'
    private constant playerunitevent EVENT = EVENT_PLAYER_UNIT_SPELL_EFFECT
endglobals


private struct data_instance extends sj_spell_data
    //precreated variables...
      //    caster  --> unit    // the caster
      //    x       --> real    // the caster's x position
      //    y       --> real    // the caster's y position
      //    ownerId --> integer // the player id of the caster's owner
      //    level   --> integer // the level of the spell
      
    //add own variables here
    

    method loopAction takes nothing returns nothing
        // will be called every PERIOD            
    endmethod
    
    method init takes nothing returns nothing
        // will be called on struct creation
        call .setRemaining( 5 ) // Replace 0 with the duration of the spell. 0 will instantly destroy the spell!
    endmethod
    
    method clear takes nothing returns nothing
        // please clear all handle variables here. Will be called when the .destroy() method is evoked.
    endmethod

// -----------------------------------
//  Please don't change the following
// -----------------------------------
    
    static constant trigger spellTrigger = CreateTrigger()
        
    static method actions takes nothing returns nothing
        if GetSpellAbilityId() == ABIL_ID then
            call .create( PERIOD, ABIL_ID ).init()
        endif
    endmethod
    
    private static method onInit takes nothing returns nothing
        call TriggerRegisterAnyUnitEventBJ( .spellTrigger, EVENT )
        call TriggerAddAction( .spellTrigger, function data_instance.actions )
    endmethod
endstruct
    
endscope

Using this, I actually wrote a small system similiar to the control point system in battletanks XD
 
Level 8
Joined
Aug 6, 2008
Messages
451
Here is my TimerMember module:

JASS:
module TimerMember    
    
    public static real TIMEOUT = .025
    
    // You must have this method in your struct:
    
    // method timerAction takes nothing returns boolean
    
    private static timer timer=CreateTimer()
    private static thistype array array
    private static integer Total=0
    
    private static method periodic takes nothing returns nothing
        local integer i=0
        loop
            exitwhen i>=.Total
            if .array[i].timerAction() then
                set .Total=.Total-1
                if .Total>0 then
                    set .array[i]=.array[.Total]
                    set i=i-1
                else
                    call PauseTimer(.timer)
                endif
            endif
            set i=i+1
        endloop
    endmethod
    
    
    method timerStart takes nothing returns nothing
         if .Total==0 then
             call TimerStart(.timer,TIMEOUT,true,function thistype.periodic)
         endif
         set .array[.Total]=this
         set .Total=.Total+1
    endmethod

    static method setPeriod takes real period returns nothing
        set .TIMEOUT=period
    endmethod
    
endmodule
 
Level 16
Joined
Feb 22, 2006
Messages
960
Here is my TimerMember module:

JASS:
module TimerMember    
    
    public static real TIMEOUT = .025
    
    // You must have this method in your struct:
    
    // method timerAction takes nothing returns boolean
    
    private static timer timer=CreateTimer()
    private static thistype array array
    private static integer Total=0
    
    private static method periodic takes nothing returns nothing
        local integer i=0
        loop
            exitwhen i>=.Total
            if .array[i].timerAction() then
                set .Total=.Total-1
                if .Total>0 then
                    set .array[i]=.array[.Total]
                    set i=i-1
                else
                    call PauseTimer(.timer)
                endif
            endif
            set i=i+1
        endloop
    endmethod
    
    
    method timerStart takes nothing returns nothing
         if .Total==0 then
             call TimerStart(.timer,TIMEOUT,true,function thistype.periodic)
         endif
         set .array[.Total]=this
         set .Total=.Total+1
    endmethod

    static method setPeriod takes real period returns nothing
        set .TIMEOUT=period
    endmethod
    
endmodule

i nearly did the same....
 
Level 8
Joined
Aug 6, 2008
Messages
451
I dont like how you use create and onDestroy methods. IMO its better to just have some startTimer method and use return true for stopping iterating.

But yea, functionality is basicly the same.
 
Status
Not open for further replies.
Top