diff --git a/assets/elements/item/periscope/bullet/periscope.bullet.yaml b/assets/elements/item/periscope/bullet/periscope.bullet.yaml new file mode 100644 index 0000000000..05d98c20a2 --- /dev/null +++ b/assets/elements/item/periscope/bullet/periscope.bullet.yaml @@ -0,0 +1,11 @@ +lifetime: 1.0 +speed: 600 +body_diameter: 15 +atlas: ./periscope_bullet.atlas.yaml + +explosion_fps: 12 +explosion_frames: 3 +explosion_volume: 0.025 +explosion_lifetime: 0.4 +explosion_sound: ../explosion/bullet_hit_dull.ogg +explosion_atlas: ../explosion/explosion.atlas.yaml diff --git a/assets/elements/item/periscope/bullet/periscope_bullet.atlas.yaml b/assets/elements/item/periscope/bullet/periscope_bullet.atlas.yaml new file mode 100644 index 0000000000..03106a1307 --- /dev/null +++ b/assets/elements/item/periscope/bullet/periscope_bullet.atlas.yaml @@ -0,0 +1,4 @@ +image: ./periscope_bullet.png +tile_size: [15, 15] +rows: 1 +columns: 1 diff --git a/assets/elements/item/periscope/bullet/periscope_bullet.png b/assets/elements/item/periscope/bullet/periscope_bullet.png new file mode 100644 index 0000000000..72ab91e931 Binary files /dev/null and b/assets/elements/item/periscope/bullet/periscope_bullet.png differ diff --git a/assets/elements/item/periscope/explosion/bullet_hit_dull.ogg b/assets/elements/item/periscope/explosion/bullet_hit_dull.ogg new file mode 100644 index 0000000000..572186bf98 Binary files /dev/null and b/assets/elements/item/periscope/explosion/bullet_hit_dull.ogg differ diff --git a/assets/elements/item/periscope/explosion/explosion.atlas.yaml b/assets/elements/item/periscope/explosion/explosion.atlas.yaml new file mode 100644 index 0000000000..1d4bda39a2 --- /dev/null +++ b/assets/elements/item/periscope/explosion/explosion.atlas.yaml @@ -0,0 +1,4 @@ +image: ./explosion.png +tile_size: [21, 21] +rows: 1 +columns: 4 diff --git a/assets/elements/item/periscope/explosion/explosion.png b/assets/elements/item/periscope/explosion/explosion.png new file mode 100644 index 0000000000..5877871eca Binary files /dev/null and b/assets/elements/item/periscope/explosion/explosion.png differ diff --git a/assets/elements/item/periscope/periscope.atlas.yaml b/assets/elements/item/periscope/periscope.atlas.yaml new file mode 100644 index 0000000000..326633c803 --- /dev/null +++ b/assets/elements/item/periscope/periscope.atlas.yaml @@ -0,0 +1,4 @@ +image: ./periscope.png +tile_size: [50, 74] +rows: 1 +columns: 1 diff --git a/assets/elements/item/periscope/periscope.element.yaml b/assets/elements/item/periscope/periscope.element.yaml new file mode 100644 index 0000000000..f18d56e07b --- /dev/null +++ b/assets/elements/item/periscope/periscope.element.yaml @@ -0,0 +1,3 @@ +name: Periscope +category: Weapons +data: periscope.yaml diff --git a/assets/elements/item/periscope/periscope.png b/assets/elements/item/periscope/periscope.png new file mode 100644 index 0000000000..b8b2b9b79c Binary files /dev/null and b/assets/elements/item/periscope/periscope.png differ diff --git a/assets/elements/item/periscope/periscope.yaml b/assets/elements/item/periscope/periscope.yaml new file mode 100644 index 0000000000..905e330a8f --- /dev/null +++ b/assets/elements/item/periscope/periscope.yaml @@ -0,0 +1,23 @@ +atlas: ./periscope.atlas.yaml + +max_ammo: 6 +cooldown: 700ms +bullet_meta: ./bullet/periscope.bullet.yaml + +shoot_fps: 15 +shoot_frames: 3 +shoot_lifetime: 0.2 +shoot_sound_volume: 0.1 +shoot_sound: ./shoot/shoot.ogg +empty_shoot_sound_volume: 0.1 +empty_shoot_sound: ./shoot/gun_empty.ogg +shoot_atlas: ./shoot/periscope_shoot.atlas.yaml + +bounciness: 0.3 +can_rotate: true +body_size: [32, 44] +fin_anim: grab_2 +angular_velocity: 0.1 +throw_velocity: 180 +grab_offset: [-2, 24] +kickback: 0 diff --git a/assets/elements/item/periscope/shoot/gun_empty.ogg b/assets/elements/item/periscope/shoot/gun_empty.ogg new file mode 100644 index 0000000000..5e4e182a59 Binary files /dev/null and b/assets/elements/item/periscope/shoot/gun_empty.ogg differ diff --git a/assets/elements/item/periscope/shoot/periscope_fire.png b/assets/elements/item/periscope/shoot/periscope_fire.png new file mode 100644 index 0000000000..379cb8614e Binary files /dev/null and b/assets/elements/item/periscope/shoot/periscope_fire.png differ diff --git a/assets/elements/item/periscope/shoot/periscope_shoot.atlas.yaml b/assets/elements/item/periscope/shoot/periscope_shoot.atlas.yaml new file mode 100644 index 0000000000..dfaacb312f --- /dev/null +++ b/assets/elements/item/periscope/shoot/periscope_shoot.atlas.yaml @@ -0,0 +1,4 @@ +image: ./periscope_fire.png +tile_size: [25, 30] +rows: 1 +columns: 4 diff --git a/assets/elements/item/periscope/shoot/shoot.ogg b/assets/elements/item/periscope/shoot/shoot.ogg new file mode 100644 index 0000000000..dd90956768 Binary files /dev/null and b/assets/elements/item/periscope/shoot/shoot.ogg differ diff --git a/assets/game.yaml b/assets/game.yaml index 8a8fb17206..68048afe0d 100644 --- a/assets/game.yaml +++ b/assets/game.yaml @@ -348,6 +348,7 @@ core: - /elements/item/mine/mine.element.yaml - /elements/item/musket/musket.element.yaml - /elements/item/buss/buss.element.yaml + - /elements/item/periscope/periscope.element.yaml - /elements/item/stomp_boots/stomp_boots.element.yaml - /elements/item/sword/sword.element.yaml - /elements/item/sniper_rifle/sniper_rifle.element.yaml diff --git a/assets/map/levels/level_7.map.yaml b/assets/map/levels/level_7.map.yaml index 0854e757c4..7b15a1b797 100644 --- a/assets/map/levels/level_7.map.yaml +++ b/assets/map/levels/level_7.map.yaml @@ -1185,7 +1185,7 @@ layers: - pos: - 712.0 - 182.5 - element: /elements/item/buss/buss.element.yaml + element: /elements/item/periscope/periscope.element.yaml - pos: - 552.0 - 438.5 diff --git a/src/core/elements.rs b/src/core/elements.rs index 918da3244c..e15734337c 100644 --- a/src/core/elements.rs +++ b/src/core/elements.rs @@ -17,6 +17,7 @@ pub mod jellyfish; pub mod kick_bomb; pub mod mine; pub mod musket; +pub mod periscope; pub mod player_spawner; pub mod slippery; pub mod slippery_seaweed; @@ -30,8 +31,9 @@ pub mod urchin; pub mod prelude { pub use super::{ buss::*, crab::*, crate_item::*, decoration::*, fish_school::*, grenade::*, jellyfish::*, - kick_bomb::*, mine::*, musket::*, player_spawner::*, slippery::*, slippery_seaweed::*, - snail::*, spike::*, sproinger::*, stomp_boots::*, sword::*, urchin::*, *, + kick_bomb::*, mine::*, musket::*, periscope::*, player_spawner::*, slippery::*, + slippery_seaweed::*, snail::*, spike::*, sproinger::*, stomp_boots::*, sword::*, urchin::*, + *, }; } @@ -317,6 +319,7 @@ install_plugins!( musket, buss, player_spawner, + periscope, slippery_seaweed, slippery, snail, diff --git a/src/core/elements/periscope.rs b/src/core/elements/periscope.rs new file mode 100644 index 0000000000..820f7e8927 --- /dev/null +++ b/src/core/elements/periscope.rs @@ -0,0 +1,288 @@ +use crate::prelude::*; + +#[derive(HasSchema, Default, Debug, Clone)] +#[type_data(metadata_asset("periscope"))] +#[repr(C)] +pub struct PeriscopeMeta { + pub grab_offset: Vec2, + pub fin_anim: Ustr, + + pub body_size: Vec2, + pub bounciness: f32, + pub can_rotate: bool, + pub throw_velocity: f32, + pub angular_velocity: f32, + pub atlas: Handle, + + pub max_ammo: u32, + pub cooldown: Duration, + pub bullet_meta: Handle, + pub kickback: f32, + + pub shoot_fps: f32, + pub shoot_lifetime: f32, + pub shoot_frames: u32, + pub shoot_sound_volume: f64, + pub empty_shoot_sound_volume: f64, + pub shoot_atlas: Handle, + pub shoot_sound: Handle, + pub empty_shoot_sound: Handle, +} + +pub fn game_plugin(game: &mut Game) { + PeriscopeMeta::register_schema(); + game.init_shared_resource::(); +} + +pub fn session_plugin(session: &mut Session) { + session + .stages + .add_system_to_stage(CoreStage::PreUpdate, hydrate) + .add_system_to_stage(CoreStage::PostUpdate, update); +} + +#[derive(Clone, Debug, HasSchema, Default)] +pub struct Periscope { + pub ammo: u32, + pub cooldown: Timer, +} + +fn hydrate( + game_meta: Root, + mut entities: ResMutInit, + mut hydrated: CompMut, + mut element_handles: CompMut, + assets: Res, + mut periscopes: CompMut, + mut atlas_sprites: CompMut, + mut bodies: CompMut, + mut transforms: CompMut, + mut items: CompMut, + mut item_throws: CompMut, + mut item_grabs: CompMut, + mut respawn_points: CompMut, + mut spawner_manager: SpawnerManager, +) { + let mut not_hydrated_bitset = hydrated.bitset().clone(); + not_hydrated_bitset.bit_not(); + not_hydrated_bitset.bit_and(element_handles.bitset()); + + let spawner_entities = entities + .iter_with_bitset(¬_hydrated_bitset) + .collect::>(); + + for spawner_ent in spawner_entities { + let transform = *transforms.get(spawner_ent).unwrap(); + let element_handle = *element_handles.get(spawner_ent).unwrap(); + let element_meta = assets.get(element_handle.0); + + if let Ok(PeriscopeMeta { + atlas, + fin_anim, + grab_offset, + max_ammo, + body_size, + can_rotate, + bounciness, + throw_velocity, + angular_velocity, + .. + }) = assets.get(element_meta.data).try_cast_ref() + { + hydrated.insert(spawner_ent, MapElementHydrated); + + let entity = entities.create(); + items.insert(entity, Item); + item_throws.insert( + entity, + ItemThrow::strength(*throw_velocity) + .with_spin(*angular_velocity) + .with_system(periscope_drop(entity, *max_ammo)), + ); + item_grabs.insert( + entity, + ItemGrab { + fin_anim: *fin_anim, + sync_animation: false, + grab_offset: *grab_offset, + }, + ); + periscopes.insert( + entity, + Periscope { + ammo: *max_ammo, + cooldown: Timer::new(Duration::from_millis(0), TimerMode::Once), + }, + ); + atlas_sprites.insert(entity, AtlasSprite::new(*atlas)); + respawn_points.insert(entity, DehydrateOutOfBounds(spawner_ent)); + transforms.insert(entity, transform); + element_handles.insert(entity, element_handle); + hydrated.insert(entity, MapElementHydrated); + bodies.insert( + entity, + KinematicBody { + shape: ColliderShape::Rectangle { size: *body_size }, + has_mass: true, + has_friction: true, + can_rotate: *can_rotate, + bounciness: *bounciness, + gravity: game_meta.core.physics.gravity, + ..default() + }, + ); + spawner_manager.create_spawner(spawner_ent, vec![entity]) + } + } +} + +fn update( + entities: Res, + mut commands: Commands, + element_handles: Comp, + assets: Res, + + mut periscopes: CompMut, + transforms: CompMut, + mut sprites: CompMut, + mut audio_center: ResMut, + + player_inventories: PlayerInventories, + mut items_used: CompMut, + items_dropped: CompMut, + time: Res