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

Fear System v3

Hi everyone,
Here is my first submission there.
It is a fear system.
What is a fear ? It is a crowd control that makes the target to move randomly while being unable to attack or get orders from the owner of the unit.

Here is the code (and the doc at the beggining) with Vex's Table or Bribe's Table.
Vexorian version :
JASS:
library FearSystem /* v3
************************************************************************************
*
*   */uses /*
*   
*       */ Table /*       http://www.wc3c.net/showthread.php?t=101246
*        //By Vexorian
*
************************************************************************************
*
*   struct Fear extends array
*
*       Description
*       -------------------------
*
*           This is a fear system; use it to remove player
*           control from a unit temporarily. Units affected
*           will also be unable to attack.
*
*       Fields
*       -------------------------
*
*           unit targ -> The unit you want to apply the fear.
* 
*           string path -> The path of the sfx you want to add to the unit.
*
*           string attach -> The attachment string you want the sfx to be on the unit
*
*           readonly effect e -> The effect currently applied to the unit.
*           Initializes to null
*
*       Methods
*       -------------------------
*
*           static method create takes nothing returns thistype
*           method destroy takes nothing returns nothing
*
*           method start takes nothing returns nothing
*           When you have set every parameters you start your fear instance.
*
*           method changeEffect takes string path, string attach returns nothing
*           If you already have set the effect of your instance and it is running
*           and you want to change it use this.
*
*           static method isFeared takes unit u returns boolean
*           static method get takes unit u returns thistype
*           
*       Operators
*       -------------------------
*
*           method operator time= takes real t returns nothing
*           method operator time takes nothing returns real
*
*       Credits
*       -------------------------
*
*           - Vexorian for vJASS and Table
*           - Maker for the DisableUnit function
*           - Bribe for Table
*           - Chobibo for the addition in the DisableUnit function/
*
************************************************************************************/
    native UnitAlive takes unit u returns boolean
    
    globals
        //There will be check every FPS second.
        private constant real FPS = 0.31250000
        //Feared units will change direction every EACH_CHANGE FPS.
        private constant integer EACH_CHANGE = 3
        //Feared units will go maximum in a circle of 150 around them each time they change direction.
        private constant real AROUND = 150.
        //The rawcode of the attack disable. Be sure it is the same in the Object Editor.
        private constant integer DISABLE_ATTACK = 'W000'
        //The rawcode of the morph. Be sure it is the same in the Object Editor.
        private constant integer MORPH_ID = 'Z001'
        //The rawcode of the bear form. Be sure it is the same in the Object Editor.
        private constant integer BEAR_ID = 'Z000'
    endglobals
    
    //The Table for Vexorian version
    globals
        private HandleTable tab
    endglobals

    
    private function round takes real r returns integer
        return R2I(r+0.5)
    endfunction
    
    private function modulo takes integer a, integer b returns integer
        return a - (a/b)*b
    endfunction
    
    //Credits to Maker for this awesum func <3
    private function DisableControl takes unit u returns nothing
        local boolean b
        call UnitAddAbility(u, 'Aloc')
        call UnitRemoveAbility(u, 'Aloc')
        if IsUnitType(u, UNIT_TYPE_HERO) then
            call UnitAddAbility(u,MORPH_ID)
            call IssueImmediateOrder(u, "metamorphosis")
            call UnitRemoveAbility(u,MORPH_ID)
        else
            call UnitAddAbility(u, BEAR_ID)
            call IssueImmediateOrder(u, "bearform")
            call UnitRemoveAbility(u, BEAR_ID)    
        endif
        //Thanks to chobibo for this idea
        if GetLocalPlayer() != GetOwningPlayer(u) then
            set b = not IsUnitHidden(u)
            call ShowUnit(u,false)
            call ShowUnit(u,b)
        endif
        //I added this line to disable their attack too.
        call UnitAddAbility(u,DISABLE_ATTACK)
    endfunction
    
    private function EnableControl takes unit u returns nothing
        local boolean backup = not IsUnitHidden(u)
        call ShowUnit(u,false)
        //I added this line to enable their attack.
        call UnitRemoveAbility(u,DISABLE_ATTACK)
        call ShowUnit(u,backup)
    endfunction
    
    struct Fear extends array
        unit targ
        string path
        string attach
        readonly effect e
        readonly boolean b
        private integer steps
        private integer startat
        private static timer period
        private static integer dindex
        private static thistype array data
        private static integer instanceCount
        private static thistype recycle
        private thistype recycleNext
        
        private static method periodic takes nothing returns nothing 
            local thistype this
            local real x
            local real y
            local integer i = 0
            loop
                exitwhen i > dindex
                set this = data[i]
                if modulo(this.steps,EACH_CHANGE) == this.startat then
                    set x = GetUnitX(this.targ)
                    set y = GetUnitY(this.targ)
                    call IssuePointOrder(this.targ, "move", GetRandomReal(x-AROUND,x+AROUND), GetRandomReal(y-AROUND, x+AROUND) )
                endif
                set this.steps = this.steps - 1
                if this.steps == 0 or not(UnitAlive(this.targ)) then
                    set data[i] = data[dindex]
                    set i = i - 1
                    set dindex = dindex - 1
                    if this.e != null then
                        call DestroyEffect(this.e)
                        set this.e = null
                    endif
                    call IssueImmediateOrder(this.targ,"stop")
                    call EnableControl(this.targ)
                    call tab.flush(this.targ)
                    if this.b then
                        set this.targ = null
                        set recycleNext = recycle
                        set recycle = this
                    endif
                endif
                if dindex == -1 then
                    call PauseTimer(period)
                endif
                set i = i + 1
            endloop
        endmethod
        
        static method isFeared takes unit u returns boolean
            return tab.exists(u)
        endmethod
        
        method operator time= takes real t returns nothing
            set this.steps = round(t/FPS)
        endmethod
        
        method operator time takes nothing returns real
            return this.steps*FPS
        endmethod
        
        method changeEffect takes string path, string attach returns nothing
            call DestroyEffect(this.e)
            set this.e = null
            set this.e = AddSpecialEffectTarget(path,this.targ,attach)
        endmethod
        
        static method get takes unit u returns thistype
            if isFeared(u) then
                return tab[u]
            else
                debug call BJDebugMsg("Tryng to get wrong instance")
                return 0
            endif
        endmethod
        
        method start takes nothing returns nothing
            debug if this.targ==null or this.steps==0 then
                debug call BJDebugMsg("You're instanciating badly ....")
                debug return
            debug endif
            set dindex = dindex + 1
            set data[dindex] = this
            set this.startat = modulo(this.steps,EACH_CHANGE)
            call DisableControl(this.targ)
            if this.path != "" and this.attach != ""  then
                set this.e = AddSpecialEffectTarget(this.path, this.targ, this.attach)
            endif
            set tab[this.targ] = this
            if dindex == 0 then
                call TimerStart(period, FPS, true, function thistype.periodic)
            endif
        endmethod
        
        static method create takes nothing returns thistype
            local thistype this
            if recycle == 0 then
                set instanceCount = instanceCount + 1
                set this = instanceCount
            else
                set this = recycle
                set recycle = recycle.recycleNext
            endif
            set this.path = ""
            set this.attach = ""
            set this.e = null
            set this.b = false
            return this
        endmethod
        
        method destroy takes nothing returns nothing
            set this.b = true
        endmethod
        
        private static method onInit takes nothing returns nothing
            set tab = HandleTable.create()
            set dindex = - 1
            set instanceCount = 0
            set recycle = 0
            set period = CreateTimer()
        endmethod
    endstruct
