finally a use for the stable and pasture.

This commit is contained in:
Storm Dragon
2026-02-06 01:11:35 -05:00
parent 055e441e1b
commit 3cf769c7f8
10 changed files with 189 additions and 17 deletions

View File

@@ -35,8 +35,27 @@ int get_resident_effect_multiplier() {
return blessing_resident_active ? 2 : 1; return blessing_resident_active ? 2 : 1;
} }
int get_horse_success_bonus() {
if (world_stables.length() == 0) return 0;
if (world_storages.length() == 0) return 0;
if (horses_count <= 0) return 0;
int count = horses_count;
if (count > MAX_HORSES) count = MAX_HORSES;
return count * HORSE_SUCCESS_BONUS_PER;
}
int get_horse_damage_bonus() {
if (world_stables.length() == 0) return 0;
if (world_storages.length() == 0) return 0;
if (horses_count <= 0) return 0;
int count = horses_count;
if (count > MAX_HORSES) count = MAX_HORSES;
return count / HORSE_DAMAGE_BONUS_STEP;
}
int get_resident_success_chance(int base_chance) { int get_resident_success_chance(int base_chance) {
int chance = base_chance * get_resident_effect_multiplier(); int chance = base_chance * get_resident_effect_multiplier();
chance += get_horse_success_bonus();
if (chance > 100) chance = 100; if (chance > 100) chance = 100;
return chance; return chance;
} }
@@ -62,8 +81,12 @@ int get_resident_cooldown(int base_cooldown) {
} }
int apply_resident_damage_bonus(int damage) { int apply_resident_damage_bonus(int damage) {
if (!blessing_resident_active) return damage; int adjusted = damage;
return damage * get_resident_effect_multiplier(); if (blessing_resident_active) {
adjusted *= get_resident_effect_multiplier();
}
adjusted += get_horse_damage_bonus();
return adjusted;
} }
void consume_food_for_residents() { void consume_food_for_residents() {
@@ -176,6 +199,54 @@ void attempt_resident_fish_smoking() {
} }
} }
void attempt_livestock_production() {
if (world_pastures.length() == 0) return;
if (world_storages.length() == 0) return;
if (livestock_count <= 0) return;
int count = livestock_count;
if (count > MAX_LIVESTOCK) count = MAX_LIVESTOCK;
int meat_produced = 0;
int skins_produced = 0;
for (int i = 0; i < count; i++) {
if (get_storage_count(ITEM_MEAT) < BASE_STORAGE_MAX) {
if (random(1, 100) <= LIVESTOCK_MEAT_CHANCE) {
add_storage_count(ITEM_MEAT, 1);
meat_produced++;
}
}
if (get_storage_count(ITEM_SKINS) < BASE_STORAGE_MAX) {
if (random(1, 100) <= LIVESTOCK_SKIN_CHANCE) {
add_storage_count(ITEM_SKINS, 1);
skins_produced++;
}
}
}
if ((meat_produced > 0 || skins_produced > 0) && x <= BASE_END) {
string msg = "Livestock produced ";
string[] outputs;
if (meat_produced > 0) outputs.insert_last(meat_produced + " meat");
if (skins_produced > 0) outputs.insert_last(skins_produced + " skins");
for (uint i = 0; i < outputs.length(); i++) {
if (i > 0) {
if (i == outputs.length() - 1) {
msg += " and ";
} else {
msg += ", ";
}
}
msg += outputs[i];
}
msg += " and added to storage.";
speak_with_history(msg, true);
}
}
void keep_base_fires_fed() { void keep_base_fires_fed() {
if (residents_count <= 0) return; if (residents_count <= 0) return;
if (!has_any_storage_food()) return; if (!has_any_storage_food()) return;

View File

@@ -684,6 +684,21 @@ void give_bandit_hideout_rewards() {
} }
} }
rewards.insert_last("");
if (world_pastures.length() == 0 || world_storages.length() == 0) {
rewards.insert_last("Pasture or storage not built. No livestock were recovered.");
} else if (livestock_count >= MAX_LIVESTOCK) {
rewards.insert_last("Pasture is full. No livestock were recovered.");
} else {
int livestockRoll = random(1, 100);
if (livestockRoll <= LIVESTOCK_ADVENTURE_CHANCE) {
livestock_count++;
rewards.insert_last("Livestock were recovered and added to your pasture.");
} else {
rewards.insert_last("No livestock were recovered.");
}
}
bool newRune = !rune_destruction_unlocked; bool newRune = !rune_destruction_unlocked;
rune_destruction_unlocked = true; rune_destruction_unlocked = true;
rewards.insert_last(""); rewards.insert_last("");

