Complicated Merging of Two Units

Level 19
Joined
May 29, 2013
Messages
1,554
Is there a way to make an ability that works like this?
  • permanently merges two units of the same type (similar to 'Mount Hippogryph')
  • has a gold and lumber cost
  • can't be cast if the player doesn't have enough resources
  • can't be cast if the newly formed unit's food cost is greater than the sum of food costs of merging units (shouldn't allow exceeding of food limit by merging units)
 
Level 22
Joined
Feb 27, 2007
Messages
3,784
Yes, but one of your requirements will need to be reconciled: it can't have a gold/lumber cost in the tooltip (and thus automatically charged to the player) if it's not based on Charge Gold & Lumber, but CG&L can't be unit-targeted. Solution: automatically choose to merge with the closest available unit. Also of note: you can set CG&L's base order id to anything you want, which you will need to use later

Aside from that, base a new 'dummy' ability on CG&L as well as another one on Mount Hippogryph (with the right fields for your morph). When the dummy ability is cast ("starts the effect of an ability"), add the Mount ability to the unit and order it to "coupletarget" the closest partner unit. You can also make your own Dismount-based ability (and corresponding CG&L) to undo the merge in the same fashion.

To disallow combining if not enough food you'll have to detect when one of the units that can merge is ordered to <whatever the base order of your CG&L ability is>. Compute if the new food would be over the player's cap, and if so order the triggering unit to "stop". You can play an error message with SimError.
 
Level 14
Joined
Nov 30, 2013
Messages
922
I don't know if this works, this is the Trigger for the customized "Mount"
  • Merge
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Mount Hippogryph
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • ((Owner of (Casting unit)) Current gold) Greater than or equal to Cost
              • ((Owner of (Casting unit)) Current lumber) Greater than or equal to Cost
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (((Owner of (Casting unit)) Food cap) - (((Owner of (Casting unit)) Food used) + 1[Additional Food Cost] )) Greater than or equal to 0
            • Then - Actions
              • Unit - Replace (Casting unit) with a (Unit) using The old unit's relative life and mana
              • Unit - Remove (Target unit of ability being cast) from the game
              • -------- Identify if the player have all requirements. --------
            • Else - Actions
              • Unit - Order (Casting unit) to Stop
              • -------- Identify if the player doesn't have enough food. --------
        • Else - Actions
          • Unit - Order (Casting unit) to Stop
          • -------- Identify if the player doesn't have enough resources. --------
Use Mount ability and change its data anyway. :p
 

Kyrbi0

Arena Moderator
Level 38
Joined
Jul 29, 2008
Messages
8,991
Is there a way to make an ability that works like this?
  • permanently merges two units of the same type (similar to 'Mount Hippogryph')
  • has a gold and lumber cost
  • can't be cast if the player doesn't have enough resources
  • can't be cast if the newly formed unit's food cost is greater than the sum of food costs of merging units (shouldn't allow exceeding of food limit by merging units)
It's like you and I are making the same custom race. o_O

ARCHON ARCHON ARCHON ARCHON ARCHON

Yes, but one of your requirements will need to be reconciled: it can't have a gold/lumber cost in the tooltip (and thus automatically charged to the player) if it's not based on Charge Gold & Lumber, but CG&L can't be unit-targeted. Solution: automatically choose to merge with the closest available unit. Also of note: you can set CG&L's base order id to anything you want, which you will need to use later

Aside from that, base a new 'dummy' ability on CG&L as well as another one on Mount Hippogryph (with the right fields for your morph). When the dummy ability is cast ("starts the effect of an ability"), add the Mount ability to the unit and order it to "coupletarget" the closest partner unit. You can also make your own Dismount-based ability (and corresponding CG&L) to undo the merge in the same fashion.

To disallow combining if not enough food you'll have to detect when one of the units that can merge is ordered to <whatever the base order of your CG&L ability is>. Compute if the new food would be over the player's cap, and if so order the triggering unit to "stop". You can play an error message with SimError.
Woah. Way useful (really need to mess around with CG&L more), but... Doesn't (Dis)Mount work perfectly well for this? Well, minus the "gold/lumber cost" & "food stoppage" parts...
 
Level 22
Joined
Feb 27, 2007
Messages
3,784
It does, which is why I suggested Hermit use it. The gold cost thing seemed more important than having it not be a 'dummy' ability on the unit.

As a side note I attempted to morph things into/out of CG&L with Engineering upgrade, and found some sad things. If you morph a spell into CG&L it loses the resource cost and stays non-targetd. If you morph it into another spell that new spell gains a gold and lumber cost equal to <DataA1> and <DataB1> respectively... but loses all of its affects and becomes non-targeted.
 
Level 22
Joined
Feb 27, 2007
Messages
3,784
If you alter the first ability it seems to have no effect. If you alter the second ability you do get the icon of that ability so I think it is actually loading it in some way. And of course the data fields.
 
Level 19
Joined
May 29, 2013
Messages
1,554
Charge Gold & Lumber
I had the same idea and thought about using a dummy ability based on Charge Gold and Lumber, but won't that just spend resources even if there's no couple target nearby and the merge doesn't happen?
You can play an error message with SimError.

  • Custom script: if udg_ErrorSound == null then
  • Custom script: set udg_ErrorSound = CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
  • Custom script: endif
  • Custom script: if GetLocalPlayer() == udg_ErrorPlayer then
  • Custom script: call ClearTextMessages()
  • Custom script: call DisplayTimedTextToPlayer( udg_ErrorPlayer, 0.52, 0.96, 2.00, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+udg_ErrorMessage+"|r" )
  • Custom script: call StartSound(udg_ErrorSound)
  • Custom script: endif

I don't know if this works, this is the Trigger for the customized "Mount"
  • Merge
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Mount Hippogryph
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • ((Owner of (Casting unit)) Current gold) Greater than or equal to Cost
              • ((Owner of (Casting unit)) Current lumber) Greater than or equal to Cost
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (((Owner of (Casting unit)) Food cap) - (((Owner of (Casting unit)) Food used) + 1[Additional Food Cost] )) Greater than or equal to 0
            • Then - Actions
              • Unit - Replace (Casting unit) with a (Unit) using The old unit's relative life and mana
              • Unit - Remove (Target unit of ability being cast) from the game
              • -------- Identify if the player have all requirements. --------
            • Else - Actions
              • Unit - Order (Casting unit) to Stop
              • -------- Identify if the player doesn't have enough food. --------
        • Else - Actions
          • Unit - Order (Casting unit) to Stop
          • -------- Identify if the player doesn't have enough resources. --------
Use Mount ability and change its data anyway. :p
I wasn't sure how to make the food cap condition. Thank you.
It's like you and I are making the same custom race. o_O
Great minds think alike. :p
 
Level 22
Joined
Feb 27, 2007
Messages
3,784
I had the same idea and thought about using a dummy ability based on Charge Gold and Lumber, but won't that just spend resources even if there's no couple target nearby and the merge doesn't happen?
You either have to refund the resource cost when no targets can be found or trigger the cost (and appropraite error) yourself and only use a Mount ability. Pick your poison.

That is literally what SimError does line-for-line except you would only have to use one line to call it in your triggers. I mean or at least write your own function for it in the Custom Script header.
 

Kyrbi0

Arena Moderator
Level 38
Joined
Jul 29, 2008
Messages
8,991
You either have to refund the resource cost when no targets can be found or trigger the cost (and appropraite error) yourself and only use a Mount ability. Pick your poison.
"Delectable tea... Or deadly poison."

Pyrogasm said:
That is literally what SimError does line-for-line except you would only have to use one line to call it in your triggers. I mean or at least write your own function for it in the Custom Script header.
Yeah, but then I'd be introducing a nasty function into my pristine World Editor. Can't have that.
 
Level 19
Joined
May 29, 2013
Messages
1,554
You either have to refund the resource cost when no targets can be found or trigger the cost (and appropraite error) yourself and only use a Mount ability. Pick your poison.
How can I detect if there are no nearby targets? I'm also worried what would happen if one of the units dies/gets stunned/Hexed/Possesed/etc. before the merging can happen.
That is literally what SimError does line-for-line except you would only have to use one line to call it in your triggers. I mean or at least write your own function for it in the Custom Script header.
Well, I'm a noob so I like to stay away from JASS/vJASS.
 
Level 22
Joined
Feb 27, 2007
Messages
3,784
How can I detect if there are no nearby targets? I'm also worried what would happen if one of the units dies/gets stunned/Hexed/Possesed/etc. before the merging can happen.
Unit group of nearby units > filter out all non-player units > filter out all units of incorrect type to merge with > pick the closest remaining unit > if no unit then refund the resource cost. Another solution would be to ALWAYS refund the resource cost immediately on cast of the CG&L skill and then resubtracting it when the units successfully cast the merge spell.
Well, I'm a noob so I like to stay away from JASS/vJASS.
13 years later and this mentality just refuses to leave the community. I sincerely don't get it. You ARE using JASS constantly-- it's the triggers themselves and especially your 8 lines of custom script! Everyone who's ever submitted some vJASS library has wondered how a simple GUI user would attempt to use their code and made it as easy and simple for them as possible; they are intentionally self-contained so that people can use them.
 
Level 8
Joined
Jan 28, 2016
Messages
486
As a side note I attempted to morph things into/out of CG&L with Engineering upgrade, and found some sad things. If you morph a spell into CG&L it loses the resource cost and stays non-targetd. If you morph it into another spell that new spell gains a gold and lumber cost equal to <DataA1> and <DataB1> respectively... but loses all of its affects and becomes non-targeted.

Can confirm. The only difference was that I managed to make the ability unit targeting, however it still lost its resource cost after the conversion unfortunately.

I'm gonna have to crack down someday & make a big giant test map for just Engineering Upgrade, really sounding the unsounded.

Scratch that, "we're". It's obvious you have tested this at least partially. Collaboration?

If you want to save some more time and effort, you could have a look at my map here. It involves the use of the Bear Form trick, which might be of use in the context of this morphing issue as well.

Well, I'm a noob so I like to stay away from JASS/vJASS.

You could take all that custom script in your post and move it to the map header. Then whenever you need to a "SimError," you can use just one line of custom script to call the function.

JASS:
// Your custom script as a function for use in the map header.
// Note that it doesn't have any parameters as you're using globals.
function OnSpellFail takes nothing returns nothing
    if udg_ErrorSound == null then
        set udg_ErrorSound = CreateSoundFromLabel("InterfaceError",false,false,false,10,10)
    endif
    if GetLocalPlayer() == udg_ErrorPlayer then
        call ClearTextMessages()
        call DisplayTimedTextToPlayer( udg_ErrorPlayer, 0.52, 0.96, 2.00, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+udg_ErrorMessage+"|r" )
        call StartSound(udg_ErrorSound)
    endif
endfunction

// This is the function I use in my maps, which I "borrowed" from DotA.
function OnSpellFail takes player loc_player01, string loc_string01 returns nothing
    local sound loc_sound01 = CreateSoundFromLabel("InterfaceError",false,false,false,10,10)
    if (GetLocalPlayer() == loc_player01) then
        if (loc_string01 != "") and (loc_string01 != null) then
            call ClearTextMessages()
            call DisplayTimedTextToPlayer(loc_player01,0.50,-1.00,2.00,"|cffffcc00"+loc_string01+"|r")
        endif
        call StartSound(loc_sound01)
    endif
    call KillSoundWhenDone(loc_sound01)
endfunction
  • Test Trigger
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: call OnSpellFail()
 
Level 19
Joined
May 29, 2013
Messages
1,554
13 years later and this mentality just refuses to leave the community. I sincerely don't get it. You ARE using JASS constantly-- it's the triggers themselves and especially your 8 lines of custom script!
Programming was never my kind of thing. Even those 8 lines were not written by me.
You could take all that custom script in your post and move it to the map header. Then whenever you need to a "SimError," you can use just one line of custom script to call the function.

JASS:
// Your custom script as a function for use in the map header.
// Note that it doesn't have any parameters as you're using globals.
function OnSpellFail takes nothing returns nothing
    if udg_ErrorSound == null then
        set udg_ErrorSound = CreateSoundFromLabel("InterfaceError",false,false,false,10,10)
    endif
    if GetLocalPlayer() == udg_ErrorPlayer then
        call ClearTextMessages()
        call DisplayTimedTextToPlayer( udg_ErrorPlayer, 0.52, 0.96, 2.00, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+udg_ErrorMessage+"|r" )
        call StartSound(udg_ErrorSound)
    endif
endfunction

// This is the function I use in my maps, which I "borrowed" from DotA.
function OnSpellFail takes player loc_player01, string loc_string01 returns nothing
    local sound loc_sound01 = CreateSoundFromLabel("InterfaceError",false,false,false,10,10)
    if (GetLocalPlayer() == loc_player01) then
        if (loc_string01 != "") and (loc_string01 != null) then
            call ClearTextMessages()
            call DisplayTimedTextToPlayer(loc_player01,0.50,-1.00,2.00,"|cffffcc00"+loc_string01+"|r")
        endif
        call StartSound(loc_sound01)
    endif
    call KillSoundWhenDone(loc_sound01)
endfunction
  • Test Trigger
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: call OnSpellFail()
I'm not even sure how to do that, so I'd rather not complicate it. Also, I would need two error messages: - "Build more X to continue unit production." and "Unable to find couple target."


  • Events
    • Map initialization
  • Conditions
  • Actions
    • Set NoFood = GruntNoFood1 <gen>
    • Set ErrorMessage = Build more Orc Burrows to continue unit production.
    • Set Error = Error <gen>
    • Set UnableToFindTarget = Unable to find couple target.
  • Events
    • Unit - A unit Begins casting an ability
  • Conditions
    • (Ability being cast) Equal to Merge (Dummy)
  • Actions
    • Set MergeCaster = (Casting unit)
    • Set MergePlayer = (Owner of MergeCaster)
    • Set MergeGroup = (Units within 250.00 of (Position of MergeCaster) matching ((Unit-type of (Matching unit)) Equal to Merging Unit))
    • Unit Group - Remove MergeCaster from MergeGroup
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • ((MergePlayer Food used) + 4) Less than or equal to (MergePlayer Food cap)
      • Then - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Number of units in MergeGroup) Greater than or equal to 1
          • Then - Actions
            • Unit - Add Merge to MergeCaster
            • Unit - Remove Merge (Dummy) from MergeCaster
            • Unit - Order MergeCaster to Night Elf Archer - Mount Hippogryph
          • Else - Actions
            • Player - Set MergePlayer Current gold to ((MergePlayer Current gold) + 220)
            • Player - Set MergePlayer Current lumber to ((MergePlayer Current lumber) + 50)
            • Custom script: if udg_NoFood == null then
            • Custom script: set udg_NoFood = CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
            • Custom script: endif
            • Custom script: if GetLocalPlayer() == udg_MergePlayer then
            • Custom script: call ClearTextMessages()
            • Custom script: call DisplayTimedTextToPlayer( udg_MergePlayer, 0.52, 0.96, 2.00, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+udg_ErrorMessage+"|r" )
            • Custom script: call StartSound(udg_NoFood)
            • Custom script: endif
      • Else - Actions
        • Player - Set MergePlayer Current gold to ((MergePlayer Current gold) + 220)
        • Player - Set MergePlayer Current lumber to ((MergePlayer Current lumber) + 50)
        • Custom script: if udg_Error == null then
        • Custom script: set udg_Error = CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
        • Custom script: endif
        • Custom script: if GetLocalPlayer() == udg_MergePlayer then
        • Custom script: call ClearTextMessages()
        • Custom script: call DisplayTimedTextToPlayer( udg_MergePlayer, 0.52, 0.96, 2.00, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+udg_UnableToFindTarget+"|r" )
        • Custom script: call StartSound(udg_Error)
        • Custom script: endif
    • Custom script: call DestroyGroup(udg_MergeGroup)
 
Level 8
Joined
Jan 28, 2016
Messages
486
I'm not even sure how to do that, so I'd rather not complicate it. Also, I would need two error messages: - "Build more X to continue unit production." and "Unable to find couple target."


  • Events
    • Map initialization
  • Conditions
  • Actions
    • Set NoFood = GruntNoFood1 <gen>
    • Set ErrorMessage = Build more Orc Burrows to continue unit production.
    • Set Error = Error <gen>
    • Set UnableToFindTarget = Unable to find couple target.
  • Events
    • Unit - A unit Begins casting an ability
  • Conditions
    • (Ability being cast) Equal to Merge (Dummy)
  • Actions
    • Set MergeCaster = (Casting unit)
    • Set MergePlayer = (Owner of MergeCaster)
    • Set MergeGroup = (Units within 250.00 of (Position of MergeCaster) matching ((Unit-type of (Matching unit)) Equal to Merging Unit))
    • Unit Group - Remove MergeCaster from MergeGroup
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • ((MergePlayer Food used) + 4) Less than or equal to (MergePlayer Food cap)
      • Then - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Number of units in MergeGroup) Greater than or equal to 1
          • Then - Actions
            • Unit - Add Merge to MergeCaster
            • Unit - Remove Merge (Dummy) from MergeCaster
            • Unit - Order MergeCaster to Night Elf Archer - Mount Hippogryph
          • Else - Actions
            • Player - Set MergePlayer Current gold to ((MergePlayer Current gold) + 220)
            • Player - Set MergePlayer Current lumber to ((MergePlayer Current lumber) + 50)
            • Custom script: if udg_NoFood == null then
            • Custom script: set udg_NoFood = CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
            • Custom script: endif
            • Custom script: if GetLocalPlayer() == udg_MergePlayer then
            • Custom script: call ClearTextMessages()
            • Custom script: call DisplayTimedTextToPlayer( udg_MergePlayer, 0.52, 0.96, 2.00, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+udg_ErrorMessage+"|r" )
            • Custom script: call StartSound(udg_NoFood)
            • Custom script: endif
      • Else - Actions
        • Player - Set MergePlayer Current gold to ((MergePlayer Current gold) + 220)
        • Player - Set MergePlayer Current lumber to ((MergePlayer Current lumber) + 50)
        • Custom script: if udg_Error == null then
        • Custom script: set udg_Error = CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
        • Custom script: endif
        • Custom script: if GetLocalPlayer() == udg_MergePlayer then
        • Custom script: call ClearTextMessages()
        • Custom script: call DisplayTimedTextToPlayer( udg_MergePlayer, 0.52, 0.96, 2.00, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+udg_UnableToFindTarget+"|r" )
        • Custom script: call StartSound(udg_Error)
        • Custom script: endif
    • Custom script: call DestroyGroup(udg_MergeGroup)

