Jasshelper error: Cannot find Functions

Bribe

vJass errors are legion
Reaction score
67
I meant at what float-value :p

Would it be .03, 0.01, 0.00125 or what?
 

Bribe

vJass errors are legion
Reaction score
67
Why would T32 use just one timer for all the modules then? Or does that library just need an update?
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Why would T32 use just one timer for all the modules then? Or does that library just need an update?
Stacking callbacks on 1 timer is good for low period.
Perhaps you can look at the code of KT2.
It stackes all of the callback under THRESHOLD into 1 timer. (Different timer for different period, for sure)
For value above THRESHOLD, KT2 will switch to another mechanism with 1 timer per callback, it is called Tazo(Jesus4Lyf named it, don't ask me why).
In Tazo, KT2 will create trigger for timer event, hence it is much slower than simple timer attaching.
 

Bribe

vJass errors are legion
Reaction score
67
kingkingyyk3, isn't that exactly what KeyTimers2 does, links all the like-frequency callbacks on one timer...? Jesus4Lyf proclaimed that library as the most efficient for its use.

Jesus4Lyf said:
This is, at the time of release, the most efficient timer system in existance.

One of his famous one-liners.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
kingkingyyk3, isn't that exactly what KeyTimers2 does, links all the like-frequency callbacks on one timer...? Jesus4Lyf proclaimed that library as the most efficient for its use.
Take a look at his benchmark? (The attachment :) )
He said that TimerUtils is more efficient than KT2 in high period.
Linking all like frequency is not a good way for high period.
Imagine :
Callback A added into KT with 5 seconds expiration.
After 2 seconds.
Callback B added into KT with 5 seconds expiration.
Callback B is added into 5 seconds timer callback stack.
After 3 seconds.
Callback A and Callback B is called.
Realise that? It is not accurate at all.

One of his famous one-liners.
For low period mechanism only.

