Files
draugnorak/src/quest_system.nvgt

223 lines
7.5 KiB
Plaintext

// Quest system
#include "src/quests/bat_invasion_game.nvgt"
#include "src/quests/catch_the_boomerang_game.nvgt"
#include "src/quests/enchanted_melody_game.nvgt"
#include "src/quests/escape_from_hel_game.nvgt"
#include "src/quests/skeletal_bard_game.nvgt"
const int QUEST_BAT_INVASION = 0;
const int QUEST_CATCH_BOOMERANG = 1;
const int QUEST_ENCHANTED_MELODY = 2;
const int QUEST_ESCAPE_FROM_HEL = 3;
const int QUEST_SKELETAL_BARD = 4;
const int QUEST_TYPE_COUNT = 5;
int[] quest_queue;
bool quest_roll_done_today = false;
string get_quest_name(int quest_type) {
if (quest_type == QUEST_BAT_INVASION) return "Bat Invasion";
if (quest_type == QUEST_CATCH_BOOMERANG) return "Catch the Boomerang";
if (quest_type == QUEST_ENCHANTED_MELODY) return "Enchanted Melody";
if (quest_type == QUEST_ESCAPE_FROM_HEL) return "Escape from Hel";
if (quest_type == QUEST_SKELETAL_BARD) return "Skeletal Bard";
return "Unknown Quest";
}
string get_quest_description(int quest_type) {
if (quest_type == QUEST_BAT_INVASION) {
return "Bat Invasion. Giant killer bats are attacking. Press space to throw when the bat is centered.";
}
if (quest_type == QUEST_CATCH_BOOMERANG) {
return "Catch the Boomerang. Throw and catch the boomerang as it returns for up to 4 points.";
}
if (quest_type == QUEST_ENCHANTED_MELODY) {
return "Enchanted Melody. Repeat the pattern using E R D F or U I J K. Lowest to highest pitch.";
}
if (quest_type == QUEST_ESCAPE_FROM_HEL) {
return "Escape from Hel. Press space to jump over open graves. The pace quickens.";
}
if (quest_type == QUEST_SKELETAL_BARD) {
return "Skeletal Bard. A skeleton named Billy Bones is practicing to become a bard. Count the notes.";
}
return "Unknown quest.";
}
int get_quest_chance_from_favor() {
int chance = int(favor * QUEST_CHANCE_PER_FAVOR);
if (chance < QUEST_MIN_CHANCE && favor >= 1.0) chance = QUEST_MIN_CHANCE;
if (chance > 100) chance = 100;
return chance;
}
bool quest_menu_background_tick() {
return menu_background_tick();
}
void quest_boomerang_hit_sound() {
play_player_damage_sound();
}
void add_quest(int quest_type) {
if (quest_queue.length() >= QUEST_MAX_ACTIVE) return;
quest_queue.insert_last(quest_type);
notify("A new quest is available: " + get_quest_name(quest_type) + ".");
}
void attempt_daily_quest() {
if (quest_roll_done_today) return;
if (favor < 1.0) return;
if (world_altars.length() == 0) return;
if (quest_queue.length() >= QUEST_MAX_ACTIVE) return;
quest_roll_done_today = true;
int chance = get_quest_chance_from_favor();
int roll = random(1, 100);
if (roll > chance) return;
int quest_type = random(0, QUEST_TYPE_COUNT - 1);
add_quest(quest_type);
}
void check_quest_menu() {
if (key_pressed(KEY_Q)) {
if (x > BASE_END) {
speak_with_history("You are not in the base.", true);
return;
}
if (quest_queue.length() == 0) {
speak_with_history("No quests available.", true);
return;
}
run_quest_menu();
}
}
string get_quest_favor_phrase(int score) {
if (score <= 2) return "The gods are displeased with your performance.";
if (score < QUEST_STONE_SCORE) return "The gods are pleased with your performance.";
int extreme_threshold = QUEST_LOG_SCORE - 2;
if (score < extreme_threshold) return "The gods are very pleased with your performance.";
if (score < QUEST_LOG_SCORE) return "The gods are extremely pleased with your performance.";
return "The gods are ultimately pleased with your performance.";
}
void apply_quest_reward(int score) {
double favor_gain = score * QUEST_FAVOR_PER_POINT;
if (favor_gain < 0) favor_gain = 0;
if (favor_gain > 1.0) favor_gain = 1.0;
favor += favor_gain;
// Determine quantity based on score
// <= 2: 0
// 3-5: 1
// 6-7: 2
// 8-9: 3
// >= 10: 4
int quantity = 0;
if (score >= QUEST_LOG_SCORE) quantity = 4;
else if (score >= QUEST_LOG_SCORE - 2) quantity = 3;
else if (score >= QUEST_STONE_SCORE) quantity = 2;
else if (score > 2) quantity = 1;
// Select reward item
int[] possible_rewards = {
ITEM_STICKS, ITEM_VINES, ITEM_REEDS, ITEM_STONES, ITEM_LOGS, ITEM_CLAY,
ITEM_MEAT, ITEM_SKINS, ITEM_FEATHERS, ITEM_DOWN, ITEM_FISH, ITEM_SMOKED_FISH,
ITEM_HEAL_SCROLL, ITEM_INCENSE, ITEM_BASKET_FOOD
};
int reward_item = possible_rewards[random(0, possible_rewards.length() - 1)];
int added_amount = 0;
if (quantity > 0) {
added_amount = add_to_stack(get_personal_count(reward_item), quantity);
add_personal_count(reward_item, added_amount);
// Special handling for fish which needs weights
if (reward_item == ITEM_FISH) {
for (int i = 0; i < added_amount; i++) {
add_personal_fish_weight(get_default_fish_weight());
}
}
}
string message = "Quest Complete!\n\nRewards:\n";
message += get_quest_favor_phrase(score) + "\n";
message += "Favor: +" + format_favor(favor_gain) + "\n";
if (added_amount > 0) {
message += get_item_display_name(reward_item) + ": +" + added_amount + "\n";
} else if (quantity > 0) {
message += "Inventory full, could not receive " + get_item_display_name(reward_item) + ".\n";
} else {
message += "No items awarded.\n";
}
message += "\nScore: " + score;
text_reader(message, "Quest Rewards", true);
attempt_pet_offer_from_quest(score);
}
void run_quest(int quest_type) {
p.pause_all();
int score = 0;
if (quest_type == QUEST_BAT_INVASION) score = run_bat_invasion();
else if (quest_type == QUEST_CATCH_BOOMERANG) score = run_catch_the_boomerang();
else if (quest_type == QUEST_ENCHANTED_MELODY) score = run_enchanted_melody();
else if (quest_type == QUEST_ESCAPE_FROM_HEL) score = run_escape_from_hel();
else if (quest_type == QUEST_SKELETAL_BARD) score = run_skeletal_bard();
if (return_to_main_menu_requested) {
p.resume_all();
return;
}
apply_quest_reward(score);
p.resume_all();
}
void run_quest_menu() {
speak_with_history("Quest menu.", true);
int selection = 0;
string[] options;
for (uint i = 0; i < quest_queue.length(); i++) {
options.insert_last(get_quest_name(quest_queue[i]));
}
while(true) {
wait(5);
if (menu_background_tick()) {
return;
}
if (key_pressed(KEY_ESCAPE)) {
speak_with_history("Closed.", true);
break;
}
string count_str = " " + (selection + 1) + " of " + options.length();
if (key_pressed(KEY_DOWN)) {
play_menu_move_sound();
selection++;
if (selection >= options.length()) selection = 0;
count_str = " " + (selection + 1) + " of " + options.length();
speak_with_history(options[selection] + count_str, true);
}
if (key_pressed(KEY_UP)) {
play_menu_move_sound();
selection--;
if (selection < 0) selection = options.length() - 1;
count_str = " " + (selection + 1) + " of " + options.length();
speak_with_history(options[selection] + count_str, true);
}
if (key_pressed(KEY_RETURN)) {
play_menu_select_sound();
int quest_type = quest_queue[selection];
quest_queue.remove_at(selection);
run_quest(quest_type);
break;
}
}
}