• 🏆 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!

Time Warp - Revisited

Basic idea by teuncreemers. Inspired by writing complex 2-D arrays, I made Time Warp a group spell by using 2D arrays within a hashtable. This spell is fully-MUI and heavily bug-proofed.

Launch this spell on a target area and you have them right where you want them! Units that attempt to flee will be attacked by the magic of the portal; units that stick around are at your mercy... there is no escape!


A fleet of inter-dimensional banshees haunt the targets in a select area until the link collapses, thrusting each victim back through time, retracing their steps.

Magic lasts longer and has higher Area of Effect at each level.

Credits:
- Berb for Projectile, Knockback Lite
- Grim001 for AutoIndex and AutoEvents
- Anitarf for Vector

Spell requires Warcraft 3 patch 1.30, extensive modification for Projectile (to use Effect type instead of Unit) and slight modification for AutoIndex (player count increase) and Vector (replace null return value with 0).

Keywords:
Time, warp, travel, system, machine, original, spell, bribe, teuncreemers, vjass, Zinc, fun, high, performance, versatile, youtube
Contents

Time Warp (Map)

Reviews
11:11, 26th May 2010 The_Reborn_Devil: The coding looks very good and it's well documented. Many constants which allow users to change it too. The effects are neat as well. Status: Approved Rating: Highly Recommended

Moderator

M

Moderator

11:11, 26th May 2010
The_Reborn_Devil:

The coding looks very good and it's well documented. Many constants which allow users to change it too. The effects are neat as well.


Status: Approved
Rating: Highly Recommended
 
Level 15
Joined
Jul 6, 2009
Messages
889
-Why not just use SpellEvent or GTrigger? It saves having people to use 'yet' another system.
-Your struct name is a bit ... strange. A? Something like data is much better.
-Timer period is 0.01, 100 FPS is a bit too much, something like 0.03125 works.
-Effects should be customizable.
-GetDurationFromLevel() should be at the top of the script in configurables section. Make it a function if you must.
-Why the hell are you using hashtables in a struct? Use TimerUtils or KeyTimers2 to pass data, it is much more cleaner looking.
-Make the entire if line: if IsUnitEnemy() and etc a configurable function at the top... so it'd be ValidateUnit( unit )....
-Actually, unsure whats better, but use a filter method and do the 'actions' in there.

----------------------------------------------

-Spell is terrible looking right now, Units collide each other resulting in ugly movement, either turn collision off or use SetUnitX/Y.
-The spell idea is basically a 'Blink Back' or 'X Marks the Return' from DotA. Not particularly original.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
-Why not just use SpellEvent or GTrigger? It saves having people to use 'yet' another system.
-Your struct name is a bit ... strange. A? Something like data is much better.
-Timer period is 0.01, 100 FPS is a bit too much, something like 0.03125 works.
-Effects should be customizable.
-GetDurationFromLevel() should be at the top of the script in configurables section. Make it a function if you must.
-Why the hell are you using hashtables in a struct? Use TimerUtils or KeyTimers2 to pass data, it is much more cleaner looking.
-Make the entire if line: if IsUnitEnemy() and etc a configurable function at the top... so it'd be ValidateUnit( unit )....
-Actually, unsure whats better, but use a filter method and do the 'actions' in there.

----------------------------------------------

-Spell is terrible looking right now, Units collide each other resulting in ugly movement, either turn collision off or use SetUnitX/Y.
-The spell idea is basically a 'Blink Back' or 'X Marks the Return' from DotA. Not particularly original.

I agree with most points except with the last statement
it's called "X marks the Spot" and this one is aoe and moves the unit back over the path it went there instead of just instantly teleporting it which leads me to the conclustion that's not just a cheap copy but a a very nice idea
(well..mostlikely it would be even better with SetUnitX/Y as mentioned already)

