In need of fear system

krainert

Member
Reaction score
10
Greetings,

Is there a decent fear system out there?
What I need is a system that lets me set a unit to run off in a particular direction for a particular duration of time during which it will ignore (or postpone) orders.

Thanks.
 

Dirac

22710180
Reaction score
147
Well i feel like i'm would be able to write one to you now but, each "faction" of your map should have an neutral ally since the only way of making a player lose control of an unit is, well, making the player no longer own that unit. Adding locust is out of the question.
 

SanKakU

Member
Reaction score
21
what if you make the unit a peon and use a dummy unit to attack it, making it run away from the attacker? well...you'd still want to do something about received orders. i bet you can just force the unit to only respond to the order if it's a point order like move and in some sort of direction away from the point of fear...which could get kind of complicated to code, involving some math algorythms.
 

luorax

Invasion in Duskwood
Reaction score
67
Tornado Wander + [ljass]SetUnitPathing(u,true)[/ljass]. You can change the range in the object editor, dynamic values are useless (the max range is always the same).

EDIT: oh lol, I've just created my fear system for my map using this method, and the target died instantly after hitting a tree...

EDIT2: Okay, I came up with this:

JASS:
library FearSystem uses IsUnitMoving,Table

    globals
        private constant real PERIOD=.05
        
        private constant real MIN_RANGE=300.
        private constant real MAX_RANGE=500.
        private constant real ANGLE=45.
    endglobals

    //********************************************************************************
    //                                     CODE
    //********************************************************************************

    struct Fear
        private unit u
        private real dur
        
        private real x
        private real y
        private real nx
        private real ny
        
        private thistype next
        private thistype prev
        
        private static Table table
        private static boolean toPrevent
        
        private method destroy takes nothing returns nothing
            /*
            
                Buff based on Slow Aura
                        -- REMOVE --
            call UnitMakeAbilityPermanent(this.u,false,'A60B')
            call UnitRemoveAbility(this.u,'A60B')
            call UnitRemoveAbility(this.u,'B60B')
            */
            call IssueImmediateOrder(this.u,"stop")
            
            set this.prev.next=this.next
            set this.next.prev=this.prev
                
            call this.table.remove(GetHandleId(this.u))
            call this.deallocate()
        endmethod
        method issue takes nothing returns nothing
            local real r=GetRandomReal(MIN_RANGE,MAX_RANGE)
            local real angle=GetRandomReal(GetUnitFacing(this.u)-ANGLE,GetUnitFacing(this.u)+ANGLE)
            set this.nx=this.x + r * Cos(angle * bj_DEGTORAD)
            set this.ny=this.y + r * Sin(angle * bj_DEGTORAD)
            set thistype.toPrevent=false
            call IssuePointOrderById(this.u,851986,this.nx,this.ny)
            set thistype.toPrevent=true
        endmethod
        static method periodic takes nothing returns nothing
            local thistype this = thistype(0)
            
            loop
                set this=this.next
                exitwhen this==0
                if this.dur<=0 or not UnitAlive(this.u) then
                    call this.destroy()
                else
                    if not IsUnitMoving(this.u) then
                        call this.issue()
                    endif
                    set this.dur=this.dur-PERIOD
                endif
            endloop
        endmethod
        static method removeFear takes unit u returns nothing
            local integer id=GetHandleId(u)
            
            if thistype.table.has(id) then
                call thistype(thistype.table[id]).destroy()
            endif
        endmethod
        static method getFear takes unit u returns real
            local integer id=GetHandleId(u)
            
            if thistype.table.has(id) then
                return thistype(thistype.table[id]).dur
            else
                return 0.
            endif
        endmethod
        static method addFear takes unit u, real dur returns nothing
            local thistype this
            local integer id=GetHandleId(u)
            
            if thistype.table.has(id) then
                set this=thistype.table[id]
            else    
                set this=thistype.allocate()
                set thistype(0).next.prev=this
                set this.next=thistype(0).next
                set thistype(0).next=this
                set this.prev=thistype(0)
                set thistype.table[id]=this
                set this.u=u
                set this.dur=0
                set this.x=GetUnitX(u)
                set this.y=GetUnitY(u)
                /*
                
                Buff based on Slow Aura
                            -- ADD --
                call UnitAddAbility(u,'A60B')
                call UnitMakeAbilityPermanent(u,true,'A60B')
                */
            endif
        
            if this.dur<dur then
                set this.dur=dur
            endif
        endmethod
        private static method doPrevent takes nothing returns boolean
            local thistype this
            if thistype.table.has(GetHandleId(GetTriggerUnit())) and thistype.toPrevent then
                set this=thistype.table[GetHandleId(GetTriggerUnit())]
                set thistype.toPrevent=false
                call IssuePointOrderById(this.u,851986,this.nx,this.ny)
                set thistype.toPrevent=true
            endif
            return false
        endmethod
        
        private static trigger Prevent=CreateTrigger()
        private static method onInit takes nothing returns nothing
            set thistype.table=Table.create()
            set thistype.toPrevent=true
            call TimerStart(CreateTimer(),PERIOD,function true,function Fear.periodic()
            
            call TriggerRegisterAnyUnitEventBJ(thistype.Prevent, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
            call TriggerRegisterAnyUnitEventBJ(thistype.Prevent, EVENT_PLAYER_UNIT_ISSUED_ORDER )
            call TriggerRegisterAnyUnitEventBJ(thistype.Prevent, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
            call TriggerAddCondition(thistype.Prevent,Condition(function thistype.doPrevent))
        endmethod
    endstruct
endlibrary


Credit goes to Ayanami, because it's based on his Stun struct. (I was lazy to write my own struct with a linked list and table, because there's already one)
Uses Table and IsUnitMoving.
 

Dirac

22710180
Reaction score
147
I gotta say, that's one useful system. Here i corrected some syntax errors, and also, the boolean UnitAlive isn't working for me so i replaced it with GetWidgetLife(u)>0.405, changed the API, static methods are unfriendly
JASS:
library FearSystem uses IsUnitMoving,Table
//******************************************************
//API:
/*
function UnitFear takes unit whichUnit, real duration returns nothing

function UnitStopFear takes unit whichUnit returns nothing

function UnitFearElapsed takes unit whichUnit returns real
*/
//******************************************************
    globals
        private constant real PERIOD=.05
        
        private constant real MIN_RANGE=300.
        private constant real MAX_RANGE=500.
        private constant real ANGLE=45.
    endglobals

    //********************************************************************************
    //                                     CODE
    //********************************************************************************

    private struct Fear
        unit u
        real dur
        
        real x
        real y
        real nx
        real ny
        
        thistype next
        thistype prev
        
        static Table table
        static boolean toPrevent
        
        method destroy takes nothing returns nothing
            /*
            
                Buff based on Slow Aura
                        -- REMOVE --
            call UnitMakeAbilityPermanent(this.u,false,'A60B')
            call UnitRemoveAbility(this.u,'A60B')
            call UnitRemoveAbility(this.u,'B60B')
            */
            call IssueImmediateOrder(this.u,"stop")
            
            set this.prev.next=this.next
            set this.next.prev=this.prev
                
            call this.table.remove(GetHandleId(this.u))
            call this.deallocate()
        endmethod
        private method issue takes nothing returns nothing
            local real r=GetRandomReal(MIN_RANGE,MAX_RANGE)
            local real angle=GetRandomReal(GetUnitFacing(this.u)-ANGLE,GetUnitFacing(this.u)+ANGLE)
            set this.nx=this.x + r * Cos(angle * bj_DEGTORAD)
            set this.ny=this.y + r * Sin(angle * bj_DEGTORAD)
            set thistype.toPrevent=false
            call IssuePointOrderById(this.u,851986,this.nx,this.ny)
            set thistype.toPrevent=true
        endmethod
        static method periodic takes nothing returns nothing
            local thistype this = thistype(0)
            
            loop
                set this=this.next
                exitwhen this==0
                if this.dur<=0 or not (GetWidgetLife(this.u)>0.405) then
                    call this.destroy()
                else
                    if not IsUnitMoving(this.u) then
                        call this.issue()
                    endif
                    set this.dur=this.dur-PERIOD
                endif
            endloop
        endmethod
        private static method doPrevent takes nothing returns boolean
            local thistype this
            if thistype.table.has(GetHandleId(GetTriggerUnit())) and thistype.toPrevent then
                set this=thistype.table[GetHandleId(GetTriggerUnit())]
                set thistype.toPrevent=false
                call IssuePointOrderById(this.u,851986,this.nx,this.ny)
                set thistype.toPrevent=true
            endif
            return false
        endmethod
        
        private static trigger Prevent=CreateTrigger()
        private static method onInit takes nothing returns nothing
            set thistype.table=Table.create()
            set thistype.toPrevent=true
            call TimerStart(CreateTimer(),PERIOD,true,function Fear.periodic)
            
            call TriggerRegisterAnyUnitEventBJ(thistype.Prevent, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
            call TriggerRegisterAnyUnitEventBJ(thistype.Prevent, EVENT_PLAYER_UNIT_ISSUED_ORDER )
            call TriggerRegisterAnyUnitEventBJ(thistype.Prevent, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
            call TriggerAddCondition(thistype.Prevent,Condition(function thistype.doPrevent))
        endmethod
    endstruct
    function UnitFear takes unit u, real dur returns nothing
            local Fear this
            local integer id=GetHandleId(u)
            
            if Fear.table.has(id) then
                set this=Fear.table[id]
            else    
                set this=Fear.create()
                set Fear(0).next.prev=this
                set this.next=Fear(0).next
                set Fear(0).next=this
                set this.prev=Fear(0)
                set Fear.table[id]=this
                set this.u=u
                set this.dur=0
                set this.x=GetUnitX(u)
                set this.y=GetUnitY(u)
                /*
                
                Buff based on Slow Aura
                            -- ADD --
                call UnitAddAbility(u,'A60B')
                call UnitMakeAbilityPermanent(u,true,'A60B')
                */
            endif
        
            if this.dur<dur then
                set this.dur=dur
            endif
    endfunction
    function UnitStopFear takes unit u returns nothing
            local integer id=GetHandleId(u)
            
            if Fear.table.has(id) then
                call Fear(Fear.table[id]).destroy()
            endif
    endfunction
    function UnitFearElapsed takes unit u returns real
            local integer id=GetHandleId(u)
            
            if Fear.table.has(id) then
                return Fear(Fear.table[id]).dur
            else
                return 0.
            endif
    endfunction
endlibrary
 

luorax

Invasion in Duskwood
Reaction score
67
Well, I like the struct syntax, and AFAIK krainert isn't new to vJASS: However I should have adeed some function wrappers, that's true.
About UnitAlive: is it declared anywhere in your map? If not, declare it: [ljass]native UnitAlive takes unit u returns boolean[/ljass]

If it is and still causes errors, the problem should be somewhere in your installed JNGP plugins. I had the same problem with it, but turning off the "AdicOptimizer" module (cJASS menu) solved it.
 

Magthridon96

Member
Reaction score
2
GetWidgetLife(u)>0.405

Nope..
It's [ljass]GetWidgetLife(u)>=0.405[/ljass]

A unit is dead if [ljass]GetWidgetLife(u)<0.405[/ljass]
Thus, it's alive when [ljass]GetWidgetLife(u)>=0.405[/ljass]
 

luorax

Invasion in Duskwood
Reaction score
67
Well, even [ljass]IsUnitType(this.u,UNIT_TYPE_DEAD)[/ljass] is better, isn't it?
 

luorax

Invasion in Duskwood
Reaction score
67
I've heard that checking if a unit is dead using [ljass]GetWidgetLife[/ljass] can return incorrect values sometimes, but to be honest, dunno, I've never tested it. [ljass]UnitAlive[/ljass] works fine for me :p
 

tommerbob

Minecraft. :D
Reaction score
110
Yeah just declare the UnitAlive native in your map script, done. AFAIK its the best way.
 

tooltiperror

Super Moderator
Reaction score
231
Well, the best solution would be to make a library like this...

JASS:
library IsUnitAlive
    globals
        private constant boolean AI_NATIVE = true
    endglobals

    static if AI_NATIVE then
        native UnitAlive takes unit u returns boolean
    endif

    function IsUnitAlive takes unit u returns boolean
        static if AI_NATIVE then
            return UnitAlive(u)
        endif
        static if not AI_NATIVE then
            return GetWidgetLife(u) &gt; 0.405
        endif
    endfunction
endlibrary


Then people can use whatever method they want, libraries and snippets would all just use that library, and fixing the native would be simple as only fixing one function.

Would anyone approve of making a standard like this?
 

krainert

Member
Reaction score
10
Wow, thanks, guys - and please excuse me for forgetting about this thread. I'll look at this once I get home.
 

krainert

Member
Reaction score
10
Let me see if I understand your code correctly...
You prevent the unit from accepting orders while under the effect of fear by re-ordering it to move to wherever the system needs it to go whenever it is ordered to do anything else?
 

luorax

Invasion in Duskwood
Reaction score
67
Exactly.
I wanted to use Tornado Wander. It's easier, you only have to add/removei t when needed. However it turns the pathing off, so I had to turn it on again. But what happens, if the target's pathing was already turned off?
The direction was also constant, as I've noticed.
But the reason why I dropped this idea was a bug: if the unit had Tornado Wander, it instantly died when hit a tree.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top