Fair enough, no harm done. Thought I'd show how you could implement it and hey, you could always come back to this whenever you want or need to.

As for your trigger, it seems fine but you're gonna need to be a bit more specific as to what doesn't work. If there are no error messages displayed at all, then there might be something going on the Editor side of things (i.e.: one of the data fields of an ability isn't set correctly). Additionally, you're leaking a location when you set up the group.
 
Level 19
Joined
May 29, 2013
Messages
1,554
it seems fine but you're gonna need to be a bit more specific as to what doesn't work.
I attached a demo map so you could test it. It's really buggy:
  • It charges gold and lumber even when the merge doesn't happen.
  • It gives me the "Build more X to continue unit production" error even though I have enough food.
  • It gives me the "Unable to find couple target" error even if there are valid targets nearby.
  • It doesn't merge units even when all conditions are met (food, resources and a nearby target).
  • Sometimes, after many failed attempts, it actually merges two units.
there might be something going on the Editor side of things (i.e.: one of the data fields of an ability isn't set correctly).
I don't think the problem is related to object editor.
Additionally, you're leaking a location when you set up the group.
I thought that last line of custom script was supposed to fix the leak. How can I fix it?
 

Attachments

  • MergeDemo.w3x
    27.6 KB · Views: 42
Last edited:
Level 22
Joined
Feb 27, 2007
Messages
3,784
Caveat: I have not looked at your test map-- I made my own. Turns out you don't have to use both Mount/Pickup (you can get away with only one of them) but it requires a few things to be set properly for it to work at all:
  • Data - Move To Partner must be true for at least one of the merging abilities (even with 99999 Cast Range)
  • Stats - Area of Effect is the range that it searches in for a merge target
  • Stats - Cast Range is the max range from each other units will merge (if AoE > Cast Range they'll move to be within range before casting the merge)
  • The order to use the ability is not, in fact, coupletarget as the OE suggests but instead coupleinstant
  • The merging unit and all possible merge targets need to have the Mount ability for target searching to work (this means you can filter targets by selectively removing the ability)
  • The unit from which you 'cast' the merge must face the targeted merge unit to successfully cast the merge spell. This limitation cannot be subverted.

With that in mind this simple trigger works almost perfectly except for if the selected unit is not facing its new target:
  • Merge
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge Gold and Lumber
    • Actions
      • Player - Enable Mount Hippogryph for (Owner of (Triggering unit))
      • Custom script: set udg_DidCast = IssueImmediateOrder(GetTriggerUnit(), "coupleinstant")
      • Player - Disable Mount Hippogryph for (Owner of (Triggering unit))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DidCast Equal to False
        • Then - Actions
          • Player - Add 100 to (Owner of (Triggering unit)) Current gold
          • Player - Add 100 to (Owner of (Triggering unit)) Current lumber
        • Else - Actions
I was able to slightly mitigate this effect by moving the unit I guessed it was going to merge with to be right in front of the caster, but there are still cases where the units don't successfully merge.

  • Merge
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge Gold and Lumber
    • Actions
      • Set TempPoint = (Position of (Triggering unit))
      • Set TempPoint2 = (TempPoint offset by 50.00 towards (Facing of (Triggering unit)) degrees)
      • Set TempUnit = No unit
      • Set TempReal = 900.00
      • Unit Group - Pick every unit in (Units within TempReal of TempPoint) and do (Actions)
        • Loop - Actions
          • Set TempPoint3 = (Position of (Picked unit))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is alive) Equal to True
              • (Unit-type of (Picked unit)) Equal to Peasant
              • (Owner of (Picked unit)) Equal to (Owner of (Triggering unit))
              • (Distance between TempPoint and TempPoint3) Less than or equal to TempReal
              • (Picked unit) Not equal to (Triggering unit)
            • Then - Actions
              • Set TempReal = (Distance between TempPoint and TempPoint3)
              • Set TempUnit = (Picked unit)
            • Else - Actions
          • Custom script: call RemoveLocation(udg_TempPoint3)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • TempUnit Not equal to No unit
        • Then - Actions
          • Custom script: call SetUnitX(udg_TempUnit, GetLocationX(udg_TempPoint2))
          • Custom script: call SetUnitY(udg_TempUnit, GetLocationY(udg_TempPoint2))
          • Player - Enable Mount Hippogryph for (Owner of (Triggering unit))
          • Custom script: set udg_DidCast = IssueImmediateOrder(GetTriggerUnit(), "coupleinstant")
          • Player - Disable Mount Hippogryph for (Owner of (Triggering unit))
        • Else - Actions
          • Set DidCast = False
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DidCast Equal to False
        • Then - Actions
          • Player - Add 100 to (Owner of (Triggering unit)) Current gold
          • Player - Add 100 to (Owner of (Triggering unit)) Current lumber
        • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint)
      • Custom script: call RemoveLocation(udg_TempPoint2)
If you are okay with that occasional bug then this method will work for you. If you don't like that then your only options are to have the "mount hippogryff" ability always visible on the mergeable units in addition to the the CG&L ability that actually does it and have to stop the player from manually casting the mount... or only add the mount ability briefly to nearby units whenever the merge is requested and then immediately remove it from any unit that doesn't start a merge. Figuring out how exactly to do that will take a bit of experimenting.

Alternatively, just trigger the replacement of units yourself whenever the cast CG&L. At this point I think it will be easier just to do that .
 
Last edited:
Level 12
Joined
Mar 24, 2013
Messages
1,105
They don't actually "merge."

Mount: Hippo and Archer are removed and a Mounted Hippo is created. Dismount: Mounted Hippo is removed and a Hippo and Archer are created.

(It's possible that it recycles the previous Hippo and Archer but I'd doubt it).

I haven't tested it but, I'd guess that any reference to the original Hippo/Archer/(Mounted Hippo after dismount) is "lost" because it is just creating new.

Also on topic of the thread as Pyro said, it's definitely going to less cumbersome to just trigger a "fake" merge ability then to try and use built in features.

Edit: I'm actually curious about this, going to see if I can throw something together.
 
Last edited:
Level 8
Joined
Jan 28, 2016
Messages
486
what actually happens to the units when hippo mounting? which one gets referred to from unit variables and stuff after the merge? if they unmerge again which one keeps references they got while together?

Pretty much what @pOke said.

I'll need to go back and find that request I made for a fellow member involving a mount system but if I'm not mistaken, the unit targeting version of the two abilities (think it's the "old" one) keeps reference to the unit that casts the spell after coupling. Once they decouple however, two new units are created which ruined my initial attempt at the request. I might be wrong though; I'll double-check tomorrow.

This is getting crazy... All for a silly Archon morph.

I know but we're like, this close, to making it happen. And by we, I mean @Pyrogasm. :p

I thought that last line of custom script was supposed to fix the leak. How can I fix it?

The last line removes the unit group leak but not the location leak. I put together a short example in the spoiler below.

  • Leaks
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Merge (Dummy)
    • Actions
      • Set MergeCaster = (Triggering unit)
      • Set MergeLocation = (Position of MergeCaster)
      • Set MergeGroup = (Units within 250.00 of MergeLocation)
      • Custom script: call RemoveLocation(udg_MergeLocation)
      • Custom script: call DestroyGroup(udg_MergeGroup)
 
Level 12
Joined
Mar 24, 2013
Messages
1,105
So, I glanced through most of the thread. Hopefully I didn't do anything wrong haha.

So, I based the "Merge" on the Destroyer Form from Obsidian Statues. This lets us have the UI of Gold/Lumber and Food. It will also say "not enough X" as expected.

To begin:

Begins Channeling is used in Merge Cast. This will allow us to prevent the spell cast and we can check if the player has an appropriate unit to merge with. If not, debug msg. If so, find the closest appropriate unit, call it the partner. The partner then receives an invisible unit target spell based on channel and is ordered to cast it on the unit who requested the merge.

The partner will now be walking toward our unit who requested the merge. During this time should a player try to send the request again, a debug msg will appear saying that someone is coming. If either should die en route, the merge will be cancelled (currently there is a debug msg). If the partner receives an order of anything but "stun," the merge will be cancelled (currently there is a debug msg).

When the partner gets close enough to cast the invisible unit target spell. We catch it again with Begins Channeling, then we remove the partner from the game and order the requesting unit to morph to the "Merged" unit.

As it stands now, it doesn't take into account the partner's HP at the time, the newly merged unit will have the HP of the requesting unit as it was the one who morphed. You can easily set the requester's HP to some combination/portion of the partner and requester's HP if desired.

If the partner "merges" while the requester is stunned, the partner will disappear and after the stun the requester will morph as expected. Only potential problem is that long stuns could look odd or if they lead to the requester dying the player will have lost both.

You'll have to decide if/how you want to address these issues.

You'll probably want/need to change my debug msgs to be player specific or if they are needed at all.

Let me know if you have any problems, as I could have made a mistake, I'll post the code so others can hopefully spot any potential issues.

  • Merge Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: set udg_MU_Group = CreateGroup()
      • Set MU_MergeType = Peasant (Fake) // The unit type of the mergers.
  • Merge Cast
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Mortar Team // Merge Ability
    • Actions
      • Set TempUnit = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Partner for TempUnit) Equal to 1
        • Then - Actions
          • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
          • Unit Group - Remove MU_Partner[MU_MaxIndex] from MU_Group
          • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
          • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
          • Set MU_MaxIndex = (MU_MaxIndex - 1)
          • Game - Display to (All players) the text: Merge Successful
        • Else - Actions
          • Unit - Order TempUnit to Stop
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (TempUnit is in MU_Group) Equal to False
            • Then - Actions
              • Set TempPoint = (Position of TempUnit)
              • Set TempReal = 100000.00
              • Set TempUnit3 = No unit
              • Set TempGroup = (Units owned by (Owner of TempUnit))
              • Unit Group - Pick every unit in TempGroup and do (Actions)
                • Loop - Actions
                  • Set TempUnit2 = (Picked unit)
                  • Set TempPoint2 = (Position of TempUnit2)
                  • Set TempReal2 = (Distance between TempPoint and TempPoint2)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Unit-type of TempUnit2) Equal to MU_MergeType
                      • (TempUnit2 is alive) Equal to True
                      • TempUnit2 Not equal to TempUnit
                      • TempReal2 Less than TempReal
                      • (TempUnit2 is in MU_Group) Equal to False
                    • Then - Actions
                      • Set TempUnit3 = TempUnit2
                      • Set TempReal = TempReal2
                    • Else - Actions
                  • Custom script: call RemoveLocation(udg_TempPoint2)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TempUnit3 Not equal to No unit
                • Then - Actions
                  • Set MU_MaxIndex = (MU_MaxIndex + 1)
                  • Set MU_Caster[MU_MaxIndex] = (Triggering unit)
                  • Set MU_Partner[MU_MaxIndex] = TempUnit3
                  • Unit - Add Partner to MU_Partner[MU_MaxIndex]
                  • Unit - Order MU_Partner[MU_MaxIndex] to Undead Death Knight - Death Coil MU_Caster[MU_MaxIndex]
                  • Unit Group - Add MU_Caster[MU_MaxIndex] to MU_Group
                  • Unit Group - Add MU_Partner[MU_MaxIndex] to MU_Group
                  • Game - Display to (All players) the text: partner found
                • Else - Actions
                  • Game - Display to (All players) the text: No partner found.
              • Custom script: call RemoveLocation(udg_TempPoint)
              • Custom script: call DestroyGroup(udg_TempGroup)
            • Else - Actions
              • Game - Display to (All players) the text: Partner already on ...
  • Merge Cancel
    • Events
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order with no target
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • Custom script: if GetIssuedOrderId() == 851973 or GetIssuedOrderId() == 852222 then
      • -------- Don't cancel for Stunned Order and Partner --------
      • Custom script: return
      • Custom script: endif
      • For each (Integer TempInteger) from 1 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to MU_Partner[TempInteger]
            • Then - Actions
              • Unit - Remove Partner from MU_Partner[TempInteger]
              • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
              • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
              • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
              • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
              • Set MU_MaxIndex = (MU_MaxIndex - 1)
              • Game - Display to (All players) the text: Cancelled by Order
            • Else - Actions
  • Merge Dies Prior
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • For each (Integer TempInteger) from 1 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • TempUnit Equal to MU_Partner[TempInteger]
                  • TempUnit Equal to MU_Caster[TempInteger]
            • Then - Actions
              • Unit - Remove Partner from MU_Partner[TempInteger]
              • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
              • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
              • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
              • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
              • Set MU_MaxIndex = (MU_MaxIndex - 1)
              • Game - Display to (All players) the text: Cancelled by Death
            • Else - Actions
  • Merge Partner Cast // This orders the Merge
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Partner
    • Actions
      • Set TempUnit = (Triggering unit)
      • For each (Integer TempInteger) from 1 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to MU_Partner[TempInteger]
            • Then - Actions
              • Unit - Add Partner to MU_Caster[TempInteger]
              • Unit - Remove MU_Partner[TempInteger] from the game
              • Custom script: call IssueImmediateOrderById(udg_MU_Caster[udg_TempInteger], 852532)
            • Else - Actions
 

