• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] Special Effect for Allies of Player

Status
Not open for further replies.
Level 12
Joined
May 16, 2020
Messages
660
Hi,

I want to show a special effect only to allies of a player who is casting an ability.

In another threat I found a method to show the SFX to ONE player. But how do I adjust this JASS code to include "all allies of Player X"?
  • empty.gif
    joinbottomminus.gif
    playergroup.gif
    Player Group - Pick every player in ActivePlayers and do (Actions)
    • empty.gif
      empty.gif
      joinbottomminus.gif
      actions.gif
      Loop - Actions
      • empty.gif
        empty.gif
        empty.gif
        join.gif
        set.gif
        Set VariableSet PN = (Player number of (Picked player))
      • empty.gif
        empty.gif
        empty.gif
        join.gif
        set.gif
        Set VariableSet effectString = Objects\RandomObject\RandomObject
      • empty.gif
        empty.gif
        empty.gif
        join.gif
        page.gif
        Custom script: if GetLocalPlayer() != GetTriggerPlayer() then
      • empty.gif
        empty.gif
        empty.gif
        join.gif
        set.gif
        Set VariableSet effectString = <Empty String>
      • empty.gif
        empty.gif
        empty.gif
        join.gif
        page.gif
        Custom script: endif
      • empty.gif
        empty.gif
        empty.gif
        join.gif
        ani.gif
        Special Effect - Create a special effect attached to the overhead of Paladin 0000 <gen> using effectString
      • empty.gif
        empty.gif
        empty.gif
        joinbottom.gif
        set.gif
        Set VariableSet quest_Sfx2[PN] = (Last created special effect)

Many thanks
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
check the trigger at the bottom of this thread, it shows an effect only to a defined player group. you basically just need to edit the "set variable" at the top of the trigger...

 
Level 12
Joined
May 16, 2020
Messages
660
Thank you. Is it required to create these "empty strings" for player that are not affected?
Since I pre-filter already for "allies of the caster", the GetLocalPlayer() can just grab whatever I pre-filtered, no?

I created the following:

In the Index / start of the spell:
  • Set VariableSet YA_PlayerGroup = (All allies of (Owner of YA_Caster[YA_Index]).)
  • Player Group - Pick every player in YA_PlayerGroup and do (Actions)
    • Loop - Actions
      • Set VariableSet YA_Player = (Player number of (Picked player))
      • Custom script: if GetLocalPlayer() == GetEnumPlayer() then
      • -------- Destroy the SFX in case the spell has already been started by another caster --------
      • Special Effect - Destroy YA_SFX_B[YA_Player]
      • Special Effect - Create a special effect attached to the overhead of YA_Target[YA_Index] using Abilities\Spells\Other\HowlOfTerror\HowlTarget.mdl
      • Set VariableSet YA_SFX_B[YA_Player] = (Last created special effect)
      • Custom script: endif
  • Custom script: call DestroyForce(udg_YA_PlayerGroup)

And then in the De-Indexing / end of the spell:
  • Set VariableSet YA_PlayerGroup = (All allies of (Owner of YA_Caster[YA_Integer]).)
  • Player Group - Pick every player in YA_PlayerGroup and do (Actions)
    • Loop - Actions
      • Set VariableSet YA_Player = (Player number of (Picked player))
      • Custom script: if GetLocalPlayer() == GetEnumPlayer() then
      • -------- Destroy the SFX in case the spell has already been started by another caster --------
      • Special Effect - Destroy YA_SFX_B[YA_Player]
      • Custom script: endif
  • Custom script: call DestroyForce(udg_YA_PlayerGroup)
 
Level 12
Joined
May 16, 2020
Messages
660
I guess because every guide I see does it. But I don't see why:


 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,456
The Special Effect needs to be created/destroyed for EVERYONE in order to avoid desyncing. So you can't create/destroy it locally.

The solution here is to change the model path for the special effect locally.
  • Set Variable effectString = <Empty String>
  • Custom script: if GetLocalPlayer() == YourPlayer then
  • Set Variable effectString = Desired model path
  • Custom script: endif
So the LocalPlayer() of your choice is given the correct model path while everyone else will use the empty one "".

