• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Playing sounds for a single player without issues

Status
Not open for further replies.

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,583
Hello, I know there's a lot of threads on this subject but they're all very dated and lacked the answer I was looking for.

Basically, I'm trying to play a sound whenever the user presses a custom frame button.

I've got this function for playing the sound but the issue is it requires x/y coordinates and only works if the user's camera is near those coordinates:
Lua:
function PlaySoundForPlayer(sndPath, player, sndX, sndY, vol)
    if GetLocalPlayer() ~= player then
        sndPath = ""
    end
    local snd = CreateSound(sndPath, false, true, true, 10, 10, "DefaultEAXON")
    local point = Location(sndX, sndY)
    SetSoundChannel(snd, 0)
    SetSoundDistances(snd, 600, 500000)
    SetSoundDistanceCutoff(snd, 500000)
    SetSoundDuration(snd, GetSoundFileDuration(sndPath))
    SetSoundVolume(snd, 127)
    SetSoundConeAngles(snd, 0, 0, 127)
    SetSoundConeOrientation(snd, 0, 0, 0)
    SetSoundPitch(snd, 1.0)
    PlaySoundAtPointBJ(snd, vol, point, 0)
    KillSoundWhenDone(snd)
end
Is there any solution to get around the limiting nature of Warcraft 3's sounds? I simply want a sound that always plays regardless of location and does not interrupt/get interrupted by other sounds.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
EDIT:
This function seem to be working fine now. Not sure why it didn't work properly in my tests before.
 
Last edited:

Wrda

Spell Reviewer
Level 26
Joined
Nov 18, 2012
Messages
1,895
Variable point is leaking a location.
You might also consider using SetSoundPosition instead of PlaySoundAtPointBJ
Is there any solution to get around the limiting nature of Warcraft 3's sounds? I simply want a sound that always plays regardless of location and does not interrupt/get interrupted by other sounds.
Something tells me you're using 3D sounds.

I've been making a compilation of general functions, and the sound part is the following:
Lua:
--Sound
    ---Play general sound.
    ---@param path string
    ---@param pitch number
    ---@param isloop boolean
    ---@return sound
    function SoundPlayGeneral(path, pitch, isloop)
        local snd = CreateSound(path, isloop, false, false, 10, 10, "DefaultEAXON")
        --Stuff that must be performed immediately upon creation of sounds
        SetSoundChannel(snd, 0)
        SetSoundVolume(snd, 127)
        SetSoundPitch(snd, pitch)
        StartSound(snd)
        if not isloop then
            KillSoundWhenDone(snd)
        end
        return snd
    end
    ---Play general sound for player.
    ---@param path string
    ---@param pitch number
    ---@param whichPlayer player
    ---@param isloop boolean
    ---@return sound
    function SoundPlayGeneralForPlayer(path, pitch, whichPlayer, isloop)
        local snd = CreateSound(path, isloop, false, false, 10, 10, "DefaultEAXON")
        --Stuff that must be performed immediately upon creation of sounds
        SetSoundChannel(snd, 0)
        SetSoundVolume(snd, 127)
        SetSoundPitch(snd, pitch)
        if GetLocalPlayer() ~= whichPlayer then
            SetSoundVolume(snd, 0)
        end
        StartSound(snd)
        if not isloop then
            KillSoundWhenDone(snd)
        end
        return snd
    end
    ---Play sound in 3D, attached to unit.
    ---@param path string
    ---@param pitch number
    ---@param whichUnit unit
    ---@param isloop boolean
    ---@return sound
    function SoundPlay3DUnit(path, pitch, whichUnit, isloop)
        local snd = CreateSound(path, isloop, true, true, 10, 10, "DefaultEAXON")
        --Stuff that must be performed immediately upon creation of sounds
        SetSoundChannel(snd, 0)
        SetSoundVolume(snd, 127)
        SetSoundPitch(snd, pitch)
        --These are settings necessary for 3-D sounds to function properly
        SetSoundDistances(snd, 600., 10000.)
        SetSoundDistanceCutoff(snd, 3000.)
        SetSoundConeAngles(snd, 0., 0., 127)
        SetSoundConeOrientation(snd, 0., 0., 0.)
        AttachSoundToUnit(snd, whichUnit)
        StartSound(snd)
        if not isloop then
            KillSoundWhenDone(snd)
        end
        return snd
    end
    ---play sound in 3D, on a point.
    ---@param path string
    ---@param pitch number
    ---@param x number
    ---@param y number
    ---@param z number
    ---@param isloop boolean
    ---@return sound
    function SoundPlay3DCoords(path, pitch, x, y, z, isloop)
        local snd = CreateSound(path, isloop, true, true, 10, 10, "DefaultEAXON")
        --Stuff that must be performed immediately upon creation of sounds
        SetSoundChannel(snd, 0)
        SetSoundVolume(snd, 127)
        SetSoundPitch(snd, pitch)
        --These are settings necessary for 3-D sounds to function properly
        SetSoundDistances(snd, 600., 10000.)
        SetSoundDistanceCutoff(snd, 3000.)
        SetSoundConeAngles(snd, 0., 0., 127)
        SetSoundConeOrientation(snd, 0., 0., 0.)
        SetSoundPosition(snd, x, y, z)
        StartSound(snd)
        if not isloop then
            KillSoundWhenDone(snd)
        end
        return snd
    end
