• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Rheiko's Fear System [RFS] v1.0.2

RFS (Rheiko Fear System) is an extremely lightweight system that provides a simple, flexible way to apply a fear mechanic to any target you choose. Best of all, it's compatible with Warcraft 3 version 1.26—rejoice, 1.26 users!

Although it’s written in pure vanilla JASS (just the way I love it), it also fully supports GUI. Yes, even you GUI folks can now strike fear into the hearts of your enemies—or be feared yourselves!

What's good?​

  • Super Lightweight
    Tested in unit-heavy environments with many simultaneous instances and showed very little to no performance impact.
  • Full Control
    You can apply, remove, and check the fear effect on any unit at any time.
  • Stackable Duration
    The fear duration can be stacked if desired.
  • Configurable System
    Change the timeout, maximum move distance, effect model, and attachment point with ease.
  • Easy to Import
    Just copy the RFS folder then paste it into your map and start using it—minimal setup required!

What's the catch?​

  • Hashtable Usage
    Not really a downside, but take note: the system uses its own hashtable, and Warcraft maps can only hold up to 255 hashtables. Use them wisely.
  • No Buff Icon by Default
    The system doesn’t display a buff icon on affected units. However, this can be easily implemented yourself: Just create a dummy caster and apply a spell that leaves a buff on the feared unit.
    • You can either match the buff’s duration with the system's fear duration
    • Or use a max-duration buff and remove it manually using the RFS_OnFinishEvent Equals to 1.00 event.

How to Import?​

  • Make sure your world editor has this option enabled:
    • Go to File -> Preferences -> Automatically create unknown variables while pasting trigger data
  • Copy the "RFS" folder and paste it into your map
  • You are done! Congratulations!
  • You can check the configurable options in RFS trigger, please read the documentation!

How to use this?​

I have prepared some examples so you can easily implement this into your map! Please check them out and feel free to ask if there is anything you are confused about!

Apply Example

Check Example

Remove Example

Finish Event

Custom Howl of Terror

Dispel Magic