GetLocalPlayer() can be used in a Loop pretty much the same way it's used outside of a Loop. For example, to reference the (Picked player) in a Pick Every Player function you would use "if GetLocalPlayer() == GetEnumPlayer() then". Or you can always use a Player variable if you aren't familiar with the Jass Event Response equivalents.

Here's some Jass functions that you'd probably use with it:
GetOwningPlayer() = You supply a unit in the parameters and it gets you the player that the unit belongs to
GetEnumPlayer() = Picked player
GetTriggerPlayer() = Triggering player
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Understood. But I have a question for this:
The Special Effect needs to be created/destroyed for EVERYONE in order to avoid desyncing. So you can't create/destroy it locally.

If I "pick every player in (all allies of XXX)" doesn't this pre-filter the selection already, hence it won't create the SFX for everyone.
(because the Picked Player is already limited to the allies, so all enemies are excluded)

So I will need to re-do this trigger, right?:

  • Set VariableSet YA_PlayerGroup = (All allies of (Owner of YA_Caster[YA_Index]).)
  • Player Group - Pick every player in YA_PlayerGroup and do (Actions)
    • Loop - Actions
      • Set VariableSet YA_Player = (Player number of (Picked player))
      • Set VariableSet YA_String = <Empty String>
      • Custom script: if GetLocalPlayer() == GetEnumPlayer() then
      • Set VariableSet YA_String = Abilities\Spells\Other\HowlOfTerror\HowlTarget.mdl
      • Custom script: endif
      • -------- Destroy the SFX in case the spell has already been started by another caster --------
      • Special Effect - Destroy YA_SFX_B[YA_Player]
      • Special Effect - Create a special effect attached to the overhead of YA_Target[YA_Index] using Abilities\Spells\Other\HowlOfTerror\HowlTarget.mdl
      • Set VariableSet YA_SFX_B[YA_Player] = (Last created special effect)
  • Custom script: call DestroyForce(udg_YA_PlayerGroup)

Also, I assume when we talk about "everyone" you mean PLAYERS, not computers, right?
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,456
Set the String to empty before you enumerate over the Player Group.

Also, you're never referencing YA_String when you create the Special Effect.

Also, you're creating the special effect multiple times. You just want to create it once as far as I can tell? It's not like YA_Target changes from player to player.

And I mean EVERYONE, Computers included. At least as far as I know.

Something like this:
  • Actions
    • Set VariableSet tempEffect = <Empty String>
    • Player Group - Pick every player in someGroup and do (Actions)
      • Loop - Actions
        • Custom script: if GetLocalPlayer() == GetEnumPlayer() then
        • Set VariableSet tempEffect = Human/Wizard/Fireball.mdl
        • Custom script: endif
    • Special Effect - Create a special effect at (Center of (Playable map area)) using tempEffect
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Also, you're creating the special effect multiple times. You just want to create it once as far as I can tell? It's not like YA_Target changes from player to player.
Ideally yes, I want to only create the SFX once on the target. But the SFX should be visible to my entire team. Hence I think I have no other choice but to create it several times.

For example, if I'm in team 1, I want the SFX to be visible for Players 1, 2, 3, 4, 5, 6. But not visible for Players 7, 8, 9, 10, 11, 12 (and neither for player 13 to 24, neutral and neutral hostile)

Set the String to empty before you enumerate over the Player Group.
I re-read what you did here so adjusted accordingly.
But: How do I correctly destroy the effects, without causing a desync?
Currently I only destroy the SFX for Players that are allies, but I assume the empty model paths for enemies are not destroyed.

  • Set VariableSet YA_PlayerGroup = (All allies of (Owner of YA_Caster[YA_Index]).)
  • Player Group - Pick every player in YA_PlayerGroup and do (Actions)
    • Loop - Actions
      • Set VariableSet YA_Player = (Player number of (Picked player))
      • Set VariableSet YA_String = Abilities\Spells\Other\HowlOfTerror\HowlTarget.mdl
      • Custom script: if GetLocalPlayer() != GetEnumPlayer() then
      • Set VariableSet YA_String = <Empty String>
      • Custom script: endif
      • -------- Destroy the SFX in case the spell has already been started by another caster --------
      • Special Effect - Destroy YA_SFX_B[YA_Player]
      • Special Effect - Create a special effect attached to the overhead of YA_Target[YA_Index] using YA_String
      • Set VariableSet YA_SFX_B[YA_Player] = (Last created special effect)
  • Custom script: call DestroyForce(udg_YA_PlayerGroup)

