use different head drop meshes

This commit is contained in:
2025-06-06 10:15:45 +02:00
parent 67320b3be4
commit 6e8e995da5
4 changed files with 66 additions and 38 deletions

View File

@@ -1,6 +1,6 @@
use crate::{
GameState, billboards::Billboard, global_observer, loading_assets::GameAssets,
physics_layers::GameLayer, player::Player, sounds::PlaySound,
GameState, billboards::Billboard, global_observer, heads_database::HeadsDatabase,
loading_assets::HeadDropAssets, physics_layers::GameLayer, player::Player, sounds::PlaySound,
squish_animation::SquishAnimation, tb_entities::SecretHead,
};
use avian3d::prelude::*;
@@ -8,7 +8,29 @@ use bevy::prelude::*;
use std::f32::consts::PI;
#[derive(Event, Reflect)]
pub struct HeadDrops(pub Vec3, pub usize);
pub struct HeadDrops {
pos: Vec3,
head_id: usize,
impulse: bool,
}
impl HeadDrops {
pub fn new(pos: Vec3, head_id: usize) -> Self {
Self {
pos,
head_id,
impulse: true,
}
}
fn new_static(pos: Vec3, head_id: usize) -> Self {
Self {
pos,
head_id,
impulse: false,
}
}
}
#[derive(Component, Reflect)]
#[reflect(Component)]
@@ -28,63 +50,65 @@ pub fn plugin(app: &mut App) {
global_observer!(app, on_head_drop);
}
fn spawn(
mut commands: Commands,
query: Query<(Entity, &GlobalTransform, &SecretHead)>,
assets: Res<GameAssets>,
) {
fn spawn(mut commands: Commands, query: Query<(Entity, &GlobalTransform, &SecretHead)>) {
for (e, t, head) in query {
commands
.spawn((
Name::new("headdrop"),
SecretHeadMarker,
HeadDrop(head.head_id),
Transform::from_translation(t.translation() + Vec3::new(0., 2., 0.)),
Visibility::default(),
Collider::sphere(1.5),
LockedAxes::ROTATION_LOCKED,
RigidBody::Dynamic,
CollisionLayers::new(LayerMask(GameLayer::Collectibles.to_bits()), LayerMask::ALL),
CollisionEventsEnabled,
Restitution::new(0.6),
))
.with_child((
Billboard,
SquishAnimation(2.6),
SceneRoot(assets.mesh_head_drop.clone()),
));
commands.trigger(HeadDrops::new_static(
t.translation() + Vec3::new(0., 2., 0.),
head.head_id,
));
commands.entity(e).despawn();
}
}
fn on_head_drop(trigger: Trigger<HeadDrops>, mut commands: Commands, assets: Res<GameAssets>) {
let HeadDrops(position, id) = trigger.event();
fn on_head_drop(
trigger: Trigger<HeadDrops>,
mut commands: Commands,
assets: Res<HeadDropAssets>,
heads_db: Res<HeadsDatabase>,
gltf_assets: Res<Assets<Gltf>>,
) -> Result<(), BevyError> {
let drop = trigger.event();
let angle = rand::random::<f32>() * PI * 2.;
let spawn_dir = Quat::from_rotation_y(angle) * Vec3::new(0.5, 0.6, 0.).normalize();
commands.trigger(PlaySound::HeadDrop);
if drop.impulse {
commands.trigger(PlaySound::HeadDrop);
}
let ability = format!("{:?}.glb", heads_db.head_stats(drop.head_id).ability).to_lowercase();
let mesh = if let Some(handle) = assets.meshes.get(ability.as_str()) {
gltf_assets.get(handle)
} else {
gltf_assets.get(&assets.meshes["none.glb"])
}
.ok_or_else(|| "asset not found")?;
commands
.spawn((
Name::new("headdrop"),
HeadDrop(*id),
Transform::from_translation(*position),
HeadDrop(drop.head_id),
Transform::from_translation(drop.pos),
Visibility::default(),
Collider::sphere(1.5),
ExternalImpulse::new(spawn_dir * 180.).with_persistence(false),
LockedAxes::ROTATION_LOCKED,
RigidBody::Dynamic,
CollisionLayers::new(LayerMask(GameLayer::Collectibles.to_bits()), LayerMask::ALL),
CollisionEventsEnabled,
Restitution::new(0.6),
))
.insert_if(
ExternalImpulse::new(spawn_dir * 180.).with_persistence(false),
|| drop.impulse,
)
.with_child((
Billboard,
SquishAnimation(2.6),
SceneRoot(assets.mesh_head_drop.clone()),
SceneRoot(mesh.scenes[0].clone()),
));
Ok(())
}
fn collect_head(