1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. The Results have come out of the old ARENA oven. Check out who won the 30th Texturing Contest!
    Dismiss Notice
  4. Hey guys, we've posted the Results for the 30th Modeling Contest. Check them out!
    Dismiss Notice
  5. The 15th Mini-Mapping Contest came to an end. The Secrets of Warcraft 3 are soon to be revealed! Come and vote in the public poll for your favorite maps.
    Dismiss Notice
  6. The 12th incarnation of the Music Contest is LIVE! The theme is Synthwave. Knight Rider needs a song to listen to on his journey. You should definitely have some fun with this theme!
    Dismiss Notice
  7. Join other hivers in a friendly concept-art contest. The contestants have to create a genie coming out of its container. We wish you the best of luck!
    Dismiss Notice
  8. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[GUI-friendly] Wayback (Time Travel/Rewind System)

Submitted by _Guhun_
This bundle is marked as approved. It works and satisfies the submission rules.
[GUI-Friendly] Wayback v1.1.0

System Requirements

This system allows you to make units "go back in time" by periodically saving snapshots of their current states in a Linked List created with GLL. When you want to make the unit return to another point in time, the system simply reads the saved data and restores the unit to that point, including (by default) life, mana and position.

You can also make the unit slowly rewind through time, going through each position it had previosuly been in.

For vJASS users, there exists a similar system made by the ever-awesome Bribe: Retro.

Snapshots:

Wayback periodically saves the current state of a unit in a "snapshot", which is identified by a unique ID generated with GMUI (using the generic Recycle Key: 1). Because of the way snapshots are saved, advanced users can save their own data in a snapshot, allowing for more than just unit life, mana and position to be saved and restored.

Hashtable:

Unit Handle ID
0 -> timer
1 -> GLL List
2 -> snapshot counter
3 -> maximum snapshots (determines max rewind time = period * maximum snapshots)

Timer Handle ID
0 -> unit

(negative) Snapshot ID
0 -> unit HP
1 -> unit MP
2 -> unit X
3 -> unit Y


How to Import:

  1. Open World Editor. File -> Preferences -> Tick box for "Automatically create unknown variables (...)"
  2. Copy the "GUI MUI Engine" category into your map.
  3. Open the "GMUI Header" trigger and copy its contents into your map header.
  4. Copy the "GUI Linked Lists" category into your map.
  5. Open the "GLL Header" trigger and copy its contents into your map header, below GMUI.
  6. Copy the trigger category "Wayback System" into your map.
  7. Delete all disabled triggers with "Import" in their name
  8. Done!
