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

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.

READ ME

JASS:
=================================B U F F     S Y S T E M====================================
This system has two parts:
    - CREATE_BUFF_OBJECT: Create ability and buff to use for this system.
        + When the first time you create buff object, you MUST CLOSED Jassnewgen and RE-OPEN it.
        + If you use JNGP 2.0, dont worry about external object each times you save map (RECOMMENDED).
        + If you use JNGP v5d or else, please put CREATE_BUFF_OBJECT to a seperate trigger (DISABLE it when create buff finished).
    - CREATE_BUFF: Create core code that you have to create if you want to use this system.
        + Create a struct contents all things of a specific buff.
        + Put in a seperate trigger or inside Buff Trigger.
    
                                REQUIREMENTS
                - JassNewGen Pack v5d or higher.
        Link: (blizzardmodding.info/4263/the-jass-newgen-pack-jngp-2-0/)
                - Vexorian - Jass Helper 0.A.2.B
        Link: (www.wc3c.net/showthread.php?t=88142)
                - Vexorian - Timer Utils 
        Link: (www.wc3c.net/showthread.php?t=101322)
                - Nestharus - Unit Indexer
        Link: (www.hiveworkshop.com/forums/spells-569/unit-indexer-v5-3-0-1-a-260859/)
                - Nestharus - Trigger
        Link: (www.hiveworkshop.com/forums/spells-569/trigger-v1-1-0-2-a-260933/)
                        
                                HOW TO USE:
STEP 1: Create buff object through textmacro CREATE_BUFF_OBJECT.
    //! textmacro CREATE_BUFF_OBJECT takes RAWCODE, NAME, ICON, DESCRIPTION
    + RAWCODE: I recommended you use 3 DIGITS.
    + EXAMPLE:
    //! runtextmacro CREATE_BUFF_OBJECT("rag","Rage", "ReplaceableTexturesCommandButtonsBTNAncestralSpirit.blp", "This unit is affected by Rage.")
    + Above line that you have created a buff called "Rage" with AbilityId = 'Arag', BuffId = 'Brag'.
STEP 2: Create specific buff struct.
    //! textmacro CREATE_BUFF takes RAWCODE, NAME
    + RAWCODE: I recommended you use 3 DIGITS (same as with RAWCODE of buff object)
    + EXAMPLE:
    //! runtextmacro CREATE_BUFF("rag","Rage")
    struct BuffRage extends array will be created.
    
    if you want to apply BuffRage to a specific unit (whichUnit) use this function:
        call BuffRage[whichUnit].apply()
                         apply a buff:     call Buff$NAME$[whichUnit].apply()
        
        To remove a buff from a specific unit use this function:
        call BuffRage[whichUnit].remove()
                         remove a buff:     call Buff$NAME$[whichUnit].remove()
                         
    To apply a buff to a unit for a duration, you can set buff duration:
        set BuffRage[whichUnit].duration = real Duration
    The buff will exist pernament if you didnt set duration or set duration <= 0

    Extra function:
        function RegisterApplyBuff$NAME$Event takes boolexpr whichBoolexpr returns TriggerCondition
        function RegisterRemoveBuff$NAME$Event takes boolexpr whichBoolexpr returns TriggerCondition
        
STEP 3: Feel free to use and modify.

The EXAMPLE is inside Buff trigger and Test Category.

===========================================N O T I C E====================================================

If you want to USE this system, you MUST have KNOWLEDGE about vJASS. At least, you must understand how to use.

===========================================C R E D I T====================================================
                                        Special thanks to:
                                            Veroxian
                                            Nestharus
                                        The Hiveworkshop

CORE CODE

JASS:
library Buff requires UnitIndexer, TimerUtils

//! textmacro CREATE_BUFF_OBJECT takes RAWCODE, NAME, ICON, DESCRIPTION
    //! external ObjectMerger w3a Aasl A$RAWCODE$ ansf "(Buff System)" anam "$NAME$" abuf 1 B$RAWCODE$ Slo1 1 0 aare 1 0 atar 1 self
    //! external ObjectMerger w3h Basl B$RAWCODE$ fnsf "(Buff System)" ftip "$NAME$" fube "$DESCRIPTION$" fart "$ICON$"
//! endtextmacro