I'm not much into JASS so I'm not sure but aren't these libaries just wrapper functions for hashtables?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
There goes my concept:(
I posted that at (my) 3:00AM so there isn't much going through my mind at that stage, and went to bed 5 minutes later. If I had posted it at a human hour, I wouldn't have missed that key note. I have to sincerely apologize.

This is your idea, I've put that at the top of the spell, but I've also read about a lot of timetravel spells similar in principle to this one so by making it open source (since I did all the code anyway and I am a strong believer in open source) I don't see it as a problem. I've noted that this is your basic concept at the top of the description.

Have you tried either spell, yet? I asked you if it worked and you didn't reply back.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
-Why not just use SpellEvent or GTrigger? It saves having people to use 'yet' another system.
I don't use other systems. Ooooh 15 lines of easy code is suddenly a huge complex system that no one will ever understand. Really? TimerUtils is hundreds of lines, yet I could do everything I need just by good coding and my whole spell would be the same length as the stupid system.

-Your struct name is a bit ... strange. A? Something like data is much better.
Thanks, i am new to structs. I think i'll use data from now on.
-Timer period is 0.01, 100 FPS is a bit too much
Normally, yes, but in this case not.
-Effects should be customizable.
-GetDurationFromLevel() should be at the top of the script in configurables section. Make it a function if you must.
-Make the entire if line: if IsUnitEnemy() and etc a configurable function at the top... so it'd be ValidateUnit( unit )....
-Actually, unsure whats better, but use a filter method and do the 'actions' in there.
This spell is basic. A lot of things compacted into the fewest lines possible. For now it is what it is, hence 1.0. Later, I'll add UI-friendly features.

-Why the hell are you using hashtables in a struct? Use TimerUtils or KeyTimers2 to pass data, it is much more cleaner looking.
lol, there is no way those can contain the massive amounts of unit-specific data I'm storing in that one hashtable. Again, I don't use other peoples' 500 lines of code overglorified systems. I just get the job done with maximum compatibility within the scope of the spell and to not cause lag.
-Spell is terrible looking right now, Units collide each other resulting in ugly movement, either turn collision off or use SetUnitX/Y.
Yeah, I need to return it to SetX/Y, thing is I need the units to stand still during the callback process so I used SUP for convenience (Though when you bring it to my attention I should just add a "stop" command manually and go back to setunitx/y)
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
Yeah I tried the spell and it worked fine.
The thing was that I wanted to make this spell myself just to make my first real jass spell on my own. You made it for me which was great to learn stuff a bit but in the end I was planning to make this spell on my own anyway.
I'm not mad or something, just a littlebit disappointed:p
 
Level 6
Joined
Nov 3, 2008
Messages
117
Ok. Sum Feedback. As xBlackrose said don't use hashtables. For that i recommend you to use another struct in combination with Tables by Vexorian. Do sth like this
[jass="code"]struct data
//your variables which needs to be saved go here
static HandleTable "blub"
static method get takes unit u returns data
return "blub"
endmethod

static method create unit u returns data
local data a=data.create()
set "blub"=a
return a
endmethod

endstruct[/code]

the HandleTable can be created in the Init function

But as you havent mentioned yet, that you don't want to use others libs, you can use UnitUserData aswell, but that may malfunction with other peoples maps.

you should know that hashtables are 2x slower than arrays ( structs )

Common. That Spell Indexer library is just nonsense. What you do there is like A BJ of the TriggerRegisterAnyUnitEventBJ (lolz) no need to use this.

Don't use bj_LastCreatedGroup. This may end up in a conflict, because it can be used anywhere else and then your group has more units as it actually should have to.
FirstOfGroup loops are slow. Use a filter function to detect units.


I will add more later, bit tired atm.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
you should know that hashtables are 2x slower than arrays ( structs )
Common knowledge. However, I need an array of essentially infinite size, and you can't do that without hashtables or some way of generating dozens to hundreds of extra arrays.[/quote]

What you do there is like A BJ of the TriggerRegisterAnyUnitEventBJ
Unlike the BJ, this only registers events to players that are actually playing, so you're saving a lot of handles. Btw you type like a child.

Don't use bj_LastCreatedGroup. This may end up in a conflict, because it can be used anywhere else and then your group has more units as it actually should have to.
Thanks, I will change this when I get home :)
FirstOfGroup loops are slow. Use a filter function to detect units.
I have a feeling you're dissecting much of my code without realizing why I'm doing it like that (such as the hashtables).
Edit: On second look (now that I'm home) it turns out you are right here. I originally had some operators there that I thought would benefit more from inlining the code, but you're right :) Thanks again.
 
Last edited:
Level 15
Joined
Jul 6, 2009
Messages
889
I don't use other systems. Ooooh 15 lines of easy code is suddenly a huge complex system that no one will ever understand. Really? TimerUtils is hundreds of lines, yet I could do everything I need just by good coding and my whole spell would be the same length as the stupid system.

It does everything you need on its own with just a function call, it removes the need of having to do what you do, i'll potentiallly get tiresome repeating for every spell. Also, if you are uploading it to a public spell section, other people use such 'stupid' systems, and will want to use it.

