[Trigger] Cancel Specific Instance of a MUI

Status
Not open for further replies.
Level 3
Joined
Jun 9, 2009
Messages
38
First of all, I'd like to thank everyone who's been here to help. You guys are really good at all this coding, and I give you props for that. Been a really big help to me in my map making.


All these triggers working together make a link between two buildings. The Link transfers mana between the two buildings at a specified rate (1 mana per 1s).

  • PT
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • ((Triggering unit) is A structure) Equal to True
    • Actions
      • Set integers[1] = (integers[1] + 1)
      • Set turnoff[integers[1]] = False
      • Set casting[integers[1]] = (Triggering unit)
      • Set casted[integers[1]] = (Target unit of ability being cast)
      • Lightning - Create a Chain Lightning - Secondary lightning effect from source (Position of casted[integers[1]]) to target (Position of casting[integers[1]])
      • Set lightning[integers[1]] = (Last created lightning effect)
      • Trigger - Turn on loop <gen>
  • loop
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
      • turnoff[integers[1]] Equal to False
      • (Mana of casting[integers[1]]) Greater than or equal to 5.00
    • Actions
      • For each (Integer integers[2]) from 1 to integers[1], do (Actions)
        • Loop - Actions
          • Unit - Set mana of casting[integers[2]] to ((Mana of casting[integers[2]]) - 1.00)
          • Unit - Set mana of casted[integers[2]] to ((Mana of casted[integers[2]]) + 1.00)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • turnoff[integers[2]] Equal to True
            • Then - Actions
              • Lightning - Destroy lightning[integers[2]]
              • Custom script: call SetUnitPosition(GetTriggerUnit(), GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()))
            • Else - Actions
  • PTCancel
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Cancel Transfers
      • ((Triggering unit) is A structure) Equal to True
    • Actions
      • Set turnoff[integers[1]] = True
The cancel trigger right now only cancels the most recently made link.

Is there a way to cancel a specific link between buildings? Or at least cancel all links to a specific building.

EDIT: I am in the process of learning JASS. Will take a bit though.
 
Last edited:
Level 3
Joined
Aug 9, 2008
Messages
60
Why not have a global array of units that have started the ability, and when a unit begins cancel transfer, loop through the global array checking if it's the unit that started the link, when you find the unit cancel the specific link.
 
Level 3
Joined
Jun 9, 2009
Messages
38
That certainly sounds like it will work. Can you give an example though? I'd see it alot better if I can see where I would change stuff.

Also I assume that it will make my PTCancel trigger null.
 
Level 3
Joined
Aug 9, 2008
Messages
60
By the way, when a unit cancels the link, he also starts one up, because your first trigger doesn't have a condition which checks if the ability is start or end link.

And your integers never decreases, so after 8191 units this will stop working.

Anyways, I don't GUI so I can't help, sorry.
 
Level 3
Joined
Jun 9, 2009
Messages
38
By the way, when a unit cancels the link, he also starts one up, because your first trigger doesn't have a condition which checks if the ability is start or end link.

What do you mean also starts one up? I noticed that it has to send another 1 mana before it checks for the cancel boolean. I put that in it's own if/the/else.

  • loop
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
      • turnoff[integers[1]] Equal to False
      • (Mana of casting[integers[1]]) Greater than or equal to 5.00
    • Actions
      • For each (Integer integers[2]) from 1 to integers[1], do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • turnoff[integers[2]] Equal to False
            • Then - Actions
              • Unit - Set mana of casted[integers[2]] to ((Mana of casted[integers[2]]) + 1.00)
              • Unit - Set mana of casting[integers[2]] to ((Mana of casting[integers[2]]) - 1.00)
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • turnoff[integers[2]] Equal to True
            • Then - Actions
              • Lightning - Destroy lightning[integers[2]]
              • Custom script: call SetUnitPosition(GetTriggerUnit(), GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()))
            • Else - Actions
And your integers never decreases, so after 8191 units this will stop working.


I remember someone somewhere mentioning a returnindex script, that would reuse indexes or so. Does anyone have a clue?
 
Level 3
Joined
Aug 9, 2008
Messages
60
Your first trigger doesn't check what spell the building is casting, so whenever building casts ANY spell, the trigger will start.

Also, when the building stops casting, you should lower the index, and remove everything that was associated with it.
 
Level 3
Joined
Jun 9, 2009
Messages
38
  • Then - Actions
    • Lightning - Destroy lightning[integers[2]]
    • Custom script: call SetUnitPosition(GetTriggerUnit(), GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()))
    • Set integers[1] = (integers[1] - 1)
Kinda like so? I also added the ability check at the beginning of the trigger that initiates the loop.
 
Level 3
Joined
Aug 9, 2008
Messages
60
  • Then - Actions
    • Lightning - Destroy lightning[integers[2]]
    • Custom script: call SetUnitPosition(GetTriggerUnit(), GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()))
    • Set integers[1] = (integers[1] - 1)
Kinda like so? I also added the ability check at the beginning of the trigger that initiates the loop.

You're not nearly done yet.

EXAMPLE:

Lets say you have four buildings: A,B,C,D.

A and B buildings are the ones with energy transfer, buildings C and D are the ones who are to receive the energy.

If building A started the link with C, and B started the link with D, you would have two instances of your spell.

Now, let's say, for some reason, you decide to cancel your A's ability.

You index will be reduced to one, without doing any additional work, making your loop STILL actively channel the ability started by A, and stop working for B, which is completely opposite of what you wanted.

What you will have to do to solve this, is actually take the spot of the last instance of the ability being casted (which in this case is building B, value being 2), and move all those values to the instance being canceled (which in this case is building A, value being 1), after you do that, you can safely reduce the index.

Another way of going about this, is simply looping through all instances and lowering their numbers down by one, but it's very inefficient and this method is just as easy to do, without the extra useless computing time.



(Noticed you use an array for your two integer values, simply making two integers would make your coding much easier, since you won't have to keep going to grab the index of the array... most of the time it's 1 anyways. Side note of another note: integers are faster than integer arrays, so you really have no reason to be using an array, and a reason to be using a normal integer instead.)
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
The easiest way to make this kind of things is using custom value with structs.
There are most likely syntax errors so don't wonder if this doesn't work exactly as it is.
JASS:
struct Link
    unit target
endstruct

function CreateLink takes unit base, unit target returns nothing
    local Link lb = Link.create()
    local Link lt = Link.create()
    set lb.target = base
    set lt.target = target

    call SetUnitData(base,lb) // I do not remember if this is the right syntax
    call SetUnitData(target,lt)

    // whatever else you want

endfunction

function DestroyLink takes unit base returns nothing
    local Link lb = GetUnitData(base)
    local Link lt = GetUnitData(lb.target)

    // not sure if this is needed
    call SetUnitData(base,0)
    call SetUnitData(target,0)

    // this is needed.
    call lb.destroy()
    call lt.destroy()
endfunction

You will, of course, probably want to add more info to the link, which is the easiest thing to do with structs.

[edit] If units can have multiple links, you'd want to use arrays of units in the struct. Since arrays are limited to a preset number (and you do not want big arrays in structs since they limit the instance capacity), you'd maybe prefer to move to another solution.
 
Status
Not open for further replies.
Top