Dashing spell Help!

Coding Help

13 years
Well, i need a simple dash using JNGP. I need it to learn more about jass and all, so please make it simple and easy to understand! ???
13 years
Dash? Just "shooting" the caster towards the target area?
I am looking into similar things right too for the moment ^^ (However, since I am exploring the options to just use one timer for the whole map, I think someone else here have a simple way of doing it. )
You will need a timer for this. Now, there is probably someone here who could make a easy dash-spell here, you could also check out the Key Timers2, but that might be for a more experienced user.
I'll come back with something if no1 else have given you a answer (:
13 years
edited 13 years
Hmmm, definitely you've started with a difficult spell :)

Please in the triggers section check the DASH trigger. this code is heavily commented.

In order to see the effect, just order any red unit to attack.

To do: add eyecandy...


Code (jass) Select
1
library DASH initializer init requires Alloc, GetWidgetMeasures // Alloc is a library to manage struct creation and deletion
2
3
globals // with vJASS we can define globals freely, here's an example
4
    private constant real MINDIST = 116. //this is the min dist for melee units. this variable is only valid inside the library, for being "private"
5
    private constant real DT = 0.02 // timer interval...
6
    private constant real SPEED = 1300. // sets the unit speed...
7
    private          hashtable HT = InitHashtable() // this is the key to make any spell MUI...
8
    private          key DKEY // this "type" of data is a constant integer which is unique for this code. Useful with hastables...
9
endglobals
10
11
private struct data extends array // this struct allos to store data in one variable name
12
    unit c // we define the type of objects or handle the struct will use
13
    unit t // in this case, the caster unit and the target unit
14
    timer tm
15
    
16
    implement Alloc // injects alloc into the struct
17
    
18
    method destroy takes nothing returns nothing
19
        set .c = null // a short way to write "this.c"
20
        set .t = null
21
        call PauseTimer(.tm)
22
        call .deallocate() // very important frees the data to be used later...
23
    endmethod
24
    
25
    private static method Loop takes nothing returns nothing 
26
    // this method is only callable inside the struct. Any function outside the struct won't be able to call it.
27
        local thistype D = thistype(LoadInteger(HT, GetHandleId(GetExpiredTimer()), DKEY)) // we get the WHOLE DATA
28
        local real a = GetWidgetsAngle(D.c, D.t) // we now can call any part of the data in this function!!
29
        local real d = GetWidgetsDistance(D.c, D.t)
30
        if d <= MINDIST then
31
            call D.destroy()
32
            return
33
        endif
34
        call SetUnitFacing(D.c, a)
35
        call SetUnitX(D.c, GetUnitX(D.c) + SPEED * DT * Cos(a))
36
        call SetUnitY(D.c, GetUnitY(D.c) + SPEED * DT * Sin(a))
37
    endmethod
38
    
39
    method start takes nothing returns nothing
40
        call SaveInteger(HT, GetHandleId(this.tm), DKEY, integer(this)) // this is the data struct, integer(this) will get the index of the data
41
        call TimerStart(this.tm, DT, true, function thistype.Loop)
42
    endmethod
43
    
44
    static method create takes unit caster, unit target returns thistype
45
        local thistype d = thistype.allocate() // thistype refers to data, allocate creates the data struct
46
        set d.c = caster // now we set the components of the struct...
47
        set d.t = target
48
        if d.tm == null then
49
            set d.tm = CreateTimer() 
50
        endif
51
        return d
52
    endmethod
53
endstruct
54
55
private function dashit takes nothing returns boolean 
56
    local data D
57
    if GetIssuedOrderId() == OrderId("Attack") then
58
        call DisplayTimedTextFromPlayer(Player(0), 0,0,3, "c: " + GetUnitName(GetTriggerUnit())+ "| t: " + GetUnitName(GetOrderTargetUnit()))
59
        set D = data.create(GetTriggerUnit(), GetOrderTargetUnit())
60
        call D.start() // a variable can use their own functions :D
61
    endif
62
    return false
63
endfunction
64
65
private function init takes nothing returns nothing
66
    local trigger t = CreateTrigger()
67
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
68
    call TriggerAddCondition(t, Condition(function dashit)) // we use Conditions because they're faster then Actions...
69
    set t = null
70
endfunction
71
72
endlibrary
13 years
Well, the test ability trigger cant be enable!
13 years
I have a lot of codes there, sorry for not putting all cleaned up in the testmap, but the idea is that you check the "DASH" library only and if you want the dependencies (Alloc, GetWidgetMeasures). One good practice to understand the code is to read it from the end to the beginning.

Go ahead a fill me with questions :)
13 years
I cant see how it work if it cant even have a test ability trigger to do that, guy!
13 years
Hmm, Moyack, you mentioned hashtables. Now, I am very curious about the speed in those. I mean, a normal global variable with an array should be faster, but that speed difference, is it noticable, or am I a bit overanalytic?
13 years
Quote from: Judash137 on January 29, 2013, 10:44:44 AM
I cant see how it work if it cant even have a test ability trigger to do that, guy!
Do you need an ability to cast it?? ok...

