1. Find your way through the deepest dungeon in the 18th Mini Mapping Contest Poll.
    Dismiss Notice
  2. A brave new world lies beyond the seven seas. Join the 34th Modeling Contest today!
    Dismiss Notice
  3. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
Hive 3 Remoosed BETA - NOW LIVE. Go check it out at BETA Hive Workshop! Post your feedback in this new forum BETA Feedback.
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Disable an ability for a specific hero/unit

Discussion in 'General Mapping Tutorials' started by WaterKnight, Nov 20, 2012.

  1. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,035
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5

    Exposition



    Blizzard offers the jass function
    SetPlayerAbilityAvailable


    or in GUI

    • Player - Enable/Disable Ability


    which allows us to hide/disable an ability from the command card of a unit. In contrast to
    UnitRemoveAbility


    or in GUI

    • Unit - Remove Ability


    the cooldown of the ability keeps running in the background and any momentary casts of this ability do not get interrupted. That is quite the advantage.

    Unfortunately, the action covers all the units of a given player and there is no variant for a specific unit.
    Fortunately, this tutorial will present some solution.

    I have to differentiate between heroes and units. Well, the unit way could be used for heroes too, but it's more cumbersome and less performant. Also, the procedure for non-heroes harbors danger. I cannot say if it's practicable in the end but maybe with the proper configurations.

    Anyway, read For Heroes first. The second part references it.

    For Heroes



    There is a very useful ability for us mapmakers out there called Engineering Upgrade. Its raw code is ANeg, so I will name it that way in this tutorial from now on. The ability holds the power to convert another ability on the unit to a different one. You have to specify both the source and the target ability.

    ex:
    ANeg with Blizzard (source) to Bash (target)

    If you add this ANeg to a unit with the Blizzard ability, it will end up with Bash instead.

    Now, I have to tell that when transforming an ability this way, the target ability on the unit inherits some of the source ability's features, such as the remaining cooldown. Furthermore, if you change the source ability while the unit is currently casting it, the unit won't be bothered the least and continue normally. This can be well observed on a channeling spell like Blizzard for example. So two main properties I ascribed to
    SetPlayerAbilityAvailable
    above are fulfilled.

    We only need to hide the target ability (and ANeg) now. To not get in conflict with any other stuff, we may create a new dummy ability. I will refer to it as Placeholder. It can basically be of any base, or close to. I usually choose Agyb (Gyrocopter Bombs) for an effectless non-active ability although it could make sense to use the Slow Aura of Tornado or Attribute Bonus here since those abilities do not possess an icon in the first place/can be hidden by configuration. Anyway, Placeholder and ANeg can both be shrouded by
    SetPlayerAbilityAvailable
    , which should be done at map init. Note that ANeg still works when disabled.

    Simplification note: I found that the Placeholder can also be the ANeg itself. The unit will have it twice then but it works.

    To reveal the ability again, remove ANeg from the unit. The conversion will be reverted with the cooldown still intact. Since ANeg does not remember the source ability it transformed but instead looks up its object data, each ability we want to be able to hide requires another Placeholder plus another ANeg (or only another ANeg if ANeg is the Placeholder).

    For Non-Heroes



    Why can we not do the same process for non-heroes? Wc3 will crash when trying to add ANeg to a normal unit. So the plan is to disguise the unit as a heroic hero. The only way I have found to accomplish that is by morphing the unit into another (hero) unit type. Doing so is dangerous according to Dr Super Good, and I believe so myself, but maybe it's okay with the proper settings or conditions. The game won't immediately shut down but may run into problems later on when events happen. Another contra is that not each morphing method interrupts the unit's order but it will reset the animation.

    Now, if we just morph the unit, add ANeg to hide the ability, then remorph the unit to its original type, that won't work because the unit would still hold ANeg without being a hero and Wc3 does not like it. If we could only remove ANeg before reverting and still keep the ability transformation, our problem would immediately vanish. There comes another trick into play:

    Reversed Engineering Upgrade Trick:
    As I have stated above, ANeg does not keep in mind which ability it has been used on, rather looks it up from its object editor data. What do you think will happen when we swap source and target ability? Placeholder becomes the source, the ability we want to hide becomes the target. Our unit does not possess Placeholder in the beginning. Nothing will happen when we add ANeg. When we take ANeg away again, however, it will "revert" our original ability by Placeholder. Transformation successful, without keeping ANeg.

    The reason I have not suggested this above is because it needs another ANeg now to get from Placeholder to the original ability, one more object.

    Additional information on morphing units: A unit will lose all abilities which the target unit type does not possess, while morphing, unless you apply the function
    UnitMakeAbilityPermanent
    before. This is necessary to keep Placeholder/original ability. I usually have it combined with
    UnitAddAbility
    in a header function.
    UnitMakeAbilityPermanent
    does not have a GUI equivalent.

    Summarized:

    to disable ability:
    morph unit to hero
    add ANeg1 (Placeholder to original)
    remove ANeg1 (Placeholder to original)
    morph unit back

    to enable ability:
    morph unit to hero
    add ANeg2 (original to Placeholder)
    remove ANeg2 (original to Placeholder)
    morph unit back

    Finally, I would like to recommend the morphing method and make some comments on the hero unit type.

    Of course, we want to be able to do this without any delay. Therefore, the active ones like Metamorphosis are no good, you would also need to trigger orders etc., which would again interrupt casts. Chaos (Srtt) is not sufficient either as it suffers from some minimal delay. The choice goes to the method described here. The trick it makes use of is practically the same as in Reversed Engineering.

    Comments on the hero unit type: Blizzard did not account for morphing units into heroes/backwards. Heroes benefit from hero attributes, which influence stats such as hitpoints or armor. When the unit reverts into non-hero form, those bonuses are not dissolved, so the unit ends up with false values. To counter this, just set hero attributes to zero. Also set the base armor value of heroes to 0 (gameplay constant Hero Attribute - Defense Base (before Agility Bonus)). You can equalize this by manually adding the default base armor to each hero in your map. In addition, check Values - Hero - Hide Hero Interface Icon, else the hero portrait will persist.

    Test maps are attached.
     

    Attached Files:

  2. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,430
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    Wow this works beautifully. :) This is a very creative technique and props for testing it thoroughly/getting it to work for regular units.

    Approved.
     
  3. defskull

    defskull

    Joined:
    Mar 27, 2008
    Messages:
    7,978
    Resources:
    17
    Spells:
    17
    Resources:
    17
    I have just found out that if you use this Event, it won't work.

    • Unit - A unit Starts the effect of an ability


    Why ?
    Because the Event loaded first, doesn't even give the caster a chance to successfully cast the spell, therefore, the spell will be "removed" or hidden and its cooldown won't goes off because technically, the spell isn't being cast at all.

    Solution: Use Unit - A unit Finishes casting an ability
     
  4. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,035
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    You should always use the end cast event unless your spell is channeling. You just need to transfer the event responses from spell effect. Well, you would build your own events anyway rather than to write native solutions everywhere.

    Since ANcl abilities can be hidden on certain levels and switching the ability levels does not revoke the cooldown, is there any point to prefer the approach here?
     
  5. defskull

    defskull

    Joined:
    Mar 27, 2008
    Messages:
    7,978
    Resources:
    17
    Spells:
    17
    Resources:
    17
    Well, my point is to point out that you should not use that Event, maybe you should include that in the main post ?
    Users need to know the limit/boundary of a certain solution.

    Are you trying to say that if your spell is channeling, it's okay to use A unit Starts the effect of an ability ?
    If this is what you're saying, then it's wrong.
    You still won't be able to make it goes on cooldown if you use that Event, Channeling or non-channelling spell - or perhaps I'm mistaken for your statement.
     
  6. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,035
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    My point is that you would want to detect the start of a channeling spell but end cast fires afterwards.
     
  7. Cokemonkey11

    Cokemonkey11

    Wurst Reviewer

    Joined:
    May 9, 2006
    Messages:
    3,271
    Resources:
    18
    Tools:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    2
    JASS:
    7
    Resources:
    18
    This is a great tutorial. I've tried implementing it in my Orianna spellpack (which had this existing bug that the previous method I was using didn't passify an ability)

    But just like the existing version, the passification fails to work.

    Maybe you have an idea of what's wrong? Casting Q, E, and R should temporarily make all abilities passive, and when they return their cooldowns should persist.
     

    Attached Files:

  8. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,035
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    The signature of the abilities you want to swap should be the same (use another channel ability). Else a lot of strange stuff can happen because part of the original spells properties are transfered. In your map, the passive abilities actually are given to the unit but are not displayed.

    Anyway, with channel, you can simply append a level that is not visible and change to that one while it should be disabled. In my map, I did well with completely disconnecting the hero skill menu from the actual spells the unit can cast.
     
  9. Cokemonkey11

    Cokemonkey11

    Wurst Reviewer

    Joined:
    May 9, 2006
    Messages:
    3,271
    Resources:
    18
    Tools:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    2
    JASS:
    7
    Resources:
    18
    Oh. That sounds important, maybe put it in the tutorial.

    Yeah, but I had a problem with that, which is why I'm trying other methods. Maybe you have an idea of what's wrong there - http://www.hiveworkshop.com/forums/spells-569/orianna-spellpack-1-0-1-a-244925/
     
  10. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,035
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    line 653: you check the disabled ability instead of the original

    You should not mess with the ability on SPELL_EFFECT, since it is still being casted there.
     
  11. Cokemonkey11

    Cokemonkey11

    Wurst Reviewer

    Joined:
    May 9, 2006
    Messages:
    3,271
    Resources:
    18
    Tools:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    2
    JASS:
    7
    Resources:
    18
    This is a mistake in the pasted script, but doesnt exist in the uploaded map (oops)

    If I change it to SPELL_FINISH it fails because SPELL_FINISH doesn't include data for GetSpellTargetX(), among other things. I could put everything on a short timer to *try* this solution but it would take a lot of time. How confident are you that that's the problem?
     
  12. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,035
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    I did not know about that or forgot it. Most abilities in my map are Channel, thus I might not have observed it.

    I tested it. I converted it to a trigger action and put a wait in the orianna.attack function. If you do it on SPELL_EFFECT, the ability's level is changed and then is cast -> since you currently do not have a proper sixth level in object editor, you gain the default properties of Channel.

    It's fairly easy to store the event responses of SPELL_EFFECT on the caster and then retrieve them on SPELL_ENDCAST or SPELL_FINISH.

    Ps: I believe Brilliance Aura was said to be able to fatal on IncUnitAbilityLevel. If you need passive icons for show, take abilities that really do nothing else like Gyrocopter Bombs or Moon Glaives. You do not need to cast them, so any amount of them on a single unit works.
     
  13. Cokemonkey11

    Cokemonkey11

    Wurst Reviewer

    Joined:
    May 9, 2006
    Messages:
    3,271
    Resources:
    18
    Tools:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    2
    JASS:
    7
    Resources:
    18
    In my map it was also channel. Is there a good passive ability icon to replace channel with that won't cause side-effects?


    I didn't have to! I used a timer with a duration of 0. and it worked perfectly. Thanks so much, this bug has been around for nearly a year.

    Yes, you have looked at two versions so far. One increments channel to a hidden slot but was broken because incabilitylevel to a hidden slot in the same thread as the SPELL_EFFECT condition caused it to reset cooldown.

    The other version used the thing described in this tutorial.

    The new version (and the solution) works like the first, but adds a timer before calling Orianna.attack().

    Thanks again.
     
  14. WaterKnight

    WaterKnight

    Joined:
    Aug 18, 2009
    Messages:
    4,035
    Resources:
    5
    Maps:
    1
    Tutorials:
    4
    Resources:
    5
    You can level Channel into invisibility, then give the unit another passive ability. Gyrocopter Bombs or Moon Glaives are good because they are just for show, their gameplay effects as you know from melee are done via researches.
     
  15. Cokemonkey11

    Cokemonkey11

    Wurst Reviewer

    Joined:
    May 9, 2006
    Messages:
    3,271
    Resources:
    18
    Tools:
    1
    Maps:
    5
    Spells:
    3
    Tutorials:
    2
    JASS:
    7
    Resources:
    18
    Right, that's what I've always been doing, but after ~a year of that aforementioned bug I tried using tinker upgrade instead.
     
  16. Xisthename

    Xisthename

    Joined:
    Mar 10, 2013
    Messages:
    4
    Resources:
    0
    Resources:
    0
    This is amazing! Just what i needed for my star wars map :D
     
  17. Legal_Ease

    Legal_Ease

    Joined:
    Feb 8, 2013
    Messages:
    1,453
    Resources:
    28
    Icons:
    11
    Packs:
    1
    Skins:
    2
    Maps:
    10
    Template:
    1
    Tutorials:
    3
    Resources:
    28
    But what if I want to silence just one ability to show the disabled icon?
     
  18. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,430
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    • Use the steps given in the tutorial to disable the ability.
    • Add a dummy ability with the disabled icon--base it off a passive so it cannot be cast. Make sure it has the same button position as the active ability.
    • Note: when you pause, you'll get a green icon (assuming you used a DISBTN as the "active" icon for an ability). To fix this, you'll have to import the DISBTN as a BTN and import a copy of it as its DISBTN*. It is redundant, but it works.


    *Technically, you can save a bit of space using this method, but the technique hasn't been polished yet.
     
  19. dtnmang

    dtnmang

    Joined:
    Apr 20, 2010
    Messages:
    562
    Resources:
    12
    Models:
    5
    Maps:
    2
    Ported Models:
    1
    Tutorials:
    4
    Resources:
    12
    If I use this to disable a Spell Book, will the passive spells in the book still work? (Sorry, don't have Warcraft 3 near me right now)
     
  20. Ender Wiggins

    Ender Wiggins

    Joined:
    Mar 29, 2020
    Messages:
    556
    Resources:
    4
    Icons:
    3
    Maps:
    1
    Resources:
    4
    is there any way to use this to make the "build" ability invisible (yet usable) for only 1 unit type?