Spell Multicast

SwedishChef

New Member
Reaction score
32
Multicast

What is this?
*Whenever a spell is cast, by a hero with the multicast ability, there is a percent chance that it will cast again a second time.
*Works with all spells without having to add a condition for every spell
*Trigger both in GUI and Jass
*Easy to customize (if you use the Jass trigger)

Screenshot:

I saw that there were a couple of threads asking about Multicast spells and I also wanted one for my map so I made one. If you find any bugs please report them here since I will update the spell and use it myself. Feel free to use it in any of your maps and give credit if you ain't a sneaky bastard. ;)

The trigger in GUI:
Trigger:
  • Multicast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Level of Multicast for (Triggering unit)) Greater than 0
      • (Random integer number between 1 and 100) Less than or equal to (12 + (8 x (Level of Multicast for (Triggering unit))))
    • Actions
      • Custom script: local integer locExecCount = GetTriggerExecCount(GetTriggeringTrigger())
      • Custom script: if locExecCount == 50 then
      • Custom script: call ResetTrigger(GetTriggeringTrigger())
      • Custom script: endif
      • Custom script: set udg_trigExecCount = locExecCount
      • Set MyLocation = (Position of (Triggering unit))
      • Set MulticastAbility = (Ability being cast)
      • Set MulticastPoint[trigExecCount] = (Target point of ability being cast)
      • Set MulticastTarget[trigExecCount] = (Target unit of ability being cast)
      • Set MulticastOrder[trigExecCount] = (Current order of (Triggering unit))
      • Unit - Create 1 Dummy Unit for (Owner of (Triggering unit)) at MyLocation facing Default building facing degrees
      • Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
      • Unit - Add MulticastAbility to (Last created unit)
      • Unit - Set level of MulticastAbility for (Last created unit) to (Level of MulticastAbility for (Triggering unit))
      • Floating Text - Create floating text that reads Multicast above (Triggering unit) with Z offset 0.00, using font size 15.00, color (100.00%, 0.00%, 0.00%), and 0.00% transparency
      • Floating Text - Change (Last created floating text): Disable permanence
      • Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
      • Floating Text - Change the lifespan of (Last created floating text) to 3.00 seconds
      • Set MulticastDummy[trigExecCount] = (Last created unit)
      • Custom script: call RemoveLocation(udg_MyLocation)
      • Wait 0.20 seconds
      • Custom script: set udg_trigExecCount = locExecCount
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Playable map area) contains MulticastPoint[trigExecCount]) Equal to True
        • Then - Actions
          • Custom script: call IssuePointOrderByIdLoc( udg_MulticastDummy[udg_trigExecCount], udg_MulticastOrder[udg_trigExecCount], udg_MulticastPoint[udg_trigExecCount] )
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • MulticastTarget[trigExecCount] Not equal to No unit
        • Then - Actions
          • Custom script: call IssueTargetOrderById( udg_MulticastDummy[udg_trigExecCount], udg_MulticastOrder[udg_trigExecCount], udg_MulticastTarget[udg_trigExecCount] )
          • Custom script: call IssueImmediateOrderById( udg_MulticastDummy[udg_trigExecCount], udg_MulticastOrder[udg_trigExecCount] )
        • Else - Actions
      • Custom script: call RemoveLocation( udg_MulticastPoint[udg_trigExecCount] )

