From ffe4d7f824bfc23003e19d5145f96dd5182cee95 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 15:27:00 -0400
Subject: [PATCH 1/9] base

---
 src/entities/enemy/base.rs | 7 +++++++
 src/entities/enemy/mod.rs  | 1 +
 src/entities/mod.rs        | 3 ++-
 3 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100644 src/entities/enemy/base.rs
 create mode 100644 src/entities/enemy/mod.rs

diff --git a/src/entities/enemy/base.rs b/src/entities/enemy/base.rs
new file mode 100644
index 0000000..c330af7
--- /dev/null
+++ b/src/entities/enemy/base.rs
@@ -0,0 +1,7 @@
+
+
+pub trait EnemyBase {
+    fn render();
+    fn handle_logic();
+    fn handle_getting_attacked();
+}
\ No newline at end of file
diff --git a/src/entities/enemy/mod.rs b/src/entities/enemy/mod.rs
new file mode 100644
index 0000000..307b359
--- /dev/null
+++ b/src/entities/enemy/mod.rs
@@ -0,0 +1 @@
+pub mod base;
\ No newline at end of file
diff --git a/src/entities/mod.rs b/src/entities/mod.rs
index e948307..5bf6e50 100644
--- a/src/entities/mod.rs
+++ b/src/entities/mod.rs
@@ -1 +1,2 @@
-pub mod fish;
\ No newline at end of file
+pub mod fish;
+pub mod enemy;
\ No newline at end of file

From e6726916a672ca666af3e66b7812e79a9ee1fa7b Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 15:40:17 -0400
Subject: [PATCH 2/9] extracting player code

---
 src/gamecore.rs                 |  9 ++--
 src/logic/ingame/hud.rs         |  8 +--
 src/logic/ingame/mod.rs         |  3 +-
 src/logic/ingame/playerlogic.rs | 57 ---------------------
 src/player.rs                   | 90 ++++++++++++++++++++++++++++++++-
 5 files changed, 96 insertions(+), 71 deletions(-)

