Snippet TriggerRegisterAnyUnitDamageEvent

XeNiM666

I lurk for pizza
Reaction score
138
TriggerRegisterAnyUnitDamageEvent​

Well basically this adds an event to a trigger "Any unit Takes Damage" with a small feature.
The small feature is that you can show the damage dealt whether any unit in the map takes damage. You can set it so there's a point in time that no damage is shown.

What to do:
Just copy the code below:
JASS:
scope Damage initializer Initialization
    
    globals
        // SELF EXPLANATORY
        // SET THIS TO FALSE IF YOU DONT WANT TO SHOW DAMAGE DEALT
        public boolean Show_Damage_Dealt = true
        
        // IF Show_Damage_Dealt = true THEN THIS IS THE COLOR OF THE TEXTTAG THAT WILL SHOW THE DAMAGE DEALT
        private constant string Damage_dealt_Texttag_color = "|CFF000000"

//********************************************************************//
//                TOUCH ONLY IF YOU KNOW WHAT TO DO...                //
//********************************************************************//
        
        public constant trigger trig = CreateTrigger()
        private constant group Dmg_Grp = CreateGroup()
    endglobals
    
    private function Damage_Check takes nothing returns boolean
        return IsUnitInGroup( GetTriggerUnit(), Dmg_Grp ) == true and GetEventDamage() > 0.00 and Show_Damage_Dealt == true
    endfunction

    private function Damage_Show takes nothing returns nothing
        local texttag tt = CreateTextTag()
        
        local unit u = GetTriggerUnit()
        local real x = GetUnitX( u )
        local real y = GetUnitY( u )
        
        call SetTextTagText( tt, Damage_dealt_Texttag_color + I2S( R2I( GetEventDamage() ) ), 0.023 )
        call SetTextTagVelocity( tt, 0.06102 * Cos( 90.00 * bj_DEGTORAD ), 0.06102 * Sin( 90.00 * bj_DEGTORAD ) )
        call SetTextTagPos( tt, x, y, 0.00 )
        call SetTextTagPermanent( tt, false )
        call SetTextTagLifespan( tt, 2.50 )
        call SetTextTagFadepoint( tt, 1.00 )
        
        set tt = null
        set u = null
    endfunction
    
    //=================================================================================================

    private function Check takes nothing returns boolean
        return IsUnitInGroup( GetFilterUnit(), Dmg_Grp ) == false
    endfunction

    private function Actions takes nothing returns nothing
        local group g = CreateGroup()
        local unit u = null

        call GroupEnumUnitsInRange( g, 0.00, 0.00, 99999.00, Condition( function Check ) )
        
        loop
            set u = FirstOfGroup( g )
            
            // REGISTER UNIT DAMAGE EVENTS IN EVERY DAMAGE DETECTION TRIGGER
            
            call TriggerRegisterUnitEvent( trig, u, EVENT_UNIT_DAMAGED )
            call GroupAddUnit( Dmg_Grp, u )
            
            exitwhen u == null
            
            call GroupRemoveUnit( g, u )
        endloop
        
        call DestroyGroup( g )
        set g = null
    endfunction
    
    function TriggerRegisterAnyUnitDamageEvent takes trigger t returns nothing
        local group g = Dmg_Grp
        local unit u = null
        
        loop
            set u = FirstOfGroup( g )
            exitwhen u == null
            
            call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DAMAGED )
            
            call GroupRemoveUnit( g, u )
        endloop
        
        call DestroyGroup( g )
        set g = null
        set u = null
    endfunction

    //===========================================================================
   
    private function Initialization takes nothing returns nothing
        local trigger t = CreateTrigger(  )
        call TriggerRegisterTimerEvent( t, 0.50, true )
        call TriggerAddAction( t, function Actions )
        set t = null
        
        call TriggerAddCondition( trig, Condition( function Damage_Check ) )
        call TriggerAddAction( trig, function Damage_Show )
        
        call Preload( Damage_dealt_Texttag_color )
        call PreloadStart()
    endfunction

endscope


This code contains this function:
JASS:
function TriggerRegisterAnyUnitDamageEvent takes trigger t returns nothing

Sample:
JASS:
call TriggerRegisterAnyUnitDamageEvent( MyTrigger )

What this does is register "Any unit Takes Damage" to the trigger of your choice.

