item flashing
This commit is contained in:
@@ -2,15 +2,10 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Container {
|
pub struct Container {
|
||||||
// Maximum weight this container can hold
|
|
||||||
pub max_weight: u32,
|
pub max_weight: u32,
|
||||||
// Maximum number of items (None = unlimited)
|
|
||||||
pub max_items: Option<u32>,
|
pub max_items: Option<u32>,
|
||||||
// Current weight of contents
|
|
||||||
pub current_weight: u32,
|
pub current_weight: u32,
|
||||||
// List of item entities contained
|
|
||||||
pub contents: Vec<Entity>, // TODO - move away from Entity
|
pub contents: Vec<Entity>, // TODO - move away from Entity
|
||||||
// Whether the container is currently open/accessible
|
|
||||||
pub is_open: bool,
|
pub is_open: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,10 @@ use crate::entities::item::types::ItemType;
|
|||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
#[require(Transform, Visibility)]
|
#[require(Transform, Visibility)]
|
||||||
pub struct Item {
|
pub struct Item {
|
||||||
// How worn/damaged the item is (0-255, where 255 is completely destroyed)
|
|
||||||
pub wear: u8,
|
pub wear: u8,
|
||||||
// The quality of craftsmanship for the base item
|
|
||||||
pub quality: Quality,
|
pub quality: Quality,
|
||||||
// Time until stains fade (in game ticks/turns),
|
|
||||||
pub stain_time: u16,
|
pub stain_time: u16,
|
||||||
// Temperature of the item (for hot/cold items)
|
pub temperature: i16, // Can be negative for cold items
|
||||||
pub temperature: i16, // Can be negative for very cold items
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Item {
|
impl Default for Item {
|
||||||
@@ -52,27 +48,19 @@ impl Item {
|
|||||||
|
|
||||||
let total_weight = base_weight + decoration_weight;
|
let total_weight = base_weight + decoration_weight;
|
||||||
|
|
||||||
// Convert to u32 (multiply by 1000 to get grams if density was in kg/unit)
|
// Convert to u32
|
||||||
(total_weight * 1000.0) as u32
|
(total_weight) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate total value considering all factors
|
|
||||||
pub fn calculate_value(
|
pub fn calculate_value(
|
||||||
&self,
|
&self,
|
||||||
item_type: &ItemType,
|
item_type: &ItemType,
|
||||||
base_material: &Material,
|
base_material: &Material,
|
||||||
decorations: Option<&ItemDecorations>,
|
decorations: Option<&ItemDecorations>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
// Base value from item type and material
|
|
||||||
let base_value = item_type.base_value() + base_material.base_value();
|
let base_value = item_type.base_value() + base_material.base_value();
|
||||||
|
|
||||||
// Apply quality multiplier to base
|
|
||||||
let quality_modified_value = base_value as f32 * self.quality.value_multiplier();
|
let quality_modified_value = base_value as f32 * self.quality.value_multiplier();
|
||||||
|
|
||||||
// Additional value from decorations
|
|
||||||
let decoration_value = decorations.map(|d| d.total_decoration_value()).unwrap_or(0);
|
let decoration_value = decorations.map(|d| d.total_decoration_value()).unwrap_or(0);
|
||||||
|
|
||||||
// Reduce value based on wear
|
|
||||||
let wear_multiplier = (255 - self.wear) as f32 / 255.0;
|
let wear_multiplier = (255 - self.wear) as f32 / 255.0;
|
||||||
|
|
||||||
let total_value = (quality_modified_value + decoration_value as f32) * wear_multiplier;
|
let total_value = (quality_modified_value + decoration_value as f32) * wear_multiplier;
|
||||||
@@ -80,33 +68,27 @@ impl Item {
|
|||||||
total_value as u32
|
total_value as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the item is destroyed due to wear
|
|
||||||
pub fn is_destroyed(&self) -> bool {
|
pub fn is_destroyed(&self) -> bool {
|
||||||
self.wear >= 255
|
self.wear >= 255
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply wear to the item
|
|
||||||
pub fn add_wear(&mut self, wear_amount: u8) {
|
pub fn add_wear(&mut self, wear_amount: u8) {
|
||||||
self.wear = self.wear.saturating_add(wear_amount);
|
self.wear = self.wear.saturating_add(wear_amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if item has any stains
|
|
||||||
pub fn has_stains(&self) -> bool {
|
pub fn has_stains(&self) -> bool {
|
||||||
self.stain_time > 0
|
self.stain_time > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduce stain time (call this periodically to fade stains)
|
|
||||||
pub fn reduce_stain_time(&mut self, amount: u16) {
|
pub fn reduce_stain_time(&mut self, amount: u16) {
|
||||||
self.stain_time = self.stain_time.saturating_sub(amount);
|
self.stain_time = self.stain_time.saturating_sub(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add staining to the item
|
|
||||||
pub fn add_stain(&mut self, duration: u16) {
|
pub fn add_stain(&mut self, duration: u16) {
|
||||||
self.stain_time = self.stain_time.saturating_add(duration);
|
self.stain_time = self.stain_time.saturating_add(duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bundle for creating item entities
|
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct ItemBundle {
|
pub struct ItemBundle {
|
||||||
pub item: Item,
|
pub item: Item,
|
||||||
@@ -118,12 +100,9 @@ pub struct ItemBundle {
|
|||||||
pub sprite: Sprite,
|
pub sprite: Sprite,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Component for items that have names (can be generated or custom)
|
|
||||||
#[derive(Component, Debug, Clone)]
|
#[derive(Component, Debug, Clone)]
|
||||||
pub struct ItemName {
|
pub struct ItemName {
|
||||||
// The base name of the item type
|
|
||||||
pub base_name: String,
|
pub base_name: String,
|
||||||
// Custom name given by player or generated
|
|
||||||
pub custom_name: Option<String>,
|
pub custom_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,25 +123,20 @@ impl ItemName {
|
|||||||
) -> String {
|
) -> String {
|
||||||
let mut parts = Vec::new();
|
let mut parts = Vec::new();
|
||||||
|
|
||||||
// Quality prefix
|
|
||||||
let quality_name = item.quality.display_name();
|
let quality_name = item.quality.display_name();
|
||||||
if !quality_name.is_empty() {
|
if !quality_name.is_empty() {
|
||||||
parts.push(quality_name.to_string());
|
parts.push(quality_name.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base material
|
|
||||||
parts.push(base_material.name());
|
parts.push(base_material.name());
|
||||||
|
|
||||||
// Item name
|
|
||||||
parts.push(self.base_name.clone());
|
parts.push(self.base_name.clone());
|
||||||
|
|
||||||
let mut result = parts.join(" ");
|
let mut result = parts.join(" ");
|
||||||
|
|
||||||
// Add decorations to the description
|
|
||||||
if let Some(decorations) = decorations {
|
if let Some(decorations) = decorations {
|
||||||
let mut decoration_parts = Vec::new();
|
let mut decoration_parts = Vec::new();
|
||||||
|
|
||||||
// Gem encrustings
|
|
||||||
for gem in &decorations.gem_encrustings {
|
for gem in &decorations.gem_encrustings {
|
||||||
let quality_prefix = if gem.quality != Quality::Ordinary {
|
let quality_prefix = if gem.quality != Quality::Ordinary {
|
||||||
format!("{} ", gem.quality.display_name())
|
format!("{} ", gem.quality.display_name())
|
||||||
@@ -176,7 +150,6 @@ impl ItemName {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trim materials
|
|
||||||
for trim in &decorations.trim_materials {
|
for trim in &decorations.trim_materials {
|
||||||
let quality_prefix = if trim.quality != Quality::Ordinary {
|
let quality_prefix = if trim.quality != Quality::Ordinary {
|
||||||
format!("{} ", trim.quality.display_name())
|
format!("{} ", trim.quality.display_name())
|
||||||
@@ -191,7 +164,6 @@ impl ItemName {
|
|||||||
decoration_parts.push(format!("with {} trim", trim_name));
|
decoration_parts.push(format!("with {} trim", trim_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Engravings
|
|
||||||
for engraving in &decorations.engravings {
|
for engraving in &decorations.engravings {
|
||||||
let quality_prefix = if engraving.quality != Quality::Ordinary {
|
let quality_prefix = if engraving.quality != Quality::Ordinary {
|
||||||
format!("{} ", engraving.quality.display_name())
|
format!("{} ", engraving.quality.display_name())
|
||||||
@@ -209,7 +181,6 @@ impl ItemName {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom name
|
|
||||||
if let Some(custom) = &self.custom_name {
|
if let Some(custom) = &self.custom_name {
|
||||||
result = format!("\"{}\" {}", custom, result);
|
result = format!("\"{}\" {}", custom, result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,8 @@ use crate::entities::item::quality::Quality;
|
|||||||
|
|
||||||
#[derive(Component, Debug, Clone)]
|
#[derive(Component, Debug, Clone)]
|
||||||
pub struct ItemDecorations {
|
pub struct ItemDecorations {
|
||||||
// Gems encrusted on the item
|
|
||||||
pub gem_encrustings: Vec<GemEncrusting>,
|
pub gem_encrustings: Vec<GemEncrusting>,
|
||||||
// Metal trim/bands
|
|
||||||
pub trim_materials: Vec<TrimMaterial>,
|
pub trim_materials: Vec<TrimMaterial>,
|
||||||
// Engravings on the item
|
|
||||||
pub engravings: Vec<Engraving>,
|
pub engravings: Vec<Engraving>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +25,6 @@ impl ItemDecorations {
|
|||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate total additional weight from decorations
|
|
||||||
pub fn total_decoration_weight(&self) -> f32 {
|
pub fn total_decoration_weight(&self) -> f32 {
|
||||||
let gem_weight: f32 = self
|
let gem_weight: f32 = self
|
||||||
.gem_encrustings
|
.gem_encrustings
|
||||||
@@ -42,11 +38,9 @@ impl ItemDecorations {
|
|||||||
.map(|trim| trim.material.density() * trim.amount)
|
.map(|trim| trim.material.density() * trim.amount)
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
// Engravings don't add weight, they remove material
|
|
||||||
gem_weight + trim_weight
|
gem_weight + trim_weight
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate total additional value from decorations
|
|
||||||
pub fn total_decoration_value(&self) -> u32 {
|
pub fn total_decoration_value(&self) -> u32 {
|
||||||
let gem_value: f32 = self
|
let gem_value: f32 = self
|
||||||
.gem_encrustings
|
.gem_encrustings
|
||||||
@@ -97,26 +91,26 @@ impl ItemDecorations {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct GemEncrusting {
|
pub struct GemEncrusting {
|
||||||
pub material: Material, // Should be a gem, but using material to gain access to its wider functions
|
pub material: Material, // Should be a gem, but using material to gain access to its wider functions
|
||||||
pub size: f32, // Size of the gem (affects weight and value)
|
pub size: f32,
|
||||||
pub quality: Quality, // Quality of the gem cut
|
pub quality: Quality,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TrimMaterial {
|
pub struct TrimMaterial {
|
||||||
pub material: Material, // Usually metal for bands/trim
|
pub material: Material, // Usually metal for bands/trim
|
||||||
pub amount: f32, // Amount of material used
|
pub amount: f32,
|
||||||
pub quality: Quality, // Quality of the trim work
|
pub quality: Quality,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Engraving {
|
pub struct Engraving {
|
||||||
pub subject: String, // What the engraving depicts
|
pub subject: String,
|
||||||
pub quality: Quality, // Quality of the engraving
|
pub quality: Quality,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Engraving {
|
impl Engraving {
|
||||||
pub fn base_value(&self) -> f32 {
|
pub fn base_value(&self) -> f32 {
|
||||||
// Base value for engravings (they're pure craftsmanship)
|
// Base value for engravings (they're pure craftsmanship so a static value is fine)
|
||||||
20.0
|
20.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub enum Material {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Material {
|
impl Material {
|
||||||
// Weight per unit volume (arbitrary units - adjust as needed)
|
// Weight per unit volume (arbitrary units - TODO: Adjust later)
|
||||||
pub fn density(&self) -> f32 {
|
pub fn density(&self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
Material::NA => 1.0,
|
Material::NA => 1.0,
|
||||||
|
|||||||
@@ -6,18 +6,15 @@ use crate::entities::item::Item;
|
|||||||
|
|
||||||
#[derive(Component, Debug)]
|
#[derive(Component, Debug)]
|
||||||
pub struct Perishable {
|
pub struct Perishable {
|
||||||
// How much the item has decayed (0-255)
|
|
||||||
pub decay: u8,
|
pub decay: u8,
|
||||||
// How fast this item decays per tick
|
|
||||||
pub decay_rate: u8,
|
pub decay_rate: u8,
|
||||||
// What happens when fully decayed
|
|
||||||
pub decay_result: DecayResult,
|
pub decay_result: DecayResult,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum DecayResult {
|
pub enum DecayResult {
|
||||||
Disappear,
|
Disappear,
|
||||||
Transform(ItemType, Material), // Transform into another item type with different material
|
Transform(ItemType, Material), // Transform into another item type with different material (fish -> rotten fish)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decay_system(
|
pub fn decay_system(
|
||||||
@@ -26,18 +23,14 @@ pub fn decay_system(
|
|||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
for (entity, mut perishable, item, item_type, base_material) in perishable_items.iter_mut() {
|
for (entity, mut perishable, item, item_type, base_material) in perishable_items.iter_mut() {
|
||||||
// Simple decay - you might want to make this more sophisticated
|
|
||||||
if time.elapsed_secs_f64() as u32 % 60 == 0 {
|
if time.elapsed_secs_f64() as u32 % 60 == 0 {
|
||||||
// Decay every 60 seconds
|
|
||||||
perishable.decay = perishable.decay.saturating_add(perishable.decay_rate);
|
perishable.decay = perishable.decay.saturating_add(perishable.decay_rate);
|
||||||
|
|
||||||
if perishable.decay >= 255 {
|
if perishable.decay >= 255 {
|
||||||
match &perishable.decay_result {
|
match &perishable.decay_result {
|
||||||
DecayResult::Disappear => {
|
DecayResult::Disappear => {
|
||||||
commands.entity(entity).despawn();
|
commands.entity(entity).despawn();
|
||||||
}
|
}
|
||||||
DecayResult::Transform(new_item_type, new_material) => {
|
DecayResult::Transform(new_item_type, new_material) => {
|
||||||
// Transform the item
|
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(new_item_type.clone())
|
.insert(new_item_type.clone())
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use crate::entities::item::{Item, ItemBundle, ItemDecorations, ItemType, Material, Quality};
|
use crate::entities::item::{Item, ItemBundle, ItemDecorations, ItemType, Material, Quality};
|
||||||
|
use crate::world::tiles::tilemap;
|
||||||
use crate::world::VisibleGameEntity;
|
use crate::world::VisibleGameEntity;
|
||||||
|
|
||||||
// Enum for misc item prefabs
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum MiscPrefab {
|
pub enum MiscPrefab {
|
||||||
RawMeat,
|
RawMeat,
|
||||||
@@ -12,11 +12,13 @@ pub enum MiscPrefab {
|
|||||||
|
|
||||||
// Spawns a misc prefab at a given position.
|
// Spawns a misc prefab at a given position.
|
||||||
// These are all likely temporary to speed up development but will be replaced by semi-custom items everywhere.
|
// These are all likely temporary to speed up development but will be replaced by semi-custom items everywhere.
|
||||||
|
// As well as acting as demonstration of how to spawn items for the future.
|
||||||
pub fn spawn_prefab(
|
pub fn spawn_prefab(
|
||||||
commands: &mut Commands,
|
commands: &mut Commands,
|
||||||
asset_server: &Res<AssetServer>,
|
asset_server: &Res<AssetServer>,
|
||||||
prefab: MiscPrefab,
|
prefab: MiscPrefab,
|
||||||
position: Vec3,
|
position: Vec3,
|
||||||
|
tilemap: &mut ResMut<tilemap::TileMap>,
|
||||||
) -> Entity {
|
) -> Entity {
|
||||||
match prefab {
|
match prefab {
|
||||||
MiscPrefab::RawMeat => {
|
MiscPrefab::RawMeat => {
|
||||||
@@ -37,7 +39,16 @@ pub fn spawn_prefab(
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.id();
|
.id();
|
||||||
commands.entity(meat).insert(VisibleGameEntity).id()
|
let mut items = tilemap
|
||||||
|
.item_tiles
|
||||||
|
.get(&position.as_ivec3())
|
||||||
|
.unwrap_or(&Vec::new())
|
||||||
|
.clone();
|
||||||
|
items.push(meat.index());
|
||||||
|
tilemap
|
||||||
|
.item_tiles
|
||||||
|
.insert(position.as_ivec3(), items.clone());
|
||||||
|
return commands.entity(meat).insert(VisibleGameEntity).id();
|
||||||
}
|
}
|
||||||
MiscPrefab::Coin => {
|
MiscPrefab::Coin => {
|
||||||
let coin = commands
|
let coin = commands
|
||||||
@@ -57,6 +68,15 @@ pub fn spawn_prefab(
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.id();
|
.id();
|
||||||
|
let mut items = tilemap
|
||||||
|
.item_tiles
|
||||||
|
.get(&position.as_ivec3())
|
||||||
|
.unwrap_or(&Vec::new())
|
||||||
|
.clone();
|
||||||
|
items.push(coin.index());
|
||||||
|
tilemap
|
||||||
|
.item_tiles
|
||||||
|
.insert(position.as_ivec3(), items.clone());
|
||||||
commands.entity(coin).insert(VisibleGameEntity).id()
|
commands.entity(coin).insert(VisibleGameEntity).id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ pub enum Quality {
|
|||||||
Superior = 3,
|
Superior = 3,
|
||||||
Exceptional = 4,
|
Exceptional = 4,
|
||||||
Masterwork = 5,
|
Masterwork = 5,
|
||||||
// Special artifact quality
|
// Special artifact quality (created through moments of genius or madness)
|
||||||
Artifact = 10,
|
Artifact = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ use crate::entities::item::Item;
|
|||||||
use crate::entities::item::ItemBundle;
|
use crate::entities::item::ItemBundle;
|
||||||
use crate::entities::item::ItemName;
|
use crate::entities::item::ItemName;
|
||||||
|
|
||||||
// System to reduce stain time over time
|
|
||||||
pub fn stain_fade_system(time: Res<Time>, mut items: Query<&mut Item>) {
|
pub fn stain_fade_system(time: Res<Time>, mut items: Query<&mut Item>) {
|
||||||
// Fade stains every 10 seconds
|
|
||||||
if time.elapsed_secs_f64() as u32 % 10 == 0 {
|
if time.elapsed_secs_f64() as u32 % 10 == 0 {
|
||||||
for mut item in items.iter_mut() {
|
for mut item in items.iter_mut() {
|
||||||
item.reduce_stain_time(1);
|
item.reduce_stain_time(1);
|
||||||
@@ -18,7 +16,7 @@ pub fn stain_fade_system(time: Res<Time>, mut items: Query<&mut Item>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to create a decorated item
|
// Helper function to create a decorated item (DEMO ONLY)
|
||||||
pub fn create_decorated_item(
|
pub fn create_decorated_item(
|
||||||
commands: &mut Commands,
|
commands: &mut Commands,
|
||||||
item_type: ItemType,
|
item_type: ItemType,
|
||||||
|
|||||||
@@ -2,22 +2,15 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
#[derive(Component, Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Component, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum ItemType {
|
pub enum ItemType {
|
||||||
// Weapons
|
|
||||||
Weapon(WeaponType),
|
Weapon(WeaponType),
|
||||||
// Armor/Clothing
|
|
||||||
Armor(ArmorType),
|
Armor(ArmorType),
|
||||||
// Tools
|
|
||||||
Tool(ToolType),
|
Tool(ToolType),
|
||||||
// Consumables
|
|
||||||
Food(FoodType),
|
Food(FoodType),
|
||||||
Drink(DrinkType),
|
Drink(DrinkType),
|
||||||
Medicine,
|
Medicine,
|
||||||
// Crafting materials
|
|
||||||
RawMaterial,
|
RawMaterial,
|
||||||
// Trade goods
|
|
||||||
Gem,
|
Gem,
|
||||||
Coin,
|
Coin,
|
||||||
// Misc
|
|
||||||
Container,
|
Container,
|
||||||
Book,
|
Book,
|
||||||
Toy,
|
Toy,
|
||||||
|
|||||||
@@ -1,24 +1,20 @@
|
|||||||
use crate::constants::TILE_SIZE;
|
use crate::constants::TILE_SIZE;
|
||||||
use crate::constants::*;
|
use crate::constants::*;
|
||||||
use crate::entities::item::{
|
use crate::entities::item::{spawn_prefab, MiscPrefab};
|
||||||
create_decorated_item, spawn_prefab, FoodType, Item, ItemBundle, ItemDecorations, ItemType,
|
|
||||||
Material, MiscPrefab, Quality, WoodType,
|
|
||||||
};
|
|
||||||
use crate::entities::shared_components::Ambulatory;
|
use crate::entities::shared_components::Ambulatory;
|
||||||
|
use crate::world::tiles::tilemap;
|
||||||
use crate::world::VisibleGameEntity;
|
use crate::world::VisibleGameEntity;
|
||||||
use bevy::ecs::spawn;
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rand::prelude::*;
|
use bevy_rand::prelude::*;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
// Pig bundle
|
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct Pig {
|
pub struct Pig {
|
||||||
ambulatory: Ambulatory,
|
ambulatory: Ambulatory,
|
||||||
sprite: Sprite,
|
sprite: Sprite,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
visibility: Visibility,
|
visibility: Visibility,
|
||||||
drop_timer: PigDropTimer, // NEW
|
drop_timer: PigDropTimer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pig {
|
impl Pig {
|
||||||
@@ -43,11 +39,9 @@ impl Pig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer component for pigs dropping items
|
|
||||||
#[derive(Component, Deref, DerefMut)]
|
#[derive(Component, Deref, DerefMut)]
|
||||||
pub struct PigDropTimer(pub Timer);
|
pub struct PigDropTimer(pub Timer);
|
||||||
|
|
||||||
// Spawn a handful of pigs
|
|
||||||
pub fn spawn_pigs(
|
pub fn spawn_pigs(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
@@ -70,12 +64,12 @@ pub fn spawn_pigs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// System: make pigs drop items every 5 seconds
|
|
||||||
pub fn pig_drop_system(
|
pub fn pig_drop_system(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut pigs: Query<(&mut PigDropTimer, &Transform)>,
|
mut pigs: Query<(&mut PigDropTimer, &Transform)>,
|
||||||
|
mut tilemap: ResMut<tilemap::TileMap>,
|
||||||
) {
|
) {
|
||||||
for (mut timer, transform) in &mut pigs {
|
for (mut timer, transform) in &mut pigs {
|
||||||
timer.tick(time.delta());
|
timer.tick(time.delta());
|
||||||
@@ -87,6 +81,7 @@ pub fn pig_drop_system(
|
|||||||
&asset_server,
|
&asset_server,
|
||||||
MiscPrefab::RawMeat,
|
MiscPrefab::RawMeat,
|
||||||
transform.translation,
|
transform.translation,
|
||||||
|
&mut tilemap,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ pub fn spawn_rabbits(
|
|||||||
mut rng_q: Query<&mut Entropy<WyRand>, With<Global>>,
|
mut rng_q: Query<&mut Entropy<WyRand>, With<Global>>,
|
||||||
) {
|
) {
|
||||||
if let Ok(mut rng) = rng_q.single_mut() {
|
if let Ok(mut rng) = rng_q.single_mut() {
|
||||||
// Spawn a handful of rabbits
|
|
||||||
for _ in 0..15 {
|
for _ in 0..15 {
|
||||||
let rab = commands
|
let rab = commands
|
||||||
.spawn(Rabbit::new(
|
.spawn(Rabbit::new(
|
||||||
|
|||||||
+6
-1
@@ -1,7 +1,10 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rand::prelude::*;
|
use bevy_rand::prelude::*;
|
||||||
|
|
||||||
use crate::entities::livestock::pig::pig_drop_system;
|
use crate::{
|
||||||
|
entities::livestock::pig::pig_drop_system,
|
||||||
|
world::tiles::{item_tile_management_system, ItemRotationTimer},
|
||||||
|
};
|
||||||
|
|
||||||
mod camera;
|
mod camera;
|
||||||
mod constants;
|
mod constants;
|
||||||
@@ -56,5 +59,7 @@ fn main() {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_systems(Update, pig_drop_system)
|
.add_systems(Update, pig_drop_system)
|
||||||
|
.insert_resource(ItemRotationTimer::default())
|
||||||
|
.add_systems(Update, item_tile_management_system)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,98 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_platform::collections::hash_map::HashMap;
|
use bevy_platform::collections::hash_map::HashMap;
|
||||||
|
|
||||||
|
use crate::{entities::item::Item, game};
|
||||||
|
|
||||||
#[derive(Resource, Default, Clone)]
|
#[derive(Resource, Default, Clone)]
|
||||||
pub struct TileMap {
|
pub struct TileMap {
|
||||||
pub floor_tiles: HashMap<IVec3, (i32, bool, bool, bool, i32, [u32; 8])>, //id, canStandIn, canStandOn, visiblyTransparent, astar_weight, visible_range
|
pub floor_tiles: HashMap<IVec3, (i32, bool, bool, bool, i32, [u32; 8])>, //id, canStandIn, canStandOn, visiblyTransparent, astar_weight, visible_range
|
||||||
pub fixture_tiles: HashMap<IVec3, (i32, bool, bool, [u32; 8])>, // id, canStandIn, canStandOn, visible_range
|
pub fixture_tiles: HashMap<IVec3, (i32, bool, bool, [u32; 8])>, // id, canStandIn, canStandOn, visible_range
|
||||||
|
pub item_tiles: HashMap<IVec3, Vec<u32>>, // Entity.id's of items on this tile
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
pub struct ItemRotationTimer {
|
||||||
|
timer: Timer,
|
||||||
|
current_indices: HashMap<IVec3, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ItemRotationTimer {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
timer: Timer::from_seconds(0.4f32, TimerMode::Repeating),
|
||||||
|
current_indices: HashMap::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn item_tile_management_system(
|
||||||
|
time: Res<Time>,
|
||||||
|
mut tilemap: ResMut<TileMap>,
|
||||||
|
mut rotation_timer: ResMut<ItemRotationTimer>,
|
||||||
|
z_index: Res<game::ZIndex>,
|
||||||
|
mut visibility_query: Query<&mut Visibility, With<Item>>,
|
||||||
|
) {
|
||||||
|
println!(
|
||||||
|
"{} items accross {} tiles",
|
||||||
|
visibility_query.iter().count(),
|
||||||
|
tilemap.item_tiles.len()
|
||||||
|
);
|
||||||
|
rotation_timer.timer.tick(time.delta());
|
||||||
|
|
||||||
|
let mut tiles_to_remove = Vec::new();
|
||||||
|
let mut tiles_with_items = Vec::new();
|
||||||
|
|
||||||
|
for (position, items) in tilemap.item_tiles.iter() {
|
||||||
|
if items.is_empty() {
|
||||||
|
tiles_to_remove.push(*position);
|
||||||
|
} else {
|
||||||
|
tiles_with_items.push((*position, items.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for position in tiles_to_remove {
|
||||||
|
tilemap.item_tiles.remove(&position);
|
||||||
|
rotation_timer.current_indices.remove(&position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if rotation_timer.timer.just_finished() {
|
||||||
|
for (position, items) in tiles_with_items {
|
||||||
|
if position.z > z_index.0 as i32 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if items.len() <= 1 {
|
||||||
|
if let Some(&entity_id) = items.first() {
|
||||||
|
let entity = Entity::from_raw(entity_id);
|
||||||
|
if let Ok(mut visibility) = visibility_query.get_mut(entity) {
|
||||||
|
*visibility = Visibility::Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_index = rotation_timer
|
||||||
|
.current_indices
|
||||||
|
.get(&position)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
if let Some(¤t_entity_id) = items.get(current_index) {
|
||||||
|
let current_entity = Entity::from_raw(current_entity_id);
|
||||||
|
if let Ok(mut visibility) = visibility_query.get_mut(current_entity) {
|
||||||
|
*visibility = Visibility::Hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let next_index = (current_index + 1) % items.len();
|
||||||
|
|
||||||
|
if let Some(&next_entity_id) = items.get(next_index) {
|
||||||
|
let next_entity = Entity::from_raw(next_entity_id);
|
||||||
|
if let Ok(mut visibility) = visibility_query.get_mut(next_entity) {
|
||||||
|
*visibility = Visibility::Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rotation_timer.current_indices.insert(position, next_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user