diff --git a/src/gamecore.rs b/src/gamecore.rs
index d8216b7..db20954 100644
--- a/src/gamecore.rs
+++ b/src/gamecore.rs
@@ -31,10 +31,10 @@ impl fmt::Display for GameState {
 
 #[derive(Debug, Serialize, Deserialize, Default)]
 pub struct GameProgress {
-    coins: u32,
-    max_depth: f32,
-    fastest_time: Option<f64>,
-    inventory: Vec<ShopItems>,
+    pub coins: u32,
+    pub max_depth: f32,
+    pub fastest_time: Option<f64>,
+    pub inventory: Vec<ShopItems>,
 }
 
 impl GameProgress {
@@ -43,6 +43,7 @@ impl GameProgress {
             ..Default::default()
         }
     }
+    
 
     pub fn from_file(file: String) -> Result<Self, Error> {
         // Load the file
diff --git a/src/logic/ingame/hud.rs b/src/logic/ingame/hud.rs
index 6a70ff9..e7e508d 100644
--- a/src/logic/ingame/hud.rs
+++ b/src/logic/ingame/hud.rs
@@ -8,13 +8,7 @@ pub fn render_hud(
     window_center: Vector2,
 ) {
     // Get the relevant data
-    let dist_from_player_to_end = game_core
-        .player
-        .position
-        .distance_to(game_core.world.end_position);
-    let dist_from_start_to_end = Vector2::zero().distance_to(game_core.world.end_position);
-    let progress = ((dist_from_start_to_end - dist_from_player_to_end) / dist_from_start_to_end)
-        .clamp(0.0, 1.0);
+    let progress = game_core.player.calculate_depth_percent(&game_core.world);
 
     // Determine the progress slider position
     let slider_bound_height = 20.0;
diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs
index 18ab910..e58c92e 100644
--- a/src/logic/ingame/mod.rs
+++ b/src/logic/ingame/mod.rs
@@ -126,7 +126,8 @@ impl Screen for InGameScreen {
             }
 
             // Render Player
-            playerlogic::render_player(&mut context_2d, game_core);
+            // playerlogic::render_player(&mut context_2d, game_core);
+            game_core.player.render(&mut context_2d, &mut game_core.resources);
         }
 
         // Render the hud
diff --git a/src/logic/ingame/playerlogic.rs b/src/logic/ingame/playerlogic.rs
index 6446ec5..c1e5ec6 100644
--- a/src/logic/ingame/playerlogic.rs
+++ b/src/logic/ingame/playerlogic.rs
@@ -169,60 +169,3 @@ pub fn update_player_movement(
     // }
 }
 
-pub fn render_player(context_2d: &mut RaylibMode2D<RaylibDrawHandle>, game_core: &mut GameCore) {
-    // Get the player
-    let player = &game_core.player;
-
-    // Convert the player direction to a rotation
-    let player_rotation = Vector2::zero().angle_to(player.direction);
-
-    // Render the player's boost ring
-    // This functions both as a breath meter, and as a boost meter
-    let boost_ring_max_radius = player.size.x + 5.0;
-    context_2d.draw_circle(
-        player.position.x as i32,
-        player.position.y as i32,
-        boost_ring_max_radius * player.boost_percent,
-        TRANSLUCENT_WHITE_64,
-    );
-    context_2d.draw_ring(
-        Vector2 {
-            x: player.position.x as i32 as f32,
-            y: player.position.y as i32 as f32,
-        },
-        boost_ring_max_radius,
-        boost_ring_max_radius + 1.0,
-        0,
-        (360.0 * player.breath_percent) as i32,
-        0,
-        TRANSLUCENT_WHITE_96,
-    );
-
-    // Render the player based on what is happening
-    if player.is_boost_charging {
-        game_core.resources.player_animation_boost_charge.draw(
-            context_2d,
-            player.position,
-            player_rotation.to_degrees() - 90.0,
-        );
-    } else if player.is_boosting {
-        game_core.resources.player_animation_boost.draw(
-            context_2d,
-            player.position,
-            player_rotation.to_degrees() - 90.0,
-        );
-    } else if player.is_moving {
-        game_core.resources.player_animation_regular.draw(
-            context_2d,
-            player.position,
-            player_rotation.to_degrees() - 90.0,
-        );
-    } else {
-        game_core.resources.player_animation_regular.draw_frame(
-            context_2d,
-            player.position,
-            player_rotation.to_degrees() - 90.0,
-            0,
-        );
-    }
-}
diff --git a/src/player.rs b/src/player.rs
index 01c5343..6daddf1 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -1,6 +1,13 @@
-use raylib::math::{Rectangle, Vector2};
+use raylib::prelude::*;
 
-use crate::lib::utils::triangles::rotate_vector;
+use crate::{
+    gamecore::{GameCore, GameProgress},
+    items::ShopItems,
+    lib::utils::triangles::rotate_vector,
+    pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96},
+    resources::GlobalResources,
+    world::World,
+};
 
 #[derive(Debug, Default)]
 pub struct Player {
@@ -13,6 +20,7 @@ pub struct Player {
     pub is_moving: bool,
     pub is_boosting: bool,
     pub is_boost_charging: bool,
+    pub inventory: Vec<ShopItems>,
 }
 
 impl Player {
@@ -56,4 +64,82 @@ impl Player {
 
         return rectangle.check_collision_circle_rec(self.position, (self.size.y * 0.5) / 2.0);
     }
+
+    /// Calculate how far the player is
+    pub fn calculate_depth_percent(&self, world: &World) -> f32 {
+        let dist_from_player_to_end = self.position.distance_to(world.end_position);
+        let dist_from_start_to_end = Vector2::zero().distance_to(world.end_position);
+        return ((dist_from_start_to_end - dist_from_player_to_end) / dist_from_start_to_end)
+            .clamp(0.0, 1.0);
+    }
+
+    /// Create GameProgress from the current life
+    pub fn create_statistics(&self, game_core: &GameCore, current_time: f64) -> GameProgress {
+        GameProgress {
+            coins: self.coins,
+            inventory: self.inventory.clone(),
+            max_depth: self.calculate_depth_percent(&game_core.world),
+            fastest_time: Some(current_time - game_core.last_state_change_time),
+        }
+    }
+
+    /// Render the player
+    pub fn render(
+        &self,
+        context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
+        resources: &mut GlobalResources,
+    ) {
+        // Convert the player direction to a rotation
+        let player_rotation = Vector2::zero().angle_to(self.direction);
+
+        // Render the player's boost ring
+        // This functions both as a breath meter, and as a boost meter
+        let boost_ring_max_radius = self.size.x + 5.0;
+        context_2d.draw_circle(
+            self.position.x as i32,
+            self.position.y as i32,
+            boost_ring_max_radius * self.boost_percent,
+            TRANSLUCENT_WHITE_64,
+        );
+        context_2d.draw_ring(
+            Vector2 {
+                x: self.position.x as i32 as f32,
+                y: self.position.y as i32 as f32,
+            },
+            boost_ring_max_radius,
+            boost_ring_max_radius + 1.0,
+            0,
+            (360.0 * self.breath_percent) as i32,
+            0,
+            TRANSLUCENT_WHITE_96,
+        );
+
+        // Render the player based on what is happening
+        if self.is_boost_charging {
+            resources.player_animation_boost_charge.draw(
+                context_2d,
+                self.position,
+                player_rotation.to_degrees() - 90.0,
+            );
+        } else if self.is_boosting {
+            resources.player_animation_boost.draw(
+                context_2d,
+                self.position,
+                player_rotation.to_degrees() - 90.0,
+            );
+        } else if self.is_moving {
+            resources.player_animation_regular.draw(
+                context_2d,
+                self.position,
+                player_rotation.to_degrees() - 90.0,
+            );
+        } else {
+            resources.player_animation_regular.draw_frame(
+                context_2d,
+                self.position,
+                player_rotation.to_degrees() - 90.0,
+                0,
+            );
+        }
+    }
 }

From 7d06fcb6d1a3dfa20e72c0422158cf271fd566d9 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 15:46:28 -0400
Subject: [PATCH 3/9] more cleanup

---
 src/lib/utils/profiler.rs | 18 +++++++++++++++++-
 src/main.rs               |  1 +
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/lib/utils/profiler.rs b/src/lib/utils/profiler.rs
index c813885..e8af3ea 100644
--- a/src/lib/utils/profiler.rs
+++ b/src/lib/utils/profiler.rs
@@ -1,3 +1,4 @@
+use raylib::math::Vector2;
 use serde_json::json;
 use serialstudio::{
     data::{DataGroup, DataSet, TelemetryFrame},
@@ -21,7 +22,8 @@ pub struct ProfilerData {
     // Player 
     pub player_coins: u32,
     pub player_boost_percent: f32,
-    pub player_breath_percent: f32
+    pub player_breath_percent: f32,
+    pub player_pose: Vector2
 }
 
 /// The development profiler
@@ -147,6 +149,20 @@ impl GameProfiler {
                             unit: Some("%".to_string()),
                             w_type: None,
                         },
+                        DataSet {
+                            title: Some("X".to_string()),
+                            value: json!(self.data.player_pose.x),
+                            graph: Some(false),
+                            unit: Some("pixels".to_string()),
+                            w_type: None,
+                        },
+                        DataSet {
+                            title: Some("Y".to_string()),
+                            value: json!(self.data.player_pose.y),
+                            graph: Some(false),
+                            unit: Some("pixels".to_string()),
+                            w_type: None,
+                        },
                     ],
                 },
             ],