Attachments

  • MergeUnit.w3x
    21.3 KB · Views: 41
Level 19
Joined
May 29, 2013
Messages
1,554
@Pyrogasm: Thank you. I eventually managed to get it working for the most part However, I couldn't solve these problems:
  • I had to make the range really small (250) or else units would instantly merge without having to be next to each other.
  • Only one unit has to be selected. If both units are selected when I order them to merge, they just permanently channel the ability and never merge.
The last line removes the unit group leak but not the location leak. I put together a short example in the spoiler below.

  • Leaks
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Merge (Dummy)
    • Actions
      • Set MergeCaster = (Triggering unit)
      • Set MergeLocation = (Position of MergeCaster)
      • Set MergeGroup = (Units within 250.00 of MergeLocation)
      • Custom script: call RemoveLocation(udg_MergeLocation)
      • Custom script: call DestroyGroup(udg_MergeGroup)
Thanks, but do I always need to store the position of the caster in a variable?

@pOke: Once again the day is saved thanks to you! It works just like I wanted and you even found a way to include food cost in the tooltip. You're a genius!
As it stands now, it doesn't take into account the partner's HP at the time, the newly merged unit will have the HP of the requesting unit as it was the one who morphed.
Do I need to heal the caster (set life to 100% or something) before morphing if I want the "merged" unit to appear with full HP?
You'll probably want/need to change my debug msgs to be player specific or if they are needed at all.
I'll probably remove them. The "No partner found" message is the only one I need.
Let me know if you have any problems
This isn't really important, but it gets buggy when multiple units are selected and ordered to merge (at the same time).
 
