System Attack Detection

gref

New Member
Reaction score
33
Attack Detection 1.10
No current versions are stable. Please wait to use this in your map until a stable version has been released.

System Description:
An Attack Detection system is system that triggers, for all units, when they take damage, depending on whether that damage was caused via a spell or an attack, a predefined action. The purpose of the system is to make it as simple as possible to detect and respond to damage events, as it is for all generic events.

Most recent update: January 10th 2008.
GUI: 1.10b: Removed the need for 3 global variables.
Jass: 1.10c: ExecuteFunc use changed to trigger action use. Syntax errors will occur on compile now rather than in game.



Changelog
Version 1.00:
-Changed to PUI from CSCache- More user friendliness/safety as a result
-Added more demo items
-Added shop to get items from in game
-File size is halved

Version 1.01:
-Added support for excluding dummy units from system. Slight performance increase, has no effect on system behaviour as dummy units do not take damage.

Version 1.10
-Removed everyones hands from my library
-Added support for GUI
-Added ExecuteFunc for Jass

Version 1.10b Jass
-Added an important level of data abstraction for Jass users

Version 1.10b GUI
-Removed the need for 3 Global variables, making initialization simpler.

Version 1.10c Jass
-Change ExecuteFunc use to TriggerExecute, allowing syntaxing, and removing multiple-thread abuse.

Screenshots:
ADSystemScreen.jpg

ADSystemScreen2.jpg

System Code:
Jass 1.10c
JASS:
//====================>
// AD by gref.
//====================>
// To add functions scroll down to where it says Add Functions.


library AttackDetection initializer Init_AttackDetection requires PUI

//====================>
// Constants
//====================>
    // AbilCode = the integer id of AD Ability
    // BuffCode = the interger id of AD Buff
    globals
        private constant integer BuffCode = 'B000'
        private constant integer AbilCode = 'A000' 
        
        private trigger array SpellTriggers
        private trigger array AttackTriggers
        private integer SpellNumber = 0
        private integer AttackNumber = 0 
        
        unit AD_Attacker
        unit AD_Defender
        real AD_Damage
        
        private integer array Dummys
        private integer DummyNumber = 0 
    endglobals
//====================>
// Data types
//====================>
    struct AD
        trigger t
        triggeraction ta
        unit u    
        
        private static AD array THIS
                
        static method Get takes unit whichUnit returns AD
            local integer pui = GetUnitIndex(whichUnit)
            if .THIS[pui]==null then
                set .THIS[pui] = AD.allocate()
            endif
            return .THIS[pui]
        endmethod
    endstruct

//====================>
// User Editted Functions
//====================>
    function AD_AddDummy takes integer id returns nothing
        set Dummys[DummyNumber] = id
        set DummyNumber = DummyNumber + 1
    endfunction
    
    function AD_AddFunction takes code userFunc, boolean attack returns nothing
        if(attack == true) then   
            set AttackTriggers[AttackNumber] = CreateTrigger()
            call TriggerAddAction(AttackTriggers[AttackNumber], userFunc)
            set AttackNumber = AttackNumber + 1             
        else            
            set SpellTriggers[SpellNumber] = CreateTrigger()
            call TriggerAddAction(SpellTriggers[SpellNumber], userFunc)
            set SpellNumber = SpellNumber + 1           
        endif    
    endfunction

    private function IsUnitDummy takes integer id returns boolean
        local integer i = 0
    
        loop
            exitwhen i == DummyNumber
            
            if (id == Dummys<i>) then
                return true
            endif
            
            set i = i + 1
        endloop
                
        return false
    endfunction
    
    //Add Functions in the demonstrated spaces below.
    private function UnitDamaged takes nothing returns nothing
        local integer i = 0
        
        set AD_Damage = GetEventDamage()
        set AD_Attacker = GetEventDamageSource()
        set AD_Defender = GetTriggerUnit()
        
        
        if(GetUnitAbilityLevel(GetTriggerUnit(), BuffCode) &gt; 0) then   
            call UnitRemoveAbility(GetTriggerUnit(), BuffCode)  
            
                   
            loop
                exitwhen i == AttackNumber
            
                call TriggerExecute(AttackTriggers<i>)
            
                set i = i+1       
            endloop
                    
        else   
        
            loop
                exitwhen i == SpellNumber
            
                call TriggerExecute(SpellTriggers<i>)
            
                set i = i+1       
            endloop
        
        endif
        
    endfunction     