//! textmacro CREATE_BUFF takes RAWCODE, NAME
    struct Buff$NAME$ extends array
        readonly static integer Ability = 'A$RAWCODE$'
        readonly static integer Id = 'B$RAWCODE$'
        readonly static Trigger ApplyTrigger
        readonly static Trigger RemoveTrigger
        readonly static unit TriggerUnit
        readonly timer Timer
        
        static method onRemove takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = GetTimerData(t)
            set TriggerUnit = null
            call this.remove()
            call ReleaseTimer(t)
        endmethod
        
        method operator duration= takes real t returns nothing
            if t > 0 then
                if this.Timer != null then
                    call PauseTimer(this.Timer)
                    call ReleaseTimer(this.Timer)
                endif
                set this.Timer = NewTimerEx(this)
                call TimerStart(this.Timer, t, false, function thistype.onRemove)
            else
                if this.Timer != null then
                    call PauseTimer(this.Timer)
                    call ReleaseTimer(this.Timer)
                endif
            endif
        endmethod
        
        method operator duration takes nothing returns real
            return TimerGetRemaining(this.Timer)
        endmethod
        
        method apply takes nothing returns nothing
            set TriggerUnit = null
            if GetUnitAbilityLevel(this.unit, Ability) == 0 then
                set TriggerUnit = this.unit
                call ApplyTrigger.fire()
                call UnitMakeAbilityPermanent(this.unit, true, Ability)
                call UnitAddAbility(this.unit, Ability)
            endif
        endmethod
        
        method remove takes nothing returns nothing
            set TriggerUnit = null
            if GetUnitAbilityLevel(this.unit, Ability) != 0 then
                set TriggerUnit = this.unit
                call RemoveTrigger.fire()
                call UnitRemoveAbility(this.unit, Ability)
                call UnitRemoveAbility(this.unit, Id)
            endif
        endmethod
        
        private static method onInit takes nothing returns nothing
            set ApplyTrigger = Trigger.create(false)
            set RemoveTrigger = Trigger.create(false)
        endmethod
        
        implement GlobalUnitIndex
    endstruct
    
function RegisterApplyBuff$NAME$Event takes boolexpr whichBoolexpr returns TriggerCondition
    return Buff$NAME$.ApplyTrigger.register(whichBoolexpr)
endfunction

function RegisterRemoveBuff$NAME$Event takes boolexpr whichBoolexpr returns TriggerCondition
    return Buff$NAME$.RemoveTrigger.register(whichBoolexpr)
endfunction
//! endtextmacro
                            /* Put your textmacro here */
// 2 lines below is test Create Buff.
//! runtextmacro CREATE_BUFF_OBJECT("rag","Rage", "ReplaceableTexturesCommandButtonsBTNAncestralSpirit.blp", "This unit is affected by Rage.")
//! runtextmacro CREATE_BUFF("rag", "Rage")
endlibrary

TEST BUFF EXAMPLE
JASS:
scope test initializer inittest
    globals
        unit uu 
    endglobals
    
    private function a takes nothing returns boolean
        local unit u = BuffRage.TriggerUnit
        call SetWidgetLife(u, 1)
        call BJDebugMsg(GetUnitName(u) + " is applied Rage Buff!!!")
        return false
    endfunction
    
    private function b takes nothing returns boolean
        local unit u = BuffRage.TriggerUnit
        call SetWidgetLife(u, 220)
        call BJDebugMsg(GetUnitName(u) + " is removed Rage Buff!!!")
        return false
    endfunction
    
    
    private function inittest takes nothing returns nothing
        set uu = CreateUnit(Player(0), 'hpea', 0, 0, 0)
        call RegisterApplyBuffRageEvent(Filter(function a))
        call RegisterRemoveBuffRageEvent(Filter(function b))
        call BuffRage[uu].apply()
        set BuffRage[uu].duration = 5
    endfunction
endscope

Buff%20Ingame%20Screenshot.jpg


Changelog:

-[02/07/2015] Initial first version.

MAKE SURE YOU ARE REGISTRY WARCRAFT 3 AND JNGP IN TRUE WAY


Keywords:
buff, system, unit, indexer, btdonald
Contents

Just another Warcraft III map (Map)

Reviews
12:36, 11th Jul 2015 IcemanBo: So we wait for an update for now.
Level 24
Joined
Aug 1, 2013
Messages
4,657
The problem of using an aura is simply that you cannot dispell the buff.
At least not by default.
Via triggers on the other hand it is... however this doesnt have any effect in your system.
It does not necessarily have to be added because it cost a lot of performance to do so, but you should mention it.
It might be a good idea to have a function that dispells. (one that loops through all buffs on each unit and checks if they pass a certain filter.)