JASS:
    //////////
    // TAZO //
    ////////////////////////////////////////////////////////////////////////////
    // KT2 implementation for higher periods (low frequency).
    globals
        private constant integer TAZO_DATAMEM=8190 // Added for KT2 hook. Don't change.
    endglobals
    
    globals
        private conditionfunc TAZO_LoadDataCond
        private conditionfunc TAZO_RemoveInstanceCond
        
        private timer   array TAZO_TrigTimer
        private integer array TAZO_Data
        private boolexpr array TAZO_Boolexpr
        
        private trigger array TAZO_AvailableTrig
        private integer       TAZO_Max=0
        
        private integer       TAZO_ConstructNext=0
        private trigger array TAZO_ConstructTrig
        private integer array TAZO_ConstructCount
    endglobals
    
    globals//locals
        private integer TAZO_ConKey
    endglobals
    private function TAZO_Constructer takes nothing returns boolean
        set TAZO_ConKey=GetData()
        call TriggerExecute(TAZO_ConstructTrig[TAZO_ConKey])
        set TAZO_ConstructCount[TAZO_ConKey]=TAZO_ConstructCount[TAZO_ConKey]-1
        if TAZO_ConstructCount[TAZO_ConKey]==0 then
            set TAZO_Max=TAZO_Max+1
            set TAZO_AvailableTrig[TAZO_Max]=TAZO_ConstructTrig[TAZO_ConKey]
            set TAZO_TrigTimer[TAZO_ConKey]=CreateTimer()
            call TriggerRegisterTimerExpireEvent(TAZO_AvailableTrig[TAZO_Max],TAZO_TrigTimer[TAZO_ConKey])
            return true
        endif
        return false
    endfunction
    
    globals//locals
        private trigger TAZO_DeadTrig
        private integer TAZO_DeadCount
    endglobals
    private function TAZO_Recycle takes nothing returns boolean
        set TAZO_DeadTrig=GetTriggeringTrigger()
        set TAZO_DeadCount=GetTriggerExecCount(TAZO_DeadTrig)
        call TriggerClearConditions(TAZO_DeadTrig)
        call DestroyBoolExpr(TAZO_Boolexpr[TAZO_DeadCount])
        call PauseTimer(TAZO_TrigTimer[TAZO_DeadCount])
        set TAZO_Max=TAZO_Max+1
        set TAZO_AvailableTrig[TAZO_Max]=TAZO_DeadTrig
        return false
    endfunction
    
    private function TAZO_LoadData takes nothing returns boolean
        // KT2 Data Hook
        set t_mem=TAZO_DATAMEM
        set Data[TAZO_DATAMEM]=TAZO_Data[GetTriggerExecCount(GetTriggeringTrigger())]
        // End KT2 Data Hook
        return false
    endfunction
    
    private function InitTrigExecCount takes trigger t, integer d returns nothing
        if d>128 then
            call InitTrigExecCount.execute(t,d-128)
            set d=128
        endif
        loop
            exitwhen d==0
            set d=d-1
            call TriggerExecute(t)
        endloop
    endfunction
    
    globals//locals
        private integer TAZO_AddKey
        private trigger TAZO_AddTrigger
    endglobals
    public function TAZOadd takes code func, integer data, real period returns nothing
        if TAZO_Max==0 then
            // Failsafe.
            set TAZO_ConstructNext=TAZO_ConstructNext+1
            set TAZO_AddTrigger=CreateTrigger()
            set TAZO_AddKey=TAZO_ConstructNext
            call InitTrigExecCount.execute(TAZO_AddTrigger,TAZO_AddKey)
            set TAZO_TrigTimer[TAZO_AddKey]=CreateTimer()
            call TriggerRegisterTimerExpireEvent(TAZO_AddTrigger,TAZO_TrigTimer[TAZO_AddKey])
        else
            set TAZO_AddTrigger=TAZO_AvailableTrig[TAZO_Max]
            set TAZO_AddKey=GetTriggerExecCount(TAZO_AddTrigger)
            set TAZO_Max=TAZO_Max-1
        endif
        set TAZO_Data[TAZO_AddKey]=data
        set TAZO_Boolexpr[TAZO_AddKey]=And(Condition(func),TAZO_RemoveInstanceCond)
        call TriggerAddCondition(TAZO_AddTrigger,TAZO_LoadDataCond)
        call TriggerAddCondition(TAZO_AddTrigger,TAZO_Boolexpr[TAZO_AddKey])
        call TimerStart(TAZO_TrigTimer[TAZO_AddKey],period,true,null)
        if TAZO_Max<10 then
            set TAZO_ConstructNext=TAZO_ConstructNext+1
            set TAZO_ConstructTrig[TAZO_ConstructNext]=CreateTrigger()
            set TAZO_ConstructCount[TAZO_ConstructNext]=TAZO_ConstructNext
            call KTadd(function TAZO_Constructer,TAZO_ConstructNext,TAZO_CONSTRUCT_PERIOD)
        endif
    endfunction
    
    private function TAZOinit takes nothing returns nothing
        set TAZO_LoadDataCond=Condition(function TAZO_LoadData)
        set TAZO_RemoveInstanceCond=Condition(function TAZO_Recycle)
        // Allow for GetData
        set Next[TAZO_DATAMEM]=TAZO_DATAMEM
        set Prev[TAZO_DATAMEM]=TAZO_DATAMEM
        // End allow for GetData
        loop
            exitwhen TAZO_Max==TAZO_PRECACHE
            set TAZO_ConstructNext=TAZO_ConstructNext+1 // The index.
            set TAZO_Max=TAZO_Max+1 // Will be the same in the initialiser as ConstructNext.
            set TAZO_AvailableTrig[TAZO_Max]=CreateTrigger()
            call InitTrigExecCount.execute(TAZO_AvailableTrig[TAZO_Max],TAZO_ConstructNext)
            set TAZO_TrigTimer[TAZO_ConstructNext]=CreateTimer()
            call TriggerRegisterTimerExpireEvent(TAZO_AvailableTrig[TAZO_Max],TAZO_TrigTimer[TAZO_ConstructNext])
        endloop
    endfunction

Involves triggers and timers and some sort of "hack :p ".
 

Bribe

vJass errors are legion
Reaction score
67
Egads, you really threw me for a loop. Next time seperate "efficiency" from "accuracy" in that context o_O

Plus, this low-frequency, low-period stuff is confusing the way you and him switch the two around. High-frequency means low real value on the timer, and high-period means high real value on the timer. It's enough to make anyone have to read it several times and still miss a lot of the catch on which is which.

Anyway, thanks for the help. The conclusion I would make is: any value low enough to not notice a one-time difference between 0.00 and itself should be using KeyTimers2.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Anyway, thanks for the help. The conclusion I would make is: any value low enough to not notice a one-time difference between 0.00 and itself should be using KeyTimers2.
For 0.03125 seconds period, T32 still pawn KT2.
 

Bribe

vJass errors are legion
Reaction score
67
That's a possibility. Any recommendation how to faux a static method in that mix? In the current setup I use it's not as simple as just enabling/disabling each struct, and evaluating every instance within that loop will lose efficiency.
 

