From 8f796c92fabee3456bc98de4137ec5fe7b5cc8db Mon Sep 17 00:00:00 2001 From: hut Date: Tue, 14 May 2024 04:35:45 +0200 Subject: [PATCH] implement InJupitersShadow achievement --- src/common.rs | 34 ++++++++++++++++++++++++++++++++++ src/game.rs | 24 ++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/common.rs b/src/common.rs index 27d0af4..3ff15a0 100644 --- a/src/common.rs +++ b/src/common.rs @@ -63,3 +63,37 @@ pub fn alive(settings: Res) -> bool { pub fn in_control(settings: Res) -> bool { return settings.in_control(); } + +pub fn in_shadow( + light_source_pos: DVec3, + light_source_r: f64, + shadow_caster_pos: DVec3, + shadow_caster_r: f64, + camera_pos: DVec3 +) -> bool { + if light_source_r < shadow_caster_r { + error!("common::in_shadow only works if light_source_r > shadow_caster_r"); + return false; + } + + let direction = (shadow_caster_pos - light_source_pos).normalize(); + let shadow_caster_to_player = camera_pos - shadow_caster_pos; + + // Calculate the distance to the shadow caster if the player was projected + // onto the line of the shadow, with positive numbers = in the shadow, + // negative numbers = in between light source and shadow caster. + let projection_length = shadow_caster_to_player.dot(direction); + if projection_length < 0.0 { + return false; + } + + let projection = projection_length * direction; + + // Calculate the vector to the closest point along the shadow line + let closest_vector = shadow_caster_to_player - projection; + + let distance_between_light_and_caster = (shadow_caster_pos - light_source_pos).length(); + let max_distance = shadow_caster_r + ((shadow_caster_r - light_source_r) / distance_between_light_and_caster) * projection_length; + + return closest_vector.length() < max_distance; +} diff --git a/src/game.rs b/src/game.rs index e5ef5fe..44548e5 100644 --- a/src/game.rs +++ b/src/game.rs @@ -27,8 +27,11 @@ impl Plugin for GamePlugin { app.add_systems(PreUpdate, handle_player_death); app.add_systems(PostUpdate, update_id2pos); app.add_systems(Update, handle_achievement_event.run_if(on_event::())); + app.add_systems(Update, check_achievements); app.insert_resource(Id2Pos(HashMap::new())); app.insert_resource(var::AchievementTracker::default()); + app.insert_resource(AchievementCheckTimer( + Timer::from_seconds(1.0, TimerMode::Repeating))); app.add_event::(); app.add_event::(); app.add_event::(); @@ -37,6 +40,7 @@ impl Plugin for GamePlugin { #[derive(Event)] pub struct PlayerDiesEvent(pub actor::DamageType); #[derive(Resource)] pub struct Id2Pos(pub HashMap); +#[derive(Resource)] pub struct AchievementCheckTimer(pub Timer); #[derive(Event)] pub enum AchievementEvent { @@ -396,3 +400,23 @@ fn handle_achievement_event( } } } + +fn check_achievements( + time: Res