Also, it would be cool if you can tell the game to make a positive aura instead.
I mean, Tornado Aura is a negative aura which results in a red buff aka debuff.
A positive aura like Devotion Aura leaves a green buff which should be used for positive effects.
The only problem is that I do not know of a positive aura that hides the icon just like tornado... maybe an item ability could do it though.
 
Level 11
Joined
Dec 3, 2011
Messages
366
The problem of using an aura is simply that you cannot dispell the buff.
At least not by default.
Via triggers on the other hand it is... however this doesnt have any effect in your system.
It does not necessarily have to be added because it cost a lot of performance to do so, but you should mention it.
It might be a good idea to have a function that dispells. (one that loops through all buffs on each unit and checks if they pass a certain filter.)

Also, it would be cool if you can tell the game to make a positive aura instead.
I mean, Tornado Aura is a negative aura which results in a red buff aka debuff.
A positive aura like Devotion Aura leaves a green buff which should be used for positive effects.
The only problem is that I do not know of a positive aura that hides the icon just like tornado... maybe an item ability could do it though.

Dispell buff ~ hmmm ..I think I will update it soon (something like Buff List).
Red buff can easily change color by color tag (I think)

The effect of buff, you must code. This system support you create buff, register apply/remove buff event.

If use positive aura we must create a spellbook. I think it's useless. :ogre_kawaii:
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Red buff means negative buff.
Negative buff is removed when you remove negative buffs through triggers.
Positive buff is also negative buff in your system.

Anyway, how I do it in my system is to add and remove the aura to the targeted unit on intervals.
That way, the normal action "Remove buffs from unit" also removes the custom buff and it will get detected.
Because the ability is never on the unit, it doesnt matter if it is visible because you never see it.

I think that adding and removing it every 4 seconds (until the remaining duration is less than 4 seconds) can work out well enough.
I am not quite sure if that is worth the making though because, yes you can change the buff's red or green name in the tooltip using color codes and you wont be using the buffs that much like normal buffs.
 
Level 11
Joined
Dec 3, 2011
Messages
366
Red buff means negative buff.
Negative buff is removed when you remove negative buffs through triggers.
Positive buff is also negative buff in your system.

Anyway, how I do it in my system is to add and remove the aura to the targeted unit on intervals.
That way, the normal action "Remove buffs from unit" also removes the custom buff and it will get detected.
Because the ability is never on the unit, it doesnt matter if it is visible because you never see it.

I think that adding and removing it every 4 seconds (until the remaining duration is less than 4 seconds) can work out well enough.
I am not quite sure if that is worth the making though because, yes you can change the buff's red or green name in the tooltip using color codes and you wont be using the buffs that much like normal buffs.