Last edited:
Level 22
Joined
Feb 27, 2007
Messages
3,784
Only one unit has to be selected. If both units are selected when I order them to merge, they just permanently channel the ability and never merge.
it gets buggy when multiple units are selected and ordered to merge (at the same time).
I did not have that problem with my test map. The infinite channeling happened to me when the units had both a Mount and Pick Up ability on them at any one time, but otherwise doing it to any number of selected units worked as expected.

Afaik it doesn't 'save' the units merged from/to, but it does automatically equalize health and keep them selected the whole time. Breaks ctrl select groups though.
 
Level 19
Joined
May 29, 2013
Messages
1,554
I did not have that problem with my test map. The infinite channeling happened to me when the units had both a Mount and Pick Up ability on them at any one time
You're right. I was so excited about pOke's map that I forgot to post my trigger. I made some changes and now some parts don't make any sense to me, but it (sort of) works.
  • Events
    • Unit - A unit Is issued an order with no target
  • Conditions
    • (Issued order) Equal to (Order(neutralspell))
  • Actions
    • Set MergeCaster = (Ordered unit)
    • Set MergeLocation = (Position of MergeCaster)
    • Set MergePlayer = (Owner of MergeCaster)
    • Player - Enable Merge (Mount Hippogryph) for MergePlayer
    • Set MergeGroup = (Units within 250.00 of MergeLocation matching (((Unit-type of (Matching unit)) Equal to Merging Unit) and ((((Matching unit) is alive) Equal to True) and ((Owner of (Matching unit)) Equal to MergePlayer))))
    • Unit Group - Remove MergeCaster from MergeGroup
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • ((MergePlayer Food used) + 4) Less than or equal to (MergePlayer Food cap)
      • Then - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Number of units in MergeGroup) Greater than or equal to 1
          • Then - Actions
            • Player - Set MergePlayer Current gold to ((MergePlayer Current gold) - 100)
            • Player - Set MergePlayer Current lumber to ((MergePlayer Current lumber) - 100)
            • Unit - Add Merge (Pick up Archer) to MergeCaster
            • Unit - Remove Merge (Dummy) from MergeCaster
            • Unit - Order MergeCaster to Night Elf Hippogryph - Pick Up Archer
          • Else - Actions
            • Player - Set MergePlayer Current gold to ((MergePlayer Current gold) + 100)
            • Player - Set MergePlayer Current lumber to ((MergePlayer Current lumber) + 100)
            • Custom script: if udg_Error == null then
            • Custom script: set udg_Error = CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
            • Custom script: endif
            • Custom script: if GetLocalPlayer() == udg_MergePlayer then
            • Custom script: call ClearTextMessages()
            • Custom script: call DisplayTimedTextToPlayer( udg_MergePlayer, 0.52, 0.96, 2.00, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+udg_UnableToFindTarget+"|r" )
            • Custom script: call StartSound(udg_Error)
            • Custom script: endif
      • Else - Actions
        • Player - Set MergePlayer Current gold to ((MergePlayer Current gold) + 100)
        • Player - Set MergePlayer Current lumber to ((MergePlayer Current lumber) + 100)
        • Custom script: if udg_NoFood == null then
        • Custom script: set udg_NoFood = CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
        • Custom script: endif
        • Custom script: if GetLocalPlayer() == udg_MergePlayer then
        • Custom script: call ClearTextMessages()
        • Custom script: call DisplayTimedTextToPlayer( udg_MergePlayer, 0.52, 0.96, 2.00, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+udg_ErrorMessage+"|r" )
        • Custom script: call StartSound(udg_NoFood)
        • Custom script: endif
    • Player - Disable Merge (Mount Hippogryph) for MergePlayer
    • Custom script: call RemoveLocation(udg_MergeLocation)
    • Custom script: call DestroyGroup(udg_MergeGroup)
 
