• 🏆 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!

Setting Ability Levels for a Unit

Status
Not open for further replies.
Level 37
Joined
Jul 22, 2015
Messages
3,485
I have a tower in my map that uses Phoenix Fire (Fire Blast (Tier #)) as one of its passive abilities. Unfortunately, Phoenix Fire does not appear in the command card of the unit that has it :( My fix around this is giving the tower a "fake passive" which doesn't actually do anything but show a description. The fake passive has 6 levels on it, each level describing the damage its supposed to be dealing, DoT duration, etc.

Fire Blast (Tier #) is seperated into 3 different abilities because I want each tier to change the Missle Art. Since there are 3 tiers, that means I need 3 seperate abilities :3 Whenever the tower upgrades to its next level, I have to change both the level of the fake passive + phoenix fire passive. Below is my current approach of setting the neccesary levels to their relevant tower level o: is there a better and or more efficient way of doing this? I feel like my way is extremely amateur. I manually added comments from the thread to explain what's going on exactly.

  • Set UpgradedTower = (Triggering unit)
  • Set UpgradedTower_Level = (Point-value of UpgradedTower)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • -------- --------
      • -------- Checking if UpgradedTower has the fake passive because only Fire Towers will have this passive --------
      • -------- --------
      • (Level of Fire Blast (Fake Passive) for UpgradedTower) Greater than or equal to 1
    • Then - Actions
      • -------- --------
      • -------- If pont value = 2, set level of fake passive to level 2 --------
      • -------- If pont value = 3, set level of fake passive to level 3 --------
      • Unit - Set level of Fire Blast (Fake Passive) for UpgradedTower to UpgradedTower_Level
      • -------- --------
      • -------- Level 1 & 2 Tower have Tier 1 --------
      • -------- Level 3 & 4 Tower have Tier 2 --------
      • -------- Level 5 & 6 Tower have Tier 3 --------
      • -------- Units will always have level 1 by default, so I only have to set it to level 2 when they upgrade --------
      • Unit - Set level of Fire Blast (Tier 1) for UpgradedTower to 2
      • Unit - Set level of Fire Blast (Tier 2) for UpgradedTower to 2
      • Unit - Set level of Fire Blast (Tier 3) for UpgradedTower to 2
    • Else - Actions
 
Level 25
Joined
Sep 26, 2009
Messages
2,378
I think it's a good approach for a first try. What you could do is put this condition:
  • (Level of Fire Blast (Fake Passive) for UpgradedTower) Greater than or equal to 1
into the condition block of the trigger (in the condition block under event block), because everything is dependant on this condition. There's no need to read the tower's point value if it's not the correct tower, right? Of course here I'm presuming that the trigger above is only for the fire towers.

Next, save the ability types into an "ability" array. So Fire Blast (Tier 1) in FireBlastArray[1], (Tier 2) under index [2], etc. Then, when you upgrade your tower, increase its level of FireBlastArray[UpgradedTower_Level]'s ability to level 2. So for example a tower with point value 3 (UpgradedTower_Level = 3) will set level of FireBlastArray[3] to level 2.

Of course you will need an initialization trigger where you save those 3 abilities into the array, but you should have some general map initialization trigger anyway :)

  • Your trigger
    • Events
      • *some event*
    • Conditions
      • (Level of Fire Blast (Fake Passive) for (Triggering unit)) Greater than 0
    • Actions
      • Set UpgradedTower = (Triggering unit)
      • Set UpgradedTower_Level = (Point-value of UpgradedTower)
      • Unit - Set level of Fire Blast (Fake Passive) for UpgradedTower to UpgradedTower_Level
      • Unit - Set level of FireBlastArray[UpgradedTower_Level] for UpgradedTower to 2
And this should be part of your map initializing trigger:
  • Your map ini trigger
    • Events
      • Map Initialization
    • Conditions
    • Actions
      • ... some other stuff you initialize
      • Set FireBlastArray[1] = Fire Blast (Tier 1)
      • Set FireBlastArray[2] = Fire Blast (Tier 2)
      • Set FireBlastArray[3] = Fire Blast (Tier 3)
Also, consider using temporal variables. Those are variables with no purpose, as they're used just to help you refer to stuff rather than save information. That way you don't have to create new global variables for each trigger, but instead re-use these temporal variables.

Your trigger could actually look like this with temporal variables (naming them is your own choice, be it with tmp_ prefix, some different prefix, or without prefix at all, etc.)
  • Your trigger
    • Events
      • *some event*
    • Conditions
      • (Level of Fire Blast (Fake Passive) for (Triggering unit)) Greater than 0
    • Actions
      • Set tmp_unit = (Triggering unit)
      • Set tmp_int = (Point-value of UpgradedTower)
      • Unit - Set level of Fire Blast (Fake Passive) for tmp_unit to tmp_int
      • Unit - Set level of FireBlastArray[tmp_int] for tmp_unit to 2
As I've said, the main advantage here is that you don't have to create billions of variables which you would use exclusively in only one trigger. But remeber if you use temporal variables - those variables must not save the information for any length of time, except for that trigger's run!
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I think it's a good approach for a first try.

Thank you for the response, Nichilus. Unfortunately, I'm a little tired so I will read your post after my nap >:) I'll send you a visitor message if I run into any problems or if the solution works !

EDIT:
What you could do is put this condition:
  • (Level of Fire Blast (Fake Passive) for UpgradedTower) Greater than or equal to 1
into the condition block of the trigger (in the condition block under event block), because everything is dependant on this condition. There's no need to read the tower's point value if it's not the correct tower, right? Of course here I'm presuming that the trigger above is only for the fire towers.

Sorry I totally forgot to specify this :( all the towers are going to be in this trigger. I'm thinking that checks if the point value of the triggering unit is below or equal to 6 because ONLY the towers will have point values like this in my map.

Next, save the ability types into an "ability" array. So Fire Blast (Tier 1) in FireBlastArray[1], (Tier 2) under index [2], etc. Then, when you upgrade your tower, increase its level of FireBlastArray[UpgradedTower_Level]'s ability to level 2. So for example a tower with point value 3 (UpgradedTower_Level = 3) will set level of FireBlastArray[3] to level 2.

Of course you will need an initialization trigger where you save those 3 abilities into the array, but you should have some general map initialization trigger anyway :)

Never thought about doing it this way :) I will try this!

EDIT: All thought its perfect for setting the ability level for Phoenix Fire, it's conflicting for the fake passive. The fake passive has 6 abilities, and the point value of the towers only go up to 3. Here's the current setup:

  • Level 1 & 2 Tower Point Value = 1
  • Level 3 & 4 Tower Point Value = 2
  • Level 5 & 6 Tower Point Value = 3
Note: I didn't add setting the level of the fake passive because it's conflicting.
  • Tower Ability Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set FireBlastFP = Fire Blast (Fake Passive)
      • Set FireBlast[1] = Fire Blast (Tier 1)
      • Set FireBlast[2] = Fire Blast (Tier 2)
      • Set FireBlast[3] = Fire Blast (Tier 3)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Level of Fire Blast (Fake Passive) for UpgradeTower_TowerUnit) Equal to 2
          • (Level of Fire Blast (Fake Passive) for UpgradeTower_TowerUnit) Equal to 4
          • (Level of Fire Blast (Fake Passive) for UpgradeTower_TowerUnit) Equal to 6
    • Then - Actions
      • Unit - Set level of FireBlast[UpgradeTower_TowerLevel] for UpgradeTower_TowerUnit to 2
    • Else - Actions