Buff basically is an aura spell (so It can't be removed by Remove buff from unit).

You don't know
JASS:
 UnitRemoveAbility(whichUnit, buffId)
will remove buff instantly.

You can see my remove() method, you can see that trick.

Don't care about Remove buffs from unit.

Edit:

I create this system through Buff Handler - Muzzel. Tornado Aura is used ^^!~
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
  • Unit - Remove Positive buffs considered Magic or physical from (Triggering unit) (Exclude expiration timers, Include auras)
I said that they wont be removed by default... that dispel abilities does not remove them.
Via triggers, it is possible though.

There is no way that you can just make a filter without making a trigger and add the filter to that right?
I think it is not even as bad as I think but still.

I actually have no idea how you would be able to loop through all buffs on a specific unit without looping through all buffs and check if the unit is that target.
At first, I thought about using a unit indexer and placing the buffs in an array but then you can only have one buff per unit...

EDIT:
I think about making my personal version cause I dont use structs very well... actually, I just dont use them at all.
One question though... do I see it right that you use 2 triggers per instance of a buff?

Also, those set TriggerUnit = null isnt really necessary on remove and apply...

EDIT2:
Also allow Invulnerable + Vulnerable in targets allowed...
If I understand correctly, you only allow self.
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,716
As you mention it yourself, what are the advantages of this over Buff Handler.
Basically why should a user chose this over Buff Handler?

When looking at BuffHandler, why didn't you inheritate really essential functionality like
BUFF_POLICITY or onPeriodic. How do I manage custom members for my struct if I need them?

Why not allocate every Buff instance over a parent struct?
 
Level 11
Joined
Dec 3, 2011
Messages
366
  • Unit - Remove Positive buffs considered Magic or physical from (Triggering unit) (Exclude expiration timers, Include auras)
I said that they wont be removed by default... that dispel abilities does not remove them.
Via triggers, it is possible though.

There is no way that you can just make a filter without making a trigger and add the filter to that right?
I think it is not even as bad as I think but still.

I actually have no idea how you would be able to loop through all buffs on a specific unit without looping through all buffs and check if the unit is that target.
At first, I thought about using a unit indexer and placing the buffs in an array but then you can only have one buff per unit...

EDIT:
I think about making my personal version cause I dont use structs very well... actually, I just dont use them at all.
One question though... do I see it right that you use 2 triggers per instance of a buff?

Also, those set TriggerUnit = null isnt really necessary on remove and apply...

EDIT2:
Also allow Invulnerable + Vulnerable in targets allowed...
If I understand correctly, you only allow self.

I use 2 triggers per struct not instance, TriggerUnit = null make my code more safety (I think).

Aura is allow target self.

As you mention it yourself, what are the advantages of this over Buff Handler.
Basically why should a user chose this over Buff Handler?

When looking at BuffHandler, why didn't you inheritate really essential functionality like
BUFF_POLICITY or onPeriodic. How do I manage custom members for my struct if I need them?

Why not allocate every Buff instance over a parent struct?

Hmmmm, I used to think like you. But I think some think useless. A parent struct with stub method is good on case you use it in a struct, what about outside :( Method onApply and onRemove can easily replace by
JASS:
RegisterApplyBuff$NAME$Event
JASS:
RegisterRemoveBuff$NAME$Event
Example:
JASS:
RegisterApplyBuffRageEvent(Filter(thistype.onApply))

I think that's a good solution.

Anyway, thank for your feedbacks :ogre_kawaii::ogre_kawaii:

P/s: Wietlol I will test with
  • Unit - Remove Positive buffs considered Magic or physical from (Triggering unit) (Exclude expiration timers, Include auras)
anh give you the result!

EDIT:

BUFF_POLICY will be added to this ^^!~

EDIT:

This is easy to create a new buff for anyone include function for both GUI/JASS.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Targets Allowed is always a bit of a pain imo.

Self means that you can target yourself.
Because everything like Friend, Ally and Enemy are false, it only targets himself.

However, Invulnerable is also invulnerable to targeted spells. Remember that you cant cast Storm Bolt on an invulnerable unit?
That is why you NEED Invulnerable to be true.

However, this means that you are ONLY allowed to target invulnerable units.
So you also have to set Vulnerable to true.
That way, it doesnt matter if your hero is vulnerable or not.


About removing...
If you remove the buff and want to check periodically, you are taking a lot of performance that is not necessary.
I dont care if you tell me that that function does not work for your buffs and I have to use your custom method that loops through all buffs on a certain unit.
But only if you tell me in the top of the system (in the documentation, probably in a bug list) that I have to do it.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Hmmmm, I used to think like you. But I think some think useless. A parent struct with stub method is good on case you use it in a struct, what about outside :( Method onApply and onRemove can easily replace by

And now no longer :D . Data structure is up to you. It was just an idea.
I think it's really important to compare two code snippets which share the same goal.
Because somehow a user has to decide which one he should import to his map.
I'm curious on the GUI attempt. For this please try to make it
compatible with the normal wc3 world editor. :)

Yes onApply/onRemove can be replaced by trigger evaluation thats true,
that's why i mentioned an on period function.

You should definitly think of a way users can do UnitHasBuff(unit, buff)
 
Level 11
Joined
Dec 3, 2011
Messages
366
And now no longer :D . Data structure is up to you. It was just an idea.
I think it's really important to compare two code snippets which share the same goal.
Because somehow a user has to decide which one he should import to his map.
I'm curious on the GUI attempt. For this please try to make it
compatible with the normal wc3 world editor. :)

Yes onApply/onRemove can be replaced by trigger evaluation thats true,
that's why i mentioned an on period function.

You should definitly think of a way users can do UnitHasBuff(unit, buff)

First, I think we must give the user more choices (use external object (easy way but not common) or create object by your self) .
Second, I'll make this work independently with TimerUtils or Unit Indexer (no more requirement).
Third, do u think hook can solve problem with UnitHasBuff hmmm

I'm thinking about combine this with buff handler :ogre_kawaii:
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
JASS:
Object Buff
    unit            buff_Target
    unit            buff_Source
    integer         buff_BuffType
    timer           buff_Timer
    real            buff_Duration
    
Object BuffType
    integer         bufftype_AbilityId
    integer         bufftype_BuffId
    real            bufftype_Interval
    trigger         bufftype_TriggerApply
    trigger         bufftype_TriggerInterval
    trigger         bufftype_TriggerRemove
    //User defined:
    boolean         bufftype_Classification_CrowdControl
    boolean         bufftype_Classification_Magical
    boolean         bufftype_Classification_Physical
    //etc
    //etc
    //etc



    function Buff_Expire takes nothing returns nothing
        call Buff_Destroy(GetTimerData(GetExpiredTimer()))
    endfunction
    function Buff_Interval takes nothing returns nothing
        local integer id = GetTimerData(GetExpiredTimer())
        
        call TriggerEvaluate(udg_Bufftype_TriggerInterval[udg_Buff_BuffType[id]])
        
        set udg_Buff_Duration[id] = udg_Buff_Duration[id] - udg_Bufftype_Interval[udg_Buff_BuffType[id]]
        if udg_Buff_Duration[id] > udg_Bufftype_Interval[udg_Buff_BuffType[id]] then
            call TimerStart(udg_Buff_Timer[id], udg_Buff_Duration[id], false, function Buff_Expire)
        endif
        
    endfunction
    function Buff_Apply takes unit source, unit target, integer buffType, real duration returns integer
        local integer id = Buff_Create()
        
        set buff_Source[id] = source
        set buff_Target[id] = target
        set buff_BuffType[id] = buffType
        set buff_Timer[id] = NewTimerEx(id)
        set buff_Duration[id] = duration
        
        if bufftype_Interval[buff_BuffType[id]] > 0. then
            call TimerStart(buff_Timer[id], bufftype_Interval[buff_BuffType[id]], true, function Buff_Interval)
        else
            call TimerStart(buff_Timer[id], duration, false, function Buff_Expire)
        endif
        
        call TriggerEvaluate(bufftype_TriggerApply[buff_BuffType[id]])
        
        return id
    endfunction

As you can see my buff uses almost the same data as yours but the only difference is that it also stores the duration.

Also, each bufftype has an interval which is 0 by default but you can change that.

When a buff starts, it checks if it has an interval (meaning interval is bigger than 0) and then it will run the Interval function instead of the Expire function.

EDIT:
Ow yes, the classifications (which I need for my maps for example) are just an example of how extra variables are created.

EDIT2:
Haha GUI version is available but I have to fix something from core code.
You then have to write it without Struct, without TimerUtils, without TextMacros, and everything else.
You then better create from scratch then :D
 
Last edited:
Level 11
Joined
Dec 3, 2011
Messages
366
JASS:
Object Buff
    unit            buff_Target
    unit            buff_Source
    integer         buff_BuffType
    timer           buff_Timer
    real            buff_Duration
    
Object BuffType
    integer         bufftype_AbilityId
    integer         bufftype_BuffId
    real            bufftype_Interval
    trigger         bufftype_TriggerApply
    trigger         bufftype_TriggerInterval
    trigger         bufftype_TriggerRemove
    //User defined:
    boolean         bufftype_Classification_CrowdControl
    boolean         bufftype_Classification_Magical
    boolean         bufftype_Classification_Physical
    //etc
    //etc
    //etc



    function Buff_Expire takes nothing returns nothing
        call Buff_Destroy(GetTimerData(GetExpiredTimer()))
    endfunction
    function Buff_Interval takes nothing returns nothing
        local integer id = GetTimerData(GetExpiredTimer())
        
        call TriggerEvaluate(udg_Bufftype_TriggerInterval[udg_Buff_BuffType[id]])
        
        set udg_Buff_Duration[id] = udg_Buff_Duration[id] - udg_Bufftype_Interval[udg_Buff_BuffType[id]]
        if udg_Buff_Duration[id] > udg_Bufftype_Interval[udg_Buff_BuffType[id]] then
            call TimerStart(udg_Buff_Timer[id], udg_Buff_Duration[id], false, function Buff_Expire)
        endif
        
    endfunction
    function Buff_Apply takes unit source, unit target, integer buffType, real duration returns integer
        local integer id = Buff_Create()
        
        set buff_Source[id] = source
        set buff_Target[id] = target
        set buff_BuffType[id] = buffType
        set buff_Timer[id] = NewTimerEx(id)
        set buff_Duration[id] = duration
        
        if bufftype_Interval[buff_BuffType[id]] > 0. then
            call TimerStart(buff_Timer[id], bufftype_Interval[buff_BuffType[id]], true, function Buff_Interval)
        else
            call TimerStart(buff_Timer[id], duration, false, function Buff_Expire)
        endif
        
        call TriggerEvaluate(bufftype_TriggerApply[buff_BuffType[id]])
        
        return id
    endfunction

As you can see my buff uses almost the same data as yours but the only difference is that it also stores the duration.

Also, each bufftype has an interval which is 0 by default but you can change that.

When a buff starts, it checks if it has an interval (meaning interval is bigger than 0) and then it will run the Interval function instead of the Expire function.

EDIT:
Ow yes, the classifications (which I need for my maps for example) are just an example of how extra variables are created.

EDIT2:

You then have to write it without Struct, without TimerUtils, without TextMacros, and everything else.
You then better create from scratch then :D

A new struct coming called BuffData ... will store buff information ^^!~
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
BuffHandler imho is superior to this, for the following reasons:

- Cleaner API (no use of Textmacros)
- Provides duration and periodic callbacks by default
- differentiates between preDestroy (fires when the buff is actually destroyed) and onRemove (fires when the buff is removed from the unit) ... which is critical for spell-steal or dispel abilities
- Buff icons are actually optional
- Provides two default stacking policies (infinitely stacking buffs and non-stacking buffs) and allows to define custom policies
- Provides a data structure for iterating through buffs and buff-lists (which are like groups just for buffs)
- Having onRemove and onApply as actual events requires extra input of the user, while not really providing any real advantage (Why would you need this on a per-instance basis instead of per-type? Buffs of the same type usually follow the same rules)


MAKE SURE YOU ARE REGISTRY WARCRAFT 3 AND JNGP IN TRUE WAY
Wat?
 
Level 11
Joined
Dec 3, 2011
Messages
366
BuffHandler imho is superior to this, for the following reasons:

- Cleaner API (no use of Textmacros)
- Provides duration and periodic callbacks by default
- differentiates between preDestroy (fires when the buff is actually destroyed) and onRemove (fires when the buff is removed from the unit) ... which is critical for spell-steal or dispel abilities
- Buff icons are actually optional
- Provides two default stacking policies (infinitely stacking buffs and non-stacking buffs) and allows to define custom policies
- Provides a data structure for iterating through buffs and buff-lists (which are like groups just for buffs)
- Having onRemove and onApply as actual events requires extra input of the user, while not really providing any real advantage (Why would you need this on a per-instance basis instead of per-type? Buffs of the same type usually follow the same rules)



Wat?

:ogre_haosis: I'm going to remake this system. Combine buff handler and this, more features.

Now, buff handler must use struct ... extends Buff to use. That isn't convenient.

Buff Handler or this should work through inside/outside struct, GUI/ JASS and more.

But anyway, thanks for your feedback :ogre_kawaii::ogre_kawaii:

P/s: a new version coming soon ^^!~
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
Now, buff handler must use struct ... extends Buff to use. That isn't convenient.
I don't know how struct extension should be any less convenient than this weird mixture of struct syntax and functions.
It's perfectly logical that a custom buff extends basic buffs, imho.

Buff Handler or this should work through inside/outside struct, GUI/ JASS and more.
Buff Handler was not written with the GUIers in mind, that's true.

But your system lacks core features, that's all I'm saying. If you intend to write a GUI friendly buff system, better remove the struct syntax completely.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
What happens when two buffs of the same kind are applied to a unit when

1. They are the same level
2. The current one is a lower level than the new one
3. The current one is a higher level than the new one

Will they stack? Will one override the other? Will they refresh? Will nothing happen?

Buffs, in the above regard, have pretty standard behavior across all games. The only difference in buffs is that some stack and some don't. They might also stack up to x number of times or when certain conditions are met. Heck, the amount they stack may change from one moment to another as well.


The reason I did not like Muzzel's buff handler is because he didn't handle the stuff I mentioned above. This system also doesn't handle those things.

If practically all but the absolutely simplest of buffs use the above, you should handle the above : P. I handled it in my AuraStruct resource. Auras are slightly more complicated than buffs too because the lower level auras persist underneath the higher level ones. When the high level ones goes away, the next highest pops up ; ). Auras are really just buffs that constantly refresh.
 