Level 12
Joined
Mar 24, 2013
Messages
1,105
Do I need to heal the caster (set life to 100% or something) before morphing if I want the "merged" unit to appear with full HP?

In the Merge Cast Partner, you'd just set the life of the Caster to 100% if you want it to be "fully healed" upon merging.


but it gets buggy when multiple units are selected and ordered to merge (at the same time).

You're right. I've fouled something up, I'll take another look and update it.
 
Level 8
Joined
Jan 28, 2016
Messages
486
Thanks, but do I always need to store the position of the caster in a variable?

Yeah, pretty much. These tutorials should be able to explain it better than I can:
P.S.: Just wanted to say I greatly appreciate the effort you put into the aesthetics of the map; most would have the bare-minimum terrain and generic "Just another Warcraft III map" title. That's not to say that it's a bad thing (it can be, at times, extremely frustrating when trying to find a map with the in-game menu) but not many go that extra step with test maps anymore. It's refreshing to see this from another member. Kudos to you, my friend!


So, I glanced through most of the thread. Hopefully I didn't do anything wrong haha.

So, I based the "Merge" on the Destroyer Form from Obsidian Statues. This lets us have the UI of Gold/Lumber and Food. It will also say "not enough X" as expected.

To begin:

Begins Channeling is used in Merge Cast. This will allow us to prevent the spell cast and we can check if the player has an appropriate unit to merge with. If not, debug msg. If so, find the closest appropriate unit, call it the partner. The partner then receives an invisible unit target spell based on channel and is ordered to cast it on the unit who requested the merge.