Features:
As you can see there are 2 configurables, Show_Damage_Dealt and Damage_dealt_Texttag_color.
Show_Damage_Dealt - A boolean whether the damage is shown when any unit in the map takes damage.
Damage_dealt_Texttag_color - A string containing the color of the texttag created to show how much damage is dealt.

To set whether show any damage, do this:
JASS:
set Show_Damage_Dealt = true

if you dont want to show damage, do this:
JASS:
set Show_Damage_Dealt = false


Enjoy! :)

~ XeNiM666
 

wraithseeker

Tired.
Reaction score
122
Why are you converting radians and degrees?

You also forgot if that if a unit is damaged through every 0.03 seconds, wouldn't it malfunction with UnitDamageTarget?

I don't think this is nice except the displaying damage part which is a good snippet for users :)

This defeats the purpose of your DamageEvent.
 

Flare

Stops copies me!
Reaction score
662
Slight problem...
JASS:
local group g = Dmg_Grp
...
call DestroyGroup( g )

You've just destroyed Dmg_grp :p g is pointing to the same group that Dmg_grp is, so when you destroy the group g points to, you destroy the group that Dmg_grp points to, and the system doesn't seem to work from that point :p

JASS:
        loop
            set u = FirstOfGroup( g )
            exitwhen u == null
            
            call TriggerRegisterUnitEvent( t, u, EVENT_UNIT_DAMAGED )
            
            call GroupRemoveUnit( g, u )
        endloop

Again, g and Dmg_grp are the same group so whatever you do to g will affect Dmg_grp - you've just emptied your storage group :p That should be replaced with a ForGroup, and store the function parameter in a global so you can transfer it to the group callback.

Also, since events are usually registered at initialization, your system doesn't work once more. Why?

First of all, there won't be any units in Dmg_grp at initialization, so first part. Secondly, there's no automated updating of the registered triggers. You only update the trig variable every 0.5 seconds (registering units when they enter the map is probably a better solution, depending on the type of map, since units may not enter the map very frequently).

Any triggers other than the system trigger that have the event registered will only have event registration for units that exist at the time that the function was called.
 

Darius34

New Member
Reaction score
30
Why register events for every unit in every trigger? You could just as well work with a single trigger with the registered events for every unit. That saves on the handle count - which is good when using some systems.

Anyway, take a look at this: it's a damage detection snippet that's very similar to what you're doing. The implementation there is solid, so you might want to refer to it. Adding on to what Flare said, you need to track when units enter the map area to have damage triggers automatically update, and register any pre-placed units at initialization.
 

Flare

Stops copies me!
Reaction score
662
Why are you converting radians and degrees?
Converting radians and degrees? He's only converting degrees to radians, what the hell are you on about? :confused:

You also forgot if that if a unit is damaged through every 0.03 seconds, wouldn't it malfunction with UnitDamageTarget?
What? Why would something malfunction with UnitDamageTarget? Anyway, damaging units with UnitDamageTarget every 0.03 seconds is a bit stupid anyway

This defeats the purpose of your DamageEvent.
Defeats the purpose? You seem to have mixed up the meaning of this phrase with something else. LLDD is an alternative to other systems, it doesn't defeat the purpose of making one... nobody says you have to use one system in particular. What would defeat the purpose of making it would be if (a) it couldn't possibly work, no matter what way you do it (not the case here, since it can work properly with some improvements), or (b) it didn't provide any benefit whatsoever (and you yourself, wraithseeker, said that the damage display may be useful, thus making it beneficial)
 

wraithseeker

