How to make a seemingly simple custom ability

imakunee

New Member
Reaction score
4
Try using dying unit instead of triggering unit in removedeaddummy.

Noofdummy doesn't need to be set to 0 and it's adding up so fast because you have your trigger adding 1 to it every time the trigger is called for every unit in sprayedunits. I think you can use set noofdummy = Number of units in sprayedunits. Then you don't really need that loop at all.

Add Clear Parent Hashtable hashtable to the final else in faeriefirehash. That will clean out all the values in your hashtable that may cause some lag if they build up.

I'm not sure what's causing those weird lag issues. o.o But if you make the above changes and it still lags we'll have to get someone better at triggers than I am. I'm fairly new too. But don't feel bad! This looks great from what I see. You've really advanced fast into trigger making. I just keep waiting for someone to jump in here and laugh at us then link this spell someone else made or tell us an unbelievably easy way to do it. haha >.>
 

unpro

New Member
Reaction score
1
Omg.. I can't believe I totally messed up the debugging part, I guess my brain had an information overflow error...

I followed your suggestions and below is the modified trigger. In addition, I remade the debugging portion, hope I didn't mess it up this time:)

Trigger:
  • stickyspray
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Sticky spray
    • Actions
      • Wait 0.10 seconds
      • Unit - Create 1 dummyani (Custom Campaign) for (Triggering player) at (Position of (Triggering unit)) facing 0.00 degrees
      • Unit - Order (Last created unit) to Neutral Alchemist - Healing Spray ((Position of (Triggering unit)) offset by 400.00 towards (Facing of (Triggering unit)) degrees)
      • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
      • Set Point1 = (Position of (Triggering unit))
      • Set Real1 = (Facing of (Triggering unit))
      • Set Unitgp = (Units within 550.00 of Point1 matching (((Owner of (Matching unit)) Not equal to Player 9 (Gray)) and (((Owner of (Triggering unit)) Not equal to Player 10 (Light Blue)) and ((Unit-type of (Triggering unit)) Not equal to dummy (Custom Campaign)))))
      • Unit Group - Pick every unit in Unitgp and do (Actions)
        • Loop - Actions
          • Set Point2 = (Position of (Picked unit))
          • Set Real2 = (Angle from Point1 to Point2)
          • If (Real2 Less than 0.00) then do (Set Real2 = (Real2 + 360.00)) else do (Do nothing)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Real2 Less than (Real1 + 40.00)
              • Real2 Greater than (Real1 - 40.00)
            • Then - Actions
              • Unit - Create 1 dummy (Custom Campaign) for (Owner of (Picked unit)) at (Position of (Picked unit)) facing 0.00 degrees
              • Unit - Order (Last created unit) to Night Elf Druid Of The Talon - Faerie Fire (Picked unit)
              • Unit - Order (Last created unit) to Human Sorceress - Slow (Picked unit)
              • Unit - Add a 0.50 second Generic expiration timer to (Last created unit)
              • Unit - Create 1 dummyshade for (Triggering player) at (Position of (Picked unit)) facing 0.00 degrees
              • Unit - Add a 5.00 second Generic expiration timer to (Last created unit)
              • Unit Group - Add (Last created unit) to sprayedunits
              • Hashtable - Save Handle Of(Last created unit) as 0 of (Key (Last created unit)) in hashtable
              • Hashtable - Save Handle Of(Picked unit) as 1 of (Key (Last created unit)) in hashtable
              • Set noofdummy = (noofdummy + 1.00)
              • Trigger - Turn on faeriefirehash <gen>
              • Trigger - Turn on removedeaddummy <gen>
              • Custom script: call RemoveLocation (udg_Point2)
            • Else - Actions
              • Custom script: call RemoveLocation (udg_Point2)
      • Custom script: call RemoveLocation (udg_Point1)
      • Custom script: call DestroyGroup (udg_Unitgp)

Trigger:
  • faeriefirehash
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (sprayedunits is empty) Equal to False
        • Then - Actions
          • Unit Group - Pick every unit in sprayedunits and do (Actions)
            • Loop - Actions
              • Set sprayedtar = (Load 1 of (Key (Picked unit)) in hashtable)
              • Set sprayedpoint = (Position of sprayedtar)
              • Unit - Move (Picked unit) instantly to sprayedpoint
              • Custom script: call RemoveLocation (udg_sprayedpoint)
        • Else - Actions
          • Custom script: call DestroyGroup (udg_sprayedunits)
          • Hashtable - Clear hashtable
          • Trigger - Turn off removedeaddummy <gen>
          • Trigger - Turn off (This trigger)

