From 3bdf44994c64676d0f2096eaad2cfdf3d948ca1e Mon Sep 17 00:00:00 2001
From: Dominic Masters <dominic@domsplace.com>
Date: Thu, 30 Mar 2023 18:29:56 -0700
Subject: [PATCH] Testing some enemies

---
 src/dawn/scene/Scene.cpp                      |  2 +-
 .../physics/2d/CharacterController2D.cpp      | 27 +++++---
 .../physics/2d/CharacterController2D.hpp      | 14 +++-
 src/dawn/scene/debug/SceneDebugLine.cpp       | 23 ++++---
 src/dawnrose/CMakeLists.txt                   |  4 +-
 src/dawnrose/scene/components/CMakeLists.txt  |  3 +
 .../scene/components/EntityHealth.cpp         | 39 +++++++++++
 .../scene/components/EntityHealth.hpp         | 51 ++++++++++++++
 .../scene/components/EntityRandomWalk.cpp     | 53 ++++++++++++++
 .../scene/components/EntityRandomWalk.hpp     | 30 ++++++++
 src/dawnrose/scene/components/HurtHazard.cpp  | 11 +++
 src/dawnrose/scene/components/HurtHazard.hpp  | 16 +++++
 .../scene/components/PlayerController.cpp     | 31 ++++++++-
 .../scene/components/PlayerController.hpp     |  9 ++-
 src/dawnrose/scenes/HelloWorldScene.hpp       | 20 ++++--
 src/dawnshared/util/mathutils.hpp             |  9 +--
 src/dawnshared/util/random.hpp                | 69 +++++++++++--------
 src/dawntools/prefabtool/Parsers.hpp          |  5 ++
 .../prefabtool/PrefabComponentParser.cpp      |  2 +
 19 files changed, 348 insertions(+), 70 deletions(-)
 create mode 100644 src/dawnrose/scene/components/EntityHealth.cpp
 create mode 100644 src/dawnrose/scene/components/EntityHealth.hpp
 create mode 100644 src/dawnrose/scene/components/EntityRandomWalk.cpp
 create mode 100644 src/dawnrose/scene/components/EntityRandomWalk.hpp
 create mode 100644 src/dawnrose/scene/components/HurtHazard.cpp
 create mode 100644 src/dawnrose/scene/components/HurtHazard.hpp

diff --git a/src/dawn/scene/Scene.cpp b/src/dawn/scene/Scene.cpp
index f097427a..86908e22 100644
--- a/src/dawn/scene/Scene.cpp
+++ b/src/dawn/scene/Scene.cpp
@@ -28,7 +28,7 @@ void Scene::update() {
   this->itemsNotInitialized.clear();
 
   #if DAWN_DEBUG_BUILD
-    // this->debugGrid();
+    this->debugGrid();
     this->debugOrigin();
     this->debugHitboxes();
   #endif
diff --git a/src/dawn/scene/components/physics/2d/CharacterController2D.cpp b/src/dawn/scene/components/physics/2d/CharacterController2D.cpp
index fb2a924b..63844fe0 100644
--- a/src/dawn/scene/components/physics/2d/CharacterController2D.cpp
+++ b/src/dawn/scene/components/physics/2d/CharacterController2D.cpp
@@ -33,11 +33,7 @@ void CharacterController2D::onStart() {
       auto allColliders = getScene()->findComponents<Collider2D>();
       auto itColliders = allColliders.begin();
 
-      glm::vec2 normal;
-      float_t entryTime;
-      float_t exitTime;
-      glm::vec2 entryPoint;
-      glm::vec2 exitPoint;
+      struct CharacterController2DCollisionEventInfo info;
       bool_t result = false;
 
       // Check for collisions, definitely not working 100% yet 
@@ -46,20 +42,33 @@ void CharacterController2D::onStart() {
         ++itColliders;
         if(c == myCollider) continue;
         result = myCollider->getCollidingResult(
-          velocity, c, normal, entryTime, exitTime, entryPoint, exitPoint
-        ) && entryTime <= delta;
-        if(result) break;
+          velocity,
+          c,
+          info.normal,
+          info.entryTime,
+          info.exitTime,
+          info.entryPoint,
+          info.exitPoint
+        ) && info.entryTime <= delta;
+        if(result) {
+          info.collider = c;
+          break;
+        }
       }
       
       if(result) {
         moveAmount = glm::vec2(0, 0);
         velocity = glm::vec2(0, 0);
+        this->eventCollision.invoke(info);
       } else {
         moveAmount = velocity;
       }
     }
 