Inflict Fear on Attack


  • Apply Example
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • -------- - --------
      • -------- Example --------
      • -------- - --------
      • -------- This is how you inflict fear on a unit --------
      • -------- Make sure to use Run RFS_ApplyFear (checking conditions) --------
      • -------- Run RFS_ApplyFear (ignoring conditions) will not work here --------
      • -------- - --------
      • -------- AttachPoint & SfxModel are completely optional --------
      • -------- - --------
      • Set RFS_Param_Unit = Paladin 0001 <gen>
      • Set RFS_Param_Duration = 4.00
      • Set RFS_Param_Stackable = False
      • Set RFS_Param_AttachPoint = overhead
      • Set RFS_Param_SfxModel = Abilities\Spells\NightElf\shadowstrike\shadowstrike.mdl
      • Trigger - Run RFS_ApplyFear (checking conditions)

  • Check Example
    • Events
      • Player - Player 1 (Red) Selects a unit
    • Conditions
    • Actions
      • -------- - --------
      • -------- Example --------
      • -------- - --------
      • -------- - --------
      • -------- This is how you check if a unit is currently in fear --------
      • -------- - --------
      • Set RFS_Param_Unit = (Triggering unit)
      • Trigger - Run RFS_CheckFear (checking conditions)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RFS_IsUnitInFear Equal to True
        • Then - Actions
          • Game - Display to (All players) for 10.00 seconds the text: ((Name of RFS_Param_Unit) + is terrified!)
        • Else - Actions
          • Game - Display to (All players) for 10.00 seconds the text: ((Name of RFS_Param_Unit) + is not afraid!)

  • Remove Example
    • Events
      • Player - Player 1 (Red) types a chat message containing -r as An exact match
    • Conditions
    • Actions
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units currently selected by (Triggering player)) and do (Actions)
        • Loop - Actions
          • -------- - --------
          • -------- We check if the unit is in fear first --------
          • -------- - --------
          • Set RFS_Param_Unit = (Picked unit)
          • Trigger - Run RFS_CheckFear (checking conditions)
          • -------- - --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • RFS_IsUnitInFear Equal to True
            • Then - Actions
              • -------- - --------
              • -------- If they are in fear then --------
              • -------- We remove the effect --------
              • -------- - --------
              • Set RFS_Param_Unit = (Picked unit)
              • Trigger - Run RFS_RemoveFear (checking conditions)
              • -------- - --------
            • Else - Actions

  • Finish Event
    • Events
      • Game - RFS_OnFinishEvent becomes Equal to 1.00
    • Conditions
    • Actions
      • -------- - --------
      • -------- This event triggers when the fear effect is over --------
      • -------- You can do whatever you want here --------
      • -------- For example, you can remove buff, cause damage, etc --------
      • -------- Variable in response to this event is "RFS_LastFinishedUnit" --------
      • -------- - --------
      • Set TempPoint = (Position of RFS_LastFinishedUnit)
      • Special Effect - Create a special effect at TempPoint using Abilities\Spells\Demon\DarkPortal\DarkPortalTarget.mdl
      • Special Effect - Destroy (Last created special effect)
      • Custom script: call RemoveLocation(udg_TempPoint)

  • Howl of Terror
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Howl of Terror (Custom)
    • Actions
      • Set TempPoint = (Position of (Triggering unit))
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 832.00 of TempPoint) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) belongs to an enemy of (Triggering player)) Equal to True
              • ((Picked unit) is A structure) Equal to False
              • ((Picked unit) is Mechanical) Equal to False
              • ((Picked unit) is dead) Equal to False
            • Then - Actions
              • Set RFS_Param_Unit = (Picked unit)
              • Set RFS_Param_Duration = 10.00
              • Set RFS_Param_Stackable = False
              • Trigger - Run RFS_ApplyFear (checking conditions)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint)

  • Dispel Magic
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Dispel Magic
    • Actions
      • Set TempPoint = (Target point of ability being cast)
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 224.00 of TempPoint) and do (Actions)
        • Loop - Actions
          • Set RFS_Param_Unit = (Picked unit)
          • Trigger - Run RFS_CheckFear (checking conditions)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • RFS_IsUnitInFear Equal to True
              • ((Picked unit) is dead) Equal to False
            • Then - Actions
              • Set RFS_Param_Unit = (Picked unit)
              • Trigger - Run RFS_RemoveFear (checking conditions)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint)

  • Passive Fear
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • (Unit-type of (Attacking unit)) Equal to Archmage
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Random integer number between 1 and 100) Less than or equal to 50
        • Then - Actions
          • Set RFS_Param_Unit = (Attacked unit)
          • Set RFS_Param_Duration = 5.00
          • Set RFS_Param_Stackable = False
          • Set RFS_Param_AttachPoint = origin
          • Set RFS_Param_SfxModel = Abilities\Spells\Undead\Cripple\CrippleTarget.mdl
          • Trigger - Run RFS_ApplyFear (checking conditions)
        • Else - Actions

Code​

JASS:
//===========================================================================
//=
//=     Rheiko Fear System / RFS
//=     version 1.0.2
//=
//=     Description:
//=     A very lightweight system that allows you to inflict and remove fear effect on a unit
//=
//=     GUI user, please scroll down and check configuration right away!
//=
//=     These are APIs for JASS users:
//=    
//=     function Trig_RFS_ApplyFear takes unit whichUnit, real duration, boolean stackable, string sfxModel, string attachPoint returns nothing
//=         - Inflict fear on a unit
//=
//=     function Trig_RFS_RemoveFear takes unit u returns nothing
//=         - Remove fear from a unit
//=
//=     function Trig_RFS_IsUnitInFear takes unit u returns boolean
//=         - Check if a unit is in fear
//=
//===========================================================================
function Trig_RFS_Configurations takes nothing returns nothing
    //===========================================================================
    //                              CONFIGURATION
    //===========================================================================
        //-----------------------------------------------------------------------
        //-- This will show debug messages if you set it to true
        //-----------------------------------------------------------------------
        set udg_RFS_Debug = false
   
        //-----------------------------------------------------------------------
        //-- This is the maximum distance offset
        //-- the unit will be ordered to move to
        //-- periodically
        //-----------------------------------------------------------------------
        set udg_RFS_MaxDistance = 200.0
   
        //-----------------------------------------------------------------------
        //-- This is the special effect attached on the affected unit
        //-- Since this is written in JASS, the file path must use double "\"
        //-- So please do not forget that
        //-----------------------------------------------------------------------
        set udg_RFS_SfxModelDefault = "Abilities\\Spells\\Other\\HowlOfTerror\\HowlTarget.mdl"
   
        //-----------------------------------------------------------------------
        //-- This is the attachment point for the special effect
        //-- For example: chest, hand right, hand left, origin, etc
        //-----------------------------------------------------------------------
        set udg_RFS_AttachPointDefault = "chest"
       
        //-----------------------------------------------------------------------
        //-- This is how often the unit will be
        //-- ordered to move around when affected
        //-----------------------------------------------------------------------
        set udg_RFS_Timeout = 0.4
    //===========================================================================
    //                              END OF CONFIG
    //===========================================================================