View File

@@ -620,6 +620,21 @@ void give_unicorn_rewards() {
rewards.insert_last("You have already mastered the Rune of Swiftness."); rewards.insert_last("You have already mastered the Rune of Swiftness.");
} }
rewards.insert_last("");
if (world_stables.length() == 0 || world_storages.length() == 0) {
rewards.insert_last("Stable or storage not built. No horses were captured.");
} else if (horses_count >= MAX_HORSES) {
rewards.insert_last("Stable is full. No horses were captured.");
} else {
int horseRoll = random(1, 100);
if (horseRoll <= HORSE_ADVENTURE_CHANCE) {
horses_count++;
rewards.insert_last("A horse joins your stable.");
} else {
rewards.insert_last("No horses were captured.");
}
}
append_adventure_completion_rewards(ADVENTURE_UNICORN, rewards); append_adventure_completion_rewards(ADVENTURE_UNICORN, rewards);
// Display rewards in text reader // Display rewards in text reader

View File

@@ -115,7 +115,7 @@ const int STORAGE_LOG_COST = 6;
const int STORAGE_STONE_COST = 9; const int STORAGE_STONE_COST = 9;
const int STORAGE_VINE_COST = 8; const int STORAGE_VINE_COST = 8;
const int PASTURE_LOG_COST = 8; const int PASTURE_LOG_COST = 8;
const int PASTURE_VINE_COST = 20; const int PASTURE_ROPE_COST = 18;
const int STABLE_LOG_COST = 10; const int STABLE_LOG_COST = 10;
const int STABLE_STONE_COST = 15; const int STABLE_STONE_COST = 15;
const int STABLE_VINE_COST = 10; const int STABLE_VINE_COST = 10;
@@ -127,6 +127,16 @@ const int INCENSE_REED_COST = 1;
const int INCENSE_HOURS_PER_STICK = 4; const int INCENSE_HOURS_PER_STICK = 4;
const double INCENSE_FAVOR_PER_HOUR = 0.3; const double INCENSE_FAVOR_PER_HOUR = 0.3;
// Livestock and stable settings
const int MAX_HORSES = 9;
const int MAX_LIVESTOCK = 9;
const int HORSE_ADVENTURE_CHANCE = 30;
const int LIVESTOCK_ADVENTURE_CHANCE = 30;
const int HORSE_SUCCESS_BONUS_PER = 2;
const int HORSE_DAMAGE_BONUS_STEP = 3;
const int LIVESTOCK_MEAT_CHANCE = 6;
const int LIVESTOCK_SKIN_CHANCE = 3;
// Bandit settings // Bandit settings
const int BANDIT_HEALTH = 4; const int BANDIT_HEALTH = 4;
const int BANDIT_MAX_COUNT = 3; const int BANDIT_MAX_COUNT = 3;

View File