Level 11
Joined
Dec 3, 2011
Messages
366
What happens when two buffs of the same kind are applied to a unit when

1. They are the same level
2. The current one is a lower level than the new one
3. The current one is a higher level than the new one

Will they stack? Will one override the other? Will they refresh? Will nothing happen?

Buffs, in the above regard, have pretty standard behavior across all games. The only difference in buffs is that some stack and some don't. They might also stack up to x number of times or when certain conditions are met. Heck, the amount they stack may change from one moment to another as well.


The reason I did not like Muzzel's buff handler is because he didn't handle the stuff I mentioned above. This system also doesn't handle those things.

If practically all but the absolutely simplest of buffs use the above, you should handle the above : P. I handled it in my AuraStruct resource. Auras are slightly more complicated than buffs too because the lower level auras persist underneath the higher level ones. When the high level ones goes away, the next highest pops up ; ). Auras are really just buffs that constantly refresh.

I'm rewritting this but I cause some problem about Table. Have you ever cause this bug :ogre_datass:

http://www.hiveworkshop.com/forums/lab-715/bug-table-cause-bug-save-handle-267383/
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
What happens when two buffs of the same kind are applied to a unit when

1. They are the same level
2. The current one is a lower level than the new one
3. The current one is a higher level than the new one

Will they stack? Will one override the other? Will they refresh? Will nothing happen?