Trigger:
  • removedeaddummy
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Dying unit) Equal to (Load 0 of (Key (Dying unit)) in hashtable)
    • Actions
      • Unit Group - Remove (Triggering unit) from sprayedunits
      • Set noofdummy = (noofdummy - 1.00)

Trigger:
  • debugger
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Sticky spray
    • Actions
      • For each (Integer A) from 1 to 10, do (Actions)
        • Loop - Actions
          • Floating Text - Create floating text that reads (String(noofdummy)) at (Center of (Playable map area)) with Z offset 0.00, using font size 50.00, color (100.00%, 0.00%, 100.00%), and 0.00% transparency
          • Floating Text - Change (Last created floating text): Disable permanence
          • Floating Text - Change the lifespan of (Last created floating text) to 0.50 seconds
          • Floating Text - Change the fading age of (Last created floating text) to 0.50 seconds
          • Wait 0.50 seconds


I did some testing. If the debugger is to be trusted, the following occurs.
First cast: 1 dummyshade produced, destroyed after 5 seconds, shows destroying trigger is working.
Second cast: 2 dummyshades produced, not destroyed.:confused:
Subsequent casts: Counter shows 5, 9, 16, 28 and so on. Lag on each casts sets in after 200-300 or so.
Casts on a different unit: Counter increases by 1, 2, 5 and so on, causing no lag until it hits the same problem as the first unit.

I re-read the trigger over and over again and still don't see how and why more and more dummyshades are produced even when casts are separated by over 10 seconds each. I have a suspicion though, is it because of the "leak-fixing" custom scripts on the faeriefirehash trigger? Because I made them myself and I'm not too sure it is fully correct.

Another weird thing is why is the lag unit-specific? Sounds like too many units, dummy and actual, on the spot. But I've added a expiration timer for all dummy units...
 

imakunee

New Member
Reaction score
4
In setstickyspray when you set up unitgp you use triggering unit instead of matching unit a couple of times. I just noticed it myself. XD

In removedeaddummy you still use triggering unit instead of dying unit when removing it from the unit group.

That's all I see for now.
 

unpro

New Member
Reaction score
1
The words "careless mistake" I heard so many times in school has came back to haunt me T.T

And now... it works so much better. The counter doesn't increase exponentially anymore since the restricting criteria is correct. Lag is eliminated, or at least reduced to a much lesser amount. However, there is still 1 more bug left to quash.

The first cast makes the counter increase by 1, and reduces back to 0 after the 5 seconds. However, subsequent casts cause the counter to rise by 1 but not drop after 5 seconds, whether multiple casts or casts on a different unit.

A weird exception is when I cast multiple times in succession before the first spell finishes. This will cause the counter to rise and fall in line with the dummy unit spawning and expiring. This correct effect will end once all instances of the spell end. After that, the aforementioned bug situation occurs.


So I went to create a debugger to display when faeriefirehash trigger ends. It showed an interesting result. On first cast, the trigger ends after the 5 seconds, probably around 5-6 seconds after the cast. On subsequent casts, the trigger ends immediately!
Doesn't make sense since the condition sees whether sprayedunits(unitgroup) is empty, but there is an addition to sprayedunits before this trigger is even turned on. Also, first cast works properly. Is it because Trigger - Turn off(This trigger) in faeriefirehash doesn't work correctly?
 

imakunee

New Member
Reaction score
4
It's because sprayedunits gets destroyed but never recreated. If you destroy a unit group you can't add units to it anymore.

To bypass that problem I'd try removing the part that adds the dummyshades to sprayedunits. Instead, in the beginning of faeriefirehash, set sprayedunits = units of type dummyshade. Then move destroying sprayed units to always happen. (just move it to the very bottom of the trigger, outside of the if statement) That way each time faeriefirehash is called sprayedunits is created and destroyed no matter what.
 

unpro

