195 lines
5.5 KiB
Rust
195 lines
5.5 KiB
Rust
use avian3d::prelude::*;
|
|
use bevy::{
|
|
ecs::{component::HookContext, world::DeferredWorld},
|
|
math::*,
|
|
prelude::*,
|
|
};
|
|
use bevy_trenchbroom::prelude::*;
|
|
|
|
use crate::cash::Cash;
|
|
use crate::loading_assets::GameAssets;
|
|
use crate::physics_layers::GameLayer;
|
|
|
|
#[derive(PointClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform)]
|
|
#[component(on_add = Self::on_add)]
|
|
#[model({ "path": "models/spawn.glb" })]
|
|
pub struct SpawnPoint {}
|
|
|
|
impl SpawnPoint {
|
|
fn on_add(mut world: DeferredWorld, HookContext { entity, .. }: HookContext) {
|
|
let Some(assets) = world.get_resource::<GameAssets>() else {
|
|
return;
|
|
};
|
|
|
|
let mesh = assets.mesh_spawn.clone();
|
|
|
|
world.commands().entity(entity).insert((
|
|
Name::new("spawn"),
|
|
SceneRoot(mesh),
|
|
RigidBody::Static,
|
|
ColliderConstructorHierarchy::new(ColliderConstructor::ConvexHullFromMesh),
|
|
));
|
|
}
|
|
}
|
|
|
|
#[derive(SolidClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[geometry(GeometryProvider::new().convex_collider())]
|
|
pub struct Worldspawn;
|
|
|
|
#[derive(SolidClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[geometry(GeometryProvider::new())]
|
|
#[base(Transform)]
|
|
pub struct Water;
|
|
|
|
#[derive(SolidClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform)]
|
|
#[geometry(GeometryProvider::new().convex_collider())]
|
|
pub struct Crates;
|
|
|
|
#[derive(SolidClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform)]
|
|
#[geometry(GeometryProvider::new().convex_collider())]
|
|
pub struct NamedEntity {
|
|
pub name: String,
|
|
}
|
|
|
|
#[derive(SolidClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform, Target)]
|
|
#[geometry(GeometryProvider::new().convex_collider())]
|
|
pub struct Platform;
|
|
|
|
#[derive(PointClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform)]
|
|
pub struct PlatformTarget {
|
|
pub targetname: String,
|
|
}
|
|
|
|
#[derive(SolidClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform, Target)]
|
|
#[geometry(GeometryProvider::new().convex_collider())]
|
|
pub struct Movable {
|
|
pub name: String,
|
|
}
|
|
|
|
#[derive(PointClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform)]
|
|
pub struct MoveTarget {
|
|
pub targetname: String,
|
|
}
|
|
|
|
#[derive(PointClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform)]
|
|
pub struct CameraTarget {
|
|
pub targetname: String,
|
|
}
|
|
|
|
#[derive(PointClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform, Target)]
|
|
pub struct CutsceneCamera {
|
|
pub name: String,
|
|
pub targetname: String,
|
|
}
|
|
|
|
#[derive(PointClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform, Target)]
|
|
pub struct CutsceneCameraMovementEnd;
|
|
|
|
#[derive(PointClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform)]
|
|
#[component(on_add = Self::on_add)]
|
|
#[model({ "path": "models/alien_naked.glb" })]
|
|
pub struct EnemySpawn {
|
|
pub head: String,
|
|
pub key: String,
|
|
pub disable_ai: bool,
|
|
}
|
|
|
|
impl EnemySpawn {
|
|
fn on_add(mut world: DeferredWorld, HookContext { entity, .. }: HookContext) {
|
|
//TODO: figure out why this crashes if removed
|
|
let Some(_assets) = world.get_resource::<GameAssets>() else {
|
|
return;
|
|
};
|
|
|
|
let this = world.get_entity(entity).unwrap().get::<Self>().unwrap();
|
|
let this_transform = world
|
|
.get_entity(entity)
|
|
.unwrap()
|
|
.get::<Transform>()
|
|
.unwrap();
|
|
|
|
let mut this_transform = *this_transform;
|
|
this_transform.translation += Vec3::new(0., 1.5, 0.);
|
|
|
|
let head = this.head.clone();
|
|
|
|
world.commands().entity(entity).insert((
|
|
this_transform,
|
|
Name::from(format!("enemy [{}]", head)),
|
|
Visibility::default(),
|
|
RigidBody::Dynamic,
|
|
Collider::capsule(0.6, 2.),
|
|
CollisionLayers::new(LayerMask(GameLayer::Npc.to_bits()), LayerMask::ALL),
|
|
LockedAxes::new().lock_rotation_z().lock_rotation_x(),
|
|
));
|
|
}
|
|
}
|
|
|
|
#[derive(PointClass, Component, Reflect, Default)]
|
|
#[reflect(QuakeClass, Component)]
|
|
#[base(Transform)]
|
|
#[component(on_add = Self::on_add)]
|
|
#[model({ "path": "models/cash.glb" })]
|
|
pub struct CashSpawn {}
|
|
|
|
impl CashSpawn {
|
|
fn on_add(mut world: DeferredWorld, HookContext { entity, .. }: HookContext) {
|
|
let Some(assets) = world.get_resource::<GameAssets>() else {
|
|
return;
|
|
};
|
|
|
|
let mesh = assets.mesh_cash.clone();
|
|
|
|
world.commands().entity(entity).insert((
|
|
Name::new("cash"),
|
|
SceneRoot(mesh),
|
|
Cash,
|
|
Collider::cuboid(2., 3.0, 2.),
|
|
CollisionLayers::new(LayerMask(GameLayer::Collectibles.to_bits()), LayerMask::ALL),
|
|
CollisionEventsEnabled,
|
|
Sensor,
|
|
));
|
|
}
|
|
}
|
|
|
|
pub fn plugin(app: &mut App) {
|
|
app.register_type::<SpawnPoint>();
|
|
app.register_type::<Worldspawn>();
|
|
app.register_type::<Water>();
|
|
app.register_type::<Crates>();
|
|
app.register_type::<NamedEntity>();
|
|
app.register_type::<Platform>();
|
|
app.register_type::<PlatformTarget>();
|
|
app.register_type::<Movable>();
|
|
app.register_type::<MoveTarget>();
|
|
app.register_type::<CameraTarget>();
|
|
app.register_type::<CutsceneCamera>();
|
|
app.register_type::<CutsceneCameraMovementEnd>();
|
|
app.register_type::<EnemySpawn>();
|
|
app.register_type::<CashSpawn>();
|
|
}
|