-    if(mathAbs<float_t>(moveAmount.x) <= 0.001f && mathAbs<float_t>(moveAmount.y) <= 0.001f) return;
+    if(
+      mathAbs<float_t>(moveAmount.x) <= 0.001f &&
+      mathAbs<float_t>(moveAmount.y) <= 0.001f
+    ) return;
 
     transform->setLocalPosition(
       transform->getLocalPosition() + (glm::vec3(moveAmount.x, 0, moveAmount.y) * delta)
diff --git a/src/dawn/scene/components/physics/2d/CharacterController2D.hpp b/src/dawn/scene/components/physics/2d/CharacterController2D.hpp
index 04d5bbd4..d897d5f6 100644
--- a/src/dawn/scene/components/physics/2d/CharacterController2D.hpp
+++ b/src/dawn/scene/components/physics/2d/CharacterController2D.hpp
@@ -7,15 +7,23 @@
 #include "Collider2D.hpp"
 
 namespace Dawn {
+  struct CharacterController2DCollisionEventInfo {
+    Collider2D *collider;
+    glm::vec2 normal;
+    float_t entryTime;
+    float_t exitTime;
+    glm::vec2 entryPoint;
+    glm::vec2 exitPoint;
+  };
+
   class CharacterController2D : public SceneItemComponent {
-    private:
-      void move(glm::vec2 distance);
-      
     public:
       // @optional
       glm::vec2 velocity = glm::vec2(0, 0);
       // @optional
       float_t friction = 12.0f;
+
+      StateEvent<struct CharacterController2DCollisionEventInfo> eventCollision;
       
       CharacterController2D(SceneItem *i);
       void onStart() override;
diff --git a/src/dawn/scene/debug/SceneDebugLine.cpp b/src/dawn/scene/debug/SceneDebugLine.cpp
index eb4575bf..e6954cec 100644
--- a/src/dawn/scene/debug/SceneDebugLine.cpp
+++ b/src/dawn/scene/debug/SceneDebugLine.cpp
@@ -62,11 +62,11 @@ void Scene::debugLine(struct SceneDebugLine line) {
 }
 
 void Scene::debugRay(struct SceneDebugRay ray) {
-  this->debugLine((struct SceneDebugLine){
-    .v0 = ray.start,
-    .v1 = ray.start + ray.direction,
-    .color = ray.color
-  });
+  struct SceneDebugLine line;
+  line.v0 = ray.start;
+  line.v1 = ray.start + ray.direction;
+  line.color = ray.color;
+  this->debugLine(line);
 }
 
 void Scene::debugCube(struct SceneDebugCube cube) {
@@ -154,12 +154,13 @@ void Scene::debugHitboxes() {
     switch(c->getColliderType()) {
       case COLLIDER3D_TYPE_CUBE:
         auto asCube = dynamic_cast<CubeCollider*>(c);
-        this->debugCube((struct SceneDebugCube){
-          .min = asCube->min,
-          .max = asCube->max,
-          .color = COLOR_BLUE,
-          .transform = asCube->transform->getWorldTransform()
-        });
+        struct SceneDebugCube c2;
+        c2.min = asCube->min;
+        c2.max = asCube->max;
+        c2.color = COLOR_BLUE;
+        c2.transform = asCube->transform->getWorldTransform();
+
+        this->debugCube(c2);
         break;
     }
     ++itColliders;
diff --git a/src/dawnrose/CMakeLists.txt b/src/dawnrose/CMakeLists.txt
index a103937e..32584930 100644
--- a/src/dawnrose/CMakeLists.txt
+++ b/src/dawnrose/CMakeLists.txt
@@ -19,4 +19,6 @@ add_subdirectory(scene)
 
 # Assets
 set(ROSE_ASSETS_DIR ${DAWN_ASSETS_DIR}/games/rose)
-tool_prefab(${ROSE_ASSETS_DIR}/prefabs/Player.xml)
\ No newline at end of file
+tool_prefab(${ROSE_ASSETS_DIR}/prefabs/Player.xml)
+tool_prefab(${ROSE_ASSETS_DIR}/prefabs/Urchin.xml)
+tool_prefab(${ROSE_ASSETS_DIR}/prefabs/Crab.xml)
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/CMakeLists.txt b/src/dawnrose/scene/components/CMakeLists.txt
index e88c2c98..ea78b6e8 100644
--- a/src/dawnrose/scene/components/CMakeLists.txt
+++ b/src/dawnrose/scene/components/CMakeLists.txt
@@ -8,4 +8,7 @@ target_sources(${DAWN_TARGET_NAME}
   PRIVATE
     GameCamera.cpp
     PlayerController.cpp
+    EntityHealth.cpp
+    HurtHazard.cpp
+    EntityRandomWalk.cpp
 )
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/EntityHealth.cpp b/src/dawnrose/scene/components/EntityHealth.cpp
new file mode 100644
index 00000000..66e90fff
--- /dev/null
+++ b/src/dawnrose/scene/components/EntityHealth.cpp
@@ -0,0 +1,39 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "EntityHealth.hpp"
+
+using namespace Dawn;
+
+EntityHealth::EntityHealth(SceneItem* item) : SceneItemComponent(item) {
+  
+}
+
+void EntityHealth::onStart() {
+  useEvent([&](float_t delta){
+    if(this->invincibleTime > 0.0f) {
+      this->invincibleTime -= delta;
+    }
+
+    if(this->stunTime > 0.0f) {
+      this->stunTime -= delta;
+    }
+  }, getScene()->eventSceneUpdate);
+}
+
+bool_t EntityHealth::isInvincible() {
+  return this->invincibleTime > 0.0f;
+}
+
+bool_t EntityHealth::isStunned() {
+  return this->stunTime > 0.0f;
+}
+
+void EntityHealth::damage(struct DamageInformation info) {
+  if(this->isInvincible()) return;
+  this->health -= info.amount;
+  this->invincibleTime = info.invincibleTime;
+  this->stunTime = info.stunTime;
+}
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/EntityHealth.hpp b/src/dawnrose/scene/components/EntityHealth.hpp
new file mode 100644
index 00000000..ec8e0a29
--- /dev/null
+++ b/src/dawnrose/scene/components/EntityHealth.hpp
@@ -0,0 +1,51 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "scene/SceneItemComponent.hpp"
+
+namespace Dawn {
+  struct DamageInformation {
+    int32_t amount = 0;
+    float_t invincibleTime = 2.0f;
+    float_t stunTime = 0.4f;
+  };
+
+  class EntityHealth : public SceneItemComponent {
+    public:
+      // @optional
+      int32_t health = 10;
+      // @optional
+      int32_t maxHealth = 10;
+      // @optional
+      float_t invincibleTime = 0.0f;
+      // @optional
+      float_t stunTime = 0.0f;
+      
+      EntityHealth(SceneItem* item);
+      void onStart() override;
+
+      /**
+       * Returns true if the entity is invincible
+       * 
+       * @return True if invincible, false otherwise.
+       */
+      bool_t isInvincible();
+
+      /**
+       * Returns true if the entity is stunned.
+       * 
+       * @return True if stunned, false otherwise.
+       */
+      bool_t isStunned();
+
+      /**
+       * Apply damage to this entity.
+       * 
+       * @param info The damage information.
+       */
+      void damage(struct DamageInformation info);
+  };
+}
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/EntityRandomWalk.cpp b/src/dawnrose/scene/components/EntityRandomWalk.cpp
new file mode 100644
index 00000000..468ffb8f
--- /dev/null
+++ b/src/dawnrose/scene/components/EntityRandomWalk.cpp
@@ -0,0 +1,53 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "EntityRandomWalk.hpp"
+
+using namespace Dawn;
+
+EntityRandomWalk::EntityRandomWalk(SceneItem* item) : SceneItemComponent(item) {
+  
+}
+
+std::vector<SceneItemComponent*> EntityRandomWalk::getDependencies() {
+  return {
+    (characterController = item->getComponent<CharacterController2D>())
+  };
+}
+
+void EntityRandomWalk::onStart() {
+  assertNotNull(characterController);
+
+  useEvent([&](float_t delta) {
+    // Do we need to pick a new destination
+    if(timeLeftUntilNextDecision <= 0.0f) {
+      // Pick a new destination to walk to.
+      destination = randRange(-walkRange, walkRange);
+      destination.x = mathAbs(destination.y) > mathAbs(destination.x) ? 0 : destination.x;
+      destination.y = destination.x == 0 ? destination.y : 0;
+      destination += glm::vec2(transform->getLocalPosition().x, transform->getLocalPosition().z);
+      timeLeftUntilNextDecision = 4.0f;
+    } else {
+      timeLeftUntilNextDecision -= delta;
+    }
+
+    // Get the direction to move in
+    glm::vec2 pos = destination - glm::vec2(
+      transform->getLocalPosition().x,
+      transform->getLocalPosition().z
+    );
+
+    // Conver to an angle and then convert back into a 2D vector. This mimics a
+    // user essentially "moving the analogue stick in this direction"
+    
+    if(mathAbs(pos.x) > 1.0f || mathAbs(pos.y) > 1.0f) {
+      float_t angle = atan2(pos.y, pos.x);
+      glm::vec2 movement(cos(angle), sin(angle));
+      transform->setLocalRotation(glm::quat(glm::vec3(0, -angle + 1.5708f, 0)));
+      characterController->velocity += movement * delta * moveSpeed;
+    }
+    
+  }, getScene()->eventSceneUpdate);
+}
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/EntityRandomWalk.hpp b/src/dawnrose/scene/components/EntityRandomWalk.hpp
new file mode 100644
index 00000000..90644efb
--- /dev/null
+++ b/src/dawnrose/scene/components/EntityRandomWalk.hpp
@@ -0,0 +1,30 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "scene/SceneItemComponent.hpp"
+#include "util/random.hpp"
+#include "scene/components/physics/2d/CharacterController2D.hpp"
+
+namespace Dawn {
+  class EntityRandomWalk : public SceneItemComponent {
+    protected:
+      CharacterController2D *characterController = nullptr;
+
+    public:
+      // @optional
+      float_t timeLeftUntilNextDecision = 0.0f;
+      // @optional
+      float_t moveSpeed = 30.0f;
+      // @optional
+      glm::vec2 destination = glm::vec2(0, 0);
+      // @optional
+      glm::vec2 walkRange = glm::vec2(12.0f, 12.0f);
+
+      EntityRandomWalk(SceneItem* item);
+      std::vector<SceneItemComponent*> getDependencies() override;
+      void onStart() override;
+  };
+}
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/HurtHazard.cpp b/src/dawnrose/scene/components/HurtHazard.cpp
new file mode 100644
index 00000000..b26f863d
--- /dev/null
+++ b/src/dawnrose/scene/components/HurtHazard.cpp
@@ -0,0 +1,11 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "HurtHazard.hpp"
+
+using namespace Dawn;
+
+HurtHazard::HurtHazard(SceneItem* item) : SceneItemComponent(item) {}
+
diff --git a/src/dawnrose/scene/components/HurtHazard.hpp b/src/dawnrose/scene/components/HurtHazard.hpp
new file mode 100644
index 00000000..c779d8b0
--- /dev/null
+++ b/src/dawnrose/scene/components/HurtHazard.hpp
@@ -0,0 +1,16 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "scene/SceneItemComponent.hpp"
+
+namespace Dawn {
+  class HurtHazard : public SceneItemComponent {
+    public:
+      int32_t damage = 1;
+      
+      HurtHazard(SceneItem* item);
+  };
+}
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/PlayerController.cpp b/src/dawnrose/scene/components/PlayerController.cpp
index 8c0ab88b..1d593894 100644
--- a/src/dawnrose/scene/components/PlayerController.cpp
+++ b/src/dawnrose/scene/components/PlayerController.cpp
@@ -14,19 +14,24 @@ PlayerController::PlayerController(SceneItem *item) : SceneItemComponent(item) {
 
 std::vector<SceneItemComponent*> PlayerController::getDependencies() {
   return {
-    (this->characterController = item->getComponent<CharacterController2D>())
+    (this->characterController = item->getComponent<CharacterController2D>()),
+    (this->entityHealth = item->getComponent<EntityHealth>())
   };
 }
 
 void PlayerController::onStart() {
   assertNotNull(this->characterController);
+  assertNotNull(this->entityHealth);
 
   useEvent([&](float_t delta){
+    // Don't move if stunned.
+    if(entityHealth->isStunned()) return;
+
     // Movement
     auto inputMove = getGame()->inputManager.getAxis2D(
       INPUT_BIND_NEGATIVE_X, INPUT_BIND_POSITIVE_X,
       INPUT_BIND_NEGATIVE_Y, INPUT_BIND_POSITIVE_Y
-    ) * delta * moveSpeed;
+    );
     
     if(inputMove.x != 0 || inputMove.y != 0) {
       float_t angle = atan2(inputMove.y, inputMove.x);
@@ -37,4 +42,26 @@ void PlayerController::onStart() {
       characterController->velocity += movement * delta * moveSpeed;
     }
   }, getScene()->eventSceneUpdate);
+
+  // Hurt Hazard Processing
+  useEvent([&](struct CharacterController2DCollisionEventInfo info) {
+    if(entityHealth->isInvincible()) return;
+
+    auto hurtHazard = info.collider->item->getComponent<HurtHazard>();
+    if(hurtHazard == nullptr) return;
+
+    glm::vec2 back = glm::vec2(
+      info.collider->transform->getLocalPosition().x,
+      info.collider->transform->getLocalPosition().z
+    ) - glm::vec2(
+      this->transform->getLocalPosition().x,
+      this->transform->getLocalPosition().z
+    );
+
+    this->characterController->velocity = back * -hitKnockback;
+    this->entityHealth->damage({
+      .amount = hurtHazard->damage
+    });
+  }, this->characterController->eventCollision);
+
 }
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/PlayerController.hpp b/src/dawnrose/scene/components/PlayerController.hpp
index 09e7641b..735e7ea5 100644
--- a/src/dawnrose/scene/components/PlayerController.hpp
+++ b/src/dawnrose/scene/components/PlayerController.hpp
@@ -5,20 +5,23 @@
 
 #pragma once
 #include "scene/components/physics/2d/CharacterController2D.hpp"
+#include "scene/components/HurtHazard.hpp" 
+#include "scene/components/EntityHealth.hpp"
 
 namespace Dawn {
   class PlayerController : public SceneItemComponent {
     protected:
       CharacterController2D *characterController;
+      EntityHealth *entityHealth;
 
     public:
       // @optional
-      float_t moveSpeed = 80.0f;
+      float_t moveSpeed = 60.0f;
+      // @optional
+      float_t hitKnockback = 20.0f;
 
       PlayerController(SceneItem *item);
-
       std::vector<SceneItemComponent*> getDependencies() override;
-
       void onStart() override;
   };
 }
\ No newline at end of file
diff --git a/src/dawnrose/scenes/HelloWorldScene.hpp b/src/dawnrose/scenes/HelloWorldScene.hpp
index 4a0a656c..c34432a7 100644
--- a/src/dawnrose/scenes/HelloWorldScene.hpp
+++ b/src/dawnrose/scenes/HelloWorldScene.hpp
@@ -7,6 +7,8 @@
 #include "scene/Scene.hpp"
 #include "scene/components/GameCamera.hpp"
 #include "prefabs/Player.hpp"
+#include "prefabs/Urchin.hpp"
+#include "prefabs/Crab.hpp"
 #include "prefabs/ui/debug/FPSLabel.hpp"
 #include "display/mesh/CapsuleMesh.hpp"
 #include "display/mesh/CubeMesh.hpp"
@@ -21,15 +23,21 @@ namespace Dawn {
 
         auto player = Player::create(this);
 
+        auto urchin = Urchin::create(this);
+        urchin->transform.setLocalPosition(glm::vec3(0, 0, -5));
+
+        auto crab = Crab::create(this);
+        crab->transform.setLocalPosition(glm::vec3(3, 0, 0));
+
         canvas = UICanvas::create(this);
 
-        auto wallBox = this->createSceneItem()->addComponent<BoxCollider>();
-        wallBox->min = glm::vec2(-4, -3);
-        wallBox->max = glm::vec2(-3, 3);
+        // auto wallBox = this->createSceneItem()->addComponent<BoxCollider>();
+        // wallBox->min = glm::vec2(-4, -3);
+        // wallBox->max = glm::vec2(-3, 3);
         
-        auto wallBox2 = this->createSceneItem()->addComponent<BoxCollider>();
-        wallBox2->min = glm::vec2(-3, -4);
-        wallBox2->max = glm::vec2(3, -3);
+        // auto wallBox2 = this->createSceneItem()->addComponent<BoxCollider>();
+        // wallBox2->min = glm::vec2(-3, -4);
+        // wallBox2->max = glm::vec2(3, -3);
         
         camera = Camera::create(this);
         camera->fov = 0.436332f;
diff --git a/src/dawnshared/util/mathutils.hpp b/src/dawnshared/util/mathutils.hpp
index 5c689eed..bc280002 100644
--- a/src/dawnshared/util/mathutils.hpp
+++ b/src/dawnshared/util/mathutils.hpp
@@ -68,12 +68,13 @@ namespace Dawn {
    * @param b Number to modulo with. (a % b)
    * @returns The modulo result.
    */
-  static float_t mathMod(float_t value, float_t modulo) {
-    return (float_t)fmod(value, modulo);
+  template<typename T>
+  static inline T mathMod(T value, T modulo) {
+    return ((value % modulo) + modulo) % modulo;
   }
 
-  static int32_t mathMod(int32_t value, int32_t modulo) {
-    return ((value % modulo) + modulo) % modulo;
+  static inline float_t mathMod(float_t value, float_t modulo) {
+    return (float_t)fmod(value, modulo);
   }
 
   /**
diff --git a/src/dawnshared/util/random.hpp b/src/dawnshared/util/random.hpp
index 8f1c3ffc..aa065531 100644
--- a/src/dawnshared/util/random.hpp
+++ b/src/dawnshared/util/random.hpp
@@ -4,40 +4,49 @@
 // https://opensource.org/licenses/MIT
 
 #pragma once
-#include "dawnlibs.hpp"
 #include "mathutils.hpp"
 
-/**
- * Seed the random number generator
- * @param seed Seed to use for the seeded random number generator.
- */
-static void randSeed(int32_t seed) {
-  srand(seed);
-}
+namespace Dawn {
+  /**
+   * Seed the random number generator
+   * @param seed Seed to use for the seeded random number generator.
+   */
+  static void randSeed(int32_t seed) {
+    srand(seed);
+  }
 
-static int32_t randomGeneratei32() {
-  return (int32_t)rand();
-}
+  static int32_t randomGeneratei32() {
+    return (int32_t)rand();
+  }
 
-/**
- * Generates a random number.
- * @returns A random number.
- */
-template<typename T>
-static T randomGenerate() {
-  return (T)((float_t)randomGeneratei32() * MATH_PI);
-}
+  /**
+   * Generates a random number.
+   * @returns A random number.
+   */
+  template<typename T>
+  static T randomGenerate() {
+    return (T)((float_t)randomGeneratei32() * MATH_PI);
+  }
 
-////////////////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////////////////
 
-/**
- * Clamps a random number generation.
- * 
- * @param min Minimum value to generate from. (Inclusive)
- * @param max Maximum value to generate to. (Exclusive)
- * @return Random number between min and max.
- */
-template<typename T>
-static inline T randRange(T min, T max) {
-  return mathMod(randomGenerate<T>(), (max - min)) + min;
+  /**
+   * Clamps a random number generation.
+   * 
+   * @param min Minimum value to generate from. (Inclusive)
+   * @param max Maximum value to generate to. (Exclusive)
+   * @return Random number between min and max.
+   */
+  template<typename T>
+  static inline T randRange(T min, T max) {
+    return mathMod<T>(randomGenerate<T>(), (max - min)) + min;
+  }
+
+  static inline float_t randRange(float_t min, float_t max) {
+    return mathMod(randomGenerate<float_t>(), (max - min)) + min;
+  }
+
+  static inline glm::vec2 randRange(glm::vec2 min, glm::vec2 max) {
+    return glm::vec2(randRange(min.x, max.x), randRange(min.y, max.y));
+  }
 }
\ No newline at end of file
diff --git a/src/dawntools/prefabtool/Parsers.hpp b/src/dawntools/prefabtool/Parsers.hpp
index 3fcf7f56..62715d45 100644
--- a/src/dawntools/prefabtool/Parsers.hpp
+++ b/src/dawntools/prefabtool/Parsers.hpp
@@ -33,6 +33,11 @@ namespace Dawn {
     return v;
   };
 
+  static inline std::string intParser(std::string v, std::string *error) {
+    v = stringTrim(v);
+    return v;
+  }
+
   static inline std::string vec2Parser(std::string v, std::string *error) {
     // Split string by comma into two strings that we pass into float
     auto split = stringSplit(v, ",");
diff --git a/src/dawntools/prefabtool/PrefabComponentParser.cpp b/src/dawntools/prefabtool/PrefabComponentParser.cpp
index e84e316e..10e5cb1d 100644
--- a/src/dawntools/prefabtool/PrefabComponentParser.cpp
+++ b/src/dawntools/prefabtool/PrefabComponentParser.cpp
@@ -57,6 +57,8 @@ int32_t PrefabComponentParser::onParse(
       parser = vec2Parser;
     } else if(type.find("vec3") != std::string::npos) {
       parser = vec3Parser;
+    } else if(type == "int32_t" || type == "int") {
+      parser = intParser;
     } else if(type.find("*") == (type.size() - 1)) {
       type = type.substr(0, type.size() - 1);
       parser = rawParser;