Skip to content

Commit 832c523

Browse files
authored
feat: rework porters to be a task of people (#90)
1 parent a07c8a4 commit 832c523

8 files changed

Lines changed: 85 additions & 94 deletions

File tree

src/gameplay/logistics/mod.rs

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/gameplay/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::screens::Screen;
44

55
pub mod hud;
66
pub mod item;
7-
pub mod logistics;
87
pub mod people;
98
pub mod player;
109
pub mod random;
@@ -30,7 +29,6 @@ pub fn plugin(app: &mut App) {
3029
app.add_plugins((
3130
hud::plugin,
3231
item::plugin,
33-
logistics::plugin,
3432
people::plugin,
3533
player::plugin,
3634
random::plugin,

src/gameplay/people/mod.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
use bevy::prelude::*;
22

3+
use crate::gameplay::world::construction::StructureConstructed;
4+
35
pub mod naming;
6+
pub mod pathfinding;
7+
pub mod porting;
48

59
pub(super) fn plugin(app: &mut App) {
6-
app.add_plugins((naming::plugin,));
10+
app.add_plugins((naming::plugin, pathfinding::plugin, porting::plugin));
11+
12+
app.add_systems(
13+
FixedUpdate,
14+
add_housed_people_to_new_structures.run_if(on_message::<StructureConstructed>),
15+
);
716
}
817

918
#[derive(Component, Reflect, Debug, Default)]
@@ -19,3 +28,14 @@ pub struct Houses(Vec<Entity>);
1928
#[reflect(Component)]
2029
#[relationship(relationship_target = Houses)]
2130
pub struct HousedIn(pub Entity);
31+
32+
fn add_housed_people_to_new_structures(
33+
mut structures_constructed: MessageReader<StructureConstructed>,
34+
mut commands: Commands,
35+
) {
36+
for StructureConstructed(structure) in structures_constructed.read() {
37+
for _ in 0..3 {
38+
commands.spawn((Name::new("Person"), Person, HousedIn(*structure)));
39+
}
40+
}
41+
}
Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,25 @@ use bevy::{
77

88
use crate::gameplay::{
99
FactorySystems,
10-
logistics::{
11-
path::Pathable,
12-
porter::{PorterArrival, PorterLost},
13-
},
10+
people::porting::{PorterArrival, PorterLost, Porting},
1411
recipe::{
1512
assets::Recipe,
1613
select::{RecipeChanged, SelectedRecipe},
1714
},
1815
world::{
1916
construction::{Constructions, StructureConstructed},
17+
demolition::Demolished,
2018
tilemap::coord::Coord,
2119
},
2220
};
2321

2422
pub(super) fn plugin(app: &mut App) {
2523
app.add_systems(
2624
FixedUpdate,
27-
pathfind
28-
.in_set(FactorySystems::Logistics)
29-
.run_if(on_message::<RecipeChanged>.or(on_message::<StructureConstructed>)),
25+
pathfind.in_set(FactorySystems::Logistics).run_if(
26+
on_message::<RecipeChanged>
27+
.or(on_message::<StructureConstructed>.or(on_message::<Demolished>)),
28+
),
3029
);
3130

3231
app.add_systems(
@@ -35,9 +34,17 @@ pub(super) fn plugin(app: &mut App) {
3534
);
3635
}
3736

38-
#[derive(Component, Reflect)]
37+
#[derive(Component, Reflect, Default)]
3938
#[reflect(Component)]
40-
pub struct WalkPath(pub Vec<Entity>);
39+
pub struct Pathable {
40+
pub walkable: bool,
41+
}
42+
43+
impl Pathable {
44+
pub fn walkable() -> Self {
45+
Self { walkable: true }
46+
}
47+
}
4148

4249
fn pathfind(
4350
structures: Query<(Entity, &SelectedRecipe)>,
@@ -120,17 +127,17 @@ fn pathfind(
120127
pub struct PorterPaths(pub VecDeque<(Entity, Vec<Entity>)>);
121128

122129
fn walk_along_path(
123-
query: Query<(Entity, &mut Transform, &mut WalkPath, &mut Sprite)>,
124-
transforms: Query<&Transform, Without<WalkPath>>,
130+
porters: Query<(Entity, &mut Transform, &mut Porting, &mut Sprite)>,
131+
transforms: Query<&Transform, Without<Porting>>,
125132
time: Res<Time>,
126133
mut porter_arrivals: MessageWriter<PorterArrival>,
127134
mut porter_losses: MessageWriter<PorterLost>,
128135
) {
129136
const SPEED: f32 = 64.0;
130137
const ARRIVAL_THRESHHOLD: f32 = 16.0;
131138

132-
for (entity, mut transform, mut walk_path, mut sprite) in query {
133-
let Some(goal) = walk_path.0.last() else {
139+
for (entity, mut transform, mut porting, mut sprite) in porters {
140+
let Some(goal) = porting.path.last() else {
134141
continue;
135142
};
136143

@@ -146,9 +153,9 @@ fn walk_along_path(
146153
.move_towards(goal_transform.translation, SPEED * time.delta_secs());
147154

148155
if transform.translation.distance(goal_transform.translation) <= ARRIVAL_THRESHHOLD {
149-
walk_path.0.pop();
156+
porting.path.pop();
150157

151-
if walk_path.0.is_empty() {
158+
if porting.path.is_empty() {
152159
porter_arrivals.write(PorterArrival(entity));
153160
}
154161
}
Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use crate::gameplay::{
77
assets::{ItemDef, Transport},
88
inventory::Inventory,
99
},
10-
logistics::pathfinding::{PorterPaths, WalkPath},
10+
people::pathfinding::PorterPaths,
11+
people::{Houses, Person},
1112
recipe::{assets::Recipe, select::SelectedRecipe},
1213
sprite_sort::{YSortSprite, ZIndexSprite},
1314
};
@@ -25,46 +26,39 @@ pub(super) fn plugin(app: &mut App) {
2526
#[derive(Component, Reflect, Deref, DerefMut)]
2627
#[reflect(Component)]
2728
#[require(PorterSpawnOutputIndex)]
28-
pub struct PorterSpawnTimer(pub Timer);
29+
pub struct PorterCooldown(pub Timer);
2930

3031
#[derive(Component, Reflect, Deref, DerefMut, Default)]
3132
#[reflect(Component)]
3233
struct PorterSpawnOutputIndex(usize);
3334

34-
#[derive(Component, Reflect)]
35-
#[reflect(Component)]
36-
#[relationship_target(relationship = PorterOf)]
37-
pub struct Porters(Vec<Entity>);
38-
39-
#[derive(Component, Reflect)]
40-
#[reflect(Component)]
41-
#[relationship(relationship_target = Porters)]
42-
pub struct PorterOf(pub Entity);
43-
44-
#[derive(Component, Reflect)]
45-
#[reflect(Component)]
46-
pub struct PorterTo(pub Entity);
47-
48-
#[derive(Component, Reflect)]
49-
#[reflect(Component)]
50-
pub struct PortingItem(pub AssetId<ItemDef>);
51-
5235
#[derive(Message, Reflect, Debug)]
5336
pub struct PorterArrival(pub Entity);
5437

5538
#[derive(Message, Reflect, Debug)]
5639
pub struct PorterLost(pub Entity);
5740

41+
#[derive(Component, Reflect, Debug)]
42+
#[reflect(Component)]
43+
pub struct Porting {
44+
pub item: AssetId<ItemDef>,
45+
pub source: Entity,
46+
pub destination: Entity,
47+
pub path: Vec<Entity>,
48+
}
49+
5850
fn spawn_porter(
5951
structure_query: Query<(
6052
Entity,
6153
&Transform,
62-
&mut PorterSpawnTimer,
54+
&mut PorterCooldown,
6355
&mut PorterSpawnOutputIndex,
6456
&SelectedRecipe,
6557
&mut Inventory,
6658
&mut PorterPaths,
59+
&Houses,
6760
)>,
61+
person_query: Query<(), (With<Person>, Without<Porting>)>,
6862
mut commands: Commands,
6963
item_defs: Res<Assets<ItemDef>>,
7064
recipes: Res<Assets<Recipe>>,
@@ -79,12 +73,17 @@ fn spawn_porter(
7973
selected_recipe,
8074
mut inventory,
8175
mut porter_paths,
76+
houses,
8277
) in structure_query
8378
{
8479
if !timer.tick(time.delta()).is_finished() {
8580
continue;
8681
}
8782

83+
let Some(person) = houses.iter().find(|e| person_query.contains(*e)) else {
84+
continue;
85+
};
86+
8887
let Some(recipe) = recipes.get(&selected_recipe.0) else {
8988
continue;
9089
};
@@ -101,16 +100,15 @@ fn spawn_porter(
101100
continue;
102101
}
103102

104-
let Some((input, path)) = porter_paths.0.front() else {
103+
let Some((destination, path)) = porter_paths.0.front() else {
105104
continue;
106105
};
107106

108107
let Some(item_def) = item_defs.get(*item_id) else {
109108
continue;
110109
};
111110

112-
commands.spawn((
113-
Name::new("Porter"),
111+
commands.entity(person).insert((
114112
*transform,
115113
Sprite::default(),
116114
Anchor(Vec2::new(0.0, -0.25)),
@@ -121,13 +119,14 @@ fn spawn_porter(
121119
Transport::Bag => Animation::tag("walk_bag"),
122120
},
123121
},
124-
Inventory::with_single(*item_id, 1),
125122
YSortSprite,
126123
ZIndexSprite(10),
127-
PorterOf(structure),
128-
PorterTo(*input),
129-
PortingItem(*item_id),
130-
WalkPath(path.clone()),
124+
Porting {
125+
item: *item_id,
126+
source: structure,
127+
destination: *destination,
128+
path: path.clone(),
129+
},
131130
));
132131

133132
*quantity -= 1;
@@ -139,25 +138,27 @@ fn spawn_porter(
139138

140139
fn despawn_lost_porters(mut porter_losses: MessageReader<PorterLost>, mut commands: Commands) {
141140
for PorterLost(entity) in porter_losses.read() {
142-
commands.entity(*entity).despawn();
141+
commands.entity(*entity).remove::<(Sprite, Porting)>();
143142
}
144143
}
145144

146145
fn drop_of_items(
147146
mut poter_arrivals: MessageReader<PorterArrival>,
148-
porters: Query<(&PortingItem, &PorterTo)>,
147+
porters: Query<&Porting>,
149148
mut structures: Query<&mut Inventory>,
150149
mut commands: Commands,
151150
) {
152151
for PorterArrival(porter) in poter_arrivals.read() {
153-
commands.entity(*porter).despawn();
152+
commands.entity(*porter).remove::<(Sprite, Porting)>();
154153

155-
let (PortingItem(item_id), PorterTo(structure)) = porters.get(*porter).unwrap();
154+
let Ok(porting) = porters.get(*porter) else {
155+
continue;
156+
};
156157

157-
if let Ok(mut inventory) = structures.get_mut(*structure) {
158+
if let Ok(mut inventory) = structures.get_mut(porting.destination) {
158159
inventory
159160
.items
160-
.entry(*item_id)
161+
.entry(porting.item)
161162
.and_modify(|q| *q += 1)
162163
.or_insert(1);
163164
}

src/gameplay/structure/harvest.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ pub fn plugin(app: &mut App) {
2121
app.add_systems(
2222
FixedUpdate,
2323
(
24-
(add_people_to_harvester, assign_harvester_taxonomy)
25-
.run_if(on_message::<StructureConstructed>),
24+
assign_harvester_taxonomy.run_if(on_message::<StructureConstructed>),
2625
sync_harvester_range,
2726
assign_harvester_deposit,
2827
harvest_deposit,
@@ -52,22 +51,6 @@ pub struct Harvests(pub Entity);
5251
#[reflect(Component)]
5352
pub struct HarvestTimer(pub Timer);
5453

55-
fn add_people_to_harvester(
56-
mut structures_constructed: MessageReader<StructureConstructed>,
57-
harvester_query: Query<Entity, With<Harvester>>,
58-
mut commands: Commands,
59-
) {
60-
for StructureConstructed(structure) in structures_constructed.read() {
61-
if !harvester_query.contains(*structure) {
62-
continue;
63-
}
64-
65-
for _ in 0..3 {
66-
commands.spawn((Name::new("Person"), Person, HousedIn(*structure)));
67-
}
68-
}
69-
}
70-
7154
fn assign_harvester_taxonomy(
7255
mut structures_constructed: MessageReader<StructureConstructed>,
7356
mut harvester_query: Query<(&Coord, &Range, &mut AseAnimation), With<Harvester>>,

src/gameplay/structure/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::time::Duration;
33
use bevy::prelude::*;
44

55
use crate::gameplay::{
6-
logistics::porter::PorterSpawnTimer, structure::assets::StructureDef,
6+
people::porting::PorterCooldown, structure::assets::StructureDef,
77
world::demolition::Demolishable,
88
};
99

@@ -12,6 +12,7 @@ pub mod default_recipe;
1212
pub mod harvest;
1313
pub mod highlight;
1414
pub mod interactable;
15+
pub mod path;
1516
pub mod range;
1617

1718
pub fn plugin(app: &mut App) {
@@ -21,13 +22,14 @@ pub fn plugin(app: &mut App) {
2122
harvest::plugin,
2223
highlight::plugin,
2324
interactable::plugin,
25+
path::plugin,
2426
));
2527
}
2628

2729
#[derive(Component, Reflect)]
2830
#[reflect(Component)]
2931
#[require(
30-
PorterSpawnTimer(Timer::new(Duration::from_secs(5), TimerMode::Repeating)),
32+
PorterCooldown(Timer::new(Duration::from_secs(5), TimerMode::Once)),
3133
Demolishable
3234
)]
3335
pub struct Structure(pub Handle<StructureDef>);

0 commit comments

Comments
 (0)