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

Refund mana cost

Status
Not open for further replies.
Level 2
Joined
Mar 6, 2020
Messages
14
Hello,

I want that my abilities can only be cast on Dark Grass. I already achieved this with the following trigger:
  • SummonHeadhunters
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Ability being cast) Equal to 003 Summon Headhunter
          • (Ability being cast) Equal to 203 Summon Headhunter
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Terrain type at (Target point of ability being cast)) Equal to Lordaeron Summer - Dark Grass
        • Then - Actions
          • Game - Display to (All players) the text: Casting summon head...
          • Set VariableSet loc = (Position of (Triggering unit))
          • Set VariableSet loc2 = (Target point of ability being cast)
          • Set VariableSet loc3 = ((Target point of ability being cast) offset by (0.00, 175.00))
          • Set VariableSet loc4 = ((Target point of ability being cast) offset by (0.00, -175.00))
          • Unit - Create 1 DummyHeadhunterCaster for (Owner of (Triggering unit)) at loc facing Default building facing degrees
          • Unit - Order (Last created unit) to Orc Shadow Hunter - Serpent Ward loc2
          • Unit - Create 1 DummyHeadhunterCaster for (Owner of (Triggering unit)) at loc facing Default building facing degrees
          • Unit - Order (Last created unit) to Orc Shadow Hunter - Serpent Ward loc3
          • Unit - Create 1 DummyHeadhunterCaster for (Owner of (Triggering unit)) at loc facing Default building facing degrees
          • Unit - Order (Last created unit) to Orc Shadow Hunter - Serpent Ward loc4
          • Custom script: call RemoveLocation(udg_loc)
          • Custom script: call RemoveLocation(udg_loc2)
          • Custom script: call RemoveLocation(udg_loc3)
          • Custom script: call RemoveLocation(udg_loc4)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Owner of (Triggering unit)) Equal to Player 1 (Red)
            • Then - Actions
              • Trigger - Run CycleRedDeck <gen> (checking conditions)
            • Else - Actions
              • Trigger - Run CycleBlueDeck <gen> (checking conditions)
        • Else - Actions
          • Game - Display to (All players) the text: You are not allowed...
          • Unit - Order (Triggering unit) to Stop.
          • Unit - Set mana of (Triggering unit) to ((Unit: (Triggering unit)'s Real Field: Mana ('umpc')) + (Real((Mana cost of (Ability being cast), Level 0.))))
If the target is not Dark Grass, i order the unit to stop casting. Then, I want to refund the mana. However, this does not work for the following reason:
1. Unit casts ability
2. Trigger runs, adds mana to the unit
3. Warcraft substracts manacost from the unit

As you can see this is not the right order... It should be like this:
1. Unit casts ability
2. Warcraft substract manacost from the unit
3. Trigger adds mana to the unit

Please, can someone have a look at it and give me a better solution? I really have no idea how to make this work...

Thank you in advance!
 
Last edited:
Level 13
Joined
Nov 4, 2006
Messages
1,239
i had literally the exact same problem, i bypassed it by adding a 0.1s wait to the else actions, since triggering unit doesn't get lost after a wait. should even still be MUI, right?

  • Else - Actions
    • Wait 0.10 seconds
    • Unit - Set mana of (Triggering unit) to ((Mana of (Triggering unit)) + ((Real((Level of Magmaexplosion (Firebeast) (Hero) for (Triggering unit)))) x 50.00))
    • Unit - For Unit (Triggering unit), end cooldown of ability Magmaexplosion (Firebeast) (Hero)
    • Game - Display to (Player group((Owner of (Triggering unit)))) the text: This ability has to...
 
Level 2
Joined
Mar 6, 2020
Messages
14
Try using "A unit Begins casting of an ability" instead. This event fires before the ability is casted without consuming mana or cooldown.

This does not work. Still consuming mana. Maybe because all my spells are instant and therefore the stop command does not work idk.

i had literally the exact same problem, i bypassed it by adding a 0.1s wait to the else actions, since triggering unit doesn't get lost after a wait. should even still be MUI, right?

  • Else - Actions
    • Wait 0.10 seconds
    • Unit - Set mana of (Triggering unit) to ((Mana of (Triggering unit)) + ((Real((Level of Magmaexplosion (Firebeast) (Hero) for (Triggering unit)))) x 50.00))
    • Unit - For Unit (Triggering unit), end cooldown of ability Magmaexplosion (Firebeast) (Hero)
    • Game - Display to (Player group((Owner of (Triggering unit)))) the text: This ability has to...

Yup this actually works. But I am not so sure about the wait... I am not very experienced with the wc3 editor, but i read somewhere that you should avoid wait if possible.
 
Level 13
Joined
Nov 4, 2006
Messages
1,239
yeah i know, but it was no issue in my map since i didn't need the spell to be MUI, and while waits are of course not always great, sometimes they are the easiest solution. you could probably also work with a timer or something.

i suggest you try if it works with multiple units at the same time, if yes, everything is fine, if not you have to look for something else
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
You can also interrupt a unit in response to an issued order. Something like this:

  • Interrupt Order
    • Events
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order with no target
    • Conditions
      • (Issued order) Not equal to (Order(move))
      • (Issued order) Not equal to (Order(smart))
      • (Issued order) Not equal to (Order(stop))
      • (Issued order) Not equal to (Order(attack))
      • (Issued order) Not equal to (Order(holdposition))
      • (Issued order) Not equal to (Order(patrol))
    • Actions
      • Trigger - Turn off (This trigger)
      • Set VariableSet OrderPoint = (Position of (Ordered unit))
      • Unit - Order (Ordered unit) to Move To OrderPoint
      • Custom script: call RemoveLocation (udg_OrderPoint)
      • Trigger - Turn on (This trigger)
It's usually easier to filter out the orders that you don't want to cancel rather than the ones that you do.

So with this trigger, if the unit uses any ability the order will get interrupted.

You could add the terrain check to the conditions, but that will leak a point so you're better off using an If Then Else in the actions.

Set Point = position of triggering unit -> If terrain at Point equal to X then -> Interrupt the order -> Remove Point

This does not work. Still consuming mana. Maybe because all my spells are instant and therefore the stop command does not work idk.

Yup this actually works. But I am not so sure about the wait... I am not very experienced with the wc3 editor, but i read somewhere that you should avoid wait if possible.
Waits in this case are fine because you're referencing "Triggering Unit" which works like a local variable.

That being said, certain information is lost when you use a Wait such as "Target point of ability being cast". Also, some other Event Responses are treated like global variables so they can potentially get replaced during the Wait.

i had literally the exact same problem, i bypassed it by adding a 0.1s wait to the else actions, since triggering unit doesn't get lost after a wait. should even still be MUI, right?

  • Else - Actions
    • Wait 0.10 seconds
    • Unit - Set mana of (Triggering unit) to ((Mana of (Triggering unit)) + ((Real((Level of Magmaexplosion (Firebeast) (Hero) for (Triggering unit)))) x 50.00))
    • Unit - For Unit (Triggering unit), end cooldown of ability Magmaexplosion (Firebeast) (Hero)
    • Game - Display to (Player group((Owner of (Triggering unit)))) the text: This ability has to...
You can get the mana cost of an ability using:
  • Set Variable Integer = (For (Triggering unit), Mana cost of (Ability being cast), Level 0.)
The level is actually indexed starting at 0, which means that Level 0 = level 1, Level 1 = level 2, etc... The easiest way to handle this would be some simple arithmetic: "Level (level of ability being cast - 1)"

Also, I believe Ability being cast is lost when you use a Wait so you would have to track the ability in some other way. The easiest method for GUI users would be shadowed global variables which can be done fairly easily: local udg_
 
Last edited:
Level 2
Joined
Mar 6, 2020
Messages
14
Waits in this case are fine because you're referencing "Triggering Unit" which works like a local variable.

That being said, certain information is lost when you use a Wait such as "Target point of ability being cast". Also, some other Event Responses are treated like global variables so they can potentially get replaced during the Wait.
Thanks for making this clear. I will use wait then.

Also thanks for the other suggestion. Maybe I might use this somewhere else.


You could add the terrain check to the conditions, but that will leak a point so you're better off using an If Then Else in the actions.

Set Point = position of triggering unit -> If terrain at Point equal to X then -> Interrupt the order -> Remove Point

Ok so when i understand you correctly my following code leaks a point?
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Terrain type at (Target point of ability being cast)) Equal to Lordaeron Summer - Dark Grass
    • Then - Actions
      • Game - Display to (All players) the text: Casting summon hawks
    • Else - Actions
      • Game - Display to (All players) the text: You are not allowed...
is this better?

  • Set VariableSet pos = (Target point of ability being cast)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Terrain type at pos) Equal to Lordaeron Summer - Dark Grass
    • Then - Actions
      • Game - Display to (All players) the text: Casting summon hawks
    • Else - Actions
      • Game - Display to (All players) the text: You are not allowed...
  • Custom script: call RemoveLocation(udg_pos)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
is this better?
  • Set VariableSet pos = (Target point of ability being cast)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Terrain type at pos) Equal to Lordaeron Summer - Dark Grass
    • Then - Actions
      • Game - Display to (All players) the text: Casting summon hawks
    • Else - Actions
      • Game - Display to (All players) the text: You are not allowed...
  • Custom script: call RemoveLocation(udg_pos)
Yep, that's exactly how you'd do it.
 
Status
Not open for further replies.
Top