Skip to content

Commit 1909727

Browse files
authored
feat: add profession concept, migrate harvesting and porting (#93)
1 parent 7fc9efc commit 1909727

22 files changed

+534
-254
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
id = "foragers_outpost"
2+
name = "Forager's Outpost"

assets/manifests/structures/harvester.structure.toml

Lines changed: 0 additions & 2 deletions
This file was deleted.
File renamed without changes.

assets/sprites/structures/harvester_fauna.aseprite renamed to assets/sprites/structures/foragers_outpost_fauna.aseprite

File renamed without changes.

assets/sprites/structures/harvester_flora.aseprite renamed to assets/sprites/structures/foragers_outpost_flora.aseprite

File renamed without changes.

assets/sprites/structures/harvester_minerale.aseprite renamed to assets/sprites/structures/foragers_outpost_minerale.aseprite

File renamed without changes.

src/gameplay/item/inventory.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,3 @@ use crate::gameplay::item::assets::ItemDef;
99
pub struct Inventory {
1010
pub items: HashMap<AssetId<ItemDef>, u32>,
1111
}
12-
13-
impl Inventory {
14-
pub fn with_single(item_id: AssetId<ItemDef>, amount: u32) -> Self {
15-
Self {
16-
items: HashMap::from([(item_id, amount)]),
17-
}
18-
}
19-
}

src/gameplay/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub fn plugin(app: &mut App) {
2424
FixedUpdate,
2525
(
2626
FactorySystems::Construction,
27-
FactorySystems::Harvest,
27+
FactorySystems::Forage,
2828
FactorySystems::Logistics,
2929
FactorySystems::Work,
3030
FactorySystems::Demolish,
@@ -50,7 +50,7 @@ pub fn plugin(app: &mut App) {
5050
#[derive(SystemSet, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
5151
pub enum FactorySystems {
5252
Construction,
53-
Harvest,
53+
Forage,
5454
Logistics,
5555
Work,
5656
Demolish,

src/gameplay/people/foraging.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
use bevy::prelude::*;
2+
3+
use crate::gameplay::{
4+
FactorySystems,
5+
item::inventory::Inventory,
6+
people::{Assignment, Forager, Person},
7+
structure::{
8+
deposit::{Deposit, DepositDef},
9+
foragers_outpost::ForagersOutpost,
10+
range::Range,
11+
},
12+
world::{construction::Constructions, tilemap::coord::Coord},
13+
};
14+
15+
pub(super) fn plugin(app: &mut App) {
16+
app.add_systems(
17+
FixedUpdate,
18+
(
19+
assign_deposit_to_forager,
20+
forage_deposit,
21+
cleanup_empty_deposits,
22+
)
23+
.chain()
24+
.in_set(FactorySystems::Forage),
25+
);
26+
}
27+
28+
#[derive(Component, Reflect, Debug)]
29+
#[reflect(Component)]
30+
#[relationship_target(relationship = Forages)]
31+
pub struct ForagedBy(Vec<Entity>);
32+
33+
#[derive(Component, Reflect, Debug)]
34+
#[reflect(Component)]
35+
#[relationship(relationship_target = ForagedBy)]
36+
#[require(ForagingTimer(Timer::from_seconds(1.0, TimerMode::Repeating)))]
37+
pub struct Forages(pub Entity);
38+
39+
#[derive(Component, Reflect, Debug)]
40+
#[reflect(Component)]
41+
pub struct ForagingTimer(pub Timer);
42+
43+
fn assign_deposit_to_forager(
44+
foragers: Query<(Entity, &Assignment), (With<Person>, With<Forager>, Without<Forages>)>,
45+
foragers_outposts: Query<(&Coord, &Range), With<ForagersOutpost>>,
46+
deposit_query: Query<Entity, With<Deposit>>,
47+
constructions: Res<Constructions>,
48+
mut commands: Commands,
49+
) {
50+
for (person, assignment) in foragers {
51+
let Ok((coord, range)) = foragers_outposts.get(assignment.structure) else {
52+
continue;
53+
};
54+
55+
let Some(deposit) = range.iter(coord.0).find_map(|pos| {
56+
constructions
57+
.get(&pos)
58+
.and_then(|d| deposit_query.get(*d).ok())
59+
}) else {
60+
continue;
61+
};
62+
63+
commands.entity(person).insert(Forages(deposit));
64+
}
65+
}
66+
67+
fn forage_deposit(
68+
foragers: Query<(&Forages, &mut ForagingTimer, &Assignment), With<Person>>,
69+
mut foragers_outpost: Query<&mut Inventory>,
70+
mut deposits: Query<&mut Deposit>,
71+
deposit_definitions: Res<Assets<DepositDef>>,
72+
time: Res<Time>,
73+
) {
74+
for (forages, mut foraging_timer, assignment) in foragers {
75+
if !foraging_timer.0.tick(time.delta()).just_finished() {
76+
continue;
77+
}
78+
79+
let Ok(mut foragers_outpost_inventory) = foragers_outpost.get_mut(assignment.structure)
80+
else {
81+
continue;
82+
};
83+
84+
let Ok(mut deposit) = deposits.get_mut(forages.0) else {
85+
continue;
86+
};
87+
88+
let Some(deposit_def) = deposit_definitions.get(&deposit.handle) else {
89+
continue;
90+
};
91+
92+
if deposit.quantity == 0 {
93+
continue;
94+
}
95+
96+
deposit.quantity -= 1;
97+
98+
foragers_outpost_inventory
99+
.items
100+
.entry(deposit_def.item_id)
101+
.and_modify(|v| *v += 1)
102+
.or_insert(1);
103+
}
104+
}
105+
106+
fn cleanup_empty_deposits(
107+
deposits: Query<(Entity, &Deposit, &Coord)>,
108+
mut constructions: ResMut<Constructions>,
109+
mut commands: Commands,
110+
) {
111+
for (entity, deposit, coord) in deposits {
112+
if deposit.quantity == 0 {
113+
constructions.remove(coord);
114+
commands.entity(entity).despawn();
115+
}
116+
}
117+
}

src/gameplay/people/mod.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,25 @@ use bevy::prelude::*;
22

33
use crate::gameplay::{people::naming::NameManager, world::construction::StructureConstructed};
44

5+
pub mod foraging;
56
pub mod naming;
67
pub mod pathfinding;
78
pub mod porting;
9+
pub mod profession;
10+
11+
pub use profession::{
12+
AssignPerson, Assignees, Assignment, Forager, PersonAssignmentChanged, Porter, Profession,
13+
UnassignPerson,
14+
};
815

916
pub(super) fn plugin(app: &mut App) {
10-
app.add_plugins((naming::plugin, pathfinding::plugin, porting::plugin));
17+
app.add_plugins((
18+
foraging::plugin,
19+
naming::plugin,
20+
pathfinding::plugin,
21+
porting::plugin,
22+
profession::plugin,
23+
));
1124

1225
app.add_systems(
1326
FixedUpdate,
@@ -19,24 +32,22 @@ pub(super) fn plugin(app: &mut App) {
1932
#[reflect(Component)]
2033
pub struct Person;
2134

22-
#[derive(Component, Reflect, Debug)]
23-
#[reflect(Component)]
24-
#[relationship_target(relationship = HousedIn, linked_spawn)]
25-
pub struct Houses(Vec<Entity>);
26-
27-
#[derive(Component, Reflect, Debug)]
28-
#[reflect(Component)]
29-
#[relationship(relationship_target = Houses)]
30-
pub struct HousedIn(pub Entity);
31-
3235
fn add_housed_people_to_new_structures(
3336
mut structures_constructed: MessageReader<StructureConstructed>,
3437
mut commands: Commands,
3538
mut name_manager: ResMut<NameManager>,
3639
) {
3740
for StructureConstructed(structure) in structures_constructed.read() {
3841
for _ in 0..3 {
39-
commands.spawn((Name::new(name_manager.next()), Person, HousedIn(*structure)));
42+
let id = commands
43+
.spawn((Name::new(name_manager.next()), Person))
44+
.id();
45+
46+
commands.trigger(AssignPerson {
47+
person: id,
48+
structure: *structure,
49+
profession: Profession::Porter,
50+
});
4051
}
4152
}
4253
}

0 commit comments

Comments
 (0)