• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[General] Should I create a variable for all the units in the conditions?

Status
Not open for further replies.
Level 10
Joined
Sep 25, 2013
Messages
521
Hi! I'm wondering if i should create a variable, call it Catapults, so that instead of checking if the triggering unit is any one of these conditions it just checks if it is part of the Catapults unit group. I know in cases of periodic event triggers this helps the performance, but for a damage event like this, is this needed? Thanks! Here's the trigger:

  • Catapult Damage to Ships
    • Events
      • Game - PDD_damageEventTrigger becomes Equal to 1.00
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • PDD_damageType Equal to PDD_PHYSICAL
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • And - All (Conditions) are true
                • Conditions
                  • Or - Any (Conditions) are true
                    • Conditions
                      • (Unit-type of PDD_source) Equal to Ballista |c00FFFF00(Siege)|r (Elves)
                      • (Unit-type of PDD_source) Equal to Ballistapult |c00FFFF00(Siege)|r (Mordor)
                      • (Unit-type of PDD_source) Equal to Catapult |c00FFFF00(Siege)|r (Dwarves)
                      • (Unit-type of PDD_source) Equal to Catapult |c00FFFF00(Siege)|r (Gondor)
                      • (Unit-type of PDD_source) Equal to Catapult |c00FFFF00(Siege)|r (Haradrim)
                      • (Unit-type of PDD_source) Equal to Demolisher |c00FFFF00(Siege)|r (Isengard)
                      • (Unit-type of PDD_source) Equal to Glaive Laucher |c00FFFF00(Siege)|r (Elves)
                      • (Unit-type of PDD_source) Equal to Devestator (Haradrim)
                      • (Unit-type of PDD_source) Equal to Infernal Contraption (Isengard)
                      • (Unit-type of PDD_source) Equal to Onager (Gondor)
                      • (Unit-type of PDD_source) Equal to Plague Bringer (Mordor)
                      • (Unit-type of PDD_source) Equal to Siege Breaker (Dwarves)
                      • (Unit-type of PDD_source) Equal to Trebuchet (Gondor)
                      • (Unit-type of PDD_source) Equal to Devestator Unit
                      • (Unit-type of PDD_source) Equal to Onager Unit
                      • (Unit-type of PDD_source) Equal to Siege Breaker Unit
                  • Or - Any (Conditions) are true
                    • Conditions
                      • (Unit-type of PDD_target) Equal to Fishing Ship
                      • (Unit-type of PDD_target) Equal to Barrage Ship |c00FFFF00(Archer)|r
                      • (Unit-type of PDD_target) Equal to Frigate |c00FFFF00(Archer)|r
                      • (Unit-type of PDD_target) Equal to Warship |c00FFFF00(Infantry)|r (Dwarves)
                      • (Unit-type of PDD_target) Equal to Warship |c00FFFF00(Infantry)|r (Elves)
                      • (Unit-type of PDD_target) Equal to Warship |c00FFFF00(Infantry)|r (Gondor)
                      • (Unit-type of PDD_target) Equal to Warship |c00FFFF00(Infantry)|r (Haradrim)
                      • (Unit-type of PDD_target) Equal to Warship |c00FFFF00(Infantry)|r (Isengard)
                      • (Unit-type of PDD_target) Equal to Warship |c00FFFF00(Infantry)|r (Mordor)
            • Then - Actions
              • Set PDD_amount = (PDD_amount x 4.00)
            • Else - Actions
        • Else - Actions
 
Level 10
Joined
Sep 25, 2013
Messages
521
Thank you :)