This is what I think I SHOULD do to properly set both fake & real passive.
  • Level 1 Tower Point Value = 1
  • Level 2 Tower Point Value = 2
  • Level 3 Tower Point Value = 3
  • Level 4 Tower Point Value = 4
  • Level 5 Tower Point Value = 5
  • Level 6 Tower Point Value = 6
  • Tower Ability Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set FireBlastFP = Fire Blast (Fake Passive)
      • Set FireBlast[2] = Fire Blast (Tier 1)
      • Set FireBlast[4] = Fire Blast (Tier 2)
      • Set FireBlast[6] = Fire Blast (Tier 3)
  • Set UpgradeTower_TowerUnit = (Triggering unit)
  • Set UpgradeTower_TowerLevel = (Point-value of UpgradeTower_TowerUnit)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Level of Fire Blast (Fake Passive) for UpgradeTower_TowerUnit) Greater than 0
    • Then - Actions
      • Unit - Set level of FireBlastFP for UpgradeTower_TowerUnit to UpgradeTower_TowerLevel
      • Set FireBlastFP_Level = (Level of FireBlastFP for UpgradeTower_TowerUnit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • FireBlastFP_Level Equal to 2
              • FireBlastFP_Level Equal to 4
              • FireBlastFP_Level Equal to 6
        • Then - Actions
          • Unit - Set level of FireBlast[UpgradeTower_TowerLevel] for UpgradeTower_TowerUnit to 2
        • Else - Actions
    • Else - Actions

Also, consider using temporal variables. Those are variables with no purpose, as they're used just to help you refer to stuff rather than save information. That way you don't have to create new global variables for each trigger, but instead re-use these temporal variables.

Is there any other benefit to using global variables? Does having too many variables affect performance?


On a side note, I also prefer having different Map Init triggers because its easier to find what I need :) like all config variables related to X spell are in the X Config triggers, and all tower config variables are in the Tower Config trigger. Is this a bad idea?
 