The trigger in Jass:
JASS:
scope Multicast initializer InitTrig

    globals
        private constant integer ABILITY_ID 		  = 'A000'         //Raw code of the multicast ability
        private constant integer DUMMY_ID 	          = 'u001'         //Raw code of the multicast dummy
        private constant real    SPELL_DELAY 		  = .2 	           // Sets the delay between the casted spell and the multicasted spell
        private constant real    LIFE_TIME_DUMMY 	  = 2.             // How long the dummy will last, if you use spells like blizzard you would want to make this longer.
       
        private constant string  TEXTTAG_TEXT         = "Multicast!"  // The text that will be displayed when multicasting
        private constant real    TEXTTAG_HEIGHT       = 15.            // Height of text
        private constant real    TEXT_SIZE            = 0.040          // Size of text
        private constant real	 LIFE_TIME_TEXT 	  = 3.             // Time util text disappear
        private constant real	 TEXT_FADE_POINT 	  = 0.2            // Time it takes before the text is shown and starts to fade out 
        private constant integer TEXT_COLOR_RED       = 255            // The "red" color of the texttag
        private constant integer TEXT_COLOR_GREEN     = 0              // The "greed" color of the texttag
        private constant integer TEXT_COLOR_BLUE      = 0              // The "blue" color of the texttag
        private constant integer TEXT_COLOR_ALPHA     = 0              // The "alpha" color of the texttag (Transparency)
    endglobals

    private constant function Chance takes integer spellLvl returns real
        return 12. + (8. * spellLvl)                                   // Chance to multicast
    endfunction

//=========================================================\\
//========== Nothing to edit past this point ==============\\
//=========================================================\\

    private function Conditions takes nothing returns boolean
        return GetUnitAbilityLevel(GetTriggerUnit(), ABILITY_ID) > 0 and GetRandomInt(1, 100) <= Chance(GetUnitAbilityLevel(GetTriggerUnit(), ABILITY_ID))
    endfunction

    private function Actions takes nothing returns nothing
        local unit   u  = GetTriggerUnit()
        local real   x  = GetUnitX (u)
        local real   y  = GetUnitY (u)
        local player p  = GetOwningPlayer(u)
        local unit   t  = GetSpellTargetUnit()
        local real   tx = GetSpellTargetX()
        local real   ty = GetSpellTargetY()
        local string s  = OrderId2String( GetUnitCurrentOrder( u ) )
        local integer spellid = GetSpellAbilityId()
        local texttag tt
        local unit tu
        set tu = CreateUnit( p, DUMMY_ID, x, y, 270 )
                
      //============= Multicast Text ===================\\
            set tt = CreateTextTag()
            call SetTextTagPermanent ( tt, false )
            call SetTextTagText ( tt, TEXTTAG_TEXT, TEXT_SIZE )
            call SetTextTagPos ( tt, x, y, TEXTTAG_HEIGHT )
            call SetTextTagColor (tt, TEXT_COLOR_RED, TEXT_COLOR_GREEN, TEXT_COLOR_BLUE, TEXT_COLOR_ALPHA )
            call SetTextTagVelocity ( tt, 0.0355 * Cos(90. * bj_DEGTORAD), 0.0355 * Sin( 90. * bj_DEGTORAD ) )
            call SetTextTagVisibility ( tt, true )
            call SetTextTagFadepoint ( tt, TEXT_FADE_POINT )
            call SetTextTagLifespan ( tt, LIFE_TIME_TEXT )
      //==================================================\\
        
        call TriggerSleepAction( SPELL_DELAY )
        
        call UnitApplyTimedLife( tu, 'BTLF', LIFE_TIME_DUMMY+SPELL_DELAY )
        call UnitAddAbility( tu, spellid )
        call SetUnitAbilityLevel (tu, spellid, GetUnitAbilityLevel(u, ABILITY_ID ) )
        
        if GetRectMaxX( bj_mapInitialPlayableArea ) > tx and GetRectMinX( bj_mapInitialPlayableArea ) < tx and GetRectMaxY( bj_mapInitialPlayableArea ) > ty and GetRectMinY( bj_mapInitialPlayableArea ) < tx and t == null then
            call IssuePointOrder ( tu, s, tx, ty )
            call IssueTargetOrder(tu, s, t)
        elseif t != null or t != u then
            call IssueTargetOrder( tu, s, t )
            call IssueImmediateOrder( tu, s )
        endif
        
        set p  = null
        set u  = null
        set tu = null
        set t  = null
        set s  = null
        set tt = null
    endfunction

    private function InitTrig takes nothing returns nothing
        local trigger t = CreateTrigger()
        
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t, Condition(function Conditions))
        call TriggerAddAction(t, function Actions)
    endfunction

