Weather system added, mostly decoration. Some tweaks to residents. Moved altar to its own menu, s for sacrifice. You can no longer burn incense outside the base.
This commit is contained in:
@@ -76,16 +76,78 @@ int perform_resident_defense() {
|
||||
int damage = 0;
|
||||
if (useSpear && storage_spears > 0) {
|
||||
damage = RESIDENT_SPEAR_DAMAGE;
|
||||
play_1d_with_volume_step("sounds/weapons/spear_swing.ogg", x, BASE_END + 1, false, 3.0);
|
||||
// Weapons don't get consumed on use - they break via daily breakage check
|
||||
// Just play the sound
|
||||
play_1d_with_volume_step("sounds/weapons/spear_swing.ogg", x, BASE_END + 1, false, RESIDENT_DEFENSE_VOLUME_STEP);
|
||||
} else if (storage_slings > 0 && storage_stones > 0) {
|
||||
damage = random(RESIDENT_SLING_DAMAGE_MIN, RESIDENT_SLING_DAMAGE_MAX);
|
||||
// Slings use stones as ammo, so consume a stone
|
||||
storage_stones--;
|
||||
play_1d_with_volume_step("sounds/weapons/sling_hit.ogg", x, BASE_END + 1, false, 3.0);
|
||||
play_1d_with_volume_step("sounds/weapons/sling_hit.ogg", x, BASE_END + 1, false, RESIDENT_DEFENSE_VOLUME_STEP);
|
||||
}
|
||||
|
||||
return damage;
|
||||
}
|
||||
|
||||
// Proactive resident sling defense
|
||||
timer resident_sling_timer;
|
||||
const int RESIDENT_SLING_COOLDOWN = 4000; // 4 seconds between shots
|
||||
|
||||
void attempt_resident_sling_defense() {
|
||||
// Only if residents exist and have slings with stones
|
||||
if (residents_count <= 0) return;
|
||||
if (storage_slings <= 0 || storage_stones <= 0) return;
|
||||
|
||||
// Cooldown between shots
|
||||
if (resident_sling_timer.elapsed < RESIDENT_SLING_COOLDOWN) return;
|
||||
|
||||
// Find nearest enemy within sling range
|
||||
int nearestDistance = SLING_RANGE + 1;
|
||||
int targetPos = -1;
|
||||
bool targetIsBandit = false;
|
||||
|
||||
int sling_origin = BASE_END;
|
||||
|
||||
// Check zombies
|
||||
for (uint i = 0; i < zombies.length(); i++) {
|
||||
int dist = abs(zombies[i].position - sling_origin);
|
||||
if (dist > 0 && dist <= SLING_RANGE && dist < nearestDistance) {
|
||||
nearestDistance = dist;
|
||||
targetPos = zombies[i].position;
|
||||
targetIsBandit = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check bandits
|
||||
for (uint i = 0; i < bandits.length(); i++) {
|
||||
int dist = abs(bandits[i].position - sling_origin);
|
||||
if (dist > 0 && dist <= SLING_RANGE && dist < nearestDistance) {
|
||||
nearestDistance = dist;
|
||||
targetPos = bandits[i].position;
|
||||
targetIsBandit = true;
|
||||
}
|
||||
}
|
||||
|
||||
// No targets in range
|
||||
if (targetPos == -1) return;
|
||||
|
||||
// Shoot!
|
||||
resident_sling_timer.restart();
|
||||
storage_stones--;
|
||||
|
||||
int damage = random(RESIDENT_SLING_DAMAGE_MIN, RESIDENT_SLING_DAMAGE_MAX);
|
||||
play_1d_with_volume_step("sounds/weapons/sling_hit.ogg", x, targetPos, false, RESIDENT_DEFENSE_VOLUME_STEP);
|
||||
|
||||
if (targetIsBandit) {
|
||||
damage_bandit_at(targetPos, damage);
|
||||
} else {
|
||||
damage_zombie_at(targetPos, damage);
|
||||
}
|
||||
|
||||
// Play hit sound on enemy
|
||||
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", x, targetPos, ZOMBIE_SOUND_VOLUME_STEP);
|
||||
}
|
||||
|
||||
void process_daily_weapon_breakage() {
|
||||
if (residents_count <= 0) return;
|
||||
|
||||
@@ -149,3 +211,53 @@ void process_daily_weapon_breakage() {
|
||||
notify(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// Resident resource collection
|
||||
const int RESIDENT_COLLECTION_CHANCE = 10; // 10% chance per basket per hour
|
||||
|
||||
void attempt_resident_collection() {
|
||||
// Only during daytime
|
||||
if (!is_daytime) return;
|
||||
|
||||
// Need residents
|
||||
if (residents_count <= 0) return;
|
||||
|
||||
// Need baskets in storage to enable collection
|
||||
if (storage_reed_baskets <= 0) return;
|
||||
|
||||
// Number of residents who can collect = min(residents, baskets)
|
||||
int active_collectors = (residents_count < storage_reed_baskets) ? residents_count : storage_reed_baskets;
|
||||
|
||||
// Each active collector has a 10% chance to collect something
|
||||
for (int i = 0; i < active_collectors; i++) {
|
||||
if (random(1, 100) > RESIDENT_COLLECTION_CHANCE) continue;
|
||||
|
||||
// Determine what to collect (weighted random)
|
||||
// Sticks and vines more common, logs and stones less common
|
||||
int roll = random(1, 100);
|
||||
string item_name = "";
|
||||
|
||||
if (roll <= 40) {
|
||||
// 40% chance - stick
|
||||
storage_sticks++;
|
||||
item_name = "stick";
|
||||
} else if (roll <= 70) {
|
||||
// 30% chance - vine
|
||||
storage_vines++;
|
||||
item_name = "vine";
|
||||
} else if (roll <= 85) {
|
||||
// 15% chance - stone
|
||||
storage_stones++;
|
||||
item_name = "stone";
|
||||
} else {
|
||||
// 15% chance - log
|
||||
storage_logs++;
|
||||
item_name = "log";
|
||||
}
|
||||
|
||||
// Announce only if player is in base
|
||||
if (x <= BASE_END) {
|
||||
screen_reader_speak("Resident added " + item_name + " to storage.", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user