[Solved] Trigger efficiency .. Unit groups

Status
Not open for further replies.
Level 5
Joined
Mar 30, 2006
Messages
60
Hi,

I have a pretty general question: What's the best option to create a custom-buff system that still interacts with regular WC3 dispel spells?

I am working on an altered melee map mod system which adds additional units/abilities/heroes to existing races, aswell as adding 2 entirely new races.

To make use of customized abilities and units I imported quite a lot of custom models, custom icons and spell effects. Which ofcourse make the map more performance hungry. That's why I want to make everything as optional as possible to avoid crashes.

To the system I'm currently using:

I mainly rely on hidden spellbooks, which contain custom buff auras to give the desired effects. In the following ability the spellbook contains a crit strike ability and the item armour buff ability +3.

The spellbook is applied with a dummy spell based on channel. After the spell is cast on a unit it's moved into a pre defined unit group.
I have a total of 20 unit groups in which buff-affected units are moved when they receive a spell.

The units that are in those groups are periodically checked for having the buff in place. If not the spellbook is removed and the unit aswell from the group. This is to make sure that the buffs to not extend over dispel abilities.

I know that this system works well enough for a low amount of ability triggers, but since I add 2 custom races (with 10 heroes, ~ 25 units, ~30 new techs, icons, custom models, spell effects etc), 5 new heroes for the existing races + 1 neutral hero + new neutral units, all with custom enhanced spells I realised that this system takes quite some performance through sheer numbers.

To make this more clear to see for everyone I'll include some trigger examples :

Example: Molten Armour
Adds critical strike + armour to the target unit. Dispelable by regular anti magic spells. (Spell theft, abolish magic etc.)

  • Molten Armour
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Molten Armour (neuneu)
    • Actions
      • Set TempUnit = (Target unit of ability being cast)
      • Animation - Change TempUnit's vertex coloring to (100.00%, 60.00%, 45.00%) with 10.00% transparency
      • Unit Group - Add TempUnit to MoltenGroup
      • Unit - Add Molten Armour Spellbook to TempUnit
What I'd like to know is following: is it better to use individual spellbooks for units and add those via trigger, or give all units one hidden spellbook and add/remove the abilities via custom text trigger to the spellbook?

Next part, Unit group trigger:
  • Alle GUI Trigger
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
  • [...]
    • Unit Group - Pick every unit in MoltenGroup and do (Actions)
      • Loop - Actions
        • Set TempUnit = (Picked unit)
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (TempUnit has buff Molten Armour ) Equal to False
          • Then - Actions
            • Unit - Remove Molten Armour Spellbook from TempUnit
            • Animation - Change TempUnit's vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
            • Unit Group - Remove TempUnit from MoltenGroup
          • Else - Actions
  • [...]
This trigger fires every 0.20secs of game time and contains all unit groups in this kind.

It seems like this is getting pretty performance heavy once more than 4 players participate in the game and spells start hitting the field.

