refactor: extract generic digging system, drop tables, remove debug code

- New src/entities/item/drop_table.rs: DropEntry (chance, min/max count,
  pseudo-RNG roll) + DropTable wrapper. grass=5% coin 1-2, rock=10% coin 1,
  dirt/air=none.
- New src/entities/shared_systems/digging.rs: Digger component + dig_system.
  Any entity with Digger digs the tile below on its interval. Replaces
  rabbit_dig_system/rabbit_fall_debug_system/RabbitDigTimer/RabbitFallDebug.
- New TileMap::dig_floor: remove_floor + insert air. Used by dig_system.
- FloorTileData: added drop_table field. Lost Copy derive (Vec field).
  Updated all 6 terrain.rs call sites with per-tile drop tables.
- Pig: removed PigDropTimer + pig_drop_system. Drops were debug placeholder.
  TODO added for future loot-on-death/butcher system.
- Rabbit: removed all debug components/systems. Now uses Digger::new(5.0).
- main.rs: removed rabbit_dig_system/rabbit_fall_debug_system/pig_drop_system,
  added shared_systems::digging::dig_system.
This commit is contained in:
2026-03-21 15:40:34 +00:00
parent 1a170ea9a9
commit ce3746366c
9 changed files with 238 additions and 301 deletions
+73
View File
@@ -0,0 +1,73 @@
use crate::entities::item::prefabs::misc::misc_prefabs::MiscPrefab;
use bevy::prelude::*;
#[derive(Clone, Debug)]
pub struct DropEntry {
pub prefab: MiscPrefab,
pub chance: f32,
pub min_count: u32,
pub max_count: u32,
}
impl DropEntry {
pub fn always(prefab: MiscPrefab) -> Self {
Self {
prefab,
chance: 1.0,
min_count: 1,
max_count: 1,
}
}
pub fn chance(prefab: MiscPrefab, chance: f32, min_count: u32, max_count: u32) -> Self {
Self {
prefab,
chance,
min_count,
max_count,
}
}
pub fn roll(&self, pos: IVec3) -> u32 {
if self.chance < 1.0 {
let r = pseudo_rand_f32(pos);
if r >= self.chance {
return 0;
}
}
pseudo_rand_u32(pos) % (self.max_count - self.min_count + 1) + self.min_count
}
}
#[derive(Clone, Debug, Default)]
pub struct DropTable(pub Vec<DropEntry>);
impl DropTable {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
fn hash3(pos: IVec3) -> u32 {
let mut h: u32 = 0;
h = h.wrapping_mul(374761393).wrapping_add(pos.x as u32);
h = h.wrapping_mul(374761393).wrapping_add(pos.y as u32);
h = h.wrapping_mul(374761393).wrapping_add(pos.z as u32);
h ^= h >> 13;
h = h.wrapping_mul(1274126177);
h ^= h >> 16;
h
}
fn pseudo_rand_u32(pos: IVec3) -> u32 {
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos() as u32;
hash3(pos) ^ timestamp
}
fn pseudo_rand_f32(pos: IVec3) -> f32 {
let val = pseudo_rand_u32(pos);
(val as f32) / (u32::MAX as f32)
}