//====================&gt;
// Initialization
//====================&gt;

    private function UnitEntersWorld takes nothing returns nothing
        local unit  u = GetEnteringUnit()
        local AD a = AD.Get(u) 
        
        if(IsUnitDummy(GetUnitTypeId(u)) != true) then
        
            //Clear the previous units triggers
            if(a.u != null) then
                call TriggerRemoveAction(a.t, a.ta)
                call DestroyTrigger(a.t)  
            endif                 
                
            //Add the new ones.                                         
            set a.u = u
            set a.t = CreateTrigger()
            call TriggerRegisterUnitEvent(a.t, u, EVENT_UNIT_DAMAGED) 
            call UnitAddAbility(u, AbilCode)  
            set a.ta = TriggerAddAction(a.t, function UnitDamaged)  
        endif
                       
        set u = null
    endfunction

    private function Init_AttackDetection takes nothing returns nothing
    // Adds all units on the map at initilization to damage detection triggers.
        local unit u
        local group g = CreateGroup()
        local AD a
        local trigger t = CreateTrigger() //Add a trigger to make all units entering the map added.
        
        call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            
            set a = AD.Get(u)
            //Clear the previous units triggers
            if(a.u != null) then
                call TriggerRemoveAction(a.t, a.ta)
                call DestroyTrigger(a.t)  
            endif                 
                
            //Add the new ones.                                         
            set a.u = u
            set a.t = CreateTrigger()
            call TriggerRegisterUnitEvent(a.t, u, EVENT_UNIT_DAMAGED) 
            call UnitAddAbility(u, AbilCode)  
            set a.ta = TriggerAddAction(a.t, function UnitDamaged)   
             
        
            call GroupRemoveUnit(g, u)
        endloop    
        
        //Add units entering world trigger.
        call TriggerRegisterEnterRectSimple(t, GetWorldBounds())
        call TriggerAddAction(t, function UnitEntersWorld)
                     
        
        set u = null
        set g = null
        set t = null
    endfunction

endlibrary</i></i></i>

GUI 1.10b
JASS:
//====================&gt;
// AD by gref.
//====================&gt;
// To add functions scroll down to where it says Add Functions.


library AttackDetection initializer Init_AttackDetection requires PUI

//====================&gt;
// Constants
//====================&gt;
    // AbilCode = the integer id of AD Ability
    // BuffCode = the interger id of AD Buff
    globals
        private constant integer BuffCode = &#039;B000&#039;
        private constant integer AbilCode = &#039;A000&#039; 
    endglobals
//====================&gt;
// Data types
//====================&gt;
    struct AD
        trigger t
        triggeraction ta
        unit u    
        
        private static AD array THIS
                
        static method Get takes unit whichUnit returns AD
            local integer pui = GetUnitIndex(whichUnit)
            if .THIS[pui]==null then
                set .THIS[pui] = AD.allocate()
            endif
            return .THIS[pui]
        endmethod
    endstruct