Buffs, in the above regard, have pretty standard behavior across all games. The only difference in buffs is that some stack and some don't. They might also stack up to x number of times or when certain conditions are met. Heck, the amount they stack may change from one moment to another as well.


The reason I did not like Muzzel's buff handler is because he didn't handle the stuff I mentioned above. This system also doesn't handle those things.

If practically all but the absolutely simplest of buffs use the above, you should handle the above : P. I handled it in my AuraStruct resource. Auras are slightly more complicated than buffs too because the lower level auras persist underneath the higher level ones. When the high level ones goes away, the next highest pops up ; ). Auras are really just buffs that constantly refresh.
This is basicly featuritis all over again.

As long as you have a way to define your own stacking policies (and BuffHandler has that), I don't see a reason why all that should be there by default.
Because in most cases you don't care for these things. 90% of the time you either want buffs to stack infinitely (which is the default) or make the last applied buff overwrite all other buffs of the same type (which is the other selectable default behaviour).

All other policies imho are extremely map-specific. Adding them as defaults is a waste of effort, especially for a system that was clearly made for the vJasser, not the lowlevel GUIer.


I know we have different views on that; you're someone who enjoys feature-complete systems with ultimate flexibility (and high complexity)
On the other end, I prefer simpler frameworks and add the required extra features manually. Because every feature I won't use is a waste of resources. And it's easier to have less, then expand upon that than to have more and slim it.
 