endfunction

function Trig_RFS_IsUnitInFear takes unit u returns boolean
    local integer uId = GetHandleId(u)

    //-- Load unit's current flag (IsUnitFeared)
    local integer flag = LoadInteger(udg_RFS_Table, uId, 0)

    if flag == 1 then
        return true
    else
        return false
    endif
endfunction

function Trig_RFS_CheckFear_Actions takes nothing returns boolean
    set udg_RFS_IsUnitInFear = Trig_RFS_IsUnitInFear(udg_RFS_Param_Unit)
    return false
endfunction

function Trig_RFS_RemoveFear takes unit u returns nothing
    //-- Get unit's handle id
    local integer uId = GetHandleId(u)

    //-- Get the special effect
    local effect e = LoadEffectHandle(udg_RFS_Table, uId, 2)

    //-- Destroy the special effect
    call DestroyEffect(e)

    //-- CLean up hashtable
    call FlushChildHashtable(udg_RFS_Table, uId)

    //-- Order the affected unit to stop
    call IssueImmediateOrderById(u, 851972)

    //-- Debug
    if udg_RFS_Debug == true then
        call BJDebugMsg("[|cffffcc00System|r] - " + "Fear is successfully removed")
    endif

    set e = null
endfunction

function Trig_RFS_Death_Actions takes nothing returns boolean
    local unit u = GetTriggerUnit()
    local integer uId = GetHandleId(u)

    //-- Load unit's current flag (IsUnitFeared)
    local integer flag = LoadInteger(udg_RFS_Table, uId, 0)

    if flag == 0 then
        set u = null
        return false
    endif   
   
    set udg_RFS_LastFinishedUnit = u
    set udg_RFS_OnFinishEvent = 1.00
    set udg_RFS_OnFinishEvent = 0.00
    call Trig_RFS_RemoveFear(u)
       
    set u = null
    return false
endfunction

function Trig_RFS_Order_Actions takes nothing returns boolean
    //-- Local variables
    local real x
    local real y

    //-- GetIssuedOrderId
    local integer oId

    //-- Get the unit and its id
    local unit u = GetOrderedUnit()
    local integer uId = GetHandleId(u)

    //-- Load unit's current flag (IsTerrified)
    local integer isTerrified = LoadInteger(udg_RFS_Table, uId, 0)

    if isTerrified == 0 then
        set u = null
        return false
    endif

    set oId = GetIssuedOrderId()

    if oId == 851973 then
        set u = null
        return false
    endif

    call DisableTrigger(GetTriggeringTrigger())

    //-- Load coordinates
    set x = LoadReal(udg_RFS_Table, uId, 3)
    set y = LoadReal(udg_RFS_Table, uId, 4)

    //-- Order unit to move
    call IssuePointOrderById(u, 851986, x, y)

    call EnableTrigger(GetTriggeringTrigger())

    //-- Debug
    if udg_RFS_Debug == true then
        call BJDebugMsg("[|cffffcc00System|r] - " + "Order is successfully prevented")
    endif

    set u = null
    return false
endfunction