Edit:
So this would be the right way to do it?

  • Ships Add
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Unit-type of (Triggering unit)) Equal to Barrage Ship |c00FFFF00(Archer)|r
          • (Unit-type of (Triggering unit)) Equal to Frigate |c00FFFF00(Archer)|r
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Dwarves)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Elves)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Gondor)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Haradrim)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Isengard)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Mordor)
    • Actions
      • Unit Group - Add (Triggering unit) to Ships
  • Ships Remove
    • Events
      • Unit - A unit Dies
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Unit-type of (Triggering unit)) Equal to Barrage Ship |c00FFFF00(Archer)|r
          • (Unit-type of (Triggering unit)) Equal to Frigate |c00FFFF00(Archer)|r
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Dwarves)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Elves)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Gondor)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Haradrim)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Isengard)
          • (Unit-type of (Triggering unit)) Equal to Warship |c00FFFF00(Infantry)|r (Mordor)
    • Actions
      • Unit Group - Remove (Triggering unit) from Ships
and the reference the unit group on the damage event trigger
 
Last edited:
Level 10
Joined
Sep 25, 2013
Messages
521
You can shorten the "Catapult Remove" trigger quite a bit. Just check if the triggering unit is in the group.

Like this?

  • Ship Resistance to Archers and Towers
    • Events
      • Game - PDD_damageEventTrigger becomes Equal to 1.00
    • Conditions
      • PDD_damageType Equal to PDD_PHYSICAL
      • (PDD_target is in Ships) Equal to True
      • (PDD_source is in ArchersTowers) Equal to True
    • Actions
      • Set PDD_amount = (PDD_amount x 0.50)
 

EdgeOfChaos

E

EdgeOfChaos

You can also store each unit type in a unit type array, and then loop through from 0 to last index, checking whether the unit type = variable[index], and then perform actions if it is. That way you can entirely forget about indexing/deindexing, and there should be no performance loss for such few actions.

But yes, in general there should never be a condition like in the first post.
 
Level 10
Joined
Sep 25, 2013
Messages
521
You can also store each unit type in a unit type array, and then loop through from 0 to last index, checking whether the unit type = variable[index], and then perform actions if it is. That way you can entirely forget about indexing/deindexing, and there should be no performance loss for such few actions.

I'm not sure how to do that, I'm a pretty basic triggerer, but i'd like to learn. And also i have several of these types of trigger. I'm trying to make it so catapults are strong vs ships, archers (including towers and archer type ships) deal less damage to catapults, and walls are more resistant to catapults. If you have time could you possibly look at my map, just at these specific triggers, and show me a more efficient way? I want my map to be as lag free as possible. I understand if not :) the triggers are under the "units" category and at the top of the category
 

Attachments

  • Lotr Conquest v 0.5 Alpha.w3x
    7.7 MB · Views: 61
Level 24
Joined
Aug 1, 2013
Messages
4,657
It looks like you want to have a custom damage table.
Like damage types:
Arrow, Siege, Sharp, Blunt, Magic, etc.
And let ships take only 50% damage from arrows, 200% damage from siege, 100% damage from sharp, 150% damage from blunt and 50% damage from magic.
And that for lets say 10 different kinds of unit types.

I can tell you it is much better to create those damage and armor types instead.
So you just make global variables of each type and set their default value to a unique integer.
So Arrow = 1, Siege = 2, Sharp = 3, etc. (yes no 0)
And Ships = 1, Horse = 2, Siege = 3, Footman = 4, etc. (no 0 either)

Then you create a "table" from an integer array.
12345

6
78910

11
12131415

16
17181920

21
22232425
Now you can place the modifiers in the table.

So in (1, 1), you have arrows hitting ships.
At map init, you stored a 0.5 (50%) in that place.
In (2, 1), you have siege hitting ships.
At map init, you stored a 2 (200%) in that place.

Then you only have to have one trigger for ALL damage and armor types that just loads in the types of the source and target and then calculates the new damage.

Units that dont have an armor type or damage type defined, have 0 as armor and/or damage type.
So you have to place a 1 for every index in the table for 0.
So
(0, 0) = 1
(0, 1) = 1
(0, 2) = 1
(0, 3) = 1
(1, 0) = 1
(2, 0) = 1
etc.