diff --git a/src/main.rs b/src/main.rs
index 75a8769..aa48d4a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -134,6 +134,7 @@ fn main() {
             profiler.data.player_coins = game_core.player.coins;
             profiler.data.player_boost_percent = game_core.player.boost_percent;
             profiler.data.player_breath_percent = game_core.player.breath_percent;
+            profiler.data.player_pose = game_core.player.position;
 
             // Send telemetry data
             profiler.update();

From b6bcdad88cb85d8bb5a18782d3419d4bc75cc341 Mon Sep 17 00:00:00 2001
From: rsninja722 <jnick722547@gmail.com>
Date: Sat, 24 Apr 2021 16:02:46 -0400
Subject: [PATCH 4/9] boids

---
 assets/worlds/mainworld.json |   9 +--
 src/entities/fish.rs         | 105 +++++++++++++++++++++++++++--------
 2 files changed, 83 insertions(+), 31 deletions(-)

diff --git a/assets/worlds/mainworld.json b/assets/worlds/mainworld.json
index 45a78a5..dc9cf5c 100644
--- a/assets/worlds/mainworld.json
+++ b/assets/worlds/mainworld.json
@@ -4,13 +4,6 @@
         "y": 10000.0
     },
     "fish": [
-        {
-            "x": 500.0,
-            "y": 300.0
-        },
-        {
-            "x": 800.0,
-            "y": 200.0
-        }
+        {"x":49,"y":801},{"x":570,"y":594},{"x":761,"y":186},{"x":760,"y":940},{"x":241,"y":32},{"x":501,"y":18},{"x":487,"y":37},{"x":802,"y":849},{"x":864,"y":43},{"x":544,"y":886},{"x":987,"y":710},{"x":949,"y":404},{"x":694,"y":32},{"x":364,"y":899},{"x":26,"y":849},{"x":253,"y":627},{"x":39,"y":547},{"x":307,"y":730},{"x":133,"y":967},{"x":861,"y":76},{"x":199,"y":229},{"x":617,"y":532},{"x":391,"y":388},{"x":491,"y":816},{"x":539,"y":243},{"x":222,"y":288},{"x":81,"y":784},{"x":432,"y":830},{"x":741,"y":737},{"x":426,"y":480},{"x":591,"y":437},{"x":903,"y":380},{"x":653,"y":349},{"x":684,"y":235},{"x":797,"y":438},{"x":546,"y":615},{"x":497,"y":523},{"x":406,"y":468},{"x":173,"y":183},{"x":641,"y":187},{"x":517,"y":294},{"x":527,"y":650},{"x":962,"y":237},{"x":25,"y":868},{"x":16,"y":369},{"x":434,"y":712},{"x":632,"y":315},{"x":172,"y":421},{"x":450,"y":53},{"x":731,"y":220},{"x":532,"y":467},{"x":816,"y":497},{"x":948,"y":539},{"x":467,"y":829},{"x":533,"y":809},{"x":146,"y":989},{"x":850,"y":245},{"x":989,"y":214},{"x":203,"y":354},{"x":466,"y":611},{"x":382,"y":376},{"x":111,"y":148},{"x":411,"y":77},{"x":124,"y":418},{"x":154,"y":611},{"x":56,"y":732},{"x":800,"y":488},{"x":851,"y":668},{"x":240,"y":220},{"x":1000,"y":62},{"x":95,"y":784},{"x":700,"y":428},{"x":735,"y":517},{"x":259,"y":843},{"x":647,"y":268},{"x":668,"y":823},{"x":198,"y":241},{"x":243,"y":422},{"x":838,"y":433},{"x":642,"y":97},{"x":563,"y":974},{"x":386,"y":548},{"x":646,"y":482},{"x":691,"y":794},{"x":167,"y":485},{"x":978,"y":622},{"x":845,"y":431},{"x":529,"y":719},{"x":963,"y":145},{"x":6,"y":412},{"x":381,"y":830},{"x":918,"y":118},{"x":915,"y":27},{"x":618,"y":262},{"x":250,"y":635},{"x":100,"y":500},{"x":442,"y":321},{"x":769,"y":767},{"x":714,"y":204},{"x":506,"y":872},{"x":575,"y":178},{"x":256,"y":411},{"x":921,"y":617},{"x":971,"y":214},{"x":726,"y":702},{"x":103,"y":450},{"x":501,"y":134},{"x":265,"y":993},{"x":31,"y":63},{"x":502,"y":448},{"x":46,"y":457},{"x":809,"y":184},{"x":763,"y":962},{"x":632,"y":873},{"x":916,"y":761},{"x":710,"y":720},{"x":873,"y":222},{"x":256,"y":861},{"x":246,"y":482},{"x":390,"y":812},{"x":28,"y":247},{"x":516,"y":523},{"x":869,"y":43},{"x":680,"y":740},{"x":406,"y":65},{"x":657,"y":196},{"x":692,"y":635},{"x":97,"y":993},{"x":616,"y":490},{"x":515,"y":955},{"x":412,"y":502},{"x":743,"y":565},{"x":16,"y":499},{"x":324,"y":582},{"x":871,"y":62},{"x":128,"y":476},{"x":716,"y":525},{"x":627,"y":2},{"x":730,"y":913},{"x":704,"y":522},{"x":242,"y":934},{"x":172,"y":277},{"x":651,"y":948},{"x":349,"y":263},{"x":731,"y":967},{"x":382,"y":762},{"x":217,"y":15},{"x":49,"y":25},{"x":583,"y":110},{"x":700,"y":620},{"x":230,"y":537},{"x":285,"y":978},{"x":4,"y":791},{"x":939,"y":866},{"x":371,"y":342},{"x":759,"y":870},{"x":892,"y":103},{"x":57,"y":129},{"x":233,"y":383},{"x":171,"y":472},{"x":173,"y":842},{"x":516,"y":464},{"x":407,"y":458},{"x":963,"y":231},{"x":526,"y":253},{"x":815,"y":857},{"x":175,"y":909},{"x":993,"y":255},{"x":129,"y":390},{"x":76,"y":997},{"x":833,"y":174},{"x":501,"y":396},{"x":897,"y":218},{"x":876,"y":601},{"x":41,"y":165},{"x":993,"y":473},{"x":606,"y":308},{"x":831,"y":382},{"x":517,"y":828},{"x":984,"y":26},{"x":286,"y":712},{"x":422,"y":311},{"x":448,"y":103},{"x":260,"y":229},{"x":5,"y":738},{"x":283,"y":346},{"x":744,"y":463},{"x":634,"y":719},{"x":446,"y":977},{"x":220,"y":89},{"x":745,"y":866},{"x":851,"y":860},{"x":369,"y":940},{"x":828,"y":577},{"x":350,"y":337},{"x":334,"y":378},{"x":203,"y":248},{"x":665,"y":788},{"x":334,"y":927},{"x":307,"y":764},{"x":500,"y":763},{"x":613,"y":843},{"x":384,"y":253},{"x":956,"y":569},{"x":846,"y":137},{"x":105,"y":728},{"x":686,"y":226},{"x":657,"y":52},{"x":592,"y":433},{"x":997,"y":820},{"x":746,"y":389},{"x":405,"y":448},{"x":973,"y":19},{"x":538,"y":518},{"x":790,"y":275},{"x":633,"y":738},{"x":128,"y":484},{"x":603,"y":371},{"x":932,"y":21},{"x":582,"y":445},{"x":438,"y":793},{"x":963,"y":69},{"x":158,"y":263},{"x":988,"y":297},{"x":249,"y":227},{"x":245,"y":466},{"x":131,"y":495},{"x":620,"y":266},{"x":505,"y":384},{"x":813,"y":647},{"x":113,"y":66},{"x":757,"y":10},{"x":2,"y":707},{"x":540,"y":140},{"x":562,"y":691},{"x":484,"y":433},{"x":859,"y":455},{"x":248,"y":117},{"x":36,"y":432},{"x":798,"y":754},{"x":611,"y":291},{"x":664,"y":770},{"x":299,"y":788},{"x":433,"y":920},{"x":540,"y":739},{"x":201,"y":829},{"x":972,"y":362},{"x":811,"y":120},{"x":941,"y":670},{"x":186,"y":448},{"x":549,"y":611},{"x":206,"y":387},{"x":973,"y":437},{"x":700,"y":709},{"x":472,"y":243},{"x":971,"y":518},{"x":184,"y":540},{"x":271,"y":257},{"x":290,"y":895},{"x":546,"y":7},{"x":256,"y":542},{"x":418,"y":553},{"x":816,"y":875},{"x":908,"y":547},{"x":315,"y":354},{"x":266,"y":471},{"x":242,"y":88},{"x":785,"y":52},{"x":497,"y":47},{"x":466,"y":279},{"x":750,"y":690},{"x":329,"y":296},{"x":545,"y":715},{"x":508,"y":562},{"x":993,"y":467},{"x":703,"y":733},{"x":824,"y":11},{"x":419,"y":337},{"x":393,"y":229},{"x":898,"y":261},{"x":264,"y":708},{"x":711,"y":768},{"x":568,"y":409},{"x":473,"y":342},{"x":329,"y":53},{"x":95,"y":815},{"x":783,"y":977},{"x":48,"y":551},{"x":635,"y":931},{"x":653,"y":86},{"x":9,"y":153},{"x":955,"y":660},{"x":480,"y":716},{"x":936,"y":622},{"x":607,"y":221},{"x":423,"y":545},{"x":507,"y":668},{"x":676,"y":957},{"x":253,"y":515},{"x":327,"y":495},{"x":965,"y":808},{"x":2,"y":807},{"x":276,"y":199},{"x":584,"y":75},{"x":770,"y":51},{"x":667,"y":717},{"x":944,"y":913},{"x":982,"y":977},{"x":618,"y":482},{"x":372,"y":545},{"x":507,"y":518},{"x":604,"y":492},{"x":772,"y":730},{"x":350,"y":141},{"x":783,"y":437},{"x":282,"y":714},{"x":269,"y":691},{"x":991,"y":386},{"x":234,"y":196},{"x":908,"y":635},{"x":785,"y":340},{"x":125,"y":712},{"x":466,"y":210},{"x":280,"y":185},{"x":995,"y":466},{"x":589,"y":258},{"x":700,"y":120},{"x":855,"y":323},{"x":690,"y":355},{"x":755,"y":353},{"x":378,"y":970},{"x":865,"y":270},{"x":220,"y":62},{"x":685,"y":848},{"x":670,"y":907},{"x":710,"y":671},{"x":209,"y":68},{"x":642,"y":470},{"x":104,"y":642},{"x":631,"y":328},{"x":898,"y":424},{"x":909,"y":427},{"x":189,"y":141},{"x":259,"y":993},{"x":332,"y":791},{"x":842,"y":778},{"x":63,"y":390},{"x":146,"y":895},{"x":230,"y":274},{"x":316,"y":447},{"x":603,"y":59},{"x":377,"y":841},{"x":602,"y":119},{"x":728,"y":557},{"x":395,"y":514},{"x":379,"y":754},{"x":822,"y":840},{"x":860,"y":478},{"x":695,"y":360},{"x":156,"y":784},{"x":241,"y":353},{"x":195,"y":199},{"x":284,"y":110},{"x":484,"y":966},{"x":889,"y":370},{"x":246,"y":684},{"x":710,"y":345},{"x":382,"y":635},{"x":447,"y":948},{"x":741,"y":274},{"x":224,"y":883},{"x":99,"y":37},{"x":472,"y":803},{"x":141,"y":397},{"x":371,"y":602},{"x":7,"y":482},{"x":184,"y":990},{"x":555,"y":313},{"x":573,"y":886},{"x":167,"y":365},{"x":810,"y":721},{"x":958,"y":767},{"x":891,"y":561},{"x":314,"y":987},{"x":156,"y":95},{"x":349,"y":542},{"x":775,"y":35},{"x":121,"y":655},{"x":311,"y":242},{"x":534,"y":135},{"x":71,"y":134},{"x":367,"y":896},{"x":447,"y":524},{"x":120,"y":421},{"x":878,"y":398},{"x":469,"y":822},{"x":483,"y":966},{"x":240,"y":880},{"x":759,"y":980},{"x":531,"y":759},{"x":395,"y":118},{"x":354,"y":360},{"x":173,"y":924},{"x":550,"y":958},{"x":888,"y":379},{"x":244,"y":448},{"x":999,"y":554},{"x":941,"y":455},{"x":798,"y":916},{"x":134,"y":123},{"x":90,"y":440},{"x":923,"y":263},{"x":405,"y":595},{"x":194,"y":387},{"x":370,"y":697},{"x":943,"y":888},{"x":607,"y":336},{"x":168,"y":105},{"x":874,"y":66},{"x":675,"y":50},{"x":601,"y":242},{"x":925,"y":728},{"x":643,"y":609},{"x":769,"y":713},{"x":410,"y":913},{"x":153,"y":776},{"x":775,"y":949},{"x":184,"y":93},{"x":624,"y":632},{"x":899,"y":804},{"x":909,"y":327},{"x":371,"y":510},{"x":663,"y":415},{"x":337,"y":542},{"x":248,"y":104},{"x":925,"y":450},{"x":310,"y":925},{"x":4,"y":550},{"x":559,"y":652},{"x":671,"y":296},{"x":414,"y":60},{"x":972,"y":505},{"x":221,"y":147},{"x":318,"y":592},{"x":861,"y":656},{"x":258,"y":675},{"x":565,"y":390},{"x":703,"y":236},{"x":227,"y":76},{"x":989,"y":252},{"x":924,"y":419},{"x":983,"y":971},{"x":795,"y":244},{"x":256,"y":498},{"x":517,"y":674},{"x":89,"y":197},{"x":366,"y":234},{"x":41,"y":952},{"x":487,"y":981},{"x":939,"y":922},{"x":384,"y":315},{"x":958,"y":57},{"x":499,"y":152},{"x":716,"y":167},{"x":167,"y":301},{"x":781,"y":964},{"x":101,"y":215},{"x":605,"y":396},{"x":31,"y":973},{"x":128,"y":831},{"x":685,"y":701},{"x":150,"y":507},{"x":663,"y":77},{"x":792,"y":561},{"x":398,"y":281},{"x":168,"y":936},{"x":8,"y":266},{"x":19,"y":723},{"x":377,"y":975},{"x":68,"y":114},{"x":191,"y":784},{"x":94,"y":222},{"x":986,"y":578},{"x":474,"y":160},{"x":936,"y":945},{"x":603,"y":778},{"x":105,"y":845},{"x":955,"y":583},{"x":832,"y":905},{"x":264,"y":132},{"x":219,"y":747},{"x":515,"y":562},{"x":178,"y":198},{"x":999,"y":1},{"x":470,"y":345},{"x":450,"y":490},{"x":967,"y":306},{"x":257,"y":360},{"x":632,"y":26},{"x":916,"y":382},{"x":631,"y":194},{"x":492,"y":235},{"x":479,"y":373},{"x":887,"y":154},{"x":65,"y":181},{"x":956,"y":879},{"x":567,"y":578},{"x":718,"y":617},{"x":464,"y":243},{"x":545,"y":410},{"x":923,"y":340},{"x":978,"y":716},{"x":277,"y":261},{"x":462,"y":600},{"x":687,"y":507}
     ]
 }
