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

Fastest Spell System

Status
Not open for further replies.
Level 7
Joined
Apr 18, 2010
Messages
102
Hi, for a while now, after leaning a little bit of vJass, i have been using DYNAMIC INDEXING in my spells, demonstrated in this tutorial

[vJASS] Dynamic Indexing Tutorial

When i was still using GUI i was using hashtables, using only 1 set of variables for all my spells (etc. Array of Caster, Target, Range, etc.) While accomplishing MUI by creating a dummy unit as the spell's ID and adding it to a unique group per different spell..


I am wondering what would be the fastest / most systematic spell making system?

Lately ive been looking at Perfect Unit Indexing, and other unit indexing like the one used here:

[LoL] Gragas Abilities Set v1.5


Ofcourse, I plan to stick with vJass and would use dummy recycler systems, spell effect events, and the kind to improve the performance of the spells.
 

Wrda

Spell Reviewer
Level 26
Joined
Nov 18, 2012
Messages
1,887
Honestly, structs in vJASS are useless for this matter: 1)they generate a lot of garbage code behind for little gain.
2) they act like integers (for array purposes), thus they do what a normal GUI dynamic indexing would but you can't reference the exact instance without making additional integer globals and then loop.
3) Consequently, they make you do double the work than needed.
Gragas Abilities Set v1.5 doesn't use Dynamic Indexing, it uses Unit Indexer, which is different.
 

Wrda

Spell Reviewer
Level 26
Joined
Nov 18, 2012
Messages
1,887
Unit Indexer is one of your best options, still it doesn't make it able to do cast the same spell with the same unit, the data will be overwritten.
The Dynamic Indexing (the one from GUI) is another best option for you, specially if you want to do the mechanism mentioned above. Transformed to JASS should just work fine.
 
Level 7
Joined
Apr 18, 2010
Messages
102
I could make it so every spell instance spawn / recycld a dummy and use its custom value (or in this case , index) so that the same unit can cast the same spell multiple times.

Ohh.. so i should just stick to the normal dynamic indexing and just do that in vjass without using structs?
 
Level 7
Joined
Apr 18, 2010
Messages
102
Hmm but then bot using scopes would mean that if i use array variables like caster, target , range
At the deindexing part i would have to do the following:

Caster[loop] =caster[index]
Target[loop] = target[index]
Range[loop] = range[index]
...
Same goes for every variable i want to be used for the whole spell's duration

While using scopes i would just
Deallocate ..

...

A few thoughts:
-maybe i should use UNIT INDEXERS for systems,
-dynamic indexing with scopes for spells
 

Wrda

Spell Reviewer
Level 26
Joined
Nov 18, 2012
Messages
1,887
Hmm but then bot using scopes would mean that if i use array variables like caster, target , range
At the deindexing part i would have to do the following:

Caster[loop] =caster[index]
Target[loop] = target[index]
Range[loop] = range[index]
...
Same goes for every variable i want to be used for the whole spell's duration

While using scopes i would just
Deallocate ..

...
Need to private them.
The thing is, Caster[loop] = Caster[maxindex] will be way faster and simpler than the deallocate method from structs, which I think is replacing the previous node with next node and so on. That means it keeps the indexes in order, but there's no real visible benefit in doing that.

A few thoughts:
-maybe i should use UNIT INDEXERS for systems,
-dynamic indexing with scopes for spells
-Really depends on what you need, but yes, bribe's Unit Indexer in particulary, since I like it, is useful and you could use it.
-yes.
 
Level 39
Joined
Feb 27, 2007
Messages
5,011
You are massively overthinking this. Never in my entire history as a mapmaker have I come upon a situation in which the overhead associated with allocating and deallocating struct instances has made any sort of noticeable difference. Wrda is trying to scare you away from doing something for the tiniest of minor gains in 'code efficiency' that you will never, ever notice. Consider how infrequently that code will be run compared to all other parts of your spell code. The ease of use increase associated with struct allocation/deallocation is absolutely worth it:
JASS:
scope Spell
globals
  public keyword SpellData
  public SpellData array SD
  public integer COUNT = 0
  private integer IT = 0 //global iterator so functions can access it
  public real PERIOD = 0.05
  public timer SpellTimer = CreateTimer()
  public trigger SpellTrigger = CreateTrigger()
endglobals

public struct SpellData
  unit u = null
  unit d = null
  real x = 0.
  real y = 0.
  integer dur = 0

  method endInstance takes integer currentIndex returns nothing
    call RemoveUnit(this.d)
    //do whatever else

    set SD[currentIndex] = SD[COUNT]
    set COUNT = COUNT-1
    set IT = IT - 1
    if COUNT == 0 then
      call PauseTimer(SpellTimer)
    endif

    call this.destroy()
  endmethod

  method doPeriodic takes nothing returns boolean
    //return true if instance should end
    set this.dur = this.dur -1
    return this.dur <= 0
  endmethod

  static method onPeriodic takes nothing returns nothing
    local thistype s

    set IT = 0
    loop
      set s = SD[IT]
      if s.doPeriodic() then
        call s.endInstance()
      endif

      set IT = IT+1
      exitwhen IT >= COUNT
    endloop
  endmethod

  static method create takes ... returns thistype
    local thistype s = thistype.allocate()

    //set variables

    set SD[COUNT] = s
    set COUNT = COUNT + 1
    if COUNT == 1 then
      call TimerStart(SpellTimer, PERIOD, true, function thistype.onPeriodic)
    endif
  endmethod
endstruct
endscope
Now you don't have to think about it ever again.
 
Level 18
Joined
Jan 1, 2018
Messages
728
the deallocate method from structs, which I think is replacing the previous node with next node and so on. That means it keeps the indexes in order, but there's no real visible benefit in doing that.
Incorrect, if this operation really took O(n), nobody would use structs.

Let me tell you how allocate and deallocate really work.
For every struct, three variables are created. Two integers, and one integer array. These are used as a stack for indices that can be recycled.
The array is 1-indexed, so the value at index 0 is unused. When there exists an object with a certain index, the value at that index in the array is set to -1.
When an object is deallocated, its value in the array is set to either 0, if the stack is empty, or the index that was previously on top of the stack.
About the two integer variables: one of them tracks the index in the array that corresponds to the top of the stack, while the other tracks the next available index if the stack is empty.

The 'benefit' of doing it like this has nothing to do with keeping the indices in order, it's to not randomly change an object's reference index.
 
Status
Not open for further replies.
Top