The partner will now be walking toward our unit who requested the merge. During this time should a player try to send the request again, a debug msg will appear saying that someone is coming. If either should die en route, the merge will be cancelled (currently there is a debug msg). If the partner receives an order of anything but "stun," the merge will be cancelled (currently there is a debug msg).

When the partner gets close enough to cast the invisible unit target spell. We catch it again with Begins Channeling, then we remove the partner from the game and order the requesting unit to morph to the "Merged" unit.

As it stands now, it doesn't take into account the partner's HP at the time, the newly merged unit will have the HP of the requesting unit as it was the one who morphed. You can easily set the requester's HP to some combination/portion of the partner and requester's HP if desired.

If the partner "merges" while the requester is stunned, the partner will disappear and after the stun the requester will morph as expected. Only potential problem is that long stuns could look odd or if they lead to the requester dying the player will have lost both.

You'll have to decide if/how you want to address these issues.

You'll probably want/need to change my debug msgs to be player specific or if they are needed at all.

Let me know if you have any problems, as I could have made a mistake, I'll post the code so others can hopefully spot any potential issues.

  • Merge Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: set udg_MU_Group = CreateGroup()
      • Set MU_MergeType = Peasant (Fake) // The unit type of the mergers.
  • Merge Cast
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Mortar Team // Merge Ability
    • Actions
      • Set TempUnit = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Partner for TempUnit) Equal to 1
        • Then - Actions
          • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
          • Unit Group - Remove MU_Partner[MU_MaxIndex] from MU_Group
          • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
          • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
          • Set MU_MaxIndex = (MU_MaxIndex - 1)
          • Game - Display to (All players) the text: Merge Successful
        • Else - Actions
          • Unit - Order TempUnit to Stop
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (TempUnit is in MU_Group) Equal to False
            • Then - Actions
              • Set TempPoint = (Position of TempUnit)
              • Set TempReal = 100000.00
              • Set TempUnit3 = No unit
              • Set TempGroup = (Units owned by (Owner of TempUnit))
              • Unit Group - Pick every unit in TempGroup and do (Actions)
                • Loop - Actions
                  • Set TempUnit2 = (Picked unit)
                  • Set TempPoint2 = (Position of TempUnit2)
                  • Set TempReal2 = (Distance between TempPoint and TempPoint2)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Unit-type of TempUnit2) Equal to MU_MergeType
                      • (TempUnit2 is alive) Equal to True
                      • TempUnit2 Not equal to TempUnit
                      • TempReal2 Less than TempReal
                      • (TempUnit2 is in MU_Group) Equal to False
                    • Then - Actions
                      • Set TempUnit3 = TempUnit2
                      • Set TempReal = TempReal2
                    • Else - Actions
                  • Custom script: call RemoveLocation(udg_TempPoint2)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TempUnit3 Not equal to No unit
                • Then - Actions
                  • Set MU_MaxIndex = (MU_MaxIndex + 1)
                  • Set MU_Caster[MU_MaxIndex] = (Triggering unit)
                  • Set MU_Partner[MU_MaxIndex] = TempUnit3
                  • Unit - Add Partner to MU_Partner[MU_MaxIndex]
                  • Unit - Order MU_Partner[MU_MaxIndex] to Undead Death Knight - Death Coil MU_Caster[MU_MaxIndex]
                  • Unit Group - Add MU_Caster[MU_MaxIndex] to MU_Group
                  • Unit Group - Add MU_Partner[MU_MaxIndex] to MU_Group
                  • Game - Display to (All players) the text: partner found
                • Else - Actions
                  • Game - Display to (All players) the text: No partner found.
              • Custom script: call RemoveLocation(udg_TempPoint)
              • Custom script: call DestroyGroup(udg_TempGroup)
            • Else - Actions
              • Game - Display to (All players) the text: Partner already on ...
  • Merge Cancel
    • Events
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order with no target
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • Custom script: if GetIssuedOrderId() == 851973 or GetIssuedOrderId() == 852222 then
      • -------- Don't cancel for Stunned Order and Partner --------
      • Custom script: return
      • Custom script: endif
      • For each (Integer TempInteger) from 1 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to MU_Partner[TempInteger]
            • Then - Actions
              • Unit - Remove Partner from MU_Partner[TempInteger]
              • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
              • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
              • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
              • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
              • Set MU_MaxIndex = (MU_MaxIndex - 1)
              • Game - Display to (All players) the text: Cancelled by Order
            • Else - Actions
  • Merge Dies Prior
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • For each (Integer TempInteger) from 1 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • TempUnit Equal to MU_Partner[TempInteger]
                  • TempUnit Equal to MU_Caster[TempInteger]
            • Then - Actions
              • Unit - Remove Partner from MU_Partner[TempInteger]
              • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
              • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
              • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
              • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
              • Set MU_MaxIndex = (MU_MaxIndex - 1)
              • Game - Display to (All players) the text: Cancelled by Death
            • Else - Actions
  • Merge Partner Cast // This orders the Merge
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Partner
    • Actions
      • Set TempUnit = (Triggering unit)
      • For each (Integer TempInteger) from 1 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to MU_Partner[TempInteger]
            • Then - Actions
              • Unit - Add Partner to MU_Caster[TempInteger]
              • Unit - Remove MU_Partner[TempInteger] from the game
              • Custom script: call IssueImmediateOrderById(udg_MU_Caster[udg_TempInteger], 852532)
            • Else - Actions

