|
|
|
|
@ -16,15 +16,19 @@ impl Plugin for TutorialPlugin {
|
|
|
|
|
)
|
|
|
|
|
.add_systems(
|
|
|
|
|
Update,
|
|
|
|
|
menu::handle_menu_button::<TutorialState>.run_if(in_state(GameState::Play)),
|
|
|
|
|
// Toggle the tutorial state iff we are in the play state and the tutorial button was pressed
|
|
|
|
|
toggle_tutorial_button.run_if(in_state(GameState::Play).and_then(
|
|
|
|
|
|buttons: Query<&Interaction, (With<Button>, With<Tutorial>, Changed<Interaction>)>| -> bool {
|
|
|
|
|
buttons.iter().any(|i| *i == Interaction::Pressed)
|
|
|
|
|
},
|
|
|
|
|
)),
|
|
|
|
|
)
|
|
|
|
|
.add_systems(
|
|
|
|
|
Update,
|
|
|
|
|
(
|
|
|
|
|
// Evaluate if a piece is selected
|
|
|
|
|
step.run_if(state_exists::<TutorialState>())
|
|
|
|
|
.run_if(not(in_state(TutorialState::None)))
|
|
|
|
|
.run_if(
|
|
|
|
|
step.run_if(
|
|
|
|
|
state_exists::<TutorialState>().and_then(
|
|
|
|
|
// A piece changes sides
|
|
|
|
|
any_component_changed::<game::Side>
|
|
|
|
|
// When a piece is selected, we
|
|
|
|
|
@ -37,12 +41,15 @@ impl Plugin for TutorialPlugin {
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
.add_systems(OnExit(GameState::Play), deactivate::<TutorialState>)
|
|
|
|
|
.add_systems(OnEnter(GameState::Play), activate::<Tutorial>)
|
|
|
|
|
.add_systems(
|
|
|
|
|
Update,
|
|
|
|
|
activate_tutorial_step.run_if(state_changed::<TutorialState>()),
|
|
|
|
|
activate_tutorial_step.run_if(
|
|
|
|
|
state_exists::<TutorialState>().and_then(state_changed::<TutorialState>()),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -54,9 +61,9 @@ pub(crate) struct Tutorial;
|
|
|
|
|
pub(crate) enum TutorialState {
|
|
|
|
|
#[default]
|
|
|
|
|
None,
|
|
|
|
|
Empty,
|
|
|
|
|
Intro,
|
|
|
|
|
Objective,
|
|
|
|
|
Empty,
|
|
|
|
|
PieceIntro,
|
|
|
|
|
PieceQueen,
|
|
|
|
|
PieceDrone,
|
|
|
|
|
@ -270,13 +277,13 @@ fn step(
|
|
|
|
|
|
|
|
|
|
info!("Curr: {:?}, Seen: {:?}", curr_state.get(), seen);
|
|
|
|
|
|
|
|
|
|
next_state.set(match curr_state.get() {
|
|
|
|
|
// This transition is implicit. Menu transitions from None to Intro
|
|
|
|
|
TutorialState::None => TutorialState::Intro,
|
|
|
|
|
match curr_state.get() {
|
|
|
|
|
// None does not go to Intro, that is controlled by the button handler
|
|
|
|
|
TutorialState::None => next_state.set(TutorialState::None),
|
|
|
|
|
// From Intro we always go to Objective
|
|
|
|
|
TutorialState::Intro => TutorialState::Objective,
|
|
|
|
|
TutorialState::Intro => next_state.set(TutorialState::Objective),
|
|
|
|
|
// From objective we go to the Pieces flow intro
|
|
|
|
|
TutorialState::Objective => TutorialState::PieceIntro,
|
|
|
|
|
TutorialState::Objective => next_state.set(TutorialState::PieceIntro),
|
|
|
|
|
// From PiecesIntro we can go to any other Pieces if a piece is selected
|
|
|
|
|
// Each pieces tutorial can transition to any other, as well as Ownership
|
|
|
|
|
TutorialState::PieceIntro
|
|
|
|
|
@ -304,7 +311,7 @@ fn step(
|
|
|
|
|
let pawn_seen = seen.0.contains(&TutorialState::PiecePawn);
|
|
|
|
|
|
|
|
|
|
// A piece is selected, so talk about it
|
|
|
|
|
if piece_selected {
|
|
|
|
|
let next = if piece_selected {
|
|
|
|
|
// When a queen is selected for the first time...
|
|
|
|
|
if queen_selected && !queen_seen {
|
|
|
|
|
TutorialState::PieceQueen
|
|
|
|
|
@ -335,14 +342,16 @@ fn step(
|
|
|
|
|
TutorialState::PieceEnd
|
|
|
|
|
// Default, empty (tutorial doesn't always need to show something)
|
|
|
|
|
} else {
|
|
|
|
|
TutorialState::Empty
|
|
|
|
|
}
|
|
|
|
|
TutorialState::PieceIntro
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
next_state.set(next);
|
|
|
|
|
}
|
|
|
|
|
// After the outro, we exit the tutorial
|
|
|
|
|
TutorialState::Outro => TutorialState::None,
|
|
|
|
|
TutorialState::Outro => next_state.set(TutorialState::None),
|
|
|
|
|
TutorialState::_Promotions => todo!("Not implemented yet!"),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn activate_tutorial_step(
|
|
|
|
|
@ -363,29 +372,15 @@ fn activate_tutorial_step(
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start by loading the same game as display3d does
|
|
|
|
|
|
|
|
|
|
// Show the intro text when entering Intro TutorialState
|
|
|
|
|
// Continue
|
|
|
|
|
|
|
|
|
|
// Show objective when entering Objective TutorialState
|
|
|
|
|
// Continue
|
|
|
|
|
|
|
|
|
|
// Prompt user to click some pieces
|
|
|
|
|
// When each piece type is clicked, show relevant text
|
|
|
|
|
// Once all pieces are described say jumping text
|
|
|
|
|
// Finally end with final text
|
|
|
|
|
// Continue
|
|
|
|
|
|
|
|
|
|
// When a piece crosses the canal, show ownership text
|
|
|
|
|
// Continue
|
|
|
|
|
|
|
|
|
|
// A few moves in, show field promotions text
|
|
|
|
|
// Continue
|
|
|
|
|
|
|
|
|
|
// End with outro text
|
|
|
|
|
// Continue
|
|
|
|
|
|
|
|
|
|
// Play game out as usual
|
|
|
|
|
|
|
|
|
|
// If player early exits, set TutorialState to None
|
|
|
|
|
// Toggles the menu on/off by inserting/removing the Tutorial state
|
|
|
|
|
fn toggle_tutorial_button(
|
|
|
|
|
state: Res<State<TutorialState>>,
|
|
|
|
|
mut next_state: ResMut<NextState<TutorialState>>,
|
|
|
|
|
) {
|
|
|
|
|
match state.get() {
|
|
|
|
|
// If inactive, start the intro
|
|
|
|
|
TutorialState::None => next_state.set(TutorialState::Intro),
|
|
|
|
|
// Else, revert to None state
|
|
|
|
|
_ => next_state.set(TutorialState::None),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|