| 03-17-2008, 12:41 PM | #1 |
SADS - Simple Attack Detect System Why is it simple? - Only uses 1 trigger for whole system to run, unlike most attack detect system out there that needs one trigger per unit in order to function. - Guaranteed no leak! Even with RemoveUnit() functions that is known buggy with other attack detect system around. Requires: - Jass knowldege, might need some vJass knowledge but that isn't really matter if you follow the step by step rule. - vJass compiler. Warning! This is a alpha version, in other word, it is not totally complete, I'm just releasing it to get some feedbacks around before I move deeper into adding orb functions and other Attack-Detect-Engine related functions. Use this in your map at your own risk! System Code JASS:library SADS initializer InitSADS //*************************************************************************** //* Simple Attack Detect System * //* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ * //* Uses only one global trigger and one global group to run this whole * //* unlike other ADS out there where you needs one (some even need 2) * //* trigger per unit. It's simple! * //* * //*************************************************************************** //Configuration globals private constant integer DetectId = 'A000' //Based off slow poison put in spellbook private constant integer DetectBuff1 = 'Bspo' //Slow Poison buff1 private constant integer DetectBuff2 = 'Bssd' //Slow Poison buff2 private constant real RefreshInterval = 120 //120seconds endglobals //Global onDamage function, this function will run whenever a unit takes damage function OnDamageFunction takes unit attacker, unit attacked, boolean IsAttack, real Damage returns nothing local texttag t if Damage>0 then set t=CreateTextTag() call SetTextTagPos(t,GetUnitX(attacked)+GetRandomReal(-50,50),GetUnitY(attacked)+GetRandomReal(-50,50),0) call SetTextTagColor(t,255,255,255,255) if IsAttack then call SetTextTagText(t,I2S(R2I(Damage))+"|c00ff0000!|r",0.025) else call SetTextTagText(t,I2S(R2I(Damage))+"|c000000ff!|r",0.025) endif call SetTextTagPermanent(t,false) call SetTextTagFadepoint(t,0.1) call SetTextTagVelocity(t,0,0.02) call SetTextTagLifespan(t,1.5) endif set t=null endfunction //*************************************************************************// //* *// //* SADS code *// //* *// //*************************************************************************// function interface SADS_Orbs takes unit damager, unit damaged, real damage returns nothing globals boolean SADS_IsAttack unit SADS_Attacker unit SADS_Attacked real SADS_Damage private timer Ti private trigger Tr private group Gr private code Co private integer orb_n = 0 private SADS_Orbs array orb_f private unit array orb_u endglobals //=========================================================================== // orb coding //=========================================================================== function RegisterOrbFunction takes unit u, SADS_Orbs f returns nothing set orb_u[orb_n]=u set orb_f[orb_n]=f set orb_n=orb_n+1 endfunction function RemoveRegisteredOrb takes unit u, SADS_Orbs f returns nothing local integer n = orb_n loop set n=n-1 exitwhen n<0 if orb_u[n]==u and orb_f[n]==f then if n!=orb_n-1 then set orb_u[n]=orb_u[orb_n-1] set orb_f[n]=orb_f[orb_n-1] endif set orb_n=orb_n-1 endif endloop endfunction function ClearRegisterdOrb takes unit u returns nothing local integer n = orb_n loop set n=n-1 exitwhen n<0 if orb_u[n]==u then if n!=orb_n-1 then set orb_u[n]=orb_u[orb_n-1] set orb_f[n]=orb_f[orb_n-1] endif set orb_n=orb_n-1 endif endloop endfunction //=========================================================================== // ADS coding //=========================================================================== private function OnDamage takes nothing returns nothing local unit u=GetTriggerUnit() local unit a=GetEventDamageSource() local boolean b=false local real dmg = GetEventDamage() local integer n if GetUnitAbilityLevel(u,DetectBuff1)>0 then call UnitRemoveAbility(u,DetectBuff1) set b=true elseif (GetUnitAbilityLevel(u,DetectBuff2)>0) then call UnitRemoveAbility(u,DetectBuff2) set b=true endif call OnDamageFunction(a,u,b,dmg) if b then set n=orb_n loop set n=n-1 exitwhen n<0 if a==orb_u[n] then set SADS_Attacker = a set SADS_Attacked = u set SADS_Damage = dmg call orb_f[n].execute(a,u,dmg) endif endloop endif set u=null set a=null endfunction private function InitUnit takes unit u returns nothing call UnitAddAbility(u,DetectId) call TriggerRegisterUnitEvent(Tr,u,EVENT_UNIT_DAMAGED) call GroupAddUnit(Gr,u) endfunction private function Refresh_child takes nothing returns nothing call TriggerRegisterUnitEvent(Tr,GetEnumUnit(),EVENT_UNIT_DAMAGED) endfunction private function Refresh takes nothing returns nothing call TriggerClearActions(Tr) call DestroyTrigger(Tr) set Tr=CreateTrigger() call TriggerAddAction(Tr,Co) call ForGroup(Gr, function Refresh_child) endfunction //=========================================================================== // Initialization //=========================================================================== private function OnEnter takes nothing returns nothing call InitUnit(GetTriggerUnit()) endfunction private function InitSADS takes nothing returns nothing local trigger t = CreateTrigger() local region r = CreateRegion() local unit u local integer i = 15 local group g = CreateGroup() loop //disable dummy spellbook call SetPlayerAbilityAvailable(Player(i),DetectId,false) set i=i-1 exitwhen i<0 endloop set Ti=CreateTimer() set Tr=CreateTrigger() set Gr=CreateGroup() set Co=function OnDamage call TriggerAddAction(Tr,Co) call GroupEnumUnitsInRect(g,GetWorldBounds(),null) loop set u=FirstOfGroup(g) exitwhen u==null call GroupRemoveUnit(g,u) call InitUnit(u) endloop call DestroyGroup(g) call TimerStart(Ti,RefreshInterval,true,function Refresh) call RegionAddRect(r,GetWorldBounds()) call TriggerRegisterEnterRegion(t,r,null) call TriggerAddAction(t, function OnEnter) set t=null set r=null set g=null endfunction endlibrary |
| 03-17-2008, 05:08 PM | #2 | |
bayan Nothing new or nonstandart, just an other clone. Quote:
oh lol |
| 03-18-2008, 04:30 AM | #3 |
well simply achiving things will different method, why not? The one trigger/unit is memory eating monster when you have ~300 units in your map |
| 03-18-2008, 11:30 AM | #4 |
No leak? Oh really? Unit event leaks. Memory hogging is a small price to pay for memory leakage on every unit, particularly given that it will cause the handle indexes to increment a lot, which can be bad for H2S usage. |
| 03-18-2008, 12:49 PM | #5 |
1) Never null texttags, this may cause hurge problems if texttags meet 99limit. 2) There is many memory control functions, to remove orbs better use one of them (or ever hardcoded inside vJass struct allocator) 3) call TriggerClearActions(Tr) is HARMFULL function never use it, its just unplug events without destroying them. |
| 03-18-2008, 03:28 PM | #6 | |
Quote:
-where the hell i use H2S? Diod: 1) the text tag are just a test for the damage detection to work... it is not the part of the system anyway... 2) I don't quite what you trying to say here, can you explain more pls? 3) are you saying that event leaks? well i think i can do something on that... Go here for some information about the SADS... I did some research before making this map okay... ain't making it for the sake of making it... |
| 03-18-2008, 04:03 PM | #7 |
Don't we already have quite a few systems in the resource database for this sort of thing? We really shouldn't have too much overlap in there, it gets a bit repetitive. And he mentioned H2S in the event it were used in a map this is used in. By allocating hundreds of events, you're spiking the handle index count in the map, which could potentially lead to problems if you happen to use H2S or a few other things. I don't really think there's a better way to approach this type of system, though. I'd much rather have a unit damage event leaking than intercept the attack trigger event and try to clock if the projectile/attack hits the target or any of the other alternatives. (I've tried numerous) And yes, TriggerClearActions, ResetTrigger, and so forth are unstable and cause handle indexing failures relatively reliably and quickly. It's unfortunate, it would be really useful to be able to reuse triggers like that, but in all of the times I've tried it, it's only resulted in map failure elsewhere. (That's not good) |
| 03-18-2008, 04:17 PM | #8 | |
if the problem is at the unit handle, codahar discovered that: Quote:
// bout the TriggerClearAction, I may or may not use those, what I did is just destroy the trigger every t seconds, I'm just calling those functions for... safety precaution (and didn't know that it cause harm instead). I though it was safe to use since Vex is using it in the Caster System. Oh well... JASS:function CS_KillTrigger takes trigger t returns nothing if (t!=null) then call TriggerRemoveAction(t,GetAttachedTriggerAction(t,"ac")) call CleanAttachedVars(t) call DestroyTrigger(t) endif endfunction |
| 03-18-2008, 04:19 PM | #9 |
That seems highly improbable, since in my map I register two damage events to a single unit and both seem to work perfectly fine. |
| 03-18-2008, 04:51 PM | #10 | |
Quote:
Refreshing the trigger should (and is believed to) clear up the memory leaks, but that solution has the problem that it is much more likely to create lag spikes, since you're recreating all the events simultaneously. Yeah your system doesn't actually leak in the long term, but the benefits of slight smaller memory usage (which deteriorates the further apart you refresh it) are likely to be very heavily outweighed by the lag from refreshing (and hence the reason we don't already use it). |
| 03-19-2008, 03:40 PM | #11 |
hmph i just did some experiment there, i changed the trigger refresh interval to 0.5 second and added more units in the map (up to 235 units). The result is that I can barely notice the lag spike you spoke of, well it might differs from different com, I'm attaching the test map below please tell me if there's any lag spike with and without the SADS |
| 03-19-2008, 05:52 PM | #12 |
The problem isn't on a test map, but on a big map with lots of other stuff going on. Your system will never be as efficient as other methods we already have. The necessity to recreate a very large trigger often is not a price worth paying for the possibility of shaving off less than a MB of memory usage. Given that, I see no reason why anyone would choose this over others; it simply wouldn't add anything to the data base. |
| 03-29-2008, 05:09 PM | #13 |
I think my biggest complaint with this system is that it really doesn't offer anything new to users. We have at least 4 systems already in the database and scattered across the site that cover every aspect of damage management. Really, I don't think we need another at this point, so I doubt there's any reason to pursue it further. I could move this to the trigger forum so searches and the like will pick it up in the event someone wants to see it. Also, why in the world are you using a code variable? |
| 03-30-2008, 10:53 AM | #14 | |
Quote:
btw about the code... I was testing something before this and forget to remove it lol... just wondering whats wrong with code variable anyway O_o" |
