Name | Type | is_array | initial_value |
---@diagnostic disable: undefined-global
if Debug then Debug.beginFile 'TotalInitialization' end
--[[ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Total Initialization version 5.3.1
Created by: Bribe
Contributors: Eikonium, HerlySQR, Tasyen, Luashine, Forsakn
Inspiration: Almia, ScorpioT1000, Troll-Brain
Hosted at: https://github.com/BribeFromTheHive/Lua/blob/master/TotalInitialization.lua
Debug library hosted at: https://www.hiveworkshop.com/threads/debug-utils-ingame-console-etc.330758/
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ]]
---Calls the user's initialization function during the map's loading process. The first argument should either be the init function,
---or it should be the string to give the initializer a name (works similarly to a module name/identically to a vJass library name).
---
---To use requirements, call `Require.strict 'LibraryName'` or `Require.optional 'LibraryName'`. Alternatively, the OnInit callback
---function can take the `Require` table as a single parameter: `OnInit(function(import) import.strict 'ThisIsTheSameAsRequire' end)`.
---
-- - `OnInit.global` or just `OnInit` is called after InitGlobals and is the standard point to initialize.
-- - `OnInit.trig` is called after InitCustomTriggers, and is useful for removing hooks that should only apply to GUI events.
-- - `OnInit.map` is the last point in initialization before the loading screen is completed.
-- - `OnInit.final` occurs immediately after the loading screen has disappeared, and the game has started.
---@class OnInit
--
--Simple Initialization without declaring a library name:
---@overload async fun(initCallback: Initializer.Callback)
--
--Advanced initialization with a library name and an optional third argument to signal to Eikonium's DebugUtils that the file has ended.
---@overload async fun(libraryName: string, initCallback: Initializer.Callback, debugLineNum?: integer)
--
--A way to yield your library to allow other libraries in the same initialization sequence to load, then resume once they have loaded.
---@overload async fun(customInitializerName: string)
OnInit = {}
---@alias Initializer.Callback fun(require?: Requirement | {[string]: Requirement}):...?
---@alias Requirement async fun(reqName: string, source?: table): unknown
-- `Require` will yield the calling `OnInit` initialization function until the requirement (referenced as a string) exists. It will check the
-- global API (for example, does 'GlobalRemap' exist) and then check for any named OnInit resources which might use that same string as its name.
--
-- Due to the way Sumneko's syntax highlighter works, the return value will only be linted for defined @class objects (and doesn't work for regular
-- globals like `TimerStart`). I tried to request the functionality here: https://github.com/sumneko/lua-language-server/issues/1792 , however it
-- was closed. Presumably, there are other requests asking for it, but I wouldn't count on it.
--
-- To declare a requirement, use: `Require.strict 'SomeLibrary'` or (if you don't care about the missing linting functionality) `Require 'SomeLibrary'`
--
-- To optionally require something, use any other suffix (such as `.optionally` or `.nonstrict`): `Require.optional 'SomeLibrary'`
--
---@class Require: { [string]: Requirement }
---@overload async fun(reqName: string, source?: table): string
Require = {}
do
local library = {} --You can change this to false if you don't use `Require` nor the `OnInit.library` API.
--CONFIGURABLE LEGACY API FUNCTION:
---@param _ENV table
---@param OnInit any
local function assignLegacyAPI(_ENV, OnInit)
OnGlobalInit = OnInit; OnTrigInit = OnInit.trig; OnMapInit = OnInit.map; OnGameStart = OnInit.final --Global Initialization Lite API
--OnMainInit = OnInit.main; OnLibraryInit = OnInit.library; OnGameInit = OnInit.final --short-lived experimental API
--onGlobalInit = OnInit; onTriggerInit = OnInit.trig; onInitialization = OnInit.map; onGameStart = OnInit.final --original Global Initialization API
--OnTriggerInit = OnInit.trig; OnInitialization = OnInit.map --Forsakn's Ordered Indices API
end
--END CONFIGURABLES
local _G, rawget, insert =
_G, rawget, table.insert
local initFuncQueue = {}
---@param name string
---@param continue? function
local function runInitializers(name, continue)
--print('running:', name, tostring(initFuncQueue[name]))
if initFuncQueue[name] then
for _,func in ipairs(initFuncQueue[name]) do
coroutine.wrap(func)(Require)
end
initFuncQueue[name] = nil
end
if library then
library:resume()
end
if continue then
continue()
end
end
local function initEverything()
---@param hookName string
---@param continue? function
local function hook(hookName, continue)
local hookedFunc = rawget(_G, hookName)
if hookedFunc then
rawset(_G, hookName,
function()
hookedFunc()
runInitializers(hookName, continue)
end
)
else
runInitializers(hookName, continue)
end
end
hook(
'InitGlobals',
function()
hook(
'InitCustomTriggers',
function()
hook('RunInitializationTriggers')
end
)
end
)
hook(
'MarkGameStarted',
function()
if library then
for _,func in ipairs(library.queuedInitializerList) do
func(nil, true) --run errors for missing requirements.
end
for _,func in pairs(library.yieldedModuleMatrix) do
func(true) --run errors for modules that aren't required.
end
end
OnInit = nil
Require = nil
end
)
end
---@param initName string
---@param libraryName string | Initializer.Callback
---@param func? Initializer.Callback
---@param debugLineNum? integer
---@param incDebugLevel? boolean
local function addUserFunc(initName, libraryName, func, debugLineNum, incDebugLevel)
if not func then
---@cast libraryName Initializer.Callback
func = libraryName
else
assert(type(libraryName) == 'string')
if debugLineNum and Debug then
Debug.beginFile(libraryName, incDebugLevel and 3 or 2)
Debug.data.sourceMap[#Debug.data.sourceMap].lastLine = debugLineNum
end
if library then
func = library:create(libraryName, func)
end
end
assert(type(func) == 'function')
--print('adding user func: ' , initName , libraryName, debugLineNum, incDebugLevel)
initFuncQueue[initName] = initFuncQueue[initName] or {}
insert(initFuncQueue[initName], func)
if initName == 'root' or initName == 'module' then
runInitializers(initName)
end
end
---@param name string
local function createInit(name)
---@async
---@param libraryName string --Assign your callback a unique name, allowing other OnInit callbacks can use it as a requirement.
---@param userInitFunc Initializer.Callback --Define a function to be called at the chosen point in the initialization process. It can optionally take the `Require` object as a parameter. Its optional return value(s) are passed to a requiring library via the `Require` object (defaults to `true`).
---@param debugLineNum? integer --If the Debug library is present, you can call Debug.getLine() for this parameter (which should coincide with the last line of your script file). This will neatly tie-in with OnInit's built-in Debug library functionality to define a starting line and an ending line for your module.
---@overload async fun(userInitFunc: Initializer.Callback)
return function(libraryName, userInitFunc, debugLineNum)
addUserFunc(name, libraryName, userInitFunc, debugLineNum)
end
end
OnInit.global = createInit 'InitGlobals' -- Called after InitGlobals, and is the standard point to initialize.
OnInit.trig = createInit 'InitCustomTriggers' -- Called after InitCustomTriggers, and is useful for removing hooks that should only apply to GUI events.
OnInit.map = createInit 'RunInitializationTriggers' -- Called last in the script's loading screen sequence. Runs after the GUI "Map Initialization" events have run.
OnInit.final = createInit 'MarkGameStarted' -- Called immediately after the loading screen has disappeared, and the game has started.
do
---@param self table
---@param libraryNameOrInitFunc function | string
---@param userInitFunc function
---@param debugLineNum number
local function __call(
self,
libraryNameOrInitFunc,
userInitFunc,
debugLineNum
)
if userInitFunc or type(libraryNameOrInitFunc) == 'function' then
addUserFunc(
'InitGlobals', --Calling OnInit directly defaults to OnInit.global (AKA OnGlobalInit)
libraryNameOrInitFunc,
userInitFunc,
debugLineNum,
true
)
elseif library then
library:declare(libraryNameOrInitFunc) --API handler for OnInit "Custom initializer"
else
error(
"Bad OnInit args: "..
tostring(libraryNameOrInitFunc) .. ", " ..
tostring(userInitFunc)
)
end
end
setmetatable(OnInit --[[@as table]], { __call = __call })
end
do --if you don't need the initializers for 'root', 'config' and 'main', you can delete this do...end block.
local gmt = getmetatable(_G) or
getmetatable(setmetatable(_G, {}))
local rawIndex = gmt.__newindex or rawset
local hookMainAndConfig
---@param _G table
---@param key string
---@param fnOrDiscard unknown
function hookMainAndConfig(_G, key, fnOrDiscard)
if key == 'main' or key == 'config' then
---@cast fnOrDiscard function
if key == 'main' then
runInitializers 'root'
end
rawIndex(_G, key, function()
if key == 'config' then
fnOrDiscard()
elseif gmt.__newindex == hookMainAndConfig then
gmt.__newindex = rawIndex --restore the original __newindex if no further hooks on __newindex exist.
end
runInitializers(key)
if key == 'main' then
fnOrDiscard()
end
end)
else
rawIndex(_G, key, fnOrDiscard)
end
end
gmt.__newindex = hookMainAndConfig
OnInit.root = createInit 'root' -- Runs immediately during the Lua root, but is yieldable (allowing requirements) and pcalled.
OnInit.config = createInit 'config' -- Runs when `config` is called. Credit to @Luashine: https://www.hiveworkshop.com/threads/inject-main-config-from-we-trigger-code-like-jasshelper.338201/
OnInit.main = createInit 'main' -- Runs when `main` is called. Idea from @Tasyen: https://www.hiveworkshop.com/threads/global-initialization.317099/post-3374063
end
if library then
library.queuedInitializerList = {}
library.customDeclarationList = {}
library.yieldedModuleMatrix = {}
library.moduleValueMatrix = {}
function library:pack(name, ...)
self.moduleValueMatrix[name] = table.pack(...)
end
function library:resume()
if self.queuedInitializerList[1] then
local continue, tempQueue, forceOptional
::initLibraries::
repeat
continue=false
self.queuedInitializerList, tempQueue =
{}, self.queuedInitializerList
for _,func in ipairs(tempQueue) do
if func(forceOptional) then
continue=true --Something was initialized; therefore further systems might be able to initialize.
else
insert(self.queuedInitializerList, func) --If the queued initializer returns false, that means its requirement wasn't met, so we re-queue it.
end
end
until not continue or not self.queuedInitializerList[1]
if self.customDeclarationList[1] then
self.customDeclarationList, tempQueue =
{}, self.customDeclarationList
for _,func in ipairs(tempQueue) do
func() --unfreeze any custom initializers.
end
elseif not forceOptional then
forceOptional = true
else
return
end
goto initLibraries
end
end
local function declareName(name, initialValue)
assert(type(name) == 'string')
assert(library.moduleValueMatrix[name] == nil)
library.moduleValueMatrix[name] =
initialValue and { true, n = 1 }
end
function library:create(name, userFunc)
assert(type(userFunc) == 'function')
declareName(name, false) --declare itself as a non-loaded library.
return function()
self:pack(name, userFunc(Require)) --pack return values to allow multiple values to be communicated.
if self.moduleValueMatrix[name].n == 0 then
self:pack(name, true) --No values were returned; therefore simply package the value as `true`
end
end
end
---@async
function library:declare(name)
declareName(name, true) --declare itself as a loaded library.
local co = coroutine.running()
insert(
self.customDeclarationList,
function()
coroutine.resume(co)
end
)
coroutine.yield() --yields the calling function until after all currently-queued initializers have run.
end
local processRequirement
---@async
function processRequirement(
optional,
requirement,
explicitSource
)
if type(optional) == 'string' then
optional, requirement, explicitSource =
true, optional, requirement --optional requirement (processed by the __index method)
else
optional = false --strict requirement (processed by the __call method)
end
local source = explicitSource or _G
assert(type(source)=='table')
assert(type(requirement)=='string')
::reindex::
local subSource, subReq =
requirement:match("([\x25w_]+)\x25.(.+)") --Check if user is requiring using "table.property" syntax
if subSource and subReq then
source,
requirement =
processRequirement(subSource, source), --If the container is nil, yield until it is not.
subReq
if type(source)=='table' then
explicitSource = source
goto reindex --check for further nested properties ("table.property.subProperty.anyOthers").
else
return --The source table for the requirement wasn't found, so disregard the rest (this only happens with optional requirements).
end
end
local function loadRequirement(unpack)
local package = rawget(source, requirement) --check if the requirement exists in the host table.
if not package and not explicitSource then
if library.yieldedModuleMatrix[requirement] then
library.yieldedModuleMatrix[requirement]() --load module if it exists
end
package = library.moduleValueMatrix[requirement] --retrieve the return value from the module.
if unpack and type(package)=='table' then
return table.unpack(package, 1, package.n) --using unpack allows any number of values to be returned by the required library.
end
end
return package
end
local co, loaded
local function checkReqs(forceOptional, printErrors)
if not loaded then
loaded = loadRequirement()
loaded = loaded or optional and
(loaded==nil or forceOptional)
if loaded then
if co then coroutine.resume(co) end --resume only if it was yielded in the first place.
return loaded
elseif printErrors then
coroutine.resume(co, true)
end
end
end
if not checkReqs() then --only yield if the requirement doesn't already exist.
co = coroutine.running()
insert(library.queuedInitializerList, checkReqs)
if coroutine.yield() then
error("Missing Requirement: "..requirement) --handle the error within the user's function to get an accurate stack trace via the `try` function.
end
end
return loadRequirement(true)
end
---@type Requirement
function Require.strict(name, explicitSource)
return processRequirement(nil, name, explicitSource)
end
setmetatable(Require --[[@as table]], {
__call = processRequirement,
__index = function()
return processRequirement
end
})
local module = createInit 'module'
--- `OnInit.module` will only call the OnInit function if the module is required by another resource, rather than being called at a pre-
--- specified point in the loading process. It works similarly to Go, in that including modules in your map that are not actually being
--- required will throw an error message.
---@param name string
---@param func fun(require?: Initializer.Callback):any
---@param debugLineNum? integer
OnInit.module = function(name, func, debugLineNum)
if func then
local userFunc = func
func = function(require)
local co = coroutine.running()
library.yieldedModuleMatrix[name] =
function(failure)
library.yieldedModuleMatrix[name] = nil
coroutine.resume(co, failure)
end
if coroutine.yield() then
error("Module declared but not required: "..name)
end
return userFunc(require)
end
end
module(name, func, debugLineNum)
end
end
if assignLegacyAPI then --This block handles legacy code.
---Allows packaging multiple requirements into one table and queues the initialization for later.
---@deprecated
---@param initList string | table
---@param userFunc function
function OnInit.library(initList, userFunc)
local typeOf = type(initList)
assert(typeOf=='table' or typeOf=='string')
assert(type(userFunc) == 'function')
local function caller(use)
if typeOf=='string' then
use(initList)
else
for _,initName in ipairs(initList) do
use(initName)
end
if initList.optional then
for _,initName in ipairs(initList.optional) do
use.lazily(initName)
end
end
end
end
if initList.name then
OnInit(initList.name, caller)
else
OnInit(caller)
end
end
local legacyTable = {}
assignLegacyAPI(legacyTable, OnInit)
for key,func in pairs(legacyTable) do
rawset(_G, key, func)
end
OnInit.final(function()
for key in pairs(legacyTable) do
rawset(_G, key, nil)
end
end)
end
initEverything()
end
if Debug then Debug.endFile() end
do
--[[
===========================================================================================
Hero Wound Sounds
by Antares
Easily add on-damage "ouch"-sounds to heroes for your rpg or other hero map.
How to import:
Copy this library into your map. Extract the imported sound files into an empty folder, then
import those that you need into your map. Saving your map in folder mode might make the
import process more convenient.
Edit the parameters in the config section to your liking.
To import additional wound sounds from World of Warcraft characters, go to www.wowhead.com, then
go to Database -> Sounds. In the Name field, enter either "Wound" or the name of your race/gender
combination, for example "TaurenFemale." The names of the wound sound files are not entirely
consistent and it might take some experimentation to find the ones you are looking for.
Download the sound files, then you need to convert the .ogg files to .flac or .mp3. You can
do this via online tools or with Audacity (freeware). To do so, select all sound files in your
explorer, then drag them into the Audacity window. On the left, increase the volume of each
file by roughly 3 db. Then go to File -> Export -> Export Multiple and select .mp3 as the
output format.
Rename the files to
YourNameHit1.mp3
YourNameHit2.mp3
...
YourNameCrit.mp3
Import the sound files into the specified subfolder and add a line to the Init function to
tell the library how many normal wound sounds exist. For example, if you import TaurenFemale
and it has 4 wound sounds plus a crit sound, it should be:
numberOfWoundSounds.TaurenFemale = 4
===========================================================================================
API
===========================================================================================
AddWoundSoundsToUnit(whichUnit, whichSoundPath)
RemoveWoundSoundsFromUnit(whichUnit)
PauseWoundSoundsForUnit(whichUnit)
AdjustWoundSoundVolumeForUnit(whichUnit, volumePercent)
===========================================================================================
]]
--=========================================================================================
--Config
--=========================================================================================
local WOUND_SOUND_COOLDOWN = 1.25 --Minimum time between to wound sounds. Crit sounds will play even when normal wound sounds are on cooldown.
local ENABLE_HIT_SOUNDS = true --Disable if you only want wound crit sounds.
local HIT_SOUND_THRESHOLD = 3 --Damage required to trigger a normal wound sound.
local ENABLE_CRIT_SOUNDS = true --Disable if you only want normal wound sounds.
local CRIT_SOUND_THRESHOLD = 10 --Damage required to trigger a wound crit sound.
local THRESHOLD_IN_PERCENT = true --true if thresholds are given in percentage of hero max hp. false if thresholds are given in absolute values.
local TRIGGER_ON_ATTACK_DAMAGE = true --Disable if attacks should not trigger wound sounds.
local TRIGGER_ON_NON_ATTACK_DAMAGE = true --Disable if only attacks should trigger wound sounds.
local PLAY_ONLY_FOR_OWNER = true --Disable if every player should hear the wound sounds, not just the owner.
local PLAY_AS_3D_SOUND = false --Enable if wound sounds should be played as a 3D sound on the hero's location.
local SOUND_3D_MIN_DIST = 600 --Only if PLAY_AS_3D_SOUND is enabled.
local SOUND_3D_MAX_DIST = 4000 --Only if PLAY_AS_3D_SOUND is enabled.
local AUTO_CLEANUP_ON_DEATH = false --Enable if memory leaks should automatically be handled on death of a nonhero unit. Otherwise, leaks must be
--manually removed with RemoveWoundSoundsFromUnit.
local SOUND_FILE_SUBFOLDER = "WoundSounds\\" --The subfolder where the imported wound sounds are stored in.
--=========================================================================================
local numberOfWoundSounds = {}
local woundSound = {}
--=========================================================================================
--Here, the number of wound sounds for each race/gender combination are stored. When you
--import new sound files, add them here.
--=========================================================================================
if ENABLE_HIT_SOUNDS then
numberOfWoundSounds.BloodElfFemale = 4
numberOfWoundSounds.BloodElfFemale = 4
numberOfWoundSounds.BloodElfMale = 4
numberOfWoundSounds.Cat = 3
numberOfWoundSounds.DraeneiMale = 5
numberOfWoundSounds.DwarfFemale = 5
numberOfWoundSounds.DwarfMale = 4
numberOfWoundSounds.GnomeFemale = 3
numberOfWoundSounds.GnomeMale = 4
numberOfWoundSounds.GoblinFemale = 5
numberOfWoundSounds.GoblinMale = 4
numberOfWoundSounds.HumanFemale = 4
numberOfWoundSounds.HumanMale = 3
numberOfWoundSounds.NagaFemale = 4
numberOfWoundSounds.NightElfFemale = 4
numberOfWoundSounds.NightElfMale = 4
numberOfWoundSounds.OrcMale = 5
numberOfWoundSounds.PandarenMale = 4
numberOfWoundSounds.TaurenMale = 3
numberOfWoundSounds.TrollMale = 5
numberOfWoundSounds.UndeadFemale = 3
numberOfWoundSounds.UndeadMale = 3
numberOfWoundSounds.VoidElfFemale = 4
numberOfWoundSounds.VrykulFemale = 5
end
local function OnDeath()
RemoveWoundSoundsFromUnit(GetTriggerUnit())
end
local function PlayWoundSound(soundPath, volumePercent, whichUnit)
local volume = volumePercent
local s = CreateSound(soundPath, false, PLAY_AS_3D_SOUND, PLAY_AS_3D_SOUND, 10, 10, "DefaultEAXON")
if PLAY_ONLY_FOR_OWNER and GetLocalPlayer() ~= GetOwningPlayer(whichUnit) then
volume = 0
end
if PLAY_AS_3D_SOUND then
SetSoundPosition( s, GetUnitX(whichUnit), GetUnitY(whichUnit), 50)
SetSoundDistances( s , SOUND_3D_MIN_DIST , SOUND_3D_MAX_DIST )
end
SetSoundVolumeBJ(s, volume)
StartSound(s)
KillSoundWhenDone(s)
end
local function WoundSoundOnDamage()
local u = BlzGetEventDamageTarget()
local amount = GetEventDamage()
if amount > GetUnitState(u, UNIT_STATE_LIFE) then
return
end
if not TRIGGER_ON_ATTACK_DAMAGE and BlzGetEventIsAttack() then
return
end
if not TRIGGER_ON_NON_ATTACK_DAMAGE and not BlzGetEventIsAttack() then
return
end
local w = woundSound[u]
if w.isPaused then
return
end
if ENABLE_CRIT_SOUNDS and ((amount > CRIT_SOUND_THRESHOLD and not THRESHOLD_IN_PERCENT) or (amount > CRIT_SOUND_THRESHOLD*BlzGetUnitMaxHP(u)/100 and THRESHOLD_IN_PERCENT)) then
if WOUND_SOUND_COOLDOWN == 0 or TimerGetRemaining(w.woundCritTimer) == 0 then
local fullPath = SOUND_FILE_SUBFOLDER .. w.soundPath .. "Crit.mp3"
if WOUND_SOUND_COOLDOWN > 0 then
TimerStart(w.woundTimer, WOUND_SOUND_COOLDOWN, false, nil)
TimerStart(w.woundCritTimer, WOUND_SOUND_COOLDOWN, false, nil)
end
PlayWoundSound(fullPath, w.volumePercent, u)
end
elseif ENABLE_HIT_SOUNDS and (amount > HIT_SOUND_THRESHOLD and not THRESHOLD_IN_PERCENT) or (amount > HIT_SOUND_THRESHOLD*BlzGetUnitMaxHP(u)/100 and THRESHOLD_IN_PERCENT) then
if WOUND_SOUND_COOLDOWN == 0 or TimerGetRemaining(w.woundTimer) == 0 then
w.lastSound = ModuloInteger(w.lastSound + math.random(0,numberOfWoundSounds[w.soundPath] - 2), numberOfWoundSounds[w.soundPath]) + 1
local fullPath = SOUND_FILE_SUBFOLDER .. w.soundPath .. "Hit" .. w.lastSound .. ".mp3"
if WOUND_SOUND_COOLDOWN > 0 then
TimerStart(w.woundTimer, WOUND_SOUND_COOLDOWN, false, nil)
end
PlayWoundSound(fullPath, w.volumePercent, u)
end
end
end
---@param whichUnit unit
---@param whichSoundPath string
function AddWoundSoundsToUnit(whichUnit, whichSoundPath)
woundSound[whichUnit] = {}
woundSound[whichUnit].soundPath = whichSoundPath
woundSound[whichUnit].damageTrigger = CreateTrigger()
if WOUND_SOUND_COOLDOWN > 0 then
if ENABLE_HIT_SOUNDS then
woundSound[whichUnit].woundTimer = CreateTimer()
end
if ENABLE_CRIT_SOUNDS then
woundSound[whichUnit].woundCritTimer = CreateTimer()
end
end
woundSound[whichUnit].isPaused = false
woundSound[whichUnit].lastSound = 0
woundSound[whichUnit].volumePercent = 100
TriggerAddAction(woundSound[whichUnit].damageTrigger, WoundSoundOnDamage)
TriggerRegisterUnitEvent(woundSound[whichUnit].damageTrigger, whichUnit, EVENT_UNIT_DAMAGED)
if AUTO_CLEANUP_ON_DEATH and not IsUnitType(whichUnit, UNIT_TYPE_HERO) then
woundSound[whichUnit].deathTrigger = CreateTrigger()
TriggerAddAction(woundSound[whichUnit].deathTrigger, OnDeath)
TriggerRegisterUnitEvent(woundSound[whichUnit].deathTrigger, whichUnit, EVENT_UNIT_DEATH)
end
end
---@param whichUnit unit
function RemoveWoundSoundsFromUnit(whichUnit)
if WOUND_SOUND_COOLDOWN > 0 then
if ENABLE_HIT_SOUNDS then
DestroyTimer(woundSound[whichUnit].woundTimer)
end
if ENABLE_CRIT_SOUNDS then
DestroyTimer(woundSound[whichUnit].woundCritTimer)
end
end
DestroyTrigger(woundSound[whichUnit].damageTrigger)
if AUTO_CLEANUP_ON_DEATH and not IsUnitType(whichUnit, UNIT_TYPE_HERO) then
DestroyTrigger(woundSound[whichUnit].deathTrigger)
end
woundSound[whichUnit] = nil
end
---@param whichUnit unit
---@param pause boolean
function PauseWoundSoundsForUnit(whichUnit, pause)
woundSound[whichUnit].isPaused = pause
end
---@param whichUnit unit
---@param percentage number
function AdjustWoundSoundVolumeForUnit(whichUnit, percentage)
woundSound[whichUnit].volumePercent = math.min(100,percentage)
end
end
do
local function Init()
local G = CreateGroup()
GroupEnumUnitsOfPlayer(G, Player(0), nil)
while BlzGroupGetSize(G) > 0 do
local u = FirstOfGroup(G)
if GetUnitTypeId(u) == FourCC("Hpal") then
AddWoundSoundsToUnit(u, "HumanMale")
elseif GetUnitTypeId(u) == FourCC("Emoo") then
AddWoundSoundsToUnit(u, "NightElfFemale")
elseif GetUnitTypeId(u) == FourCC("Nngs") then
AddWoundSoundsToUnit(u, "NagaFemale")
elseif GetUnitTypeId(u) == FourCC("Otch") then
AddWoundSoundsToUnit(u, "TaurenMale")
elseif GetUnitTypeId(u) == FourCC("Npbm") then
AddWoundSoundsToUnit(u, "PandarenMale")
end
GroupRemoveUnit(G, u)
end
CreateFogModifierRectBJ( true, Player(0), FOG_OF_WAR_VISIBLE, GetPlayableMapRect() )
end
OnInit.final(Init)
end