• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Change Icon of Ability after Completing Upgrade

Status
Not open for further replies.

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
178
I want to make this:
When I make Greater Devour Magic (custom upgrade in slaughter house). I want destroyers to have bigger area of this abbility and change its icon to another one.

How do I get it:
I based my upgrade on Pulverize Damage Increase , that unlocks second level of ability with another stats. I need to premade second level of Devour Magic and new upgrade, with replaced data of Pulverize by Devour Magic. Also I must add this to upgrades used by unit. It is simple analogy but despite of the fact I can change so many statistics in second ability level for example name of it to "Greater Devour Magic", I can't change its icon.

What I need:
Upgrade complete will change statistics of ability but it wouldnt change its icon. Do you know how can I change icon of Devour Magic to another one pernamently, on every existing and upcoming units? What is the simplest and the best way to do this?

The most important thing is there are many players, how to change it only for one who reached upgrade?
 
Level 6
Joined
Aug 28, 2015
Messages
213
I think if you want to use triggers this Should do the trick
  • ChangeIcon
    • Events
      • Unit - A unit Finishes research
    • Conditions
      • (Researched tech-type) Equal to 'YourResearch'
    • Actions
      • Custom script: if (GetLocalPlayer() == GetTriggerPlayer()) then
      • Set abilityIconPath = 'Your Icon Path' //Like: ReplaceableTextures\PassiveButtons\PASBTNPlagueCloud.blp
      • Custom script: endif
      • Ability - Set Icon of 'YourAbility' to abilityIconPath
Make sure to set the abilityIconPath variable on map initialization to your first used icon path.
 
  • Like
Reactions: KPC

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
178
Hi, thanks for your answer. To be honest i'm not that good in variables/custom script and I gonna need some detail if u can tell how do they work I will be grateful.

1.
I need to know what variables are used and what types they are.
abilityIconPath is that String type? Are there another variables?

2.
Make sure to set the abilityIconPath variable on map initialization to your first used icon path.
Is this about initial Value of Variable or I need to set its Value in Initialization trigger?

3. How does it works? Can you describe it shortly?

I think if you want to use triggers this Should do the trick
  • ChangeIcon
    • Actions
      • Custom script: if (GetLocalPlayer() == GetTriggerPlayer()) then
      • Custom script: endif
 
Level 13
Joined
May 10, 2009
Messages
868

1. Yes and no.

2. Either one will do the job.

3. To sum it up, you can make a certain client/player run a piece of code whereas others will ignore it. In this case, when a certain player finishes that research, the if block makes sure that only such client/player will have their variable changed to something else.

It goes like this:

> Map start -> Everybody has "DevourMagicLevel1.blp" stored in "Path" variable.

> Player 1 finishes that research -> Assign "DevourMagicLevel2.blp" to "Path" only for this player.

> The other players still have the original value, for now.

Here's a thread where Chaosy explains it further.
 
Last edited:
  • Like
Reactions: KPC

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
178
BloodSoul thanks for your answer. Now the problem is: when player have shared units and he made upgrade, he sees changed icon also on level 1 ability (on his ally units). He wouldnt have unit with level 1 ability so its ok for him but when he selects ally unit with no upgrade he gona see changed ablilty icon on it.

The same problem is when ally with shared units selects unit of player who completed upgrade but he didn't. Than he gonna see normal icon on ally unit with level 2 ability.

The problem is changing icon of ability for player instead of changing icon of ability on specific level.

Now I'm not sure if my solution with upgrade Pulverize Damage Increase is the best. Looks like it gona be easier to make another ability with new icon/stats and replace them after upgrade. what do you think about it?
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,031
Now the problem is: when player have shared units and he made upgrade, he sees changed icon also on level 1 ability (on his ally units). He wouldnt have unit with level 1 ability so its ok for him but when he selects ally unit with no upgrade he gona see changed ablilty icon on it.
This is a result of the method you used to change the icon. The icon is changed completely for the player, not for any specific units of the player. If you don't want this behavior you will have to find another solution.
Looks like it gona be easier to make another ability with new icon/stats and replace them after upgrade.
There really isn't a "replace ability with ability" command anywhere that you could use. You would have to manually remove the old ability from and add the new ability to any units that should have the upgraded ability with a trigger. Something like:
  • Events
    • Unit - A unit enters (Playable map area)
  • Conditions
    • (Level of <normal ability> for (Triggering unit)) greater than 0
    • DevourUpgrade[(Player number of (Owner of (Triggering Unit)))] equal to true
  • Actions
    • Unit - Remove <normal ability> from (Triggering Unit)
    • Unit - Add <upgraded ability> to (Triggering unit) //it may also be necessary to save/set the level too if the ability has multiple levels in addition to the 'upgraded' version
And you will set the boolean DevourUpgrade variable when a player researches it:
  • Events
    • Unit - A unit finishes research
  • Conditions
    • (Researched tech-type) equal to <Devour upgrade>
  • Actions
    • Set DevourUpgrade[(Player number of (Triggering Player))] = True
    • Custom script: set bj_wantDestroyGroup = true //this cleans a group leak that would occur in the next line
    • Unit Group - Pick every unit in (Units owned by (Triggering Player)) matching (Level of <normal ability> for (Matching Unit) greater than 0) and do (Actions)
      • Loop - Actions
        • Unit - Remove <normal ability> from (Picked Unit)
        • Unit - Add <upgraded ability> to (Picked Unit) //same caveat about saving/setting level here
I think another way to achieve this would be to use a hidden Engineering Upgrade ability on your Devour units that morphs the base spell into the upgraded spell. Then enable this EU ability with the researched tech. (Oh EU master @Kyrbi0 haveth thou thoughts?)
 
  • Like
