A couple more quests added.
This commit is contained in:
BIN
sounds/quests/boomerang.ogg
LFS
Normal file
BIN
sounds/quests/boomerang.ogg
LFS
Normal file
Binary file not shown.
@@ -222,7 +222,7 @@ const int GOOSE_FALL_SPEED = 100; // ms per foot
|
|||||||
const int GOOSE_FLY_AWAY_CHANCE = 0; // Chance out of 1000 per tick to fly away
|
const int GOOSE_FLY_AWAY_CHANCE = 0; // Chance out of 1000 per tick to fly away
|
||||||
const int GOOSE_MAX_DIST_FROM_WATER = 4; // How far they can wander from water
|
const int GOOSE_MAX_DIST_FROM_WATER = 4; // How far they can wander from water
|
||||||
const int GOOSE_MAX_COUNT = 3;
|
const int GOOSE_MAX_COUNT = 3;
|
||||||
const int GOOSE_HOURLY_SPAWN_CHANCE = 35; // Percent chance per hour to spawn a goose
|
const int GOOSE_HOURLY_SPAWN_CHANCE = 40; // Percent chance per hour to spawn a goose
|
||||||
const int GOOSE_SIGHT_RANGE = 0;
|
const int GOOSE_SIGHT_RANGE = 0;
|
||||||
|
|
||||||
// Weather settings
|
// Weather settings
|
||||||
|
|||||||
@@ -19,6 +19,22 @@ string get_base_equipment_name(int equip_type) {
|
|||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string get_base_equipment_name_plural(int equip_type) {
|
||||||
|
if (equip_type == EQUIP_SPEAR) return "Spears";
|
||||||
|
if (equip_type == EQUIP_AXE) return "Stone Axes";
|
||||||
|
if (equip_type == EQUIP_SLING) return "Slings";
|
||||||
|
if (equip_type == EQUIP_BOW) return "Bows";
|
||||||
|
if (equip_type == EQUIP_HAT) return "Skin Hats";
|
||||||
|
if (equip_type == EQUIP_GLOVES) return "Skin Gloves";
|
||||||
|
if (equip_type == EQUIP_PANTS) return "Skin Pants";
|
||||||
|
if (equip_type == EQUIP_TUNIC) return "Skin Tunics";
|
||||||
|
if (equip_type == EQUIP_MOCCASINS) return "Moccasins";
|
||||||
|
if (equip_type == EQUIP_POUCH) return "Skin Pouches";
|
||||||
|
if (equip_type == EQUIP_BACKPACK) return "Backpacks";
|
||||||
|
if (equip_type == EQUIP_FISHING_POLE) return "Fishing Poles";
|
||||||
|
return "Items";
|
||||||
|
}
|
||||||
|
|
||||||
// Get inventory count for an equipment type
|
// Get inventory count for an equipment type
|
||||||
int get_unruned_equipment_count(int equip_type) {
|
int get_unruned_equipment_count(int equip_type) {
|
||||||
if (equip_type == EQUIP_SPEAR) return get_personal_count(ITEM_SPEARS);
|
if (equip_type == EQUIP_SPEAR) return get_personal_count(ITEM_SPEARS);
|
||||||
@@ -158,6 +174,12 @@ void run_rune_equipment_menu(int rune_type) {
|
|||||||
engrave_rune(equip_type, rune_type);
|
engrave_rune(equip_type, rune_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key_pressed(KEY_TAB)) {
|
||||||
|
int equip_type = equipment_types[selection];
|
||||||
|
engrave_rune_max(equip_type, rune_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,3 +216,48 @@ void engrave_rune(int equip_type, int rune_type) {
|
|||||||
speak_with_history("Missing: " + missing, true);
|
speak_with_history("Missing: " + missing, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void engrave_rune_max(int equip_type, int rune_type) {
|
||||||
|
// Validate requirements
|
||||||
|
string missing = "";
|
||||||
|
if (get_personal_count(ITEM_KNIVES) < 1) missing += "Stone Knife ";
|
||||||
|
|
||||||
|
int unruned_count = get_unruned_equipment_count(equip_type);
|
||||||
|
if (unruned_count < 1) {
|
||||||
|
speak_with_history("No " + get_base_equipment_name(equip_type) + " available.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clay_count = get_personal_count(ITEM_CLAY);
|
||||||
|
int favor_count = int(favor);
|
||||||
|
int max_craft = unruned_count;
|
||||||
|
if (clay_count < max_craft) max_craft = clay_count;
|
||||||
|
if (favor_count < max_craft) max_craft = favor_count;
|
||||||
|
|
||||||
|
if (missing != "") {
|
||||||
|
speak_with_history("Missing: " + missing, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max_craft <= 0) {
|
||||||
|
if (clay_count < 1) missing += "1 clay ";
|
||||||
|
if (favor < 1.0) missing += "1 favor ";
|
||||||
|
if (missing == "") missing = "resources";
|
||||||
|
speak_with_history("Missing: " + missing, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume materials (knife is not consumed, it's a tool)
|
||||||
|
add_personal_count(ITEM_CLAY, -max_craft);
|
||||||
|
favor -= double(max_craft);
|
||||||
|
|
||||||
|
for (int i = 0; i < max_craft; i++) {
|
||||||
|
decrement_unruned_equipment(equip_type);
|
||||||
|
add_runed_item(equip_type, rune_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
simulate_crafting(6 * max_craft);
|
||||||
|
|
||||||
|
string item_name = (max_craft == 1) ? get_base_equipment_name(equip_type) : get_base_equipment_name_plural(equip_type);
|
||||||
|
speak_with_history("Engraved " + max_craft + " " + item_name + " with " + get_rune_name(rune_type) + ".", true);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
// Quest system
|
// Quest system
|
||||||
#include "src/quests/bat_invasion_game.nvgt"
|
#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/enchanted_melody_game.nvgt"
|
||||||
#include "src/quests/escape_from_hel_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_BAT_INVASION = 0;
|
||||||
const int QUEST_ENCHANTED_MELODY = 1;
|
const int QUEST_CATCH_BOOMERANG = 1;
|
||||||
const int QUEST_ESCAPE_FROM_HEL = 2;
|
const int QUEST_ENCHANTED_MELODY = 2;
|
||||||
const int QUEST_TYPE_COUNT = 3;
|
const int QUEST_ESCAPE_FROM_HEL = 3;
|
||||||
|
const int QUEST_SKELETAL_BARD = 4;
|
||||||
|
const int QUEST_TYPE_COUNT = 5;
|
||||||
|
|
||||||
int[] quest_queue;
|
int[] quest_queue;
|
||||||
bool quest_roll_done_today = false;
|
bool quest_roll_done_today = false;
|
||||||
|
|
||||||
string get_quest_name(int quest_type) {
|
string get_quest_name(int quest_type) {
|
||||||
if (quest_type == QUEST_BAT_INVASION) return "Bat Invasion";
|
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_ENCHANTED_MELODY) return "Enchanted Melody";
|
||||||
if (quest_type == QUEST_ESCAPE_FROM_HEL) return "Escape from Hel";
|
if (quest_type == QUEST_ESCAPE_FROM_HEL) return "Escape from Hel";
|
||||||
|
if (quest_type == QUEST_SKELETAL_BARD) return "Skeletal Bard";
|
||||||
return "Unknown Quest";
|
return "Unknown Quest";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,12 +28,18 @@ string get_quest_description(int quest_type) {
|
|||||||
if (quest_type == QUEST_BAT_INVASION) {
|
if (quest_type == QUEST_BAT_INVASION) {
|
||||||
return "Bat Invasion. Giant killer bats are attacking. Press space to throw when the bat is centered.";
|
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) {
|
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.";
|
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) {
|
if (quest_type == QUEST_ESCAPE_FROM_HEL) {
|
||||||
return "Escape from Hel. Press space to jump over open graves. The pace quickens.";
|
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.";
|
return "Unknown quest.";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +50,14 @@ int get_quest_chance_from_favor() {
|
|||||||
return chance;
|
return chance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void quest_menu_background_tick() {
|
||||||
|
menu_background_tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
void quest_boomerang_hit_sound() {
|
||||||
|
play_player_damage_sound();
|
||||||
|
}
|
||||||
|
|
||||||
void add_quest(int quest_type) {
|
void add_quest(int quest_type) {
|
||||||
if (quest_queue.length() >= QUEST_MAX_ACTIVE) return;
|
if (quest_queue.length() >= QUEST_MAX_ACTIVE) return;
|
||||||
quest_queue.insert_last(quest_type);
|
quest_queue.insert_last(quest_type);
|
||||||
@@ -139,8 +159,10 @@ void run_quest(int quest_type) {
|
|||||||
p.pause_all();
|
p.pause_all();
|
||||||
int score = 0;
|
int score = 0;
|
||||||
if (quest_type == QUEST_BAT_INVASION) score = run_bat_invasion();
|
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_ENCHANTED_MELODY) score = run_enchanted_melody();
|
||||||
else if (quest_type == QUEST_ESCAPE_FROM_HEL) score = run_escape_from_hel();
|
else if (quest_type == QUEST_ESCAPE_FROM_HEL) score = run_escape_from_hel();
|
||||||
|
else if (quest_type == QUEST_SKELETAL_BARD) score = run_skeletal_bard();
|
||||||
apply_quest_reward(score);
|
apply_quest_reward(score);
|
||||||
p.resume_all();
|
p.resume_all();
|
||||||
}
|
}
|
||||||
|
|||||||
89
src/quests/catch_the_boomerang_game.nvgt
Normal file
89
src/quests/catch_the_boomerang_game.nvgt
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
// Catch the Boomerang quest game
|
||||||
|
int run_catch_the_boomerang() {
|
||||||
|
string[] instructions;
|
||||||
|
instructions.insert_last("=== Catch the Boomerang ===");
|
||||||
|
instructions.insert_last("");
|
||||||
|
instructions.insert_last("Throw a boomerang and catch it on the return.");
|
||||||
|
instructions.insert_last("");
|
||||||
|
instructions.insert_last("How to play:");
|
||||||
|
instructions.insert_last(" - Press Space to throw");
|
||||||
|
instructions.insert_last(" - Press Space again when it sounds close");
|
||||||
|
instructions.insert_last(" - There are 5 turns");
|
||||||
|
instructions.insert_last(" - Better timing earns more points (up to 4)");
|
||||||
|
instructions.insert_last("");
|
||||||
|
instructions.insert_last("Close this screen to begin.");
|
||||||
|
text_reader_lines(instructions, "Quest Instructions", true);
|
||||||
|
|
||||||
|
wait(500);
|
||||||
|
|
||||||
|
const string boomerangSound = "sounds/quests/boomerang.ogg";
|
||||||
|
const int turnsTotal = 5;
|
||||||
|
int score = 0;
|
||||||
|
int caughtCount = 0;
|
||||||
|
string[] skillLevel = {"", "almost dropped", "managed to catch", "caught", "expertly caught"};
|
||||||
|
|
||||||
|
bool firstTurnPrompt = true;
|
||||||
|
|
||||||
|
for (int turn = 0; turn < turnsTotal; turn++) {
|
||||||
|
if (firstTurnPrompt) {
|
||||||
|
speak_with_history("Press Space to throw.", true);
|
||||||
|
firstTurnPrompt = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
wait(5);
|
||||||
|
if (key_pressed(KEY_SPACE)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxDistance = random(40, 70);
|
||||||
|
int boomerangY = -2;
|
||||||
|
bool returning = false;
|
||||||
|
bool resolved = false;
|
||||||
|
int stepDelay = random(180, 280);
|
||||||
|
int stepSize = 2;
|
||||||
|
|
||||||
|
while (!resolved) {
|
||||||
|
wait(stepDelay);
|
||||||
|
|
||||||
|
p.play_2d(boomerangSound, 0.0, 0.0, 0.0, boomerangY, false);
|
||||||
|
|
||||||
|
if (key_pressed(KEY_SPACE)) {
|
||||||
|
if (returning && boomerangY > -5) {
|
||||||
|
int points = 5 + boomerangY;
|
||||||
|
if (points < 1) points = 1;
|
||||||
|
if (points > 4) points = 4;
|
||||||
|
score += points;
|
||||||
|
caughtCount++;
|
||||||
|
string promptSuffix = (turn < turnsTotal - 1) ? " Press Space to throw." : "";
|
||||||
|
speak_with_history("You " + skillLevel[points] + " the boomerang. " + points + " points." + promptSuffix, true);
|
||||||
|
} else {
|
||||||
|
string promptSuffix = (turn < turnsTotal - 1) ? " Press Space to throw." : "";
|
||||||
|
speak_with_history("You missed the boomerang." + promptSuffix, true);
|
||||||
|
}
|
||||||
|
resolved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resolved) {
|
||||||
|
if (!returning && boomerangY <= -maxDistance) {
|
||||||
|
returning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boomerangY += returning ? stepSize : -stepSize;
|
||||||
|
|
||||||
|
if (boomerangY >= 0) {
|
||||||
|
string promptSuffix = (turn < turnsTotal - 1) ? " Press Space to throw." : "";
|
||||||
|
speak_with_history("The boomerang hit you." + promptSuffix, true);
|
||||||
|
quest_boomerang_hit_sound();
|
||||||
|
resolved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wait(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
speak_with_history("You caught " + caughtCount + " boomerangs for a total of " + score + " points.", true);
|
||||||
|
return score;
|
||||||
|
}
|
||||||
93
src/quests/skeletal_bard_game.nvgt
Normal file
93
src/quests/skeletal_bard_game.nvgt
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
// Skeletal Bard quest game
|
||||||
|
string[] skeletalBardNotes = {
|
||||||
|
"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"
|
||||||
|
};
|
||||||
|
|
||||||
|
void play_skeletal_bard_note() {
|
||||||
|
int noteIndex = random(0, skeletalBardNotes.length() - 1);
|
||||||
|
p.play_stationary(skeletalBardNotes[noteIndex], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int select_note_count(int minNotes, int maxNotes, int startValue) {
|
||||||
|
int selection = startValue;
|
||||||
|
speak_with_history("Select number of notes. " + selection + ".", true);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
wait(5);
|
||||||
|
quest_menu_background_tick();
|
||||||
|
|
||||||
|
if (key_pressed(KEY_UP)) {
|
||||||
|
if (selection < maxNotes) selection++;
|
||||||
|
speak_with_history("" + selection + ".", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_pressed(KEY_DOWN)) {
|
||||||
|
if (selection > minNotes) selection--;
|
||||||
|
speak_with_history("" + selection + ".", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_pressed(KEY_RETURN)) {
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_skeletal_bard() {
|
||||||
|
string[] instructions;
|
||||||
|
instructions.insert_last("=== Skeletal Bard ===");
|
||||||
|
instructions.insert_last("");
|
||||||
|
instructions.insert_last("A skeleton named Billy Bones is practicing to become a bard.");
|
||||||
|
instructions.insert_last("Listen to the melody and count the notes.");
|
||||||
|
instructions.insert_last("");
|
||||||
|
instructions.insert_last("How to play:");
|
||||||
|
instructions.insert_last(" - After the tune, choose the number of notes");
|
||||||
|
instructions.insert_last(" - Use Up/Down to change the number");
|
||||||
|
instructions.insert_last(" - Press Enter to confirm");
|
||||||
|
instructions.insert_last(" - There are 5 rounds, up to 4 points each");
|
||||||
|
instructions.insert_last("");
|
||||||
|
instructions.insert_last("Close this screen to begin.");
|
||||||
|
text_reader_lines(instructions, "Quest Instructions", true);
|
||||||
|
|
||||||
|
wait(500);
|
||||||
|
|
||||||
|
int score = 0;
|
||||||
|
const int rounds = 5;
|
||||||
|
|
||||||
|
for (int round = 0; round < rounds; round++) {
|
||||||
|
int length = random(5, 20);
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
play_skeletal_bard_note();
|
||||||
|
wait(random(200, 400));
|
||||||
|
}
|
||||||
|
|
||||||
|
wait(400);
|
||||||
|
|
||||||
|
int guess = select_note_count(5, 20, 5);
|
||||||
|
int diff = length - guess;
|
||||||
|
if (diff < 0) diff = -diff;
|
||||||
|
|
||||||
|
int points = 4 - diff;
|
||||||
|
if (points < 0) points = 0;
|
||||||
|
score += points;
|
||||||
|
|
||||||
|
speak_with_history("You entered " + guess + " notes and the actual number was " + length + ". " + points + " points. Press Enter to continue.", true);
|
||||||
|
while (true) {
|
||||||
|
wait(5);
|
||||||
|
if (key_pressed(KEY_RETURN)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
speak_with_history("Skeletal Bard complete. Your score for all five tunes is " + score + ".", true);
|
||||||
|
return score;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user