//====================&gt;
// User Editted Functions
//====================&gt;

    private function IsUnitDummy takes integer id returns boolean
        local integer i = 0
    
        loop
            exitwhen udg_AD_Dummys<i> == null
        
            if (id == udg_AD_Dummys<i>) then
                return true
            endif
            
            set i = i + 1
        endloop
                
        return false
    endfunction
    
    //Add Functions in the demonstrated spaces below.
    private function UnitDamaged takes nothing returns nothing
        local integer i = 0
        
        set udg_AD_Damage = GetEventDamage()
        set udg_AD_Attacker = GetEventDamageSource()
        set udg_AD_Defender = GetTriggerUnit()
        
        
        if(GetUnitAbilityLevel(GetTriggerUnit(), BuffCode) &gt; 0) then   
            call UnitRemoveAbility(GetTriggerUnit(), BuffCode)  
            
                   
            loop
                exitwhen udg_AD_AttackTriggers<i> == null
            
                if(TriggerEvaluate(udg_AD_AttackTriggers<i>)) then
                    call TriggerExecute(udg_AD_AttackTriggers<i>)            
                endif           
            
                set i = i+1       
            endloop
                    
        else   
        
            loop
                exitwhen udg_AD_SpellTriggers<i> == null
            
                if(TriggerEvaluate(udg_AD_SpellTriggers<i>)) then
                    call TriggerExecute(udg_AD_SpellTriggers<i>)            
                endif           
            
                set i = i+1       
            endloop
        
        endif
        
        if(i == 0) then
            call BJDebugMsg(&quot;Error: No AD triggers defined. Start at 0 array index.&quot;)
        endif
        
    endfunction     

//====================&gt;
// Initialization
//====================&gt;

    private function UnitEntersWorld takes nothing returns nothing
        local unit  u = GetEnteringUnit()
        local AD a = AD.Get(u) 
        
        if(IsUnitDummy(GetUnitTypeId(u)) != true) then
        
            //Clear the previous units triggers
            if(a.u != null) then
                call TriggerRemoveAction(a.t, a.ta)
                call DestroyTrigger(a.t)  
            endif                 
                
            //Add the new ones.                                         
            set a.u = u
            set a.t = CreateTrigger()
            call TriggerRegisterUnitEvent(a.t, u, EVENT_UNIT_DAMAGED) 
            call UnitAddAbility(u, AbilCode)  
            set a.ta = TriggerAddAction(a.t, function UnitDamaged)  
        endif
                       
        set u = null
    endfunction

    private function Init_AttackDetection takes nothing returns nothing
    // Adds all units on the map at initilization to damage detection triggers.
        local unit u
        local group g = CreateGroup()
        local AD a
        local trigger t = CreateTrigger() //Add a trigger to make all units entering the map added.
        
        call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            
            set a = AD.Get(u)
            //Clear the previous units triggers
            if(a.u != null) then
                call TriggerRemoveAction(a.t, a.ta)
                call DestroyTrigger(a.t)  
            endif                 
                
            //Add the new ones.                                         
            set a.u = u
            set a.t = CreateTrigger()
            call TriggerRegisterUnitEvent(a.t, u, EVENT_UNIT_DAMAGED) 
            call UnitAddAbility(u, AbilCode)  
            set a.ta = TriggerAddAction(a.t, function UnitDamaged)   
             
        
            call GroupRemoveUnit(g, u)
        endloop    
        
        //Add units entering world trigger.
        call TriggerRegisterEnterRectSimple(t, GetWorldBounds())
        call TriggerAddAction(t, function UnitEntersWorld)
                     
        
        set u = null
        set g = null
        set t = null
    endfunction

endlibrary</i></i></i></i></i></i></i></i>

 

Attachments

  • AD System 1.10b GUI.w3x
    96.6 KB · Views: 387
  • AD System 1.10c Jass.w3x
    81.7 KB · Views: 313

Cohadar

master of fugue
Reaction score
209
Any Attack Detection engine that uses CSCashe fails - Instantly
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
Want me to share my system?
Although it is abit lame, but it works well on me.
JASS:
//&lt;-- Damaged Main Engine --&gt;//
globals
    private trigger p = null
    private trigger time = CreateTrigger()
endglobals

private function pickedCond takes nothing returns boolean
    return GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)&gt;0 and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) == false