retupmoc258

New Member
Reaction score
1
See, structs allow you to make your own types, like integers and units and locations. I mean, what is a location but two reals? Then, you have methods.
[/JASS]

Alright, so I am doing a system that requires there to be a list of "stats" for a unit. So, if I were to set up a structure, say "struct Stats" then I could put in a bunch of things that make up the "Stats" such as life points, other variables, elemental damage rates, and stuff like that, then I just have something that stores an array of "Stats" and then I recall those based on the array and . . . something like that?

How exactly should I go about it? Is it even worth it? Right now I have hashtables storing the values. Of course that means the retrieval code looks a whole screen wide, but it gets the job done well enough. Would something like this be equivelent?

JASS:
//! Something worthless
struct Stats
real HP
real MP
real Strength
real Defense
//etc
method Attack takes unit Target returns nothing
call UnitDamageTarget((Strength - Defense), //etc
endmethod
endstruct


Something like this? I've already set things up and they work with little to no lag, but it seems like something of this nature could be ten times more efficient if I understood it.
 

tooltiperror

Super Moderator
Reaction score
231
I'm not sure if this is right, but I believe you can use the AIDS Struct for that. AIDS is Jesus4Lyf's powerful and pretty amazing indexer that provides a textmacro (he says he'll make it a module, but he hasn't yet) that allows you to give units additional stats, sort of, like more attributes for units. It's all abstract, but it's pretty cool.

JASS:

//! fix alignment
 library VirtualUnit
   private struct Stats extends array
     //! runtextmacro AIDS()
     private real HP
     private real MP
       private method onCreate takes nothing returns nothing
       endmethod
   endstruct
 endlibrary
 

retupmoc258

New Member
Reaction score
1
I'm not sure if this is right, but I believe you can use the AIDS Struct for that. AIDS is Jesus4Lyf's powerful and pretty amazing indexer that provides a textmacro (he says he'll make it a module, but he hasn't yet) that allows you to give units additional stats, sort of, like more attributes for units. It's all abstract, but it's pretty cool.

I looked into it. I guess ultimately unless I know how to actually make it work, it isn't useful to me. I have been studying structures recently, and I saw you can attach it to the unit custom data, which I think would work just as well. All units will have one specifically tied to either the type of unit (so they would be registered by another function or I just have a method with an interface for simplification) or to the unit itself (which each one is unique for the heroes, and for the enemies, each unit is just a clone that cannot change or grow).

The AIDS macro looks like it would save time with indexing and looking up the indexes, but I don't understand where the actual structure is saved for the unit. Is it saved in an AIDS array? More clarification would be good.
 

tooltiperror

Super Moderator
Reaction score
231
AIDS is as close as you can get to extending Units. It is pretty much a struct attached to every single unit. This example makes all units that are footmen respawn after death.

JASS:

// Note: Comment serves no purpose.
  private struct Creep extends array // You always extend array.
     //! runtextmacro AIDS()
     private method AIDS_onDestroy takes nothing returns nothing
         call TriggerSleepAction(3.00)
         call ReviveUnit(this.unit) // Pretend it exists.
     endfunction
     private static method AIDS_filter takes unit u returns boolean
         if GetUnitTypeId(u)=='hfoo' then
           return true
         endif
       return false
     endmethod
  endstruct
 

Bribe

vJass errors are legion
Reaction score
67
You don't always extend array. Maybe if you have AIDs, but (hopefully) most people don't have AIDs.
 

retupmoc258

New Member
Reaction score
1
Alright, well with a structure attached to each unit, where is it stored? How do I access it? I don't understand that part. It just looks like a bunch of code that handles when stuff happens to a unit that is registered in the AIDS program. That's basically what I'm looking for, but there will be dozens of units with the same set of stats (like 30 stats or so) and then functions outside of the structure that load the structure, get the stats it needs, modify some stats along the way, and then saves the structure back to the unit. How does AIDS actually do that? How does it store a structure to the unit other than creating an index value. Then where does it find the structure that was attached? Where is that stored? How do I retrieve the values in the structure through AIDS?

I think that's my biggest hang-up on this. I understand enough about structures now that creating a structure isn't a problem, and handling them isn't too big of a problem, but I don't understand enough to realize where AIDS is storing the data. It looks like just handling code, a program set so that when something happens to that registered unit, it runs one of the many handler codes that corresponds with my structure. I can use that to handle when a unit is attacked, dies, or kills a unit, or whatever, but what do I do if I want to change variables inside of it?
 

tooltiperror

Super Moderator
Reaction score
231
In AIDS, you are given four methods, which are essentially functions in structs. Let me just explain that these four methods allow you complete control over units. In theory, one could completely rescript units in WC3 with AIDS. And I mean rescript completely, moving, fighting, animating, armor, they could even do insane things like add fatigue, anything they want.

Note to self: Make a tutorial on AIDS.
JASS:
// Note: Comment serves no purpose.
  library Placeholder uses AIDS
     private struct Data extends array //All AIDS structs extend array.
         boolean holy // A regular struct member.
         trigger t
         private static method AIDS_filter takes unit u returns boolean
           /* This method lets you decide who you want to index in this
               struct.  If the function returns true, unit u will be indexed
               into the struct. */
             return true
         endmethod
         private method AIDS_onCreate takes nothing returns nothing
             //All things in here will be done when a unit is created in the map
             //and the filter returns true.  Refer to the unit as this.unit.
             set this.holy=true // Give the boolean a default value of true.
             set t=CreateTrigger()
             //Pretend right here we register a function to run when a unit
             //is killed, with the callback method being onKill.
         endmethod
         method onKill takes nothing returns nothing
             if GetKillingUnit()==this.unit then // If this is the indexed unit,
                 set this.holy=false//They killed the unit, they aren't holy anymore.
             endif
         endmethod
     endstruct
  endlibrary


Notes:
  • In reality, onKill would have to be above AIDS_onCreate for it to function properly, because it is used in onCreate and technically has not been declared yet, but I wanted you to read it chronologically.
  • You can also use the filter as a true filter, and only return true if the unit is a paladin for example.
 

retupmoc258

New Member
Reaction score
1
Okay, this added a little more understanding. How do I access information from OUTSIDE the structure (aka, the functions and triggers?) So, my unit dies, does AIDS run the structure for that unit's onKill method? Or do I have to initiate something to make it register that event for that unit. I think I see how I have to register the trigger to activate on death, right? So I just register the event with this.unit onCreate and tell it to run the onKill method when the trigger executes, is that right? Then as long as everything is run inside of the AIDS structure, I don't need any external functions to make anything work? Is that a good summary?

So then I have every function that modifies a unit's structure INSIDE the structure as a method, then it will work fine? Sounds a lot simpler than what I've been doing. Unfortunately, I have some triggers that modify TWO unit's stats at the same time. How would I make that work?

Okay, last thing I think I need to learn how to do with this system before I am sold on it. I have a unit that changes classes, and when he goes from one class to the next, certain qualities transfer, certain qualities stay in memory and decay over time (but can be transfered to the structure of the new unit), so what if I have AIDS with my system? If I have my hero change classes (create a new unit) then how would I easily transfer over his information? It looks like if I could just get the index value he represents, then change the unit that corresponds to his index, that everything would transfer fine.
 

tooltiperror

Super Moderator
Reaction score
231
Okay, this added a little more understanding. How do I access information from OUTSIDE the structure (aka, the functions and triggers?) So, my unit dies, does AIDS run the structure for that unit's onKill method? Or do I have to initiate something to make it register that event for that unit. I think I see how I have to register the trigger to activate on death, right? So I just register the event with this.unit onCreate and tell it to run the onKill method when the trigger executes, is that right? Then as long as everything is run inside of the AIDS structure, I don't need any external functions to make anything work? Is that a good summary?
No, the onKill method isn't a part of AIDS, I made that myself. Remember, read the comment, I 'pretended' to register that in the AIDS_onCreate method.

So then I have every function that modifies a unit's structure INSIDE the structure as a method, then it will work fine? Sounds a lot simpler than what I've been doing. Unfortunately, I have some triggers that modify TWO unit's stats at the same time. How would I make that work?
All your programming should be done inside the struct. I can't really help since you're not being specific.

Okay, last thing I think I need to learn how to do with this system before I am sold on it. I have a unit that changes classes, and when he goes from one class to the next, certain qualities transfer, certain qualities stay in memory and decay over time (but can be transfered to the structure of the new unit), so what if I have AIDS with my system? If I have my hero change classes (create a new unit) then how would I easily transfer over his information? It looks like if I could just get the index value he represents, then change the unit that corresponds to his index, that everything would transfer fine.
You would have to store all of that in the struct though, anything you want to save, but I think you can do something like this.
JASS:

set this.unit=CreateUnit(...)

You'll have to ask Jesus4Lyf the specifics on that.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top