function Trig_RFS_Timer_Actions takes nothing returns nothing
    //-- Local variables
    local real x1
    local real y1
    local real x2
    local real y2

    //-- Get expired timer
    local timer t = GetExpiredTimer()

    //-- Get its handle id
    local integer tId = GetHandleId(t)

    //-- Load unit
    local unit u = LoadUnitHandle(udg_RFS_Table, tId, 0)

    //-- Get unit's handle id
    local integer uId = GetHandleId(u)

    //-- Load unit's current flag (IsUnitFeared)
    local integer flag = LoadInteger(udg_RFS_Table, uId, 0)

    //-- Get unit's fear duration
    local real duration = LoadReal(udg_RFS_Table, uId, 1)
   
    if duration > 0 and flag == 1 then
        //-- Decrease duration
        set duration = duration - udg_RFS_Timeout

        //-- Get unit's coor
        set x1 = GetUnitX(u)
        set y1 = GetUnitY(u)

        //-- Give new order
        set x2 = GetRandomReal(x1 - udg_RFS_MaxDistance, x1 + udg_RFS_MaxDistance)
        set y2 = GetRandomReal(y1 - udg_RFS_MaxDistance, y1 + udg_RFS_MaxDistance)
        call IssuePointOrderById(u, 851986, x2, y2)

        //-- Update coordinates
        call SaveReal(udg_RFS_Table, uId, 3, x2)
        call SaveReal(udg_RFS_Table, uId, 4, y2)

        //-- Update duration
        call SaveReal(udg_RFS_Table, uId, 1, duration)
    else
        //-- Remove the fear effect
        if duration <= 0 and flag == 1 then
            set udg_RFS_LastFinishedUnit = u
            set udg_RFS_OnFinishEvent = 1.00
            set udg_RFS_OnFinishEvent = 0.00
            call Trig_RFS_RemoveFear(u)
        endif

        //-- Clean up hashtable
        call FlushChildHashtable(udg_RFS_Table, tId)

        //-- Destroy the timer
        call DestroyTimer(t)       

        //-- Debug
        if udg_RFS_Debug == true then
            call BJDebugMsg("[|cffffcc00System|r] - " + "Timer is successfully destroyed")
        endif
    endif

    set u = null
    set t = null   
endfunction

function Trig_RFS_RemoveFear_Actions takes nothing returns boolean
    local unit u = udg_RFS_Param_Unit
    call Trig_RFS_RemoveFear(u)

    set u = null
    return false
endfunction

function Trig_RFS_ApplyFear takes unit whichUnit, real duration, boolean stackable, string sfxModel, string attachPoint returns nothing
    //-- Local variables
    local real x1
    local real y1
    local real x2
    local real y2
    local timer t
    local integer tId

    //-- Get target's handle id
    local integer uId = GetHandleId(whichUnit)

    //-- Load unit's current flag (IsUnitFeared)
    local integer flag = LoadInteger(udg_RFS_Table, uId, 0)

    //-- Load unit's current duration
    local real d = LoadReal(udg_RFS_Table, uId, 1)

    //-- Load effect handle
    local effect e = LoadEffectHandle(udg_RFS_Table, uId, 2)

    //-- Check if stackable
    if stackable == true then
        set d = d + duration
    else
        if duration > d then
            set d = duration
        endif
    endif

    //-- Update duration
    call SaveReal(udg_RFS_Table, uId, 1, d)

    //-- Make sure to destroy previous effect if it exists
    call DestroyEffect(e)

    //-- Create a new special effect on the unit
    if sfxModel == "" then
        set sfxModel = udg_RFS_SfxModelDefault
    endif
    if attachPoint == "" then
        set attachPoint = udg_RFS_AttachPointDefault
    endif
    set e = AddSpecialEffectTarget(sfxModel, whichUnit, attachPoint)     

    //-- Save the effect handle
    call SaveEffectHandle(udg_RFS_Table, uId, 2, e)

    //-- Check if unit is already in fear
    if flag == 1 then
        if udg_RFS_Debug == true then
            call BJDebugMsg("[|cffffcc00System|r] - " + "Fear is reapplied")
        endif
        set t = null          
        set e = null
        return
    endif

    //-- Get unit's coor
    set x1 = GetUnitX(whichUnit)
    set y1 = GetUnitY(whichUnit)

    //-- Order them to move around
    set x2 = GetRandomReal(x1 - udg_RFS_MaxDistance, x1 + udg_RFS_MaxDistance)
    set y2 = GetRandomReal(y1 - udg_RFS_MaxDistance, y1 + udg_RFS_MaxDistance)
    call IssuePointOrderById(whichUnit, 851986, x2, y2)

    //-- Save coordinates
    call SaveReal(udg_RFS_Table, uId, 3, x2)
    call SaveReal(udg_RFS_Table, uId, 4, y2)

    //-- Update unit's flag to mark them feared
    call SaveInteger(udg_RFS_Table, uId, 0, 1)

    //-- Create and start a timer
    set t = CreateTimer()
    call TimerStart(t, udg_RFS_Timeout, true, function Trig_RFS_Timer_Actions)

    //-- Save the timer and attach unit's id to it
    set tId = GetHandleId(t)
    call SaveUnitHandle(udg_RFS_Table, tId, 0, whichUnit)

    //-- Debug
    if udg_RFS_Debug == true then
        call BJDebugMsg("[|cffffcc00System|r] - " + "Fear is applied")
    endif

    set t = null          
    set e = null