endfunction

private function pickedAct takes nothing returns nothing
local unit e = GetEnumUnit()
    call TriggerRegisterUnitEvent(p,e,EVENT_UNIT_DAMAGED)
set e = null
endfunction

private function TimeAct takes nothing returns nothing
local group picked = CreateGroup()

    //Setting Trigger
    if p != null then
        call DestroyTrigger(p)
    endif
    set p = CreateTrigger()
    call TriggerAddCondition(p,Condition(function GTCond))
    call TriggerAddAction(p, function GTAct )
    //End
    

    call GroupEnumUnitsInRect(picked, bj_mapInitialPlayableArea,Condition(function pickedCond))
    call ForGroup(picked, function pickedAct)
    
call DestroyGroup(picked)
set picked = null
endfunction
//&lt;-- Damaged Main Engine End --&gt;//
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
Any Attack Detection engine that uses CSCashe fails - Instantly

Code:
  Extreme amount of attacks during one game
+ Every attack uses CACHE
+ Cache is slow, especially in great amounts
====================================
= Fail (read: lag or slow system)

Am I about right on your thoughts?



Gals: you have a damage detection system, we need an attack detection system
 

gref

New Member
Reaction score
33
Oh I'm sorry Mr. IFlamePandasBecauseMySystemIsSoSLow.
Isn't your system only 9% faster than gamecache anyway? A.
And B. simple integer attachment really doesn't take very long on ANY system.
OH NOES! Everytime a unit is damaged it has to make 0 CSCache calls. GG LAG!!1!
There are only CSCache calls when a unit is added or removed.

And Gals is right...it is a damage detection system. It just makes sure the damage is from an attack or spell.

My system has negatives Cohadar, which is why I put the whole Negatives bit in the readme, and linked to 2 other systems that do the same thing. Performance however, really isn't one of them.
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
Oh I'm sorry Mr. IFlamePandasBecauseMySystemIsSoSLow.
Isn't your system only 9% faster than gamecache anyway? A.
And B. simple integer attachment really doesn't take very long on ANY system.

What 'my system'? I don't have a system.
What I'm saying is using game cache at all is kinda outdated, but using game cache for every attack made during an entire game is completely absurd.

I had a spell once which moved 84 dummy units at once and I first used KaTTaNa's handle vars (game cache) for the struct attaching (struct = integer!).

My spell lagged and was even game ruiningly slow during multiple casts due to this flawed game cache speed.

When I used Cohadar's ABC (no cache) afterwards, it didn't lag at all anymore.

Go figure.
 

gref

New Member
Reaction score
33
Wasn't talking to you Magentix :)

There is no gamecache on any attacks at all.
There are in fact no timers either. So ABC really isn't very relevant.

That is all.
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
>>Gals: you have a damage detection system, we need an attack detection system
Sry ya, I am noob.

Main Topic
It is a basic knowledge to every advance mapper, gamecache is slow and quite unstable.
Take another try, use struct attachment system. They don't use gamecache but global arrays.