Normally, yes, but in this case not.
Set to configurable

Again, I don't use other peoples' 500 lines of code overglorified systems. I just get the job done with maximum compatibility within the scope of the spell and to not cause lag.
Public resource forum.

Yeah, I need to return it to SetX/Y, thing is I need the units to stand still during the callback process so I used SUP for convenience (Though when you bring it to my attention I should just add a "stop" command manually and go back to setunitx/y)

Why are you having a stop order anyways? Stopping order is essentially recalcuating pathing, which results in the ugly movement. You didn't change much visual wise in this aspect, it still yields same result. If you want a unit to not be able to issue orders, use SetUnitPosition and turn collision off. But then again, users should be able to decide if this spell interrupts channeling or not.

Unlike the BJ, this only registers events to players that are actually playing, so you're saving a lot of handles. Btw you type like a child.
I have an ownership changing spell, it changes ownership to a random player, then it orders the target to spam all its spells on the a random area, wasting it, but, it somehow changes the ownership into an unused slot. And in result, it does not work as it's not registered for that player.

--

-I have LOC_FX_B set to "", I want not effect, yet handles are being wasted as an empty effect is being created.
-Every if dependent on a constant boolean should be static, so it's not compiled, = effeciency
-Ambience should be configurable, the colours and crap.
-Since you insist on using as least handles as possible, add an if for each effect:

JASS:
if STRING_EFFECT != "" then
    call DestroyEffect( AddSpecialEffect() )
        endif
- Area should be configurable.

- return untrue, why not use false, it does the same thing.
- o_O, duration should be in seconds. And should return a real.
- Actually, your entire spell is messy, seriously, what the heck, modular?, tab?, released?, indeed (why not 'true'), I'm lost as to how it functions. And where you calculate how long until 'release back to normal' state.

Gameplay wise:
- Fog is somewhat strange how it is instant, add an option for fading it.
- Have an area of effect indicator for the spell, which means new base spell, use Channel.

--

This spell is 100% MUI and can be cast infinite times, even on the same units, without causing any errors.
So too can alot of spells.

Spell is open source, so here are the vJass codes necessary to make this work:
Every public spell is open source .__. why state that it is?
 
Last edited:
Level 16
Joined
Jul 4, 2008
Messages
1,106
. . . Stop teh flame, Even I don't know anything of vJass, I have to say this:
If he wants to make everything by himself and not to use stuff by other people, then he can do it.
vJass is not probably about copying from other people. (Which seems to be atm the way everyone is doing)

~ Thanks for dropping my IQ, I normally don't even post on a vJass spell.
 
Level 15
Joined
Jul 6, 2009
Messages
889
it's called "X marks the Spot" and this one is aoe and moves the unit back over the path it went there instead of just instantly teleporting it which leads me to the conclustion that's not just a cheap copy but a a very nice idea

Oops. Dunno what I was thinking, X Marks the Spot it is, mistake lol. But still, the only difference between this and DotA's is area of effect and that it is not instant.

Total code nazi O_O
I am not a code nazi :(

I'm MRFAN1231, and I'm a Bomb.

. . . Stop teh flame, Even I don't know anything of vJass, I have to say this:
Flaming? I see none.

If he wants to make everything by himself and not to use stuff by other people, then he can do it.
Of course he can, but then why would he upload it for other people to use? He's letting 'other people' use it.

vJass is not probably about copying from other people. (Which seems to be atm the way everyone is doing)
What?

--

For the spell, maybe you should add lightning effects, or just something that link's the unit to it's original position. To show where it will 'return to'. Also, since this spell will serve some use as it's DotA related and people love DotA. Maybe you would want to add a 'Force Return' spell, all the linked units will move back to the original spot.
 
Nice job overall. Neat spell. =)

However, some notes on the code:
JASS:
    constant boolean untrue = not true
    constant boolean indeed = not untrue

Any particular need of this? =P

Also, for the spell indexer problem, this:
JASS:
    private function Init takes nothing returns nothing
        call CreateSpellTrigger(function data.Conditions)
        static if CHANGE_AMBIENCE then
            set fadeTimer = CreateTimer()
            call InitFadeValues()
        endif
    endfunction

Could be:
JASS:
library TimeWarp initializer Init requires optional SpellIndexer
//...