endscope

Extra Notes:
*When I tested in my own map I found out that Summon Lava Spawn didn't work with this ability. If you find any other spell which won't work post them here and I will make a list of them.
*Test map based of Tinki3's template so credits to him
*Credits to Laiev, Undead.Cow and Komaqtion for helping me with the jass trigger!

Known Errors:
Abilities which have a maximum range and unit target such as Chain Lightning will almost never work if you cast it at maximum range

Download the map and read the README there for information about how to implement this spell in your map
 

Attachments

  • Multicast GUI & Jass - SwedishChef.w3x
    54.9 KB · Views: 619

Weep

Godspeed to the sound of the pounding
Reaction score
401
Trigger:
  • Custom script: set udg_trigExecCount = locExecCount
This line also needs to be after the wait in order to be MUI. As it stands, that global would be overwritten if any unit casts a multicast spell during that 0.2 second delay.

This is also a pretty poor indexing technique, and you don't need it anyway; just use more locals.

Trigger:
  • Unit - Set level of MulticastAbility for (Triggering unit) to (Level of Multicast for (Triggering unit))
Um...what? So, if I have Multicast at level 1 and Fan of Knives at level 3, when a successful multicast happens, Fan of Knives would be reduced to level 1...

Trigger:
  • Unit - Add (Ability being cast) to (Last created unit)
You've already set (Ability being cast) to MulticastAbility, so just use the variable.
 

SwedishChef

New Member
Reaction score
32
Yeah I forgot to do that! Thanks for noting I will change it right away.

Hm this was for my own map at first so I made this so it could be more balanced. But yours makes more sence so I will change it.

Okey ;).

Updated!

E: I just have a quick question. Which is better to remove MyLocation before or after the wait. Before must be better right?
 

HeX.16

Isn't Trollin You Right Now
Reaction score
131
I would give its a 7/10.
Usefull but its east to make. If it was Jass or vJass it would get 10/10.
 

SwedishChef

New Member
Reaction score
32
I will post what it does in the main post since I have forgotten it. Good tips!

This is to less and to easy makeable for approving.

If you search for Multicast you get lots of threads which still haven't solved their problems yet, so I thought I could make one. I didn't know that a spell could be to easy for being approved. The main thing must be that someone can have some use of it and that it works.


E: Explaination good enough? I'm trying to make a Jass version now ;).

Updated!
Now I have also made a jass trigger, please note that I ain't very good at jass and the things I made here were just to convert the trigger and fix the things I know how to fix. Many of the things I did I also learned today so I know there is alot to be fixed, so please comment on the things I should fix on the jass trigger.
 

HeX.16

Isn't Trollin You Right Now
Reaction score
131
Not every1 can understand Jass so make notes so we know what changes what.
JASS:
//These notes
 

Laiev

Hey Listen!!
Reaction score
188
I edited your jass code a bit and make a vJass version, also sorry for something, I can't test it <don't play wc3 anymore and don't edit anymore> and for this reason, i can't remove the bjs

If someone can :) please, do it
JASS:
scope Multicast initializer InitTrig

globals
	private constant integer ABILITY_ID 		  = &#039;A000&#039; //Raw code of the ability
	private constant integer DUMMY_ID 	          = &#039;u001&#039; //Raw code of the dummy
	
	private constant real    LIFE_TIME_DUMMY 	  = 2.     // How long the dummy will last, if you use spells like blizzard you would want to make this longer.
	private constant real    PERCENTAGE_PER_LEVEL     = 8 	   //This will be 8 * level of ability
	private constant real	 PERCENTAGE_CONSTANT      = 12     //This will be 12 + (PERCENTAGE_PER_LEVEL * level ability)
	private constant real    SPELL_DELAY 		  = .2 	   // Sets the delay between the casted spell and the multicasted spell
	private constant real	 LIFE_TIME_TEXT 	  = 3.     //Time util text disappear
	private constant real	 TEXT_FADE_POINT 	  = 2.     //Idk how explain
