Favor lowered. It should require actual work to maintain. Fixed a bug with pets.

This commit is contained in:
Storm Dragon
2026-02-14 00:16:02 -05:00
parent 6687863fbe
commit dc23ddabb2
12 changed files with 276 additions and 326 deletions
+3 -3
View File
@@ -11,9 +11,9 @@ const int BANDIT_HIDEOUT_BASE_SPAWN_RANGE = 10;
const int BANDIT_HIDEOUT_START_SPAWN_RANGE = 10;
const int BANDIT_HIDEOUT_BARRICADE_HP_PER_DAY = 34;
const int BANDIT_HIDEOUT_BARRICADE_HP_MAX = 500;
const double BANDIT_HIDEOUT_FAVOR_PER_KILL = 0.2;
const double BANDIT_HIDEOUT_BASE_FAVOR = 3.0;
const double BANDIT_HIDEOUT_FAVOR_MAX = 10.0;
const double BANDIT_HIDEOUT_FAVOR_PER_KILL = 0.08;
const double BANDIT_HIDEOUT_BASE_FAVOR = 0.30;
const double BANDIT_HIDEOUT_FAVOR_MAX = 1.0;
class HideoutBandit {
int position;
+2 -2
View File
@@ -653,7 +653,7 @@ void give_unicorn_rewards() {
speak_with_history("Victory!", true);
// Calculate rewards
int favor_reward = 4 + random(1, 4); // 4 + 1d4 = 5-8 favor
double favor_reward = double(random(7, 10)) / 10.0; // 0.7-1.0 favor
favor += favor_reward;
int scrolls_added = add_to_stack(get_personal_count(ITEM_HEAL_SCROLL), 1);
add_personal_count(ITEM_HEAL_SCROLL, scrolls_added);
@@ -667,7 +667,7 @@ void give_unicorn_rewards() {
string[] rewards;
rewards.insert_last("=== Victory Rewards ===");
rewards.insert_last("");
rewards.insert_last("The gods are pleased with your victory! " + favor_reward + " favor awarded.");
rewards.insert_last("The gods are pleased with your victory! " + format_favor(favor_reward) + " favor awarded.");
rewards.insert_last("Heal Scrolls: +" + scrolls_added + ".");
rewards.insert_last("");
if (new_rune) {
+8 -1
View File
@@ -442,7 +442,14 @@ int add_to_stack(int current, int amount) {
string format_favor(double value) {
if (value < 0) value = 0;
return "" + int(value);
int scaled = int((value * 100.0) + 0.5);
int wholePart = scaled / 100;
int fractionalPart = scaled % 100;
if (fractionalPart <= 0) return "" + wholePart;
if (fractionalPart < 10) return wholePart + ".0" + fractionalPart;
if (fractionalPart % 10 == 0) return wholePart + "." + (fractionalPart / 10);
return wholePart + "." + fractionalPart;
}
string get_equipped_weapon_name() {
+10 -2
View File
@@ -110,6 +110,14 @@ bool sort_string_case_insensitive_sounds(const string &in a, const string &in b)
return a.lower() < b.lower();
}
void append_unique_case_insensitive(string[]@ items, const string&in value) {
string lowerValue = value.lower();
for (uint i = 0; i < items.length(); i++) {
if (items[i].lower() == lowerValue) return;
}
items.insert_last(value);
}
string collapse_spaces(const string&in text) {
string result = text;
while (result.find_first(" ") > -1) {
@@ -159,13 +167,13 @@ void add_doc_entries(string[]@ labels, string[]@ paths, int[]@ types) {
string[]@ mdFiles = find_files("files/*.md");
if (@mdFiles !is null) {
for (uint i = 0; i < mdFiles.length(); i++) {
docFiles.insert_last(mdFiles[i]);
append_unique_case_insensitive(docFiles, 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]);
append_unique_case_insensitive(docFiles, mdCapsFiles[i]);
}
}
+8 -3
View File
@@ -1,6 +1,11 @@
// Altar/sacrifice menu system
// Functions for sacrificing items at the altar
string format_altar_favor(double value) {
if (value < 0) value = 0;
return "" + int(value);
}
void check_altar_menu(int player_x) {
if (!key_pressed(KEY_S)) return;
@@ -43,7 +48,7 @@ void sacrifice_item(int item_type) {
cleanup_equipment_after_inventory_change();
double favor_gain = get_item_favor_value(item_type);
favor += favor_gain;
speak_with_history("Sacrificed 1 " + get_item_label_singular(item_type) + ". Favor +" + format_favor(favor_gain) + ". Total " + format_favor(favor) + ".", true);
speak_with_history("Sacrificed 1 " + get_item_label_singular(item_type) + ". Favor +" + format_altar_favor(favor_gain) + ". Total " + format_altar_favor(favor) + ".", true);
}
void sacrifice_item_max(int item_type) {
@@ -71,11 +76,11 @@ void sacrifice_item_max(int item_type) {
double total_favor = favor_per_item * available;
favor += total_favor;
speak_with_history("Sacrificed " + available + " " + get_item_label(item_type) + ". Favor +" + format_favor(total_favor) + ". Total " + format_favor(favor) + ".", true);
speak_with_history("Sacrificed " + available + " " + get_item_label(item_type) + ". Favor +" + format_altar_favor(total_favor) + ". Total " + format_altar_favor(favor) + ".", true);
}
void run_altar_menu() {
speak_with_history("Altar. Favor " + format_favor(favor) + ".", true);
speak_with_history("Altar. Favor " + format_altar_favor(favor) + ".", true);
int selection = 0;
string[] options;
+12 -5
View File
@@ -404,8 +404,10 @@ void check_pet_call_key() {
petOut = true;
petPosition = get_pet_listener_pos();
petPositionValid = true;
if (file_exists("sounds/pets/call_pet.ogg")) {
p.play_stationary("sounds/pets/call_pet.ogg", false);
if (file_exists("sounds/action/call_pet.ogg")) {
/* But I can feel it, black water washes over me.
As it soothes I call to you with my control. */
p.play_stationary("sounds/action/call_pet.ogg", false);
}
}
@@ -661,7 +663,7 @@ bool try_pet_pickup_small_game(const string&in gameType, string &out message) {
}
add_personal_count(ITEM_SMALL_GAME, 1);
personal_small_game_types.insert_last(gameType);
message = "Your " + get_pet_display_name() + " retrieved " + gameType + ". A " + get_pet_display_name() + " returns to you.";
message = "Your " + get_pet_display_name() + " retrieved " + gameType + ".";
return true;
}
@@ -681,7 +683,7 @@ bool try_pet_pickup_world_drop(WorldDrop@ drop, string &out message) {
return true;
}
add_personal_count(ITEM_ARROWS, 1);
message = "Your " + get_pet_display_name() + " retrieved an arrow. A " + get_pet_display_name() + " returns to you.";
message = "Your " + get_pet_display_name() + " retrieved an arrow.";
return true;
}
if (drop.type == "boar carcass") {
@@ -690,7 +692,7 @@ bool try_pet_pickup_world_drop(WorldDrop@ drop, string &out message) {
return true;
}
add_personal_count(ITEM_BOAR_CARCASSES, 1);
message = "Your " + get_pet_display_name() + " retrieved a boar carcass. A " + get_pet_display_name() + " returns to you.";
message = "Your " + get_pet_display_name() + " retrieved a boar carcass.";
return true;
}
return false;
@@ -868,6 +870,11 @@ void handle_pet_hourly_update(int hour) {
}
}
if (petKnockoutHoursRemaining <= 0 && petHealth > 0 && petHealth < PET_HEALTH_MAX) {
petHealth += 1;
if (petHealth > PET_HEALTH_MAX) petHealth = PET_HEALTH_MAX;
}
if (!has_pet_food_available()) {
adjust_pet_loyalty(-PET_LOYALTY_HUNGER_LOSS);
}
+4 -2
View File
@@ -45,7 +45,7 @@ string get_quest_description(int quest_type) {
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 < QUEST_MIN_CHANCE && favor >= 1.0) chance = QUEST_MIN_CHANCE;
if (chance > 100) chance = 100;
return chance;
}
@@ -66,7 +66,7 @@ void add_quest(int quest_type) {
void attempt_daily_quest() {
if (quest_roll_done_today) return;
if (favor <= 1.0) return;
if (favor < 1.0) return;
if (world_altars.length() == 0) return;
if (quest_queue.length() >= QUEST_MAX_ACTIVE) return;
@@ -105,6 +105,7 @@ string get_quest_favor_phrase(int score) {
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
@@ -142,6 +143,7 @@ void apply_quest_reward(int score) {
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";
+76 -38
View File
@@ -414,47 +414,85 @@ bool setup_new_character() {
}
bool select_save_file(string &out filename) {
string[] files = get_save_files();
if (files.length() == 0) return false;
string[] options;
for (uint i = 0; i < files.length(); i++) {
string displayName;
int sex = SEX_MALE;
int day = 1;
if (!read_save_metadata(files[i], displayName, sex, day)) {
displayName = strip_save_extension(files[i]);
options.insert_last(displayName);
} else {
string sex_label = (sex == SEX_FEMALE) ? "female" : "male";
options.insert_last(displayName + ", " + sex_label + ", day " + day);
}
}
int selection = 0;
speak_with_history("Load game. Select character.", true);
speak_with_history(options[selection], true);
while (true) {
wait(5);
if (key_pressed(KEY_DOWN)) {
play_menu_move_sound();
selection++;
if (selection >= options.length()) selection = 0;
speak_with_history(options[selection], true);
string[] files = get_save_files();
if (files.length() == 0) return false;
string[] options;
string[] displayNames;
int[] sexValues;
int[] dayValues;
bool[] hasMetadata;
for (uint i = 0; i < files.length(); i++) {
string displayName;
int sex = SEX_MALE;
int day = 1;
bool gotMeta = read_save_metadata(files[i], displayName, sex, day);
if (!gotMeta) {
displayName = strip_save_extension(files[i]);
options.insert_last(displayName);
} else {
string sex_label = (sex == SEX_FEMALE) ? "female" : "male";
options.insert_last(displayName + ", " + sex_label + ", day " + day);
}
displayNames.insert_last(displayName);
sexValues.insert_last(sex);
dayValues.insert_last(day);
hasMetadata.insert_last(gotMeta);
}
if (key_pressed(KEY_UP)) {
play_menu_move_sound();
selection--;
if (selection < 0) selection = int(options.length()) - 1;
speak_with_history(options[selection], true);
int selection = 0;
speak_with_history("Load game. Select character. Press delete to remove a save.", true);
speak_with_history(options[selection], true);
bool refreshList = false;
while (true) {
wait(5);
if (key_pressed(KEY_DOWN)) {
play_menu_move_sound();
selection++;
if (selection >= options.length()) selection = 0;
speak_with_history(options[selection], true);
}
if (key_pressed(KEY_UP)) {
play_menu_move_sound();
selection--;
if (selection < 0) selection = int(options.length()) - 1;
speak_with_history(options[selection], true);
}
if (key_pressed(KEY_RETURN)) {
play_menu_select_sound();
filename = files[selection];
return true;
}
if (key_pressed(KEY_DELETE)) {
string prompt = "Are you sure you want to delete the character " + displayNames[selection];
if (hasMetadata[selection]) {
string sex_label = (sexValues[selection] == SEX_FEMALE) ? "female" : "male";
prompt += " gender " + sex_label + " days " + dayValues[selection] + "?";
} else {
prompt += "?";
}
int confirm = ui_question("", prompt);
if (confirm == 1) {
if (file_delete(files[selection])) {
speak_with_history("Save deleted.", true);
refreshList = true;
break;
} else {
ui_info_box("Draugnorak", "Delete Save", "Unable to delete save.");
speak_with_history(options[selection], true);
}
} else {
speak_with_history(options[selection], true);
}
}
if (key_pressed(KEY_ESCAPE)) {
return false;
}
}
if (key_pressed(KEY_RETURN)) {
play_menu_select_sound();
filename = files[selection];
return true;
}
if (key_pressed(KEY_ESCAPE)) {
if (!refreshList) {
return false;
}
}
+2 -1
View File
@@ -894,7 +894,8 @@ string get_time_string() {
} else if (weather_state == WEATHER_STORMY) {
conditions.insert_last("Storming");
}
if (!is_daytime) {
bool can_see_night_sky = (weather_state == WEATHER_CLEAR || weather_state == WEATHER_WINDY);
if (!is_daytime && can_see_night_sky) {
conditions.insert_last("Moon and stars");
}
if (conditions.length() > 0) {