Quote from: rvonsonsnadtz on January 29, 2013, 12:08:00 PM
Hmm, Moyack, you mentioned hashtables. Now, I am very curious about the speed in those. I mean, a normal global variable with an array should be faster, but that speed difference, is it noticable, or am I a bit overanalytic?
Yes, a global array is way faster but searching in it will be slow as more data is stored in the array. In the other hand, hashtables are a little bit slower but searching and getting data is way faster and totally direct. You won't notice any difference...
13 years
Well, glad that Moyack came to help.. Did some reading now about Key-Timers 2 that it isn't as good as it says. However, those posts are from august 2011, so if it is updated since, then perhaps their is some hope, otherwise, well..
My testing with it does atleast show that it doesn't fit my needs at all.. A quite quick test showed that it built up a HUGE nr of processes somewhere (in comparison with a much simpler yet more effective approach from me, which seemed to keep the CPU-usage quite steady).

Btw, a bit off-topic, but Moyack, I see u use the
Code (Jass) Select
1
2
local trigger t = CreateTrigger()
3
call RegisterEvent(t, blahblah)
4
call TriggerAddAction(t, blahblah)
5
set t = null
6

However.. By some unknown reasons, my triggers using this won't fire.. No clue why.
They want the "set gg_trg_blahblah = CreateTrigger()"
13 years
Code updated:

Code (jass) Select
1
library DASH initializer init requires Alloc, GetWidgetMeasures // Alloc is a library to manage struct creation and deletion
2
3
globals // with vJASS we can define globals freely, here's an example
4
    private constant integer ABILID = 'A000' //This will define the ability rawcode we'll use...
5
    private constant real MINDIST = 116. //this is the min dist for melee units. this variable is only valid inside the library, for being "private"
6
    private constant real DT = 0.02 // timer interval...
7
    private constant real SPEED = 1300. // sets the unit speed...
8
    private          hashtable HT = InitHashtable() // this is the key to make any spell MUI...
9
    private          key DKEY // this "type" of data is a constant integer which is unique for this code. Useful with hastables...
10
endglobals
11
12
private struct data extends array // this struct allos to store data in one variable name
13
    unit c // we define the type of objects or handle the struct will use
14
    unit t // in this case, the caster unit and the target unit
15
    timer tm
16
    
17
    implement Alloc // injects alloc into the struct
18
    
19
    method destroy takes nothing returns nothing
20
        set .c = null // a short way to write "this.c"
21
        set .t = null
22
        call PauseTimer(.tm)
23
        call .deallocate() // very important frees the data to be used later...
24
    endmethod
25
    
26
    private static method Loop takes nothing returns nothing 
27
    // this method is only callable inside the struct. Any function outside the struct won't be able to call it.
28
        local thistype D = thistype(LoadInteger(HT, GetHandleId(GetExpiredTimer()), DKEY)) // we get the WHOLE DATA
29
        local real a = GetWidgetsAngle(D.c, D.t) // we now can call any part of the data in this function!!
30
        local real d = GetWidgetsDistance(D.c, D.t)
31
        if d <= MINDIST then
32
            call PauseUnit(D.c, false) // unpuase the unit
33
            call IssueTargetOrder(D.c, "attack", D.t)
34
            call D.destroy()
35
            return
36
        endif
37
        call SetUnitFacing(D.c, a)
38
        call SetUnitX(D.c, GetUnitX(D.c) + SPEED * DT * Cos(a))
39
        call SetUnitY(D.c, GetUnitY(D.c) + SPEED * DT * Sin(a))
40
    endmethod
41
    
42
    method start takes nothing returns nothing
43
        call SaveInteger(HT, GetHandleId(this.tm), DKEY, integer(this)) // this is the data struct, integer(this) will get the index of the data
44
        call PauseUnit(this.c, true) // this is to make the unit facing change work...
45
        call TimerStart(this.tm, DT, true, function thistype.Loop)
46
    endmethod
47
    
48
    static method create takes unit caster, unit target returns thistype
49
        local thistype d = thistype.allocate() // thistype refers to data, allocate creates the data struct
50
        set d.c = caster // now we set the components of the struct...
51
        set d.t = target
52
        if d.tm == null then
53
            set d.tm = CreateTimer() 
54
        endif
55
        return d
56
    endmethod
57
endstruct
58
59
private function dashit takes nothing returns boolean 
60
    local data D
61
    if GetSpellAbilityId() == ABILID then
62
        set D = data.create(GetTriggerUnit(), GetSpellTargetUnit())
63
        call D.start() // a variable can use their own functions :D
64
    endif
65
    return false
66
endfunction
67
68
private function init takes nothing returns nothing
69
    local trigger t = CreateTrigger()
70
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
71
    call TriggerAddCondition(t, Condition(function dashit)) // we use Conditions because they're faster then Actions...
72
    set t = null
73
endfunction
74
75
endlibrary


the map is now cleaned up.

Quote from: rvonsonsnadtz on January 29, 2013, 06:10:39 PM
Btw, a bit off-topic, but Moyack, I see u use the
Code (Jass) Select
1
2
local trigger t = CreateTrigger()
3
call RegisterEvent(t, blahblah)
4
call TriggerAddAction(t, blahblah)
5
set t = null
6

However.. By some unknown reasons, my triggers using this won't fire.. No clue why.
They want the "set gg_trg_blahblah = CreateTrigger()"
Have you set the function as library bla initializer <your funciton name>??
13 years
Well, it still have no ability to test yet!
13 years
Judash137, any questions????