Using the System:


  • Since the system needs to save snapshots periodically, it will require more processing power for each unit you want to be able to go back in time. Therefore, you need to manually specify when you want a unit to be able to go back through time.

    Variables before execution:
    Wayback_Unit The unit we wish to register in the system.
    Wayback_Time The maximum time the unit will be able to return in time.
    Wayback_Precision How precise the system will be (time between each snapshot)


    GUI-only method:
    • Actions
      • Set Wayback_Unit = YourUnit
      • Set Wayback_Time = YourMaxTime
      • Set Wayback_Precision = YourDesiredPrecision
      • Trigger - Run Wayback Main <gen> (ignoring conditions)


  • The system saves a lot of data in hashtables, so if you are not gonna have a unit go back through time anymore, you should unregister it. It is especially important to unregister a unit before it is removed from play (to avoid memory leaks). Unregistering a unit also stops the periodic timer that takes snapshots.

    Variables before execution:
    Wayback_Unit The unit we wish to unregister from the system.
    Wayback_Time We set this to a negative number when we want to unregister a unit.


    GUI-only method:
    • Actions
      • Set Wayback_Unit = YourUnit
      • Set Wayback_Time = -1
      • Trigger - Run Wayback Main <gen> (ignoring conditions)


  • This is the main feature of wayback. Using this function, the unit is instantly transported back in time, appearing on the position it had been in at the specified time.

    Variables before execution:
    Wayback_Unit The unit we want to take back through time.
    Wayback_Time The amount of time (in seconds) the unit will go back (0 for maximum). Use a non-negative number.


    GUI-only method:
    • Actions
      • Set Wayback_Unit = YourUnit
      • Set Wayback_Time = YourTime (non-negative, 0 for max)
      • Trigger - Run Wayback Main <gen> (checking conditions)


  • This is another cool feature that allows you to make units slowly go back in time over a specified duration.

    Variables before execution:
    Wayback_Unit The unit we want to take back through time.
    Wayback_Time The amount of time (in seconds) the unit will go back. Use a negative number.
    Wayback_Precision How much time the rewind should take.


    GUI-only method:
    • Actions
      • Set Wayback_Unit = YourUnit
      • Set Wayback_Time = YourTime (negative number)
      • Set Wayback_Precision = YourDuration
      • Trigger - Run Wayback Main <gen> (checking conditions)



  • At the very top of the Wayback Main trigger, you will find this code that allows you to easily configure Wayback to store any value that you want, instead of only the values that the system would normally store!

    Code (vJASS):

    //===========================================================================
    // Easy Configuration
    //===========================================================================

    // Use the functions/textmacros defined here to change the behaviour of the system by changing
    // what data is stored in a snapshot. You could, for example, store the unit's flying height as
    // well by simply adding the commented out lines at the end of each function.

    //! novjass
    function StoreSnapshotData takes integer snapshot, unit whichUnit returns nothing
    //! endnovjass
    //! textmacro StoreSnapshotData
        //Whenever a new snapshot of a unit is created, this code is run to store data.
        //You can alter this function(JASS)/textmacro(vJASS) to store whatever values you need.
     
        call SaveReal(udg_Wayback_Hashtable, snapshot, 0, GetUnitState(whichUnit, UNIT_STATE_LIFE))
        call SaveReal(udg_Wayback_Hashtable, snapshot, 1, GetUnitState(whichUnit, UNIT_STATE_MANA))
        call SaveReal(udg_Wayback_Hashtable, snapshot, 2, GetUnitX(whichUnit))
        call SaveReal(udg_Wayback_Hashtable, snapshot, 3, GetUnitY(whichUnit))
        // Example of user-defined data:
        //call SaveReal(udg_Wayback_Hashtable, snapshot, 4, GetUnitFlyHeight(whichUnit))
    //! endtextmacro
    //! novjass
    endfunction
    //! endnovjass

    //! novjass
    function UnitLoadSnapshot takes integer snapshot, unit whichUnit returns nothing
    //! endnovjass
    //! textmacro UnitLoadSnapshot
        //Whenever a new snapshot of a unit is created, this code is to restore the unit.
        //You can alter this function(JASS)/textmacro(vJASS) to use any custom data you have added.
     
        call SetUnitState(whichUnit, UNIT_STATE_LIFE, LoadReal(udg_Wayback_Hashtable, snapshot, 0))
        call SetUnitState(whichUnit, UNIT_STATE_MANA, LoadReal(udg_Wayback_Hashtable, snapshot, 1))
        call SetUnitX(whichUnit, LoadReal(udg_Wayback_Hashtable, snapshot, 2))
        call SetUnitY(whichUnit, LoadReal(udg_Wayback_Hashtable, snapshot, 3))
        // Example of user-defined data:
        //call SetUnitFlyHeight(whichUnit, LoadReal(udg_Wayback_Hashtable, snapshot, 4))
    //! endtextmacro
    //! novjass
    endfunction
    //! endnovjass
     


  • Code (vJASS):

    //===========================================================================
    // Code and API
    //===========================================================================

    //=======
    //Register Unit functions
    //=======

    //Registers a unit in the System, allowing you to specify a function for the periodic timer
    function Wayback_RegisterUnitEx takes unit whichUnit, real period, integer maxSnapshots, code timerFunc returns nothing
    endfunction

    //Register unit with default timer function
    function Wayback_RegisterUnit takes unit whichUnit, real period, integer maxSnapshots returns nothing
    endfunction

    //Register unit using a duration instead of maximum snapshots and using default timer function
    function Wayback_RegisterUnitDuration takes unit whichUnit, real period, real duration, real period2 returns nothing
    endfunction

    //Register unit using a duration instead of maximum snapshots
    function Wayback_RegisterUnitDurationEx takes unit whichUnit, real period, real duration, real period2, code timerFunc returns nothing
    endfunction

    //Unregisters a unit from the system, deleting all snapshot data and the timer
    function Wayback_UnregisterUnit takes unit whichUnit returns nothing
    endfunction

    //=======
    //Restoring and Rewinding functions
    //=======

    //Instantly restores a unit to their oldest snapshot
    //Returns the ID of the snapshot for extended functionality
    function Wayback_RestoreUnit takes unit whichUnit returns integer
    endfunction

    //Instantly moves unit "time" seconds back in time, up to their oldest snapshot
    //Returns the ID of the snapshot for extended functionality
    function Wayback_RestoreUnitEx takes unit whichUnit, real time returns integer
    endfunction

    //Instantly moves unit a single snapshot back in time
    //The unit ID variable should be the unit's handle ID
    //Returns the ID of the snapshot for extended functionality
    function Wayback_RestoreUnitByIdOneStep takes unit whichUnit, integer unitID returns integer
    endfunction

    //Instantly moves unit a single snapshot back in time
    //Returns the ID of the snapshot for extended functionality
    function Wayback_RestoreUnitOneStep takes unit whichUnit returns integer
    endfunction

    //=======

    //Takes a unit back in "time" seconds in time, snapshot-by-snapshot, over "duration" seconds
    function Wayback_RewindUnit takes unit whichUnit, real time, real duration returns nothing
    endfunction
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //End of Wayback
    ////////////////////////////////////////////////////////////////////////////////////////////////////
     




