[System] Smooth Timers

Discussion in 'Starcraft 2 (SC2) Editor Help' started by Jesus4Lyf, Apr 23, 2010.

  1. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    Smooth Timers​

    Version 1.1.0​

    See attached SC2Lib file.
    Slightly similar to the Warcraft III Timer32 system, but nowhere near as cool. But GUI!

    • SmoothTimersExampleInit
      • Events
        • Timer - Elapsed time is 1.0 Game Time seconds
      • Local Variables
        • SmoothTimer = 0 <Integer>
      • Conditions
      • Actions
        • Variable - Set SmoothTimer = (NewSmoothTimer(SmoothTimersExample, 5))
        • General - Wait 2.0 Game Time seconds
        • DestroySmoothTimer(SmoothTimer)

    • SmoothTimersExample
      • Events
      • Local Variables
      • Conditions
      • Actions
        • UI - Display (Text((GetSmoothTimerData((GetExpiringSmoothTimer()))))) for (All players) to Debug area

    The example will just display "5" a whole lot. The premise is, that using the data integer as an index, you can attach whatever you wish to timers, which will fire 32 times per second. This is to overcome SC2 limitations on timers only being able to fire as fast as 16 times per second, as well as overcoming their lack of data attachment. :thup:

    The original SC2 timer system.

    Attached Files:

  2. PurgeandFire

    PurgeandFire zxcvmkgdfg

    +513 / 0 / -0
    Where is the code? Unless there is something to open .sc2lib besides galaxy editor. Well, I am mostly just curious of how you achieved it. I had an idea in mind but I doubted it would work. =)
  3. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    It's really difficult to show code. Because you can't show -everything- that easily. This lib has something like 24 things in it.

    I just fire off two timers running at 16 execs/sec each, and try to seperate them by 0.03125. I discovered that the UI (ie. display messages) do not display more than 16 times per second regardless, so I've assumed this works but haven't thoroughly tested it yet. :thup:

    The way I discovered that was by using 0.0 waits, which seem to equate to 0.03125 in single player (God knows if that's the same for b.net, though - timers on 0 period still go to 0.0625 it seems, so...).

    So.. yeah. :)
    I can always upgrade it some how if it turns out that the timers are somehow actually firing at the same time - and I'm sure that will be discovered soon enough, if they are. :D

    Internally, aside from that, the code is much like Timer32, it uses a doubly linked list of nodes which has a periodic handler to iterate through them. :)
  4. PurgeandFire

    PurgeandFire zxcvmkgdfg

    +513 / 0 / -0
    Heh, I was actually thinking of that two-timer method. :D But I didn't think it would work; I had just assumed that timers were inaccurate in general. But my idea was a bit messy and since I don't have the editor, it was nothing but a theory. =P

    How do these weird things always exist? :p It's as if blizzard adds them purposely for modders to find. I wonder what happens if you put in a negative (unless it crashes/syntax error) I guess you used game-time, since Romek got 0 wait = 0 s from using real-time. (Then again, real-time is apparently approximated)

    Nice of you to kick off with a decent timer system though, props for that since it is usually started off using some typecasting and whatever Blizz has to offer. =P
  5. Zwiebelchen

    Zwiebelchen You can change this now in User CP.

    +60 / 0 / -0
    Is there no way to make the timer fire faster than 16 times per second? How did you actually find that out? I mean ... couldn't the DisplayMessage be the one that can only fire 16 times and not the timer?

    If timers in SC2 can not run faster than 16 fps, then this really is a slap into the face of anyone who wants to "script" special effects or unit movement, etc.

    And did you do intense tests on the Wait function? Maybe timer systems are obsolete in SC2, depending on how good the wait function turns out to be.

    EDIT: I read the other threads in this forum ... seems that wait is awful too.

    However, first of, I want to thank you for the effort you are already putting into the editor to write all those amazing scripts already that come in so handy for all mappers out there in the future.

    One suggestion for this system: Could you somehow make it able to attach structs instead of integers to the timer? I know this is not possible, as indexing only allows integers, but I know you can come up with some neat workaround ... I do not want to index all my structs in the future - except you write an additional system like "GetStructId" or something that perfectly identifies all structs used.
  6. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    Thanks for your response.

    I can't yet pass records as parameters or return records. It's really unfortunate, but Blizzard has not (at least yet) implemented pointers in GUI.

    I expect some things to be done around function pointers and record pointers, at which point systems like this shall receive an update. Until then, I'm not even sure how they're going to go about it - if they are at all.

    I agree that indexing records is a pain. :)
  7. Zwiebelchen

    Zwiebelchen You can change this now in User CP.

    +60 / 0 / -0
    Hmm, so you wrote this especially for GUI users? In that case, would it be possible to attach structs in a galaxy-users-only version, as I am not going to use GUI at all, but start with galaxy right from the start.

    If not ... then there is always the possibility to create an auto-indexing system for structs, kinda like all those unit indexing systems in wc3. Is there really nothing like a native GetHandleId for structs?

    Alternatively, you could implement an internal struct ID for this timer system only. Kinda like when the data is attached, it puts the struct into an T32 internal global struct array and attaches the index of that struct in this array to the timer.

    This would magically allow structs for timers. However, the amount of timers and structs you can attach to them would be limited that way because of max array size, but I think that shouldn't be a problem.

    Or simply write a GetStructId lib ... I think that would be the easiest way to deal with that.

    PS: We need a systems&tutorials subforum for galaxy ;)
  8. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    That, and currently pointers to structs are currently type safe, so far as I can tell - unlike in WC3 where pointers to structs were literally integers.

    So, in other words, currently even if I did a Galaxy version, I believe I'd have to hard code what struct or struct pointer type can be passed in - making this approach useless.

    I think we will have to see what Blizz gives us in future patches, if you view the system in its current for as inadequate. Personally, I've never been a fan of waiting for Blizz. :)
    It is being considered, especially when some more content turns up.
  9. Zwiebelchen

    Zwiebelchen You can change this now in User CP.

    +60 / 0 / -0
    I could imagine structs being an extend of some other type ... have you checked that? In that case, you'd only need to create that mothertype array.

    If nothing else helps, then we would have to use custom structs by extends integer kinda like Newgen did them again ... But that would be such a waste.

    Damn, I can simply not understand why blizzard is trying to fuck us so much with timers.

    You have to agree that - in the current state - the system is quite useless as you do not want to create a struct array for every damn system you write. At least I wouldn't want to do that.
  10. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    Depends. A struct array can be really neat. Consider attaching to units or players - anything that has an index naturally. Example.
    I should do an indexing system, because guess what, Blizz implemented the same ol' custom value/user data thing...

    >I could imagine structs being an extend of some other type
    I'm not sure there's such a thing as "extend" yet. :confused:
    I'm hoping they add some flexibility with type safety around pointers. Lol... I just don't assume they would.
  11. Zwiebelchen

    Zwiebelchen You can change this now in User CP.

    +60 / 0 / -0
    Yeah, but there are situations where you have to attach to timers ...

    I simply can not believe that blizzard hasnt implemented a way to get a struct's ID. I mean: there are hashtables in Galaxy, arent they? Without a GetStructId, you wouldnt be able to use them in hashtables ...
    There simply HAS to be a mother-type, or certain natives wouldn't work. (I suppose there are natives that allow structs as input parameter ... maybe check the natives list ...)

    I once read somewhere that you could define user data completely different in SC2 ... but maybe that was just a false information.

    I think there is "extends". I saw it somewhere in one of those pre-editor "I checked the luas of the maps" discussions.
  12. Romek

    Romek Super Moderator Staff Member

    +961 / 0 / -0
    > I mean: there are hashtables in Galaxy, arent they?
    There are? :rolleyes:
  13. Zwiebelchen

    Zwiebelchen You can change this now in User CP.

    +60 / 0 / -0
    In this case, forget what I said. Blizzard obviously screwed us hard with Galaxy in its current state and I think I am definitely not going to script more complex systems until it fucking allows non-typesafe arrays or at least to create a GetStructId function.
    I am so going to spam the beta forums about that -_- ... I just feel like they made a fool out of us, providing us with an editor that is - script-wise - worse than the Wc3 editor.

    EDIT: If only they would allow me to post into the US beta forums ... >_>
  14. Cookiemaster

    Cookiemaster New Member

    +36 / 0 / -0

    and Banks look like gamecache to me.
  15. Zwiebelchen

    Zwiebelchen You can change this now in User CP.

    +60 / 0 / -0
    Hmm, are data tables just more-dimensional arrays or are they natives? In that case, you could check the input parameters for the data fields to find out the mother-type of structs.
  16. Cookiemaster

    Cookiemaster New Member

    +36 / 0 / -0
    Taken from: http://paste.sc2mapster.com/1979/

    It's not possible to create a data table in any way, you only specify wether the set/get var should be global or local, and supply a key with it. (which is in the form of a string.)

    Using DataTableValueType(bool global, string name) you can get what kind of object has been stored in the data table.
    // Data Table
    // - Data tables provide named storage for any script type.
    //   Table access may be either global or thread-local.
    // Types
    const int c_dataTypeUnknown             = -1;
    const int c_dataTypeAbilCmd             =  0;
    const int c_dataTypeActor               =  1;
    const int c_dataTypeActorScope          =  2;
    const int c_dataTypeAIFilter            =  3;
    const int c_dataTypeBank                =  4;
    const int c_dataTypeBool                =  5;
    const int c_dataTypeByte                =  6;
    const int c_dataTypeCameraInfo          =  7;
    const int c_dataTypeCinematic           =  8;
    const int c_dataTypeColor               =  9;
    const int c_dataTypeControl             = 10;
    const int c_dataTypeConversation        = 11;
    const int c_dataTypeDialog              = 12;
    const int c_dataTypeDoodad              = 13;
    const int c_dataTypeFixed               = 14;
    const int c_dataTypeInt                 = 15;
    const int c_dataTypeMarker              = 16;
    const int c_dataTypeObjective           = 17;
    const int c_dataTypeOrder               = 18;
    const int c_dataTypePing                = 19;
    const int c_dataTypePlanet              = 20;
    const int c_dataTypePlayerGroup         = 21;
    const int c_dataTypePoint               = 22;
    const int c_dataTypePortrait            = 23;
    const int c_dataTypeRegion              = 24;
    const int c_dataTypeReply               = 25;
    const int c_dataTypeRevealer            = 26;
    const int c_dataTypeRoom                = 27;
    const int c_dataTypeSound               = 28;
    const int c_dataTypeSoundLink           = 29;
    const int c_dataTypeString              = 30;
    const int c_dataTypeText                = 31;
    const int c_dataTypeTimer               = 32;
    const int c_dataTypeTransmission        = 33;
    const int c_dataTypeTransmissionSource  = 34;
    const int c_dataTypeTrigger             = 35;
    const int c_dataTypeUnit                = 36;
    const int c_dataTypeUnitFilter          = 37;
    const int c_dataTypeUnitGroup           = 38;
    const int c_dataTypeUnitRef             = 39;
    const int c_dataTypeWave                = 40;
    const int c_dataTypeWaveInfo            = 41;
    const int c_dataTypeWaveTarget          = 42;
    // General functionality
    native void     DataTableClear (bool global);
    native int      DataTableValueCount (bool global);
    native string   DataTableValueName (bool global, int index);
    native bool     DataTableValueExists (bool global, string name);
    native int      DataTableValueType (bool global, string name);
    native void     DataTableValueRemove (bool global, string name);
    // Type-specific value set/get
    // - c_dataTypeAbilCmd
    native void         DataTableSetAbilCmd (bool global, string name, abilcmd val);
    native abilcmd      DataTableGetAbilCmd (bool global, string name);
    // - c_dataTypeActor
    native void         DataTableSetActor (bool global, string name, actor val);
    native actor        DataTableGetActor (bool global, string name);
    // - c_dataTypeActorScope
    native void         DataTableSetActorScope (bool global, string name, actorscope val);
    native actorscope   DataTableGetActorScope (bool global, string name);
    // - c_dataTypeAIFilter
    native void         DataTableSetAIFilter (bool global, string name, aifilter val);
    native aifilter     DataTableGetAIFilter (bool global, string name);
    // - c_dataTypeBank
    native void         DataTableSetBank (bool global, string name, bank val);
    native bank         DataTableGetBank (bool global, string name);
    // - c_dataTypeBool
    native void         DataTableSetBool (bool global, string name, bool val);
    native bool         DataTableGetBool (bool global, string name);
    // - c_dataTypeByte
    native void         DataTableSetByte (bool global, string name, byte val);
    native byte         DataTableGetByte (bool global, string name);
    // - c_dataTypeCameraInfo
    native void         DataTableSetCameraInfo (bool global, string name, camerainfo val);
    native camerainfo   DataTableGetCameraInfo (bool global, string name);
    // - c_dataTypeCinematic
    native void         DataTableSetCinematic (bool global, string name, int val);
    native int          DataTableGetCinematic (bool global, string name);
    // - c_dataTypeColor
    native void         DataTableSetColor (bool global, string name, color val);
    native color        DataTableGetColor (bool global, string name);
    // - c_dataTypeControl
    native void         DataTableSetControl (bool global, string name, int val);
    native int          DataTableGetControl (bool global, string name);
    // - c_dataTypeConversation
    native void         DataTableSetConversation (bool global, string name, int val);
    native int          DataTableGetConversation (bool global, string name);
    // - c_dataTypeDialog
    native void         DataTableSetDialog (bool global, string name, int val);
    native int          DataTableGetDialog (bool global, string name);
    // - c_dataTypeDoodad
    native void         DataTableSetDoodad (bool global, string name, doodad val);
    native doodad       DataTableGetDoodad (bool global, string name);
    // - c_dataTypeFixed
    native void         DataTableSetFixed (bool global, string name, fixed val);
    native fixed        DataTableGetFixed (bool global, string name);
    // - c_dataTypeInt
    native void         DataTableSetInt (bool global, string name, int val);
    native int          DataTableGetInt (bool global, string name);
    // - c_dataTypeMarker
    native void         DataTableSetMarker (bool global, string name, marker val);
    native marker       DataTableGetMarker (bool global, string name);
    // - c_dataTypeObjective
    native void         DataTableSetObjective (bool global, string name, int val);
    native int          DataTableGetObjective (bool global, string name);
    // - c_dataTypeOrder
    native void         DataTableSetOrder (bool global, string name, order val);
    native order        DataTableGetOrder (bool global, string name);
    // - c_dataTypePing
    native void         DataTableSetPing (bool global, string name, int val);
    native int          DataTableGetPing (bool global, string name);
    // - c_dataTypePlanet
    native void         DataTableSetPlanet (bool global, string name, int val);
    native int          DataTableGetPlanet (bool global, string name);
    // - c_dataTypePlayerGroup
    native void         DataTableSetPlayerGroup (bool global, string name, playergroup val);
    native playergroup  DataTableGetPlayerGroup (bool global, string name);
    // - c_dataTypePoint
    native void         DataTableSetPoint (bool global, string name, point val);
    native point        DataTableGetPoint (bool global, string name);
    // - c_dataTypePortrait
    native void         DataTableSetPortrait (bool global, string name, int val);
    native int          DataTableGetPortrait (bool global, string name);
    // - c_dataTypeRegion
    native void         DataTableSetRegion (bool global, string name, region val);
    native region       DataTableGetRegion (bool global, string name);
    // - c_dataTypeReply
    native void         DataTableSetReply (bool global, string name, int val);
    native int          DataTableGetReply (bool global, string name);
    // - c_dataTypeRevealer
    native void         DataTableSetRevealer (bool global, string name, revealer val);
    native revealer     DataTableGetRevealer (bool global, string name);
    // - c_dataTypeRoom
    native void         DataTableSetRoom (bool global, string name, int val);
    native int          DataTableGetRoom (bool global, string name);
    // - c_dataTypeSound
    native void         DataTableSetSound (bool global, string name, sound val);
    native sound        DataTableGetSound (bool global, string name);
    // - c_dataTypeSoundLink
    native void         DataTableSetSoundLink (bool global, string name, soundlink val);
    native soundlink    DataTableGetSoundLink (bool global, string name);
    // - c_dataTypeString
    native void         DataTableSetString (bool global, string name, string val);
    native string       DataTableGetString (bool global, string name);
    // - c_dataTypeText
    native void         DataTableSetText (bool global, string name, text val);
    native text         DataTableGetText (bool global, string name);
    // - c_dataTypeTimer
    native void         DataTableSetTimer (bool global, string name, timer val);
    native timer        DataTableGetTimer (bool global, string name);
    // - c_dataTypeTransmission
    native void         DataTableSetTransmission (bool global, string name, int val);
    native int          DataTableGetTransmission (bool global, string name);
    // - c_dataTypeTransmissionSource
    native void                 DataTableSetTransmissionSource (bool global, string name, transmissionsource val);
    native transmissionsource   DataTableGetTransmissionSource (bool global, string name);
    // - c_dataTypeTrigger
    native void         DataTableSetTrigger (bool global, string name, trigger val);
    native trigger      DataTableGetTrigger (bool global, string name);
    // - c_dataTypeUnit
    native void         DataTableSetUnit (bool global, string name, unit val);
    native unit         DataTableGetUnit (bool global, string name);
    // - c_dataTypeUnitFilter
    native void         DataTableSetUnitFilter (bool global, string name, unitfilter val);
    native unitfilter   DataTableGetUnitFilter (bool global, string name);
    // - c_dataTypeUnitGroup
    native void         DataTableSetUnitGroup (bool global, string name, unitgroup val);
    native unitgroup    DataTableGetUnitGroup (bool global, string name);
    // - c_dataTypeUnitRef
    native void         DataTableSetUnitRef (bool global, string name, unitref val);
    native unitref      DataTableGetUnitRef (bool global, string name);
    // - c_dataTypeWave
    native void         DataTableSetWave (bool global, string name, wave val);
    native wave         DataTableGetWave (bool global, string name);
    // - c_dataTypeWaveInfo
    native void         DataTableSetWaveInfo (bool global, string name, waveinfo val);
    native waveinfo     DataTableGetWaveInfo (bool global, string name);
    // - c_dataTypeWaveTarget
    native void         DataTableSetWaveTarget (bool global, string name, wavetarget val);
    native wavetarget   DataTableGetWaveTarget (bool global, string name);
  17. Zwiebelchen

    Zwiebelchen You can change this now in User CP.

    +60 / 0 / -0
    So without a struct indexing system, you can not use structs in the data table ... hell, blizzard did really make a mess out of that struct engine. :thdown:

    I just hope this is all still subject of change ...

    In the current state, Galaxy is even worse than JASS.
  18. Jesus4Lyf

    Jesus4Lyf Good Idea™

    +394 / 0 / -0
    >In the current state, Galaxy is even worse than JASS.
    Worse than vJass*.
    JASS only had arrays. :)
  19. Cookiemaster

    Cookiemaster New Member

    +36 / 0 / -0
    JASS had arrays, and GetHandleID/H2I.
  20. Romek

    Romek Super Moderator Staff Member

    +961 / 0 / -0
    > JASS had arrays, and GetHandleID/H2I.
    Exactly. :p

    Also, I can confirm that the timers can indeed only run 16 times per second. It took 6.25 seconds for a timer with a 0.01 second timeout to expire 100 times. :(

Share This Page