New Member
Reaction score
1
Trigger:
  • faeriefirehash
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
      • Set sprayedunits = (Units in (Playable map area) matching ((Unit-type of (Triggering unit)) Equal to dummyshade))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (sprayedunits is empty) Equal to False
        • Then - Actions
          • Unit Group - Pick every unit in sprayedunits and do (Actions)
            • Loop - Actions
              • Set sprayedtar = (Load 1 of (Key (Picked unit)) in hashtable)
              • Set sprayedpoint = (Position of sprayedtar)
              • Unit - Move (Picked unit) instantly to sprayedpoint
              • Custom script: call RemoveLocation (udg_sprayedpoint)
        • Else - Actions
          • Hashtable - Clear hashtable
          • Trigger - Turn off removedeaddummy <gen>
          • Floating Text - Create floating text that reads faeriefirehash ende... at (Center of (Playable map area)) with Z offset 10.00, using font size 25.00, color (100.00%, 0.00%, 100.00%), and 0.00% transparency
          • Floating Text - Change (Last created floating text): Disable permanence
          • Floating Text - Change the lifespan of (Last created floating text) to 0.50 seconds
          • Floating Text - Change the fading age of (Last created floating text) to 0.50 seconds
          • Trigger - Turn off (This trigger)
      • Custom script: call DestroyGroup (udg_sprayedunits)


Is the first line made wrongly? Because this also causes faeriefirehash to end instantly as well, on the first cast too no less.

I did some variations with corresponding tests:

Previous method with leak-removing: Previous post
Previous method w/o leak-removing: Faeriefirehash trigger always end 6-8 seconds after spell ends, counter doesn't return to 0.
Current method with leak-removing: Faeriefirehash trigger always end instantly, counter doesn't return to 0.
Current method without leak-removing: Same as above.

At this point, I almost feel frustrated enough to live with the leak.. :banghead:
 

WolSHaman

knowledgeably ignorant
Reaction score
51
This trigger will do exactly what you want. Well, it's a series of triggers.
http://www.thehelper.net/forums/showthread.php?t=88985
This is a tutorial for detecting damage made by flare.

Now, create a trigger for the ability, and make the event the unit casting the ability, and have it based off of channel. Then, create a dummy unit SPECIFICALLY for this ability, and have this dummy unit have your breath of fire ability. have the special dummy cast the ability, and have a trigger with no conditions. Instead, use Flare's damage detect system to add the events, and have a condition checking the unit-type of the unit dealing damage. If the unit-type is the unit that casts the breath of fire ability, THEN it adds the buffs with a generic dummy unit. I'd post a trigger but I'm not at the world editor, I can post later if this doesn't make sense.
 

imakunee

New Member
Reaction score
4
It's using triggering unit instead of matching unit again unpro. Gotta watch those. >.>
And the floating text leaks with center of playable map area but that's just testing text so it's kk.
 

unpro

New Member
Reaction score
1
@imakunee
I changed it to matching but the same bug still occurs. Faeriefirehash still ends instantly with or without leak-fixing triggers. Another weird thing I observed is that when repeatedly and randomly casting, sometimes faeriefirehash ends randomly instead of instantly, like 2, 4, 5 seconds into the cast :confused:.

@WolSHaman
Wouldn't importing a whole damage detection system for one spell make it laggier as compared with 1 leaking trigger? Nevertheless, I'll give it a try, will edit in results later. Thanks for the suggestion.

EDIT: My attempt was cut short. When I clicked on the map file to download it, I get

We're sorry, but you may not access the requested page. Possible causes are:

* only selected computers are allowed to access this resource
* the directory is not freely accessible
* the document you're trying to access doesn't exist and the server can't provide alternative content

We apologize for the inconvenience.

If you're entitled to access this document and the problem persists, you may contact us in order to get your issue resolved.

Any mirrors? While we are at this, how do you transfer many stuff from 1 map to another? Like objects, triggers and terrain without having to open copy close open paste close open copy close open paste close etc.
 

Joccaren

You can change this now in User CP.
Reaction score
54
Put it into a folder (If they are triggers) then copy the folder
 

unpro

New Member
Reaction score
1
I searched for damage detection systems but the 2 recent ones are very heavy into JASS so I'm unable to utilize them. Anyone knows a more GUI-friendly version? Or a fix for the faeriefirehash trigger?
 

unpro

New Member
Reaction score
1
I found Weep's damage detection system and am trying it. However, faeriefirehash still ends instantly. Furthermore, I just remembered something. Locust makes units untouchable by the Pick every unit function... Does it also stop the dummy units from being placed into a unit group variable?

So, is there a workaround for the tracking dummyshade?

