]> git.localhorst.tv Git - blobs.git/blobdiff - src/creature/need.cpp
split creature when it's "ripe" lol
[blobs.git] / src / creature / need.cpp
index b56950070e974d6f56e48be084ea419ec4567b22..1b832b7e17483df2ed44f2ab85891006cc54e834 100644 (file)
@@ -3,7 +3,9 @@
 #include "IngestNeed.hpp"
 
 #include "Creature.hpp"
+#include "LocateResourceGoal.hpp"
 #include "../world/Planet.hpp"
+#include "../world/TileType.hpp"
 
 
 namespace blobs {
@@ -13,14 +15,24 @@ Need::~Need() {
 }
 
 void Need::Tick(double dt) noexcept {
-       value = std::min(1.0, value + gain * dt);
+       Increase(gain * dt);
+}
+
+void Need::Increase(double delta) noexcept {
+       value = std::min(1.0, value + delta);
+}
+
+void Need::Decrease(double delta) noexcept {
+       value = std::max(0.0, value - delta);
 }
 
 
 IngestNeed::IngestNeed(int resource, double speed, double damage)
-: resource(resource)
+: locate_goal(nullptr)
+, resource(resource)
 , speed(speed)
-, damage(damage) {
+, damage(damage)
+, ingesting(false) {
 }
 
 IngestNeed::~IngestNeed() {
@@ -28,18 +40,56 @@ IngestNeed::~IngestNeed() {
 
 void IngestNeed::ApplyEffect(Creature &c, double dt) {
        if (!IsSatisfied()) {
-               // TODO: find resource and start ingest task
+               ingesting = true;
+       }
+       if (ingesting) {
+               if (c.GetSituation().OnSurface()) {
+                       const world::TileType &t = c.GetSituation().GetTileType();
+                       bool found = false;
+                       for (auto &yield : t.resources) {
+                               if (yield.resource == resource) {
+                                       found = true;
+                                       // TODO: check if not busy with something else
+                                       double amount = std::min(yield.ubiquity, speed) * dt;
+                                       c.Grow(amount * growth * dt);
+                                       Decrease(amount);
+                                       if (value == 0.0) {
+                                               ingesting = false;
+                                               if (locate_goal) {
+                                                       // abort
+                                                       locate_goal->Complete();
+                                               }
+                                       }
+                                       break;
+                               }
+                       }
+                       if (!found && !locate_goal) {
+                               locate_goal = new LocateResourceGoal(c, resource);
+                               locate_goal->OnComplete([&](Goal &g){ OnLocateComplete(g); });
+                               c.AddGoal(std::unique_ptr<Goal>(locate_goal));
+                       }
+               }
        }
        if (IsCritical()) {
                c.Hurt(damage * dt);
        }
+       if (locate_goal) {
+               locate_goal->Urgency(value);
+       }
+}
+
+void IngestNeed::OnLocateComplete(Goal &g) {
+       if (&g == locate_goal) {
+               locate_goal = nullptr;
+       }
 }
 
 
 InhaleNeed::InhaleNeed(int resource, double speed, double damage)
 : resource(resource)
 , speed(speed)
-, damage(damage) {
+, damage(damage)
+, inhaling(false) {
 }
 
 InhaleNeed::~InhaleNeed() {
@@ -47,9 +97,14 @@ InhaleNeed::~InhaleNeed() {
 
 void InhaleNeed::ApplyEffect(Creature &c, double dt) {
        if (!IsSatisfied()) {
-               // TODO: make condition more natural with thresholds and stuff
+               inhaling = true;
+       }
+       if (inhaling) {
                if (c.GetSituation().OnPlanet() && c.GetSituation().GetPlanet().Atmosphere() == resource) {
-                       value = std::max(0.0, value - (speed * dt));
+                       Decrease(speed * dt);
+                       if (value == 0.0) {
+                               inhaling = false;
+                       }
                } else {
                        // TODO: panic
                }