Nimbin[12]?SDL & Graphics / mapcreator / commits / 578cb99

mapcreator git · master

SDL3 2.5D game and engine using assets, with map editor

sdl3 c++ game engine map-editor cmake · first commit 2025-10-31 · last commit 2026-09-07 (1 month ago) · synced 3 days ago · upstream: git.ide3.de/hsnr/sdl-spieleentwicklung/map_creator

C++ 99.3%
git clone https://git.christianimmanuel.de/sdl-graphics/mapcreator.gitwget https://git.christianimmanuel.de/sdl-graphics/mapcreator/archive/mapcreator.tar.gz

Add planting seeds

Christian Immanuel · 2026-02-14 14:51 · 578cb9991c231545590742a9846ac9f04f01cba8

 src/character/character.cpp   |  43 +++++++++---
 src/character/character.hpp   |   1 +
 src/character/message.cpp     |   1 +
 src/character/message.hpp     |   1 +
 src/inventory/inventory.cpp   | 157 +++++++++++++++++++++++++++++++++++++++++-
 src/inventory/inventory.hpp   |  18 ++++-
 src/map/map.cpp               |   6 +-
 src/vegetables/vegetables.cpp |  18 ++---
 src/vegetables/vegetables.hpp |   4 +-
 9 files changed, 222 insertions(+), 27 deletions(-)