endfunction

function Trig_RFS_ApplyFear_Actions takes nothing returns boolean
    //-- Assign locals for easy function call
    local unit u    = udg_RFS_Param_Unit
    local real d    = udg_RFS_Param_Duration
    local boolean b = udg_RFS_Param_Stackable
    local string m  = udg_RFS_Param_SfxModel
    local string a  = udg_RFS_Param_AttachPoint

    //-- Apply fear
    call Trig_RFS_ApplyFear(u, d, b, m, a)

    //-- Reset the parameters
    set udg_RFS_Param_Unit          = null
    set udg_RFS_Param_Duration      = 0.0
    set udg_RFS_Param_Stackable     = false
    set udg_RFS_Param_SfxModel      = ""
    set udg_RFS_Param_AttachPoint   = ""

    set u = null
    return false
endfunction

//===========================================================================
function InitTrig_RFS takes nothing returns nothing
    local integer i = 0

    //-- Create triggers to handle unit's order and death
    local trigger orderTrg = CreateTrigger()
    local trigger deathTrg = CreateTrigger()

    //-- Create triggers to apply and remove fear effect
    set udg_RFS_ApplyFear = CreateTrigger()
    set udg_RFS_RemoveFear = CreateTrigger()
    set udg_RFS_CheckFear = CreateTrigger()

    //-- Attach functions to each trigger
    call TriggerAddCondition(orderTrg, Condition(function Trig_RFS_Order_Actions))
    call TriggerAddCondition(deathTrg, Condition(function Trig_RFS_Death_Actions))
    call TriggerAddCondition(udg_RFS_ApplyFear, Condition(function Trig_RFS_ApplyFear_Actions))
    call TriggerAddCondition(udg_RFS_RemoveFear, Condition(function Trig_RFS_RemoveFear_Actions))
    call TriggerAddCondition(udg_RFS_CheckFear, Condition(function Trig_RFS_CheckFear_Actions))

    loop
        //-- Order events
        call TriggerRegisterPlayerUnitEvent(orderTrg, Player(i), EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null)
        call TriggerRegisterPlayerUnitEvent(orderTrg, Player(i), EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, null)
        call TriggerRegisterPlayerUnitEvent(orderTrg, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, null)

        //-- Death event
        call TriggerRegisterPlayerUnitEvent(deathTrg, Player(i), EVENT_PLAYER_UNIT_DEATH, null)

        set i = i + 1
        exitwhen i == bj_MAX_PLAYER_SLOTS
    endloop

    //-- Initialize a hashtable
    //-- Map:
    //-- 0 = Fear Flag
    //-- 1 = Fear Duration
    //-- 2 = Special Effect
    //-- 3 = CoorX
    //-- 4 = CoorY
    //-- TimerId = UnitId
    set udg_RFS_Table = InitHashtable()

    //-- Run Config
    call Trig_RFS_Configurations()

    set orderTrg = null
    set deathTrg = null
endfunction

Why this exists?​

This system was born from my desire to solve an issue with this spell that utilizes fear system. I experimented with Fear System v1.1 to see what could be improved—but in the end, I decided to write my own version from scratch using a different approach.

Credits​

  • Chopinski – for the CC & Tenacity system
  • Daffa – for porting the fear system to GUI - Fear System
  • Me (Rheiko) – for writing this version of the system


v1.0.2
  • Code Optimization
