So after discussion with IssMneur I went and implemented a parse_sound_list function and made a useful change to parse_sound as well as some other stuff, but it turns out after all of that Misc Anim Sounds entries aren't really sound lists because of that first number which specified how many sounds follow. There are two options for this that I can see:
1. Change the syntax for mainhall.tbl. I would see this as unacceptable, given the amount of stuff we'd be breaking and the possibly massive rewrites necessary, but it's there.
2. Write a function specifically for parsing Misc Anim Sounds entries. The thing is that neither parse_sound nor parse_sound_list work for Misc Anim Sounds because of the syntax, so I may be forced to write a function just for them. I have no problem doing this, I just wanted to get more experienced input before doing so.
If there are any viable options I've missed then I'm all ears.
On the bright side however is this: the Intercom Sounds flag can be successfully expanded using parse_sound, and the Door Sounds flag can be successfully expanded using parse_sound_list.
That said, here is the patch with the new/updated sound functions!
Index: code/gamesnd/gamesnd.cpp
===================================================================
--- code/gamesnd/gamesnd.cpp (revision 8067)
+++ code/gamesnd/gamesnd.cpp (working copy)
@@ -52,6 +52,30 @@
return -1;
}
+int gamesnd_get_by_iface_name(char* name)
+{
+ Assert( Snds_iface.size() <= INT_MAX );
+ Assert( Snds_iface.size() == Snds_iface_handle.size() );
+ int i = 0;
+ for(SCP_vector<game_snd>::iterator snd = Snds_iface.begin(); snd != Snds_iface.end(); ++snd)
+ {
+ char *p = strrchr( snd->filename, '.' );
+ if(p == NULL)
+ {
+ if(!stricmp(snd->filename, name))
+ {
+ return i;
+ }
+ }
+ else if(!strnicmp(snd->filename, name, p-snd->filename))
+ {
+ return i;
+ }
+ i++;
+ }
+ return -1;
+}
+
int gamesnd_get_by_tbl_index(int index)
{
//if we get passed -1, don't bother trying to look it up.
@@ -85,40 +109,111 @@
}
/**
- * Parse a sound
- *
+ * Helper function for parse_sound and parse_sound_list. Do not use directly.
+ *
* @param tag Tag
* @param idx_dest Sound index destination
* @param object_name Object name being parsed
+ * @param is_interface_sound Whether the sound is an interface sound or not (defaults to false)
+ * @param buf Buffer holding string to be parsed
*
- * This also means you shouldn't use optional_string or required_string,
- * just make sure the destination sound index can handle -1 if things
- * don't work out.
*/
-void parse_sound(char* tag, int *idx_dest, char* object_name)
+void parse_sound_core(char* tag, int *idx_dest, char* object_name, bool is_interface_sound, char* buf)
{
- char buf[MAX_FILENAME_LEN];
int idx;
- if(optional_string(tag))
+ if(is_interface_sound)
+ idx = gamesnd_get_by_iface_name(buf);
+ else
+ idx = gamesnd_get_by_name(buf);
+
+ if(idx != -1)
{
- stuff_string(buf, F_NAME, MAX_FILENAME_LEN);
- idx = gamesnd_get_by_name(buf);
- if(idx != -1)
- (*idx_dest) = idx;
+ (*idx_dest) = idx;
+ }
+ else
+ {
+ if(is_interface_sound)
+ idx = gamesnd_get_by_iface_tbl_index(atoi(buf));
else
- {
idx = gamesnd_get_by_tbl_index(atoi(buf));
- if (idx != -1)
- (*idx_dest) = idx;
- }
- Assert( Snds.size() <= INT_MAX );
- //Ensure sound is in range
- if((*idx_dest) < -1 || (*idx_dest) >= (int)Snds.size())
+ if (idx != -1)
+ (*idx_dest) = idx;
+ }
+
+ int size_to_check = 0;
+
+ if(is_interface_sound)
+ {
+ size_to_check = Snds_iface.size();
+ Assert( Snds_iface.size() == Snds_iface_handle.size() );
+ }
+ else
+ {
+ size_to_check = Snds.size();
+ }
+
+ Assert( size_to_check <= INT_MAX );
+
+ //Ensure sound is in range
+ if((*idx_dest) < -1 || (*idx_dest) >= (int)size_to_check)
+ {
+ (*idx_dest) = -1;
+ Warning(LOCATION, "%s sound index out of range on '%s'. Must be between 0 and %d. Forcing to -1 (Nonexistant sound).\n", tag, object_name, size_to_check);
+ }
+}
+
+/**
+ * Parse a sound. When using this function for a table entry,
+ * required_string and optional_string aren't needed, as this function deals with
+ * that as its tag parameter, just make sure that the destination sound index can
+ * handle -1 if things don't work out.
+ *
+ * @param tag Tag
+ * @param idx_dest Sound index destination
+ * @param object_name Object name being parsed
+ * @param is_interface_sound Whether the sound is an interface sound or not (defaults to false)
+ *
+ */
+void parse_sound(char* tag, int *idx_dest, char* object_name, bool is_interface_sound)
+{
+ if(optional_string(tag))
+ {
+ char buf[MAX_FILENAME_LEN];
+ stuff_string(buf, F_NAME, MAX_FILENAME_LEN);
+
+ parse_sound_core(tag, idx_dest, object_name, is_interface_sound, buf);
+ }
+}
+
+/**
+ * CommanderDJ - Parse a list of sounds. When using this function for a table entry,
+ * required_string and optional_string aren't needed, as this function deals with
+ * that as its tag parameter, just make sure that the destination sound index(es) can
+ * handle -1 if things don't work out.
+ *
+ * @param tag Tag
+ * @param idx_dest Destination of first sound index in list
+ * @param object_name Object name being parsed
+ * @param num Number of sounds to parse (defaults to 1)
+ * @param offset Element to start filling at (defaults to 0)
+ * @param is_interface_sound Whether the sound is an interface sound or not (defaults to false)
+ *
+ */
+void parse_sound_list(char* tag, int* idx_dest, char* object_name, int num, int offset, bool is_interface_sound)
+{
+ if(optional_string(tag))
+ {
+ //sanity checks
+ Assert(num>0);
+ Assert(offset>=0);
+
+ for(int i=0; i<num; i++)
{
- (*idx_dest) = -1;
- Warning(LOCATION, "%s sound index out of range on '%s'. Must be between 0 and %d. Forcing to -1 (Nonexistant sound).\n", tag, object_name, Snds.size());
+ char buf[MAX_FILENAME_LEN];
+ stuff_string_white(buf, MAX_FILENAME_LEN);
+ parse_sound_core(tag, &idx_dest[i+offset], object_name, is_interface_sound, buf);
}
}
}
Index: code/gamesnd/gamesnd.h
===================================================================
--- code/gamesnd/gamesnd.h (revision 8067)
+++ code/gamesnd/gamesnd.h (working copy)
@@ -28,13 +28,16 @@
void gamesnd_play_iface(int n);
void gamesnd_play_error_beep();
int gamesnd_get_by_name(char* name);
+int gamesnd_get_by_iface_name(char* name);
int gamesnd_get_by_tbl_index(int index);
int gamesnd_get_by_iface_tbl_index(int index);
//This should handle NO_SOUND just fine since it doesn't directly access lowlevel code
//Does all parsing for a sound
-void parse_sound(char* tag, int *idx_dest, char* object_name);
+void parse_sound(char* tag, int* idx_dest, char* object_name, bool is_interface_sound = false);
+void parse_sound_list(char* tag, int* idx_dest, char* object_name, int num = 1, int offset = 0, bool is_interface_sound = false);
+
// this is a callback, so it needs to be a real function
void common_play_highlight_sound();
I have tested all of these and they work as intended without breaking existing behaviour, AFAICT. You'll notice I have extended parse_sound a little bit and extracted the functionality it shares with parse_sound_list and put it into a helper function.
And here is the patch for the extension of Intercom Sounds and Door Sounds
Index: code/menuui/mainhallmenu.cpp
===================================================================
--- code/menuui/mainhallmenu.cpp (revision 8067)
+++ code/menuui/mainhallmenu.cpp (working copy)
@@ -1660,8 +1660,7 @@
}
for(idx=0; idx<m->num_random_intercom_sounds; idx++){
// intercom sound id
- required_string("+Intercom sound:");
- stuff_int(&m->intercom_sounds[idx]);
+ parse_sound("+Intercom sound:", &m->intercom_sounds[idx], "+Intercom sound:", true);
}
for(idx=0; idx<m->num_random_intercom_sounds; idx++){
// intercom pan
@@ -1761,9 +1760,7 @@
}
for(idx=0; idx<m->num_door_animations; idx++){
// door open and close sounds
- required_string("+Door sounds:");
- stuff_int(&m->door_sounds[idx][0]);
- stuff_int(&m->door_sounds[idx][1]);
+ parse_sound_list("+Door sounds:", &m->door_sounds[idx][0], "+Door sounds:", 2, 0, true);
}
for(idx=0; idx<m->num_door_animations; idx++){
// door pan value
You'll notice I've just used the tag for the name parameter for now. Once mainhalls have names they will be used instead.
Feedback/review welcome/needed!