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

Using Sounds Specific To Each Player

Status
Not open for further replies.
Level 5
Joined
Mar 24, 2020
Messages
80
Hi guys, just a quick one! I am just trying to figure out the best way to manage player specific sounds.

Q.1 - Is there a way to GetLocalPlayer to detect the picked player? So I could put it in a player group loop?
Q.2 - How do I optimize the below?

During the first 30 seconds a voiceover is being played to all players. This voiceover is broken down into 4 sounds/parts. If a player within the first 30 seconds begins building too close to a point, the voiceover stops playing for that specific player and then plays a sound/voiceover to that specific triggering player. What I need to happen is if this sound/warning is being played to the specific player, that specific player won't hear the next part of the main voiceover, IF the warning sound is still being played to them.

I hope that makes sense! So far I have this:

  • Build near gates
    • Events
      • Unit - A unit Begins construction
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Distance between (Position of (Triggering unit)) and (Position of DomainGate[1])) Less than or equal to 3500.00
          • (Distance between (Position of (Triggering unit)) and (Position of DomainGate[2])) Less than or equal to 3500.00
    • Actions
      • Game - Display to (All players matching ((Owner of (Triggering unit)) Equal to (Matching player)).) for 20.00 seconds the text: |cffff0000You are b...
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of (Triggering unit)) Equal to Player 1 (Red)
        • Then - Actions
          • Custom script: if GetLocalPlayer() == Player(0) then
          • Sound - Stop CurrentSound Immediately
          • Sound - Play You_Are_Building_Next_To_One_Of_My_Gates <gen>
          • Set VariableSet SoundGateBuildWarningBoolean[(Player number of (Owner of (Triggering unit)))] = True
          • Wait 9.00 game-time seconds
          • Set VariableSet SoundGateBuildWarningBoolean[(Player number of (Owner of (Triggering unit)))] = False
          • Custom script: endif
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of (Triggering unit)) Equal to Player 2 (Blue)
        • Then - Actions
          • Custom script: if GetLocalPlayer() == Player(1) then
          • Sound - Stop CurrentSound Immediately
          • Sound - Play You_Are_Building_Next_To_One_Of_My_Gates <gen>
          • Set VariableSet SoundGateBuildWarningBoolean[(Player number of (Owner of (Triggering unit)))] = True
          • Wait 9.00 game-time seconds
          • Set VariableSet SoundGateBuildWarningBoolean[(Player number of (Owner of (Triggering unit)))] = False
          • Custom script: endif
        • Else - Actions
  • Example
    • Events
    • Conditions
    • Actions
      • Sound - Play Part_3 <gen>
      • Set VariableSet CurrentSound = (Last played sound)
      • Player Group - Pick every player in Players and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SoundGateBuildWarningBoolean[(Player number of (Picked player))] Equal to False
            • Then - Actions
            • Else - Actions
              • Custom script: if GetLocalPlayer() == Player(PickedPlayer) then
              • Sound - Stop CurrentSound Immediately
              • Custom script: endif
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,546
1) You're leaking 4 Points in your initial Conditions. "Position of X" creates a Point that is never removed (unless managed with Point variables). You're also leaking a Player Group with your Text Message (All players matching...).

2) There's no reason to have more than one If Then Else. You can use an OR and check for multiple conditions.

If owner of triggering unit equal to Player 1 OR Player 2 then do Actions:
if GetLocalPlayer() == GetOwningPlayer(GetTriggerUnit()) then
Stop Sound
Play Sound
endif

3) Don't put the Variable/Wait stuff inside of the GetLocalPlayer code. Do it like I did in my example above, endif should be right below the Play Sound.

4) Referring to your Main Voiceover Trigger, Player(PickedPlayer) isn't a thing. Instead, change it to: if GetLocalPlayer() == GetEnumPlayer() then.

GetEnumPlayer() gets you the Picked player.

Player() requires a number between 0-27, Player(0) = Player 1, Player(1) = Player 2, Player(2) = Player 3, etc... Most things in Jass are indexed starting at 0.

With all of that being said, I can't say for certain whether or not Stopping a Sound with GetLocalPlayer will cause a desync or even work in the first place.
 