Test Map:

Command Action
unregister Unregisters all units from the system
register Registers all units in the system
wayback returns a unit 1 second in time
rewind slowly rewinds a unit 2.5 seconds back in time

Units in the test map will automatically go back in time whenever they cast an ability. In addition, you may use the above commands to test wheter the system is correctly registering and unregistering units. An unregistered unit will die and revive at position (0,0) of the map. There's not much else to test, really.

Updates and Version History:
v1:
0.1.0 > Initial Release
1.0.0 > Added function to slowly rewind units and option to return less than the max time
1.0.0a > GLL Import now contains all the correct variables
1.0.0b > Fixed some mistakes in the system description
1.1.0 > Added StoreSnapshot data UnitLoadSnapshot functions for easy config.
Upcoming:
Contents

Guhun's Wayback System (Map)

Reviews
Dr Super Good
Comments and Suggestions: Potentially useful system for implementing Heroes of the Storm Tracer style Recall abilities. Fairly easy to use as well. Having a demonstration ability that works similar to Tracer's in Heroes of the Storm would be useful...
  1. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    326
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    I swear this I'll stop flooding the spell sections with systems for now, I'm just kind of in a coding spree and just wanted to get this last one out, if only to somewhat demonstrate the data structures system.
     
    Last edited: Jan 29, 2018
  2. Chaosy

    Chaosy

    Joined:
    Jun 9, 2011
    Messages:
    10,575
    Resources:
    18
    Maps:
    1
    Spells:
    11
    Tutorials:
    6
    Resources:
    18
    I'll assume it just teleports the user to the old position/state?

    I'd probably love a visual with that. Like Tracer's E from Overwatch
     
  3. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    326
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    Yeah, basically it will by default return the unit to its original position and health/mana. But you can add more data to a snapshot. So, if, for example, you are using some sort of debuff system, you could make it so the unit loses all the debuffs it did not have, thought that may require some extra coding. For something like a stun system, though, that would be really easy to implement, I believe.

    As for visuals, right now it just teleports the unit. You could always add special effects to that, but I'm also planning on making an easy way to make the unit slowly go back through time, like Tracer does in the Widow cinematic.
     
  4. Dark_Axl

    Dark_Axl

    Joined:
    Dec 12, 2007
    Messages:
    471
    Resources:
    2
    Maps:
    1
    Spells:
    1
    Resources:
    2
    so... I assume this will become like a GUI version of Bribe's Retro ?
     
  5. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    326
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    Oh, yeah, that's basically what it comes down to, though I'm not too familiar with how retro works. But it doesn't seem like Retro supports instantly taking the unit back in time, though I could be wrong. Another difference is that Retro uses a global precision/max return time, while this system has it specified on a per-unit basis (which is a bit slower per-snapshot recording, but not gonna make that much of a diffrence, I think). Also Retro uses vJASS, so it actually looks like a decent piece of software engineering, unlike JASS ^^


    Either way, I forgot to add it to the description as an alternative vJASS system. Gonna do that now.

    Update:
    Version 1.0.0 >

    -Added function to slowly rewind units back in time
    -Added option to specify a return time lower than the max time
     
    Last edited: Jan 13, 2018
  6. Keiu

    Keiu

    Joined:
    Nov 28, 2017
    Messages:
    12
    Resources:
    0
    Resources:
    0
    Hello, may I ask something... do you need any special program to open/save maps that including JASS code? I am using Warcraft World Editor v1.28f, from the official Warcraft III game disk, but when I try to copy a JASS code spell into a custom map, it always has some script errors. By the way, I clicked the "Automatically create unknown variables (...)" already.
    [​IMG]
    [​IMG]
     
  7. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    326
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    It looks like you forgot to put the code in your map Header, thus the functions are not being found when they are referenced.

    "
    1. Copy the "GUI MUI Engine" category into your map.
    2. Open the "GMUI Header" trigger and copy its contents into your map header.
    3. Copy the "GUI Linked Lists" category into your map.
    4. Open the "GLL Header" trigger and copy its contents into your map header, below GMUI.
    "

    The map header is the thing above your triggers which has the same name as your map file.

    IMAGE
     
    Last edited: Jan 13, 2018
  8. Keiu

    Keiu

    Joined:
    Nov 28, 2017
    Messages:
    12
    Resources:
    0
    Resources:
    0
    Thanks for responding. I did all the step you listed in the 'How to Import', but now it has more script errors...
    [​IMG]
     
  9. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    326
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    It seems I forgot to add two variables to the variable import trigger, which is the cause of that error. I'll fix this asap.

    It should work once you create an integer variable named : "Lists_RECYCLE_KEY" and another trigger variable named "Lists_Trigger".

    Sorry for the inconvenience.

    PS: If it still doesn't work, you may have copied the GLL map header above the GMUI map header. It should be below.

    Update:
    1.0.0a > GLL Import now contains all the correct variables
     
    Last edited: Jan 13, 2018
  10. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    7,958
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Hi thanks for your contribution. I actually will be having more free time at i got rid of a toxic game that was dragging me down (Hearthstone) and the GUI Retro rework has been in my sights for some time.

    I haven't done a Teleport thing in Retro as the coordinates are logged in a 4D hashtable, but will make recalling instantly a feature in the system as it's more logical to build that in than to have a separate system for it.

    The add/remove can either be automatic or manual.

    Other stuff like i have in the Time Warp spell-such as effects-will be excluded from the internal system and enabled strictly through add-ons (where they belong).

    The basic API would be a simple add/remove trigger command and for activating it would be a variable set by the user to the travel duration preceded by how much time to go back. The most basic form will look something like:

    Retro__RewindUnit = (TriggeringUnit)
    Retro__RewindTo = 2.00 (seconds ago)
    Retro__RewindRate = 1.00 (takes 1 second to rewind by 2 seconds - 0 for instant).

    I look forward to seeing what other stuff comes up, but i plan to see this at a public release point by end of Feb.
     
  11. _Guhun_

    _Guhun_

    Joined:
    Jun 12, 2010
    Messages:
    326
    Resources:
    7
    Spells:
    6
    Tutorials:
    1
    Resources:
    7
    That's great xD
    Being too focused on a game can really be a detriment to productivity (talking from first-hand experience, too!)

    Can't wait for what you come up with :eek::eek:




    Update: Version 1.1.0

    Small update, but might be pretty useful one! Added an easy way to configure what data is stored in a snapshot of a unit by created two new fucntions which a JASS user can edit: Added StoreSnapshot data UnitLoadSnapshot functions for easy config.

    (If vJASS is enabled, the functions are converted to textmacros for better performance.
     
  12. MyPad

    MyPad

    Spell Reviewer

    Joined:
    May 9, 2014
    Messages:
    1,259
    Resources:
    6
    Models:
    1
    Icons:
    1
    Spells:
    3
    JASS:
    1
    Resources:
    6
    Edited tags to include GUI/Triggers as one of the tags.
     
  13. Dr Super Good

    Dr Super Good

    Spell Reviewer

    Joined:
    Jan 18, 2005
    Messages:
    25,380
    Resources:
    3
    Maps:
    1
    Spells:
    2
    Resources:
    3
    Comments and Suggestions:
    Potentially useful system for implementing Heroes of the Storm Tracer style Recall abilities. Fairly easy to use as well.

    Having a demonstration ability that works similar to Tracer's in Heroes of the Storm would be useful as I can imagine such abilities being the main use case for a system like this.​