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

[vJASS] Buff System

Level 7
Joined
Oct 11, 2008
Messages
304
I am sorry that I am not much of a use, as I can only come up with questions and ideas for now since my coding skills are on a basic level : (
The BuffSyste itself handles the instance without any problem, it uses the same method of Status with counter = counter + 1 for each buff if stack is partial or full.

So ya, there's no problem with that.

onApply1 -> add stun to the unit -> unit now is stunned (with 1)
onApply2 -> add stun to the unit -> unit still stunned (with 2 now)
onApply3 -> add stun to the unit -> unit still stunned (with 3 now)

onRemove2 -> stay stunned and with buff -> unit still stunned (with 2)
onRemove3 -> stay stunned and with buff -> unit still stunned (with 1)
onRemove1 -> remove stun of the unit -> unit is not stunned because counter = 0

Remember:

JASS:
        Example:
        
        //This will execute when:
        //  - A BUFF_STACK_NONE Buff is removed from a unit.
        //  - A BUFF_STACK_PARTIAL Buff from a certain source is removed from a unit.
        //  - A BUFF_STACK_FULL Buff instance is removed.
        method onRemove takes nothing returns nothing
            //Configure what happens when the Buff is removed.
        endmethod
        
        //This will execute when:
        //  - A BUFF_STACK_NONE/BUFF_STACK_PARTIAL Buff is applied to a unit
        //    not having the same Buff before it is applied.
        //  - A BUFF_STACK_PARTIAL Buff is applied to a unit already having
        //    the same buff but from a different source.
        //  - A BUFF_STACK_FULL Buff is applied to a unit.
        method onApply takes nothing returns nothing
            //Configure what happens when the Buff is applied.
        endmethod

I'm dumb, sorry about that xD it's all documented.
 
Level 7
Joined
Feb 9, 2021
Messages
301
The BuffSyste itself handles the instance without any problem, it uses the same method of Status with counter = counter + 1 for each buff if stack is partial or full.

So ya, there's no problem with that.

onApply1 -> add stun to the unit -> unit now is stunned (with 1)
onApply2 -> add stun to the unit -> unit still stunned (with 2 now)
onApply3 -> add stun to the unit -> unit still stunned (with 3 now)

onRemove2 -> stay stunned and with buff -> unit still stunned (with 2)
onRemove3 -> stay stunned and with buff -> unit still stunned (with 1)
onRemove1 -> remove stun of the unit -> unit is not stunned because counter = 0

Remember:

JASS:
        Example:
     
        //This will execute when:
        //  - A BUFF_STACK_NONE Buff is removed from a unit.
        //  - A BUFF_STACK_PARTIAL Buff from a certain source is removed from a unit.
        //  - A BUFF_STACK_FULL Buff instance is removed.
        method onRemove takes nothing returns nothing
            //Configure what happens when the Buff is removed.
        endmethod
     
        //This will execute when:
        //  - A BUFF_STACK_NONE/BUFF_STACK_PARTIAL Buff is applied to a unit
        //    not having the same Buff before it is applied.
        //  - A BUFF_STACK_PARTIAL Buff is applied to a unit already having
        //    the same buff but from a different source.
        //  - A BUFF_STACK_FULL Buff is applied to a unit.
        method onApply takes nothing returns nothing
            //Configure what happens when the Buff is applied.
        endmethod

I'm dumb, sorry about that xD it's all documented.
So, to conclude, I should use Disable System with your adjustments and Buff System with A BUFF_STACK_NONE to achieve my desired purpose? (which means having two buffs [stun with permanent and remove when the buff is finished]). And then I have to rebuild my cc reduction?
 
Level 7
Joined
Oct 11, 2008
Messages
304
Ya, also for the duration issue, you can simply do this:

JASS:
function onAbilityCast ...
    local StunBuff sb = StunBuff.add(source, target) //will return the buff already applied, because it don't stack
    local real newDuration = 5. //this spell apply 5 sec stun

    if sb.duration < newDuration then //if not, will use the already left duration of the buff
        set sb.duration = newDuration
    endif

    //... etc
endfunction
 
Level 11
Joined
Jul 4, 2016
Messages
626
Okay, so how? I desperately need Spell Steal for my Altered Melee. I was trying to make one by trying to adding a spell's orderid and spell steal priority integer but as a vJass noob that I am I can't figure out how to do this properly.
he hasn't been around for months, not sure you will get an answer.
 
Level 4
Joined
May 14, 2018
Messages
34
Hi there!
I know it`s probly already death thread but i should ask anyway.
What if i want to keep buff afte unit death?
I mean, i see method, that removes buff after unit death, but i can`t find out any solution to avoid it with all stuff given.
Or probly there is some way to save and use variables like dispellType,stackType,rawcode but i didn`t found it.
Very appreciated if someone will help me.
 
Level 38
Joined
Feb 27, 2007
Messages
4,951
What if i want to keep buff afte unit death?
Why? I only see this being relevant if the unit can revive in some way but you want to retain all buffs it had before it died... and I don't understand why you would want that. What should happen to the buffs' durations while the unit is dead (suspended, continue, last indefinitely)? What about effects due to the buffs? How long should it last when the unit dies? What if the unit is never revived?

There is kind of an easy way to stop buffs being removed... but it has a really bad downside. Comment out the only line in the onDeath function and buffs will never be purged on unit death:
JASS:
private static method onDeath takes nothing returns nothing
    //call thistype.dispelAll(GetTriggerUnit())
endmethod
However, this means that the data allocated by the system to keep track of buffs on a unit will become permanent, effectively amounting to a slow but consistent memory leak over time. Because the buffs are never purged, the allocated struct instances are never deallocated and they just sit there. You might think "well we should just clear that data when the unit no longer exists on the map, right?"... but there's no way to know when the unit doesn't exist anymore because no event could possibly fire when it ceases to exist. You could instead try to clean the data when units decay (turn from bodies to corpses) but even at that point the unit could be revived so maybe you don't want to clear the data yet. And heroes don't decay at all so they would never fire the event (but if they're permanently reviveable then this doesn't matter).
 
Level 4
Joined
May 14, 2018
Messages
34
There is kind of an easy way to stop buffs being removed... but it has a really bad downside. Comment out the only line in the onDeath function and buffs will never be purged on unit death:
Let`s say i want to use it for Hero buff, that won`t dispell untill some actions done.
Ik about all isues of it, and proposed solution it`s not for me.
My goal it`s make variable that can disable OnDeath method and being declared at buff creating point, for certain conditions.
Smth like:
JASS:
if GetUnitAbilityLeve(GetSellAbilityUnit(),'A000') > 0 then
set b.DisspelOnDeath==false
endif
so it will lead to smth like
JASS:
private static method onDeath takes nothing returns nothing
if this.OnDeath==true then
    call thistype.dispelAll(GetTriggerUnit())
endif
endmethod
So in that case, method "OnDeath" after checking wouldn`t do anything for This specific buff instance.
I hope you got what i mean, coz i`m bad at explaining :)
But anyway thank you for ur answer
 
Last edited:
Level 38
Joined
Feb 27, 2007
Messages
4,951
Ok, in principle that should work. It still does leak some data for units whose buffs are not dispelled on death and are never revived. I would just straight up make the buff undispellable as long as that boolean flag variable is set to true:
JASS:
    struct Buff
        boolean isDispellable = true
        //...
        method remove takes nothing returns nothing
            local boolean remove = false
            local integer id
            local thistype head
            local integer count
        
            // alteration in the line below this:
            if this.exist and not this.isDispellable then
                //...
            debug else
                debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "[Buff]: Attempted to remove non-existing Buff instance.")
            endif
        endmethod
        //...
    endstruct
Then you simply set the isDispellable flag to false for any buff that should persist through death (and other dispels). When it should be able to be removed, set it to true and either manually run .remove or dispel the unit.
 
Level 4
Joined
May 14, 2018
Messages
34
Ok, in principle that should work. It still does leak some data for units whose buffs are not dispelled on death and are never revived. I would just straight up make the buff undispellable as long as that boolean flag variable is set to true:
Thank you very much for this.
It looks like very simple but i couldn`t get it by myself.
Anyway i very appreciated.
Last question: There is any guides at Hive about this type of building code?
I`m just started and learned simple jass, so i think atleast reading about vJass gonna help me improve.
Thanks
 
Level 38
Joined
Feb 27, 2007
Messages
4,951
You're welcome, happy to help you see the solution :)
Last question: There is any guides at Hive about this type of building code?
There is a code/programming tutorials section located here. There is a subforum specifically for JASS tutorials here. However, there are probably not many tutorials about 'general programming and learning JASS' so the best suggestion I have for you is this: experiment and write code on your own, and when you get stuck simply post a thread here asking your question so that someone like me can help point you in the right direction.

You can also message me on Discord if you have any specific or simple questions you don't want to make a thread about. Travesty#8133
 
Level 38
Joined
Feb 27, 2007
Messages
4,951
Ok I understand now so I'll just speak my mind and then shut up:

Making most of the struct members readonly and then in a module manually accessing and setting those members directly with the post-JASSHelper array variable names to avoid the fact that they're readonly is just stupid. There's no reason they need to be readonly to begin with because in what circumstance would any of them be written to? Only a user who knew what they were doing would do that. It makes the code look silly, too, and slightly harder to understand.

Okay so call me stupid (and I realize this is 2016 code) but I really don't understand why a big hunk of this system refers to struct members as arrays directly and reads/writes them in the JASSHelper-parsed form of s__Buff_.... What's the purpose? Why? It just makes it all harder to read and I don't understand why that was preferable. Also you'll get fucked if you ever change anything about the naming convention.

I'm referring to the BuffApply module and the entirety of BuffEvent. @Flux probably won't reply but maybe someone else has insights. I read the documentation about modules and they do not force something like this upon the user.
 
Last edited:
Level 4
Joined
May 14, 2018
Messages
34
Hello again here.
Got another question for this system.
In some point of copypasting and changing buff structs, cjass compiler started crashing with error "unclosed or unopened module, true use module compability mode"
I`m sure it`s problem due to it`s count, coz in other map it saves good, but in main map it appears in same place with absolutely differrent types of Buff structs.
Maybe anyone knows what happened, and any solution for it?
 
Top