Kaynağa Gözat

Reworked trigger entities code.
Now only the playable character triggers them, the proper event is triggered in each case, and their sensibilities have been adjusted. Line entity events renamed to more descriptive names.

Iñigo Valentin 3 yıl önce
ebeveyn
işleme
1208f40690

+ 0 - 1
V-Gears-Installer/src/DataInstaller.cpp

@@ -145,7 +145,6 @@ int DataInstaller::Progress(){
             cur_substep_ = 0;
             return CalcProgress();
         case MEDIA_SOUNDS:
-            write_output_line_("Extracting sound " + std::to_string(cur_substep_), 2, true);
             if (media_installer_->InstallSounds() == true)
                 installation_state_ = MEDIA_SOUNDS_INDEX;
             else cur_substep_ ++;

+ 4 - 4
V-Gears-Installer/src/FieldDataInstaller.cpp

@@ -42,13 +42,13 @@ std::string FieldDataInstaller::CreateGateWayScript(
       "    on_start = function(self)\n"
       "        return 0\n"
       "    end,\n\n"
-      "    on_enter_line = function(self, entity)\n"
+      "    on_approach = function(self, entity)\n"
       "        return 0\n"
       "    end,\n\n"
-      "    on_move_to_line = function(self, entity)\n"
+      "    on_cross = function(self, entity)\n"
       "        return 0\n"
       "    end,\n\n"
-      "    on_cross_line = function(self, entity)\n"
+      "    on_near = function(self, entity)\n"
       "        if entity == \"Cloud\" then\n"
       "            if not FFVII.Data.DisableGateways then\n"
       "                load_field_map_request(\""
@@ -57,7 +57,7 @@ std::string FieldDataInstaller::CreateGateWayScript(
       "        end\n"
       "        return 0\n"
       "    end,\n\n"
-      "    on_leave_line = function(self, entity)\n"
+      "    on_leave = function(self, entity)\n"
       "        return 0\n"
       "    end,\n"
       "}\n\n";

+ 10 - 10
V-Gears-Installer/src/decompiler/field/FieldDisassembler.cpp

@@ -216,16 +216,16 @@ void FieldDisassembler::AddFunc(
             case 0: break;
             // [OK] - on_interact
             case 1: break;
-            // Move - on_enter_line
-            case 2: func->name = "on_enter_line"; break;
-            // Move - on_move_to_line
-            case 3: func->name = "on_move_to_line"; break;
-            // Go - on_cross_line
-            case 4: func->name = "on_cross_line"; break;
-            // Go1x - on_cross_line
-            case 5: func->name = "on_cross_line_once"; break;
-            // GoAway - on_leave_line
-            case 6: func->name = "on_leave_line"; break;
+            // Move - on_approach
+            case 2: func->name = "on_approach"; break;
+            // Move - on_cross
+            case 3: func->name = "on_cross"; break;
+            // Go - on_near
+            case 4: func->name = "on_near"; break;
+            // Go1x - on_near
+            case 5: func->name = "on_near_once"; break;
+            // GoAway - on_leave
+            case 6: func->name = "on_leave"; break;
         }
     }
     int id = FindId(func->start_addr, func->end_addr, insts_);

+ 4 - 4
V-Gears-Installer/src/decompiler/field/FieldEngine.cpp

@@ -88,10 +88,10 @@ void FieldEngine::Entity::MarkAsLine(
     }
     // TODO: These are not getting to the final script.
     // Maybe this can be removed?
-    AddFunction("on_enter_line", 1);
-    AddFunction("on_move_to_line", 2);
-    AddFunction("on_cross_line", 3);
-    AddFunction("on_leave_line", 4);
+    AddFunction("on_approach", 1);
+    AddFunction("on_cross", 2);
+    AddFunction("on_near", 3);
+    AddFunction("on_leave", 4);
 }
 
 bool FieldEngine::Entity::IsLine(){return is_line_;}

+ 1 - 1
V-Gears/include/core/EntityManager.h

@@ -439,7 +439,7 @@ class EntityManager : public Ogre::Singleton<EntityManager>{
          *
          * If there are triggers, and the conditions are met, the appropriate trigger function will
          * be added to the queue. This must be tested every time an entity moves. If the entity is
-         * not solid, it will do nothing.
+         * not the playable character, is not solid or is locked, it will do nothing.
          *
          * @param[in] entity Entity to check for nearby triggers.
          * @param[in] position The position of the entity.

+ 140 - 27
V-Gears/include/core/EntityTrigger.h

@@ -67,50 +67,132 @@ class EntityTrigger{
         bool IsEnabled() const;
 
         /**
-         * Adds an activator to the trigger.
+         * Sets the vertices of the line that acts as the trigger.
          *
-         * @param[in] activator Trigger activator entity.
+         * @param[in] point1 One of the vertices of the line.
+         * @param[in] point2 One of the vertices of the line.
          */
-        void AddActivator(Entity* activator);
+        void SetPoints(const Ogre::Vector3& point1, const Ogre::Vector3& point2);
 
         /**
-         * Removes an activator from the trigger.
+         * Retrieves the first vertex of the line that acts as trigger.
          *
-         * @param[in] activator Entity to remove as activator.
+         * @return The first vertex.
          */
-        void RemoveActivator(Entity* activator);
+        const Ogre::Vector3& GetPoint1() const;
 
         /**
-         * Checks if an entity is an activator of the trigger.
+         * Retrieves the second vertex of the line that acts as trigger.
          *
-         * @param[in] activator Entity to test as an activator.
-         * @return True if the entity is an activator, false otherwise.
+         * @return The second vertex.
          */
-        bool IsActivator(Entity* activator);
+        const Ogre::Vector3& GetPoint2() const;
 
         /**
-         * Sets the vertices of the line that acts as the trigger.
+         * Check if the line has been approached.
          *
-         * @param[in] point1 One of the vertices of the line.
-         * @param[in] point2 One of the vertices of the line.
+         * @return True if the playable entity solid radius has collided with the line and has not
+         * existed yet, false otherwise.
          */
-        void SetPoints(
-          const Ogre::Vector3& point1, const Ogre::Vector3& point2
-        );
+        const bool CheckApproached();
 
         /**
-         * Retrieves the first vertex of the line that acts as trigger.
+         * Sets if the the playable entity has approached the line.
          *
-         * @return The first vertex.
+         * Must be set to true when the playable entity's solid radius touches the line while
+         * manually moving, and to false when the playable entity is not near the line.
+         *
+         * @param[in] entered If the line has been approached.
          */
-        const Ogre::Vector3& GetPoint1() const;
+        void SetApproached(const bool approached);
 
         /**
-         * Retrieves the second vertex of the line that acts as trigger.
+         * Check if the line has been crossed.
          *
-         * @return The second vertex.
+         * @return True if the playable entity's center has collided with the line and has not
+         * existed yet (exit as in the line being outside the entity solid radius), false otherwise.
          */
-        const Ogre::Vector3& GetPoint2() const;
+        const bool CheckCrossed();
+
+        /**
+         * Sets if the the playable entity has crossed the line.
+         *
+         * Must be set to true when the playable entity's center touches the line while
+         * manually moving, and to false when the playable entity is not near the line.
+         *
+         * @param[in] crossed If the line has been approached.
+         */
+        void SetCrossed(const bool crossed);
+
+        /**
+         * Checks if the on_near_once event has been fired.
+         *
+         * @return True if the on_near_once event has been fired and the entity has not yet exited
+         * the line (exit as in the line being outside the entity solid radius), and false if the
+         * playable entity has approached the line but the event has not been triggered yet.
+         */
+        const bool CheckNearSingleEventTriggered();
+
+        /**
+         * Sets if the on_near_once have been triggered.
+         *
+         * Must be set to true when it's run, and to false when the playable entity is not near the
+         * line.
+         *
+         * @param[in] triggered If the on_near_once has been triggered.
+         */
+        void SetNearSingleEventTriggered(const bool triggered);
+
+        /**
+         * Checks if the cooldown that prevents caling the on_near event multiple times has ended.
+         *
+         * After the on_near script is run, a cooltime of a number of frames is set before running
+         * it again. This is because most of the time this trigger checks for a key, and if its
+         * pressed, is run multiple times.
+         *
+         * @return The number of frames remaining in the cooldown. If it's 0, the on_near event can
+         * be called again. If not, {@see DecreaseNearEventCooldown} must be called.
+         */
+        const int GetNearEventCooldown();
+
+        /**
+         * Decreases the cooldown time required between calls to on_near event by one.
+         *
+         * After the on_near script is run, a cooltime of a number of frames is set before running
+         * it again. This is because most of the time this trigger checks for a key, and if its
+         * pressed, is run multiple times.
+         */
+        void DecreaseNearEventCooldown();
+
+        /**
+         * Resets the cooldown time required between calls to on_near event.
+         *
+         * After the on_near script is run, a cooltime of a number of frames is set before running
+         * it again. This is because most of the time this trigger checks for a key, and if its
+         * pressed, is run multiple times.
+         *
+         * Must be called after firing the on_near event. After calling this, the cooldown will be
+         * reset, and all frames must be waited before calling it again.
+         */
+        void ResetNearEventCooldown();
+
+        /**
+         * Sets the cooldown time required between calls to on_near event to 0.
+         *
+         * After the on_near script is run, a cooltime of a number of frames is set before running
+         * it again. This is because most of the time this trigger checks for a key, and if its
+         * pressed, is run multiple times.
+         *
+         * Must be called whent the playable entity gets away from the line
+         */
+        void ClearNearEventCooldown();
+
+        /**
+         * Clears the proximity statuses and event triggering statuses.
+         *
+         * Can be called once the playable entity leaves the line.
+         */
+        void Clear();
 
     protected:
 
@@ -124,11 +206,6 @@ class EntityTrigger{
          */
         bool enabled_;
 
-        /**
-         * List of activators of the trigger.
-         */
-        std::vector<Entity*> activators_;
-
         /**
          * One of the vertices of the trigger line.
          */
@@ -138,5 +215,41 @@ class EntityTrigger{
          * One of the vertices of the trigger line.
          */
         Ogre::Vector3 point_2_;
+
+    private:
+
+        /**
+         * Frames to cooldown after triggering on_near event
+         *
+         * After the on_near script is run, a cooltime of a number of frames is set before running
+         * it again. This is because most of the time this trigger checks for a key, and if its
+         * pressed, is run multiple times.
+         */
+        static int NEAR_EVENT_COOLDOWN_FRAMES;
+
+        /**
+         * Indicates if the playable entity has approached the line.
+         */
+        bool approached_;
+
+        /**
+         * Indicates if the playable entity has crossed the line.
+         */
+        bool crossed_;
+
+        /**
+         * Indicates if the near_once event has been triggered.
+         */
+        bool near_single_event_triggered_;
+
+        /**
+         * Remaining frames to cooldown after triggering on_near event
+         *
+         * After the on_near script is run, a cooltime of a number of frames is set before running
+         * it again. This is because most of the time this trigger checks for a key, and if its
+         * pressed, is run multiple times.
+         */
+        int near_event_cooldown_;
+
 };
 

+ 0 - 9
V-Gears/src/core/AudioManager.cpp

@@ -106,7 +106,6 @@ void AudioManager::ScriptPlayMusic(const char* name){
 }
 
 void AudioManager::MusicPlay(const Ogre::String& name){
-    std::cout << "[MUSIC] play " << name << "\n";
     if (initialized_){
         boost::recursive_mutex::scoped_lock lock(update_mutex_);
         AudioManager::Music* music = GetMusic(name);
@@ -120,7 +119,6 @@ void AudioManager::MusicPlay(const Ogre::String& name){
 }
 
 void AudioManager::SoundPlay(const Ogre::String& name){
-    std::cout << "[FX] play " << name << "\n";
     if (initialized_){
         boost::recursive_mutex::scoped_lock lock(update_mutex_);
         AudioManager::Sound* fx = GetSound(name);
@@ -128,9 +126,6 @@ void AudioManager::SoundPlay(const Ogre::String& name){
             LOG_ERROR("No sound found with name \"" + name + "\".");
             return;
         }
-        //Player player(&update_mutex_);
-        //player.SetLoop(-1);
-        //player.Play(fx->file);
         fx_.SetLoop(-1);
         fx_.Play(fx->file);
     }
@@ -172,7 +167,6 @@ void AudioManager::AddMusic(const AudioManager::Music& music){
 }
 
 void AudioManager::AddSound(const AudioManager::Sound& sound){
-    std::cout << "[ADD_SOUND] " << sound.name << "\n";
     boost::recursive_mutex::scoped_lock lock(update_mutex_);
     for (
       std::list<AudioManager::Sound>::iterator it = sound_list_.begin();
@@ -312,18 +306,15 @@ void AudioManager::Player::Update(){
               static_cast<ALsizei>(buffer_size), static_cast<ALsizei>(vorbis_info_->rate)
             );
             alSourceQueueBuffers(source_, 1, &buffer_id);
-            std::cout << "Stream unfinished\n";
         }
         // Finished reading stream
         else{
-            std::cout << "Stream finished\n";
             stream_finished_ = true;
             break;
         }
     }
 
     if (stream_finished_ && loop_ < 0){
-        std::cout << "Stopping\n";
         Stop();
     }
 

+ 96 - 69
V-Gears/src/core/EntityManager.cpp

@@ -46,7 +46,9 @@ float EntityManager::PointElevation(
     return (_d - _c * point.y - _a * point.x) / _b;
 }
 
-float EntityManager::SideOfVector(const Ogre::Vector2& point, const Ogre::Vector2& p1, const Ogre::Vector2& p2){
+float EntityManager::SideOfVector(
+  const Ogre::Vector2& point, const Ogre::Vector2& p1, const Ogre::Vector2& p2
+){
     Ogre::Vector2 AB = p2    - p1;
     Ogre::Vector2 AP = point - p1;
     return AB.x * AP.y - AB.y * AP.x;
@@ -139,7 +141,7 @@ void EntityManager::Input(const VGears::Event& event){
             for (unsigned int i = 0; i < entity_triggers_.size(); ++ i){
                 if (
                   entity_triggers_[i]->IsEnabled() == true
-                  && entity_triggers_[i]->IsActivator(player_entity_) == true
+                  && entity_triggers_[i]->CheckApproached() == true
                 ){
                     ScriptEntity* scr_entity = ScriptManager::getSingleton().GetScriptEntityByName(
                       ScriptManager::ENTITY, entity_triggers_[i]->GetName()
@@ -148,7 +150,6 @@ void EntityManager::Input(const VGears::Event& event){
                       scr_entity, "on_interact", 1, "", "", false, false
                     );
                     if (added == false){
-                        // TODO: This pop's in almost any trigger, but it still works. Check it out.
                         LOG_WARNING(
                           "Script 'on_interact' for entity '" + entity_triggers_[i]->GetName()
                           + "' doesn't exist."
@@ -541,7 +542,7 @@ bool EntityManager::PerformWalkmeshMove(Entity* entity, const float speed){
     direction *= speed;
     // If movement is still needed but speed or time don't allow it, just return for now.
     if (direction.isZeroLength() == true){
-        CheckTriggers(entity, entity->GetPosition());
+        if (player_entity_ == entity) CheckTriggers(entity, entity->GetPosition());
         return false;
     }
     int current_triangle = entity->GetMoveTriangleId();
@@ -761,12 +762,12 @@ bool EntityManager::PerformWalkmeshMove(Entity* entity, const float speed){
       || third_entity_check != false
     ){
         // Event if the entity can't move, check for triggers, but use current position.
-        CheckTriggers(entity, entity->GetPosition());
+        if (player_entity_ == entity) CheckTriggers(entity, entity->GetPosition());
         return false;
     }
 
     // Check triggers before set entity position because move line is checked.
-    CheckTriggers(entity, end_point);
+    if (player_entity_ == entity) CheckTriggers(entity, end_point);
     entity->SetPosition(end_point);
 
     // If the entity has come to destination point, finish movement.
@@ -838,11 +839,14 @@ bool EntityManager::CheckSolidCollisions(Entity* entity, Ogre::Vector3& position
 
 void EntityManager::CheckTriggers(Entity* entity, const Ogre::Vector3& position){
     if (entity->IsSolid() == false) return;
+    if (player_entity_ != entity) return;
+    if (player_entity_->IsSolid() == false) return;
+    if (player_lock_) return;
     bool is_moving = true;
     if (
-      std::fabs(entity->GetPosition().x - position.x) < 0.01f
-      && std::fabs(entity->GetPosition().y - position.y) < 0.01f
-      && std::fabs(entity->GetPosition().z - position.z) < 0.01f
+      std::fabs(entity->GetPosition().x - position.x) < 0.005f
+      && std::fabs(entity->GetPosition().y - position.y) < 0.005f
+      && std::fabs(entity->GetPosition().z - position.z) < 0.005f
     ){
         is_moving = false;
     }
@@ -869,76 +873,99 @@ void EntityManager::CheckTriggers(Entity* entity, const Ogre::Vector3& position)
             Ogre::Degree angle = direction_to_line - movement_direction + Ogre::Degree(90);
             angle = (angle > Ogre::Degree(360)) ? angle - Ogre::Degree(360) : angle;
 
-            //bool active = false;
+
+            // Check on enter line.
+            // Must happen only once when the solid radius touches the line, while facing the line,
+            // while the entity is manually moving, and only if not already triggered.
             if (
-              square_dist != -1 && square_dist < solid_radius * solid_radius
-              //&& direction_to_line != destination_direction_to_line
-              //&& entity_triggers_[i]->IsActivator(entity) == false
-              // && angle < Ogre::Degree(180) && angle > Ogre::Degree(0)
+              square_dist != -1 && square_dist <= solid_radius * solid_radius
+              && angle < Ogre::Degree(180) && angle > Ogre::Degree(0)
+              && entity_triggers_[i]->CheckApproached() == false
+              && is_moving
             ){
+                entity_triggers_[i]->SetApproached(true);
+                //std::cout << "    [TRIGGER] " << entity->GetName() << " on_approach "
+                //  << entity_triggers_[i]->GetName() << std::endl;
+                ScriptManager::getSingleton().ScriptRequest(
+                  trigger, "on_approach", 1, entity->GetName(), "", false, false
+                );
+            }
 
-                // Test on_enter_line.
-                // To trigger it, the entity must currently be on one side on the line, and the
-                // destination point must be on the other side. The entity must be facing the line,
-                // and it must be moving.
-                if (is_moving && angle < Ogre::Degree(180) && angle > Ogre::Degree(0)){
-                    // Test on_move_to_line.
-                    // Same as on_enter_line, but even closer.
-                    if (square_dist < solid_radius * solid_radius * 0.5f){
-                        //std::cout << "    [TRIGGER] " << entity->GetName() << " on_move_to_line "
-                        //  << entity_triggers_[i]->GetName() << std::endl;
-                        ScriptManager::getSingleton().ScriptRequest(
-                          trigger, "on_move_to_line", 1, entity->GetName(), "", false, false
-                        );
-                        entity_triggers_[i]->AddActivator(entity);
-                    }
-                    //active = true;
-                    //std::cout << "    [TRIGGER] " << entity->GetName() << " on_enter_line "
-                    //  << entity_triggers_[i]->GetName() << std::endl;
-                    ScriptManager::getSingleton().ScriptRequest(
-                      trigger, "on_enter_line", 1, entity->GetName(), "", false, false
-                    );
-                    entity_triggers_[i]->AddActivator(entity);
-                }
+            // Check on move to line.
+            // Must happen only once when the entity center touches the line, if the entity has
+            // previously entered the line.
+            if (
+              square_dist != -1 && square_dist < 1
+              && entity_triggers_[i]->CheckCrossed() == false
+              && entity_triggers_[i]->CheckApproached() == true
+            ){
+                entity_triggers_[i]->SetCrossed(true);
+                //std::cout << "    [TRIGGER] " << entity->GetName() << " on_cross "
+                //  << entity_triggers_[i]->GetName() << std::endl;
+                ScriptManager::getSingleton().ScriptRequest(
+                  trigger, "on_cross", 1, entity->GetName(), "", false, false
+                );
+            }
 
-                // Test on_cross_line.
-                // To trigger it, the entity just needs to be close to the line.
-                if (square_dist != -1 && square_dist < solid_radius * solid_radius){
-                    //active = true;
+            // Check on cross line.
+            // Must happen on every frame while the entity solid radius collides with the line, if
+            // the entity has previously entered the line.
+            if (
+              square_dist != -1 && square_dist <= solid_radius * solid_radius
+              && entity_triggers_[i]->CheckApproached() == true
+            ){
+                // TODO: Fix this hack.
+                // After the on_near script is run, set a cooltime of 5 frames before running
+                // it again. This is because most of the time this trigger checks for a key, and
+                // if its pressed, is run multiple times.
+                if (entity_triggers_[i]->GetNearEventCooldown() == 0){
                     //std::cout << "    [TRIGGER] " << entity->GetName()
-                    //  << " on_cross_line " << entity_triggers_[i]->GetName() << std::endl;
+                    //  << " on_near " << entity_triggers_[i]->GetName() << std::endl;
                     ScriptManager::getSingleton().ScriptRequest(
-                      //trigger, "on_cross_line", 1, entity->GetName(), "", false, false
-                      trigger, "on_cross_line", 1, entity->GetName(), "", true, true
+                      trigger, "on_near", 1, entity->GetName(), "", true, true
                     );
-                    // Test on_cross_line_once.
-                    // Same conditions that on_cross_line, but triggered only once (i.e. if the
-                    // entity has not been registered as an activator.
-                    //std::cout << "    [TRIGGER] " << entity->GetName()
-                    //  << " on_cross_line_once " << entity_triggers_[i]->GetName() << std::endl;
-                    if (entity_triggers_[i]->IsActivator(entity) == false){
-                        ScriptManager::getSingleton().ScriptRequest(
-                          trigger, "on_cross_line_once", 1, entity->GetName(), "", false, false
-                        );
-                    }
-                    entity_triggers_[i]->AddActivator(entity);
+                    entity_triggers_[i]->ResetNearEventCooldown();
                 }
+                else entity_triggers_[i]->DecreaseNearEventCooldown();
             }
-            else{
-                // Test on_leave_line.
-                // To trigger it, on_enter_line must not be true, and the entity must be registered
-                // as an activator.
-                if (entity_triggers_[i]->IsActivator(entity)){
-                    //active = true;
-                    //std::cout << "    [TRIGGER] " << entity->GetName() << " on_leave_line "
-                    //  << entity_triggers_[i]->GetName() << std::endl;
-                    ScriptManager::getSingleton().ScriptRequest(
-                      trigger, "on_leave_line", 1, entity->GetName(), "", false, false
-                    );
-                    entity_triggers_[i]->RemoveActivator(entity);
-                }
+
+            // Check on cross line once.
+            // The same as on cross line, but only once.
+            if (
+              square_dist != -1 && square_dist < solid_radius * solid_radius
+              && entity_triggers_[i]->CheckNearSingleEventTriggered() == false
+              && entity_triggers_[i]->CheckApproached() == true
+            ){
+                entity_triggers_[i]->SetNearSingleEventTriggered(true);
+                //std::cout << "    [TRIGGER] " << entity->GetName()
+                //  << " on_near_once " << entity_triggers_[i]->GetName() << std::endl;
+                ScriptManager::getSingleton().ScriptRequest(
+                  trigger, "on_near_once", 1, entity->GetName(), "", false, false
+                );
+
+            }
+
+            // Check on leave line.
+            // Must be triggered once when the line is not in the entity solid radius, but only if
+            // on enter script has been triggered previously.
+            if (
+              square_dist != -1 && square_dist > solid_radius * solid_radius
+              && entity_triggers_[i]->CheckApproached()
+            ){
+                //std::cout << "    [TRIGGER] " << entity->GetName() << " on_leave "
+                //  << entity_triggers_[i]->GetName() << std::endl;
+                ScriptManager::getSingleton().ScriptRequest(
+                  trigger, "on_leave", 1, entity->GetName(), "", false, false
+                );
+            }
+
+            // If the entity is far enough from the line, mark every trigger as inactive
+            if (square_dist == -1 || square_dist > solid_radius * solid_radius){
+                entity_triggers_[i]->Clear();
+                //std::cout << "    [TRIGGER] " << entity->GetName() << " clear of "
+                //  << entity_triggers_[i]->GetName() << std::endl;
             }
-            //if (active) std::cout << "--------------------" << std::endl;
+
         }
     }
 }

+ 43 - 37
V-Gears/src/core/EntityTrigger.cpp

@@ -22,23 +22,26 @@ ConfigVar cv_debug_trigger(
   "debug_trigger", "Draw entity trigger debug info", "0"
 );
 
+int EntityTrigger::NEAR_EVENT_COOLDOWN_FRAMES = 5;
+
 EntityTrigger::EntityTrigger(const Ogre::String& name):
   name_(name),
   enabled_(false),
   point_1_(Ogre::Vector3::ZERO),
-  point_2_(Ogre::Vector3::ZERO)
+  point_2_(Ogre::Vector3::ZERO),
+  approached_(false),
+  crossed_(false),
+  near_single_event_triggered_(false),
+  near_event_cooldown_(0)
 {}
 
 EntityTrigger::~EntityTrigger(){}
 
 void EntityTrigger::UpdateDebug(){
     if (cv_debug_trigger.GetB() == true){
-        if (enabled_ == false)
-            DEBUG_DRAW.SetColour(Ogre::ColourValue(0.5f, 0.5f, 0.5f));
-        else if (activators_.size() > 0)
-            DEBUG_DRAW.SetColour(Ogre::ColourValue(0.04f, 0.9f, 0.5f));
-        else
-            DEBUG_DRAW.SetColour(Ogre::ColourValue(0.04f, 0.5f, 0.9f));
+        if (enabled_ == false) DEBUG_DRAW.SetColour(Ogre::ColourValue(0.5f, 0.5f, 0.5f));
+        else if (approached_ > 0) DEBUG_DRAW.SetColour(Ogre::ColourValue(0.04f, 0.9f, 0.5f));
+        else DEBUG_DRAW.SetColour(Ogre::ColourValue(0.04f, 0.5f, 0.9f));
         DEBUG_DRAW.Line3d(point_1_, point_2_);
         DEBUG_DRAW.SetColour(Ogre::ColourValue::White);
         DEBUG_DRAW.SetScreenSpace(true);
@@ -47,12 +50,6 @@ void EntityTrigger::UpdateDebug(){
         Ogre::Vector3 center = point_2_ - ((point_2_ - point_1_) / 2);
         DEBUG_DRAW.Text(center, 0, 0, name_);
         DEBUG_DRAW.SetColour(Ogre::ColourValue(0.04f, 0.9f, 0.5f));
-        for (unsigned int i = 0; i < activators_.size(); ++ i){
-            DEBUG_DRAW.Text(
-              center, 0.0f, static_cast<float>((i + 1) * 16),
-              activators_[i]->GetName()
-            );
-        }
     }
 }
 
@@ -60,34 +57,11 @@ const Ogre::String& EntityTrigger::GetName() const{return name_;}
 
 void EntityTrigger::SetEnabled(const bool enabled){
     enabled_ = enabled;
-    if (enabled == false) activators_.clear();
+    if (enabled == false) Clear();
 }
 
-
 bool EntityTrigger::IsEnabled() const{return enabled_;}
 
-void EntityTrigger::AddActivator(Entity* activator){
-    // Add only if this activator don't exist
-    unsigned int i = 0;
-    for (; i < activators_.size(); ++ i) if (activators_[i] == activator) break;
-    if (i == activators_.size()) activators_.push_back(activator);
-}
-
-void EntityTrigger::RemoveActivator(Entity* activator){
-    for (unsigned int i = 0; i < activators_.size(); ++ i){
-        if (activators_[i] == activator){
-            activators_.erase(activators_.begin() + i);
-            return;
-        }
-    }
-}
-
-bool EntityTrigger::IsActivator(Entity* activator){
-    for (unsigned int i = 0; i < activators_.size(); ++ i)
-        if (activators_[i] == activator) return true;
-    return false;
-}
-
 void EntityTrigger::SetPoints(
   const Ogre::Vector3& point1, const Ogre::Vector3& point2
 ){
@@ -98,3 +72,35 @@ void EntityTrigger::SetPoints(
 const Ogre::Vector3& EntityTrigger::GetPoint1() const{return point_1_;}
 
 const Ogre::Vector3& EntityTrigger::GetPoint2() const{return point_2_;}
+
+const bool EntityTrigger::CheckApproached(){return approached_;}
+
+void EntityTrigger::SetApproached(const bool approached){approached_ = approached;}
+
+const bool EntityTrigger::CheckCrossed(){return crossed_;}
+
+void EntityTrigger::SetCrossed(const bool crossed){crossed_ = crossed;}
+
+const bool EntityTrigger::CheckNearSingleEventTriggered(){return near_single_event_triggered_;}
+
+void EntityTrigger::SetNearSingleEventTriggered(const bool triggered){
+    near_single_event_triggered_ = triggered;
+}
+
+const int EntityTrigger::GetNearEventCooldown(){return near_event_cooldown_;}
+
+void EntityTrigger::DecreaseNearEventCooldown(){
+    if (near_event_cooldown_ > 0) near_event_cooldown_ --;
+}
+
+void EntityTrigger::ResetNearEventCooldown(){near_event_cooldown_ = NEAR_EVENT_COOLDOWN_FRAMES;}
+
+void EntityTrigger::ClearNearEventCooldown(){near_event_cooldown_ = 0;}
+
+void EntityTrigger::Clear(){
+    approached_ = false;
+    crossed_ = false;
+    near_single_event_triggered_ = false;
+    near_event_cooldown_ = 0;
+}
+