v1.0.1
  • Typing -debug now has a message feedback.
  • Fixed revive unit trigger did not revive units properly for the testmap.
  • Added two new optional parameters: RFS_Param_SfxModel & RFS_Param_AttachPoint.
    • Users can now modify the model file and its attachment point directly without needing to change the system's config. Newer effect will replace older effect. These parameters are optional, meaning if they are not used when you ApplyFear, the system will automatically use RFS_SfxModelDefault and RFS_AttachPointDefault (can be configured as well).
  • Updated some of the example triggers to feature new parameters.
v1.0
  • Released to public
Contents

Rheiko's Fear System [RFS] v1.0.2 (Map)

Reviews
Antares
Do the functions need the Trig_ prefix? They seem unnecessary as you're not adding the callbacks to the triggers with GUI. The method of disabling the order overwrite trigger is a bit slow and needlessly convoluted. It would be easier to just disable...
This is splendid! I have been having bad taste with issues I ran into with Fear System on my version, so seeing yours really is a good sight for sore eyes 👍

Would need to test it more extensively, but if it is superior in every way possible, it is time to deprecate mine in favor of yours 👍
 

Rheiko

Spell Reviewer
Level 27
Joined
Aug 27, 2013
Messages
4,243
Thanks for the kind words!
I totally get the frustration, I'm really glad RFS came across as a breath of fresh air for you. :grin:
Definitely take your time to test it thoroughly—I'd love to hear any feedback or edge cases you might uncover.
If it ends up working better for your needs, it’d be an honor to have it take the torch forward.
Big thanks to you—without your version, I wouldn't have been inspired to make this one in the first place!
 
I am tagging @Dominus15 since he seeks a version compatible with 1.26 in my Fear System thread.

