First attempt at making a struct spell.

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
Why exactly do you need any of that inside a struct? If you want movement then you just need two reals for X and Y and a unit you're moving. The rest (delay, fuse, blast, damage) can all be constant globals.
...

So I can learn how to do it properly.

The ABC Guy said:
unit types and ability ID's should be constant globals, not struct variables
Thanks.
 

SFilip

Gone but not forgotten
Reaction score
634
> So I can learn how to do it properly.
You won't be successful in this if you use them in a spell where they're not needed.
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
> So I can learn how to do it properly.
You won't be successful in this if you use them in a spell where they're not needed.

Then I need something to look at. I still don't understand where to use them. And I probably wont until someone in the know helps out by posting more explicit instructions. -.-

I am having a timer on the mine and movement on the homing mine. Apparently I need this info to do the timer thing. I want to stop using TriggerSleepAction and use a timer, but to do that I need a struct to attach something to something. Or so I've been told.

I could save myself the bother and frustration by using Handle Vars which Im familiar with, but I can see that using structs is needed in my map.

Please (for the love of chocolate everywhere!) I need more help than what the tutorials currently say. And what most people are saying is "Don't do that!" without actually telling how to do what Im trying to do.
 

Silvenon

New Member
Reaction score
19
Structs are not necessary for anything, vJass is not necessary for anything. They are made to make attaching safe, because Handle Vars can cause a bug which would make you lose your data (which is very rare, never happened to me). This bug happens because when I2H-ing, a handle can get corrupted and blah blah.....

vJass is mainly used for:
  • speed (in both aspects, coding and the executing)
  • organization
  • it just makes you feel cool
You can do everything with handle vars, but structs are preferred since they are much faster then the rusty ol' game cache, they save you much space and they're easier and faster to code with.