\ No newline at end of file
diff --git a/src/entities/fish.rs b/src/entities/fish.rs
index 452d9ed..bbb77be 100644
--- a/src/entities/fish.rs
+++ b/src/entities/fish.rs
@@ -8,10 +8,20 @@ const FISH_FOLLOW_PLAYER_SPEED: f32 = 1.8;
 const FISH_FOLLOW_PLAYER_SPEED_FAST: f32 = FISH_FOLLOW_PLAYER_SPEED * 3.0;
 const FISH_ATTACH_RADIUS: f32 = 20.0;
 
+const FISH_VISION: f32 = 25.0;
+const FISH_MAX_SPEED: f32 = 2.0;
+const FISH_MAX_FORCE: f32 = 0.05;
+const FISH_FACTOR_ATTRACTION: f32 = 1.0;
+const FISH_FACTOR_PLAYER: f32 = 0.1;
+const FISH_FACTOR_COHESION: f32 = 0.1;
+const FISH_SEPARATION_DISTANCE: f32 = 15.0;
+const FISH_FACTOR_SEPARATION: f32 = 1.5;
+
 #[derive(Debug, Clone)]
 pub struct FishEntity {
     position: Vector2,
     direction: Vector2,
+    velocity: Vector2,
     pub following_player: bool,
     size: Vector2,
     rng: ThreadRng
@@ -22,6 +32,7 @@ impl FishEntity {
         Self {
             position: position,
             direction: Vector2::zero(),
+            velocity: Vector2::zero(),
             following_player: false,
             size: Vector2 { x: 5.0, y: 8.0 },
             rng: rand::thread_rng()
@@ -37,33 +48,80 @@ impl FishEntity {
     }
 
     pub fn handle_follow_player(&mut self, player: &Player, dt: f64, other_fish: &Vec<FishEntity>) {
-        // Distance and direction to player
-        let dist_to_player = player.position - self.position;
-        let dist_to_player_lin = self.position.distance_to(player.position);
-        let mut direction_to_player = dist_to_player;
-        direction_to_player.normalize();
-
-        // Fish movement
-        let movement;
-
-        // Random variance
-        let variance = self.rng.gen_range(500.0..1000.0) / 1000.0;
-
-        // If the fish is double its follow distance from the player
-        if dist_to_player_lin.abs() > (FISH_FOLLOW_PLAYER_DISTANCE * 2.0) {
-            movement = direction_to_player * FISH_FOLLOW_PLAYER_SPEED_FAST * variance;
-        } else {
-            // Move slowly in the direction of the player unless too close
-            if dist_to_player_lin.abs() > FISH_FOLLOW_PLAYER_DISTANCE {
-                movement = direction_to_player * FISH_FOLLOW_PLAYER_SPEED * variance;
-            } else {
-                movement = Vector2::zero();
+        let mut acceleration: Vector2 = Vector2::zero();
+ 
+        let mut steer: Vector2 = Vector2::zero();
+        let mut count1: u16 = 0;
+        let mut sum1: Vector2 = Vector2::zero();
+        let mut count2: u16 = 0;
+        let mut sum2: Vector2 = Vector2::zero();
+        let mut count3: u16 = 0;
+        // separation
+        for i in other_fish {
+            let dist = (self.position - i.position).length();
+            if dist < FISH_SEPARATION_DISTANCE && dist > 0.0 {
+                let mut diff: Vector2 = self.position - i.position;
+                diff.normalize();
+                diff /= dist;
+                steer += diff;
+                count1 += 1;
+            }
+            if dist < FISH_VISION && dist > 0.0 {
+                sum1 += i.direction;
+                count2 += 1;
+                sum2 += i.position;
+                count3 += 1;
             }
         }
+        if count1 > 0 {
+            steer /= count1 as f32;
+        }
+        if steer.x != 0.0 || steer.y != 0.0 {
+            steer.normalize();
+            steer *= FISH_MAX_SPEED;
+            steer -= self.velocity;
+            steer.x = f32::min(f32::max(steer.x, -FISH_MAX_FORCE), FISH_MAX_FORCE);
+            steer.y = f32::min(f32::max(steer.y, -FISH_MAX_FORCE), FISH_MAX_FORCE);
+            acceleration += steer * FISH_FACTOR_SEPARATION;
+        }
+
+        // attraction
+        if count2 > 0 {
+            sum1 /= count2 as f32;
+            sum1.normalize();
+            sum1 *= FISH_MAX_SPEED;
+            sum1 -= self.velocity;
+            sum1.x = f32::min(f32::max(sum1.x, -FISH_MAX_FORCE), FISH_MAX_FORCE);
+            sum1.y = f32::min(f32::max(sum1.y, -FISH_MAX_FORCE), FISH_MAX_FORCE);
+            acceleration += sum1 * FISH_FACTOR_ATTRACTION;
+        }
+
+        // cohesion
+        if count3 > 0 {
+            sum2 /= count3 as f32;
+            let mut desired: Vector2 = sum2 - self.position;
+
+            desired.normalize();
+            desired *= FISH_MAX_SPEED;
+
+            desired.x = f32::min(f32::max(desired.x, -FISH_MAX_FORCE), FISH_MAX_FORCE);
+            desired.y = f32::min(f32::max(desired.y, -FISH_MAX_FORCE), FISH_MAX_FORCE);
+
+            acceleration += desired * FISH_FACTOR_COHESION;
+        }
+
+        // turn to player
+        let mut player_factor: Vector2 = player.position - self.position;
+        player_factor.normalize();
+        acceleration += player_factor * FISH_FACTOR_PLAYER;
 
         // Move the fish
-        self.direction = direction_to_player;
-        self.position += movement;
+        self.direction = self.velocity.normalized();
+        self.velocity += acceleration;
+        
+        self.velocity.x = f32::min(f32::max(self.velocity.x, -FISH_MAX_SPEED), FISH_MAX_SPEED);
+        self.velocity.y = f32::min(f32::max(self.velocity.y, -FISH_MAX_SPEED), FISH_MAX_SPEED);
+        self.position += self.velocity;
     }
 
     pub fn handle_free_movement(&mut self, player: &mut Player, dt: f64) {
@@ -76,6 +134,7 @@ impl FishEntity {
         // Handle player picking up fish
         if player.position.distance_to(self.position).abs() <= player.size.y * 2.2 {
             self.following_player = true;
+            self.velocity = self.direction.normalized();
 
             // Add currency to the player
             player.coins += 1;

From b51de3b81553e5986df32fc5a202fde12773e696 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 16:03:07 -0400
Subject: [PATCH 5/9] working on aoe

---
 src/items.rs                    | 10 +++++-----
 src/logic/ingame/playerlogic.rs |  8 +++++++-
 src/player.rs                   | 28 ++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/src/items.rs b/src/items.rs
index b49d49b..f1559bb 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1,10 +1,10 @@
-use serde::{Serialize, Deserialize};
+use serde::{Deserialize, Serialize};
 
 #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
 #[serde(tag = "t", content = "c")]
 pub enum ShopItems {
-    StunGun(u8),
+    StunGun,
     AirBag,
-    Flashlight(u8),
-    Flippers(u8)
-}
\ No newline at end of file
+    Flashlight { power: u8 },
+    Flippers { speed_increase: u8 },
+}
diff --git a/src/logic/ingame/playerlogic.rs b/src/logic/ingame/playerlogic.rs
index c1e5ec6..2bf695e 100644
--- a/src/logic/ingame/playerlogic.rs
+++ b/src/logic/ingame/playerlogic.rs
@@ -128,7 +128,8 @@ pub fn update_player_movement(
 
     // Only do this if the mouse is far enough away
     let player_real_movement = game_core.player.direction * speed_multiplier;
-    if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0 {
+    let player_stunned = game_core.player.stun_timer > 0.0;
+    if raw_movement_direction.distance_to(Vector2::zero()) > game_core.player.size.y / 2.0 || player_stunned{
         game_core.player.is_moving = true;
         game_core.player.position += player_real_movement;
 
@@ -145,6 +146,11 @@ pub fn update_player_movement(
         }
     } else {
         game_core.player.is_moving = false;
+
+        // Handle updating the stun timer
+        if player_stunned {
+            game_core.player.stun_timer -= dt;
+        }
     }
 
     // Move the camera to follow the player
diff --git a/src/player.rs b/src/player.rs
index 6daddf1..f7850ab 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -21,6 +21,8 @@ pub struct Player {
     pub is_boosting: bool,
     pub is_boost_charging: bool,
     pub inventory: Vec<ShopItems>,
+    pub stun_timer: f64,
+    pub attacking_timer: f64,
 }
 
 impl Player {
@@ -65,6 +67,18 @@ impl Player {
         return rectangle.check_collision_circle_rec(self.position, (self.size.y * 0.5) / 2.0);
     }
 
+    /// Stun the player
+    pub fn set_stun_seconds(&mut self, seconds: f64) {
+        self.stun_timer = seconds;
+    }
+
+    /// Try to attack with the stun gun
+    pub fn begin_attack(&mut self) {
+        if self.inventory.contains(&ShopItems::StunGun) && self.stun_timer == 0.0 {
+            self.stun_timer = 2.0;
+        }
+    }
+
     /// Calculate how far the player is
     pub fn calculate_depth_percent(&self, world: &World) -> f32 {
         let dist_from_player_to_end = self.position.distance_to(world.end_position);
@@ -114,6 +128,20 @@ impl Player {
             TRANSLUCENT_WHITE_96,
         );
 
+        // Calculate AOE ring
+        let aoe_ring;
+        if self.attacking_timer <= 0.25 {
+            aoe_ring = self.attacking_timer;
+        }
+
+        // Render attack AOE
+        context_2d.draw_circle_lines(
+            self.position.x as i32,
+            self.position.y as i32,
+            boost_ring_max_radius * self.boost_percent,
+            TRANSLUCENT_WHITE_64,
+        );
+
         // Render the player based on what is happening
         if self.is_boost_charging {
             resources.player_animation_boost_charge.draw(

From eb3c508c68ad726359d3ab1ce92704bf8f8e70b6 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 16:07:47 -0400
Subject: [PATCH 6/9] color fishies!

---
 src/entities/fish.rs | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/src/entities/fish.rs b/src/entities/fish.rs
index bbb77be..8982d0b 100644
--- a/src/entities/fish.rs
+++ b/src/entities/fish.rs
@@ -1,7 +1,9 @@
-use rand::{Rng, prelude::ThreadRng};
+use rand::{prelude::ThreadRng, Rng};
 use raylib::prelude::*;
 
-use crate::{gamecore::GameCore, lib::utils::triangles::rotate_vector, player::Player, world::World};
+use crate::{
+    gamecore::GameCore, lib::utils::triangles::rotate_vector, player::Player, world::World,
+};
 
 const FISH_FOLLOW_PLAYER_DISTANCE: f32 = 30.0;
 const FISH_FOLLOW_PLAYER_SPEED: f32 = 1.8;
@@ -24,18 +26,26 @@ pub struct FishEntity {
     velocity: Vector2,
     pub following_player: bool,
     size: Vector2,
-    rng: ThreadRng
+    rng: ThreadRng,
+    color: Color,
 }
 
 impl FishEntity {
     pub fn new(position: Vector2) -> Self {
+        let mut rng = rand::thread_rng();
         Self {
             position: position,
             direction: Vector2::zero(),
             velocity: Vector2::zero(),
             following_player: false,
             size: Vector2 { x: 5.0, y: 8.0 },
-            rng: rand::thread_rng()
+            color: Color {
+                r: rng.gen_range(128..225),
+                g: rng.gen_range(128..225),
+                b: rng.gen_range(128..225),
+                a: 140,
+            },
+            rng,
         }
     }
 
@@ -49,7 +59,7 @@ impl FishEntity {
 
     pub fn handle_follow_player(&mut self, player: &Player, dt: f64, other_fish: &Vec<FishEntity>) {
         let mut acceleration: Vector2 = Vector2::zero();
- 
+
         let mut steer: Vector2 = Vector2::zero();
         let mut count1: u16 = 0;
         let mut sum1: Vector2 = Vector2::zero();
@@ -118,7 +128,7 @@ impl FishEntity {
         // Move the fish
         self.direction = self.velocity.normalized();
         self.velocity += acceleration;
-        
+
         self.velocity.x = f32::min(f32::max(self.velocity.x, -FISH_MAX_SPEED), FISH_MAX_SPEED);
         self.velocity.y = f32::min(f32::max(self.velocity.y, -FISH_MAX_SPEED), FISH_MAX_SPEED);
         self.position += self.velocity;
@@ -186,7 +196,7 @@ impl FishEntity {
             self.position + fish_front,
             self.position + fish_bl,
             self.position + fish_br,
-            Color::BLACK,
+            self.color,
         );
     }
 }

From 22e9eda97c7f47b37fd769fed3cbb5cb1c262894 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 16:21:48 -0400
Subject: [PATCH 7/9] aoe ring math

---
 src/lib/utils/mod.rs            | 12 +++++++++++-
 src/logic/ingame/mod.rs         |  2 +-
 src/logic/ingame/playerlogic.rs |  4 ++++
 src/logic/loadingscreen.rs      | 14 ++------------
 src/player.rs                   | 24 +++++++++---------------
 5 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/src/lib/utils/mod.rs b/src/lib/utils/mod.rs
index 9d6dd04..baba8af 100644
--- a/src/lib/utils/mod.rs
+++ b/src/lib/utils/mod.rs
@@ -1,2 +1,12 @@
 pub mod profiler;
-pub mod triangles;
\ No newline at end of file
+pub mod triangles;
+
+pub fn calculate_linear_slide(playthrough_percent: f64) -> f64 {
+    if playthrough_percent < 0.25 {
+        return playthrough_percent / 0.25;
+    } else if playthrough_percent > 0.75 {
+        return 1.0 - ((playthrough_percent - 0.75) / 0.25);
+    } else {
+        return 1.0;
+    }
+}
\ No newline at end of file
diff --git a/src/logic/ingame/mod.rs b/src/logic/ingame/mod.rs
index e58c92e..50fe9d7 100644
--- a/src/logic/ingame/mod.rs
+++ b/src/logic/ingame/mod.rs
@@ -127,7 +127,7 @@ impl Screen for InGameScreen {
 
             // Render Player
             // playerlogic::render_player(&mut context_2d, game_core);
-            game_core.player.render(&mut context_2d, &mut game_core.resources);
+            game_core.player.render(&mut context_2d, &mut game_core.resources, dt);
         }
 
         // Render the hud
diff --git a/src/logic/ingame/playerlogic.rs b/src/logic/ingame/playerlogic.rs
index 2bf695e..afd21f5 100644
--- a/src/logic/ingame/playerlogic.rs
+++ b/src/logic/ingame/playerlogic.rs
@@ -76,6 +76,10 @@ pub fn update_player_movement(
     let user_request_boost = draw_handle.is_mouse_button_down(MouseButton::MOUSE_LEFT_BUTTON);
     let user_request_action = draw_handle.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON);
 
+    if user_request_action {
+        game_core.player.begin_attack();
+    }
+
     // Move the player in their direction
     let speed_multiplier;
     if user_request_boost && game_core.player.boost_percent >= 0.0 {
diff --git a/src/logic/loadingscreen.rs b/src/logic/loadingscreen.rs
index 184322b..06056c1 100644
--- a/src/logic/loadingscreen.rs
+++ b/src/logic/loadingscreen.rs
@@ -1,9 +1,6 @@
 use raylib::prelude::*;
 
-use crate::{
-    gamecore::{GameCore, GameState},
-    lib::wrappers::audio::player::AudioPlayer,
-};
+use crate::{gamecore::{GameCore, GameState}, lib::{utils::calculate_linear_slide, wrappers::audio::player::AudioPlayer}};
 
 use super::screen::Screen;
 
@@ -32,14 +29,7 @@ impl LoadingScreen {
 
     fn get_logo_mask(&self, playthrough_percent: f64) -> Color {
         // Determine the alpha
-        let alpha;
-        if playthrough_percent < 0.25 {
-            alpha = playthrough_percent / 0.25
-        } else if playthrough_percent > 0.75 {
-            alpha = 1.0 - ((playthrough_percent - 0.75) / 0.25);
-        } else {
-            alpha = 1.0;
-        }
+        let alpha = calculate_linear_slide(playthrough_percent);
 
         // Build a color mask
         Color {
diff --git a/src/player.rs b/src/player.rs
index f7850ab..e284f9e 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -1,13 +1,8 @@
 use raylib::prelude::*;
 
-use crate::{
-    gamecore::{GameCore, GameProgress},
-    items::ShopItems,
-    lib::utils::triangles::rotate_vector,
-    pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96},
-    resources::GlobalResources,
-    world::World,
-};
+use crate::{gamecore::{GameCore, GameProgress}, items::ShopItems, lib::utils::{calculate_linear_slide, triangles::rotate_vector}, pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96}, resources::GlobalResources, world::World};
+
+const AOE_RING_MAX_RADIUS: f32 = 40.0;
 
 #[derive(Debug, Default)]
 pub struct Player {
@@ -74,7 +69,7 @@ impl Player {
 
     /// Try to attack with the stun gun
     pub fn begin_attack(&mut self) {
-        if self.inventory.contains(&ShopItems::StunGun) && self.stun_timer == 0.0 {
+        if true || self.inventory.contains(&ShopItems::StunGun) && self.stun_timer == 0.0 {
             self.stun_timer = 2.0;
         }
     }
@@ -99,9 +94,10 @@ impl Player {
 
     /// Render the player
     pub fn render(
-        &self,
+        &mut self,
         context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
         resources: &mut GlobalResources,
+        dt: f64
     ) {
         // Convert the player direction to a rotation
         let player_rotation = Vector2::zero().angle_to(self.direction);
@@ -129,16 +125,14 @@ impl Player {
         );
 
         // Calculate AOE ring
-        let aoe_ring;
-        if self.attacking_timer <= 0.25 {
-            aoe_ring = self.attacking_timer;
-        }
+        let aoe_ring = calculate_linear_slide(self.attacking_timer) as f32;
+        self.stun_timer = (self.stun_timer - dt).max(0.0);
 
         // Render attack AOE
         context_2d.draw_circle_lines(
             self.position.x as i32,
             self.position.y as i32,
-            boost_ring_max_radius * self.boost_percent,
+            AOE_RING_MAX_RADIUS * aoe_ring,
             TRANSLUCENT_WHITE_64,
         );
 

From 8c142d2711d10e9111a74b1e9c80d853652258cc Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 16:37:58 -0400
Subject: [PATCH 8/9] Rewrite the inventory

---
 src/gamecore.rs |  9 ++++++---
 src/items.rs    | 30 ++++++++++++++++++++++++------
 src/player.rs   | 41 ++++++++++++++++++++++++++---------------
 3 files changed, 56 insertions(+), 24 deletions(-)

diff --git a/src/gamecore.rs b/src/gamecore.rs
index db20954..19b9592 100644
--- a/src/gamecore.rs
+++ b/src/gamecore.rs
@@ -6,7 +6,11 @@ use raylib::{
     camera::Camera2D, math::Vector2, prelude::RaylibDrawHandle, RaylibHandle, RaylibThread,
 };
 
-use crate::{items::ShopItems, player::Player, resources::GlobalResources, world::World};
+use crate::{
+    player::{Player, PlayerInventory},
+    resources::GlobalResources,
+    world::World,
+};
 
 use failure::Error;
 use log::debug;
@@ -34,7 +38,7 @@ pub struct GameProgress {
     pub coins: u32,
     pub max_depth: f32,
     pub fastest_time: Option<f64>,
-    pub inventory: Vec<ShopItems>,
+    pub inventory: PlayerInventory,
 }
 
 impl GameProgress {
@@ -43,7 +47,6 @@ impl GameProgress {
             ..Default::default()
         }
     }
-    
 
     pub fn from_file(file: String) -> Result<Self, Error> {
         // Load the file
diff --git a/src/items.rs b/src/items.rs
index f1559bb..87d979e 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -1,10 +1,28 @@
 use serde::{Deserialize, Serialize};
 
+// #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
+// #[serde(tag = "t", content = "c")]
+// pub enum ShopItems {
+//     StunGun,
+//     AirBag,
+//     Flashlight { power: u8 },
+//     Flippers { speed_increase: u8 },
+// }
+
+
 #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
-#[serde(tag = "t", content = "c")]
-pub enum ShopItems {
-    StunGun,
-    AirBag,
-    Flashlight { power: u8 },
-    Flippers { speed_increase: u8 },
+pub struct StunGun {
+    range: f32,
+    duration: f64
 }
+
+#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
+pub struct AirBag;
+
+#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
+pub struct Flashlight;
+
+#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
+pub struct Flippers {
+    speed_increase: f32
+}
\ No newline at end of file
diff --git a/src/player.rs b/src/player.rs
index e284f9e..afdd68c 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -1,8 +1,17 @@
 use raylib::prelude::*;
+use serde::{Serialize, Deserialize};
+use crate::{gamecore::{GameCore, GameProgress}, items::{AirBag, Flashlight, Flippers, StunGun}, lib::utils::{calculate_linear_slide}, pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96}, resources::GlobalResources, world::World};
 
-use crate::{gamecore::{GameCore, GameProgress}, items::ShopItems, lib::utils::{calculate_linear_slide, triangles::rotate_vector}, pallette::{TRANSLUCENT_WHITE_64, TRANSLUCENT_WHITE_96}, resources::GlobalResources, world::World};
+const AOE_RING_MAX_RADIUS: f32 = 60.0;
+const STUN_ATTACK_TIME: f64 = 0.75;
 
-const AOE_RING_MAX_RADIUS: f32 = 40.0;
+#[derive(Debug, Serialize, Deserialize, Default, Clone)]
+pub struct PlayerInventory {
+    stun_gun: Option<StunGun>,
+    air_bag: Option<AirBag>,
+    flashlight: Option<Flashlight>,
+    flippers: Option<Flippers>
+}
 
 #[derive(Debug, Default)]
 pub struct Player {
@@ -15,7 +24,7 @@ pub struct Player {
     pub is_moving: bool,
     pub is_boosting: bool,
     pub is_boost_charging: bool,
-    pub inventory: Vec<ShopItems>,
+    pub inventory: PlayerInventory,
     pub stun_timer: f64,
     pub attacking_timer: f64,
 }
@@ -69,8 +78,8 @@ impl Player {
 
     /// Try to attack with the stun gun
     pub fn begin_attack(&mut self) {
-        if true || self.inventory.contains(&ShopItems::StunGun) && self.stun_timer == 0.0 {
-            self.stun_timer = 2.0;
+        if true || self.inventory.stun_gun.is_some() && self.stun_timer == 0.0 {
+            self.attacking_timer = STUN_ATTACK_TIME;
         }
     }
 
@@ -97,7 +106,7 @@ impl Player {
         &mut self,
         context_2d: &mut RaylibMode2D<RaylibDrawHandle>,
         resources: &mut GlobalResources,
-        dt: f64
+        dt: f64,
     ) {
         // Convert the player direction to a rotation
         let player_rotation = Vector2::zero().angle_to(self.direction);
@@ -125,16 +134,18 @@ impl Player {
         );
 
         // Calculate AOE ring
-        let aoe_ring = calculate_linear_slide(self.attacking_timer) as f32;
-        self.stun_timer = (self.stun_timer - dt).max(0.0);
+        if self.attacking_timer != 0.0 {
+            let aoe_ring = calculate_linear_slide( self.attacking_timer / STUN_ATTACK_TIME) as f32;
+            self.attacking_timer = (self.attacking_timer - dt).max(0.0);
 
-        // Render attack AOE
-        context_2d.draw_circle_lines(
-            self.position.x as i32,
-            self.position.y as i32,
-            AOE_RING_MAX_RADIUS * aoe_ring,
-            TRANSLUCENT_WHITE_64,
-        );
+            // Render attack AOE
+            context_2d.draw_circle_lines(
+                self.position.x as i32,
+                self.position.y as i32,
+                AOE_RING_MAX_RADIUS * aoe_ring,
+                TRANSLUCENT_WHITE_64,
+            );
+        }
 
         // Render the player based on what is happening
         if self.is_boost_charging {

From 43eab974b07e29658c68a1844ac0ac6ecfb97b47 Mon Sep 17 00:00:00 2001
From: Evan Pratten <ewpratten@gmail.com>
Date: Sat, 24 Apr 2021 16:39:36 -0400
Subject: [PATCH 9/9] fix access

---
 src/items.rs  | 6 +++---
 src/player.rs | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/items.rs b/src/items.rs
index 87d979e..a541098 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -12,8 +12,8 @@ use serde::{Deserialize, Serialize};
 
 #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
 pub struct StunGun {
-    range: f32,
-    duration: f64
+    pub range: f32,
+    pub duration: f64
 }
 
 #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
@@ -24,5 +24,5 @@ pub struct Flashlight;
 
 #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
 pub struct Flippers {
-    speed_increase: f32
+    pub speed_increase: f32
 }
\ No newline at end of file
diff --git a/src/player.rs b/src/player.rs
index afdd68c..6562a32 100644
--- a/src/player.rs
+++ b/src/player.rs
@@ -79,7 +79,7 @@ impl Player {
     /// Try to attack with the stun gun
     pub fn begin_attack(&mut self) {
         if true || self.inventory.stun_gun.is_some() && self.stun_timer == 0.0 {
-            self.attacking_timer = STUN_ATTACK_TIME;
+            self.attacking_timer = self.inventory.stun_gun.as_ref().unwrap().duration;
         }
     }