Thanks for the kind words!
I totally get the frustration, I'm really glad RFS came across as a breath of fresh air for you. :grin:
Definitely take your time to test it thoroughly—I'd love to hear any feedback or edge cases you might uncover.
If it ends up working better for your needs, it’d be an honor to have it take the torch forward.
Big thanks to you—without your version, I wouldn't have been inspired to make this one in the first place!
This is from a quick glance at the code, but is there a way for RFS to allow different special effects being used for showing fear from different sources? (There's no sfx editing in the example)

My version allows different effects to be shown to indicate under effect of fear, allowing different spells to show different fear effect. I think it would be a great addition, not mandatory though.

Can't promise much right now, but a compatibility script to help people transfer from mine to yours will be on my list since this is VERY promising for me.
 

Rheiko

Spell Reviewer
Level 27
Joined
Aug 27, 2013
Messages
4,243
This is from a quick glance at the code, but is there a way for RFS to allow different special effects being used for showing fear from different sources? (There's no sfx editing in the example)

My version allows different effects to be shown to indicate under effect of fear, allowing different spells to show different fear effect. I think it would be a great addition, not mandatory though.
Unfortunately, there is none at the moment. Although, it is definitely possible to be added. My main concern was the special effects piling up even though it's coming from the same fear mechanic.

I planned to allow user to define their own fear type, so they can have multiple fear effects on a unit. Is it really necessary, though? since the effects will be all the same, I scraped the idea. I mean they are just gonna move around uncontrollably.
But I guess it's fine to have different spell show different fear effect.
 
Unfortunately, there is none at the moment. Although, it is definitely possible to be added. My main concern was the special effects piling up even though it's coming from the same fear mechanic.

I planned to allow user to define their own fear type, so they can have multiple fear effects on a unit. Is it really necessary, though? since the effects will be all the same, I scraped the idea. I mean they are just gonna move around uncontrollably.
But I guess it's fine to have different spell show different fear effect.
Yeah, it is preference so I don't really mind it not being added 👍

I just mentioned it so at least the matter exists. Fear Types would be very excessive in my opinion, though Dota 2 technically has fear types with different fear behaviors, but that's another beast to handle 😂
 

Rheiko

Spell Reviewer
Level 27
Joined
Aug 27, 2013
Messages
4,243
I just mentioned it so at least the matter exists. Fear Types would be very excessive in my opinion, though Dota 2 technically has fear types with different fear behaviors, but that's another beast to handle 😂
Oh really? I need to check that out. I'm not up-to-date with games these days.

Honestly, I was just trying to avoid excessive special effects to keep the system's performance high (although special effect shouldn't be that much of a problem). I think fear type could solve that since each type could have different special effect and it makes more sense that way.

I'll see what I can do. ;)
 
Last edited:

Rheiko

Spell Reviewer
Level 27
Joined
Aug 27, 2013
Messages
4,243
Bumped the thread for a minor update per @Daffa 's suggestion

Updated to v1.0.1
  • Typing -debug now has a message feedback.
  • Fixed revive unit trigger did not revive units properly for the testmap.
  • Added two new optional parameters: RFS_Param_SfxModel & RFS_Param_AttachPoint.
    • Users can now modify the model file and its attachment point directly without needing to change the system's config. Newer effect will replace older effect. These parameters are optional, meaning if they are not used when you ApplyFear, the system will automatically use RFS_SfxModelDefault and RFS_AttachPointDefault (can be configured as well).
  • Updated some of the example triggers to feature new parameters.
I am very fond of this system the way it is right now, so I have decided to avoid adding fear type for the time being. I will probably do so in the future and perhaps in a different resource. Only time will tell.
 

Antares

Spell Reviewer
Level 33
Joined
Dec 13, 2009
Messages
1,010
Do the functions need the Trig_ prefix? They seem unnecessary as you're not adding the callbacks to the triggers with GUI.

The method of disabling the order overwrite trigger is a bit slow and needlessly convoluted. It would be easier to just disable the trigger, issue the command, then enable it again. The trigger can also be optimized. There should be an early return if isTerrified != 1 and all variables not needed at that point should be retrieved afterwards.

These are minor issues though. The system is working as intended and is easy-to-use.

Approved
 

Rheiko

Spell Reviewer
Level 27
Joined
Aug 27, 2013
Messages
4,243
Thanks for the approval!

Do the functions need the Trig_ prefix? They seem unnecessary as you're not adding the callbacks to the triggers with GUI.
Nein! They are completely unnecessary! It's just something I learned from Dr Super Good. I read his code and found it funny but made me want to try it myself so I did. :xxd:

It would be easier to just disable the trigger, issue the command, then enable it again.
But if a user accidentally made a trigger that could catch the order and order them to move, it would possibly cause an infinite loop and crash. I wouldn't be able to disable their trigger because I wouldn't have known which one it could be.
Yeah, it works. I'm dumb.

all variables not needed at that point should be retrieved afterwards.
I don't really get this. Could you elaborate?
 
Last edited:

Antares

Spell Reviewer
Level 33
Joined
Dec 13, 2009
Messages
1,010
I don't really get this. Could you elaborate?
JASS:
function Trig_RFS_Order_Actions takes nothing returns boolean
    //-- Local variables
    local real x
    local real y

    //-- GetIssuedOrderId
    local integer oId = GetIssuedOrderId()

    //-- Get the unit and its id
    local unit u = GetOrderedUnit()
    local integer uId = GetHandleId(u)

    //-- Load unit's current flag (IsTerrified)
    local integer isTerrified = LoadInteger(udg_RFS_Table, uId, 0)

    //-- Load unit's current flag (IsOrdered)
    local integer isOrdered = LoadInteger(udg_RFS_Table, uId, 5)

    if isTerrified == 1 and oId != 851973 then
        //...
The case isTerrified == 0 will be true 99% of the time, so it makes sense to optimize the function as much as possible for that case. However, if the unit is not terrified, the call to get the issued order id and isOrdered flag is wasted. How you want to structure such a function is as such:

JASS:
//Get everything needed for guard 1
if not guard1 then
    return
end

//Get everything needed for guard 2
if not guard2 then
    return
end

//Code

So, in this specific case, it would be:
JASS:
function Trig_RFS_Order_Actions takes nothing returns boolean
    //-- Local variables
    local real x
    local real y

    //-- Get the unit and its id
    local unit u = GetOrderedUnit()
    local integer uId = GetHandleId(u)

    //-- Load unit's current flag (IsTerrified)
    local integer isTerrified = LoadInteger(udg_RFS_Table, uId, 0)

    if isTerrified == 0 then
        set u = null
        return false
    endif

    //-- GetIssuedOrderId
    local integer oId = GetIssuedOrderId()

    if oId == 851973 then
        set u = null
        return
    endif

    //-- Load unit's current flag (IsOrdered)
    local integer isOrdered = LoadInteger(udg_RFS_Table, uId, 5)

    //...
 
Top