From 833bd2c30a0c33dddaed87a3681ffb8815f5260f Mon Sep 17 00:00:00 2001 From: Louis Capitanchik <contact@louiscap.co> Date: Sun, 11 Dec 2022 05:35:36 +0000 Subject: [PATCH] Rumours at the tavern, goods produced, secrets held --- .gitignore | 4 +- assets/encounters/grasslands.encounters.toml | 16 +++ assets/resources.apack | 4 +- .../trade_manifests/monastery.manifest.toml | 53 ++++---- assets/trade_manifests/ship.manifest.toml | 8 ++ .../trade_manifests/whitestone.manifest.toml | 23 ++++ game_core/src/assets/startup.rs | 1 + game_core/src/persistance/fs_utils.rs | 16 ++- game_core/src/persistance/save_file.rs | 22 +++- game_core/src/ui/sync/sync_trade.rs | 29 +++-- game_core/src/ui/widgets/settings_panel.rs | 12 ++ game_core/src/ui/widgets/shop_panel.rs | 23 +++- game_core/src/ui/widgets/tavern_panel.rs | 98 +++++++++++++- game_core/src/world/encounters.rs | 48 ++++++- game_core/src/world/hunger.rs | 18 ++- game_core/src/world/mod.rs | 1 + game_core/src/world/spawning.rs | 88 +++++++++---- game_core/src/world/trading.rs | 3 + raw_assets/calculator.ods | Bin 0 -> 26538 bytes raw_assets/specialisms.toml | 22 +++- raw_assets/trade_goods.toml | 121 ++++++++++++++---- 21 files changed, 502 insertions(+), 108 deletions(-) create mode 100644 assets/encounters/grasslands.encounters.toml create mode 100644 assets/trade_manifests/ship.manifest.toml create mode 100644 raw_assets/calculator.ods diff --git a/.gitignore b/.gitignore index 044cdb5..3956794 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ .idea/ .vscode/ dist/ -artifacts/ \ No newline at end of file +artifacts/ + +*.ods# \ No newline at end of file diff --git a/assets/encounters/grasslands.encounters.toml b/assets/encounters/grasslands.encounters.toml new file mode 100644 index 0000000..3f51b78 --- /dev/null +++ b/assets/encounters/grasslands.encounters.toml @@ -0,0 +1,16 @@ +[[encounters]] +chance = 90 +title = "You hear a rustle in the bushes" +description = """ + +""" + +[[encounters]] +chance = 10 +title = "You see a small shrine" +description = """ +Off to the side of the path is located a small offering shrine to some forgotten god, chipped and covered in moss. + +Around the base of the shrine, you see some small totems and other miscellanious offerings. Do you want to leave anything for these ancient gods?""" + +[[encounters.options]] \ No newline at end of file diff --git a/assets/resources.apack b/assets/resources.apack index c2669d0..3ad7234 100644 --- a/assets/resources.apack +++ b/assets/resources.apack @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c7d3705a1bcb0534de927d60743ca9e4f33352bbefeaf1618d6eb91f102639fc -size 1930588 +oid sha256:08fbd17915eea98e0e3e077c32249781bb0b33d821aeab9c9dac5196eaab6527 +size 1955812 diff --git a/assets/trade_manifests/monastery.manifest.toml b/assets/trade_manifests/monastery.manifest.toml index e909957..88bc503 100644 --- a/assets/trade_manifests/monastery.manifest.toml +++ b/assets/trade_manifests/monastery.manifest.toml @@ -61,16 +61,15 @@ cost_multipliers = [ ] [Milk] -tick_decay = 0.25 -natural_limit = 0 +tick_decay = 1 +natural_limit = 15 cost_multipliers = [ [5, 1.4], [9, 1.25], - [10, 1], - [15, 0.8], - [30, 0.7], - [99999, 0.6] + [30, 1.1], + [99999, 1] ] +oversupply_trend = "halt" [Cheese] tick_decay = 0.25 @@ -97,16 +96,15 @@ cost_multipliers = [ ] [Corn] -tick_decay = 0.25 -natural_limit = 0 +tick_decay = 1.5 +natural_limit = 30 cost_multipliers = [ [5, 1.4], [9, 1.25], - [10, 1], - [15, 0.8], - [30, 0.7], - [99999, 0.6] + [30, 1.1], + [99999, 1] ] +oversupply_trend = "halt" [Tomato] tick_decay = 0.25 @@ -133,25 +131,34 @@ cost_multipliers = [ ] [Grapes] -tick_decay = 0.25 +tick_decay = 1.5 +natural_limit = 30 +cost_multipliers = [ + [5, 1.4], + [9, 1.25], + [30, 1.1], + [99999, 1] +] +oversupply_trend = "halt" + +[Wine] +tick_decay = 0.0 natural_limit = 0 cost_multipliers = [ [5, 1.4], [9, 1.25], - [10, 1], - [15, 0.8], - [30, 0.7], - [99999, 0.6] + [30, 1.1], + [99999, 1] ] +oversupply_trend = "halt" [Wheat] -tick_decay = 0.25 -natural_limit = 0 +tick_decay = 1.5 +natural_limit = 30 cost_multipliers = [ [5, 1.4], [9, 1.25], - [10, 1], - [15, 0.8], - [30, 0.7], - [99999, 0.6] + [30, 1.1], + [99999, 1] ] +oversupply_trend = "halt" \ No newline at end of file diff --git a/assets/trade_manifests/ship.manifest.toml b/assets/trade_manifests/ship.manifest.toml new file mode 100644 index 0000000..14e7eea --- /dev/null +++ b/assets/trade_manifests/ship.manifest.toml @@ -0,0 +1,8 @@ +[Bread] +tick_decay = 50.0 +natural_limit = 50 +cost_multipliers = [ + [99999, 0] +] +oversupply_trend = "halt" +undersupply_trend = "produce" \ No newline at end of file diff --git a/assets/trade_manifests/whitestone.manifest.toml b/assets/trade_manifests/whitestone.manifest.toml index dec88c9..9beb037 100644 --- a/assets/trade_manifests/whitestone.manifest.toml +++ b/assets/trade_manifests/whitestone.manifest.toml @@ -167,3 +167,26 @@ cost_multipliers = [ [30, 0.7], [99999, 0.6] ] + +[Bread] +tick_decay = 0.25 +natural_limit = 0 +cost_multipliers = [ + [5, 1.4], + [9, 1.25], + [10, 1], + [15, 0.8], + [30, 0.7], + [99999, 0.6] +] + +[Wine] +tick_decay = 0.0 +natural_limit = 0 +cost_multipliers = [ + [5, 1.8], + [9, 1.6], + [30, 1.4], + [99999, 1] +] +oversupply_trend = "halt" \ No newline at end of file diff --git a/game_core/src/assets/startup.rs b/game_core/src/assets/startup.rs index 5c607ed..74d4a5b 100644 --- a/game_core/src/assets/startup.rs +++ b/game_core/src/assets/startup.rs @@ -18,6 +18,7 @@ pub fn start_load_resources(mut loader: AssetTypeLoader) { loader.load_trade_manifest(&[ ("trade_manifests/whitestone.manifest.toml", "whitestone"), ("trade_manifests/monastery.manifest.toml", "monastery"), + ("trade_manifests/ship.manifest.toml", "ship"), ]); } diff --git a/game_core/src/persistance/fs_utils.rs b/game_core/src/persistance/fs_utils.rs index f5b9a76..6130e2a 100644 --- a/game_core/src/persistance/fs_utils.rs +++ b/game_core/src/persistance/fs_utils.rs @@ -34,7 +34,21 @@ pub fn read_config_file() -> Option<Options> { pub fn save_config_file(options: Options) -> Option<()> { let root_dir = get_root_save_dir()?; + std::fs::create_dir_all(&root_dir) + .inspect_err(|e| { + log::error!("{}", e); + }) + .ok()?; let save_path = root_dir.join("config.toml"); - std::fs::write(save_path, toml::to_string_pretty(&options).ok()?).ok() + std::fs::write( + save_path, + toml::to_string_pretty(&options) + .inspect_err(|e| { + log::error!("{}", e); + }) + .ok()?, + ) + .map(|()| log::info!("SAVED")) + .ok() } diff --git a/game_core/src/persistance/save_file.rs b/game_core/src/persistance/save_file.rs index 681702d..65d7cf2 100644 --- a/game_core/src/persistance/save_file.rs +++ b/game_core/src/persistance/save_file.rs @@ -11,11 +11,19 @@ use crate::persistance::fs_utils::{get_root_save_dir, AUTOSAVE_NAME}; use crate::states::Player; use crate::system::flow::AppState; use crate::world::{ - ActiveLevel, CurrentResidence, DistanceTravelled, EncounterState, HungerState, + ActiveLevel, CraftSpecialism, CurrentResidence, DistanceTravelled, EncounterState, HungerState, PendingLoadState, TownName, TradeManifestTickState, TradingState, TravelPath, TravelTarget, }; -pub type TownPersistenceData = HashMap<String, (TradingState, HungerState, TradeManifestTickState)>; +pub type TownPersistenceData = HashMap< + String, + ( + TradingState, + HungerState, + TradeManifestTickState, + Option<CraftSpecialism>, + ), +>; #[derive(Serialize, Deserialize, Debug, Resource)] pub struct PersistenceState { @@ -80,16 +88,22 @@ pub fn sync_state_to_persistence( &TradingState, &HungerState, &TradeManifestTickState, + Option<&CraftSpecialism>, )>, encounters: Res<EncounterState>, active_map: Res<ActiveLevel>, ) { let town_states = town_query .iter() - .map(|(name, trading, hunger, manifest)| { + .map(|(name, trading, hunger, manifest, maybe_spec)| { ( name.0.clone(), - (trading.clone(), hunger.clone(), manifest.clone()), + ( + trading.clone(), + hunger.clone(), + manifest.clone(), + maybe_spec.cloned(), + ), ) }) .collect::<TownPersistenceData>(); diff --git a/game_core/src/ui/sync/sync_trade.rs b/game_core/src/ui/sync/sync_trade.rs index 7cd58dd..7456124 100644 --- a/game_core/src/ui/sync/sync_trade.rs +++ b/game_core/src/ui/sync/sync_trade.rs @@ -6,7 +6,8 @@ use bevy::prelude::{Entity, Query, Res, ResMut, Resource, With}; use crate::const_data::{get_goods_from_name, get_goods_from_name_checked, TRADE_GOODS}; use crate::states::Player; use crate::world::{ - CurrentResidence, HungerState, TownName, TradeGood, TradeManifest, TradingState, TravelTarget, + CurrentResidence, HungerState, StarvationMarker, TownName, TradeGood, TradeManifest, + TradingState, TravelTarget, }; #[derive(Clone)] @@ -25,6 +26,7 @@ pub struct UITradeData { pub player_entity: Option<Entity>, pub shop_items: Vec<ItemTradeData>, pub hunger_descriptor: String, + pub is_starved: bool, } pub fn sync_ui_trade_data( @@ -43,6 +45,7 @@ pub fn sync_ui_trade_data( &TradingState, &HungerState, &Handle<TradeManifest>, + Option<&StarvationMarker>, )>, manifests: Res<Assets<TradeManifest>>, mut trade_data: ResMut<UITradeData>, @@ -64,21 +67,23 @@ pub fn sync_ui_trade_data( CurrentResidence::TravellingFrom(..) => String::new(), }); - let (town_entity, _, town_trading_state, hunger_state, manifest_handle) = match town_query - .into_iter() - .find(|(_, name, _, _, _)| town_name == *name.0) - { - Some(v) => v, - None => { - trade_data.shop_items = vec![]; - trade_data.town_entity = None; - return; - } - }; + let (town_entity, _, town_trading_state, hunger_state, manifest_handle, starvation) = + match town_query + .into_iter() + .find(|(_, name, _, _, _, _)| town_name == *name.0) + { + Some(v) => v, + None => { + trade_data.shop_items = vec![]; + trade_data.town_entity = None; + return; + } + }; trade_data.town_entity = Some(town_entity); trade_data.town_gold = town_trading_state.gold.max(0) as usize; trade_data.hunger_descriptor = hunger_state.get_town_descriptor(); + trade_data.is_starved = starvation.is_some(); for (item_name, trade_good) in TRADE_GOODS.iter() { let manifest = match manifests.get(manifest_handle) { diff --git a/game_core/src/ui/widgets/settings_panel.rs b/game_core/src/ui/widgets/settings_panel.rs index eafbf71..51a0c36 100644 --- a/game_core/src/ui/widgets/settings_panel.rs +++ b/game_core/src/ui/widgets/settings_panel.rs @@ -121,6 +121,9 @@ pub fn render_settings_panel( AudioSettings, >| { settings.master_volume = (settings.master_volume - 0.05).max(0.0); + save_config_file(Options { + audio: *settings + }); })} /> <BackgroundBundle @@ -151,6 +154,9 @@ pub fn render_settings_panel( AudioSettings, >| { settings.master_volume = (settings.master_volume + 0.05).min(1.0); + save_config_file(Options { + audio: *settings + }); })} /> </BackgroundBundle> @@ -236,6 +242,9 @@ pub fn render_settings_panel( AudioSettings, >| { settings.ui_volume = (settings.ui_volume - 0.05).max(0.0); + save_config_file(Options { + audio: *settings + }); })} /> <BackgroundBundle @@ -266,6 +275,9 @@ pub fn render_settings_panel( AudioSettings, >| { settings.ui_volume = (settings.ui_volume + 0.05).min(1.0); + save_config_file(Options { + audio: *settings + }); })} /> </BackgroundBundle> diff --git a/game_core/src/ui/widgets/shop_panel.rs b/game_core/src/ui/widgets/shop_panel.rs index bca69ba..074d086 100644 --- a/game_core/src/ui/widgets/shop_panel.rs +++ b/game_core/src/ui/widgets/shop_panel.rs @@ -76,7 +76,28 @@ pub fn render_shop_panel( ) -> bool { let parent_id = Some(entity); - if let Ok(props) = query.get(entity) { + if ui_data.is_starved { + rsx! { + <ElementBundle> + <TextWidgetBundle + text={TextProps { + content: "As you wander into the merchant's store, you find only ".to_string(), + size: 32.0, + ..Default::default() + }} + styles={KStyle { + color: value(Color::BLACK), + padding: edge_px(20.0), + top: stretch(1.0), + bottom: stretch(1.0), + left: stretch(1.0), + right: stretch(1.0), + ..Default::default() + }} + /> + </ElementBundle> + }; + } else if let Ok(props) = query.get(entity) { rsx! { <ElementBundle> <TextWidgetBundle diff --git a/game_core/src/ui/widgets/tavern_panel.rs b/game_core/src/ui/widgets/tavern_panel.rs index dbd1f45..078e114 100644 --- a/game_core/src/ui/widgets/tavern_panel.rs +++ b/game_core/src/ui/widgets/tavern_panel.rs @@ -12,21 +12,68 @@ use crate::ui::components::*; use crate::ui::prelude::*; use crate::ui::sync::{UITradeData, UITravelInfo}; use crate::ui::widgets::*; -use crate::world::{CurrentResidence, MapQuery, TownPaths}; +use crate::world::{ + CraftSpecialism, CurrentResidence, MapQuery, TownName, TownPaths, TradingState, +}; use crate::{basic_widget, empty_props, on_button_click}; empty_props!(TavernPanelProps); basic_widget!(TavernPanelProps => TavernPanel); +#[derive(Eq, Default, PartialEq, Debug, Clone, Component)] +pub struct TavernPanelState { + pub hint: Option<String>, +} + pub fn render_tavern_panel( In((widget_context, entity)): In<(KayakWidgetContext, Entity)>, mut commands: Commands, ui_data: Res<UITradeData>, query: Query<&TavernPanelProps>, + state_query: Query<&TavernPanelState>, + foo: Query<(&TownName, &CraftSpecialism)>, ) -> bool { let parent_id = Some(entity); + let state_entity = widget_context.use_state(&mut commands, entity, TavernPanelState::default()); + + let buy_hint = on_button_click!( + ParamSet<( + Query<&mut TradingState, With<Player>>, + Query<(&TownName, &CraftSpecialism)>, + Query<&mut TavernPanelState> + )>, + |mut params: ParamSet<( + Query<&mut TradingState, With<Player>>, + Query<(&TownName, &CraftSpecialism)>, + Query<&mut TavernPanelState> + )>| { + let success = if let Ok(mut trade_state) = params.p0().get_single_mut() { + trade_state.spend_gold(50) + } else { + false + }; - if let Ok(props) = query.get(entity) { + let rumour = if success { + let query = params.p1(); + let mut viable_iter = query.iter(); + let viable_count = viable_iter.len(); + if viable_count < 1 { + None + } else { + let selected = viable_iter.nth(fastrand::usize(0..viable_count)); + selected.map(|(name, craft)| craft.format_rumour(&name.0)) + } + } else { + None + }; + + if let Ok(mut state_state) = params.p2().get_mut(state_entity) { + state_state.hint = rumour.clone(); + } + } + ); + + if let (Ok(props), Ok(state)) = (query.get(entity), state_query.get(state_entity)) { rsx! { <ElementBundle> <TextWidgetBundle @@ -38,12 +85,35 @@ pub fn render_tavern_panel( }} text={TextProps { size: 32.0, - content: String::from("A strange bartender eyes you suspiciously"), + content: if ui_data.is_starved { String::from("The corpse of a bartender slumps over the bar") } else { String::from("A strange bartender eyes you suspiciously") }, ..Default::default() }} /> + { if let Some(hint) = &state.hint { + constructor! { + <TextWidgetBundle + styles={KStyle { + top: px(20.0), + bottom: px(20.0), + left: stretch(1.0), + right: stretch(1.0), + color: value(Color::BLACK), + ..Default::default() + }} + text={TextProps { + size: 28.0, + content: format!("\"{}\"", &hint), + ..Default::default() + }} + /> + } + }} + + <ScrollContextProviderBundle> <ScrollBoxBundle> + { if state.hint.is_none() { + constructor! { <TextWidgetBundle styles={KStyle { top: px(20.0), @@ -59,8 +129,30 @@ pub fn render_tavern_panel( ..Default::default() }} /> + } + }} </ScrollBoxBundle> </ScrollContextProviderBundle> + + {if !ui_data.is_starved { + constructor! { + <ButtonWidget + props={ButtonWidgetProps { + font_size: 24.0, + left_icon: IconContent::Atlas(String::from("icons"), 8), + text: String::from("50g: Tip Barkeep"), + is_disabled: ui_data.player_gold < 50, + ..Default::default() + }} + styles={KStyle { + left: stretch(1.0), + right: stretch(1.0), + ..Default::default() + }} + on_event={buy_hint} + /> + } + }} </ElementBundle> }; } diff --git a/game_core/src/world/encounters.rs b/game_core/src/world/encounters.rs index 92ddbf9..66ac733 100644 --- a/game_core/src/world/encounters.rs +++ b/game_core/src/world/encounters.rs @@ -28,8 +28,10 @@ impl EncounterType { title: String::from("Your journey begins"), description: String::from(include_str!("../assets/static/intro_text.txt")), options: vec![EncounterOption { + requirements: Vec::new(), label: String::from("Journey Forth"), - outcome: vec![], + outcomes: vec![], + hide_missing_reqs: true, }], }]), _ => None, @@ -132,12 +134,19 @@ impl From<Vec<EncounterZone>> for WorldZones { } #[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(tag = "type")] pub enum EncounterOutcome { + Continue, + Description { + description: String, + }, GainResource { + description: String, resource_type: String, amount: (usize, usize), }, LoseResource { + description: String, resource_type: String, amount: (usize, usize), }, @@ -150,10 +159,35 @@ pub enum EncounterOutcome { }, } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ChanceOutcome { + pub chance: usize, + pub outcome: EncounterOutcome, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum EncounterRequirement { + MinimumItemAmount { item: String, amount: usize }, + MaximumItemAmount { item: String, amount: usize }, + MinimumGoldAmount { item: String, amount: usize }, + MaximumGoldAmount { item: String, amount: usize }, + AnyFoodLessThan { amount: usize, or_equal: bool }, + AnyFoodGreaterThan { amount: usize, or_equal: bool }, +} + +fn default_false() -> bool { + false +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EncounterOption { pub label: String, - pub outcome: Vec<EncounterOutcome>, + pub outcomes: Vec<EncounterOutcome>, + #[serde(default = "Vec::new")] + pub requirements: Vec<EncounterRequirement>, + #[serde(default = "default_false")] + pub hide_missing_reqs: bool, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -170,7 +204,8 @@ pub fn gen_encounter() -> Encounter { options: vec![ EncounterOption { label: BsVerb().fake(), - outcome: vec![EncounterOutcome::GainResource { + outcomes: vec![EncounterOutcome::GainResource { + description: Paragraph(3..5).fake(), resource_type: format!( "{} {}", BsAdj().fake::<String>(), @@ -182,10 +217,13 @@ pub fn gen_encounter() -> Encounter { (b, b + inc) }, }], + requirements: Vec::new(), + hide_missing_reqs: true, }, EncounterOption { label: BsVerb().fake(), - outcome: vec![EncounterOutcome::LoseResource { + outcomes: vec![EncounterOutcome::LoseResource { + description: Paragraph(3..5).fake(), resource_type: format!( "{} {}", BsAdj().fake::<String>(), @@ -197,6 +235,8 @@ pub fn gen_encounter() -> Encounter { (b, b + inc) }, }], + requirements: Vec::new(), + hide_missing_reqs: true, }, ], } diff --git a/game_core/src/world/hunger.rs b/game_core/src/world/hunger.rs index 67fd48b..ea6ca40 100644 --- a/game_core/src/world/hunger.rs +++ b/game_core/src/world/hunger.rs @@ -1,10 +1,12 @@ use std::collections::HashMap; -use bevy::prelude::{Component, Entity, EventReader, Mut, Query, With, Without}; +use bevy::prelude::{Commands, Component, Entity, EventReader, Mut, Query, Res, With, Without}; use serde::{Deserialize, Serialize}; +use crate::assets::AssetHandles; use crate::const_data::get_goods_from_name_checked; use crate::states::Player; +use crate::world::spawning::apply_skull_marker; use crate::world::travel::WorldTickEvent; use crate::world::{TownName, TradeGood, TradingState}; @@ -46,6 +48,7 @@ impl HungerState { } } +#[derive(Component)] pub struct StarvationMarker; pub const PLAYER_FOOD_TARGET: usize = 25; @@ -144,9 +147,20 @@ fn process_hunger_state<'a>( } } +#[derive(Default)] +pub struct PlayerStarvedEvent; + pub fn handle_entity_starvation( - food_query: Query<(Entity, &HungerState)>, + mut commands: Commands, + assets: Res<AssetHandles>, + food_query: Query<(Entity, &HungerState), Without<StarvationMarker>>, player_query: Query<(), With<Player>>, town_query: Query<&TownName>, ) { + for (entity, hunger) in &food_query { + if hunger.sustenance == 0 { + apply_skull_marker(&mut commands, &assets, entity); + commands.entity(entity).insert(StarvationMarker); + } + } } diff --git a/game_core/src/world/mod.rs b/game_core/src/world/mod.rs index 7d2d877..23131be 100644 --- a/game_core/src/world/mod.rs +++ b/game_core/src/world/mod.rs @@ -90,6 +90,7 @@ impl Plugin for WorldPlugin { ConditionSet::new() .run_in_state(AppState::InGame) .with_system(encounters::notify_new_zone) + .with_system(hunger::handle_entity_starvation) .with_system(|mut events: ResMut<Events<WorldTickEvent>>| { events.clear(); }) diff --git a/game_core/src/world/spawning.rs b/game_core/src/world/spawning.rs index 016b38b..1625ab1 100644 --- a/game_core/src/world/spawning.rs +++ b/game_core/src/world/spawning.rs @@ -293,6 +293,9 @@ pub fn populate_world( } let world_zones = WorldZones::from_entities(level.px_hei, MapQuery::get_entities_of(level)); + let mut town_entities_a = Vec::new(); + let mut town_entities_b = Vec::new(); + MapQuery::get_entities_of(level) .into_iter() .filter(|instance| instance.identifier == *"Town") @@ -331,39 +334,70 @@ pub fn populate_world( .as_ref() .and_then(|pl| pl.0.town_states.get(&name)) { - Some((trade, hunger, tick)) => TownBundle { - town_name: TownName(name.clone()), - manifest: handle, - trade_state: trade.clone(), - hunger_state: hunger.clone(), - manifest_state: tick.clone(), - world_linked: WorldLinked, - location: TransformBundle::from_transform(Transform::from_translation( - transform, - )), - }, - None => TownBundle { - town_name: TownName(name.clone()), - manifest: handle, - trade_state: TradingState { - gold: fastrand::isize(0..250) + 250, - items: asset.create_randomised_inventory(), + Some((trade, hunger, tick, maybe_spec)) => ( + maybe_spec.clone(), + TownBundle { + town_name: TownName(name.clone()), + manifest: handle, + trade_state: trade.clone(), + hunger_state: hunger.clone(), + manifest_state: tick.clone(), + world_linked: WorldLinked, + location: TransformBundle::from_transform(Transform::from_translation( + transform, + )), }, - hunger_state: HungerState::initial_town(), - manifest_state: TradeManifestTickState::default(), - world_linked: WorldLinked, - location: TransformBundle::from_transform(Transform::from_translation( - transform, - )), - }, + ), + None => ( + None, + TownBundle { + town_name: TownName(name.clone()), + manifest: handle, + trade_state: TradingState { + gold: fastrand::isize(0..250) + 250, + items: asset.create_randomised_inventory(), + }, + hunger_state: HungerState::initial_town(), + manifest_state: TradeManifestTickState::default(), + world_linked: WorldLinked, + location: TransformBundle::from_transform(Transform::from_translation( + transform, + )), + }, + ), } }) - .for_each(|bundle| { + .for_each(|(maybe_spec, bundle)| { + let is_royal_lampoon = &bundle.town_name.0 == &String::from("The Royal Lampoon"); let ent = commands.spawn((bundle, VisibilityBundle::default())).id(); - apply_skull_marker(&mut commands, &assets, ent); + if let Some(spec) = maybe_spec { + commands.entity(ent).insert(spec); + } else if is_royal_lampoon { + town_entities_a.push(ent); + } }); - log::info!("Spec {:#?}", *SPECIALISMS); + if pending_load.is_none() { + let mut specialisms = (*SPECIALISMS).clone(); + let mut handling_a = true; + for spec in specialisms { + if town_entities_a.is_empty() && !town_entities_b.is_empty() { + handling_a = false; + } else if town_entities_b.is_empty() && !town_entities_a.is_empty() { + handling_a = true; + } + + if handling_a { + let entity = town_entities_a.remove(fastrand::usize(0..town_entities_a.len())); + commands.entity(entity).insert(spec); + town_entities_b.push(entity); + } else { + let entity = town_entities_b.remove(fastrand::usize(0..town_entities_b.len())); + commands.entity(entity).insert(spec); + town_entities_a.push(entity); + } + } + } commands.insert_resource(trade_routes); commands.insert_resource(world_zones); diff --git a/game_core/src/world/trading.rs b/game_core/src/world/trading.rs index 21cff5f..643fab9 100644 --- a/game_core/src/world/trading.rs +++ b/game_core/src/world/trading.rs @@ -100,6 +100,9 @@ impl TradeManifest { } } + inventory + .entry(String::from("Bread")) + .or_insert_with(|| fastrand::usize(8..15)); inventory } } diff --git a/raw_assets/calculator.ods b/raw_assets/calculator.ods new file mode 100644 index 0000000000000000000000000000000000000000..ac7f2d3c4e2b6649eadb0e5e4e2a11d3035e7223 GIT binary patch literal 26538 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 H<Lv(c5U8Q| literal 0 HcmV?d00001 diff --git a/raw_assets/specialisms.toml b/raw_assets/specialisms.toml index 1b8c902..a4a926b 100644 --- a/raw_assets/specialisms.toml +++ b/raw_assets/specialisms.toml @@ -1,23 +1,29 @@ [[specialism]] [specialism.requirements] -Tomato = 3 -Cheese = 2 Dough = 2 +Cheese = 2 +Tomato = 3 [specialism.production] Pizza = 2 [[specialism]] [specialism.requirements] Coal = 4 -"Iron Ore" = 3 +"Iron Ore" = 5 +[specialism.production] +"Iron Ingot" = 5 + +[[specialism]] +[specialism.requirements] +"Rough Gemstone" = 5 [specialism.production] -"Iron Ingot" = 3 +"Polished Gemstone" = 5 [[specialism]] [specialism.requirements] Lumber = 10 [specialism.production] -"Spare Wheel" = 3 +"Spare Wheel" = 2 [[specialism]] [specialism.requirements] @@ -36,3 +42,9 @@ Dough = 3 Dough = 4 [specialism.production] Bread = 3 + +[[specialism]] +[specialism.requirements] +Grapes = 4 +[specialism.production] +Wine = 6 diff --git a/raw_assets/trade_goods.toml b/raw_assets/trade_goods.toml index a92a5d5..f7ad6a6 100644 --- a/raw_assets/trade_goods.toml +++ b/raw_assets/trade_goods.toml @@ -1,10 +1,10 @@ -["Armour"] +[Armour] name = "Armour" icon = ["icons", 12] food_value = 0 gold_value = 12 -["Weapons"] +[Weapons] name = "Weapons" icon = ["icons", 1] food_value = 0 @@ -16,23 +16,23 @@ icon = ["icons", 13] food_value = 0 gold_value = 27 -["Ale"] +[Ale] name = "Ale" icon = ["icons", 11] food_value = 0 gold_value = 6 -["Milk"] +[Milk] name = "Milk" icon = ["icons", 2] -food_value = 2 -gold_value = 5 +food_value = 3 +gold_value = 6 -["Cheese"] +[Cheese] name = "Cheese" icon = ["icons", 3] -food_value = 3 -gold_value = 6 +food_value = 4 +gold_value = 9 ["Spare Wheel"] name = "Spare Wheel" @@ -40,38 +40,113 @@ icon = ["icons", 28] food_value = 0 gold_value = 125 -["Berries"] +[Berries] name = "Berries" icon = ["icons", 27] -food_value = 1 +food_value = 2 gold_value = 4 -["Corn"] +[Corn] name = "Corn" icon = ["icons", 26] food_value = 2 -gold_value = 6 +gold_value = 4 -["Tomato"] +[Tomato] name = "Tomato" icon = ["icons", 25] -food_value = 2 +food_value = 3 gold_value = 6 -["Chili"] +[Chili] name = "Chili" icon = ["icons", 24] -food_value = 2 +food_value = 4 gold_value = 8 -["Grapes"] +[Grapes] name = "Grapes" icon = ["icons", 23] -food_value = 1 -gold_value = 9 +food_value = 4 +gold_value = 8 -["Wheat"] +[Wheat] name = "Wheat" icon = ["icons", 22] -food_value = 1 -gold_value = 3 +food_value = 2 +gold_value = 4 + +[Dough] +name = "Dough" +icon = ["icons", 38] +food_value = 0 +gold_value = 9 + +[Bread] +name = "Bread" +icon = ["icons", 35] +food_value = 9 +gold_value = 14 + +[Pizza] +name = "Pizza" +icon = ["icons", 36] +food_value = 18 +gold_value = 36 + +[Lumber] +name = "Lumber" +icon = ["icons", 29] +food_value = 0 +gold_value = 10 + +[Coal] +name = "Coal" +icon = ["icons", 30] +food_value = 0 +gold_value = 13 + +["Iron Ore"] +name = "Iron Ore" +icon = ["icons", 31] +food_value = 0 +gold_value = 8 + +[Iron] +name = "Iron" +icon = ["icons", 32] +food_value = 0 +gold_value = 33 + +["Rough Gemstone"] +name = "Rough Gemstone" +icon = ["icons", 33] +food_value = 0 +gold_value = 12 + +["Polished Gemstone"] +name = "Polished Gemstone" +icon = ["icons", 34] +food_value = 0 +gold_value = 19 + + +["Religious Artifact"] +name = "Religious Artifact" +icon = ["icons", 34] +food_value = 0 +gold_value = 125 + + +["Strange Doll"] +name = "Polished Gemstone" +icon = ["icons", 34] +food_value = 0 +gold_value = 19 + +["Wine"] +name = "Wine" +icon = ["icons", 37] +food_value = 7 +gold_value = 12 + -- GitLab