@@ -1,4 +1,30 @@
// Crafting buildings // Crafting buildings
bool has_building_options() {
bool base_has_firepit = false;
bool base_has_fire = false;
for (uint i = 0; i < world_firepits.length(); i++) {
if (world_firepits[i].position <= BASE_END) {
base_has_firepit = true;
break;
}
}
for (uint i = 0; i < world_fires.length(); i++) {
if (world_fires[i].position <= BASE_END) {
base_has_fire = true;
break;
}
}
if (x > BASE_END || !base_has_firepit) return true;
if (x > BASE_END || !base_has_fire) return true;
if (get_herb_garden_at_base() == null) return true;
if (world_storages.length() == 0) return true;
if (world_pastures.length() == 0 && world_storages.length() > 0) return true;
if (world_stables.length() == 0 && world_storages.length() > 0) return true;
if (world_altars.length() == 0) return true;
return false;
}
void run_buildings_menu() { void run_buildings_menu() {
speak_with_history("Buildings.", true); speak_with_history("Buildings.", true);
@@ -44,15 +70,15 @@ void run_buildings_menu() {
building_types.insert_last(3); building_types.insert_last(3);
} }
// Only show pasture if not built // Only show pasture if not built and storage exists
if (world_pastures.length() == 0) { if (world_pastures.length() == 0 && world_storages.length() > 0) {
options.insert_last("Pasture (8 Logs, 20 Vines) [Base Only]"); options.insert_last("Pasture (8 Logs, 18 Ropes) [Base Only, Requires Storage]");
building_types.insert_last(4); building_types.insert_last(4);
} }
// Only show stable if not built // Only show stable if not built and storage exists
if (world_stables.length() == 0) { if (world_stables.length() == 0 && world_storages.length() > 0) {
options.insert_last("Stable (10 Logs, 15 Stones, 10 Vines) [Base Only]"); options.insert_last("Stable (10 Logs, 15 Stones, 10 Vines) [Base Only, Requires Storage]");
building_types.insert_last(5); building_types.insert_last(5);
} }
@@ -62,6 +88,11 @@ void run_buildings_menu() {
building_types.insert_last(6); building_types.insert_last(6);
} }
if (options.length() == 0) {
speak_with_history("No buildings available.", true);
return;
}
while(true) { while(true) {
wait(5); wait(5);
menu_background_tick(); menu_background_tick();
@@ -221,18 +252,22 @@ void craft_pasture() {
speak_with_history("Pasture must be built in the base.", true); speak_with_history("Pasture must be built in the base.", true);
return; return;
} }
if (world_storages.length() == 0) {
speak_with_history("Storage must be built before a pasture.", true);
return;
}
if (world_pastures.length() > 0) { if (world_pastures.length() > 0) {
speak_with_history("Pasture already built.", true); speak_with_history("Pasture already built.", true);
return; return;
} }
string missing = ""; string missing = "";
if (get_personal_count(ITEM_LOGS) < PASTURE_LOG_COST) missing += PASTURE_LOG_COST + " logs "; if (get_personal_count(ITEM_LOGS) < PASTURE_LOG_COST) missing += PASTURE_LOG_COST + " logs ";
if (get_personal_count(ITEM_VINES) < PASTURE_VINE_COST) missing += PASTURE_VINE_COST + " vines "; if (get_personal_count(ITEM_ROPES) < PASTURE_ROPE_COST) missing += PASTURE_ROPE_COST + " ropes ";
if (missing == "") { if (missing == "") {
simulate_crafting(28); simulate_crafting(28);
add_personal_count(ITEM_LOGS, -PASTURE_LOG_COST); add_personal_count(ITEM_LOGS, -PASTURE_LOG_COST);
add_personal_count(ITEM_VINES, -PASTURE_VINE_COST); add_personal_count(ITEM_ROPES, -PASTURE_ROPE_COST);
add_world_pasture(x); add_world_pasture(x);
speak_with_history("Pasture built.", true); speak_with_history("Pasture built.", true);
} else { } else {
@@ -245,6 +280,10 @@ void craft_stable() {
speak_with_history("Stable must be built in the base.", true); speak_with_history("Stable must be built in the base.", true);
return; return;
} }
if (world_storages.length() == 0) {
speak_with_history("Storage must be built before a stable.", true);
return;
}
if (world_stables.length() > 0) { if (world_stables.length() > 0) {
speak_with_history("Stable already built.", true); speak_with_history("Stable already built.", true);
return; return;

View File

@@ -23,8 +23,10 @@ void run_crafting_menu() {
category_types.insert_last(2); category_types.insert_last(2);
categories.insert_last("Clothing"); categories.insert_last("Clothing");
category_types.insert_last(3); category_types.insert_last(3);
categories.insert_last("Buildings"); if (has_building_options()) {
category_types.insert_last(4); categories.insert_last("Buildings");
category_types.insert_last(4);
}
categories.insert_last("Barricade"); categories.insert_last("Barricade");
category_types.insert_last(5); category_types.insert_last(5);

View File

@@ -38,11 +38,17 @@ void run_base_info_menu() {
if (get_herb_garden_at_base() != null) options.insert_last("Herb garden built"); if (get_herb_garden_at_base() != null) options.insert_last("Herb garden built");
else options.insert_last("Herb garden not built"); else options.insert_last("Herb garden not built");
if (world_pastures.length() > 0) options.insert_last("Pasture built"); if (world_pastures.length() > 0) {
else options.insert_last("Pasture not built"); options.insert_last("Pasture built. Livestock " + livestock_count + " of " + MAX_LIVESTOCK);
} else {
options.insert_last("Pasture not built");
}
if (world_stables.length() > 0) options.insert_last("Stable built"); if (world_stables.length() > 0) {
else options.insert_last("Stable not built"); options.insert_last("Stable built. Horses " + horses_count + " of " + MAX_HORSES);
} else {
options.insert_last("Stable not built");
}
string filter_text = ""; string filter_text = "";
int[] filtered_indices; int[] filtered_indices;
string[] filtered_options; string[] filtered_options;

View File

@@ -608,6 +608,8 @@ void reset_game_state() {
residents_count = 0; residents_count = 0;
undead_residents_count = 0; undead_residents_count = 0;
undead_residents_pending = 0; undead_residents_pending = 0;
horses_count = 0;
livestock_count = 0;
current_hour = 8; current_hour = 8;
current_day = 1; current_day = 1;
@@ -902,6 +904,8 @@ bool save_game_state() {
saveData.set("world_residents_count", residents_count); saveData.set("world_residents_count", residents_count);
saveData.set("world_undead_residents_count", undead_residents_count); saveData.set("world_undead_residents_count", undead_residents_count);
saveData.set("world_undead_residents_pending", undead_residents_pending); saveData.set("world_undead_residents_pending", undead_residents_pending);
saveData.set("world_horses_count", horses_count);
saveData.set("world_livestock_count", livestock_count);
saveData.set("world_expanded_terrain_types", join_string_array(expanded_terrain_types)); saveData.set("world_expanded_terrain_types", join_string_array(expanded_terrain_types));
string[] treeData; string[] treeData;
@@ -1043,6 +1047,12 @@ bool load_game_state_from_file(const string&in filename) {
if (undead_residents_count < 0) undead_residents_count = 0; if (undead_residents_count < 0) undead_residents_count = 0;
undead_residents_pending = int(get_number(saveData, "world_undead_residents_pending", 0)); undead_residents_pending = int(get_number(saveData, "world_undead_residents_pending", 0));
if (undead_residents_pending < 0) undead_residents_pending = 0; if (undead_residents_pending < 0) undead_residents_pending = 0;
horses_count = int(get_number(saveData, "world_horses_count", 0));
livestock_count = int(get_number(saveData, "world_livestock_count", 0));
if (horses_count < 0) horses_count = 0;
if (livestock_count < 0) livestock_count = 0;
if (horses_count > MAX_HORSES) horses_count = MAX_HORSES;
if (livestock_count > MAX_LIVESTOCK) livestock_count = MAX_LIVESTOCK;
if (!barricade_initialized) { if (!barricade_initialized) {
init_barricade(); init_barricade();
} else { } else {

View File

@@ -642,6 +642,7 @@ void update_time() {
attempt_resident_snare_retrieval(); attempt_resident_snare_retrieval();
attempt_resident_fishing(); attempt_resident_fishing();
attempt_resident_fish_smoking(); attempt_resident_fish_smoking();
attempt_livestock_production();
if (current_hour == 6) { if (current_hour == 6) {
save_game_state(); save_game_state();
} }

View File

@@ -55,6 +55,9 @@ class WorldAltar {
} }
WorldAltar@[] world_altars; WorldAltar@[] world_altars;
int horses_count = 0;
int livestock_count = 0;
// Add functions // Add functions
void add_world_firepit(int pos) { void add_world_firepit(int pos) {
WorldFirepit@ fp = WorldFirepit(pos); WorldFirepit@ fp = WorldFirepit(pos);