split control system into control and action systems

This commit is contained in:
Vivian Lim 2020-10-28 23:40:21 -07:00
parent 838bc12ea9
commit 293f2aaa25
3 changed files with 94 additions and 33 deletions

78
src/action_system.rs Normal file
View File

@ -0,0 +1,78 @@
use specs::prelude::*;
use specs_derive::*;
use super::{Powered, RunState, gamelog::GameLog, components::*};
use serde::{Serialize, Deserialize};
use std::collections::VecDeque;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum EntityAction {
Move(Movement, EntityTargetAction), // dx, dy
ActOnSelf(EntityTargetAction),
PowerConsumingAction(Box<EntityAction>, f32)
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum EntityTargetAction {
InSequenceUntilFailure(Vec<EntityTargetAction>),
AllInSequence(Vec<EntityTargetAction>),
ToggleInGrid(bool),
ToggleEnabled(bool),
Move(Movement),
None
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Movement {
dx: i32,
dy: i32,
blocked_by_walls: bool,
}
#[derive(Component, Debug, Serialize, Deserialize, Clone)]
pub struct Actions {
pub action_queue: VecDeque<EntityAction>
}
// A system responsible for executing actions by mapping them to intent components or directly changing the world
pub struct ActionSystem {}
impl<'a> System<'a> for ActionSystem {
#[allow(clippy::type_complexity)]
type SystemData = (
Entities<'a>,
WriteStorage<'a, Actions>,
WriteStorage<'a, Powered>,
WriteStorage<'a, Position>,
WriteStorage<'a, WantsToInteract>,
ReadExpect<'a, RunState>,
WriteExpect<'a, GameLog>
);
fn run(&mut self, data : Self::SystemData) {
let (entities,
mut actions,
mut powered,
mut position,
mut wantstointeract,
runstate,
mut log) = data;
for (entity, actions, power, position) in (&entities, &mut actions, (&mut powered).maybe(), (&mut position).maybe()).join() {
while !actions.action_queue.is_empty(){
if let Some(action) = actions.action_queue.pop_front(){
match action {
EntityAction::Move(movement, entityTargetAction) => {
// todo: try moving, see if anything else is there, and if so do the target action to it
// need to read player::try_move_player again and really get what's going on there.
}
EntityAction::ActOnSelf(_) => {} // todo: do the target action to yourself
EntityAction::PowerConsumingAction(_, _) => {} // todo: see if power cost is met, deduct it, and then do the inner action
}
}
}
}
}
}

View File

@ -1,6 +1,6 @@
use specs::prelude::*;
use specs_derive::*;
use super::{Powered, RunState, gamelog::GameLog};
use super::{Powered, RunState, gamelog::GameLog, action_system::EntityAction, action_system::Actions};
use serde::{Serialize, Deserialize};
use std::collections::VecDeque;
@ -12,11 +12,11 @@ pub struct Controlled {
pub right: Option<EntityAction>,
pub primary: Option<EntityAction>,
pub secondary: Option<EntityAction>,
pub action_queue: VecDeque<RequestedAction>,
pub input_queue: VecDeque<RequestedInput>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum RequestedAction {
pub enum RequestedInput {
Up,
Down,
Left,
@ -25,30 +25,7 @@ pub enum RequestedAction {
Secondary,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum EntityAction {
Move(Movement, EntityTargetAction), // dx, dy
ActOnSelf(EntityTargetAction),
PowerConsumingAction(Box<EntityAction>, f32)
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum EntityTargetAction {
InSequenceUntilFailure(Vec<EntityTargetAction>),
AllInSequence(Vec<EntityTargetAction>),
ToggleInGrid(bool),
ToggleEnabled(bool),
Move(Movement),
None
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Movement {
dx: i32,
dy: i32,
blocked_by_walls: bool,
}
// A system responsible for converting user inputs into actions.
pub struct ControlSystem {}
impl<'a> System<'a> for ControlSystem {
@ -56,17 +33,17 @@ impl<'a> System<'a> for ControlSystem {
type SystemData = (
Entities<'a>,
WriteStorage<'a, Controlled>,
WriteStorage<'a, Powered>,
WriteStorage<'a, Actions>,
ReadExpect<'a, RunState>,
WriteExpect<'a, GameLog>
);
fn run(&mut self, data : Self::SystemData) {
let (entities, mut controllable, mut powered, runstate, mut log) = data;
let (entities, mut controllable, mut actions, runstate, mut log) = data;
if let RunState::PlayerTurn = *runstate {
for (entity, control, power) in (&entities, &mut controllable, (&mut powered).maybe()).join() {
let action_taken_by_entity_maybe: Option<&Option<EntityAction>> = match &(control.action_queue.pop_back()) {
if let RunState::PlayerTurn = *runstate { // maybe need to revisit this. what is this, exactly? idle?
for (entity, control, power) in (&entities, &mut controllable, (&mut actions).maybe()).join() {
let action_taken_by_entity_maybe: Option<&Option<EntityAction>> = match &(control.input_queue.pop_back()) {
Some(action) => match action {
Up => Some(&control.up),
Down => Some(&control.down),
@ -79,14 +56,18 @@ impl<'a> System<'a> for ControlSystem {
};
if let Some(Some(action_taken_by_entity)) = action_taken_by_entity_maybe {
// TODO put these into the Action component and create it if it doesn't exist.
/*
self.execute_action(&mut data);
match action_taken_by_entity {
EntityAction::Move(_, _) => {} // todo: try moving, see if anything else is there, and if so do the target action to it
EntityAction::ActOnSelf(_) => {} // todo: do the target action to yourself
EntityAction::PowerConsumingAction(_, _) => {} // todo: see if power cost is met, deduct it, and then do the inner action
// need some recursive function to do this probably
}
*/
}
}
}
}
}
}

View File

@ -23,6 +23,8 @@ mod power_system;
use power_system::PowerSystem;
mod control_system;
use control_system::ControlSystem;
mod action_system;
use action_system::ActionSystem;
pub use control_system::Controlled; // this component is defined in control_system
mod damage_system;
use damage_system::DamageSystem;