System BuffStruct

Discussion in 'Systems and Snippets' started by Jesus4Lyf, Jan 28, 2010.

  1. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    BuffStruct​

    Version 1.0.4​

    Requirements:
    - Jass NewGen
    - AIDS
    - Damage
    - TimerUtils (optional)

    JASS:
    //
    //      ___ _   _ ___ ___ ___ _____ ___ _   _  ___ _____ 
    //     | _ ) | | | __| __/ __|_   _| _ \ | | |/ __|_   _|
    //     | _ \ |_| | _|| _|\__ \ | | |   / |_| | (__  | |
    //     |___/\___/|_| |_| |___/ |_| |_|_\\___/ \___| |_|
    //                                         By Jesus4Lyf
    //                                                                    v 1.0.4
    //      What is BuffStruct?
    //     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //          BuffStruct is a simple buff adding/removal/tracking system designed for
    //          rapid map development. It automatically generates all object data and
    //          backing code for adding and removing buffs to and from units.
    //          
    //      How to implement?
    //     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //          1. Create a new trigger named BuffStructHeader. Go to 'Edit -> Convert
    //          to Custom Text', and replace everything that's there with this script.
    //
    //          2. Create a new trigger immediately after BuffStructHeader, named
    //          BuffStructFooter. go to 'Edit -> Convert to Custom Text', and replace
    //          everything that's there with: //! endexternalblock
    //
    //          3. To make a BuffStruct, make a new trigger between BuffStructHeader
    //          and BuffStructFooter, and use the template below.
    //
    //      BuffStruct Template:
    //     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //          Example:
    /*
    //! runtextmacro BuffType("Return")
        //! runtextmacro SetBuffName("Return")
        //! runtextmacro SetBuffAlignment("NEUTRAL")
        //! runtextmacro SetBuffTooltip("This unit is being Returned; it will return to its previous location soon.")
        //! runtextmacro SetBuffIcon("ReplaceableTextures\\CommandButtons\\BTNDaggerOfEscape.blp")
    //! runtextmacro BuffStruct()
        real x
        real y
        method onCreate takes nothing returns nothing
            set this.x = GetUnitX(this.unit)
            set this.y = GetUnitY(this.unit)
        endmethod
        method preDestroy takes nothing returns nothing
            call SetUnitX(this.unit, this.x)
            call SetUnitY(this.unit, this.y)
        endmethod
    //! runtextmacro EndBuff()
    */
    //          Documentation:
    //
    //              //! runtextmacro BuffType("Identifier")
    //                  This must contain a 1 word identifier for the buff. This is
    //                  used to create new instances with Identifier.create(unit)
    //
    //              //! runtextmacro SetBuffName("Name")
    //                  This is the name that will display in the buff tray.
    //
    //              //! runtextmacro SetBuffAlignment("NEUTRAL")
    //                  This is whether the buff is POSITIVE, NEGATIVE or NEUTRAL.
    //
    //              //! runtextmacro SetBuffTooltip("Tooltip Missing!")
    //                  This is the tooltip that will display in the buff tray.
    //
    //              //! runtextmacro SetBuffIcon("ReplaceableTextures\\CommandButtons\\BTN???.blp")
    //                  This is the icon used for the buff in the buff tray.
    //
    //              //! runtextmacro BuffStruct()
    //                  This denotes the end of textmacro configuration for a buff,
    //                  and the start of the struct that will be instanciated for
    //                  each instance of a buff.
    //                  You may use the optional event response methods here, which
    //                  are listed below.
    //
    //              //! runtextmacro EndBuff()
    //                  This denotes the end of the BuffStruct.
    //
    //      Event Response Methods:
    //     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //          In each BuffStruct, you may optionally implement the following methods:
    //
    /*              method onApply takes nothing returns nothing
    */              // Fires just after the buff is applied to a unit.
    //
    /*              method onRemove takes nothing returns nothing
    */              // Fires just before the buff is removed from a unit.
    //
    /*              method onCreate takes nothing returns nothing
    */              // Fires immediately after the buff is created and applied to
    //              // the first unit. onApply will fire immediately after this.
    //
    /*              method preDestroy takes nothing returns nothing
    */              // Fires just before the buff instance is destroyed. onRemove
    //              // will fire just before this.
    //
    /*              method onDamageReceived takes nothing returns nothing
    */              // Fires when the buffed unit takes damage. Use GetEventDamageSource()
    //              // to refer to the damaging unit.
    //              // All functions from "Damage" are available here.
    //
    /*              method onDamageDealt takes nothing returns nothing
    */              // Fires when the buffed unit deals damage. Use GetTriggerUnit()
    //              // to refer to the unit taking the damage.
    //              // All functions from "Damage" are available here.
    //
    //      Other:
    //     ¯¯¯¯¯¯¯¯
    //          All BuffStructs' instances have the ".unit" field, which is the unit
    //          the buff is currently on.
    //
    //          All BuffStructs have the .setUnit(unit) method, which will remove
    //          the buff instance from the current unit, and apply it to the given unit.
    //          Use .setUnit(null) to unapply a buff without destroying it.
    //
    //          Use .isOn(unit) --> boolean to see if a buff is on a unit.
    //
    //          To do something for each buff on a unit, use:
    /*          call BuffList[unit].forEachBuff(BUFF_ALIGNMENT_??, myMethod)
    */          // ?? should be substituted for POSITIVE, NEGATIVE or NEUTRAL.
    //          // The function used for myMethod must take only a BuffStruct argument.
    //
    //          You may destroy a buff in x seconds using:
    /*          call myBuffInstance.destroyTimed(real)
    */          // "real" is the time to destruction.
    //
    //      Thanks:
    //     ¯¯¯¯¯¯¯¯¯
    //          - 13lade619: for isolating a lag issue in the BETA version to do with
    //            creating a buff instance for a null unit.
    //
    library BuffStruct requires AIDS, Damage, optional TimerUtils
    //! externalblock extension=lua ObjectMerger $FILENAME$
        //! runtextmacro BuffStruct__StartConfig()
    
    //===========================================================================
    // CONFIG AREA
    //
        
        //===========================================================================
        // System Object Editor IDs.
        //
        
        //! runtextmacro BuffStruct__BeginSysIds()
            // Uses:
            //  - 'Bxx&' for buff type.
            //  - 'Axx&' for base ability.
            
            //! runtextmacro BuffStruct__AllowSysId("@a")
            //! runtextmacro BuffStruct__AllowSysId("@b")
            //! runtextmacro BuffStruct__AllowSysId("@c")
            //! runtextmacro BuffStruct__AllowSysId("@d")
            //! runtextmacro BuffStruct__AllowSysId("@e")
            //! runtextmacro BuffStruct__AllowSysId("@f")
            //! runtextmacro BuffStruct__AllowSysId("@g")
            //! runtextmacro BuffStruct__AllowSysId("@h")
            //! runtextmacro BuffStruct__AllowSysId("@i")
            //! runtextmacro BuffStruct__AllowSysId("@j")
            //! runtextmacro BuffStruct__AllowSysId("@k")
            //! runtextmacro BuffStruct__AllowSysId("@l")
            //! runtextmacro BuffStruct__AllowSysId("@m")
            //! runtextmacro BuffStruct__AllowSysId("@n")
            //! runtextmacro BuffStruct__AllowSysId("@o")
            //! runtextmacro BuffStruct__AllowSysId("@p")
            //! runtextmacro BuffStruct__AllowSysId("@q")
            //! runtextmacro BuffStruct__AllowSysId("@r")
            //! runtextmacro BuffStruct__AllowSysId("@s")
            //! runtextmacro BuffStruct__AllowSysId("@t")
            //! runtextmacro BuffStruct__AllowSysId("@u")
            //! runtextmacro BuffStruct__AllowSysId("@v")
            //! runtextmacro BuffStruct__AllowSysId("@w")
            //! runtextmacro BuffStruct__AllowSysId("@x")
            //! runtextmacro BuffStruct__AllowSysId("@y")
            //! runtextmacro BuffStruct__AllowSysId("@z")
            //! runtextmacro BuffStruct__AllowSysId("@A")
            //! runtextmacro BuffStruct__AllowSysId("@B")
            //! runtextmacro BuffStruct__AllowSysId("@C")
            //! runtextmacro BuffStruct__AllowSysId("@D")
            //! runtextmacro BuffStruct__AllowSysId("@E")
            //! runtextmacro BuffStruct__AllowSysId("@F")
            //! runtextmacro BuffStruct__AllowSysId("@G")
            //! runtextmacro BuffStruct__AllowSysId("@H")
            //! runtextmacro BuffStruct__AllowSysId("@I")
            //! runtextmacro BuffStruct__AllowSysId("@J")
            //! runtextmacro BuffStruct__AllowSysId("@K")
            //! runtextmacro BuffStruct__AllowSysId("@L")
            //! runtextmacro BuffStruct__AllowSysId("@M")
            //! runtextmacro BuffStruct__AllowSysId("@N")
            //! runtextmacro BuffStruct__AllowSysId("@O")
            //! runtextmacro BuffStruct__AllowSysId("@P")
            //! runtextmacro BuffStruct__AllowSysId("@Q")
            //! runtextmacro BuffStruct__AllowSysId("@R")
            //! runtextmacro BuffStruct__AllowSysId("@S")
            //! runtextmacro BuffStruct__AllowSysId("@T")
            //! runtextmacro BuffStruct__AllowSysId("@U")
            //! runtextmacro BuffStruct__AllowSysId("@V")
            //! runtextmacro BuffStruct__AllowSysId("@W")
            //! runtextmacro BuffStruct__AllowSysId("@X")
            //! runtextmacro BuffStruct__AllowSysId("@Y")
            //! runtextmacro BuffStruct__AllowSysId("@Z")
            
        //! runtextmacro BuffStruct__EndSysIds()
        
    //===========================================================================
    // END CONFIG AREA
    //
        //! runtextmacro BuffStruct__EndConfig()
        
        
        //===========================================================================
        // SYSTEM AREA
        //
        
        globals
            constant integer BUFF_ALIGNMENT_POSITIVE=1
            constant integer BUFF_ALIGNMENT_NEGATIVE=2
            constant integer BUFF_ALIGNMENT_NEUTRAL=3
        endglobals
        
        private function interface Method takes integer this returns nothing
        
        //! textmacro BuffStruct__StartConfig
        //! endtextmacro
        //! textmacro BuffStruct__EndConfig
        //! endtextmacro
        
        
        //===========================================================================
        // Id Declaration
        //
        //  Exposes a module which implements the system ids, as per the system
        // configuration, automatically filling structs starting from struct ID #1.
        // 
        
        //! textmacro BuffStruct__BeginSysIds
            private keyword abilType
            private keyword buffType
            private keyword idMax
            
            private module SysIds
                /*libprivate*/ integer abilType
                /*libprivate*/ integer buffType
                /*libprivate*/ static integer idMax=0
                private static method onInit takes nothing returns nothing
                    //! i sysIds={}
                    //! i maxSysIds=0
        //! endtextmacro
        //! textmacro BuffStruct__EndSysIds
                endmethod
            endmodule
            //! i sysIdsUsed=0
        //! endtextmacro
        
        //! textmacro BuffStruct__AllowSysId takes SYSID
            set thistype.idMax=thistype.idMax+1
            //! i maxSysIds=maxSysIds+1
            
            set thistype(thistype.idMax).abilType='A$SYSID$&'
            set thistype(thistype.idMax).buffType='B$SYSID$&'
            //! i sysIds[maxSysIds]={abilType="A$SYSID$&", buffType="B$SYSID$&"}
        //! endtextmacro
        
        //===========================================================================
        // BuffType Struct
        //
        
        private struct BuffType
            implement SysIds // supplies abilType, buffType, preloaded.
        endstruct
        
        //===========================================================================
        // BuffStruct
        //
        private keyword buffUnit
        private keyword next
        private keyword prev
        private keyword temp
        
        private interface DEFAULTS
            static BuffStruct temp
            
            unit buffUnit
            BuffStruct next
            BuffStruct prev
            
            // User implementable
            method onCreate takes nothing returns nothing defaults nothing
            method onApply takes nothing returns nothing defaults nothing
            method onRemove takes nothing returns nothing defaults nothing
            method preDestroy takes nothing returns nothing defaults nothing
            method onDamageReceived takes nothing returns nothing defaults nothing
            method onDamageDealt takes nothing returns nothing defaults nothing
            
            // Module
            method setUnit takes unit whichUnit returns nothing defaults nothing
        endinterface
        
        struct BuffStruct extends DEFAULTS
            private static method timedDestroyCallback takes nothing returns nothing
                static if LIBRARY_TimerUtils then
                    local timer t=GetExpiredTimer()
                    call thistype(GetTimerData(t)).destroy()
                    call ReleaseTimer(t)
                endif
            endmethod
            method destroyTimed takes real time returns nothing
                static if LIBRARY_TimerUtils then
                    local timer t=NewTimer()
                    call SetTimerData(t,this)
                    call TimerStart(t,time,false,function thistype.timedDestroyCallback)
                else
                    call BJDebugMsg("BuffStruct Error: Must import TimerUtils in order to use .timedDestroy method.")
                endif
            endmethod
        endstruct
        
        module BuffStruct
            static integer ALIGNMENT=BUFF_ALIGNMENT_NEUTRAL
            //! textmacro BuffStruct__AttachToWhichUnit
                set BuffStruct.temp=BuffList[whichUnit][thistype.ALIGNMENT]
                set BuffStruct.temp.prev.next=this
                set this.prev=BuffStruct.temp.prev
                set BuffStruct.temp.prev=this
                set this.next=BuffStruct.temp
            //! endtextmacro
            
            private static BuffType typeStruct=0
            static method isOn takes unit whichUnit returns boolean
                return GetUnitAbilityLevel(whichUnit,thistype.typeStruct.abilType)>0
            endmethod
            private static method onInit takes nothing returns nothing
                set thistype.typeStruct=BuffType.create()
            endmethod
            
            method operator unit takes nothing returns unit
                return this.buffUnit
            endmethod
            
            method setUnit takes unit whichUnit returns nothing
                if this.buffUnit!=null then
                    call this.onRemove()
                    set this.next.prev=this.prev
                    set this.prev.next=this.next
                    call UnitMakeAbilityPermanent(this.buffUnit,false,thistype.typeStruct.abilType)
                    call UnitRemoveAbility(this.buffUnit,thistype.typeStruct.abilType)
                    call UnitRemoveAbility(this.buffUnit,thistype.typeStruct.buffType)
                endif
                set this.buffUnit=whichUnit
                if whichUnit!=null then
                    call UnitAddAbility(whichUnit,thistype.typeStruct.abilType)
                    call UnitMakeAbilityPermanent(whichUnit,true,thistype.typeStruct.abilType)
                    //! runtextmacro BuffStruct__AttachToWhichUnit()
                    call this.onApply()
                endif
            endmethod
            
            private method onDestroy takes nothing returns nothing
                if this.buffUnit!=null then
                    call this.onRemove()
                    call this.preDestroy()
                    set this.next.prev=this.prev
                    set this.prev.next=this.next
                    call UnitMakeAbilityPermanent(this.buffUnit,false,thistype.typeStruct.abilType)
                    call UnitRemoveAbility(this.buffUnit,thistype.typeStruct.abilType)
                    call UnitRemoveAbility(this.buffUnit,thistype.typeStruct.buffType)
                else
                    call this.preDestroy()
                endif
            endmethod
            
            static method create takes unit whichUnit returns thistype
                local thistype this=thistype.allocate()
                set this.buffUnit=whichUnit
                if whichUnit==null then
                    call this.onCreate()
                else
                    call UnitAddAbility(whichUnit,thistype.typeStruct.abilType)
                    call UnitMakeAbilityPermanent(whichUnit,true,thistype.typeStruct.abilType)
                    //! runtextmacro BuffStruct__AttachToWhichUnit()
                    call this.onCreate()
                    call this.onApply()
                endif
                return this
            endmethod
        endmodule
        
        //! textmacro BuffType takes IDENTIFIER
            struct $IDENTIFIER$ extends BuffStruct
                implement BuffStruct
                //! i itemIdentifier="$IDENTIFIER$"
                private static method onInit takes nothing returns nothing
                    //! i sysIdsUsed=sysIdsUsed+1
                    // Defaults.
                    //! i buffName="$IDENTIFIER$"
                    //! i buffIcon=""
                    //! i buffDescription=""
                    //! i buffAlignment="NEUTRAL"
        //! endtextmacro
        
        //! textmacro SetBuffName takes VAL
            //! i buffName="$VAL$"
        //! endtextmacro
        //! textmacro SetBuffIcon takes VAL
            //! i buffIcon="$VAL$"
        //! endtextmacro
        //! textmacro SetBuffTooltip takes VAL
            //! i buffDescription="$VAL$"
        //! endtextmacro
        //! textmacro SetBuffAlignment takes VAL
            set thistype.ALIGNMENT=BUFF_ALIGNMENT_$VAL$
            //! i buffAlignment="$VAL$"
        //! endtextmacro
        
        //! textmacro BuffStruct
                endmethod
        //! endtextmacro
        //! textmacro EndBuff
            endstruct
            // Make object data.
            // Actual buff
            //! i setobjecttype("buffs")
            //! i createobject("Basl",sysIds[sysIdsUsed].buffType)
            //! i makechange(current,"ftat","")
            //! i makechange(current,"fnsf","(BuffStruct)")
            //! i makechange(current,"fart",buffIcon)
            //! i makechange(current,"fube",buffDescription)
            //! i if buffAlignment=="POSITIVE" then
                //! i makechange(current,"ftip","|cff00FF00"..buffName.."|r")
            //! i elseif buffAlignment=="NEUTRAL" then
                //! i makechange(current,"ftip","|cff00FFFF"..buffName.."|r")
            //! i else
                //! i makechange(current,"ftip",buffName)
            //! i end
            
            // Slow aura
            //! i setobjecttype("abilities")
            //! i createobject("Aasl",sysIds[sysIdsUsed].abilType)
            //! i makechange(current,"ansf","(BuffStruct)")
            //! i makechange(current,"Slo1",1,0)
            //! i makechange(current,"aare",1,0)
            //! i makechange(current,"abuf",1,sysIds[sysIdsUsed].buffType)
            //! i makechange(current,"arac","other")
            //! i makechange(current,"atar",1,"self")
            //! i makechange(current,"anam",buffName)
        //! endtextmacro
        
        //===========================================================================
        // On Damage
        //
        
        private module DamageEvent
            private static method onDamage takes nothing returns boolean
                // Attacked
                local thistype u=thistype[GetTriggerUnit()]
                local BuffStruct base=u[BUFF_ALIGNMENT_POSITIVE]
                local BuffStruct this=base.next
                loop
                    exitwhen this==base
                    call this.onDamageReceived()
                    set this=this.next
                endloop
                set base=u[BUFF_ALIGNMENT_NEUTRAL]
                set this=base.next
                loop
                    exitwhen this==base
                    call this.onDamageReceived()
                    set this=this.next
                endloop
                set base=u[BUFF_ALIGNMENT_NEGATIVE]
                set this=base.next
                loop
                    exitwhen this==base
                    call this.onDamageReceived()
                    set this=this.next
                endloop
                // Attacker
                if GetEventDamageSource()!=null then
                    set u=thistype[GetEventDamageSource()]
                    set base=u[BUFF_ALIGNMENT_POSITIVE]
                    set this=base.next
                    loop
                        exitwhen this==base
                        call this.onDamageDealt()
                        set this=this.next
                    endloop
                    set base=u[BUFF_ALIGNMENT_NEUTRAL]
                    set this=base.next
                    loop
                        exitwhen this==base
                        call this.onDamageDealt()
                        set this=this.next
                    endloop
                    set base=u[BUFF_ALIGNMENT_NEGATIVE]
                    set this=base.next
                    loop
                        exitwhen this==base
                        call this.onDamageDealt()
                        set this=this.next
                    endloop
                endif
                return false
            endmethod
            private static method onInit takes nothing returns nothing
                local trigger t=CreateTrigger()
                call Damage_RegisterEvent(t)
                call TriggerAddCondition(t,Filter(function thistype.onDamage))
                set t=null
            endmethod
        endmodule
        
        //===========================================================================
        // Buff Listing
        //
        
        private struct LinkNode extends BuffStruct
        endstruct
        
        struct BuffList extends array
            private static LinkNode array linkNode
            method operator [] takes integer alignment returns LinkNode
                return thistype.linkNode[this*3+alignment]
            endmethod
            private method operator []= takes integer alignment, LinkNode node returns nothing
                set thistype.linkNode[this*3+alignment]=node
            endmethod
            
            private method AIDS_onCreate takes nothing returns nothing
                set BuffStruct.temp=LinkNode.create()
                set BuffStruct.temp.next=BuffStruct.temp
                set BuffStruct.temp.prev=BuffStruct.temp
                set this[BUFF_ALIGNMENT_POSITIVE]=BuffStruct.temp
                set BuffStruct.temp=LinkNode.create()
                set BuffStruct.temp.next=BuffStruct.temp
                set BuffStruct.temp.prev=BuffStruct.temp
                set this[BUFF_ALIGNMENT_NEGATIVE]=BuffStruct.temp
                set BuffStruct.temp=LinkNode.create()
                set BuffStruct.temp.next=BuffStruct.temp
                set BuffStruct.temp.prev=BuffStruct.temp
                set this[BUFF_ALIGNMENT_NEUTRAL]=BuffStruct.temp
            endmethod
            private method AIDS_onDestroy takes nothing returns nothing
                call this[BUFF_ALIGNMENT_POSITIVE].destroy()
                call this[BUFF_ALIGNMENT_NEGATIVE].destroy()
                call this[BUFF_ALIGNMENT_NEUTRAL].destroy()
            endmethod
            //! runtextmacro AIDS()
            
            implement DamageEvent
            
            method forEachBuff takes integer alignment, Method func returns nothing
                local LinkNode base=this[alignment]
                set this=thistype(base.next)
                loop
                    exitwhen this==base
                    call func.evaluate(this)
                    set this=thistype(LinkNode(this).next)
                endloop
            endmethod
        endstruct
    endlibrary
    This system allows rapid buff development, and will be extended with additional features in the future. In combination with Status, this system holds some pretty awesome power (such as moving all positive/negative/neutral buffs from one unit to another).

    In using this system, the user requires to make no object editor data for buff placement whatsoever.

    Here's an example:
    JASS:
    //! runtextmacro BuffType("Return")
        //! runtextmacro SetBuffName("Return")
        //! runtextmacro SetBuffAlignment("NEUTRAL")
        //! runtextmacro SetBuffTooltip("This unit is being Returned; it will return to its previous location soon.")
        //! runtextmacro SetBuffIcon("ReplaceableTextures\\CommandButtons\\BTNDaggerOfEscape.blp")
    //! runtextmacro BuffStruct()
        real x
        real y
        method onCreate takes nothing returns nothing
            set this.x=GetUnitX(this.unit)
            set this.y=GetUnitY(this.unit)
        endmethod
        method preDestroy takes nothing returns nothing
            call SetUnitX(this.unit,this.x)
            call SetUnitY(this.unit,this.y)
        endmethod
    //! runtextmacro EndBuff()
    This example gives a simple Return style buff. It is created with Return.create(unit). At any point you can use instance.setUnit(otherUnit) to make a different unit return to the location instead. When the buff is destroyed using .destroy, the current unit the buff is on will be returned to the location the original unit was at when it was buffed.

    Updates:
    - Version 1.0.4 (BETA): Fixed a bug to do with lag issues when a buff is created for a null unit (thanks 13lade619).
    - Version 1.0.3 (BETA): Fixed a bug where an AIDS struct was retrieved for null units when damage came from a null source.
    - Version 1.0.2 (BETA): Added static .isOn(unit) method.
    - Version 1.0.1 (BETA): Added .destroyTimed(time) method.
    - Version 1.0.0 (BETA): Release.
     

    Attached Files:

    • Like Like x 2
  2. Executor

    Executor I see you

    Ratings:
    +57 / 0 / -0
    Hehe, more and more functions I ever missed in wc3 come to life :p

    Didn't read the whole code, but the interface seems very good to me :)
     
  3. Narks

    Narks Vastly intelligent whale-like being from the stars

    Ratings:
    +92 / 0 / -0
    This is awesome. Now I can phase out those wc3c systems and replace them with SpellStruct and BuffStruct.
     
  4. Kenny

    Kenny Back for now.

    Ratings:
    +202 / 0 / -0
    Interesting..

    To tired to read through it all now, but one thing caught my attention.

    Can the preDestroy method be renamed to onDestroy?

    I know it is technically more correct the other way, but I find it more intuitive. Plus if it is named preDestroy, then shouldn't onApply be named postApply? :p

    Edit:

    Textmacro interfaces are fugly, but you did a really good job at making them usable and readable. Major props for that.

    It would look cool if there was some type of macro keyword that replaced //! runtextmacro, so that it looked a bit more structured, but that isn't your area.
     
  5. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Another demonstration, for cool factor:
    JASS:
    //! runtextmacro BuffType("Knockback")
        //! runtextmacro SetBuffName("Knocked")
        //! runtextmacro SetBuffAlignment("NEGATIVE")
        //! runtextmacro SetBuffTooltip("This unit is being Knocked Back; it is stunned and sliding backwards.")
        //! runtextmacro SetBuffIcon("ReplaceableTextures\\CommandButtons\\BTNBash.blp")
    //! runtextmacro BuffStruct()
        real speed=400*T32_PERIOD // can be changed dynamically for an instance.
        private effect e
        private method periodic takes nothing returns nothing
            local real r=GetUnitFacing(this.unit)*bj_DEGTORAD
            call SetUnitX(this.unit,GetUnitX(this.unit)-Cos(r)*this.speed)
            call SetUnitY(this.unit,GetUnitY(this.unit)-Sin(r)*this.speed)
        endmethod
        implement T32x
        method onApply takes nothing returns nothing
            call Status[this.unit].addStun()
            call this.startPeriodic()
            set this.e=AddSpecialEffectTarget("Abilities\\Spells\\Human\\Thunderclap\\ThunderclapTarget.mdl",this.unit,"overhead")
        endmethod
        method onRemove takes nothing returns nothing
            call Status[this.unit].removeStun()
            call this.stopPeriodic()
            call DestroyEffect(this.e)
        endmethod
    //! runtextmacro EndBuff()

    Epic knockback. At any point, calling instance.setUnit(unit) will change the unit being knocked back (and .setUnit(null) will dispel it, naturally). :D
    I wish. JassHelper wouldn't let me, but I shall keep seeing if there's a way... :(
    Thanks. I try. :)

    Edit: Hm! I could make a buff where if it is dispelled, it will find another unit near by and settle on it... XD

    Edit2: This requires the above buff.
    JASS:
    //! runtextmacro BuffType("LightHeaded")
        //! runtextmacro SetBuffName("Light Headed")
        //! runtextmacro SetBuffAlignment("NEGATIVE")
        //! runtextmacro SetBuffTooltip("This unit is feeling Light Headed; if it is attacked, it will be knocked back.")
        //! runtextmacro SetBuffIcon("ReplaceableTextures\\CommandButtons\\BTNDizzy.blp")
    //! runtextmacro BuffStruct()
        method onDamageReceived takes nothing returns nothing
            if Damage_IsAttack() then
                call Knockback.create(this.unit).destroyTimed(0.3)
            endif
        endmethod
    //! runtextmacro EndBuff()

    Readable? Cool? Released Version 1.0.1. :p
     
  6. quraji

    quraji zap

    Ratings:
    +143 / 0 / -0
    Pwnage
     
  7. Blackrage

    Blackrage Ultra Cool Member

    Ratings:
    +25 / 0 / -0
    ...when are UnitStruct, UpgradeStruct, and DestructibleStruct coming?
     
  8. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    AIDS.
    Wtf? XD
     
  9. Azlier

    Azlier Old World Ghost

    Ratings:
    +461 / 0 / -0
    I, for one, am waiting for RacePreferenceStruct.
     
    • Like Like x 1
  10. quraji

    quraji zap

    Ratings:
    +143 / 0 / -0
    Gold/LumberStruct?
     
  11. Narks

    Narks Vastly intelligent whale-like being from the stars

    Ratings:
    +92 / 0 / -0
    IntegerStruct
     
  12. BlackRose

    BlackRose Forum User

    Ratings:
    +239 / 0 / -0
    Struct.
     
  13. Viikuna

    Viikuna No Marlo no game.

    Ratings:
    +265 / 0 / -0
    Nice, a buff system.

    Time to request some features.



    -Possibility to make BuffClasses, such as Positive Buffs, Negative Buffs, Fire Buffs, Frost Buffs, Imba Buffs, etc.

    This is cool when you want for example to extend duration of all Fire Buffs or all Positive Buffs. ( With some ForEachBuff -function, or BuffList[ unit ].forEachBuff -method ) Buff that belongs both Fire and Positive class, naturally gets both of these.


    - Possibility to check if applied buff instance is the first or the last of the list.

    This way you can make some stacking buff that reduces armor by X each time its applied to unit, but the special effect is only created/destroyed when first buff in the list is created/destroyed.

    Also allows you to make semi and non stackable buffs. When list gets its second buff, you can destroy that first one, and maybe extend the duration of that new buff to make only duration stack.

    - Global events for those OnBuffCreate and OnBuffDestroy and others, so you can for example make some stuff for all buffs in Fire or Positive -class.

    For example, if unit gets buff that belongs to Hold class, and is currently being knockbacked, the knockback is stopped, and all buffs of Knockback -class get removed. Unit with active Hold class buffs can not receive Knockback class buffs. This way you can make some ensnare buff to prevent knockbacks.


    End of my list for now. It contains lot of Bluff Class stuff, which is because the interaction between triggered buffs is what makes them so cool, and thats why things like Buff Classes are cool too.

    I try to think some other kind of stuff too later. Anyways, stuff looks good, good luck with it.

    edit.

    And yea, make some example trigger, which removes all buffs from unit when it dies. Make sure that this triggers after other death events, so people can still use buff stuff in their death event triggers.
     
  14. Grundy

    Grundy Ultra Cool Member

    Ratings:
    +35 / 0 / -0
    If you want to loop through all buffs would you have to call BuffList[unit].forEachBuff(BUFF_ALIGNMENT_POSITIVE, myMethod), BuffList[unit].forEachBuff(BUFF_ALIGNMENT_NEGATIVE, myMethod), and BuffList[unit].forEachBuff(BUFF_ALIGNMENT_NEUTRAL, myMethod) or is there a way to loop through all buffs at once?

    Sorry if I'm just missing it (I looked for it and I'm not seeing it) but is there a way to see how many buffs a unit has? Or would I have to loop through all the buffs and increment a counter?
     
  15. Lyerae

    Lyerae I keep popping up on this site from time to time.

    Ratings:
    +105 / 0 / -0
    No, no, no!
    StructStruct.

    :p
     
  16. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    At the moment, both of what you suggested is correct, but I'm planning to add features to this system. In what sort of situation did you want to loop through all buffs?
     
  17. Renendaru

    Renendaru (Evol)ution is nothing without love.

    Ratings:
    +309 / 0 / -0
    Get all negative buffs, all positive buffs, buffs with a certain type, etc. My uses. I had a thought of using this and implementing a map with this alone for buffs, then use State to control how long someone is stunned, shorten the stun based on a value, purge a stun, etc. Would make it really fun, don't you think?
     
  18. Grundy

    Grundy Ultra Cool Member

    Ratings:
    +35 / 0 / -0
    Well there are some spells, like mirror image for example, that will remove all buffs from your hero, positive or negative. Same thing with cyclone. I might want to make a spell that removes all buffs; positive, neutral, and negative. Maybe there is (or will be) an easy way to remove all the buffs on a unit, if not then I guess I'd have to loop through all the buffs to remove them.

    Another one might a hero that has mad respect for all spell effects, and even more for stronger spell effects. So he regenerates X mana per second for each buff applied to him whether they are good or bad, with higher level buffs restoring a little more. Or he gets X bonus movement speed for each buff, or he regenerates a certain amount of hit points for each buff, or his attack damage is increased for each buff, lots of possibilities. Maybe he has 1 ability that randomly changes what bonus he gets from having a lot of buffs and his ultimate would make him get all of the different bonuses at the same time. In that case just getting the number of buffs wouldn't be enough you would actually have to loop through all the buffs to see what level they each are.

    -edit-
    Does BuffStruct even support levels for buffs? It doesn't look like it to me...am I missing something?
     
  19. Lehona

    Lehona New Member

    Ratings:
    +12 / 0 / -0
    Does GetEventDamage() work in onDamageDealt (And am I abled to block damage after receiving the amount?)?
     
  20. Jesus4Lyf

    Jesus4Lyf Good Idea™

    Ratings:
    +394 / 0 / -0
    Yep.
    Depends what you mean by levels. Can you give an example?
     

Share This Page