I'd just like to know whether there's an easier or faster version for my system possible. I ofcourse use custom text to remove points and other leaking objects, and define units/spells/integers in variables instead of using the GUI functions to save performance. Example:

  • Ambush
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Ambush (Farstrider)
    • Actions
      • Set TempUnit = (Triggering unit)
      • Set TempPoint = (Position of TempUnit)
      • Set TempAbilityLvl = (Level of Ambush (Farstrider) for TempUnit)
      • Set Temp_unitgroup = (Units within (((Real(TempAbilityLvl)) x 75.00) + 175.00) of TempPoint matching ((((Matching unit) belongs to an enemy of (Owner of TempUnit)) Equal to False) and ((((Matching unit) is A ground unit) Equal to True) and ((((Matching unit) is Magic Immune) Equa
      • Sound - Play SylvanasWhat3 <gen> at 100.00% volume, attached to TempUnit
      • Sound - Destroy (Last played sound)
      • Unit Group - Pick every unit in Temp_unitgroup and do (Actions)
        • Loop - Actions
          • Set Temp_Unit = (Picked unit)
          • Unit Group - Add Temp_Unit to AmbushGroup
          • Unit - Add Ambush (Units) to Temp_Unit
          • Unit - Set level of Ambush (Units) for Temp_Unit to TempAbilityLvl
          • Unit - Order Temp_Unit to Orc Blademaster - Wind Walk
          • Unit - Remove Ambush (Units) from Temp_Unit
      • Custom script: call RemoveLocation( udg_TempPoint )
Another example of a spell containing a dummy unit for casting a custom ability:

  • Flameshield
    • Events
    • Unit - A unit Starts the effect of an ability
    • Conditions
    • (Ability being cast) Equal to Flameshield
    • Actions
    • Set TempUnit = (Triggering unit)
    • Set Temp_point = (Position of TempUnit)
    • Unit - Create 1 Dummy for (Triggering player) at Temp_point facing (Facing of TempUnit) degrees
    • Set Temp_Unit2 = (Last created unit)
    • Unit - Add a 2.00 second Generic expiration timer to Temp_Unit2
    • Unit - Add Flameshield (Armour) to Temp_Unit2
    • Unit - Set level of Flameshield (Armour) for Temp_Unit2 to (Level of Flameshield for TempUnit)
    • Unit - Order Temp_Unit2 to Human Priest - Inner Fire (Target unit of ability being cast)
    • Custom script: call RemoveLocation( udg_Temp_point )
(question here: Better to create pre defined dummies that already have all the abilities? Or make one dummy unit that receives the spell via trigger? I have ~ 60 triggers that work like the one I posted above, with the same structure. Is it possible to reduce the amount of triggers to a more generic system like 1 trigger for allied buffs, enemy debuffs, and AoE/damage abilities? So I can add multiple spells to a dummy in a single trigger function? And if so, how can I do that? Pre define spells in variables and use a loop or smth?)

I hope we can get a productive discussion going. In case someone wants to teach me a bit of custom triggering in JASS I'm of course open for that, but I am noob "real" scripting :D

Greetings
 
Last edited:
Level 24
Joined
Aug 1, 2013
Messages
4,658
Buff auras dont work with dispels, dispels dont remove the buffs from auras because the unit is supposed to regain the buff immediately.

My buff system has a function that can remove the buffs, but that is the closest you can get to.
WC3 is bad in having the default stuff working with triggered stuff... that is why I code everything.

([TRIGGER][/TRIGGER] tags should be used for GUI Triggers.)
 
Level 5
Joined
Mar 30, 2006
Messages
60
edit thx for the trigger /trigger tip. I edited my main post.

My buff system works fine ingame. The spellbooks are attached to the buff from the casting ability. If the buff from the regular ability is dispelled or runs out the spellbook is removed with the unit group trigger.

For clarification: My custom spell uses a dummy. The dummy uses an ability that has a timed buff. For example I use inner fire for that.
The target unit is then given the spellbook and moved into the unit group which checks if the target unit has the buff from inner fire every 0.2 seconds. If the buff is removed (because of dispel or time runs out) the ability effects that I added with the spellbook are removed. the unit also is removed from the group.

In short:
wc3 unit uses ability like "molten Shield" (channel/dummy ability)
-> trigger starts that creates a dummy
-> dummy gets a spell ability that casts a buff on the target unit (Molten shield)
-> target unit is moved in unit group
-> target unit gets spell book with the abilities. which is in this case Critical Strike and + armour
-> unit group is in another trigger that fires every 0.2 secs and checks with if/then/else if Molten Shield buff is still on the unit or not
-> if not the spellbook is removed and unit is removed from the group

Result is that the custom buff/ability can be dispelled with regular Wc 3 dispel spells. Also, re-casting the same ability on the unit does not break the old buff, and I can balance/tweak buff durations with the dummy's ability, so I don't have to mess around with custom timers in triggers etc. Its also easier to set different durations for heroes and units.

Question is how to make it more efficient in terms of using less triggers.

The thing is that I dont want to re-create all wc3 abilities to be used with a triggered buff system, as that would require even more performance and even more triggers (more like another 60 triggers for the regular races).
 
Last edited:
Level 5
Joined
Mar 30, 2006
Messages
60
You could have one trigger that checks for every buff... maybe.
The buff detection already works like that.

I have one unit group for each custom spell that I use.

Examples:
Unit group MoltenArmour
Unit group Unholy Power
Unit group Sunflare
Unit group Fanaticism

etc.

All those groups are called in a single trigger every 0.2 seconds and in each group I have one if/then/else function which checks for the buff from the respective ability.

I thought that there is an option to make the dummy spell casting more efficient.

Right now I have 60 triggers which all work the same:

Unit starts ability
if/then/else - ability cast = XXX
Create 1 dummy
add buff ability XXX to unit
order unit to cast ability on target

If there's an option to make all my custom buffs use one single Dummy trigger I could save 59 triggers.

And with the unit groups idk. I have the feeling that there might be an easier way to store buffs and check for those instead of using so many groups.
 
In Ambush, Temp_unitgroup leaks.

Here are a few suggestions to "optimize:"
  • Try not to use (Matching unit) to filter out your unit groups. They are slighlty inefficient and became a pain / hassle to read and add or remove filters when you need to. Use an If / Then / Else to filter them out inside. You can take a look at this tutorial if you need more information
  • Instead of having the loops on all the time, only turn them on when there are units in a unit group. You can just use the function that counts them for you, but it would be easier and more efficient to just use an integer counter that you add +1 to when you add a unit to the unit group, and subtract -1 when you remove them from the group.
  • Use a global dummy caster that will cast the abilities for you. Create it once on map init, and just move + order to cast when you have to
 
Level 5
Joined
Mar 30, 2006
Messages
60
In Ambush, Temp_unitgroup leaks.

Here are a few suggestions to "optimize:"
  • Try not to use (Matching unit) to filter out your unit groups. They are slighlty inefficient and became a pain / hassle to read and add or remove filters when you need to. Use an If / Then / Else to filter them out inside. You can take a look at this tutorial if you need more information
  • Instead of having the loops on all the time, only turn them on when there are units in a unit group. You can just use the function that counts them for you, but it would be easier and more efficient to just use an integer counter that you add +1 to when you add a unit to the unit group, and subtract -1 when you remove them from the group.
  • Use a global dummy caster that will cast the abilities for you. Create it once on map init, and just move + order to cast when you have to
thx for the tips, I didnt think of using a global dummy yet. Good idea. Will do that :)
As for unit group leak: good to notice, I'll check through my other unit groups for leaks aswell then.
 
Status
Not open for further replies.
Top