rossturner / king-under-the-mountain

A simulation-based strategy game written in Java using LibGDX
MIT License
100 stars 17 forks source link

Pathing failures when hauling to crafting station happen repeatedly #24

Open nanodeath opened 2 months ago

nanodeath commented 2 months ago

Edit: original title was "Blacksmith struggling to haul items to forge"

A blacksmith dwarf spent the entire day basically alternating between picking up, and immediately dropping, rusted iron ingots (whee) and ebony planks to a forge where a cauldron is trying to be produced.

Screencast from 2024-05-26 16-01-53.webm Screenshot from 2024-05-26 16-03-43

I've also attached the save file right after the above video was taken (I had to re-zip it because GitHub doesn't like .save files). Goldenbow.zip

Version is Alpha 8.1.20 (969f4eb).

nanodeath commented 2 months ago

Uh, in this case I suspect it's because there's a freakin' coke oven in the way that's blocking the pathing, which is my bad. But as a player, it's not obvious (well, not blindingly obvious, anyway) that this is the problem. Maybe when pathing fails there should be an alert? I noticed that when a settler died (due to a cave-in, RIP) there was an alert; maybe we should reuse that.

  1. Verify that it's a pathing failure,
  2. Investigate adding an alert.
nanodeath commented 2 months ago

Interestingly, it seems to be hitting this code path[1] when the pathing fails this way. pathCursor and path.getCount() are each 0.

image

1: https://github.com/rossturner/king-under-the-mountain/blob/969f4ebc4633137c653e92f59329b2e627de7941/core/src/main/java/technology/rocketjump/undermount/entities/ai/goap/actions/location/GoToLocationAction.java#L99

nanodeath commented 2 months ago

Uh, I was wrong, it's actually this line: https://github.com/rossturner/king-under-the-mountain/blob/969f4ebc4633137c653e92f59329b2e627de7941/core/src/main/java/technology/rocketjump/undermount/entities/ai/goap/actions/location/GoToLocationAction.java#L274

nanodeath commented 2 months ago

I was hoping something like this would work, but it causes a crash because...some Gdx thing isn't initialized. I think I need to do this somewhere else from another thread.

diff --git a/core/src/main/java/technology/rocketjump/undermount/entities/ai/goap/actions/location/GoToLocationAction.java b/core/src/main/java/technology/rocketjump/undermount/entities/ai/goap/actions/location/GoToLocationAction.java
index 26419edd..08d1015c 100644
--- a/core/src/main/java/technology/rocketjump/undermount/entities/ai/goap/actions/location/GoToLocationAction.java
+++ b/core/src/main/java/technology/rocketjump/undermount/entities/ai/goap/actions/location/GoToLocationAction.java
@@ -11,6 +11,7 @@ import com.badlogic.gdx.utils.Array;
 import org.pmw.tinylog.Logger;
 import technology.rocketjump.undermount.entities.ai.goap.AssignedGoal;
 import technology.rocketjump.undermount.entities.ai.goap.actions.Action;
+import technology.rocketjump.undermount.entities.behaviour.creature.SettlerBehaviour;
 import technology.rocketjump.undermount.entities.components.InventoryComponent;
 import technology.rocketjump.undermount.entities.components.humanoid.SteeringComponent;
 import technology.rocketjump.undermount.entities.model.Entity;
@@ -31,6 +32,8 @@ import technology.rocketjump.undermount.persistence.SavedGameDependentDictionari
 import technology.rocketjump.undermount.persistence.model.InvalidSaveException;
 import technology.rocketjump.undermount.persistence.model.SavedGameStateHolder;
 import technology.rocketjump.undermount.rooms.HaulingAllocation;
+import technology.rocketjump.undermount.settlement.notifications.Notification;
+import technology.rocketjump.undermount.settlement.notifications.NotificationType;

 import static technology.rocketjump.undermount.entities.ai.goap.actions.Action.CompletionType.FAILURE;
 import static technology.rocketjump.undermount.entities.ai.goap.actions.Action.CompletionType.SUCCESS;
@@ -272,6 +275,14 @@ public class GoToLocationAction extends Action implements PathfindingCallback {
        if (path == null || path.getCount() == 0) {
            // No path found / possible
            completionType = FAILURE;
+
+           if (parent.parentEntity.getBehaviourComponent() instanceof SettlerBehaviour) {
+               // This isn't safe to dispatch here.
+               Notification tantrumNotification = new Notification(NotificationType.SETTLER_PATHING_FAILURE,
+                       parent.parentEntity.getLocationComponent().getWorldOrParentPosition());
+                   tantrumNotification.addTextReplacement("character", i18nTranslator.getDescription(tantrumEntity));
+               parent.messageDispatcher.dispatchMessage(MessageType.POST_NOTIFICATION, tantrumNotification);
+           }
        }
    }
nanodeath commented 2 months ago

Okay if I set a 0.1F second delay, it works fine. I didn't realize this triggered a large modal dialog though, which isn't really what I want. @rossturner any ideas on what we should do here? Because of the way the forge is shaped, the little use site circle is actually free, it's just unreachable.