-
Notifications
You must be signed in to change notification settings - Fork 0
/
sound.lua
182 lines (149 loc) · 5.97 KB
/
sound.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
--How many snores the sleep-talk has, or rather, how long the sleep-talk lasts
--If you omit the sleep-talk you can ignore this
local SLEEP_TALK_SNORES = 8
--Define what triggers the custom voice
local function use_custom_voice(m)
return current_sonic_char(m) == 1 or current_sonic_char(m) == 2 --Put your condition here!
end
if _G.charSelectExists then return end
--Define the table of samples that will be used for each player
--Global so if multiple mods use this they won't create unneeded samples
--DON'T MODIFY THIS SINCE IT'S GLOBAL FOR USE BY OTHER MODS!
gCustomVoiceSamples = {}
gCustomVoiceStream = nil
--Get the player's sample, stop whatever sound
--it's playing if it doesn't match the provided sound
--DON'T MODIFY THIS SINCE IT'S GLOBAL FOR USE BY OTHER MODS!
--- @param m MarioState
function stop_custom_character_sound(m, sound)
local voice_sample = gCustomVoiceSamples[m.playerIndex]
if voice_sample == nil or not voice_sample.loaded then
return
end
audio_sample_stop(voice_sample)
if voice_sample.file.relativePath:match('^.+/(.+)$') == sound then
return voice_sample
end
-- audio_sample_destroy(voice_sample)
end
--Play a custom character's sound
--DON'T MODIFY THIS SINCE IT'S GLOBAL FOR USE BY OTHER MODS!
--- @param m MarioState
function play_custom_character_sound(m, voice)
--Get sound, if it's a table, get a random entry from it
local sound
if type(voice) == "table" then
sound = voice[math.random(#voice)]
else
sound = voice
end
if sound == nil then return 0 end
--Get current sample and stop it
local voice_sample = stop_custom_character_sound(m, sound)
--If the new sound isn't a string, let's assume it's
--a number to return to the character sound hook
if type(sound) ~= "string" then
return sound
end
--Load a new sample and play it! Don't make a new one if we don't need to
if (m.area == nil or m.area.camera == nil) and m.playerIndex == 0 then
if gCustomVoiceStream ~= nil then
audio_stream_stop(gCustomVoiceStream)
audio_stream_destroy(gCustomVoiceStream)
end
gCustomVoiceStream = audio_stream_load(sound)
audio_stream_play(gCustomVoiceStream, true, 1)
else
if voice_sample == nil then
voice_sample = audio_sample_load(sound)
end
audio_sample_play(voice_sample, m.pos, 1)
gCustomVoiceSamples[m.playerIndex] = voice_sample
end
return 0
end
--Main character sound hook
--This hook is freely modifiable in case you want to make any specific exceptions
--- @param m MarioState
local function custom_character_sound(m, characterSound)
if not use_custom_voice(m) then return end
if characterSound == CHAR_SOUND_SNORING3 then return 0 end
if characterSound == CHAR_SOUND_HAHA and m.hurtCounter > 0 then return 0 end
local voice = SONIC_VOICETABLE[characterSound]
if current_sonic_char(m) == 1 then
voice = SONIC_VOICETABLE[characterSound]
elseif current_sonic_char(m) == 2 then
voice = AMY_VOICETABLE[characterSound]
end
if voice ~= nil then
return play_custom_character_sound(m, voice)
end
return 0
end
hook_event(HOOK_CHARACTER_SOUND, custom_character_sound)
--Snoring logic for CHAR_SOUND_SNORING3 since we have to loop it manually
--This code won't activate on the Japanese version, due to MARIO_MARIO_SOUND_PLAYED not being set
local SNORE3_TABLE = nil
local STARTING_SNORE = 46
local SLEEP_TALK_START = STARTING_SNORE + 49
local SLEEP_TALK_END = SLEEP_TALK_START + SLEEP_TALK_SNORES
--Main hook for snoring
--- @param m MarioState
local function custom_character_snore(m)
if not use_custom_voice(m) then return end
if current_sonic_char(m) == 1 then
SNORE3_TABLE = SONIC_VOICETABLE[CHAR_SOUND_SNORING3]
elseif current_sonic_char(m) == 2 then
SNORE3_TABLE = AMY_VOICETABLE[CHAR_SOUND_SNORING3]
end
--Stop the snoring!
if m.action ~= ACT_SLEEPING then
if m.isSnoring > 0 then
stop_custom_character_sound(m)
end
return
--You're not in deep snoring
elseif not (m.actionState == 2 and (m.flags & MARIO_MARIO_SOUND_PLAYED) ~= 0) then
return
end
local animFrame = m.marioObj.header.gfx.animInfo.animFrame
--Behavior for CHAR_SOUND_SNORING3
if SNORE3_TABLE ~= nil and #SNORE3_TABLE >= 2 then
--Exhale sound
if animFrame == 2 and m.actionTimer < SLEEP_TALK_START then
play_custom_character_sound(m, SNORE3_TABLE[2])
--Inhale sound
elseif animFrame == 25 then
--Count up snores
if #SNORE3_TABLE >= 3 then
m.actionTimer = m.actionTimer + 1
--End sleep-talk
if m.actionTimer >= SLEEP_TALK_END then
m.actionTimer = STARTING_SNORE
end
--Enough snores? Start sleep-talk
if m.actionTimer == SLEEP_TALK_START then
play_custom_character_sound(m, SNORE3_TABLE[3])
--Regular snoring
elseif m.actionTimer < SLEEP_TALK_START then
play_custom_character_sound(m, SNORE3_TABLE[1])
end
--Definitely regular snoring
else
play_custom_character_sound(m, SNORE3_TABLE[1])
end
end
--No CHAR_SOUND_SNORING3, just use regular snoring
elseif animFrame == 2 then
play_character_sound(m, CHAR_SOUND_SNORING2)
elseif animFrame == 25 then
play_character_sound(m, CHAR_SOUND_SNORING1)
end
end
-- Stop character sounds on warp.
function on_sync_valid()
local m = gMarioStates[0]
stop_custom_character_sound(m)
end
hook_event(HOOK_MARIO_UPDATE, custom_character_snore)
hook_event(HOOK_ON_SYNC_VALID, on_sync_valid)