Trigger:
  • stickyspraydd
    • Events
      • Game - GDD_Event becomes Equal to 0.00
    • Conditions
      • GDD_Damage Less than 10.00
    • Actions
      • Unit - Create 1 dummy (Custom Campaign) for (Owner of GDD_DamagedUnit) at (Position of (Picked unit)) facing 0.00 degrees
      • Unit - Order (Last created unit) to Night Elf Druid Of The Talon - Faerie Fire GDD_DamagedUnit
      • Unit - Order (Last created unit) to Human Sorceress - Slow GDD_DamagedUnit
      • Unit - Add a 0.50 second Generic expiration timer to (Last created unit)
      • Unit - Create 1 dummyshade for (Owner of GDD_DamageSource) at (Position of GDD_DamagedUnit) facing 0.00 degrees
      • Unit - Add a 5.00 second Generic expiration timer to (Last created unit)
      • Hashtable - Save Handle Of(Last created unit) as 0 of (Key (Last created unit)) in hashtable
      • Hashtable - Save Handle OfGDD_DamagedUnit as 1 of (Key (Last created unit)) in hashtable
      • Set noofdummy = (noofdummy + 1.00)
      • Trigger - Turn on faeriefirehash <gen>


Trigger:
  • faeriefirehash
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Remove all units from sprayedunits
      • Set sprayedunits = (Units in (Playable map area) matching ((Unit-type of (Matching unit)) Equal to dummyshade))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (sprayedunits is empty) Equal to False
        • Then - Actions
          • Unit Group - Pick every unit in sprayedunits and do (Actions)
            • Loop - Actions
              • Set sprayedtar = (Load 1 of (Key (Picked unit)) in hashtable)
              • Set sprayedpoint = (Position of sprayedtar)
              • Unit - Move (Picked unit) instantly to sprayedpoint
              • Custom script: call RemoveLocation (udg_sprayedpoint)
        • Else - Actions
          • Hashtable - Clear hashtable
          • Floating Text - Create floating text that reads faeriefirehash ende... at (Center of (Playable map area)) with Z offset 10.00, using font size 25.00, color (100.00%, 0.00%, 100.00%), and 0.00% transparency
          • Floating Text - Change (Last created floating text): Disable permanence
          • Floating Text - Change the lifespan of (Last created floating text) to 0.50 seconds
          • Floating Text - Change the fading age of (Last created floating text) to 0.50 seconds
          • Trigger - Turn off (This trigger)
 

Weep

Godspeed to the sound of the pounding
Reaction score
400
Furthermore, I just remembered something. Locust makes units untouchable by the Pick every unit function... Does it also stop the dummy units from being placed into a unit group variable?
Nope, and you're only partially right. Locust units won't be found by any "Pick every unit in region/range" function...they can still be picked:

So, is there a workaround for the tracking dummyshade?
Use Units Of Type, not Units In Region Matching Condition. Alternately, add them to the group when created, which I'll mention later.

Further notes:

Unit - Create 1 dummy (Custom Campaign) for (Owner of GDD_DamagedUnit) at (Position of (Picked unit)) facing 0.00 degrees
First, that would leak a point, you'd need to save (Position of (Picked Unit)) to a variable. Second, there's no Picked Unit in this trigger, so there won't be any such point and the unit creation will fail.

Also, do you really want it to be created for the same player as the damaged unit? (That's fine, as long as your spells can target friendly units.)

Unit - Create 1 dummyshade for (Owner of GDD_DamageSource) at (Position of GDD_DamagedUnit) facing 0.00 degrees
Point leak.

Unit Group - Remove all units from sprayedunits
Set sprayedunits = (Units in (Playable map area) matching ((Unit-type of (Matching unit)) Equal to dummyshade))
As noted above, use Units Of Type, or better yet, add the dummyshade to that unit group in the previous trigger instead of creating a unit group in this trigger (with Unit Group - Add (Last Created Unit) to sprayedunits).

In either case, you wouldn't need or want that group clear action above. (If you still create a unit group like you are now, you'd need to add Custom Script: call DestroyGroup(udg_sprayedunits) at the end of the trigger.)

Else - Actions
Hashtable - Clear hashtable
I haven't used hashtables at all (due to Mac World Editor issues) but I read something about clearing a hashtable rendering it unusable. I don't know if that's true.

You should move the action Unit Group - Remove all units from sprayedunits into this Else section, if you decide to change to the add-shade-to-group method.
 

unpro

New Member
Reaction score
1
Ok, changed it to Units of Type.
Fixed the point Leak.
Yea, the dummy can cast on friendly units. I changed it to this way because I couldn't get the dummy to cast on hostile invisible units, even with 3 kinds of truesight.

As noted above, use Units Of Type, or better yet, add the dummyshade to that unit group in the previous trigger instead of creating a unit group in this trigger (with Unit Group - Add (Last Created Unit) to sprayedunits).