Last edited:
Level 5
Joined
Mar 24, 2020
Messages
80
Uncle always coming in with the help! Thanks a lot again dude!
I've got it working with the below. Like you said with the desync issues, I may just need to test it and see if its stable or not. It would be a shame if it caused issues.

  • Build near gates
    • Events
      • Unit - A unit Begins construction
    • Conditions
    • Actions
      • Set VariableSet TempPoint = (Position of (Triggering unit))
      • Set VariableSet SpawnLocation = (Position of DomainGate[1])
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between TempPoint and SpawnLocation) Less than or equal to 3500.00
        • Then - Actions
          • Game - Display to (All players matching ((Owner of (Triggering unit)) Equal to (Matching player)).) for 20.00 seconds the text: |cffff0000You are b...
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (Owner of (Triggering unit)) Equal to Player 1 (Red)
                  • (Owner of (Triggering unit)) Equal to Player 2 (Blue)
                  • (Owner of (Triggering unit)) Equal to Player 3 (Teal)
                  • (Owner of (Triggering unit)) Equal to Player 4 (Purple)
                  • (Owner of (Triggering unit)) Equal to Player 5 (Yellow)
                  • (Owner of (Triggering unit)) Equal to Player 6 (Orange)
                  • (Owner of (Triggering unit)) Equal to Player 7 (Green)
                  • (Owner of (Triggering unit)) Equal to Player 8 (Pink)
            • Then - Actions
              • Custom script: if GetLocalPlayer() == GetOwningPlayer(GetTriggerUnit()) then
              • Sound - Stop CurrentSound Immediately
              • Sound - Play You_Are_Building_Next_To_One_Of_My_Gates <gen>
              • Custom script: endif
            • Else - Actions
          • Set VariableSet SoundGateBuildWarningBoolean[(Player number of (Owner of (Triggering unit)))] = True
          • Wait 9.00 game-time seconds
          • Set VariableSet SoundGateBuildWarningBoolean[(Player number of (Owner of (Triggering unit)))] = False
        • Else - Actions
      • Custom script: call RemoveLocation (udg_SpawnLocation)
      • Set VariableSet SpawnLocation = (Position of DomainGate[2])
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between TempPoint and SpawnLocation) Less than or equal to 3500.00
        • Then - Actions
          • Game - Display to (All players matching ((Owner of (Triggering unit)) Equal to (Matching player)).) for 20.00 seconds the text: |cffff0000You are b...
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (Owner of (Triggering unit)) Equal to Player 1 (Red)
                  • (Owner of (Triggering unit)) Equal to Player 2 (Blue)
                  • (Owner of (Triggering unit)) Equal to Player 3 (Teal)
                  • (Owner of (Triggering unit)) Equal to Player 4 (Purple)
                  • (Owner of (Triggering unit)) Equal to Player 5 (Yellow)
                  • (Owner of (Triggering unit)) Equal to Player 6 (Orange)
                  • (Owner of (Triggering unit)) Equal to Player 7 (Green)
                  • (Owner of (Triggering unit)) Equal to Player 8 (Pink)
            • Then - Actions
              • Custom script: if GetLocalPlayer() == GetOwningPlayer(GetTriggerUnit()) then
              • Sound - Stop CurrentSound Immediately
              • Sound - Play You_Are_Building_Next_To_One_Of_My_Gates <gen>
              • Custom script: endif
            • Else - Actions
          • Set VariableSet SoundGateBuildWarningBoolean[(Player number of (Owner of (Triggering unit)))] = True
          • Wait 9.00 game-time seconds
          • Set VariableSet SoundGateBuildWarningBoolean[(Player number of (Owner of (Triggering unit)))] = False
        • Else - Actions
      • Custom script: call RemoveLocation (udg_TempPoint)
      • Custom script: call RemoveLocation (udg_SpawnLocation)


  • Play Part 1
    • Events
    • Conditions
    • Actions
      • Sound - Play Part_1 <gen>
      • Set VariableSet CurrentSound = (Last played sound)
      • Player Group - Pick every player in Players and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • SoundGateBuildWarningBoolean[(Player number of (Picked player))] Equal to False
            • Then - Actions
            • Else - Actions
              • Custom script: if GetLocalPlayer() == GetEnumPlayer() then
              • Sound - Stop CurrentSound Immediately
              • Custom script: endif
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,546
So you're going to want to adjust how you're Removing SpawnLocation to prevent leaks from occuring. This is because you're using a Wait and when you do so SpawnLocation won't be removed for 9 seconds. During this time it's safe to assume that SpawnLocation could leak several times.

Something like:
If distance is <= 3500 then
Remove SpawnLocation
ELSE
Remove SpawnLocation

This way SpawnLocation is guaranteed to be removed. It's removed if there is no Wait, and it's removed BEFORE the Wait if there is one.

And Set SoundGateWarning = True -> Wait -> SoundGateWarning = False, is running regardless of the owner of triggering unit, so any Player can cause those Actions to happen not just Players 1-8.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Sounds are async by nature :
a sound won't be played if player settings sound is off, or if his wc3 is minimised, many sounds are different according the wc3 language installed, and so one.

So it should be totally safe to play or stop a sound in a local block code.
Even creating/destroying should be ok too.
 
Level 18
Joined
Jan 1, 2018
Messages
728
So it should be totally safe to play or stop a sound in a local block code.
Even creating/destroying should be ok too.
I'm not so sure this is correct, I usually only change the sound volume in local code (setting it to 0 to mute it for certain players), so I think that's the safest way if you're worried about desyncs.
 
Level 5
Joined
Mar 24, 2020
Messages
80
So you're going to want to adjust how you're Removing SpawnLocation to prevent leaks from occuring. This is because you're using a Wait and when you do so SpawnLocation won't be removed for 9 seconds. During this time it's safe to assume that SpawnLocation could leak several times.

Something like:
If distance is <= 3500 then
Remove SpawnLocation
ELSE
Remove SpawnLocation

This way SpawnLocation is guaranteed to be removed. It's removed if there is no Wait, and it's removed BEFORE the Wait if there is one.

And Set SoundGateWarning = True -> Wait -> SoundGateWarning = False, is running regardless of the owner of triggering unit, so any Player can cause those Actions to happen not just Players 1-8.

Thanks Uncle for that last fix! I've implemented it.

Sounds are async by nature :
a sound won't be played if player settings sound is off, or if his wc3 is minimised, many sounds are different according the wc3 language installed, and so one.

So it should be totally safe to play or stop a sound in a local block code.
Even creating/destroying should be ok too.

I have successfully changed the volumes within Battle.net games using this. No de-syncs yet.
 
Status
Not open for further replies.
Top