Try to understand. When you put something in a struct, you want that data to be transfered to another function (mostly via timer) and you want it to be MUI (that's why you create a local struct). Example:

JASS:
struct SomeStruct
    real crap
endstruct

function SomeFunc_Execute takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local SomeStruct ss = SomeStruct(GetHandleInt(t, "ss"))
    call DoSomethingWithCrap(ss.crap) // we don't need to declare it or anything
    call SetHandleInt(t, "ss", 0) // this is just to detach the struct from the timer
    call ss.destroy() // we just need to destroy this
    call DestroyTimer(t) // logically
    set t = null
endfunction

function SomeFunc takes nothing returns nothing
    local SomeStruct ss = SomeStruct.create // each time a new struct is created
    local timer t = CreateTimer()
    set ss.crap = GetRandomReal(0, 100)
    call SetHandleInt(t, "ss", ss) // we attach the struct to the timer
    call TimerStart(t, 0.1, false, function SomeFunc_Execute)
    set t = null
endfunction


So you put in a struct the data you would attach to a timer, and then you just attach it to the timer (so you attached that group of data). Example of Jass > vJass:

JASS:
constant function Spell_Id takes nothing returns integer
    return 'A000'
endfunction

function Spell_Condition takes nothing returns boolean
    return GetSpellAbilityId() == Spell_Id()
endfunction

function Spell_Actions takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    local real x1 = GetUnitX(c)
    local real y1 = GetUnitY(c)
    local real x2 = GetLocationX(l)
    local real y2 = GetLocationY(l)
    local real a = Atan2(y2 - y1, x2 - x1) // angle between caster and target location
    local timer t = GetExpiredTimer()
    call RemoveLocation(l)
    call SetHandleHandle(t, "c", c)
    call SetHandleReal(t, "x", x2)
    call SetHandleReal(t, "y", y2)
    call SetHandleReal(t, "a", a)
    call TimerStart(t, 1, false, function SomeOtherFunc)
    set c = null
    set l = null
endfunction


JASS:
struct Spell_Data
    unit c
    real x
    real y
    real a
endstruct

globals
    private constant integer SPELL_ID = 'A00'
endglobals

function Spell_Condition takes nothing returns boolean
    return GetSpellAbilityId() == SPELL_ID
endfunction

function Spell_Actions takes nothing returns nothing
    local Spell_Data sd = Spell_Data.create()
    local unit c = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local timer t = GetExpiredTimer()
    set sd.c = c
    set sd.x = GetLocationX(l)
    set sd.y = GetLocationY(l)
    set sd.a = Atan2(sd.y - x, sd.x - x)
    call SetHandleInt(t, "sd", sd)
    call TimerStart(t, 1, false, function SomeOtherFunc)
    call RemoveLocation(l)
    set c = null
    set l = null
endfunction


I'm trying to explain this the best I can, did this help you?
 

SFilip

Gone but not forgotten
Reaction score
634
The important thing you should note in Silvenon's last two blocks of code is that the first attaches and later retrieves 4 values.
The second does the same thing, but using structs. Because of that it only attaches 1 value (the struct itself) thus making everything must faster.

Also note that, despite popular belief, structs are not a replacement for handle vars, they are not an attachments system. They are just a system that makes attaching much easier.
 

Cohadar

master of fugue
Reaction score
209
They are just a system that makes attaching much easier.

Actually this is only a side effect, structs are good even without any attaching.
The most important feature of vJass is ability to declare globals in code, so we don't need to use those horrible udg_'s.
Anything else is just a bonus goody.
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
...Also note that, despite popular belief, structs are not a replacement for handle vars, they are not an attachments system. They are just a system that makes attaching much easier.

Thank you. That was one of the clearest helps about structs for awhile.
 

chovynz

We are all noobs! in different states of Noobism!
Reaction score
130
Screw you, why was I working my ass of if SFilip can beat me with a single sentence??

He hasn't "beat you". I'm still absorbing your post. Theres a lot in there.
Thank you too, for what you posted.

Happens to me heaps too.
 

Vexorian

Why no custom sig?
Reaction score
187
Structs are not necessary for anything, vJass is not necessary for anything. They are made to make attaching safe, because Handle Vars can cause a bug which would make you lose your data (which is very rare, never happened to me). This bug happens because when I2H-ing, a handle can get corrupted and blah blah.....

vJass is mainly used for:
  • speed (in both aspects, coding and the executing)
  • organization
  • it just makes you feel cool
You can do everything with handle vars, but structs are preferred since they are much faster then the rusty ol' game cache, they save you much space and they're easier and faster to code with.

Try to understand. When you put something in a struct, you want that data to be transfered to another function (mostly via timer) and you want it to be MUI (that's why you create a local struct). Example:

JASS:
struct SomeStruct
    real crap
endstruct

function SomeFunc_Execute takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local SomeStruct ss = SomeStruct(GetHandleInt(t, "ss"))
    call DoSomethingWithCrap(ss.crap) // we don't need to declare it or anything
    call SetHandleInt(t, "ss", 0) // this is just to detach the struct from the timer
    call ss.destroy() // we just need to destroy this
    call DestroyTimer(t) // logically
    set t = null
endfunction

function SomeFunc takes nothing returns nothing
    local SomeStruct ss = SomeStruct.create // each time a new struct is created
    local timer t = CreateTimer()
    set ss.crap = GetRandomReal(0, 100)
    call SetHandleInt(t, "ss", ss) // we attach the struct to the timer
    call TimerStart(t, 0.1, false, function SomeFunc_Execute)
    set t = null
endfunction


So you put in a struct the data you would attach to a timer, and then you just attach it to the timer (so you attached that group of data). Example of Jass > vJass:

JASS:
constant function Spell_Id takes nothing returns integer
    return 'A000'
endfunction

function Spell_Condition takes nothing returns boolean
    return GetSpellAbilityId() == Spell_Id()
endfunction

function Spell_Actions takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    local real x1 = GetUnitX(c)
    local real y1 = GetUnitY(c)
    local real x2 = GetLocationX(l)
    local real y2 = GetLocationY(l)
    local real a = Atan2(y2 - y1, x2 - x1) // angle between caster and target location
    local timer t = GetExpiredTimer()
    call RemoveLocation(l)
    call SetHandleHandle(t, "c", c)
    call SetHandleReal(t, "x", x2)
    call SetHandleReal(t, "y", y2)
    call SetHandleReal(t, "a", a)
    call TimerStart(t, 1, false, function SomeOtherFunc)
    set c = null
    set l = null
endfunction


JASS:
struct Spell_Data
    unit c
    real x
    real y
    real a
endstruct

globals
    private constant integer SPELL_ID = 'A00'
endglobals

function Spell_Condition takes nothing returns boolean
    return GetSpellAbilityId() == SPELL_ID
endfunction

function Spell_Actions takes nothing returns nothing
    local Spell_Data sd = Spell_Data.create()
    local unit c = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local timer t = GetExpiredTimer()
    set sd.c = c
    set sd.x = GetLocationX(l)
    set sd.y = GetLocationY(l)
    set sd.a = Atan2(sd.y - x, sd.x - x)
    call SetHandleInt(t, "sd", sd)
    call TimerStart(t, 1, false, function SomeOtherFunc)
    call RemoveLocation(l)
    set c = null
    set l = null
endfunction


I'm trying to explain this the best I can, did this help you?


gamecache is "decent" for attaching besides of it using like 10 bytes per new handle id that is not recycled which is not much when you find out that the handle id itself probably takes 4 bytes anyways.

But Handle vars are another story, for starters, if you insist on using their naming conventions that are so confusing, specially the whole "Local handle variables" name that is the mother of all confusion, go a head. But you should be able to remove all its functions but GetHandleInt , SetHandleInt and FlushHandleVars . Don't ever, ever use the other functions, specially SetHandleHandle and GetHandleUnit/Item whatever.

The only good was to use handle vars is to attach a pointer to array index, or an struct, if you want.

With this method, you are only needing one gamecache write/read per function call, which is not bad. You are not ever using I2H which will, for sure eventually break your map. (Really , if you got GetHandleUnit() used in your map, fix your map by removing it)

Any (I mean ANY) conversion from int to handle reference is not only calling for trouble it is also unnecessary.
 

Silvenon

New Member
Reaction score
19
If you're using structs, of course you will be using only SetHandleInt/GetHandleInt, that is logical. What kind of idiot would be using SetHandleHandle in vJass?? Struct is a synonym for safe attaching (at least to me), I know it's not meant only for safe attaching, but I use it mainly for that.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top