diff --git a/src/character/character.cpp b/src/character/character.cpp
index 2013441..2369794 100644
--- a/src/character/character.cpp
+++ b/src/character/character.cpp
@@ -63,7 +63,7 @@ Character::Init(SDL_Renderer* renderer) {
     attacking_logic   = { 0.0f, nullptr, AttackingLogicStatus_e::NONE, false, nullptr };
     consuming_logic   = { 0.0f, 3.0f, false, nullptr };
     cultivation_logic = { 0.0f, 3.0f, false, false, {0,0} };
-    planting_logic    = { 0.0f, 3.0f, false, {0,0}, VegetableData::Type::NONE };
+    planting_logic    = { 0.0f, 3.0f, false, {0,0}, VegetableData::Type::NONE, false};
     sprintstart_logic = {0, 0.8, false};
 
     death_duration = 0;
@@ -532,9 +532,14 @@ Character::collect_Object() {
         // Remove object from MapTileObject s
 
         Object* object = Object::get_ObjectById(collecting_logic.object->object_id);
-        if (object->object_type == ObjectType::VEGETABLE)
-            inventory->add_Vegetable(static_cast<Vegetable*>(object)->type, static_cast<Vegetable*>(object)->quantity, messages.get());
-        else
+        if (object->object_type == ObjectType::VEGETABLE) {
+            Vegetable* v = static_cast<Vegetable*>(object);
+            std::cout << "ISSEED " << v->is_seed << std::endl;
+            if (v->is_seed)
+                inventory->add_Seed(v->type, v->quantity, messages.get());
+            else
+                inventory->add_Vegetable(v->type, v->quantity, messages.get());
+        } else
             inventory->add_Resource(collecting_logic.resource.resource, static_cast<int>(collecting_logic.resource.quantity), messages.get());
         /*
         resources[collecting_logic.resource.resource] += collecting_logic.resource.quantity;
@@ -910,9 +915,11 @@ Character::plant_Start() {
 
     set_Status(CharacterStatus::PLANTING);
     handle_Animation();
+
     planting_logic.is_planting = true;
     planting_logic.tile_world  = tile_world;
     planting_logic.type        = static_cast<InventoryVegetable*>(selected_item)->type;
+    planting_logic.is_seed = !static_cast<InventoryVegetable*>(selected_item)->is_seed;
 }
 
 void
@@ -932,12 +939,14 @@ Character::plant_Vegetable() {
     }
 
     if (planting_logic.duration >= planting_logic.duration_max) {
-        std::cout << "DEF " << (int)planting_logic.type << std::endl;
-        Vegetable* v = new Vegetable(planting_logic.type, planting_logic.tile_world);
+        Vegetable* v = new Vegetable(planting_logic.type, planting_logic.tile_world, planting_logic.is_seed);
         TileObject to = {{0,0}, true, v->id};
         size_t id = Map::get_IdFromTilePoint(planting_logic.tile_world);
-        std::cout << "  " << id << std::endl;
         Map::tile_map[id].objects.push_back(to);
+        if (!planting_logic.is_seed) // YES thats reversed!
+            inventory->remove_Seed(planting_logic.type, 1);
+        else
+            inventory->remove_Vegetable(planting_logic.type, 1);
 
         plant_Stop();
     }
@@ -1413,8 +1422,16 @@ Character::handle_Input(Input& input, SDL_Rect win_size) {
                 if (inventory->selected_inventory.vegetable != VegetableData::Type::NONE) {
                     InventoryVegetable& iv = inventory->vegetables.at(inventory->selected_inventory.vegetable);
                     setted_hotbar = inventory->set_HotbarItem(Inventory::selected_hotbar, &iv);
+                    std::cout << "NOOO \n";
+                    //inventory->Equip(it);
+                } else
+                if (inventory->selected_inventory.seed != VegetableData::Type::NONE) {
+                    InventoryVegetable& iv = inventory->seeds.at(inventory->selected_inventory.seed);
+                    std::cout << "JEEE " << iv.is_seed << "\n";
+                    setted_hotbar = inventory->set_HotbarItem(Inventory::selected_hotbar, &iv);
                     //inventory->Equip(it);
                 } else {
+                    std::cout << "FUCK \n";
                     setted_hotbar = inventory->set_HotbarItem(Inventory::selected_hotbar, inventory->selected_inventory.item);
                     if (setted_hotbar) {
                         if (sel_item) inventory->Equip(sel_item);
@@ -1581,11 +1598,15 @@ Character::handle_Input(Input& input, SDL_Rect win_size) {
                     attack_Start();
                     return;
                 }
-            } else
-            if (selected_item->object_type == InventoryObjectType::VEGETABLE) {
+            } else {
                 if (!planting_logic.is_planting) {
-                    plant_Start();
-                    return;
+                    switch (selected_item->object_type) {
+                        case InventoryObjectType::VEGETABLE:
+                        case InventoryObjectType::SEED:
+                            plant_Start();
+                            return;
+                        default: break;
+                    }
                 }
             }
         } else
diff --git a/src/character/character.hpp b/src/character/character.hpp
index c845648..e471761 100644
--- a/src/character/character.hpp
+++ b/src/character/character.hpp
@@ -102,6 +102,7 @@ struct CharacterPlantingLogic {
     bool  is_planting;
     SDL_Point tile_world;
     VegetableData::Type type;
+    bool is_seed;
 };
 
 struct CharacterStats {
diff --git a/src/character/message.cpp b/src/character/message.cpp
index 888da34..2eabcf7 100644
--- a/src/character/message.cpp
+++ b/src/character/message.cpp
@@ -24,6 +24,7 @@ Messages::Messages() {
         {MessageKey::ADD_INVENTORY, {10, MessageType::INVENTORY, "Added item: "}},
         {MessageKey::ADD_RESOURCE,  {10, MessageType::RESOURCE,  "Resource "}},
         {MessageKey::ADD_VEGETABLE, {10, MessageType::VEGETABLE, "Vegetable "}},
+        {MessageKey::ADD_VEGETABLE_SEED,   {10, MessageType::VEGETABLE, "Seed "}},
         {MessageKey::NOTHING_TO_INTERACT,  {4, MessageType::CHARACTER, "I cant find anything to interact with.."}},
     };
 }
diff --git a/src/character/message.hpp b/src/character/message.hpp
index 6724ef8..bc3656d 100644
--- a/src/character/message.hpp
+++ b/src/character/message.hpp
@@ -36,6 +36,7 @@ enum class MessageKey {
     ADD_INVENTORY,
     ADD_RESOURCE,
     ADD_VEGETABLE,
+    ADD_VEGETABLE_SEED,
     NOTHING_TO_INTERACT,
 };
 
diff --git a/src/inventory/inventory.cpp b/src/inventory/inventory.cpp
index 26614da..f50b850 100644
--- a/src/inventory/inventory.cpp
+++ b/src/inventory/inventory.cpp
@@ -85,7 +85,7 @@ void Inventory::Unequip(EquipmentSlot slot) {
 // VEGETABLE
 void
 Inventory::add_Vegetable(VegetableData::Type type, size_t amount, Messages* messages) {
-    auto [it, inserted] = vegetables.try_emplace(type, InventoryVegetable(next_item_id, type));
+    auto [it, inserted] = vegetables.try_emplace(type, InventoryVegetable(next_item_id, type, false));
     if (inserted)
         next_item_id++;
 
@@ -103,6 +103,7 @@ Inventory::remove_Vegetable(VegetableData::Type type, size_t amount) {
     if (it == vegetables.end() || it->second.count < amount)
         return false;
 
+    std::cout << "TSCHÖÖ VEG\n";
     it->second.count -= amount;
     if (it->second.count == 0)
         vegetables.erase(it);
@@ -115,6 +116,39 @@ Inventory::get_Vegetable(VegetableData::Type type) const {
     return (it != vegetables.end()) ? it->second.count : 0;
 }
 
+// SEED
+void
+Inventory::add_Seed(VegetableData::Type type, size_t amount, Messages* messages) {
+    auto [it, inserted] = seeds.try_emplace(type, InventoryVegetable(next_item_id, type, true));
+    if (inserted)
+        next_item_id++;
+
+    it->second.count += amount;
+
+    auto* t = new VegetableData::Type(type);
+    std::cout << "ADD VEGETABLE TYPE: " << static_cast<int>(*t) << std::endl;
+    if (messages)
+        messages->Add(MessageKey::ADD_VEGETABLE_SEED, static_cast<void*>(t));
+}
+
+bool
+Inventory::remove_Seed(VegetableData::Type type, size_t amount) {
+    std::cout << "TSCHÖÖ\n";
+    auto it = seeds.find(type);
+    if (it == seeds.end() || it->second.count < amount)
+        return false;
+
+    it->second.count -= amount;
+    if (it->second.count == 0)
+        seeds.erase(it);
+    return true;
+}
+
+int
+Inventory::get_Seed(VegetableData::Type type) const {
+    auto it = seeds.find(type);
+    return (it != seeds.end()) ? it->second.count : 0;
+}
 
 // RESOURCE
 void
@@ -504,6 +538,15 @@ Inventory::draw_InfoPanel(SDL_Renderer* renderer,
             return;
         }
 
+        if (selected_item->seed != VegetableData::Type::NONE)
+        {
+            const auto& def =
+                VegetableData::crop_defs[static_cast<uint32_t>(selected_item->seed)];
+            std::string name = std::string(def.name) + " seed";
+            draw_line(name);
+            return;
+        }
+
         if (selected_item->item)
         {
             auto* inv_item =
@@ -600,6 +643,7 @@ Inventory::draw_InventoryGrid(SDL_Renderer* renderer) {
 
     int index = 0;
 
+    // RESOURCE
     for (auto& pair : resources) {
         if (pair.second <= 0) continue;
 
@@ -617,6 +661,7 @@ Inventory::draw_InventoryGrid(SDL_Renderer* renderer) {
         index++;
     }
 
+    // VEGETABLE
     for (auto& pair : vegetables) {
         if (pair.second.count <= 0) continue;
 
@@ -636,6 +681,27 @@ Inventory::draw_InventoryGrid(SDL_Renderer* renderer) {
         index++;
     }
 
+    // SEEDS
+    for (auto& pair : seeds) {
+        if (pair.second.count <= 0) continue;
+
+        //std::cout << "ITM: " << (int)pair.first << " " << pair.second << std::endl;
+        if (index >= inventory_grid_cols * inventory_grid_rows) break;
+
+
+        VegetableData::Type type = pair.first;
+        const VegetableData::CropDefinition* data = VegetableData::get_DataByType(type);
+
+        auto pos = get_tile_position(index);
+        bool highlight = (selected_inventory.is_valid &&
+                          selected_inventory.seed == pair.first);
+
+        //std::cout << "DAT: " <<data.icon_tile_x << " " <<  data.icon_tile_y << std::endl;
+        draw_icon(pos.first, pos.second, {data->icon_tile_x-1, data->icon_tile_y}, pair.second.count, highlight);
+        index++;
+    }
+
+    // ITEM -> TOOL/WEAPON
     for (auto& inv_item : items) {
         if (index >= inventory_grid_cols * inventory_grid_rows) break;
 
@@ -716,6 +782,30 @@ Inventory::hit_InventoryGrid(const SDL_FPoint& mouse) {
 
         index++;
     }
+    for (auto& pair : seeds) {
+        if (pair.second.count <= 0) continue;
+
+        if (index >= inventory_grid_cols * inventory_grid_rows) break;
+
+
+        VegetableData::Type type = pair.first;
+        const VegetableData::CropDefinition* data = VegetableData::get_DataByType(type);
+
+        SDL_FRect r = rect_for_slot(index);
+
+        if (mouse.x >= r.x && mouse.x <= r.x + r.w &&
+            mouse.y >= r.y && mouse.y <= r.y + r.h) {
+            sel.is_valid  = true;
+            sel.seed      = type;
+            sel.vegetable = VegetableData::Type::NONE;
+            sel.resource  = ResourceType::NONE;
+            sel.item      = nullptr;
+            sel.tile      = {data->icon_tile_x, data->icon_tile_y};
+            return sel;
+        }
+
+        index++;
+    }
 
 
     for (auto &inv_item : items) {
@@ -865,6 +955,14 @@ Inventory::draw_Hotbar(SDL_Renderer* renderer, TTF_Font* font) {
                 SDL_FRect src{ data->icon_tile_x * 16.f, data->icon_tile_y * 16.f, 16.f, 16.f };
                 SDL_FRect dst{ x, y, slot_size, slot_size };
                 SDL_RenderTexture(renderer, Icon::icons_texture, &src, &dst);
+            } else
+            if (hotbar[i].type == InventoryObjectType::SEED) {
+                InventoryVegetable& item = get_SeedById(hotbar[i].item_id);
+                const VegetableData::CropDefinition*
+                    data = get_DataByType(item.type);
+                SDL_FRect src{ (data->icon_tile_x-1) * 16.f, data->icon_tile_y * 16.f, 16.f, 16.f };
+                SDL_FRect dst{ x, y, slot_size, slot_size };
+                SDL_RenderTexture(renderer, Icon::icons_texture, &src, &dst);
             }
         }
 
@@ -904,6 +1002,9 @@ Inventory_s* Inventory::get_SelectedHotbarItem() {
     else
     if (eq.type == InventoryObjectType::VEGETABLE) 
         item = &get_VegetableById(hotbar[selected_hotbar].item_id);
+    else
+    if (eq.type == InventoryObjectType::SEED) 
+        item = &get_SeedById(hotbar[selected_hotbar].item_id);
 
     if (selected_hotbar == 0 || !item) {
         std::cout << "Something is broken,... " << selected_hotbar << " " << hotbar[selected_hotbar].item_id << std::endl;
@@ -926,6 +1027,13 @@ InventoryVegetable& Inventory::get_VegetableById(size_t id) {
     throw std::out_of_range("Vegetable not found");
 }
 
+InventoryVegetable& Inventory::get_SeedById(size_t id) {
+    for (auto &item : seeds)
+        if (item.second.id == id)
+            return item.second;
+    throw std::out_of_range("Vegetable not found");
+}
+
 
 
 
@@ -958,6 +1066,15 @@ static void WriteVegetable(std::ofstream &file, const InventoryVegetable &veg) {
 
 }
 
+static void WriteSeed(std::ofstream &file, const InventoryVegetable &veg) {
+    file.write(reinterpret_cast<const char*>(&veg.object_type), sizeof(veg.object_type));
+
+    file.write(reinterpret_cast<const char*>(&veg.id), sizeof(veg.id));
+    file.write(reinterpret_cast<const char*>(&veg.equipement_slot), sizeof(veg.equipement_slot));
+    file.write(reinterpret_cast<const char*>(&veg.type), sizeof(veg.type));
+    file.write(reinterpret_cast<const char*>(&veg.count), sizeof(veg.count));
+}
+
 bool Inventory::Save(const std::string &path) const {
     std::ofstream file(path + "/inventory", std::ios::binary | std::ios::trunc);
     std::cout << "Save Inventory\n";
@@ -993,6 +1110,14 @@ bool Inventory::Save(const std::string &path) const {
 
         for (const auto &pair : vegetables)
             WriteVegetable(file, pair.second);
+
+    // seed
+        count = seeds.size();
+        std::cout << "Seeds COUNT WRITE: " << count << std::endl;
+        file.write(reinterpret_cast<const char*>(&count), sizeof(count));
+
+        for (const auto &pair : seeds)
+            WriteSeed(file, pair.second);
     }
 
     // equipment slot item_id
@@ -1045,7 +1170,16 @@ static InventoryItem* ReadItem(std::ifstream &file) {
     return it;
 }
 static InventoryVegetable* ReadVegetable(std::ifstream &file) {
-    auto *veg = new InventoryVegetable(0, VegetableData::Type::NONE);
+    auto *veg = new InventoryVegetable(0, VegetableData::Type::NONE, false);
+    ReadBase(file, veg);
+
+    file.read(reinterpret_cast<char*>(&veg->type), sizeof(veg->type));
+    file.read(reinterpret_cast<char*>(&veg->count), sizeof(veg->count));
+
+    return veg;
+}
+static InventoryVegetable* ReadSeed(std::ifstream &file) {
+    auto *veg = new InventoryVegetable(0, VegetableData::Type::NONE, true);
     ReadBase(file, veg);
 
     file.read(reinterpret_cast<char*>(&veg->type), sizeof(veg->type));
@@ -1069,6 +1203,11 @@ static Inventory_s* ReadObject(std::ifstream &file)
              veg->object_type = ot;
              return veg;
          }
+        case InventoryObjectType::SEED: {
+             auto* veg = ReadSeed(file);
+             veg->object_type = ot;
+             return veg;
+         }
 
         default:
             return nullptr;
@@ -1136,6 +1275,20 @@ bool Inventory::Load(const std::string &path) {
             // we no longer need the allocated pointer after copying
             delete veg;
         }
+        count = 0;
+        file.read(reinterpret_cast<char*>(&count), sizeof(count));
+        for (uint32_t i = 0; i < count; ++i) {
+            Inventory_s *obj = ReadObject(file);
+            InventoryVegetable* veg = static_cast<InventoryVegetable*>(obj);
+
+            seeds.try_emplace(veg->type, *veg);
+            if (veg->id > next_item_id)
+                next_item_id = veg->id;
+
+            std::cout << "SEED SIZ " << seeds.size() << std::endl; 
+            // we no longer need the allocated pointer after copying
+            delete veg;
+        }
         next_item_id++;
     }
 
diff --git a/src/inventory/inventory.hpp b/src/inventory/inventory.hpp
index e4aefe7..e1d7cda 100644
--- a/src/inventory/inventory.hpp
+++ b/src/inventory/inventory.hpp
@@ -15,7 +15,8 @@
 enum class InventoryObjectType : uint8_t {
     NONE,
     ITEM,
-    VEGETABLE
+    VEGETABLE,
+    SEED
 };
 
 struct Inventory_s {
@@ -49,13 +50,15 @@ struct InventoryItem : Inventory_s {
 
 struct InventoryVegetable : Inventory_s {
     size_t count = 0;
+    bool   is_seed = false;
     VegetableData::Type type;
-    InventoryVegetable(size_t d, VegetableData::Type t)
-        : Inventory_s(d, InventoryObjectType::VEGETABLE), type(t)
+    InventoryVegetable(size_t d, VegetableData::Type t, bool s)
+        : Inventory_s(d, s ? InventoryObjectType::SEED : InventoryObjectType::VEGETABLE), is_seed(s), type(t)
     {
     }
 };
 
+
 static constexpr int HOTBAR_SLOTS = 7; // 0 == HANDS
 
 struct Equipement {
@@ -67,6 +70,7 @@ struct InventorySelection {
     Inventory_s* item = nullptr;
     ResourceType resource = ResourceType::NONE;
     VegetableData::Type vegetable = VegetableData::Type::NONE;
+    VegetableData::Type seed      = VegetableData::Type::NONE;
     Icon::TilePos tile;
     bool is_valid = false;
 };
@@ -92,6 +96,8 @@ public:
     std::unordered_map<ResourceType, int>        resources;
     std::unordered_map<VegetableData::Type, InventoryVegetable>
                                                  vegetables;
+    std::unordered_map<VegetableData::Type, InventoryVegetable>
+                                                 seeds;
 
     std::list<std::unique_ptr<InventoryItem>>    items;
 
@@ -106,6 +112,10 @@ public:
     bool remove_Vegetable(VegetableData::Type type, size_t amount);
     int  get_Vegetable(VegetableData::Type type) const;
 
+    void add_Seed(VegetableData::Type, size_t amount, Messages*);
+    bool remove_Seed(VegetableData::Type type, size_t amount);
+    int  get_Seed(VegetableData::Type type) const;
+
     void add_Resource(ResourceType type, int amount, Messages* messages);
     bool remove_Resource(ResourceType type, int amount);
     int  get_Resource(ResourceType type) const;
@@ -118,6 +128,8 @@ public:
          get_ItemById(size_t id);
     InventoryVegetable&
          get_VegetableById(size_t id);
+    InventoryVegetable&
+         get_SeedById(size_t id);
 
     // EQUIPEMENT
     void Unequip(EquipmentSlot);
diff --git a/src/map/map.cpp b/src/map/map.cpp
index e8039c1..c26ec35 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -372,6 +372,8 @@ namespace Map {
 
                     auto type = static_cast<int>(v->type);
                     file.write(reinterpret_cast<const char*>(&type), sizeof(type));
+                    file.write(reinterpret_cast<const char*>(&v->is_seed),
+                            sizeof(v->is_seed));
 
                     file.write(reinterpret_cast<const char*>(&v->quantity),
                             sizeof(v->quantity));
@@ -579,9 +581,11 @@ namespace Map {
 
                     case ObjectCategory::FARM_CROP: {
                         int type_i;
+                        bool is_seed;
                         file.read(reinterpret_cast<char*>(&type_i), sizeof(type_i));
+                        file.read(reinterpret_cast<char*>(&is_seed), sizeof(is_seed));
 
-                        Vegetable* v = new Vegetable(static_cast<VegetableData::Type>(type_i), wp);
+                        Vegetable* v = new Vegetable(static_cast<VegetableData::Type>(type_i), wp, is_seed);
 
                         file.read(reinterpret_cast<char*>(&v->quantity), sizeof(v->quantity));
                         file.read(reinterpret_cast<char*>(&v->growth_stage),
diff --git a/src/vegetables/vegetables.cpp b/src/vegetables/vegetables.cpp
index 3070e93..42e34cb 100644
--- a/src/vegetables/vegetables.cpp
+++ b/src/vegetables/vegetables.cpp
@@ -8,13 +8,13 @@ namespace VegetableData {
 
     const CropDefinition crop_defs[(int)Type::COUNT] = {
         //        STAGE: 0    1    2    3    4
-        { "",0,0,0,0,0,0,0,0,0,0,0 },
-        { "carrot",      2,1, 5,1, 6,1, 7,1, 23,0, (5-2+1)+1},
-        { "raddish",     2,3, 5,3, 6,3, 7,3, 23,1, (5-2+1)+1},
-        { "cabbage",     2,5, 5,5, 6,5, 7,5, 23,2, (5-2+1)+1},
-        { "salad",       2,7, 5,7, 6,7, 7,7, 23,3, (5-2+1)+1},
-        { "broccoli",    2,9, 5,9, 6,9, 7,9, 23,4, (5-2+1)+1},
-        { "onion",       2,11,5,11,6,11,7,11,23,5, (5-2+1)+1}
+        { "",0,0,0,0,0,0,0,0,0,0,0,false },
+        { "carrot",      2,1, 5,1, 6,1, 7,1, 23,0, (5-2+1)+1, false},
+        { "raddish",     2,3, 5,3, 6,3, 7,3, 23,1, (5-2+1)+1, false},
+        { "cabbage",     2,5, 5,5, 6,5, 7,5, 23,2, (5-2+1)+1, false},
+        { "salad",       2,7, 5,7, 6,7, 7,7, 23,3, (5-2+1)+1, false},
+        { "broccoli",    2,9, 5,9, 6,9, 7,9, 23,4, (5-2+1)+1, false},
+        { "onion",       2,11,5,11,6,11,7,11,23,5, (5-2+1)+1, false}
     };
 
     const CropDefinition* get_DataByType(Type type) {
@@ -27,7 +27,7 @@ namespace VegetableData {
     }
 }
 
-Vegetable::Vegetable( VegetableData::Type t, SDL_Point world_pos)
+Vegetable::Vegetable( VegetableData::Type t, SDL_Point world_pos, bool is_s)
     :
     Object(ObjectType::VEGETABLE,
            ObjectCategory::FARM_CROP,
@@ -37,7 +37,7 @@ Vegetable::Vegetable( VegetableData::Type t, SDL_Point world_pos)
            world_pos,
            {1,1},
            0),
-    type(t),
+    type(t), is_seed(is_s),
     growth_stage(0),
     next_update_sec(Default::get_TimeSinceStartInSec()),
     equipement_slot(EquipmentSlot::HAND_RIGHT)
diff --git a/src/vegetables/vegetables.hpp b/src/vegetables/vegetables.hpp
index f5c4b99..c83aa42 100644
--- a/src/vegetables/vegetables.hpp
+++ b/src/vegetables/vegetables.hpp
@@ -37,6 +37,7 @@ namespace VegetableData {
         int icon_tile_x;
         int icon_tile_y;
         size_t total_stages;   // auto-calculated = (grown-start)+1 + rotten
+        bool is_seed;
     };
 
 
@@ -55,6 +56,7 @@ public:
     VegetableData::Type type;
     const  VegetableData::CropDefinition* definition;
     size_t quantity = 2;
+    bool   is_seed = false;
     size_t growth_stage;       // 0 = planted, last = rotten
     double next_update_sec;    // seconds since game start
     float collecting_duration_max;
@@ -64,7 +66,7 @@ public:
 
     EquipmentSlot equipement_slot;
 
-    Vegetable(VegetableData::Type t, SDL_Point world_pos);
+    Vegetable(VegetableData::Type t, SDL_Point world_pos, bool is_s);
 
     SDL_Point get_SetPosition() override;