Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
I was talking about the sounds that are made by CreateSound... something something.
You shouldn't destroy global sounds, why would you want to do that? You should just stop the sound and start it again from the beginning when you need to.
I was talking about the sounds that are made by CreateSound... something something.
You shouldn't destroy global sounds, why would you want to do that? You should just stop the sound and start it again from the beginning when you need to.
Sorry, didn't see this. KillSoundWhenDone destroys the sound when it ends, you use it only for sounds that are manually created in the game, and that is via CreateSound function(s).
Why I have this feeling that with an enormous certainty I'm telling the wrong thing? Support me, people, anyone.
Yeah I finally got a handle on sounds, good old JASScraft
Ok, yeah when you create the normal global variable, you do not need to destroy the sound, because it is one single sound handle/object that is used everytime you call it
If you are using purely JASS, then you will probably be creating local variables, setting each one to a brand new sound variable, using it, and then you must destroy it
Normally - One Sound Used 500 times - One Object that should not be destroyed
JASS - 500 Sounds Used 1 Time Each - 500 Objects that should each be destroyed with the KillSoundWhenDone() function
They don't leak if you play them via StartSound function.
Sorry, didn't see this. KillSoundWhenDone destroys the sound when it ends, you use it only for sounds that are manually created in the game, and that is via CreateSound function(s).
Sounds are kind of like triggers. You don't have to destroy them each time and recreate them, you simply start them over and over again. When generated globals are created by using "Use as Sound" in the sound editor, it is automatically created and able to be used as an argument for sound functions.
They do "technically" leak, as you are creating a handle but it is one of those minimal leaks. Since the sound is already a global sound, you don't need to destroy it. Only when using "Create Sound" should you actually destroy it when not needed. Unless, it again, is a global sound.
Let me give you guys some info about "Sounds".
Sounds, are sounds that you hear in game. Well, there are different ways to create sounds:
- looping - This means if you want it to be looping. When using a sound in the sound editor, double-clicking it will have this as an option to checkmark or not. This too is a value in the sound editor for a certain sound's options.
- is3D - This is if you want the sound to be 3D. This means that it has to be positioned and will fade in volume as you move away from the point.
- stopwhenoutofrange - This is like a 3D sound, but instead of fading, I think this will completely stop it. This too is a value in the sound editor for a certain sound's options.
- fadeIn/OutRate - How quickly it fades in/out. The higher the input, the faster. The default is instant.
- eaxSetting - (I think) This is the "effect" of the sound. It is a special effect to the sound, but note that this is only compatible with certain sound cards. You use the suffix "EAX" and replace it with something like "Default", or "Combat", etc.. Doesn't make too much of a difference on some stuff though. For a simple null value (yes, the sound will still work), just use simple double quotes. --> ""
I'm not positive of this though. As they would simply use volume groups instead of strings for values.
- SLKEntryName - I'm not sure. I think this enters it into a SLK file.
- soundLabel - Not sure either. I think after entering the SLK entry name, I think you can use that SLK entry name to retrieve it.
That is how you create sounds.
Generally, when playing sounds more than once you can usually just simply use a global sound since it won't affect the game much.
Now let's take a look at some of the setting sounds... This will allow you to manipulate sounds easily.
JASS:
native SetSoundChannel takes sound soundHandle, integer channel returns nothing
native SetSoundConeAngles takes sound soundHandle, real inside, real outside, integer outsideVolume returns nothing
native SetSoundConeOrientation takes sound soundHandle, real x, real y, real z returns nothing
native SetSoundDistanceCutoff takes sound soundHandle, real cutoff returns nothing
native SetSoundDistances takes sound soundHandle, real minDist, real maxDist returns nothing
native SetSoundDuration takes sound soundHandle, integer duration returns nothing
native SetSoundParamsFromLabel takes sound soundHandle, string soundLabel returns nothing
native SetSoundPitch takes sound soundHandle, real pitch returns nothing
native SetSoundPlayPosition takes sound soundHandle, integer millisecs returns nothing
native SetSoundPosition takes sound soundHandle, real x, real y, real z returns nothing
native SetSoundVelocity takes sound soundHandle, real x, real y, real z returns nothing
native SetSoundVolume takes sound soundHandle, integer volume returns nothing
These are kind of advanced, out of my league in some ways. But I'll do my best at guessing.
Note that most or a lot of these are for 3D sounds. If you do not have that option checked, it might not work properly. Creating it via JASS, you need to make sure that the argument for the "is3D" parameter is set to true.
- SetSoundChannel - I think this refers to the "Channel" selection bar that is in the sound's options. I'm not sure what the identifiers (they have integer identifiers) are. But I kind of doubt it serves that purpose, a more practical purpose would be setting the actual sound channel number. If you double click a .wav (not MP3, they will probably have the encoding method in place of where the sound channel number should be) and look at the Format text. It will name the extension (WAV), then the max kilohertz of the sound, then the bit rate if it is .mp3, otherwise the sample rate for .wav, and finally the number of channels. (google it if you don't know what it is)
- SetSoundConeAngles - This is a pretty advanced sound thing. (I think) this is actual literal sound cones. When the sound cone has no sound orientation, it will simply have the same amplitude at all angles of the sound. (It won't differentiate as the angles change within the cone) I think "inside" refers to the inside cone, and "outside" refers to the outer cone.
The cone is like a flashlight, it will have a cone towards that angle I believe. I haven't really tested this out nor have I tested how it works, but I hope to soon. I'm not sure how the reals work, but I think they are set in hundredths of decibels (logarithmic unit used to measure magnitude of a physical quantity)...
When it has an orientation, it will transition and be louder as it gets towards the middle of the sound cone (the highest point, or whatever you'd like to call it) and then it will transition out as you get near the ends of the cone. If the specified angle was 270, it would be highest (loudest) at 270 and be less loud as it changes the angle.
The outside volume I believe is the amount of sound projected outside of the cone. Remember that this value is 1-127, it doesn't use Percents unless you use PercentToInt() conversion or any other manual conversion.
- SetSoundConeOrientation - If the above stuff are true, then it should determine whether throughout the cone it will be same or transition as you go towards the center (the highest point).
I'm not sure what the parameters are for, though.
- SetSoundDistanceCutoff - This simply will set the distance in which the sound will fade out. Default of 3D sounds vary. Usually when it isn't 3D, the default (grayed out) is 3,000. But for certain sounds such as sound sets, they can be as high as 100,000 or for some small sounds, it might be as low as 1,200.
- SetSoundDistances - I think this refers to the min and max distances. Min distances are the sound level at the minimum distance that the sound can be heard. Max distances are the sound level at the maximum distance that the sound can be heard.
- SetSoundDuration - This sets the duration of the sound. I haven't tested if this works. It might cutoff the end, or it might even speed it up to fit the time, but that can be done by setting a sound's pitch values.
- SetSoundParamsFromLabel - I don't know. My guess is that it can label a sound handle.
- SetSoundPitch - Increasing this will speed up the track/sound.
- SetSoundPlayPosition - This can be used to offset sounds. In SetSoundOffsetBJ, the new offset value will actually use a R2I conversion and be multiplied by 1000, so if your new offset was something like 6.2, it would be R2I(6.2*1,000)... So 6.2*1000 would simply be 6,200... Then you wouldn't really need a conversion.
- SetSoundVelocity - Like texttag velocity, I'm guessing this is the rate of change of position along a straight line.
- SetSoundVolume - This sets the volume of a sound. Like many others, it uses 127 instead of 0-100 or 0-255 or whatever you would expect.
This is a misleading function. People think it will simply just null it or make it not leak or some other variation, but it literally kills it. It destroys it, it demolishes it, so you can't play it again unless you recreate it. If you demolish a building, you can't use their stuff of course unless you rebuild it.
This is leads to a lot of problems by users. This will globally destroy it when it is done and it won't be back until you create it again. Though, there are a lot of bugs and it might not remove leaks.... So it is preferred to use a global sound. The only thing is, it might be better (Imo) to use global blocks and create it because:
1 - You get to control the name of the global
2 - You can control the creation properties
3 - It uses less lines and function executions than blizzard's creation... Unless you really want to label it...
4 - There might be some weird problems of locally creating it and problems with memory and leaks from using KillSoundWhenDone().
- CreateMIDISound - MIDI sounds are sounds with the extension .midi. .MIDI stands for Musical Instrument Digital Interface. These are used in a few maps because they are much lower in file size than .mp3 and .wav. The only downside is that you need a lot of implementation to get .MIDIs to work, and they might be lower quality. This creates a MIDI sound, I don't understand the purpose if wc3 uses all (or at least mostly) .wavs, but I think there might be some .MIDIs in wc3, but I don't know.
- GetSoundIsLoading - This probably just checks if a sound is loading. (no sh*t)
- GetSoundDuration - Retrieves the duration of a sound. Except it retrieves the number in microseconds I think... (If the sound was 1.635 seconds, it would display "1635" if you use I2S(GetSoundDuration(soundHandle))... To make it use regular seconds, just use I2R(GetSoundDuration(...))*0.001... If you want it to display only a portion of it, then you can use Substring functions.
- GetSoundFileDuration - Same as GetSoundDuration(), but uses the sound file instead of a sound handle.
- GetSoundIsPlaying - Returns if a sound is playing. Tested and it works fine. (At least for returning true)
Now, there is also one function to avoid and that is PlaySound(). This will use "KillSoundWhenDone"... So try to use StartSound() instead. PlaySoundBJ() is fine though and uses a good method, for once....
Hopefully, this will help you understand SOUNDS!!!!
EDIT: Woah!!! I feel like Pyrogasm! (Probably not entirely)
I RESERVE DIBS ON MAKING A TUTORIAL OUT OF THIS! (jk, but please don't make a tutorial before me, it will tear my heart... It took me like two days to write this. )
Thank you so much!! That is basically all the info on sounds summed up! You have no idea how grateful we are for this (or maybe you do). You should write a tutorial, you seem to know all about sounds (people usually know only a part of them).
I do very much appreciate it, although that is quite a bit of guesswork, not exactly what I was looking for ><
But, nonetheless, it will help anybody who has no idea about sound to at least start using them
(if I didn't have JASScraft, I wouldn't be able to see that when global sounds are set, where their filenames come from, as well as a few other parameters, exporting scripts is so helpful)
But, nonetheless, it will help anybody who has no idea about sound to at least start using them
(if I didn't have JASScraft, I wouldn't be able to see that when global sounds are set, where their filenames come from, as well as a few other parameters, exporting scripts is so helpful)
Yeah... You can just click, "Use as sound" in the sound editor, make a syntax error and check the InitSound function or w/e that blizzard uses. Then you can delete the sound and whala... You have the label,filepath, and other parameters.
Yeah, some of it is just guessing, but not pointless guessing Herman. Too bad no one knows what those things are for sure and there is no way to find that out.
Sounds probably suck the most, there are many bugs and misunderstandings related to them.
There are ways to test them, the only thing I don't know are some values to input... Like, if I put in a certain value, and it doesn't work, I might just assume it doesn't work because I input the wrong value Yeah.
These non-auto-assumable stuff kind of give headaches. Not like they will be hugely useful though...
It isn't an everyday problem when someone asks how to create a sound cone.
>It's voila, not whala, you(I use entirely too many periods)(I use entirely too many periods)... stupidhead
I can't see your signature
You guys are both stupidheads for using entirely too many periods x)
Voila is an instrument that I quit playing in 6th grade, whala works just fine if not better
Yeah I can't stand all the little bugs you can get in JASS
Atm I am working on a fairly complex system for producing projectiles that can follow an angled quadratic path, but the system uses both the HandleVars system and a customized version of Pandamime's HSAS
I keep getting all these bugs that just do not line up, and there is 10000x places they could be ><
Mostly the bugs are to do with the collision effect + condition, and the endeffect + condition, but FUCK it is annoying me
Sorry, almost completely offtopic, but I NEEDED TO LET IT OUT!
I can't see your signature
You guys are both stupidheads for using entirely too many periods x)
Voila is an instrument that I quit playing in 6th grade, whala works just fine if not better
Yes positions do leak ... it not something new.
But I think it leaks 3 points as Position of Unit is called twice.
And if you want to make something leaky have some imagination. That line could have been a lot longer
Nope, it leaks every single time you call Position of (Unit). You can't clear both.... do you even know how to clean leaks? You store the Position of (Unit) in a variable, then use that variable, after that destroy it with JASS. You can't get to that location of you don't store it in a variable.
And you store only 3 positions
* the first position of UNIT
* the position of UNIT2
* the point created with the polar offset
... in variables than clear them.
WE will do the same: will store 3 points, will use them, then forget to clear them. That is why I say it leaks 3 points
Set Temppos = ((Position of (Triggering unit)) offset by 100.00 towards (Facing of (Triggering unit)) degrees)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units in Damage <gen> matching (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and ((Unit-type of (Matching unit)) Equal to Treant Damage))) and do (Actions)
Loop - Actions
Unit - Move (Picked unit) instantly to Temppos
Set Damagepos = (Position of (Picked unit))
Set Damage[(Player number of (Triggering player))] = (Picked unit)
Unit - Create 1 Call Back Treant for (Owner of (Triggering unit)) at Damagepos facing Default building facing degrees
Unit - Order (Last created unit) to Special Rexxar - Battle Roar
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 100.00 of Damagepos matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True)) and do (Actions)
Loop - Actions
Unit - Order Damage[(Player number of (Triggering player))] to Attack (Picked unit)
Set Damage[(Player number of (Triggering player))] = No unit
Codes do not leak and they don't need to be nullified. Afaik they aren't handles, they are basic types like reals, integers, strings or booleans.
Just_Spectating, yes, in this line:
Set Temppos = ((Position of (Triggering unit)) offset by 100.00 towards (Facing of (Triggering unit)) degrees)
Position of Triggering unit leaks. You have to do like this:
Set TrigPos = (Position of (Triggering unit))
Set Temppos = TrigPos offset by 100.00 towards (Facing of (Triggering unit)) degrees)
Also, in that Pick every unit line, you have to destroy Damagepos inside the loop, because many locations are created and you're just destroying the last one. So you should do like this:
Unit Group - Pick every unit in (Units in Damage <gen> matching (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and ((Unit-type of (Matching unit)) Equal to Treant Damage))) and do (Actions)
Loop - Actions
Unit - Move (Picked unit) instantly to Temppos
Set Damagepos = (Position of (Picked unit))
Set Damage[(Player number of (Triggering player))] = (Picked unit)
Unit - Create 1 Call Back Treant for (Owner of (Triggering unit)) at Damagepos facing Default building facing degrees
Unit - Order (Last created unit) to Special Rexxar - Battle Roar
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 100.00 of Damagepos matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True)) and do (Actions)
Loop - Actions
Unit - Order Damage[(Player number of (Triggering player))] to Attack (Picked unit)
Custom script: call RemoveLocation(udg_Damagepos)
So the final code would look like this:
Attack Treant
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to Attack Treant
Actions
Set TrigPos = (Position of (Triggering unit))
Set Temppos = TrigPos offset by 100.00 towards (Facing of (Triggering unit)) degrees)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units in Damage <gen> matching (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and ((Unit-type of (Matching unit)) Equal to Treant Damage))) and do (Actions)
Loop - Actions
Unit - Move (Picked unit) instantly to Temppos
Set Damagepos = (Position of (Picked unit))
Set Damage[(Player number of (Triggering player))] = (Picked unit)
Unit - Create 1 Call Back Treant for (Owner of (Triggering unit)) at Damagepos facing Default building facing degrees
Unit - Order (Last created unit) to Special Rexxar - Battle Roar
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 100.00 of Damagepos matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True)) and do (Actions)
Loop - Actions
Unit - Order Damage[(Player number of (Triggering player))] to Attack (Picked unit)
Custom script: call RemoveLocation(udg_Damagepos)
Set Damage[(Player number of (Triggering player))] = No unit
Set Temppos = TrigPos offset by 100.00 towards (Facing of (Triggering unit)) degrees)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units in Damage <gen> matching (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and ((Unit-type of (Matching unit)) Equal to Treant Damage))) and do (Actions)
Loop - Actions
Unit - Move (Picked unit) instantly to Temppos
Set Damagepos = (Position of (Picked unit))
Set Damage[(Player number of (Triggering player))] = (Picked unit)
Unit - Create 1 Call Back Treant for (Owner of (Triggering unit)) at Damagepos facing Default building facing degrees
Unit - Order (Last created unit) to Special Rexxar - Battle Roar
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 100.00 of Damagepos matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True)) and do (Actions)
Loop - Actions
Unit - Order Damage[(Player number of (Triggering player))] to Attack (Picked unit)
Custom script: call RemoveLocation(udg_Damagepos)
Set Damage[(Player number of (Triggering player))] = No unit
You can use Damagepos as many times you want because you're using the same locaton, you aren't creating a new one, you just have to null it at the end.
oh, and you only need 1 "set bj_wantDestroyGroup = true i think, becouse its a setting within the trigger
You can use Damagepos as many times you want because you're using the same locaton, you aren't creating a new one, you just have to null it at the end.
I'm sure you need to set it twice, because this is what Pick every unit looks in JASS:
JASS:
function ForGroupBJ takes group whichGroup, code callback returns nothing
// If the user wants the group destroyed, remember that fact and clear
// the flag, in case it is used again in the callback.
local boolean wantDestroy = bj_wantDestroyGroup
set bj_wantDestroyGroup = false
call ForGroup(whichGroup, callback)
// If the user wants the group destroyed, do so now.
if (wantDestroy) then
call DestroyGroup(whichGroup)
endif
endfunction
You see? It sets bj_wantDestroyGroup to false even before the actual ForGroup actions, so during the execution bj_wantDestroyGroup is already false, so if you want another group loop inside the first one, you need to set it to true again.
Er, yeah, how do you code if you're not using unit groups Razorbrain? I can hardly imagine coding without using Pick every unit in group action. But I guess you have your own ways...
And stop spamming Need or at least try to sound like you're saying something useful, it's for your own good (I somehow always get away with it, bwahahahaha ).
A tip to all you GUI users, always try to store everything (mostly event responses) in variables and then use those variables instead. It's inefficient if you use triggering unit like 10 times in a single spell, sometimes if there are too many, it can cause lags (in combination with other inefficiencies in GUI).
You see, Need? I said something useful (or at least it sounded that way) and now mods can't do me shit.
JNGP World Editor.
In the modified WE some of the syntax is different [for instance Equal to now has its JASS code in brackets next to it.
I just read somewhere that using loops was inefficient or something, if that's not true then that saves me a lot of grunt work.
Using loops is not inefficient. However a ForGroup isn't exactly amazingly fast... Besides in GUI, inefficiency is not half as significant as removing the dozens of leaks caused by the different functions.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.