My original trigger was that, but it requires a third trigger that removes the dummyshade from the unit group when it dies. And I don't know WE well enough to know whether expiration timer is compatible with detecting dying units, so I switched to a more reliable sounding method(actually it was a suggestion by imakunee).

As regard to the clear unit group, if I set unit a, b to unit group, and I set unit c,d to the same unit group afterward, will unit a and b be in the unit group? Wasn't too sure about that so I just cleared it.

I have no idea about clearing the hashtable, imakunee said
"Add Clear Parent Hashtable hashtable to the final else in faeriefirehash. That will clean out all the values in your hashtable that may cause some lag if they build up."

Tests: dummyshades still don't follow the affected unit. However, they do spawn and despawn. The best thing is faeriefirehash ends correctly, which is after the 5 seconds is up(it takes 6-8 seconds), rather than instantly like it did for quite a while.


Further tests with clear parent hashtable removed: SUCCESS! imakunee~~
arghj.gif
joking, you've been a great help too:)

Trigger:
  • stickyspraydd
    • Events
      • Game - GDD_Event becomes Equal to 0.00
    • Conditions
      • GDD_Damage Less than 10.00
    • Actions
      • Set temppoint = (Position of GDD_DamagedUnit)
      • Unit - Create 1 dummy (Custom Campaign) for (Owner of GDD_DamagedUnit) at temppoint facing 0.00 degrees
      • Unit - Order (Last created unit) to Night Elf Druid Of The Talon - Faerie Fire GDD_DamagedUnit
      • Unit - Order (Last created unit) to Human Sorceress - Slow GDD_DamagedUnit
      • Unit - Add a 0.50 second Generic expiration timer to (Last created unit)
      • Unit - Create 1 dummyshade for (Owner of GDD_DamageSource) at temppoint facing 0.00 degrees
      • Unit - Add a 5.00 second Generic expiration timer to (Last created unit)
      • Hashtable - Save Handle Of(Last created unit) as 0 of (Key (Last created unit)) in hashtable
      • Hashtable - Save Handle OfGDD_DamagedUnit as 1 of (Key (Last created unit)) in hashtable
      • Trigger - Turn on faeriefirehash <gen>
      • Custom script: call RemoveLocation (udg_temppoint)


Trigger:
  • faeriefirehash
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Remove all units from sprayedunits
      • Set sprayedunits = (Units of type dummyshade)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (sprayedunits is empty) Equal to False
        • Then - Actions
          • Unit Group - Pick every unit in sprayedunits and do (Actions)
            • Loop - Actions
              • Set sprayedtar = (Load 1 of (Key (Picked unit)) in hashtable)
              • Set sprayedpoint = (Position of sprayedtar)
              • Unit - Move (Picked unit) instantly to sprayedpoint
              • Custom script: call RemoveLocation (udg_sprayedpoint)
        • Else - Actions
          • Trigger - Turn off (This trigger)
      • Custom script: call DestroyGroup (udg_sprayedunits)
 

Weep

Godspeed to the sound of the pounding
Reaction score
400
My original trigger was that, but it requires a third trigger that removes the dummyshade from the unit group when it dies. And I don't know WE well enough to know whether expiration timer is compatible with detecting dying units
It is; a unit will trigger a death event when its expiration timer runs out.

By the way, the best way to learn whether things like that work is to try it. ;)

As regard to the clear unit group, if I set unit a, b to unit group, and I set unit c,d to the same unit group afterward, will unit a and b be in the unit group?
If by "set unit to a group" you mean add it to the group, then a and b will still be in it. Units will stay in a group until removed from the group, removed from the game (eg. by dying then decaying), or the group is cleared (or if the group is destroyed altogether with DestroyGroup, of course). Keep in mind, however, that using Set <Variable> to Units... actually creates a new unit group in memory, then sets that variable to point to it, so the units you previously added won't appear to be in the group, because the variable has been set to a new, different group. (That's also why you get memory leaks without using DestroyGroup if you're not just adding and removing units.)
 

unpro

New Member
Reaction score
1
Oh man, I tried what you said, which was my original method, and had the faeriefirehash end instantly after cast. After mulling over the trigger for over 15 mins, I gave up in frustration and started to detail it out here. Then I realised I forgot to delete the "Custom script: call DestroyGroup (udg_sprayedunits)"...


Well finally, this has a happy ending after more than a month! Thank you to all who participated in this thread and given help in any way, especially imakunee. Thanks to Weep for his Damage Detection system, it rocks and you should try it!




Keywords for search: AOE, cone, cone shape, cone-shaped, invisible, permanent invis, tracking, shadow, faerie fire
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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