endlibrary

The Bribe version :
JASS:
library FearSystem /* v3
************************************************************************************
*
*   */uses /*
*   
*       */ Table /*        http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*        //By Bribe
*
************************************************************************************
*
*   struct Fear extends array
*
*       Description
*       -------------------------
*
*           This is a fear system; use it to remove player
*           control from a unit temporarily. Units affected
*           will also be unable to attack.
*
*       Fields
*       -------------------------
*
*           unit targ -> The unit you want to apply the fear.
* 
*           string path -> The path of the sfx you want to add to the unit.
*
*           string attach -> The attachment string you want the sfx to be on the unit
*
*           readonly effect e -> The effect currently applied to the unit.
*           Initializes to null
*
*       Methods
*       -------------------------
*
*           static method create takes nothing returns thistype
*           method destroy takes nothing returns nothing
*
*           method start takes nothing returns nothing
*           When you have set every parameters you start your fear instance.
*
*           method changeEffect takes string path, string attach returns nothing
*           If you already have set the effect of your instance and it is running
*           and you want to change it use this.
*
*           static method isFeared takes unit u returns boolean
*           static method get takes unit u returns thistype
*           
*       Operators
*       -------------------------
*
*           method operator time= takes real t returns nothing
*           method operator time takes nothing returns real
*
*       Credits
*       -------------------------
*
*           - Vexorian for vJASS and Table
*           - Maker for the DisableUnit function
*           - Bribe for Table
*           - Chobibo for the addition in the DisableUnit function/
*
************************************************************************************/
    native UnitAlive takes unit u returns boolean
    
    globals
        //There will be check every FPS second.
        private constant real FPS = 0.31250000
        //Feared units will change direction every EACH_CHANGE FPS.
        private constant integer EACH_CHANGE = 3
        //Feared units will go maximum in a circle of 150 around them each time they change direction.
        private constant real AROUND = 150.
        //The rawcode of the attack disable. Be sure it is the same in the Object Editor.
        private constant integer DISABLE_ATTACK = 'W000'
        //The rawcode of the morph. Be sure it is the same in the Object Editor.
        private constant integer MORPH_ID = 'Z001'
        //The rawcode of the bear form. Be sure it is the same in the Object Editor.
        private constant integer BEAR_ID = 'Z000'
    endglobals
    
    globals
        private Table tb
    endglobals
    
    private function round takes real r returns integer
        return R2I(r+0.5)
    endfunction
    
    private function modulo takes integer a, integer b returns integer
        return a - (a/b)*b
    endfunction
    
    //Credits to Maker for this awesum func <3
    private function DisableControl takes unit u returns nothing
        local boolean b
        call UnitAddAbility(u, 'Aloc')
        call UnitRemoveAbility(u, 'Aloc')
        if IsUnitType(u, UNIT_TYPE_HERO) then
            call UnitAddAbility(u,MORPH_ID)
            call IssueImmediateOrder(u, "metamorphosis")
            call UnitRemoveAbility(u,MORPH_ID)
        else
            call UnitAddAbility(u, BEAR_ID)
            call IssueImmediateOrder(u, "bearform")
            call UnitRemoveAbility(u, BEAR_ID)    
        endif
        //Thanks to chobibo for this idea
        if GetLocalPlayer() != GetOwningPlayer(u) then
            set b = not IsUnitHidden(u)
            call ShowUnit(u,false)
            call ShowUnit(u,b)
        endif
        //I added this line to disable their attack too.
        call UnitAddAbility(u,DISABLE_ATTACK)
    endfunction
    
    private function EnableControl takes unit u returns nothing
        local boolean backup = not IsUnitHidden(u)
        call ShowUnit(u,false)
        //I added this line to enable their attack.
        call UnitRemoveAbility(u,DISABLE_ATTACK)
        call ShowUnit(u,backup)
    endfunction
    
    struct Fear extends array
        unit targ
        string path
        string attach
        readonly effect e
        readonly boolean b
        private integer steps
        private integer startat
        private static timer period
        private static integer dindex
        private static thistype array data
        private static integer instanceCount
        private static thistype recycle
        private thistype recycleNext
        
        private static method periodic takes nothing returns nothing 
            local thistype this
            local real x
            local real y
            local integer i = 0
            loop
                exitwhen i > dindex
                set this = data[i]
                if modulo(this.steps,EACH_CHANGE) == this.startat then
                    set x = GetUnitX(this.targ)
                    set y = GetUnitY(this.targ)
                    call IssuePointOrder(this.targ, "move", GetRandomReal(x-AROUND,x+AROUND), GetRandomReal(y-AROUND, x+AROUND) )
                endif
                set this.steps = this.steps - 1
                if this.steps == 0 or not(UnitAlive(this.targ)) then
                    set data[i] = data[dindex]
                    set i = i - 1
                    set dindex = dindex - 1
                    if this.e != null then
                        call DestroyEffect(this.e)
                        set this.e = null
                    endif
                    call IssueImmediateOrder(this.targ,"stop")
                    call EnableControl(this.targ)
                    call tb.remove(GetHandleId(this.targ))
                    if this.b then
                        set this.targ = null
                        set recycleNext = recycle
                        set recycle = this
                    endif
                endif
                if dindex == -1 then
                    call PauseTimer(period)
                endif
                set i = i + 1
            endloop
        endmethod
        
        static method isFeared takes unit u returns boolean
            return tb.has(GetHandleId(u))
        endmethod
        
        method operator time= takes real t returns nothing
            set this.steps = round(t/FPS)
        endmethod
        
        method operator time takes nothing returns real
            return this.steps*FPS
        endmethod
        
        method changeEffect takes string path, string attach returns nothing
            call DestroyEffect(this.e)
            set this.e = null
            set this.e = AddSpecialEffectTarget(path,this.targ,attach)
        endmethod
        
        static method get takes unit u returns thistype
            local thistype this
            if isFeared(u) then
                return tb[GetHandleId(u)]
            else
                debug call BJDebugMsg("Tryng to get wrong instance")
                return 0
            endif
        endmethod
        
        method start takes nothing returns nothing
            debug if this.targ==null or this.steps==0 then
                debug call BJDebugMsg("You're instanciating badly ....")
                debug return
            debug endif
            set dindex = dindex + 1
            set data[dindex] = this
            set this.startat = modulo(this.steps,EACH_CHANGE)
            call DisableControl(this.targ)
            if this.path != "" and this.attach != ""  then
                set this.e = AddSpecialEffectTarget(this.path, this.targ, this.attach)
            endif
            set tb[GetHandleId(this.targ)] = this
            if dindex == 0 then
                call TimerStart(period, FPS, true, function thistype.periodic)
            endif
        endmethod
        
        static method create takes nothing returns thistype
            local thistype this
            if recycle == 0 then
                set instanceCount = instanceCount + 1
                set this = instanceCount
            else
                set this = recycle
                set recycle = recycle.recycleNext
            endif
            set this.path = ""
            set this.attach = ""
            set this.e = null
            set this.b = false
            return this
        endmethod
        
        method destroy takes nothing returns nothing
            set this.b = true
        endmethod
        
        private static method onInit takes nothing returns nothing
            set tb = Table.create()
            set dindex = - 1
            set instanceCount = 0
            set recycle = 0
            set period = CreateTimer()
        endmethod
    endstruct