Last edited:
Level 25
Joined
Sep 26, 2009
Messages
2,378
Note: I didn't add setting the level of the fake passive because it's conflicting.
  • Tower Ability Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set FireBlastFP = Fire Blast (Fake Passive)
      • Set FireBlast[1] = Fire Blast (Tier 1)
      • Set FireBlast[2] = Fire Blast (Tier 2)
      • Set FireBlast[3] = Fire Blast (Tier 3)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Level of Fire Blast (Fake Passive) for UpgradeTower_TowerUnit) Equal to 2
          • (Level of Fire Blast (Fake Passive) for UpgradeTower_TowerUnit) Equal to 4
          • (Level of Fire Blast (Fake Passive) for UpgradeTower_TowerUnit) Equal to 6
    • Then - Actions
      • Unit - Set level of FireBlast[UpgradeTower_TowerLevel] for UpgradeTower_TowerUnit to 2
    • Else - Actions
So if I understand that right, you want to level up one of those abilities when tower reaches level 2, 4 and 6? (As in point-value is 2/4/6). If that's so, you can use a condition:
Mod(Point-value of (tower), 2) == 0
where Mod is under Math - Modulo operation. It basically means if remainder of division of point-value by 2 is equal to 0 (e.g. every even number), then it passes the condition.

Is there any other benefit to using global variables? Does have too many variables affect performance?
There's no real performance gain apart from the number of created variables, because temporal variables are still global variables - it's just the way you use them is different than traditionally. Also imagine a scenario where you have to use a point variable to prevent memory leaks. If you use new variable for everything, you will get to a point where you have long names, so a point variable may have a name like:
  • Set MH_targetPosition = (somewhere)
  • Custom script: call RemoveLocation(udg_MH_targetPosition)
which is prone for typos, etc., while if you decide that a variable for example called simply "loc" will be your temporal point variable
  • Custom script: call RemoveLocation(udg_loc)
which is easier to read and less prone to typos, not to mention that you don't have to think what's the variable's type and purpose, etc.

On a side note, I also prefer having different Map Init triggers because its easier to find what I need :) like all config variables related to X spell are in the X Config triggers, and all tower config variables are in the Tower Config trigger. Is this a bad idea?
The way blizzard does it in WCIII and SCII is that they have one trigger which fires upon Map Initialization and this trigger runs other map ini triggers. Something like this:
  • Map Ini
    • Events
      • Map Initialization
    • Conditions
    • Actions
      • Trigger - Run Ini01 (checking conditions)
      • Trigger - Run Ini02 (/checking conditions)
  • Ini01
    • Events
    • Conditions
    • Actions
      • some actions like hero initialization
  • Ini02
    • Events
    • Conditions
    • Actions
      • some other actions - like cinematic initialization or whatnot
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
So if I understand that right, you want to level up one of those abilities when tower reaches level 2, 4 and 6? (As in point-value is 2/4/6). If that's so, you can use a condition:
Mod(Point-value of (tower), 2) == 0
where Mod is under Math - Modulo operation. It basically means if remainder of division of point-value by 2 is equal to 0 (e.g. every even number), then it passes the condition.

You understood right, and you yet again came back on top. Thank you so much, Nich! I learned a lot from you :) wish I can give you more rep. I'm starting to get into drawing, so if you need any 2D art, come ask me!

There's no real performance gain apart from the number of created variables, because temporal variables are still global variables - it's just the way you use them is different than traditionally.

Ahh okay :) I do have a lot of variables running around. I'll put that in my low priority list for now though.

The way blizzard does it in WCIII and SCII is that they have one trigger which fires upon Map Initialization and this trigger runs other map ini triggers. Something like this:
  • Map Ini
    • Events
      • Map Initialization
    • Conditions
    • Actions
      • Trigger - Run Ini01 (checking conditions)
      • Trigger - Run Ini02 (/checking conditions)
  • Ini01
    • Events
    • Conditions
    • Actions
      • some actions like hero initialization
  • Ini02
    • Events
    • Conditions
    • Actions
      • some other actions - like cinematic initialization or whatnot

I shall do this now!
 
Status
Not open for further replies.
Top