If you were pro enough, invent your own global array attaching system.
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
Ah well, I'm still waiting for the attack system out there that doesn't require an orb :(
 

gref

New Member
Reaction score
33
@ Gals

*sigh*
Your damage detection code was fine but I couldn't actually see what it did because the GTAct function wasn't in what you showed us. --

Change from CSCache: But there's no need? It's only called when a unit enters the map, leaves the map and map initialization. It's not something that happens so frequently I need a super fast attachment system that people have to copy into their map.

If I was pro enough etc: I don't want to make another standard that people have to copy into their map.

CSCache is pretty much a standard that almost everyone has, or has used, and a lot of people have in their maps. Hence I use that. I could use KaTtAnA's system. I could use ABC. I could use PandaMine's system. I could invent my own retarded system then speedtest it to boost my epeen. But I won't, because then more users would have to copy more useless crap into their map.



Ah well, I'm still waiting for the attack system out there that doesn't require an orb :(

There is actually one.
It's the first link in I put in the first post.

But it's flawed because you can attack, cancel to make actions occur when they wouldn't etc.
It's still useful for some purposes.

My main reason for using one with an orb, is because the basic orb effects are damned easy to make, so I don't see a reason not to.
 

gref

New Member
Reaction score
33
@ onDestroy: In the end...I just removed it.

I'll assume that people won't be foolish enough to alter the system and implode their maps. Probably a foolish assumption

@ Exclude unit, yeah that is a good idea.

Updated.

================================>
Updated: I just made this extremely simple to use in GUI, completely reworked the calling of the On Damage functions, and made an entire second seperate version, complete with demonstration Items.

*Tired sigh*

================================>
Updated further: Another level of data abstraction and ease of use for Jass users has been added.
As for GUI users, advice on whether I should do similar and get them to use custom script, or keep it using GUI variables would be nice...

Bump for all the effort I put in yesterday to make this usable by anyone.

I'd like everyone who'd care to give it's opinion on both the Jass and GUI version, and how to make implementation easier for both sets of people.

Should I make it so that GUI users call a custom script function or leave it as it is with the arrays?
Should I keep the executeFunc version for jass users, or make it take an actualy function? Is being able to use wait's occasionally in damage events worth the possible performance impact of using them to often?

That's fair enough.
I consider this easier to use, but I understand the other viewpoint which is why I added the other systems that approach it the other way.

All I need to make a map use this and not leak:
-One more trigger, that cleans units when they die.
-Replace RemoveUnit with my RemoveUnitClean function
-Add a AD_AddUnit(whichUnit) in where heroes are revived, or animate dead is cast.

Bump for major update.

Ok...Since it now uses PUI which should take care of the fact that all units die eventually, this is now actually user friendly.

Read the first post for details.
http://www.thehelper.net/forums/showthread.php?p=650345#post650345
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
Hmm, I' just got an idea for an Attack Detection System without orbs :eek:

Damn, now I can't wait till my exams are over, so I can start on it :(
 

0zaru

Learning vJASS ;)
Reaction score
60
An attachment system is not useless crap.

And those calls (When you call the attach int) are a lot, remember that when you create a spell that requires dummy unit, the unit enters in the playable map area. And if you call a barrier for example that needs 36 units...
 

Magentix

if (OP.statement == false) postCount++;
Reaction score
107
I'll be interested to see it. Check to make sure it isn't the same as this http://www.wc3campaigns.net/showthread.php?t=91354
And remember that autocast attack abilities always override orbs.

No, it's an idea for something that doesn't need any ability, nor check for buffs, but that's all I'm going to say right now, I need to design and test it first before I get people's hopes up
 

gref

New Member
Reaction score
33
An attachment system is not useless crap.

And those calls (When you call the attach int) are a lot, remember that when you create a spell that requires dummy unit, the unit enters in the playable map area. And if you call a barrier for example that needs 36 units...

Yup. It's alot. But CSCache will do it fine. :)

You guys all seem to forget that Stacking Orbs by Vexorian used CSCache, was much more attachment intensive, and yet is used by many many people.
 

Cohadar

master of fugue
Reaction score
209
The issues is not speed.
Attaching to units is not safe.

I think I repeated that line like 100 times by now.
You want to know why is it not safe?
Use the search button.
 

gref

New Member
Reaction score
33
It's not safe because units die and get removed I know.

Do you know why I don't care? Read the readme.

It might have something to do with the fact that I'm already requiring all users of this system to call AD_CleanUnit(whichUnit) before every unit is removed.
This includes units that die and are then removed.
Why? Because it means that I can have much simpler and faster execution and code. I did say this was not for Jass users that couldn't cover their own tracks.
 

Cohadar

master of fugue
Reaction score
209
Yeah fine.
I just don't like stuff that are harder to use that they need to be.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • 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 The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      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