private function Init takes nothing returns nothing
        local trigger t = null
        static if LIBRARY_SpellIndexer then
            call CreateSpellTrigger(function data.Conditions)
        else
            set t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t,Condition(function data.Conditions))
        endif
        static if CHANGE_AMBIENCE then
            set fadeTimer = CreateTimer()
            call InitFadeValues()
        endif
    endfunction

In case someone forgets to import the library or generally doesn't want to. If it is optional that'll fix the problem and make it less reliant.

Also:
JASS:
        if FX != "" then
            call DestroyEffect(AddSpecialEffect(FX,x,y))
        endif

Should be static. Since it is a constant string, it won't be modified outside the scope and thus the evaluation will have the same result each time on execution.

You could always use a linked list for speed with the timer, but that is up to you. It doesn't make much of a difference besides nanoseconds though. (and readability compared to the struct/stack loop)

Overall, nice job. =D I like this spell.
 
Level 15
Joined
Jul 6, 2009
Messages
889
Linking to the JassHelper thread is useful, in fact, linking to any required resource is usually the case.

Also, about the Forced Return Subskill, I think it is better if you add it once the hero learns it rather then having it instantly, and it's convenient slightly for the user to have it in the button position [1,1], so it doesn't take up the other skill's spot.

If target's level of 'Return' is 0, then add it [when they learn it].
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Thanks, yeah, actually I originally planned to do that but the configuration used to look terrible until I used Berbanog's layout :p

Now I can do it without any real problems. Actually, almost all of the suggestions I've so far received were ideas that I already thought of implementing but wasn't sure if it was needed (like the fade effect and the return-position).
 
Level 5
Joined
Dec 8, 2008
Messages
102
holy macaroni thats the sweetest spell since a long time...
code is clean and efficient and spell is eye-candy

one suggestion would be: when the units fly back, make something with them so they look like time travelers (for example color them black like in dota, or let them fade for about 50%)

5/5

EDIT: and GetTimerData(t) does 100% the same like LoadInteger(table,GetHandleId(t),0)
 
Level 7
Joined
Jun 6, 2010
Messages
224
-Your struct name is a bit ... strange. A? Something like data is much better.
-Timer period is 0.01, 100 FPS is a bit too much, something like 0.03125
-The spell idea is basically a 'Blink Back' or 'X Marks the Return' from DotA. Not particularly original.

For the first
It doesn't matter what the name is as long as its private

it can be :

JASS:
private struct g
   unit u
   static method create takes unit u returns thistype
       local thistype this = thistype.allocate()
       set this.u = u
       return this
   endmethod
endstruct

For the 2nd

Depends on what code it runs.
if it sets a variable to smth or move a unit to x,y its not big deal
if it enums a group its heavy

For the 3rd
i think you just hate the guy. This spell is neat. I may use it someday.

Well done bribe
Kudos from me :)
 
Last edited:
Level 3
Joined
Feb 4, 2010
Messages
35
It would be nice of you to make a simpler video of you using the spell once, because i'm having trouble understanding what is actually happening. I don't have time right now to download it, that's why i'm a bit picky. Just a thought.

Looks pretty cool though!
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
The damage is like this: if a unit gets out of (approximately) 240.0 range of where he was standing when the spell hit him, the missile bounces from the origin to the unit, dealing the damage each time it hits the unit, then returns for more. The further away he is from the origin, the more time the missile needs to hit him, effectively dealing less damage. The closer he is (but not within 240. range) to the origin, the more damage will be done only because the missile doesn't need so much time to bounce back and forth.

I'm going to be making an update soon to the Retro Library, so I'll be sure to update the description of this spell, too, with that info.

Thanks for the tip!
 
Level 4
Joined
Jul 6, 2011
Messages
73
for the love of all things awesome SOMEONE MAKE A WORKING TIMESTOP SPELL (that covers a medium radius around the hero. when this has been accomplished send it to me please)
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
A Time Stop spell would be a lot easier to do than this. It's really rude that you rate a spell down just because it's not the spell you're looking for. That's like if I went to a spell that creates a chicken and marked it down because it didn't create a rabbit.

Edit: You can make this a request in the Requests section here:

http://www.hiveworkshop.com/forums/requests-341/
 
  • Like
Reactions: pyf
Level 4
Joined
Jul 6, 2011
Messages
73
Hey bribe i didnt downrate im sorry if i offended u i really want a timestop spell your spell isnt bad im just mad cause no one makes a damn timestop and how do i unsubscribe to this thread cause im getting emails its annoying
 
Top