Reactions: KPC

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
178
This is a result of the method you used to change the icon. The icon is changed completely for the player, not for any specific units of the player. If you don't want this behavior you will have to find another solution.

There really isn't a "replace ability with ability" command anywhere that you could use. You would have to manually remove the old ability from and add the new ability to any units that should have the upgraded ability with a trigger. Something like:
  • Events
    • Unit - A unit enters (Playable map area)
  • Conditions
    • (Level of <normal ability> for (Triggering unit)) greater than 0
    • DevourUpgrade[(Player number of (Owner of (Triggering Unit)))] equal to true
  • Actions
    • Unit - Remove <normal ability> from (Triggering Unit)
    • Unit - Add <upgraded ability> to (Triggering unit) //it may also be necessary to save/set the level too if the ability has multiple levels in addition to the 'upgraded' version
And you will set the boolean DevourUpgrade variable when a player researches it:
  • Events
    • Unit - A unit finishes research
  • Conditions
    • (Researched tech-type) equal to <Devour upgrade>
  • Actions
    • Set DevourUpgrade[(Player number of (Triggering Player))] = True
    • Custom script: set bj_wantDestroyGroup = true //this cleans a group leak that would occur in the next line
    • Unit Group - Pick every unit in (Units owned by (Triggering Player)) matching (Level of <normal ability> for (Matching Unit) greater than 0) and do (Actions)
      • Loop - Actions
        • Unit - Remove <normal ability> from (Picked Unit)
        • Unit - Add <upgraded ability> to (Picked Unit) //same caveat about saving/setting level here
I think another way to achieve this would be to use a hidden Engineering Upgrade ability on your Devour units that morphs the base spell into the upgraded spell. Then enable this EU ability with the researched tech. (Oh EU master @Kyrbi0 haveth thou thoughts?)
Thanks a lot man, you are so helpful. I made your sugesstion and it works! But Destroyer is not unit, which enter map according to game (I mean Event: Unit - A unit enters (Playable map area)) . You know, it is created from statue, not comes out form building. So it works when I add destroyer to Slaughterhouse as unit and it doesn't work in standard variant (destroyer from statue), which is my goal. Do you have any suggestion, how can I change event: Unit - A unit enters (Playable map area) that it starts work, when destroyer is created from statue?
 
Level 6
Joined
Aug 28, 2015
Messages
213
Just use the unit finish ability event with the condition of the transformation abilty is the casted one.
You may need to add a 0 sec wait before you give the ability for the transformation.
 
  • Like
Reactions: KPC

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
178
Thank you all very much for your help. Finally I did it and it works properly. I've learned a lot but I'm curious about one thing:
Custom script: set bj_wantDestroyGroup = true
What is this and how is it work? (I know what are memory leaks) But the main question is, should I use it every time, when I use Action: Unit Group - Pick every unit into a Unit Gropu
 
Level 13
Joined
May 10, 2009
Messages
868
"Unit Group - Pick every..." in GUI generally calls another function which creates a new unit group and adds units to it depending on your needs. Unless, you're referencing another unit group variable.

Upon using "Pick every..." the function itself will check if bj_wantDestroyGroup is true. If so, the unit group mentioned will be destroyed after enumerating all of its units.

  • Actions
    • Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
      • Loop - Actions
->
JASS:
function ForGroupBJ takes group whichGroup, code callback returns nothing
    // If the user wants the group destroyed, remember that fact and clear
    // the flag, in case it is used again in the callback.
    local boolean wantDestroy = bj_wantDestroyGroup
    set bj_wantDestroyGroup = false

    call ForGroup(whichGroup, callback)

    // If the user wants the group destroyed, do so now.
    if (wantDestroy) then
        call DestroyGroup(whichGroup)
    endif
endfunction
 
Last edited:
  • Like
Reactions: KPC

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,583
Thsnks but shuld I use it once in trigger or every time I use pick units into unit group?
Here's two examples of creating a unit group. Neither of these leak.

Set bj_wantDestroyGroup is useful because it allows you to avoid using a Unit Group variable like I use in Example 2 (TempGroup). Whenever you're done using a unit group you will need to remove it using one of these two methods.
  • Example 1
    • Events
    • Conditions
    • Actions
      • Set TempPoint = (Center of (Playable map area))
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 300.00 of TempPoint) and do (Actions)
        • Loop - Actions
          • Unit - Kill (Picked unit)
      • Custom script: call RemoveLocation(udg_TempPoint)
  • Example 2
    • Events
    • Conditions
    • Actions
      • Set TempPoint = (Center of (Playable map area))
      • Set TempGroup = (Units within 300.00 of TempPoint)
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Unit - Kill (Picked unit)
      • Custom script: call RemoveLocation(udg_TempPoint)
      • Custom script: call DestroyGroup(udg_TempGroup)
Every time you use "Pick every unit" and you don't reference an already existing group then you're creating a new group that will leak unless you destroy it.
 
  • Like
Reactions: KPC
Level 39
Joined
Feb 27, 2007
Messages
5,031
It can also be nested:
  • Custom script: set bj_wantDestroyGroup = true
  • Unit Group - Pick...
    • Loop - Actions
      • Custom script: set bj_wantDestroyGroup = true
        • Unit Group - Pick...
          • Loop - Actions
            • -------- something --------
It also works when used for these conditions:
  • Custom script: set bj_wantDestroyGroup = true
  • If (All conditions are true) then do (Then actions) else do (Else actions)
    • If - Conditions
      • (Number of units in (<any group here>) greater than 5
      • (Count living units owned by Player 1 (Red)) greater than 5
    • Then - Actions
    • Else - Actions
But you obviously cannot use it for main trigger conditions and it will only destroy one group at a time so if you have multiple such checks all but one of them will leak.
 
  • Like
Reactions: KPC
Status
Not open for further replies.
Top