Residents now handle snares, retrieval and resetting. Still a chance game can escape. Residents are not as efficient at handling this than the player, but it is helpful. Meat and skins, anything harvested from butchering is stored.
This commit is contained in:
@@ -211,6 +211,163 @@ void process_daily_weapon_breakage() {
|
||||
}
|
||||
}
|
||||
|
||||
// Resident snare retrieval
|
||||
void attempt_resident_snare_retrieval() {
|
||||
// Only during daytime
|
||||
if (!is_daytime) return;
|
||||
|
||||
// Need residents
|
||||
if (residents_count <= 0) return;
|
||||
|
||||
// Need food in storage (same limitation as other resident tasks)
|
||||
if (get_storage_count(ITEM_MEAT) <= 0) return;
|
||||
|
||||
// Check each snare that has a catch
|
||||
for (int i = int(world_snares.length()) - 1; i >= 0; i--) {
|
||||
WorldSnare@ snare = world_snares[i];
|
||||
if (!snare.has_catch) continue;
|
||||
if (!snare.active) continue;
|
||||
|
||||
// Each snare has a chance to be checked by a resident this hour
|
||||
if (random(1, 100) > RESIDENT_SNARE_CHECK_CHANCE) continue;
|
||||
|
||||
// Small chance the game escapes during retrieval (like normal)
|
||||
if (random(1, 100) <= RESIDENT_SNARE_ESCAPE_CHANCE) {
|
||||
notify("A " + snare.catch_type + " escaped while a resident checked the snare at x " + snare.position + ".");
|
||||
remove_snare_at(snare.position);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if storage has room for small game
|
||||
if (get_storage_count(ITEM_SMALL_GAME) >= BASE_STORAGE_MAX) continue;
|
||||
|
||||
// Retrieve the game
|
||||
string game_type = snare.catch_type;
|
||||
int pos = snare.position;
|
||||
|
||||
// Add game to storage
|
||||
add_storage_count(ITEM_SMALL_GAME, 1);
|
||||
storage_small_game_types.insert_last(game_type);
|
||||
|
||||
// Reset the snare in place (resident empties it and resets for more game)
|
||||
snare.has_catch = false;
|
||||
snare.catch_type = "";
|
||||
snare.catch_chance = 5;
|
||||
snare.escape_chance = 5;
|
||||
snare.minute_timer.restart();
|
||||
|
||||
// Notify if player is in base
|
||||
if (x <= BASE_END) {
|
||||
speak_with_history("Resident retrieved " + game_type + " from snare at x " + pos + " and reset it.", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resident butchering - processes one game per day from storage
|
||||
void attempt_resident_butchering() {
|
||||
// Need residents
|
||||
if (residents_count <= 0) return;
|
||||
|
||||
// Need food in storage (same limitation as other resident tasks)
|
||||
if (get_storage_count(ITEM_MEAT) <= 0) return;
|
||||
|
||||
// Need game in storage
|
||||
if (get_storage_count(ITEM_SMALL_GAME) <= 0 && get_storage_count(ITEM_BOAR_CARCASSES) <= 0) return;
|
||||
|
||||
// Need a knife in storage
|
||||
if (get_storage_count(ITEM_KNIVES) <= 0) return;
|
||||
|
||||
// Need a fire in base
|
||||
bool has_fire = false;
|
||||
for (uint i = 0; i < world_fires.length(); i++) {
|
||||
if (world_fires[i].position <= BASE_END && world_fires[i].is_burning()) {
|
||||
has_fire = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_fire) return;
|
||||
|
||||
// Determine what to butcher (prioritize boar carcasses)
|
||||
string game_type = "";
|
||||
bool is_boar = false;
|
||||
|
||||
if (get_storage_count(ITEM_BOAR_CARCASSES) > 0) {
|
||||
game_type = "boar carcass";
|
||||
is_boar = true;
|
||||
} else if (storage_small_game_types.length() > 0) {
|
||||
game_type = storage_small_game_types[0];
|
||||
} else {
|
||||
game_type = "small game";
|
||||
}
|
||||
|
||||
// Calculate outputs and check storage capacity
|
||||
int meat_yield = 0;
|
||||
int skins_yield = 0;
|
||||
int feathers_yield = 0;
|
||||
int down_yield = 0;
|
||||
int sinew_yield = 0;
|
||||
|
||||
if (game_type == "goose") {
|
||||
meat_yield = 1;
|
||||
feathers_yield = random(3, 6);
|
||||
down_yield = random(1, 3);
|
||||
} else if (is_boar) {
|
||||
meat_yield = random(2, 3);
|
||||
skins_yield = 3;
|
||||
sinew_yield = 2;
|
||||
} else {
|
||||
meat_yield = 1;
|
||||
skins_yield = 1;
|
||||
}
|
||||
|
||||
// Check storage capacity for outputs
|
||||
if (meat_yield > 0 && get_storage_count(ITEM_MEAT) + meat_yield > BASE_STORAGE_MAX) return;
|
||||
if (skins_yield > 0 && get_storage_count(ITEM_SKINS) + skins_yield > BASE_STORAGE_MAX) return;
|
||||
if (feathers_yield > 0 && get_storage_count(ITEM_FEATHERS) + feathers_yield > BASE_STORAGE_MAX) return;
|
||||
if (down_yield > 0 && get_storage_count(ITEM_DOWN) + down_yield > BASE_STORAGE_MAX) return;
|
||||
if (sinew_yield > 0 && get_storage_count(ITEM_SINEW) + sinew_yield > BASE_STORAGE_MAX) return;
|
||||
|
||||
// Consume the game
|
||||
if (is_boar) {
|
||||
add_storage_count(ITEM_BOAR_CARCASSES, -1);
|
||||
} else {
|
||||
add_storage_count(ITEM_SMALL_GAME, -1);
|
||||
if (storage_small_game_types.length() > 0) {
|
||||
storage_small_game_types.remove_at(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Add outputs to storage
|
||||
if (meat_yield > 0) add_storage_count(ITEM_MEAT, meat_yield);
|
||||
if (skins_yield > 0) add_storage_count(ITEM_SKINS, skins_yield);
|
||||
if (feathers_yield > 0) add_storage_count(ITEM_FEATHERS, feathers_yield);
|
||||
if (down_yield > 0) add_storage_count(ITEM_DOWN, down_yield);
|
||||
if (sinew_yield > 0) add_storage_count(ITEM_SINEW, sinew_yield);
|
||||
|
||||
// Build notification message
|
||||
string result = "Resident butchered " + game_type + ". Added ";
|
||||
string[] outputs;
|
||||
if (meat_yield > 0) outputs.insert_last(meat_yield + " meat");
|
||||
if (skins_yield > 0) outputs.insert_last(skins_yield + " skins");
|
||||
if (feathers_yield > 0) outputs.insert_last(feathers_yield + " feathers");
|
||||
if (down_yield > 0) outputs.insert_last(down_yield + " down");
|
||||
if (sinew_yield > 0) outputs.insert_last(sinew_yield + " sinew");
|
||||
|
||||
for (uint i = 0; i < outputs.length(); i++) {
|
||||
if (i > 0) {
|
||||
if (i == outputs.length() - 1) {
|
||||
result += " and ";
|
||||
} else {
|
||||
result += ", ";
|
||||
}
|
||||
}
|
||||
result += outputs[i];
|
||||
}
|
||||
result += " to storage.";
|
||||
|
||||
notify(result);
|
||||
}
|
||||
|
||||
// Resident resource collection
|
||||
|
||||
void attempt_resident_collection() {
|
||||
|
||||
@@ -170,6 +170,8 @@ const int RESIDENT_WEAPON_BREAK_CHANCE = 10;
|
||||
const int RESIDENT_SPEAR_DAMAGE = 2;
|
||||
const int RESIDENT_SLING_DAMAGE_MIN = 3;
|
||||
const int RESIDENT_SLING_DAMAGE_MAX = 5;
|
||||
const int RESIDENT_SNARE_ESCAPE_CHANCE = 5; // 5% chance game escapes when resident retrieves
|
||||
const int RESIDENT_SNARE_CHECK_CHANCE = 15; // 15% chance per hour to check snares
|
||||
|
||||
// Goose settings
|
||||
const int GOOSE_HEALTH = 1;
|
||||
|
||||
@@ -393,6 +393,7 @@ void update_time() {
|
||||
if (current_hour == 6) {
|
||||
process_daily_weapon_breakage();
|
||||
attempt_daily_quest();
|
||||
attempt_resident_butchering();
|
||||
}
|
||||
attempt_daily_invasion();
|
||||
keep_base_fires_fed();
|
||||
@@ -403,6 +404,7 @@ void update_time() {
|
||||
attempt_blessing();
|
||||
check_weather_transition();
|
||||
attempt_resident_collection();
|
||||
attempt_resident_snare_retrieval();
|
||||
if (current_hour == 6) {
|
||||
save_game_state();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user