I don't think I've seen someone using setting the path according to localplayer regarding the sounds, volume appeared to be the standard, but I guess it works the same way.
 
Level 7
Joined
Mar 16, 2014
Messages
152
This works completely fine in my map. It's letting only certain targets be hit by a spell that can't be hit by an object editor, and fakes the usual Warcraft 3 rejection text/noise.

  • Time Bomb Check
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Time Bomb
      • ((Target unit of ability being cast) is A Hero) Equal to True
      • (Triggering unit) Not equal to (Target unit of ability being cast)
    • Actions
      • Unit - Order (Triggering unit) to Stop.
      • Unit - Set mana of (Triggering unit) to ((Mana of (Triggering unit)) + (150.00 + (150.00 x (Real((Level of Time Bomb for Kimblee_Unit))))))
      • Set VariableSet TempReal2 = (Real((Level of Time Bomb for (Triggering unit))))
      • Unit - Remove Time Bomb from (Triggering unit)
      • Unit - Add Time Bomb to (Triggering unit)
      • Unit - Set level of Time Bomb for (Triggering unit) to (Integer(TempReal2))
      • Custom script: if udg_ErrorSound == null then
      • Custom script: set udg_ErrorSound = CreateSoundFromLabel( "InterfaceError",false,false,false,10,10)
      • Set VariableSet ErrorSound = ErrorSound
      • Set VariableSet ErrorMessage = Can't target heroes other than self.
      • Set VariableSet ErrorPlayer = (Owner of (Triggering unit))
      • 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: endif
      • Custom script: call StartSound(udg_ErrorSound)
      • Custom script: endif
      • Custom script: set udg_ErrorSound = null
      • Custom script: set udg_ErrorMessage = null
      • Skip remaining actions
 
Level 39
Joined
Feb 27, 2007
Messages
5,034
This condition is largely useless: (Triggering unit) Not equal to (Target unit of ability being cast). You can make the spell's targets include "not self" and then you can't cast on yourself.

Unit - Set mana of (Triggering unit) to ((Mana of (Triggering unit)) + (150.00 + (150.00 x (Real((Level of Time Bomb for Kimblee_Unit))))))
It's also possible to read the spell's mana cost with the trigger, rather than computing its cost yourself. However, the levels for that function are all off by 1, so if you want data for spell level N you need to give it (N-1).
 
Level 7
Joined
Mar 16, 2014
Messages
152
This condition is largely useless: (Triggering unit) Not equal to (Target unit of ability being cast). You can make the spell's targets include "not self" and then you can't cast on yourself.

Unit - Set mana of (Triggering unit) to ((Mana of (Triggering unit)) + (150.00 + (150.00 x (Real((Level of Time Bomb for Kimblee_Unit))))))
It's also possible to read the spell's mana cost with the trigger, rather than computing its cost yourself. However, the levels for that function are all off by 1, so if you want data for spell level N you need to give it (N-1).
I didn't show the logic because it wasn't relevant to the topic's question, but the specific thing I wanted is castable on units (both allied and enemy) and self but not other heroes, which cannot be done with Object Editor.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,583
Thanks, I missed that leak and I'll use your functions instead. And yes, I meant 3D sounds, as far as I'm aware non-3D sounds interfere with one another if they're on the same channel. I needed a sound that would always play regardless.

What's weird is that the sound issue my function was having went away after I changed the x/y coordinates from 0,0 to the position of the player's hero using GetUnitX/Y(). So apparently that function I posted works... Odd.
 
Last edited:
Status
Not open for further replies.
Top