Tired.
Reaction score
122
JASS:
library LightLeaklessDamageDetect initializer Init
    
    // Creating threads off of this that last longer than the timeout below will likely cause issues, like everything blowing up (handle stack corruption)
    // It seems that threads created by timers, rather than executefunc / .evaluate / .execute are not affected. Any threads created from the timer thread are fine.
    // This being safe with even the usage laid out above isn't guarenteed. Use at own risk.
    // If you start getting random bugs, see if commenting out the timer line below (see comments) helps
    // If it does, report it in the thread for this script at <a href="http://www.wc3campaigns.net" target="_blank" class="link link--external" rel="nofollow ugc noopener">www.wc3campaigns.net</a>
    
    globals
        private constant real SWAP_TIMEOUT = 600. // keep high; 600 should be about the right balance.
    endglobals
    
    globals
        private conditionfunc array func
        private integer funcNext = 0
        private trigger current = null
        private trigger toDestroy = null
        private group swapGroup
        private rect mapRect
    endglobals
    
    // One of the only accessible functions. Use it to add a condition. Must return boolean type, and then have return false at the end.
    // Note that it&#039;s technically a condition, so if you put a wait in there, it&#039;ll die. But waits are lame anyway.
    function AddOnDamageFunc takes conditionfunc cf returns nothing
        call TriggerAddCondition(current, cf)
        set func[funcNext] = cf
        set funcNext = funcNext + 1
    endfunction
    
    // These inline. For avoiding feedback loops. Feel free to make your own wrapper function for damage functions using this.
    function DisableDamageDetect takes nothing returns nothing
        call DisableTrigger(current)
    endfunction
    function EnableDamageDetect takes nothing returns nothing
        call EnableTrigger(current)
    endfunction
    
    // no more accessible functions, folks.
    
    //! textmacro CGLeaklessDamageDetectAddFilter takes UNIT
        
        // add here any conditions to add the unit to the trigger, example below, commented out:
        // if GetUnitTypeId($UNIT$) != &#039;h000&#039; then // where &#039;h000&#039; is a dummy unit
        call TriggerRegisterUnitEvent(current, $UNIT$, EVENT_UNIT_DAMAGED)
        // endif
        
    //! endtextmacro
    
    private function AddEx takes nothing returns boolean
        //! runtextmacro CGLeaklessDamageDetectAddFilter(&quot;GetFilterUnit()&quot;)
        return false
    endfunction

    private function Enters takes nothing returns boolean
        //! runtextmacro CGLeaklessDamageDetectAddFilter(&quot;GetTriggerUnit()&quot;)
        return false
    endfunction
    
    private function Swap takes nothing returns nothing
        local integer i = 0
        local boolean b = IsTriggerEnabled(current)
        
        call DisableTrigger(current)
        if toDestroy != null then
            call DestroyTrigger(toDestroy)
        endif
        set toDestroy = current
        set current = CreateTrigger()
        
        if not(b) then
            call DisableTrigger(current)
        endif
        
        call GroupEnumUnitsInRect(swapGroup, mapRect, Filter(function AddEx))
        
        loop
            exitwhen i &gt;= funcNext
            call TriggerAddCondition(current, func<i>)
            set i = i + 1
        endloop
    endfunction
    
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local region r = CreateRegion()
        local integer i = 0
        set mapRect = GetWorldBounds()
        call RegionAddRect(r, mapRect)
        call TriggerRegisterEnterRegion(t, r, null)
        call TriggerAddCondition(t, Condition(function Enters))
        
        set swapGroup = CreateGroup()
        
        set current = CreateTrigger()
        loop
            exitwhen i &gt;= funcNext
            call TriggerAddCondition(current, func<i>)
            set i = i + 1
        endloop
        
        call GroupEnumUnitsInRect(swapGroup, GetWorldBounds(), Filter(function AddEx))
        
        // Commenting out the next line will make the system leak indexes and events, but should make it safer.
        call TimerStart(CreateTimer(), SWAP_TIMEOUT, true, function Swap)
    endfunction
    
endlibrary</i></i>


I'm not really sure, I read at the thread of this system was created.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • WildTurkey WildTurkey:
    is there a stephen green in the house?
    +1
  • The Helper The Helper:
    What is up WildTurkey?
  • The Helper The Helper:
    Looks like Google fixed whatever mistake that made the recipes on the site go crazy and we are no longer trending towards a recipe site lol - I don't care though because it motivated me to spend alot of time on the site improving it and at least now the content people are looking at is not stupid and embarrassing like it was when I first got back into this like 5 years ago.
  • The Helper The Helper:
    Plus - I have a pretty bad ass recipe collection now! That section of the site is 10 thousand times better than it was before
  • The Helper The Helper:
    We now have a web designer at my job. A legit talented professional! I am going to get him to redesign the site theme. It is time.
  • Varine Varine:
    I got one more day of community service and then I'm free from this nonsense! I polished a cop car today for a funeral or something I guess
  • Varine Varine:
    They also were digging threw old shit at the sheriff's office and I tried to get them to give me the old electronic stuff, but they said no. They can't give it to people because they might use it to impersonate a cop or break into their network or some shit? idk but it was a shame to see them take a whole bunch of radios and shit to get shredded and landfilled
  • The Helper The Helper:
    whatever at least you are free
  • Monovertex Monovertex:
    How are you all? :D
    +1
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top