* Get bevy 0.17 compiling and running (#72) * get bevy 0.17 compiling and running * try to fix CI breaking from const assertion for client/server features * fix `bin` -> `lib` for `shared` in CI * typo * fix some collider issues (#73) * Physics/controller improvements (#74) * trying to fix physics prediction * fixed prediction desync * substantial controller improvements * Finish off main bevy 0.17 migration (#75) * fix lookdir issues - airplane moving backwards - player model facing backwards - camera was technically backwards the whole time, and player models were facing the right way; camera is now facing forwards - firing without a target now respects lookdir * fix aim targeting * migrate to bevy_trenchbroom 0.10 crates release * fixed colliders not being adjusted out of worldspace * predict platforms to stop constant rollbacks while riding them * fix key/head drop visuals not working * Fix key/head drop random initial force * fixed static head drops duplicating * fix platform velocity inheritance * fix thrown projectiles not autorotating * fix inconsistent explosion animations * update avian3d to 0.4.1 * fix controller snapping to fixed angle upon switching heads * clean up commented code * fix broken physics positions * Clean comments, fix warnings (#77) * clean comments, fix warnings * fix missing import * steamworks 162 libs * fix mouselook --------- Co-authored-by: extrawurst <mail@rusticorn.com>
185 lines
5.7 KiB
Rust
185 lines
5.7 KiB
Rust
use crate::{
|
|
GameState, character::CharacterAnimations, head::ActiveHead, heads_database::HeadsDatabase,
|
|
};
|
|
use bevy::{animation::RepeatAnimation, ecs::query::QueryData, prelude::*};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::time::Duration;
|
|
|
|
pub fn plugin(app: &mut App) {
|
|
app.register_type::<AnimationFlags>();
|
|
|
|
app.add_systems(
|
|
Update,
|
|
update_animation.run_if(in_state(GameState::Playing)),
|
|
);
|
|
}
|
|
|
|
#[derive(Component, Default, Reflect, PartialEq, Serialize, Deserialize)]
|
|
#[reflect(Component)]
|
|
#[require(AnimationFlagCache)]
|
|
pub struct AnimationFlags {
|
|
pub any_direction: bool,
|
|
pub jumping: bool,
|
|
pub jump_count: u8,
|
|
pub shooting: bool,
|
|
pub restart_shooting: bool,
|
|
pub hit: bool,
|
|
}
|
|
|
|
#[derive(Component, Default, Reflect)]
|
|
#[reflect(Component)]
|
|
pub struct AnimationFlagCache {
|
|
pub jump_count: u8,
|
|
}
|
|
|
|
#[derive(QueryData)]
|
|
#[query_data(mutable)]
|
|
pub struct AnimationController {
|
|
pub transitions: &'static mut AnimationTransitions,
|
|
pub player: &'static mut AnimationPlayer,
|
|
}
|
|
|
|
impl AnimationController {
|
|
pub fn play_inner(
|
|
player: &mut AnimationPlayer,
|
|
transitions: &mut AnimationTransitions,
|
|
animation: AnimationNodeIndex,
|
|
transition: Duration,
|
|
repeat: RepeatAnimation,
|
|
) {
|
|
transitions
|
|
.play(player, animation, transition)
|
|
.set_repeat(repeat);
|
|
}
|
|
}
|
|
|
|
impl AnimationControllerItem<'_, '_> {
|
|
pub fn play(
|
|
&mut self,
|
|
animation: AnimationNodeIndex,
|
|
transition: Duration,
|
|
repeat: RepeatAnimation,
|
|
) {
|
|
AnimationController::play_inner(
|
|
&mut self.player,
|
|
&mut self.transitions,
|
|
animation,
|
|
transition,
|
|
repeat,
|
|
);
|
|
}
|
|
|
|
pub fn is_playing(&self, index: AnimationNodeIndex) -> bool {
|
|
self.player.is_playing_animation(index)
|
|
}
|
|
}
|
|
|
|
const DEFAULT_TRANSITION_DURATION: Duration = Duration::ZERO;
|
|
|
|
fn update_animation(
|
|
mut animated: Query<(AnimationController, &CharacterAnimations)>,
|
|
mut character: Query<(&ActiveHead, &mut AnimationFlags, &mut AnimationFlagCache)>,
|
|
headdb: Res<HeadsDatabase>,
|
|
) {
|
|
for (mut controller, anims) in animated.iter_mut() {
|
|
let (head, mut flags, mut cache) = character.get_mut(anims.of_character).unwrap();
|
|
let head = headdb.head_stats(head.0);
|
|
|
|
let is_playing_shoot = anims.shoot.is_some()
|
|
&& controller.is_playing(anims.shoot.unwrap())
|
|
&& !controller
|
|
.player
|
|
.animation(anims.shoot.unwrap())
|
|
.unwrap()
|
|
.is_finished();
|
|
let is_playing_run_shoot = anims.run_shoot.is_some()
|
|
&& controller.is_playing(anims.run_shoot.unwrap())
|
|
&& !controller
|
|
.player
|
|
.animation(anims.run_shoot.unwrap())
|
|
.unwrap()
|
|
.is_finished();
|
|
let wait_for_shoot = !head.interrupt_shoot && (is_playing_shoot || is_playing_run_shoot);
|
|
if wait_for_shoot {
|
|
return;
|
|
} else if flags.shooting && flags.any_direction && anims.run_shoot.is_some() {
|
|
if !controller.is_playing(anims.run_shoot.unwrap()) {
|
|
controller.play(
|
|
anims.run_shoot.unwrap(),
|
|
DEFAULT_TRANSITION_DURATION,
|
|
RepeatAnimation::Never,
|
|
);
|
|
}
|
|
if controller
|
|
.player
|
|
.animation(anims.run_shoot.unwrap())
|
|
.unwrap()
|
|
.is_finished()
|
|
|| flags.restart_shooting
|
|
{
|
|
controller
|
|
.player
|
|
.animation_mut(anims.run_shoot.unwrap())
|
|
.unwrap()
|
|
.replay();
|
|
|
|
flags.restart_shooting = false;
|
|
}
|
|
} else if flags.shooting && anims.shoot.is_some() {
|
|
if !controller.is_playing(anims.shoot.unwrap()) {
|
|
controller.play(
|
|
anims.shoot.unwrap(),
|
|
DEFAULT_TRANSITION_DURATION,
|
|
RepeatAnimation::Never,
|
|
);
|
|
}
|
|
if controller
|
|
.player
|
|
.animation(anims.shoot.unwrap())
|
|
.unwrap()
|
|
.is_finished()
|
|
|| flags.restart_shooting
|
|
{
|
|
controller
|
|
.player
|
|
.animation_mut(anims.shoot.unwrap())
|
|
.unwrap()
|
|
.replay();
|
|
|
|
flags.restart_shooting = false;
|
|
}
|
|
} else if flags.hit {
|
|
if !controller.is_playing(anims.hit) {
|
|
controller.play(
|
|
anims.hit,
|
|
DEFAULT_TRANSITION_DURATION,
|
|
RepeatAnimation::Never,
|
|
);
|
|
}
|
|
} else if flags.jumping {
|
|
if !controller.is_playing(anims.jump) || flags.jump_count != cache.jump_count {
|
|
controller.play(
|
|
anims.jump,
|
|
DEFAULT_TRANSITION_DURATION,
|
|
RepeatAnimation::Never,
|
|
);
|
|
cache.jump_count = flags.jump_count;
|
|
}
|
|
} else if flags.any_direction {
|
|
if !controller.player.is_playing_animation(anims.run) {
|
|
controller.play(
|
|
anims.run,
|
|
DEFAULT_TRANSITION_DURATION,
|
|
RepeatAnimation::Forever,
|
|
);
|
|
}
|
|
} else if !controller.is_playing(anims.idle) {
|
|
controller.play(
|
|
anims.idle,
|
|
DEFAULT_TRANSITION_DURATION,
|
|
RepeatAnimation::Forever,
|
|
);
|
|
}
|
|
}
|
|
}
|