You can store the armor and damage types in a hashtable using the unit type id as index.
Then you dont have to keep a list of all the units everywhere but can just store the values on map init for all units and then just load the value from the hashtable.
 
Level 10
Joined
Sep 25, 2013
Messages
521
I understand somewhat what you are saying, but I'm also a novice at creating triggers. I don't know specific terminology like global variables. Are you saying create integers and label them after each unit type i want to use? So create an integer called Archers and set it 1 for example? I also don't know how to create tables from integer arrays but i'll look it up, or does that mean just set the array to the size i need it to be, so if there's 6 types i need to keep track of then set the array to 6? Thanks fro the help btw!
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
What you want is just to enlarge the Object Editor tables of units.
However... that is not possible just like that.

What you want is specify two values for each unit type:
- Armor Type
- Damage Type

To have such data, you need an array to put them in.
To use unit type id's as indices, you need a hashtable because arrays dont reach far enough to store it... neither will they be very convenient for it.

You create a hashtable variable in the Trigger Editor.
Then you create a trigger that runs on map init that creates a new hashtable and sets the variable to that hashtable.
  • Actions
    • Hashtable - Create a hashtable
    • Set UnitTable = (Last created hashtable)
Just below that, you just do "Hashtable - Save Integer".
The unit type id is technically an integer but it doesnt work in GUI like an integer.
So we have to abuse a small trick with variables and JASS script to pass on the data from one variable to another.
  • Actions
    • Set TempUnitType = Footman
    • Custom script: set udg_TempInteger = udg_TempUnitType
    • Hashtable - Save 0 as 0 of TempInteger in UnitTable
    • Hashtable - Save 0 as 1 of TempInteger in UnitTable
Now a Footman has in row 0 and 1 the integers 0 and 0.
Ofcourse you dont want 0 and 0 but to do that properly we have to create the armor and damage types first.
OJNoHuv.png

(Be sure to use unique integers in the default values!)

So now, you can say:
  • Actions
    • Set TempUnitType = Footman
    • Custom script: set udg_TempInteger = udg_TempUnitType
    • Hashtable - Save DAMAGE_TYPE_BLUNT as 0 of TempInteger in UnitTable
    • Hashtable - Save ARMOR_TYPE_UNIT as 1 of TempInteger in UnitTable
You can technically change those 0 and 1 into something like "UnitTableRow_DamageType" and "UnitTableRow_ArmorType", but you wont be really needing those yet.

In any case, now you have to define the damage factors:
This table is small enough to place in a real array so we wont bother using a hashtable. You can use it but it wouldnt be worth the effort.
(DONT USE INTEGER LIKE I DID IN THIS IMAGE! USE REAL INSTEAD!)
iOZZhcZ.png

First of all, we want to define the maximum number of either armor types or damage types that we use. For convenience (and for optimal use), we use 90.
So we have another global variable:
INmcB2G.png

Now we have a table similar to what I have made in my previous post.
Then you create a "table" from an integer array.
12345

6
78910

11
12131415

16
17181920

21
22232425
The only difference is that this table has instead of 5 rows and 5 columns, it has 90 rows and 90 columns.

To fill or read from one of the fields of such a "table", you read by (X + Y*Xmax) or (Y X*Ymax)
Simply said, you do Y multiplied by the total size of the rows (Xmax) so you have the first index of your correct row, then you add X to it so you will be having the right X value.
The other formula is exactly the opposite and works as well.

We can do (DamageType + ArmorType*DamageTableRows):
  • Actions
    • Set DamageTable[(DAMAGE_TYPE_ARROWS + (ARMOR_TYPE_NAVAL x DamageTableRows))] = 0.50
    • Set DamageTable[(DAMAGE_TYPE_ARROWS + (ARMOR_TYPE_HORSE x DamageTableRows))] = 1.00
    • Set DamageTable[(DAMAGE_TYPE_ARROWS + (ARMOR_TYPE_UNIT x DamageTableRows))] = 1.25
