Learn sounds menu added. May need more work.
This commit is contained in:
@@ -38,6 +38,7 @@ sound_pool p(300);
|
|||||||
#include "src/notify.nvgt"
|
#include "src/notify.nvgt"
|
||||||
#include "src/speech_history.nvgt"
|
#include "src/speech_history.nvgt"
|
||||||
#include "src/text_reader.nvgt"
|
#include "src/text_reader.nvgt"
|
||||||
|
#include "src/learn_sounds.nvgt"
|
||||||
#include "src/bosses/adventure_system.nvgt"
|
#include "src/bosses/adventure_system.nvgt"
|
||||||
|
|
||||||
int run_main_menu() {
|
int run_main_menu() {
|
||||||
@@ -45,7 +46,8 @@ int run_main_menu() {
|
|||||||
|
|
||||||
int selection = 0;
|
int selection = 0;
|
||||||
string load_label = has_save_game() ? "Load Game" : "Load Game (no saves found)";
|
string load_label = has_save_game() ? "Load Game" : "Load Game (no saves found)";
|
||||||
string[] options = {"New Game", load_label, "Exit"};
|
string[] options = {"New Game", load_label, "Learn Sounds", "Exit"};
|
||||||
|
int exit_index = options.length() - 1;
|
||||||
|
|
||||||
speak_with_history(options[selection], true);
|
speak_with_history(options[selection], true);
|
||||||
|
|
||||||
@@ -72,11 +74,11 @@ int run_main_menu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (key_pressed(KEY_ESCAPE)) {
|
if (key_pressed(KEY_ESCAPE)) {
|
||||||
return 2;
|
return exit_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 2;
|
return exit_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_game()
|
void run_game()
|
||||||
@@ -119,6 +121,9 @@ void run_game()
|
|||||||
if (message == "") message = "Unable to load save.";
|
if (message == "") message = "Unable to load save.";
|
||||||
ui_info_box("Draugnorak", "Load Game", message);
|
ui_info_box("Draugnorak", "Load Game", message);
|
||||||
}
|
}
|
||||||
|
} else if (selection == 2) {
|
||||||
|
run_learn_sounds_menu();
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
sounds/actions/climb_rope.ogg
LFS
BIN
sounds/actions/climb_rope.ogg
LFS
Binary file not shown.
@@ -1111,8 +1111,7 @@ void start_rope_climb(bool climbing_up, int target_x, int target_elevation) {
|
|||||||
string direction = rope_climb_up ? "up" : "down";
|
string direction = rope_climb_up ? "up" : "down";
|
||||||
speak_with_history("Climbing " + direction + ". " + distance + " feet.", true);
|
speak_with_history("Climbing " + direction + ". " + distance + " feet.", true);
|
||||||
|
|
||||||
// Start looping rope climbing sound
|
rope_climb_sound_handle = -1;
|
||||||
rope_climb_sound_handle = p.play_stationary("sounds/actions/climb_rope.ogg", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_rope_climbing() {
|
void update_rope_climbing() {
|
||||||
@@ -1132,6 +1131,7 @@ void update_rope_climbing() {
|
|||||||
// Climbing up
|
// Climbing up
|
||||||
if (y < rope_climb_target_y) {
|
if (y < rope_climb_target_y) {
|
||||||
y++;
|
y++;
|
||||||
|
p.play_stationary("sounds/actions/climb_rope.ogg", false);
|
||||||
|
|
||||||
// Check if we've reached the target
|
// Check if we've reached the target
|
||||||
if (y >= rope_climb_target_y) {
|
if (y >= rope_climb_target_y) {
|
||||||
@@ -1142,6 +1142,7 @@ void update_rope_climbing() {
|
|||||||
// Climbing down
|
// Climbing down
|
||||||
if (y > rope_climb_target_y) {
|
if (y > rope_climb_target_y) {
|
||||||
y--;
|
y--;
|
||||||
|
p.play_stationary("sounds/actions/climb_rope.ogg", false);
|
||||||
|
|
||||||
// Check if we've reached the target
|
// Check if we've reached the target
|
||||||
if (y <= rope_climb_target_y) {
|
if (y <= rope_climb_target_y) {
|
||||||
@@ -1157,11 +1158,7 @@ void complete_rope_climb() {
|
|||||||
x = rope_climb_target_x;
|
x = rope_climb_target_x;
|
||||||
y = rope_climb_target_y;
|
y = rope_climb_target_y;
|
||||||
|
|
||||||
// Stop looping rope climbing sound
|
rope_climb_sound_handle = -1;
|
||||||
if (rope_climb_sound_handle != -1) {
|
|
||||||
p.destroy_sound(rope_climb_sound_handle);
|
|
||||||
rope_climb_sound_handle = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Play footstep for new terrain
|
// Play footstep for new terrain
|
||||||
play_footstep(x, BASE_END, GRASS_END);
|
play_footstep(x, BASE_END, GRASS_END);
|
||||||
@@ -1173,11 +1170,7 @@ void check_rope_climb_fall() {
|
|||||||
if (!rope_climbing) return;
|
if (!rope_climbing) return;
|
||||||
|
|
||||||
if (key_down(KEY_LEFT) || key_down(KEY_RIGHT)) {
|
if (key_down(KEY_LEFT) || key_down(KEY_RIGHT)) {
|
||||||
// Stop rope climbing sound
|
rope_climb_sound_handle = -1;
|
||||||
if (rope_climb_sound_handle != -1) {
|
|
||||||
p.destroy_sound(rope_climb_sound_handle);
|
|
||||||
rope_climb_sound_handle = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentElevation = get_mountain_elevation_at(x);
|
int currentElevation = get_mountain_elevation_at(x);
|
||||||
int targetElevation = get_mountain_elevation_at(rope_climb_target_x);
|
int targetElevation = get_mountain_elevation_at(rope_climb_target_x);
|
||||||
|
|||||||
258
src/learn_sounds.nvgt
Normal file
258
src/learn_sounds.nvgt
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
// Learn sounds menu
|
||||||
|
|
||||||
|
// Skip entries can be full file paths or directories (ending with "/").
|
||||||
|
string[] learnSoundSkipList = {
|
||||||
|
"sounds/quests/bone1.ogg",
|
||||||
|
"sounds/quests/bone2.ogg",
|
||||||
|
"sounds/quests/bone3.ogg",
|
||||||
|
"sounds/quests/bone4.ogg",
|
||||||
|
"sounds/quests/bone5.ogg",
|
||||||
|
"sounds/quests/bone6.ogg",
|
||||||
|
"sounds/quests/bone7.ogg",
|
||||||
|
"sounds/quests/bone8.ogg",
|
||||||
|
"sounds/actions/fishpole.ogg",
|
||||||
|
"sounds/actions/hit_ground.ogg",
|
||||||
|
"sounds/nature/"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Description entries: keep paths/texts aligned by index.
|
||||||
|
string[] learnSoundDescriptionPaths = {
|
||||||
|
"sounds/actions/bad_cast.ogg",
|
||||||
|
"sounds/actions/cast_strength.ogg",
|
||||||
|
"sounds/enemies/enter_range.ogg",
|
||||||
|
"sounds/enemies/exit_range.ogg",
|
||||||
|
"sounds/actions/falling.ogg",
|
||||||
|
"sounds/enemies/invasion.ogg",
|
||||||
|
"sounds/items/miscellaneous.ogg"
|
||||||
|
};
|
||||||
|
|
||||||
|
string[] learnSoundDescriptionTexts = {
|
||||||
|
"Your cast missed the water and landed in nearby foliage where it is unlikely to attract fish.",
|
||||||
|
"When casting release control when over water. When catching release when sound is over player.",
|
||||||
|
"An enemy is in range of your currently wielded weapon.",
|
||||||
|
"An enemy is no longer in range of your currently wielded weapon.",
|
||||||
|
"Lowers in pitch as the fall progresses.",
|
||||||
|
"The war drums pound! Prepare for combat!",
|
||||||
|
"You picked up an item for which there is no specific sound."
|
||||||
|
};
|
||||||
|
|
||||||
|
int learnSoundHandle = -1;
|
||||||
|
|
||||||
|
string normalize_path(const string&in path) {
|
||||||
|
return path.replace("\\", "/", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_directory_skip_entry(const string&in entry) {
|
||||||
|
if (entry.length() == 0) return false;
|
||||||
|
if (entry.substr(entry.length() - 1) == "/") return true;
|
||||||
|
return directory_exists(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool should_skip_sound_path(const string&in path) {
|
||||||
|
string normalizedPath = normalize_path(path);
|
||||||
|
for (uint i = 0; i < learnSoundSkipList.length(); i++) {
|
||||||
|
string entry = normalize_path(learnSoundSkipList[i]);
|
||||||
|
if (entry.length() == 0) continue;
|
||||||
|
|
||||||
|
bool isDir = is_directory_skip_entry(entry);
|
||||||
|
if (isDir) {
|
||||||
|
if (entry.substr(entry.length() - 1) != "/") entry += "/";
|
||||||
|
if (normalizedPath.length() >= entry.length() &&
|
||||||
|
normalizedPath.substr(0, entry.length()) == entry) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalizedPath == entry) return true;
|
||||||
|
|
||||||
|
if (entry.find_first("/") < 0 && entry.find_first("\\") < 0) {
|
||||||
|
if (normalizedPath.length() >= entry.length() + 1 &&
|
||||||
|
normalizedPath.substr(normalizedPath.length() - entry.length()) == entry) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string get_sound_description(const string&in path) {
|
||||||
|
string normalizedPath = normalize_path(path);
|
||||||
|
uint count = learnSoundDescriptionPaths.length();
|
||||||
|
if (learnSoundDescriptionTexts.length() < count) count = learnSoundDescriptionTexts.length();
|
||||||
|
for (uint i = 0; i < count; i++) {
|
||||||
|
if (normalize_path(learnSoundDescriptionPaths[i]) == normalizedPath) {
|
||||||
|
return learnSoundDescriptionTexts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void gather_sound_files(const string&in basePath, string[]@ outFiles) {
|
||||||
|
string[]@ files = find_files(basePath + "/*.ogg");
|
||||||
|
if (@files !is null) {
|
||||||
|
for (uint i = 0; i < files.length(); i++) {
|
||||||
|
outFiles.insert_last(basePath + "/" + files[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string[]@ folders = find_directories(basePath + "/*");
|
||||||
|
if (@folders !is null) {
|
||||||
|
for (uint i = 0; i < folders.length(); i++) {
|
||||||
|
gather_sound_files(basePath + "/" + folders[i], outFiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sort_string_case_insensitive_sounds(const string &in a, const string &in b) {
|
||||||
|
return a.lower() < b.lower();
|
||||||
|
}
|
||||||
|
|
||||||
|
string collapse_spaces(const string&in text) {
|
||||||
|
string result = text;
|
||||||
|
while (result.find_first(" ") > -1) {
|
||||||
|
result = result.replace(" ", " ", true);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string format_doc_label(const string&in filename) {
|
||||||
|
string name = filename;
|
||||||
|
string lowerName = name.lower();
|
||||||
|
if (lowerName.length() > 3 && lowerName.substr(lowerName.length() - 3) == ".md") {
|
||||||
|
name = name.substr(0, name.length() - 3);
|
||||||
|
}
|
||||||
|
name = name.replace("_", " ", true);
|
||||||
|
name = name.replace("-", " ", true);
|
||||||
|
name = collapse_spaces(name);
|
||||||
|
name = name.lower();
|
||||||
|
name.trim_whitespace_this();
|
||||||
|
if (name.length() == 0) return "Document";
|
||||||
|
string first = name.substr(0, 1).upper();
|
||||||
|
if (name.length() == 1) return first;
|
||||||
|
return first + name.substr(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
string get_sound_label_from_path(const string&in soundPath) {
|
||||||
|
string normalizedPath = normalize_path(soundPath);
|
||||||
|
int slashPos = normalizedPath.find_last_of("/");
|
||||||
|
string name = (slashPos >= 0) ? normalizedPath.substr(slashPos + 1) : normalizedPath;
|
||||||
|
string lowerName = name.lower();
|
||||||
|
if (lowerName.length() > 4 && lowerName.substr(lowerName.length() - 4) == ".ogg") {
|
||||||
|
name = name.substr(0, name.length() - 4);
|
||||||
|
}
|
||||||
|
name = name.replace("_", " ", true);
|
||||||
|
name = name.replace("-", " ", true);
|
||||||
|
name = collapse_spaces(name);
|
||||||
|
name = name.lower();
|
||||||
|
name.trim_whitespace_this();
|
||||||
|
if (name.length() == 0) return "Sound";
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_doc_entries(string[]@ labels, string[]@ paths, int[]@ types) {
|
||||||
|
if (!directory_exists("files")) return;
|
||||||
|
|
||||||
|
string[] docFiles;
|
||||||
|
string[]@ mdFiles = find_files("files/*.md");
|
||||||
|
if (@mdFiles !is null) {
|
||||||
|
for (uint i = 0; i < mdFiles.length(); i++) {
|
||||||
|
docFiles.insert_last(mdFiles[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string[]@ mdCapsFiles = find_files("files/*.MD");
|
||||||
|
if (@mdCapsFiles !is null) {
|
||||||
|
for (uint i = 0; i < mdCapsFiles.length(); i++) {
|
||||||
|
docFiles.insert_last(mdCapsFiles[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (docFiles.length() > 1) {
|
||||||
|
docFiles.sort(sort_string_case_insensitive_sounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i < docFiles.length(); i++) {
|
||||||
|
string label = format_doc_label(docFiles[i]);
|
||||||
|
labels.insert_last(label);
|
||||||
|
paths.insert_last("files/" + docFiles[i]);
|
||||||
|
types.insert_last(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_sound_entries(string[]@ labels, string[]@ paths, int[]@ types) {
|
||||||
|
string[] soundFiles;
|
||||||
|
gather_sound_files("sounds", soundFiles);
|
||||||
|
if (soundFiles.length() > 1) {
|
||||||
|
soundFiles.sort(sort_string_case_insensitive_sounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i < soundFiles.length(); i++) {
|
||||||
|
string soundPath = normalize_path(soundFiles[i]);
|
||||||
|
if (should_skip_sound_path(soundPath)) continue;
|
||||||
|
|
||||||
|
string label = get_sound_label_from_path(soundPath);
|
||||||
|
string description = get_sound_description(soundPath);
|
||||||
|
if (description.length() > 0) {
|
||||||
|
label += " - " + description;
|
||||||
|
}
|
||||||
|
labels.insert_last(label);
|
||||||
|
paths.insert_last(soundPath);
|
||||||
|
types.insert_last(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_learn_sounds_menu() {
|
||||||
|
speak_with_history("Learn sounds.", true);
|
||||||
|
|
||||||
|
string[] labels;
|
||||||
|
string[] entryPaths;
|
||||||
|
int[] entryTypes; // 0 = sound, 1 = document
|
||||||
|
|
||||||
|
add_doc_entries(labels, entryPaths, entryTypes);
|
||||||
|
add_sound_entries(labels, entryPaths, entryTypes);
|
||||||
|
|
||||||
|
if (labels.length() == 0) {
|
||||||
|
speak_with_history("No sounds available.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int selection = 0;
|
||||||
|
speak_with_history(labels[selection], true);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
wait(5);
|
||||||
|
|
||||||
|
if (key_pressed(KEY_ESCAPE)) {
|
||||||
|
speak_with_history("Closed.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_pressed(KEY_DOWN)) {
|
||||||
|
play_menu_move_sound();
|
||||||
|
selection++;
|
||||||
|
if (selection >= int(labels.length())) selection = 0;
|
||||||
|
speak_with_history(labels[selection], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_pressed(KEY_UP)) {
|
||||||
|
play_menu_move_sound();
|
||||||
|
selection--;
|
||||||
|
if (selection < 0) selection = int(labels.length()) - 1;
|
||||||
|
speak_with_history(labels[selection], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_pressed(KEY_RETURN)) {
|
||||||
|
if (entryTypes[selection] == 1) {
|
||||||
|
text_reader_file(entryPaths[selection], labels[selection], true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string soundPath = entryPaths[selection];
|
||||||
|
if (file_exists(soundPath)) {
|
||||||
|
safe_destroy_sound(learnSoundHandle);
|
||||||
|
learnSoundHandle = p.play_stationary(soundPath, false);
|
||||||
|
} else {
|
||||||
|
speak_with_history("Sound not found.", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user