Not sure if that helps, but here the entire spell for context (ignore the GetLocalPlayer() part, need to correct this now):

  • Charge of Darkness Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet YA_MS_Max[1] = 300.00
      • Set VariableSet YA_MS_Max[2] = 325.00
      • Set VariableSet YA_MS_Max[3] = 350.00
      • Set VariableSet YA_MS_Max[4] = 375.00
      • Custom script: set udg_YA_MS_Increment[1] = 0.75
      • Custom script: set udg_YA_MS_Increment[2] = 0.8125
      • Custom script: set udg_YA_MS_Increment[3] = 0.875
      • Custom script: set udg_YA_MS_Increment[4] = 0.9375
  • Charge of Darkness
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge of Darkness
    • Actions
      • Set VariableSet YA_Index = (YA_Index + 1)
      • Set VariableSet YA_Caster[YA_Index] = (Triggering unit)
      • Set VariableSet YA_Target[YA_Index] = (Target unit of ability being cast)
      • Set VariableSet YA_MS[YA_Index] = 0.00
      • Set VariableSet YA_SpeedMoved[YA_Index] = 15.00
      • Set VariableSet YA_SpeedAnimation[YA_Index] = 0.00
      • Set VariableSet YA_Level[YA_Index] = (Level of Charge of Darkness for YA_Caster[YA_Index])
      • Set VariableSet YA_LevelBash[YA_Index] = (Level of Greater Bash for YA_Caster[YA_Index])
      • Set VariableSet YA_BooleanMax[YA_Index] = False
      • -------- --------
      • -------- CREATE DUMMY UNIT FOR GREATER BASH STUN --------
      • Set VariableSet YA_Point[0] = (Position of YA_Caster[YA_Index])
      • Unit - Create 1 Dummy (Fly/Speed 0) for Neutral Passive at YA_Point[0] facing Default building facing degrees
      • Set VariableSet YA_Dummy[YA_Index] = (Last created unit)
      • Unit - Add Greater Bash (Stun) to YA_Dummy[YA_Index]
      • Ability - Set Ability: (Unit: YA_Dummy[YA_Index]'s Ability with Ability Code: Greater Bash (Stun))'s Real Level Field: Duration - Normal ('adur') of Level: 0 to (0.60 + (0.30 x (Real(YA_LevelBash[YA_Index]))))
      • Ability - Set Ability: (Unit: YA_Dummy[YA_Index]'s Ability with Ability Code: Greater Bash (Stun))'s Real Level Field: Duration - Hero ('ahdu') of Level: 0 to (0.60 + (0.30 x (Real(YA_LevelBash[YA_Index]))))
      • Custom script: call RemoveLocation(udg_YA_Point[0])
      • -------- --------
      • -------- CREATE SPECIALEFFECT FOR CASTER --------
      • Special Effect - Create a special effect attached to the origin of YA_Caster[YA_Index] using war3mapImported\Valiant Charge Royal.mdx
      • Set VariableSet YA_SFX_A[YA_Index] = (Last created special effect)
      • Custom script: call SetUnitAnimationByIndex(udg_YA_Caster[udg_YA_Index], 8)
      • -------- --------
      • -------- CREATE SPECIALEFFECT ABOVE TARGET FOR ALLIED PLAYERS --------
      • Set VariableSet YA_PlayerGroup = (All allies of (Owner of YA_Caster[YA_Index]).)
      • Player Group - Pick every player in YA_PlayerGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet YA_Player = (Player number of (Picked player))
          • Set VariableSet YA_String = Abilities\Spells\Other\HowlOfTerror\HowlTarget.mdl
          • Custom script: if GetLocalPlayer() != GetEnumPlayer() then
          • Set VariableSet YA_String = <Empty String>
          • Custom script: endif
          • -------- Destroy the SFX in case the spell has already been started by another caster --------
          • Special Effect - Destroy YA_SFX_B[YA_Player]
          • Special Effect - Create a special effect attached to the overhead of YA_Target[YA_Index] using YA_String
          • Set VariableSet YA_SFX_B[YA_Player] = (Last created special effect)
      • Custom script: call DestroyForce(udg_YA_PlayerGroup)
      • -------- --------
      • Unit - Grant shared vision of YA_Target[YA_Index] to (Owner of YA_Caster[YA_Index])
      • Unit - Turn collision for YA_Caster[YA_Index] Off.
      • Animation - Change YA_Caster[YA_Index]'s animation speed to 200.00% of its original speed
      • Animation - Change YA_Caster[YA_Index]'s vertex coloring to (80.00%, 80.00%, 80.00%) with 20.00% transparency
      • -------- --------
      • Custom script: set udg_YA_GroupDamaged[udg_YA_Index] = CreateGroup()
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • YA_Index Equal to 1
        • Then - Actions
          • Game - Display to (All players) the text: CHARGE OF DARKNESS ...
          • Countdown Timer - Start YA_Timer as a Repeating timer that will expire in 0.03 seconds
          • Trigger - Turn on Charge of Darkness Loop <gen>
        • Else - Actions
  • Charge of Darkness Loop
    • Events
      • Time - YA_Timer expires
    • Conditions
    • Actions
      • For each (Integer YA_Integer) from 1 to YA_Index, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (YA_Target[YA_Integer] is dead) Equal to True
            • Then - Actions
              • -------- IF THE TARGET DIES, PICK A NEW TARGET WITHIN 4000 AOE --------
              • Unit - Deny shared vision of YA_Target[YA_Integer] to (Owner of YA_Caster[YA_Integer])
              • Set VariableSet YA_DistanceCheck[1] = 4000.00
              • Set VariableSet YA_Point[1] = (Position of YA_Target[YA_Integer])
              • Set VariableSet YA_Target[YA_Integer] = No unit
              • Custom script: set bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 4000.00 of YA_Point[1].) and do (Actions)
                • Loop - Actions
                  • Set VariableSet YA_Unit = (Picked unit)
                  • Set VariableSet YA_Point[2] = (Position of YA_Unit)
                  • Set VariableSet YA_DistanceCheck[2] = (Distance between YA_Point[1] and YA_Point[2])
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (YA_Unit is alive) Equal to True
                      • (YA_Unit is A structure) Equal to False
                      • (YA_Unit is visible to (Owner of YA_Caster[YA_Integer]).) Equal to True
                      • (YA_Unit belongs to an enemy of (Owner of YA_Caster[YA_Integer]).) Equal to True
                      • YA_DistanceCheck[2] Less than or equal to YA_DistanceCheck[1]
                    • Then - Actions
                      • Set VariableSet YA_DistanceCheck[1] = YA_DistanceCheck[2]
                      • Set VariableSet YA_Target[YA_Integer] = YA_Unit
                    • Else - Actions
                  • Custom script: call RemoveLocation(udg_YA_Point[2])
              • Custom script: call RemoveLocation(udg_YA_Point[1])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • YA_Target[YA_Integer] Not equal to No unit
                • Then - Actions
                  • Game - Display to (All players) the text: Switched Target
                  • Unit - Grant shared vision of YA_Target[YA_Integer] to (Owner of YA_Caster[YA_Integer])
                  • -------- CREATE SPECIALEFFECT ABOVE TARGET FOR ALLIED PLAYERS --------
                  • Set VariableSet YA_PlayerGroup = (All allies of (Owner of YA_Caster[YA_Integer]).)
                  • Player Group - Pick every player in YA_PlayerGroup and do (Actions)
                    • Loop - Actions
                      • Set VariableSet YA_Player = (Player number of (Picked player))
                      • Custom script: if GetLocalPlayer() == GetEnumPlayer() then
                      • -------- Destroy the SFX in case the spell has already been started by another caster --------
                      • Special Effect - Destroy YA_SFX_B[YA_Player]
                      • Special Effect - Create a special effect attached to the overhead of YA_Target[YA_Integer] using Abilities\Spells\Other\HowlOfTerror\HowlTarget.mdl
                      • Set VariableSet YA_SFX_B[YA_Player] = (Last created special effect)
                      • Custom script: endif
                  • Custom script: call DestroyForce(udg_YA_PlayerGroup)
                • Else - Actions
                  • Unit - Pause YA_Caster[YA_Integer]
                  • Unit - Unpause YA_Caster[YA_Integer]
            • Else - Actions
          • Set VariableSet YA_Point[1] = (Position of YA_Caster[YA_Integer])
          • Set VariableSet YA_Point[2] = (Position of YA_Target[YA_Integer])
          • Set VariableSet YA_Distance = (Distance between YA_Point[1] and YA_Point[2])
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Current order of YA_Caster[YA_Integer]) Equal to (Order(magicleash))
              • YA_Distance Greater than 100.00
              • (YA_Caster[YA_Integer] is alive) Equal to True
            • Then - Actions
              • Set VariableSet YA_Angle = (Angle from YA_Point[1] to YA_Point[2])
              • Set VariableSet YA_Point[3] = (YA_Point[1] offset by YA_SpeedMoved[YA_Integer] towards YA_Angle degrees.)
              • -------- --------
              • -------- MOVE CASTER --------
              • Set VariableSet YA_X = (X of YA_Point[3])
              • Set VariableSet YA_Y = (Y of YA_Point[3])
              • Custom script: call SetUnitX(udg_YA_Caster[udg_YA_Integer], udg_YA_X)
              • Custom script: call SetUnitY(udg_YA_Caster[udg_YA_Integer], udg_YA_Y)
              • Unit - Make YA_Caster[YA_Integer] face YA_Target[YA_Integer] over 0.00 seconds
              • -------- --------
              • -------- MOVE DUMMY --------
              • Set VariableSet YA_X = (X of YA_Point[3])
              • Set VariableSet YA_Y = (Y of YA_Point[3])
              • Custom script: call SetUnitX(udg_YA_Dummy[udg_YA_Integer], udg_YA_X)
              • Custom script: call SetUnitY(udg_YA_Dummy[udg_YA_Integer], udg_YA_Y)
              • -------- --------
              • Custom script: set bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 200.00 of YA_Point[3].) and do (Actions)
                • Loop - Actions
                  • Set VariableSet YA_Unit = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (YA_Unit is alive) Equal to True
                      • (YA_Unit is A structure) Equal to False
                      • (YA_Unit is in YA_GroupDamaged[YA_Integer].) Equal to False
                      • (YA_Unit belongs to an enemy of (Owner of YA_Caster[YA_Integer]).) Equal to True
                      • YA_Unit Not equal to YA_Target[YA_Integer]
                    • Then - Actions
                      • Unit Group - Add YA_Unit to YA_GroupDamaged[YA_Integer]
                      • Unit - Cause YA_Caster[YA_Integer] to damage YA_Unit, dealing ((0.08 + (0.06 x (Real(YA_LevelBash[YA_Integer])))) x ((Current movement speed of YA_Caster[YA_Integer]) + YA_MS[YA_Integer])) damage of attack type Spells and damage type Magic
                      • Unit - Order YA_Dummy[YA_Integer] to Neutral - Hurl Boulder YA_Unit
                      • Set VariableSet YA_Point[4] = (Position of YA_Unit)
                      • -------- --------
                      • Set VariableSet Knockback2DAngle = (Angle from YA_Point[3] to YA_Point[4])
                      • Set VariableSet Knockback2DDistance = (120.00 + (10.00 x (Real(YA_LevelBash[YA_Integer]))))
                      • Set VariableSet Knockback2DTime = 0.50
                      • Set VariableSet Knockback2DUnit = YA_Unit
                      • Set VariableSet Knockback2DFriction = 0.80
                      • -------- --------
                      • Set VariableSet Knockback2DOverride = False
                      • Set VariableSet Knockback2DCollision = -1.00
                      • -------- --------
                      • Trigger - Run Knockback 2D <gen> (checking conditions)
                      • Custom script: call RemoveLocation(udg_YA_Point[4])
                    • Else - Actions
              • -------- --------
              • -------- ADJUST SPEED --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • YA_MS[YA_Integer] Less than YA_MS_Max[YA_Level[YA_Integer]]
                • Then - Actions
                  • -------- AFTER 12 SECONDS YOU REACH MAXSPEED --------
                  • Set VariableSet YA_MS[YA_Integer] = (YA_MS[YA_Integer] + YA_MS_Increment[YA_Level[YA_Integer]])
                  • Set VariableSet YA_SpeedMoved[YA_Integer] = (YA_SpeedMoved[YA_Integer] + 0.03)
                  • Set VariableSet YA_SpeedAnimation[YA_Integer] = (YA_SpeedAnimation[YA_Integer] + 0.30)
                  • Animation - Change YA_Caster[YA_Integer]'s animation speed to (200.00 + YA_SpeedAnimation[YA_Integer])% of its original speed
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • YA_BooleanMax[YA_Integer] Equal to False
                    • Then - Actions
                      • -------- MAX SPEED REACHED --------
                      • Special Effect - Create a special effect attached to the chest of YA_Caster[YA_Integer] using Abilities\Weapons\ZigguratMissile\ZigguratMissile.mdl
                      • Set VariableSet YA_SFX_C[YA_Integer] = (Last created special effect)
                      • Special Effect - Set Scale of YA_SFX_C[YA_Integer] to 3.00
                      • Set VariableSet YA_BooleanMax[YA_Integer] = True
                    • Else - Actions
              • -------- --------
              • Custom script: call RemoveLocation(udg_YA_Point[3])
            • Else - Actions
              • -------- --------
              • -------- END SPELL --------
              • -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • YA_Target[YA_Integer] Not equal to No unit
                  • (YA_Caster[YA_Integer] is alive) Equal to True
                  • YA_Distance Less than or equal to 100.00
                • Then - Actions
                  • Unit - Deny shared vision of YA_Target[YA_Integer] to (Owner of YA_Caster[YA_Integer])
                  • Unit - Cause YA_Caster[YA_Integer] to damage YA_Target[YA_Integer], dealing ((0.08 + (0.06 x (Real(YA_LevelBash[YA_Integer])))) x ((Current movement speed of YA_Caster[YA_Integer]) + YA_MS[YA_Integer])) damage of attack type Spells and damage type Magic
                  • Ability - Set Ability: (Unit: YA_Dummy[YA_Integer]'s Ability with Ability Code: Greater Bash (Stun))'s Real Level Field: Duration - Normal ('adur') of Level: 0 to (0.80 + (0.40 x (Real(YA_LevelBash[YA_Integer]))))
                  • Ability - Set Ability: (Unit: YA_Dummy[YA_Integer]'s Ability with Ability Code: Greater Bash (Stun))'s Real Level Field: Duration - Hero ('ahdu') of Level: 0 to (0.80 + (0.40 x (Real(YA_LevelBash[YA_Integer]))))
                  • Unit - Order YA_Dummy[YA_Integer] to Neutral - Hurl Boulder YA_Target[YA_Integer]
                  • Set VariableSet YA_Point[4] = (Position of YA_Unit)
                  • -------- --------
                  • Set VariableSet Knockback2DAngle = (Angle from YA_Point[1] to YA_Point[2])
                  • Set VariableSet Knockback2DDistance = (120.00 + (10.00 x (Real(YA_LevelBash[YA_Integer]))))
                  • Set VariableSet Knockback2DTime = 0.50
                  • Set VariableSet Knockback2DUnit = YA_Target[YA_Integer]
                  • Set VariableSet Knockback2DFriction = 0.80
                  • -------- --------
                  • Set VariableSet Knockback2DOverride = False
                  • Set VariableSet Knockback2DCollision = -1.00
                  • -------- --------
                  • Trigger - Run Knockback 2D <gen> (checking conditions)
                  • Unit - Order YA_Caster[YA_Integer] to Attack YA_Target[YA_Integer]
                • Else - Actions
              • -------- --------
              • -------- CREATE SPECIALEFFECT ABOVE TARGET FOR ALLIED PLAYERS --------
              • Set VariableSet YA_PlayerGroup = (All allies of (Owner of YA_Caster[YA_Integer]).)
              • Player Group - Pick every player in YA_PlayerGroup and do (Actions)
                • Loop - Actions
                  • Set VariableSet YA_Player = (Player number of (Picked player))
                  • Custom script: if GetLocalPlayer() == GetEnumPlayer() then
                  • -------- Destroy the SFX in case the spell has already been started by another caster --------
                  • Special Effect - Destroy YA_SFX_B[YA_Player]
                  • Custom script: endif
              • Custom script: call DestroyForce(udg_YA_PlayerGroup)
              • -------- --------
              • Unit - Remove YA_Dummy[YA_Integer] from the game
              • Unit - Turn collision for YA_Caster[YA_Integer] On.
              • Unit - Pause YA_Caster[YA_Integer]
              • Unit - Unpause YA_Caster[YA_Integer]
              • Unit - For Unit YA_Caster[YA_Integer], start cooldown of ability Charge of Darkness " over "(19.00 - (2.00 x (Real(YA_Level[YA_Integer])))) seconds.
              • -------- --------
              • Animation - Change YA_Caster[YA_Integer]'s animation speed to 100.00% of its original speed
              • Animation - Change YA_Caster[YA_Integer]'s vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
              • Animation - Queue YA_Caster[YA_Integer]'s stand ready animation
              • -------- --------
              • Special Effect - Destroy YA_SFX_A[YA_Integer]
              • Special Effect - Destroy YA_SFX_C[YA_Integer]
              • Custom script: call DestroyGroup(udg_YA_GroupDamaged[udg_YA_Integer])
              • -------- --------
              • Set VariableSet YA_Caster[YA_Integer] = YA_Caster[YA_Index]
              • Set VariableSet YA_Target[YA_Integer] = YA_Target[YA_Index]
              • Set VariableSet YA_MS[YA_Integer] = YA_MS[YA_Index]
              • Set VariableSet YA_SpeedMoved[YA_Integer] = YA_SpeedMoved[YA_Index]
              • Set VariableSet YA_SpeedAnimation[YA_Integer] = YA_SpeedAnimation[YA_Index]
              • Set VariableSet YA_Level[YA_Integer] = YA_Level[YA_Index]
              • Set VariableSet YA_LevelBash[YA_Integer] = YA_LevelBash[YA_Index]
              • Set VariableSet YA_BooleanMax[YA_Integer] = YA_BooleanMax[YA_Index]
              • Set VariableSet YA_Dummy[YA_Integer] = YA_Dummy[YA_Index]
              • Set VariableSet YA_SFX_A[YA_Integer] = YA_SFX_A[YA_Index]
              • Set VariableSet YA_SFX_B[YA_Integer] = YA_SFX_B[YA_Index]
              • Set VariableSet YA_SFX_C[YA_Integer] = YA_SFX_C[YA_Index]
              • Set VariableSet YA_GroupDamaged[YA_Integer] = YA_GroupDamaged[YA_Index]
              • -------- --------
              • Set VariableSet YA_Index = (YA_Index - 1)
              • Set VariableSet YA_Integer = (YA_Integer - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • YA_Index Equal to 0
                • Then - Actions
                  • Game - Display to (All players) the text: CHARGE OF DARKNESS ...
                  • Countdown Timer - Pause YA_Timer
                  • Trigger - Turn off (This trigger)
                • Else - Actions
          • Custom script: call RemoveLocation(udg_YA_Point[1])
          • Custom script: call RemoveLocation(udg_YA_Point[2])
 
Last edited:

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,456
Look at my last comment, I showed you what to do.

One effect is created AFTER the Pick Every Player function and that one effect will eventually be destroyed. The effect isn't created or destroyed locally.
The only thing that's treated locally is the model path for the effect which doesn't cause desyncs.
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Thanks, but is this creating ONE effect that only some people (my allies) can see?
I want the enemies to NOT be able to see it. To me the above looks like it's just creating a generic effect that everyone can see.

Here a video that shows the views of all allies of Spirit Breaker (Tiny does not know that he's being charged):
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,456
Thanks, but is this creating ONE effect that only some people (my allies) can see?
I want the enemies to NOT be able to see it. To me the above looks like it's just creating a generic effect that everyone can see.

Here a video that shows the views of all allies of Spirit Breaker (Tiny does not know that he's being charged):
GetLocalPlayer() runs the Actions inside of it for a specific player. This means that other players will not be affected by these Actions.

So effectString is set to a blank empty string for everyone at first. This means that the Special Effect we create will have NO MODEL, the players will never know it's there (but it is). However, Local players will have effectString set to the effect that you actually want. This results in exactly what you want.

The rule is:
It's okay to change a String inside GetLocalPlayer() but it's not okay to Create/Destroy special effects inside GetLocalPlayer(). At least like this in GUI.

Luckily, the string method works just fine. This same method is used to play Sounds for individual players.
 
Level 12
Joined
May 16, 2020
Messages
660
This... indeed works. Thanks!

  • Set VariableSet YA_String = <Empty String>
  • Set VariableSet YA_PlayerGroup = (All allies of (Owner of YA_Caster[YA_Index]).)
  • Player Group - Pick every player in YA_PlayerGroup and do (Actions)
    • Loop - Actions
      • Custom script: if GetLocalPlayer() == GetEnumPlayer() then
      • Set VariableSet YA_String = Abilities\Spells\Other\HowlOfTerror\HowlTarget.mdl
      • Custom script: endif
  • Special Effect - Create a special effect attached to the overhead of YA_Target[YA_Index] using YA_String
  • Set VariableSet YA_SFX_B[YA_Index] = (Last created special effect)
  • Custom script: call DestroyForce(udg_YA_PlayerGroup)

But I don't understand why. The way I read it:

1) First, the YA_String is set to blank (for every player, as it's a single variable without array)
2) Then I pick everyone in YA_PlayerGroup (which are players 1, 2, 3, 4, 5, 6)
3) The game then sets the Ya_String to the last result, which is the one of Player 6, i.e. "set YA_String to whatever defined string"
4) I apply this last defined string (=for Player 6) to my effect (which again... has no array, so how can this be visible to a specified group only?)

Here you also set the effect within the if / endif. Here I understand how it can be that the effect is only visible to defined players.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,456
The string + GetLocalPlayer() stuff results in this:
For players 1 to 6, YA_String = Abilities\Spells\Other\HowlOfTerror\HowlTarget.mdl
For everyone else, YA_String = <Empty String>

Now when it comes time to create the Special Effect notice how it's using YA_String as it's model:
For players 1 to 6, the special effect will use the Howl Of Terror model, because that's what YA_String is equal to for them.
For everyone else, the special effect will have no model (similar to a Dummy unit) because YA_String is empty for them.

Understand that the actions inside your If GetLocalPlayer() function, which in this case modify YA_String, only happen for the specified players:
  • Custom script: if GetLocalPlayer() == GetEnumPlayer() then
    • /// THIS STUFF ONLY HAPPENS FOR THE (PICKED PLAYER)
    • /// THIS STUFF ONLY HAPPENS FOR THE (PICKED PLAYER)
    • /// THIS STUFF ONLY HAPPENS FOR THE (PICKED PLAYER)
  • Custom script: endif
So in your case each player will have their own value for YA_String depending on their alliance with Spirit Breaker. Enemies won't see the effect because it's just an empty model (<Empty String>) but Allies on the other hand WILL see the effect because on their machines it's model has been set to HowlTarget.mdl.

So on my client the String could be equal to something different than on your client. Why doesn't this desync? I guess it's because the Variable doesn't need to be synced between the players in the first place-thus a desync can't happen. Someone who understands the concept better can step in and explain it properly.


In that thread you linked, I needed to Create the effect for everyone because of how it was being used. It was meant for a Quest system that shows "!" over the head of quest givers, and disappears when the quest is completed. So some players will see the "!" effect while others no longer see it because they've completed the quest. This means that I'd be destroying each player's effect at different times. In order to do this, multiple effects were required.

In your case, the special effect will be destroyed at the same time for EVERYONE, therefore it's unnecessary to use more than a single effect.
 
Last edited:
Status
Not open for further replies.
Top