From 94c17aa5a5ce98b893b9847a0d48a23bf8a1773e Mon Sep 17 00:00:00 2001
From: Lorenz <lorenz-martin.diel@informatik.hs-fulda.de>
Date: Thu, 6 Feb 2025 15:57:34 +0100
Subject: [PATCH] Updated unit_context_menu + ChangingUnitState to Unavailable
 + Updated getUnitsInRangeWithDamagePotential to care about faction

---
 CMakeLists.txt     |   3 +-
 src/game/Level.cpp | 138 +++++++++++++++++++++++++++++----------------
 src/game/Level.hpp |   2 +
 src/game/Unit.cpp  |   5 +-
 src/game/Unit.hpp  |   2 +
 5 files changed, 98 insertions(+), 52 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5d70b3a..5be3ed4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -74,6 +74,8 @@ file(GLOB HDF5_FILES ${RES_DIR}/*.h5)
 # Executable erstellen
 add_executable(advanced_wars ${ADVANCED_WARS_SOURCES})
 
+set(CMAKE_MODULE_PATH ${ADVANCED_WARS_SOURCE_DIR}/cmake/ ${CMAKE_MODULE_PATH})
+
 # Plattform-spezifische Konfiguration
 if(APPLE)
     # SDL2 Frameworks für macOS
@@ -159,4 +161,3 @@ foreach(H5_FILE ${HDF5_FILES})
     )
 endforeach()
 
-set(CMAKE_MODULE_PATH ${ADVANCED_WARS_SOURCE_DIR}/cmake/ ${CMAKE_MODULE_PATH})
\ No newline at end of file
diff --git a/src/game/Level.cpp b/src/game/Level.cpp
index 53e8448..c1ba55c 100644
--- a/src/game/Level.cpp
+++ b/src/game/Level.cpp
@@ -83,6 +83,7 @@ std::shared_ptr<Level> Level::loadLevel(std::string path, Engine& engine)
     std::vector<Unit>     units;
     tiles.reserve(width * height);
     bool has_factions[] = {false, false, false, false, false};
+
     for (int i = 0; i < level_tilesarray.size(); i++)
     {
         int x = i % width;
@@ -275,7 +276,7 @@ void Level::render(Engine& engine)
     {
         tile.render(engine, RENDERING_SCALE);
     }
-
+    
     if (m_showReachableTiles)
     {
         SDL_SetRenderDrawColor(engine.renderer(), 255, 255, 0, 128); // Gelb mit leichtem Alpha
@@ -476,6 +477,7 @@ void Level::handleAttack(std::pair<int, int> tilePos)
             m_showAttackableTiles = false;
             m_showReachableTiles = false;
             m_state = LevelState::SELECTING_STATE;
+            attacking.setState(UnitState::UNAVAILABLE);
         }
         else
         {
@@ -490,6 +492,8 @@ void Level::handleAttack(std::pair<int, int> tilePos)
 
 void Level::handleMovement(std::pair<int, int> tilePos)
 {
+    //Herausnehmen um sich nicht bewegen zu müssen um ins kontextmenü zu kommen
+    /*
     for (auto& [id, unit] : m_units)
     {
         if (unit.m_x == tilePos.first && unit.m_y == tilePos.second)
@@ -498,7 +502,7 @@ void Level::handleMovement(std::pair<int, int> tilePos)
             std::cout << "Unit already at clicked position" << std::endl;
             return;
         }
-    }
+    }*/
 
     bool isReachable = false;
 
@@ -514,10 +518,13 @@ void Level::handleMovement(std::pair<int, int> tilePos)
     if (isReachable)
     {
         m_units.at(m_selectedUnit).updatePosition(tilePos.first, tilePos.second);
-        m_selectedUnit = -1;
+        // m_selectedUnit = -1;
         m_showAttackableTiles = false;
         m_showReachableTiles = false;
-        m_state = LevelState::SELECTING_STATE;
+        m_state = LevelState::MENUACTIVE_STATE;
+        m_contextMenu.update(
+                    (tilePos.first * 16 + 15) * RENDERING_SCALE,
+                    (tilePos.second * 16 + 15) * RENDERING_SCALE);
     }
     else
     {
@@ -557,56 +564,33 @@ void Level::handleSelectingEvents(Engine& engine, SDL_Event& event)
                 tilePos.first * 16 * RENDERING_SCALE, tilePos.second * 16 * RENDERING_SCALE);
             if (m_selectedUnit >= 0 || m_selectedBuilding >= 0)
             {
-                m_contextMenu.update(
-                    (tilePos.first * 16 + 15) * RENDERING_SCALE,
-                    (tilePos.second * 16 + 15) * RENDERING_SCALE);
+                
                 if (m_selectedUnit >= 0)
                 {
-                    m_reachableTiles = calculateMovementRange(m_units.at(m_selectedUnit));
-                    m_units.at(m_selectedUnit).on_left_click(event);
-                    m_showReachableTiles = true;
-
-                    std::vector<Unit*> allUnits;
-
-                    for (auto& [id, unit] : m_units)
+                    if (m_units.at(m_selectedUnit).getState() != UnitState::UNAVAILABLE)
                     {
-                        allUnits.push_back(&unit);
-                    }
-
-                    std::vector<Unit*> attackableTargets =
-                        m_units.at(m_selectedUnit).getUnitsInRangeWithDamagePotential(allUnits);
+                        m_reachableTiles = calculateMovementRange(m_units.at(m_selectedUnit));
+                        m_units.at(m_selectedUnit).on_left_click(event);
+                        m_showReachableTiles = true;
 
-                    m_attackableTiles.clear();
-                    m_showAttackableTiles = true;
-                    m_attackableUnitIds.clear();
-
-                    for (Unit* target : attackableTargets)
+                        m_contextMenu.setOptions({"Attack", "Info", "Wait"});
+                        m_state = LevelState::MOVEMENT_STATE;
+                    }
+                    else
                     {
-                        // Füge die Position jedes angreifbaren Ziels hinzu
-                        m_attackableTiles.emplace_back(target->m_x, target->m_y);
-
-                        // Angreifbaren Einheits-ID setzen
-                        for (auto& [id, unit] : m_units)
-                        {
-                            if (&unit == target)
-                            {
-                                m_attackableUnitIds.insert(id);
-                                break;
-                            }
-                        }
+                        std::cout << "unit is unavailable" << std::endl;
                     }
-
-                    m_contextMenu.setOptions({"Move", "Attack", "Info", "Wait"});
                 }
                 else
                 {
                     m_contextMenu.setOptions({"Train", "Info", "Wait"});
+                    m_state = LevelState::MENUACTIVE_STATE;
                 }
-                m_state = LevelState::MENUACTIVE_STATE;
             }
         }
         break;
     case SDL_MOUSEBUTTONDOWN:
