sounds.lua

main 251 lines · 7 KB Raw
Alex Alex Commit Client Upload Part 2 19/10/2026 00:06
1local CODE = 108
2
3-- Configura��o
4local SOUNDS_CONFIG = {
5 areaSoundFolder = 'sounds/', -- Pasta onde ficam as m�sicas de �rea
6 effectSoundFolder= 'sounds/', -- Pasta onde ficam efeitos sonoros
7 checkInterval = 500, -- Intervalo (ms) para verificar se o player est� numa �rea
8 noSound = 'No sound file for this area.' -- Texto exibido na interface quando n�o h� som
9}
10
11-- �reas que t�m m�sica de fundo
12local AREAS = {
13 {
14 fromPos = {x = 3967, y = 936, z = 8},
15 toPos = {x = 4038, y = 1000, z = 8},
16 sound = "cave.ogg"
17 },
18 {
19 fromPos = {x = 3921, y = 904, z = 7},
20 toPos = {x = 4086, y = 1006, z = 7},
21 sound = "gaivotas.ogg"
22 }
23}
24
25-- Vari�veis globais
26local areaChannel -- Canal para m�sica de �rea (background)
27local effectChannel -- Canal para efeitos sonoros pontuais
28local playingAreaSound = nil -- Qual m�sica de �rea est� tocando agora
29local toggleSoundEvent = nil -- Evento agendado para checar posi��o periodicamente
30
31--[[
32 FUN��O PRINCIPAL DE INICIALIZA��O
33 Chamada quando o script do OTClient � carregado.
34--]]
35function init()
36 -- Conecta eventos do jogo
37 connect(g_game, { onGameStart = onGameStart, onGameEnd = onGameEnd })
38
39 -- Registra opcode para sons de efeito vindos do servidor
40 ProtocolGame.registerExtendedOpcode(CODE, onExtendedOpcode)
41
42 -- Cria canais de som
43 areaChannel = g_sounds.getChannel(SoundChannels.Music) -- Canal de m�sica de fundo
44 effectChannel = g_sounds.getChannel(SoundChannels.Effects) -- Canal de efeitos
45
46 -- Bot�o na interface
47 soundButton = modules.client_topmenu.addRightGameToggleButton(
48 'soundButton', 'Som', '/images/audio', toggleSoundWindow
49 )
50 soundButton:setOn(true)
51
52 -- Carrega a janela "rcsound.otui"
53 soundWindow = g_ui.loadUI('rcsound', modules.game_interface.getRightPanel())
54 soundWindow:disableResize()
55 soundWindow:setup()
56
57 if g_game.isOnline() then
58 onGameStart()
59 end
60end
61
62--[[
63 FUN��O DE FINALIZA��O
64 Chamada quando o script � descarregado do OTClient.
65--]]
66function terminate()
67 disconnect(g_game, { onGameStart = onGameStart, onGameEnd = onGameEnd })
68 ProtocolGame.unregisterExtendedOpcode(CODE)
69 onGameEnd()
70
71 soundWindow:destroy()
72 soundButton:destroy()
73end
74
75--[[
76 Chamado quando o jogo fica online (player loga)
77--]]
78function onGameStart()
79 stopAreaSound()
80 toggleSoundEvent = addEvent(checkAreaSound, SOUNDS_CONFIG.checkInterval)
81end
82
83--[[
84 Chamado quando o jogo fica offline (player desloga)
85--]]
86function onGameEnd()
87 stopAreaSound()
88 if toggleSoundEvent then
89 removeEvent(toggleSoundEvent)
90 toggleSoundEvent = nil
91 end
92end
93
94--[[
95 Abrir/fechar janela de som
96--]]
97function toggleSoundWindow()
98 if soundButton:isOn() then
99 soundWindow:close()
100 soundButton:setOn(false)
101 else
102 soundWindow:open()
103 soundButton:setOn(true)
104 end
105end
106
107function onMiniWindowClose()
108 if soundButton then
109 soundButton:setOn(false)
110 end
111end
112
113--[[
114 Checa se a posi��o "pos" est� dentro do ret�ngulo 3D [fromPos -> toPos]
115--]]
116function isInPos(pos, fromPos, toPos)
117 return (pos.x >= fromPos.x and pos.y >= fromPos.y and pos.z >= fromPos.z)
118 and (pos.x <= toPos.x and pos.y <= toPos.y and pos.z <= toPos.z)
119end
120
121--[[
122 Fun��o principal que verifica a �rea do player a cada "checkInterval"
123 e decide se deve tocar/parar a m�sica de �rea.
124--]]
125function checkAreaSound()
126 local player = g_game.getLocalPlayer()
127 if not player then return end
128
129 local pos = player:getPosition()
130 local areaSoundData = nil
131
132 for _, area in ipairs(AREAS) do
133 if isInPos(pos, area.fromPos, area.toPos) then
134 areaSoundData = area
135 break
136 end
137 end
138
139 if areaSoundData then
140 -- Se � outra m�sica, troca
141 if playingAreaSound ~= areaSoundData.sound then
142 stopAreaSound()
143 local fullPath = SOUNDS_CONFIG.areaSoundFolder .. areaSoundData.sound
144 if g_resources.fileExists(fullPath) then
145 g_logger.info("Tocando m�sica de �rea: " .. fullPath)
146 playAreaSound(fullPath)
147 playingAreaSound = areaSoundData.sound
148 else
149 g_logger.warning("Arquivo de m�sica n�o encontrado: " .. fullPath)
150 end
151 end
152 else
153 -- Se n�o est� em �rea, parar se estava tocando algo
154 if playingAreaSound then
155 g_logger.info("Parando m�sica de �rea.")
156 stopAreaSound()
157 end
158 end
159
160 toggleSoundEvent = scheduleEvent(checkAreaSound, SOUNDS_CONFIG.checkInterval)
161end
162
163--[[
164 Toca a m�sica de �rea no canal "areaChannel"
165 Ajuste o volume inicial se quiser mais alto/baixo (0.1 = 10%, 0.4 = 40% etc.).
166--]]
167function playAreaSound(soundPath)
168 if not areaChannel then
169 print("Canal de �rea n�o dispon�vel!")
170 return
171 end
172 areaChannel:play(soundPath, 0, 0.1)
173 areaChannel:setGain(0.1)
174
175 setLabel(soundPath)
176end
177
178--[[
179 Para a m�sica de �rea
180--]]
181function stopAreaSound()
182 if areaChannel then
183 areaChannel:stop()
184 end
185 playingAreaSound = nil
186 setLabel(SOUNDS_CONFIG.noSound)
187end
188
189--[[
190 Recebe opcode do servidor com algum som extra (efeito) para tocar
191--]]
192function onExtendedOpcode(protocol, code, buffer)
193 if code ~= CODE then return end
194
195 local ok, data = pcall(function() return json.decode(buffer) end)
196 if not ok then
197 print("Erro ao decodificar JSON: " .. data)
198 return
199 end
200
201 local soundFile = data.data
202 local fullPath = SOUNDS_CONFIG.effectSoundFolder .. soundFile
203 if g_resources.fileExists(fullPath) then
204 playEffectSound(fullPath)
205 else
206 print("Som n�o encontrado: " .. fullPath)
207 end
208end
209
210--[[
211 Toca um efeito sonoro e reduz momentaneamente o volume da m�sica de �rea
212 para destacar o efeito.
213--]]
214function playEffectSound(soundPath)
215 if not effectChannel then
216 print("Canal de efeito n�o dispon�vel!")
217 return
218 end
219
220 -- Se a m�sica de �rea est� tocando, diminui volume
221 if playingAreaSound and areaChannel then
222 areaChannel:setGain(0.1) -- Ajuste esse valor se quiser mais baixo durante o efeito
223 end
224
225 effectChannel:play(soundPath, 0, 1.0)
226 effectChannel:setGain(1.0)
227
228 -- Precisamos descobrir a dura��o do efeito para restaurar o volume depois
229 local duration = getSoundDuration(soundPath) or 3000
230 scheduleEvent(function()
231 -- Restaura volume da m�sica de �rea
232 if playingAreaSound and areaChannel then
233 areaChannel:setGain(0.1) -- volta ao volume anterior
234 end
235 end, duration)
236end
237
238--[[
239 Se n�o tem leitura de metadados, definimos 3 segundos como padr�o
240--]]
241function getSoundDuration(soundPath)
242 return 3000
243end
244
245--[[
246 Atualiza o texto na janela "rcsound" com o nome do som atual
247--]]
248function setLabel(str)
249 soundWindow:recursiveGetChildById('currentSound'):getChildById('value'):setText(str)
250end
251
Top