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.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top