That's a very nice alternative! Didn't even realise that Destroyer Form needed a payment to go into effect.
 
Level 19
Joined
May 29, 2013
Messages
1,554
In the Merge Cast Partner, you'd just set the life of the Caster to 100% if you want it to be "fully healed" upon merging.
MU_Caster has the array box checked and I'm not sure what to put in it's index, but I did it like this and it works:
Heal.png

Yeah, pretty much. These tutorials should be able to explain it better than I can:
Thanks, I actually came across those tutorials before, but never bothered to read them. :p
P.S.: Just wanted to say I greatly appreciate the effort you put into the aesthetics of the map; most would have the bare-minimum terrain and generic "Just another Warcraft III map" title. That's not to say that it's a bad thing (it can be, at times, extremely frustrating when trying to find a map with the in-game menu) but not many go that extra step with test maps anymore. It's refreshing to see this from another member. Kudos to you, my friend!
Yeah, since most test maps look the same, I decided to decorate it a bit.
 
Level 12
Joined
Mar 24, 2013
Messages
1,105
Sorry for the bit of delay, had some difficulty figuring out the issues, but I believe I've resolved them.

You should now be able to order a control group to cast it at the same time. Also newly merged units will be at full life.



  • Merge Cast
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Mortar Team
    • Actions
      • Set TempUnit = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Partner for TempUnit) Equal to 1
        • Then - Actions
          • For each (Integer TempInteger) from 0 to MU_MaxIndex, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TempUnit Equal to MU_Caster[TempInteger]
                • Then - Actions
                  • Unit - Remove Partner from MU_Caster[TempInteger]
                  • Unit - Remove MU_Partner[TempInteger] from the game
                  • Unit - Set life of MU_Caster[TempInteger] to 100.00%
                  • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
                  • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
                  • Set MU_Caster[TempInteger] = No unit
                  • Set MU_Partner[TempInteger] = No unit
                  • Set MU_MaxIndex = (MU_MaxIndex - 1)
                  • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
                  • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
                • Else - Actions
        • Else - Actions
          • Unit - Order TempUnit to Stop
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (TempUnit is in MU_Group) Equal to False
            • Then - Actions
              • Set TempPoint = (Position of TempUnit)
              • Set TempReal = 100000.00
              • Set TempUnit3 = No unit
              • Set TempGroup = (Units owned by (Owner of TempUnit))
              • Unit Group - Pick every unit in TempGroup and do (Actions)
                • Loop - Actions
                  • Set TempUnit2 = (Picked unit)
                  • Set TempPoint2 = (Position of TempUnit2)
                  • Set TempReal2 = (Distance between TempPoint and TempPoint2)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Unit-type of TempUnit2) Equal to MU_MergeType
                      • (TempUnit2 is alive) Equal to True
                      • TempUnit2 Not equal to TempUnit
                      • TempReal2 Less than TempReal
                      • (TempUnit2 is in MU_Group) Equal to False
                    • Then - Actions
                      • Set TempUnit3 = TempUnit2
                      • Set TempReal = TempReal2
                    • Else - Actions
                  • Custom script: call RemoveLocation(udg_TempPoint2)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TempUnit3 Not equal to No unit
                • Then - Actions
                  • Set MU_Caster[MU_MaxIndex] = (Triggering unit)
                  • Set MU_Partner[MU_MaxIndex] = TempUnit3
                  • Unit - Add Partner to MU_Partner[MU_MaxIndex]
                  • Unit - Order MU_Partner[MU_MaxIndex] to Undead Death Knight - Death Coil MU_Caster[MU_MaxIndex]
                  • Unit Group - Add MU_Caster[MU_MaxIndex] to MU_Group
                  • Unit Group - Add MU_Partner[MU_MaxIndex] to MU_Group
                  • Set MU_MaxIndex = (MU_MaxIndex + 1)
                  • Game - Display to (All players) the text: partner found
                • Else - Actions
                  • Game - Display to (All players) the text: No partner found.
              • Custom script: call RemoveLocation(udg_TempPoint)
              • Custom script: call DestroyGroup(udg_TempGroup)
            • Else - Actions
              • Game - Display to (All players) the text: Partner already on ...
  • Merge Partner Cast
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Partner
    • Actions
      • Set TempUnit = (Triggering unit)
      • For each (Integer TempInteger) from 0 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to MU_Partner[TempInteger]
            • Then - Actions
              • Unit - Add Partner to MU_Caster[TempInteger]
              • Custom script: if IssueImmediateOrderById(udg_MU_Caster[udg_TempInteger], 852531) then
              • Custom script: elseif IssueImmediateOrderById(udg_MU_Caster[udg_TempInteger], 852532) then
              • Custom script: endif
            • Else - Actions
  • Merge Cancel
    • Events
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order with no target
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • Custom script: if GetIssuedOrderId() == 851973 or GetIssuedOrderId() == 852222 then
      • -------- Don't cancel for Stunned Order and Partner --------
      • Custom script: return
      • Custom script: endif
      • For each (Integer TempInteger) from 0 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to MU_Partner[TempInteger]
            • Then - Actions
              • Unit - Remove Partner from MU_Partner[TempInteger]
              • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
              • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
              • Set MU_Caster[TempInteger] = No unit
              • Set MU_Partner[TempInteger] = No unit
              • Set MU_MaxIndex = (MU_MaxIndex - 1)
              • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
              • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
              • Game - Display to (All players) the text: Cancelled by Order
              • Custom script: if GetIssuedOrderId() == 852531 or GetIssuedOrderId() == 852532 then
              • Set MU_TimerUnit = TempUnit
              • Countdown Timer - Start MU_Timer as a One-shot timer that will expire in 0.00 seconds
              • Custom script: endif
            • Else - Actions
  • Merge Cancel 2
    • Events
      • Time - MU_Timer expires
    • Conditions
    • Actions
      • Custom script: if IssueImmediateOrderById(udg_MU_TimerUnit, 852531) then
      • Custom script: elseif IssueImmediateOrderById(udg_MU_TimerUnit, 852532) then
      • Custom script: endif
  • Merge Dies Prior
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • For each (Integer TempInteger) from 0 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • TempUnit Equal to MU_Partner[TempInteger]
                  • TempUnit Equal to MU_Caster[TempInteger]
            • Then - Actions
              • Unit - Remove Partner from MU_Caster[TempInteger]
              • Unit - Remove Partner from MU_Partner[TempInteger]
              • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
              • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
              • Set MU_Caster[TempInteger] = No unit
              • Set MU_Partner[TempInteger] = No unit
              • Set MU_MaxIndex = (MU_MaxIndex - 1)
              • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
              • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
              • Game - Display to (All players) the text: Cancelled by Death
            • Else - Actions
 