With this, you set the damage factor of
arrows vs naval to 0.50
arrows vs horse to 1.00
arrows vs unit to 1.25

You should do that for every single type in your array.

Now there is the exception case.
In some cases, you will not have defined the default value of your armor/damage types or you forgot to add the unit type that you just created in the init trigger to define their armor/damage types.
In those cases, your armor/damage type integer is 0.
It means that you will not fall under any of the damage factors.
You can choose to keep the resulting factor of 0.00 so you will not deal any damage vs those units and those units will not deal any damage against any other units.
It is the best for testing purpose but for prevention of those things in actual releases, you can set all values of index (0, I) and (I, 0) to 1.00 (you can do this in one single loop from 0 to 90 using the same formula of the armor/damage types).

Now all unit types have their armor and damage types.
If you want to be able to change those values per unit independent from each other, you have to create two arrays for those units and store the armor type and damage type from the hashtable in the arrays whenever a unit is created.
You will require a unit indexer to index the units in unique rows of the arrays.
But if you dont want that, then you can just continue with using the data.

To actually make use of this data, you slightly modify your onDamage triggers:
  • Damage Table Effect
    • Events
      • Game - PDD_damageEventTrigger becomes Equal to 1.00
    • Conditions
      • PDD_damageType Equal to PDD_PHYSICAL
    • Actions
      • Set PDD_amount = (PDD_amount x (Load ))
  • Actions
    • Set TempUnitType = (Unit-type of PDD_source)
    • Custom script: set udg_TempInteger = udg_TempUnitType
    • Set TempUnitType = (Unit-type of PDD_target)
    • Custom script: set udg_TempInteger2 = udg_TempUnitType
    • Set PDD_amount = (PDD_amount x DamageTable[((Load 0 of TempInteger from UnitTable) + ((Load 1 of TempInteger2 from UnitTable) x DamageTableRows))])
Now you need two integer variables to store both the target and the source...
You may want to use arrays for TempVariables but that is all your choice.

In any case, this trigger will make all damage be applied with the damage factor from the table.
There is only one butt (_._)... if your DDS doesnt have a damage amount modifier variable, then you are pretty much fcked up.
I know what DDS you use, and I know how to check if it has one, but I am too lazy for that.
The problem that you may see is that when you have your damage be modified by triggers and you increase damage by 100 for example, that damage will NOT be multiplied by this value. You require to have at least 2 values (Damage amount, Damage modifier) to deal proper damage in every case.
I personally use 3:
Damage amount: Just a value
Damage modifier: Multiplication of Damage amount.
Damage bonus: Bonus value without being modified.
Aka:
DMG = (amount * modifier) + bonus

But that is only optional.
 
If you want a simple boolean flag per unit, here's another approach that is great because it doesn't require any code at all:

Give all units that you want to be considered by your trigger a passive ability that does nothing (like an attribute bonus ability with 1 level that adds 0 to all stats), then simply check for that ability in the trigger.
In your case, for example you could name that ability "siege weapon". Feels intuitive as what you are scripting is basicly like a passive ability anyway.

This is how I handle many "spell like" booleans in my map. Stuff like stun immunity, slow immunity, etc. are just a passive ability that gets checked when applying these buffs.

Whenever I create a new unit, I simply select all these "types" directly in the object editor and have no need to revisit any registries at all. Nice intuitive workflow, as it works in the same way as hardcoded stuff like invulnerability, locust, etc..
 
Level 10
Joined
Sep 25, 2013
Messages
521
Thank you both for your help! Wietlol, that was actually very informative, I understand the idea behind making a custom damage table now. I went with zwieblchen's idea because I'm running low on time and I know for certain I can do it without messing it up. You guys are great!
 
Status
Not open for further replies.
Top