+    /*
         if (event.button.button == SDL_BUTTON_LEFT)
         {
             selectEntity(event.button.x, event.button.y);
@@ -634,6 +618,7 @@ void Level::handleSelectingEvents(Engine& engine, SDL_Event& event)
                 m_state = LevelState::SELECTING_STATE;
             }
         }
+    */
     default:
         break;
     }
@@ -646,11 +631,9 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
     case SDL_KEYDOWN:
         if (event.key.keysym.sym == SDLK_ESCAPE)
         {
-            m_selectedUnit = -1;
-            m_selectedBuilding = -1;
             m_state = LevelState::SELECTING_STATE;
-            m_showAttackableTiles = false;
-            m_showReachableTiles = false;
+            m_units.at(m_selectedUnit)
+                .updatePosition(unit_fallback_position.first, unit_fallback_position.second);
         }
         if (event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN)
         {
@@ -661,12 +644,20 @@ void Level::handleMenuActiveEvents(Engine& engine, SDL_Event& event)
             std::string cmd = m_contextMenu.getSelectedOption();
             if (cmd == "Wait")
             {
-                m_state = LevelState::SELECTING_STATE;
-            }
-            if (cmd == "Move")
-            {
-                m_state = LevelState::MOVEMENT_STATE;
-                // Hier Pathfinding einsetzen
+                // m_units.at(m_selectedUnit).setState(UnitState::UNAVAILABLE);
+
+                // Pruefen, ob der Key existiert
+                auto it = m_units.find(m_selectedUnit);
+                if (it != m_units.end())
+                {
+                    it->second.setState(UnitState::UNAVAILABLE);
+                    std::cout << "Unit state set to UNAVAILABLE." << std::endl;
+                    m_state = LevelState::SELECTING_STATE;
+                }
+                else
+                {
+                    std::cerr << "Selected unit id is invalid: " << m_selectedUnit << std::endl;
+                }
             }
             if (cmd == "Attack")
             {
@@ -717,11 +708,26 @@ void Level::handleMovementEvents(Engine& engine, SDL_Event& event)
         handlePositionMarker(engine, event);
         if (event.key.keysym.sym == SDLK_RETURN)
         {
+
+            if (m_units.find(m_selectedUnit) != m_units.end())
+            {
+
+                Unit& selectedUnit = m_units.at(m_selectedUnit);
+                unit_fallback_position = {selectedUnit.m_x, selectedUnit.m_y};
+            }
+            else
+            {
+                std::cerr << "No unit selected or invalid unit index!" << std::endl;
+            }
             handleMovement(m_currentPos.getPosition());
         }
         if (event.key.keysym.sym == SDLK_ESCAPE)
         {
-            m_state = LevelState::MENUACTIVE_STATE;
+            m_selectedUnit = -1;
+            m_selectedBuilding = -1;
+            m_state = LevelState::SELECTING_STATE;
+            m_showAttackableTiles = false;
+            m_showReachableTiles = false;
         }
         break;
     case SDL_MOUSEBUTTONDOWN:
@@ -740,6 +746,35 @@ void Level::handleMovementEvents(Engine& engine, SDL_Event& event)
 
 void Level::handleAttackingEvents(Engine& engine, SDL_Event& event)
 {
+    std::vector<Unit*> allUnits;
+
+    for (auto& [id, unit] : m_units)
+    {
+        allUnits.push_back(&unit);
+    }
+
+    std::vector<Unit*> attackableTargets =
+        m_units.at(m_selectedUnit).getUnitsInRangeWithDamagePotential(allUnits);
+
+    m_attackableTiles.clear();
+    m_showAttackableTiles = true;
+    m_attackableUnitIds.clear();
+
+    for (Unit* target : attackableTargets)
+    {
+        // Füge die Position jedes angreifbaren Ziels hinzu
+        m_attackableTiles.emplace_back(target->m_x, target->m_y);
+
+        // Angreifbaren Einheits-ID setzen
+        for (auto& [id, unit] : m_units)
+        {
+            if (&unit == target)
+            {
+                m_attackableUnitIds.insert(id);
+                break;
+            }
+        }
+    }
     switch (event.type)
     {
     case SDL_KEYDOWN:
@@ -747,6 +782,9 @@ void Level::handleAttackingEvents(Engine& engine, SDL_Event& event)
         if (event.key.keysym.sym == SDLK_ESCAPE)
         {
             m_state = LevelState::MENUACTIVE_STATE;
+            m_attackableTiles.clear();
+            m_showAttackableTiles = false;
+            m_attackableUnitIds.clear();
         }
         if (event.key.keysym.sym == SDLK_RETURN)
         {
diff --git a/src/game/Level.hpp b/src/game/Level.hpp
index 6e2aeea..87d4407 100644
--- a/src/game/Level.hpp
+++ b/src/game/Level.hpp
@@ -164,6 +164,8 @@ class Level : public Scene
         void handleAttack(std::pair<int, int> tilePos);
         void handleMovement(std::pair<int, int> tilePos);
         void handlePositionMarker(Engine& engine, SDL_Event& event);
+
+        std::pair<int, int> unit_fallback_position;
 };
 
 } // namespace advanced_wars
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index f5d85a3..e94a38f 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -10,6 +10,9 @@ Unit::Unit(int x, int y, UnitFaction faction, UnitId id, UnitState state, Config
 {
     // Allgemeine Einheiteneinstellungen aus Konfiguration holen
     m_cost = config.getUnitCost(id);
+
+    std::cout<<"cost"<<m_cost<< std::endl;
+
     m_movementPoints = config.getUnitMovementPoints(id);
     m_ammo = config.getUnitAmmo(id);
     m_minRange = config.getUnitMinRange(id);
@@ -242,7 +245,7 @@ std::vector<Unit*> Unit::getUnitsInRangeWithDamagePotential(const std::vector<Un
     for (Unit* unit : allUnits)
     { // Iterate over all units
         // except itself
-        if (unit == this)
+        if (unit->getFaction() == this->m_faction)
         {
             continue;
         }
diff --git a/src/game/Unit.hpp b/src/game/Unit.hpp
index a2495e2..a1c5435 100644
--- a/src/game/Unit.hpp
+++ b/src/game/Unit.hpp
@@ -125,6 +125,8 @@ class Unit
 
         void setState(UnitState state);
 
+        inline UnitState getState() const { return m_state; }
+
         /**
          * Retrieves units within range that this unit can deal damage to.
          * Considers all units provided in 'allUnits', excluding itself, and checks movement and
-- 
GitLab