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

[vJASS] Structs there and here...

Status
Not open for further replies.
Level 29
Joined
Mar 10, 2009
Messages
5,016
SOLVED!

This is my first ever vJASS struct spell, its a simple Damage Over Time...
JASS:
library DoT initializer init uses TimerUtils

globals
        private constant integer DOT_SPELLID    = 'A000'
        private constant string SFX             = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl"
        private constant string ATTPNT          = "chest"
        private constant attacktype ATT         = ATTACK_TYPE_CHAOS
        private constant damagetype DAM         = DAMAGE_TYPE_FIRE
        private constant real DURSPEED          = 0.5
endglobals

private constant function DOT_DAMAGE takes integer i returns real
    return 10. + i * 5
endfunction

private constant function DOT_DURATION takes integer i returns real
    return 5. + i * 3
endfunction

    private struct DamOT
        unit u 
        unit t
        real dam
        real dur
        integer level
        effect sfx
        static method action takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = GetTimerData(t)
            if .dur > 0 and GetWidgetLife(.t) > 0.405 then
                set .dur = .dur - DURSPEED
                call UnitDamageTarget(.u, .t, .dam, false, false, ATT, DAM, null)
                call BJDebugMsg("remaining time is " + R2S(.dur))
                call BJDebugMsg("damage is " + R2S(.dam))
            else
                call ReleaseTimer(t)
                call DestroyEffect(.sfx)           
            endif
            set t = null
        endmethod
        
        static method creates takes nothing returns thistype
            local thistype this = thistype.create()
            local timer t = NewTimer()
            set .u= GetTriggerUnit()
            set .t = GetSpellTargetUnit()
            set .level = GetUnitAbilityLevel(.u, DOT_SPELLID) 
            set .dam = DOT_DAMAGE(.level)
            set .dur = DOT_DURATION(.level)
            set .sfx = AddSpecialEffectTarget(SFX, .t, ATTPNT) 
            call SetTimerData(t, this) 
            call TimerStart(t, DURSPEED, true, function thistype.action)
            set t = null
            return this
        endmethod
    endstruct
    
private function DOT_CAST takes nothing returns boolean  
    if GetSpellAbilityId()==DOT_SPELLID then
        call DamOT.creates()
    endif
    return false
endfunction

//============================================================

private function init takes nothing returns nothing
    local trigger t                          = CreateTrigger()          
    call TriggerRegisterAnyUnitEventBJ      (t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition                (t, function DOT_CAST) 
    set t                                    = null
endfunction

endlibrary

My questions are;
1. Instead of using create, I can use allocate?
2. Why cant I use private static method?
3. Instead of "this" whreas I can use .u OR .r , I can assign for example "dot" whereas I can use dot.u OR dot.r, so is this always the case?
4. Did I release the timer correctly?
5. I really dont want to use TimerUtils, what are my options besides hashtables?
 
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
  1. Yes, but it's private. Create can be overridden (no need to name your method "creates").
  2. For? I don't think you can make a private static create method if that's what you're trying to do but I might misremember.
  3. Yes, that's just a struct reference and it's how you access member variables of a struct outside of the struct's methods (or inside static methods). In fact, naming the variable in a static method "this" and then using .foo is kind of a hack.
  4. Looks fine, although you don't need to null it.
  5. Why don't you want to use TimerUtils? Basically your options are TimerUtils or a similar system, hashtables, or some odd engine glitches that aren't fully understood and there's no reason to use over hashtables or timerutils.
 
4. All handles should be nulled as they allocate less RAM that way. It's not just about "this won't be destroyed". Even if something is never destroyed the stack pointer count will be lower and encourages better practice.

5. Should be using a stack loop or doubly-linked list while using one single timer - it will achieve the best performance as well as removing the need for TimerUtils. Jesus4Lyf's Timer32 module (T32x) is a good solution for many. Alternatively, you can code it yourself which has a learning curve but can be coded from memory alone once you know how it works.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
4. All handles should be nulled as they allocate less RAM that way. It's not just about "this won't be destroyed". Even if something is never destroyed the stack pointer count will be lower and encourages better practice.
Meh, it isn't a big deal either way and I wouldn't say either way is better than the other assuming you know the issues related to not nulling.

5. Should be using a stack loop or doubly-linked list while using one single timer - it will achieve the best performance as well as removing the need for TimerUtils. Jesus4Lyf's Timer32 module (T32x) is a good solution for many. Alternatively, you can code it yourself which has a learning curve but can be coded from memory alone once you know how it works.
That only works for low periods. For high values (over, say, a tenth of a second) it will behave strangely in the user's eyes since the damage interval won't be consistent with when the spell was cast and if you're using a buff it will be out of sync.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Right, misread that 0.5 as 0.05 ;)

For something like that he could even use a silly counter system on a low-period timer, firing every time an instance's counter reaches 0.5, but that would be much less efficient and more cumbersome than TimerUtils.
And even if it were more efficient it would be a lot of wasted effort. Sometimes it's better to just do things the easy way.
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
Thank you guys, I know that custom made timers/libraries are very useful but I just want to know some alternatives besides them, for now, hashtables is my best option, I really cant use Stack loop coz I dont trust them and its confusing...

So I have come up with another solution using hash, saves the term "this" as integer then load it as integer as well...

For? I don't think you can make a private static create method if that's what you're trying to do but I might misremember.

static method >>> private static method can't be done?, why?...


Now my lasts questions;
1. When using timer libraries with release timer or other libraries, what if hundreds of spells/applications are using them, is it OK with no conflicts?...

2. I read some codes that there are next.prev, what are they?...

Yes, but it's private. Create can be overridden (no need to name your method "creates").

if I delete the "s", it has an error
 
Last edited:
Level 20
Joined
Jul 6, 2009
Messages
1,885
I've just tested and you can freely make a private static method, even the one that overrides the default constructor.
1. When using timer libraries with release timer or other libraries, what if hundreds of spells/applications are using them, is it OK with no conflicts?...
They won't conflict.
if I delete the "s", it has an error
That's impossible, i just copied your code to a map, renamed the constructor to 'create' and no error showed up on save. (Remember to rename the function when you call it too - call DamOT.creates())
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Thank you guys, I know that custom made timers/libraries are very useful but I just want to know some alternatives besides them, for now, hashtables is my best option, I really cant use Stack loop coz I dont trust them and its confusing...
The stack loop doesn't work well for long periods (like this code).

So I have come up with another solution using hash, saves the term "this" as integer then load it as integer as well...
That's just the standard hashtable method and you are basically recreating a worse version of TUtils by doing this.

static method >>> private static method can't be done?, why?...
I thought it might not be doable with the create method specifically, but it definitely is. That said, why would you want that method to be private? You're trying to instantiate it from outside the struct, which makes me think it shouldn't be private.

Now my lasts questions;
1. When using timer libraries with release timer or other libraries, what if hundreds of spells/applications are using them, is it OK with no conflicts?...
As long as there are enough timers available. A few hundred should be more than you'll ever use but you can crank up the number of necessary.

2. I read some codes that there are next.prev, what are they?...
Instance variables for linked lists.

if I delete the "s", it has an error
That's because your method calls .create() so it would be infinitely recursive. Replace the .create() call inside that method with .allocate().
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
I dont have my JNGP with me now, but I'll test it again tonight, somehow the private static method is giving me an error...

Also, that's why I put "s" so that the called method is different than the create inside the method :), otherwise like Purplepot says, must use allocate...

...why would you want that method to be private?

Nothing special, Im just testing and asking why :)...
 
Status
Not open for further replies.
Top