endglobals

//=========================================================\\
//========== DON&#039;T TOUCH OR YOU&#039;LL FEEL THE PAIN ==========\\
//=========================================================\\

private function Conditions takes nothing returns boolean
    return GetUnitAbilityLevel(GetTriggerUnit(), ABILITY_ID) &gt; 0 and GetRandomInt(1, 100) &lt;= PERCENTAGE_CONSTANT + (PERCENTAGE_PER_LEVEL * GetUnitAbilityLevel(GetTriggerUnit(), ABILITY_ID))
endfunction

private function Actions takes nothing returns nothing
    local unit   u  = GetTriggerUnit()
    local real   x  = GetUnitX (u)
    local real   y  = GetUnitY (u)
    local player p  = GetOwningPlayer(u)
    local unit   tu = CreateUnit(p, DUMMY_ID, x, y, 270)
    local unit   t  = GetSpellTargetUnit()
    local real   tx = GetSpellTargetX()
    local real   ty = GetSpellTargetY()
    local string s  = OrderId2StringBJ(GetUnitCurrentOrder(u))
	
    call UnitApplyTimedLife(tu, &#039;BTLF&#039;, LIFE_TIME_DUMMY)
    call UnitAddAbility(tu, GetSpellAbilityId())
    call SetUnitAbilityLevel(tu, GetSpellAbilityId(), GetUnitAbilityLevel(u, GetSpellAbilityId()))
	
  //============================== DON&#039;T EDITED ==============================\\
    call CreateTextTagUnitBJ(&quot;TRIGSTR_096&quot;, u, 0, 15.00, 100, 0.00, 0.00, 0)
    call SetTextTagPermanent(GetLastCreatedTextTag(), false)
    call SetTextTagFadepoint(GetLastCreatedTextTag(), TEXT_FADE_POINT)
    call SetTextTagLifespan(GetLastCreatedTextTag(), LIFE_TIME_TEXT)
  //==========================================================================\\
	
    call TriggerSleepAction(SPELL_DELAY)
    if RectContainsLoc(GetPlayableMapRect(), GetSpellTargetLoc()) then
        call IssuePointOrder (tu, s, tx, ty)
    elseif GetSpellTargetUnit() != null then
        call IssueTargetOrder(tu, s, t)
        call IssueImmediateOrder(tu, s)
    endif
	
    set p  = null
    set u  = null
    set tu = null
    set t  = null
    set s  = null
endfunction

private function InitTrig takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Conditions))
    call TriggerAddAction(t, function Actions)
endfunction
endscope



EDIT: also i reorder the trigger :D and make it more readable and cute ^_^
 

Carnerox

The one and only.
Reaction score
84
Use Laiev's trigger but.

JASS:
   local texttag tt   
//Use this for the text.
    set tt = CreateTextTag()
        call SetTextTagText (tt, &quot;Multicast!&quot;, 0.023)
        call SetTextTagPos (u, x, y, 15)
        call SetTextTagColor (tt, 10, 255, 0, 0)
        call SetTextTagVelocity (tt, 0.0355 * Cos(90. * bj_DEGTORAD), 0.0355 * Sin(90. * bj_DEGTORAD))
        call SetTextTagVisibility (tt, true)
        call SetTextTagFadepoint (tt, TEXT_FADE_POINT)
        call SetTextTagLifespan (tt, LIFE_TIME_TEXT)
        call SetTextTagPermanent (tt, false)


Also
For

do
 

SwedishChef

New Member
Reaction score
32
Ah nice guys! This was exactly what I needed. Hah I forgot to null all locals :p. I will fix this as soon as I get some time, Jass was very funny now for some reason so maybe I will continue with it :D. Well I gotta go now, thanks again!
 

SwedishChef

New Member
Reaction score
32
Updated! I kinda forgot to edit the jass trigger or were too lazy to do it. Well now it is fixed ;). Thanks both of you!
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top