endlibrary

Credits :
- Vexorian for Table Library and vJASS.
- Maker for the help in the disable function.
- Bribe for Table Library (Yes there is two :D ).
- Chobibo for addition in the disable function.

v1.0:
- Initial Release

v1.1 :
- Trigger Optimization.
- Added a version with Table by Bribe.

v1.2 :
- Added 'Avul' during the unfeared phase.

v1.3 :
- Only one trigger for both Table Libraries.

v2.0 :
- Added a GUI/JASS version.

v2.1 :
- Fix a bug with hashtable.

v2.2 :
- Fix some issues.
- Fix this box ^^.

v2.3 :
- Change the code
- Delete the JASS version for the moment.

v2.4 :
- Fix bugs.

v2.5 :
- Thanks to chobibo you can target feared units if you're not the owner of those.

v2.6 :
- Fix a bug with the indexing.
- Fix a bug with a static integer which should have been thistype instead;
- Optimize some triggers with the backup boolean.
- Optimize round functions.
- Now properly works.

v2.7 :
- Bug corrected.

v3 :
- Separated Bribe and Vexorian codes for the sake of statif if bugs.


Give credits to me and the four above if you use it :)
Malhorne

Keywords:
Fear System, Fear, System, vJASS, JESP, Malhorne, Status Effect, Status, Status Alteration, Corwd, Control, Crowd Control
Contents

Just another Warcraft III map (Map)

Reviews
Fear System v2.7 | Reviewed by Maker | 25th November 2013 Concept[/COLOR]] It is a unique system that has not been done before. Status effect systems are a welcome addition to out spell database Triggers[/COLOR]] Leakless and MUI...
Top