Attachments

  • MergeUnit.w3x
    22.6 KB · Views: 27
Level 19
Joined
May 29, 2013
Messages
1,554
Sorry for the bit of delay, had some difficulty figuring out the issues, but I believe I've resolved them.

You should now be able to order a control group to cast it at the same time. Also newly merged units will be at full life.



  • Merge Cast
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Mortar Team
    • Actions
      • Set TempUnit = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Partner for TempUnit) Equal to 1
        • Then - Actions
          • For each (Integer TempInteger) from 0 to MU_MaxIndex, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TempUnit Equal to MU_Caster[TempInteger]
                • Then - Actions
                  • Unit - Remove Partner from MU_Caster[TempInteger]
                  • Unit - Remove MU_Partner[TempInteger] from the game
                  • Unit - Set life of MU_Caster[TempInteger] to 100.00%
                  • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
                  • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
                  • Set MU_Caster[TempInteger] = No unit
                  • Set MU_Partner[TempInteger] = No unit
                  • Set MU_MaxIndex = (MU_MaxIndex - 1)
                  • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
                  • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
                • Else - Actions
        • Else - Actions
          • Unit - Order TempUnit to Stop
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (TempUnit is in MU_Group) Equal to False
            • Then - Actions
              • Set TempPoint = (Position of TempUnit)
              • Set TempReal = 100000.00
              • Set TempUnit3 = No unit
              • Set TempGroup = (Units owned by (Owner of TempUnit))
              • Unit Group - Pick every unit in TempGroup and do (Actions)
                • Loop - Actions
                  • Set TempUnit2 = (Picked unit)
                  • Set TempPoint2 = (Position of TempUnit2)
                  • Set TempReal2 = (Distance between TempPoint and TempPoint2)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Unit-type of TempUnit2) Equal to MU_MergeType
                      • (TempUnit2 is alive) Equal to True
                      • TempUnit2 Not equal to TempUnit
                      • TempReal2 Less than TempReal
                      • (TempUnit2 is in MU_Group) Equal to False
                    • Then - Actions
                      • Set TempUnit3 = TempUnit2
                      • Set TempReal = TempReal2
                    • Else - Actions
                  • Custom script: call RemoveLocation(udg_TempPoint2)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TempUnit3 Not equal to No unit
                • Then - Actions
                  • Set MU_Caster[MU_MaxIndex] = (Triggering unit)
                  • Set MU_Partner[MU_MaxIndex] = TempUnit3
                  • Unit - Add Partner to MU_Partner[MU_MaxIndex]
                  • Unit - Order MU_Partner[MU_MaxIndex] to Undead Death Knight - Death Coil MU_Caster[MU_MaxIndex]
                  • Unit Group - Add MU_Caster[MU_MaxIndex] to MU_Group
                  • Unit Group - Add MU_Partner[MU_MaxIndex] to MU_Group
                  • Set MU_MaxIndex = (MU_MaxIndex + 1)
                  • Game - Display to (All players) the text: partner found
                • Else - Actions
                  • Game - Display to (All players) the text: No partner found.
              • Custom script: call RemoveLocation(udg_TempPoint)
              • Custom script: call DestroyGroup(udg_TempGroup)
            • Else - Actions
              • Game - Display to (All players) the text: Partner already on ...
  • Merge Partner Cast
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Partner
    • Actions
      • Set TempUnit = (Triggering unit)
      • For each (Integer TempInteger) from 0 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to MU_Partner[TempInteger]
            • Then - Actions
              • Unit - Add Partner to MU_Caster[TempInteger]
              • Custom script: if IssueImmediateOrderById(udg_MU_Caster[udg_TempInteger], 852531) then
              • Custom script: elseif IssueImmediateOrderById(udg_MU_Caster[udg_TempInteger], 852532) then
              • Custom script: endif
            • Else - Actions
  • Merge Cancel
    • Events
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order with no target
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • Custom script: if GetIssuedOrderId() == 851973 or GetIssuedOrderId() == 852222 then
      • -------- Don't cancel for Stunned Order and Partner --------
      • Custom script: return
      • Custom script: endif
      • For each (Integer TempInteger) from 0 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to MU_Partner[TempInteger]
            • Then - Actions
              • Unit - Remove Partner from MU_Partner[TempInteger]
              • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
              • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
              • Set MU_Caster[TempInteger] = No unit
              • Set MU_Partner[TempInteger] = No unit
              • Set MU_MaxIndex = (MU_MaxIndex - 1)
              • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
              • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
              • Game - Display to (All players) the text: Cancelled by Order
              • Custom script: if GetIssuedOrderId() == 852531 or GetIssuedOrderId() == 852532 then
              • Set MU_TimerUnit = TempUnit
              • Countdown Timer - Start MU_Timer as a One-shot timer that will expire in 0.00 seconds
              • Custom script: endif
            • Else - Actions
  • Merge Cancel 2
    • Events
      • Time - MU_Timer expires
    • Conditions
    • Actions
      • Custom script: if IssueImmediateOrderById(udg_MU_TimerUnit, 852531) then
      • Custom script: elseif IssueImmediateOrderById(udg_MU_TimerUnit, 852532) then
      • Custom script: endif
  • Merge Dies Prior
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • For each (Integer TempInteger) from 0 to MU_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • TempUnit Equal to MU_Partner[TempInteger]
                  • TempUnit Equal to MU_Caster[TempInteger]
            • Then - Actions
              • Unit - Remove Partner from MU_Caster[TempInteger]
              • Unit - Remove Partner from MU_Partner[TempInteger]
              • Unit Group - Remove MU_Caster[TempInteger] from MU_Group
              • Unit Group - Remove MU_Partner[TempInteger] from MU_Group
              • Set MU_Caster[TempInteger] = No unit
              • Set MU_Partner[TempInteger] = No unit
              • Set MU_MaxIndex = (MU_MaxIndex - 1)
              • Set MU_Caster[TempInteger] = MU_Caster[MU_MaxIndex]
              • Set MU_Partner[TempInteger] = MU_Partner[MU_MaxIndex]
              • Game - Display to (All players) the text: Cancelled by Death
            • Else - Actions
It's perfect! Thank you for all the time & effort which you put into this.
 
Top