I think it can be also orientated to this buff system: http://www.hiveworkshop.com/forums/submissions-414/snippet-needs-power-time-buff-230697/

It provides several events for buff, and also dispell. (periodic, apply, remove, death, dispell, and more)
You can enum all buffs for a unit, enum all positive buffs, or enum all negative buffs.
Look at the wide API and functionalities, I think it's all one need, for example refreshing the buff completly.

Really not meant as offense, but I'm not really a fan of it if it doesn't provide something more (or even less)
than already existing systems and is (iny my view) written with less readable code and API. (for example macros)
 
Level 11
Joined
Dec 3, 2011
Messages
366
I think it can be also orientated to this buff system: http://www.hiveworkshop.com/forums/submissions-414/snippet-needs-power-time-buff-230697/

It provides several events for buff, and also dispell. (periodic, apply, remove, death, dispell, and more)
You can enum all buffs for a unit, enum all positive buffs, or enum all negative buffs.
Look at the wide API and functionalities, I think it's all one need, for example refreshing the buff completly.

Really not meant as offense, but I'm not really a fan of it if it doesn't provide something more (or even less)
than already existing systems and is (iny my view) written with less readable code and API. (for example macros)
:ogre_hurrhurr: I'm re-writting this. New features and new features and new features ... :ogre_love:
 
Top