CleverRaven / Cataclysm-DDA

Cataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.
http://cataclysmdda.org
Other
10.61k stars 4.17k forks source link

Introduce a construction site indication for base camp/expansion construction in progress #71016

Closed PatrikLundell closed 9 months ago

PatrikLundell commented 9 months ago

Is your feature request related to a problem? Please describe.

The current base camp construction process does not tell the player where the construction is actually taking place, so the player has little indication of where not to place stuff in the mean time, resulting in the risk of walls obliterating valuable items.

Solution you would like.

When the construction work is started, the construction area should be indicated in some fashion. When the construction is finished the indication should be removed. It's probably acceptable if indications for aborted constructions remain (aborted jobs just removes the job, so it's hard to add any cleanup to it, and the construction will probably be restarted some time in the future).

Describe alternatives you have considered.

We've been fumbling in the dark thus far, and can most probably continue to do so without any severe lasting harm.

Additional context

The approach I've thought of (which doesn't mean it's the only one, or the best one) is to use a process along these lines:

One issue is that I'd want the removal step to remove only the indicator, and not anything else of the same type on the tile. Thus, if fields were to be used, there would be a need to have an order that erases only a specific field (if present) on the tile, not all fields.

Rokharn commented 9 months ago

Field, sounds well... But how about 'zone' from zone manager? Probably have no conflict with anything at all including walls (and easier to remove). Surely not a perfect way, but easiest (I think).

PatrikLundell commented 9 months ago

There are a couple of problems with zones:

However, that doesn't mean using zones would be a poor way of implementing it (especially if the suggestion to add display of zones is implemented).

IdleSol commented 9 months ago

Mark the tiles with crosses. Something like a practice target, only it's a cross. Its placement does not seem to depend on furniture or buildings.

The zone logic currently only supports rectangles. Constructions placing furniture and the like often place these at non adjacent locations. This could be worked around by making it multiple zones (or change zones to not be restricted to rectangles)

As I understand it, it's about a new zone: "a camp construction zone" that covers the entire construction area. Not the many separate zones for each furniture or building area. It doesn't matter that the construction will be in a separate tile. This is a kind of warning, construction work is going on here.

I've rarely built camps, but from memory they are built in rectangular zones, right?

PatrikLundell commented 9 months ago

Construction consists of one or more construction parts:

Note that you can have more than one of these, so you can e.g. have two partially overlapping squares (of different sizes) of placements, where the overlapping parts either contain "do nothing" in both of them, or only one of them. Most of the time (possibly no existing case) they don't have overlaps, but it's very common for the actual construction to be rectangular with unequal length sides, so one dimension has to be padded with "do nothing" tiles. Furniture placement is often done with single tile commands spread out over the building to be furnished.

Covering more tiles than actually affected by a construction with indications is sloppy, but better than nothing. However, if the effort to provide it is put in, it's likely you'd want to do it neatly.

IdleSol commented 9 months ago

I will immediately apologize for the quality of the text, I use deepl translate. And the second point is that I know practically nothing about programming.

To create a faction camp use files from: /data/json/mapgen/basecamps/expansion

Using the central part of the base camp as an example:

And the map generation happens at the time the builder is revoked?

When selecting a builder to work on the task, you can run the same map generation procedure, but with the "palettes" and "set" sections replaced Example 1.

 {
    "type": "mapgen",
    "update_mapgen_id": "fbmk_canteen_stove",
    "method": "json",
    "object": {
      "set": [
        { "point": "furniture", "id": "f_woodstove", "x": 11, "y": 8 },
        { "point": "furniture", "id": "f_woodstove", "x": 13, "y": 8 },
        { "point": "furniture", "id": "f_counter", "x": 10, "y": 8 }
      ],
      "place_loot": [ { "item": "pot", "x": 10, "y": 8 }, { "item": "pan", "x": 10, "y": 8 } ]
    }
  },

Turns into:

      "set": [
        { "point": "furniture", "id": "FAKE_ITEM", "x": 11, "y": 8 },
        { "point": "furniture", "id": "FAKE_ITEM", "x": 13, "y": 8 },
        { "point": "furniture", "id": "FAKE_ITEM", "x": 10, "y": 8 }
      ],

Where FAKE_ITEM is some item/furniture/structure intended to indicate a construction site. Example 2.

 {
    "type": "mapgen",
    "method": "json",
    "nested_mapgen_id": "fbmk_canteen_smoking_area_construction",
    "object": {
      "parameters": {
        "fbmk_construction_palette": {
          "type": "palette_id",
          "scope": "omt",
          "default": {
            "distribution": [
              "fbmk_concrete_palette",
              "fbmk_log_palette",
              "fbmk_metal_palette",
              "fbmk_migo_resin_palette",
              "fbmk_rammed_earth_palette",
              "fbmk_rock_palette",
              "fbmk_wad_palette",
              "fbmk_wood_palette"
            ]
          }
        }
      },
      "mapgensize": [ 7, 7 ],
      "rows": [
        ",w,w   ",
        ",,,,   ",
        ",,,,   ",
        ",,aw   ",
        ",,,,   ",
        ",,,,   ",
        "ww,w   "
      ],
      "flags": [ "ALLOW_TERRAIN_UNDER_OTHER_DATA" ],
      "palettes": [ { "param": "fbmk_construction_palette" }, "fbmk_common_palette" ]
    }
  },
{
    "type": "palette",
    "id": "fbmk_common_palette",
    "terrain": { ",": "t_dirtfloor", "a": "t_dirtfloor", "p": "t_dirt", "B": "t_grass", "U": "t_rootcellar" },
    "furniture": {
      ",": "f_clear",
      "a": "f_stool",
      "b": "f_bench",
      "c": "f_counter",
      "h": "f_chair",
      "p": "f_planter",
      "r": "f_rack_wood",
      "t": "f_table",
      "B": "f_birdbath",
      "V": "f_fvat_empty"
    }
  },

Turns into:

 "palettes": [ { "param": "fbmk_construction_palette" }, "fbmk_common_palette_FAKE" ]
{
    "type": "palette",
    "id": "fbmk_common_palette_FAKE",
    "terrain": { ",": "t_dirtfloor", "a": "t_dirtfloor", "p": "t_dirt", "B": "t_grass", "U": "t_rootcellar" },
    "furniture": {
      ",": "FAKE_ITEM",
      "a": "FAKE_ITEM",
      "b": "FAKE_ITEM",
      "c": "FAKE_ITEM",
      "h": "FAKE_ITEM",
      "p": "FAKE_ITEM",
      "r": "FAKE_ITEM",
      "t": "FAKE_ITEM",
      "B": "FAKE_ITEM",
      "V": "FAKE_ITEM"
    }
  },

If necessary, similarly with the "terrain" section.

Alternative. Add new versions of structures, furniture and items with the prefix fake: f_woodstove -> fake_f_woodstove

id: "fake_f_woodstove"
"copy-from": "f_woodstove"

And replace and/or add new flags:

Maybe you can get away with duplicating items if there is a way to keep changing flags .

PatrikLundell commented 9 months ago

@IdleSol: There's a need for a clarification, possibly caused by translation: The actual construction happens when the companion is returned from the job (and I suspect "revoked" is caused by the translation, as that words would apply more to an emergency recall, which I don't think is what you mean).

Your suggested approach of just create modified copies of each construction step order and apply those rather than trying to aggregate them is an interesting one that might be easier to implement. At the very least, it's worth investigating.

In your second example, you'd also have to replace the terrain entries with t_null, but that's just a detail.

Using items as indicators would mostly work, but has a number of issues:

While it might be possible to create indicator furniture, it's a lot of work for a limited benefit, as somebody would have to create all those furniture entries, and there's no easy way to get code to replace the real furniture with the corresponding indicator one (you can transform the string representing the furniture into another string using a pattern, but then there is no guarantee there is a JSON entry matching that string). You also have an issue where a piece of furniture is to be replaced by another. In all, I think it's way too much work (and maintenance) to be worth it. (As an aside, "fake" is used to name furniture and items made available for basecamp crafting, such as a fake charcoal kiln to provide recipes with the benefits the real charcoal kiln at the site provides. Thus, a different token would be needed. Also, the "f" prefix should be retained for all furniture, so if the method would be used, it would be better with either an infix (between "f" and the rest), or a suffix. These things are just details, however).

Edit: Didn't see this earlier, but the .../expansion directory is for the expansions that can surround the base camp, not the base camp itself. That doesn't change the logic, as the same logic is applied to the basecamp itself (which is located under .../base).

Rokharn commented 9 months ago

Well, even adding mapgen 'rows' at the description will help a lot. It's by itself a some kind of illustration.

IdleSol commented 9 months ago

@PatrikLundell

There's a need for a clarification, possibly caused by translation:

You're absolutely right.

Using items as indicators would mostly work, but has a number of issues:

I agree, the use of the word " item", was not correct. It's more like an example: fake_item, fake_furniture ... or any other variant.

While it might be possible to create indicator furniture, it's a lot of work for a limited benefit, as somebody would have to create all those furniture entries, and there's no easy way to get code to replace the real furniture with the corresponding indicator one (you can transform the string representing the furniture into another string using a pattern, but then there is no guarantee there is a JSON entry matching that string). You also have an issue where a piece of furniture is to be replaced by another. In all, I think it's way too much work (and maintenance) to be worth it.

I thought it was easy enough to automate. Then, it turns out the only option is to change any furniture or construction to a construction marking the building area.

IdleSol commented 9 months ago

You must be very good at this.

How viable is the idea of building a camp without using ready-made templates?

Something like the game tells you what needs to be built. And it is up to the player to decide where and in what form to build. After that the game checks if there are necessary constructions and opens access to recipes.

That is, in the first approximation, the game should be able to determine what buildings are present on this global map tile. And if they correspond to the necessary ones, it opens access to recipes for kitchen, garage, saltworks and so on.

PatrikLundell commented 9 months ago

Part of the problem is to find something that's visible but doesn't clash with other somethings of the same type while also not affecting anything else, such as passing or seeing through.

The second post:

There is the bare bones base camp which doesn't have any constructions at all. All construction that's desired has to be built by the player using either the construction menu ('*'), or using construction zones and orders to the PC/companions to perform zone construction.

The problem with a "build this and you'll the (maybe) gets rewarded with access to new recipes" approach is to devise the logic that detects if you've constructed what's required. While it's easy to determine whether you've constructed a cooking place, there's no easy logic to determine whether you've build ta kitchen around it, and it gets even more complicated to determine whether you've fulfilled the requirements for a forge building when you build a forge within the same building as you've got your stove in.

It's possible to do this using an honor system, i.e. a "I've built a kitchen. Now give me access to cooking recipes" that just checks that there's a (approved) cooking facility somewhere within the base camp (or expansion) tile.

It's currently not possible to build an expansion without starting an expansion (i.e. build on surrounding tiles without going through the Survey that marks the tile for a purpose). It would be easy to make a free form expansion, but then you'd be back to the problem with determining if things are constructed "properly".

It can also be noted that a major problem with base camp/expansion recipes is that they're just a long unsorted list of recipes, so making more recipes available just adds to the bloat: the UI needs a total overhaul that would probably cause it to work like PC/companion crafting. However, nobody who's able to do it has been willing to tackle it for many years.

Personally I don't like the game progression logic of "you build this and you get access to these recipes". I'd rather have base camps work the same way as PC/companion crafting does, i.e. you construct the "furniture" required to craft things, and you get access to that functionality when crafting, while the recipe selection available would be dependent on knowledge and book access. In this vision the difference between PC/companion and camp crafting is that the former would be restricted to resources within 6 tiles of the crafter, while the latter would have access to all facilities available to the camp, as well as the other difference in that PC/companion crafting is done at the site, subject to various interruptions, while camp crafting has the companion disappear until recalled (after the time has been spent) with no micro management hassle (restart the crafting job each morning, etc.). Ideally, camp companion crafting should be subject to all the conditions of PC/companion crafting, such as failures, etc. which isn't the case currently.

However, all this is a side track to the subject of this suggestion.

IdleSol commented 9 months ago

Thanks for the reply.

Other alternatives? How is graffiti implemented? Something else?

Is it possible to replace furniture generation with zone generation? Ideally zones for building that furniture. Something like that:

- { "point": "furniture", "id": "f_woodstove", "x": 11, "y": 8 },
+ { "point": "LOOT_ZONE", "id": "LOOT_UNSORTED", "x": 11, "y": 8 },

This is just an example, I have no idea what should be there. And since I haven't found where the "construction: blueprint" zone is described. I took the first one I could find.

Ideally, we replace "furniture", "id": "f_woodstove" with id: "construction: blueprint" [parameter: "f_woodstove"] Ignore the errors, it's to clarify the idea.

And then opening the zone editor, you can determine what and where to build.

Further development, the ability to enable display from the camp construction menu: ~ "Show me the construction plan". And excluding access from the zone menu.

Rokharn commented 9 months ago

the difference between PC/companion and camp crafting is that the former would be restricted to resources within 6 tiles of the crafter

If one day this actually happen, not many players actually will want to build faction camp. This is really much the work, building resources and time. Reward by way of just to use resources, which just farther away, is not enough at practical way.

Camp surely needs to provide something exclusive. Ability to chop trees? The AI already can do it without the camp. Collect food? It's mostly ineffective at all even at a high skill level of npc. Right now, recipes like armor and so on is a main reason to start this thing. And still very optional. Food cost so high, so much easier to do it by yourself or ask npc directly, if recipe unlocked. Oh, and months of preparation building to unlock the ability for faction craft not help at all here. Well reality bubble have some limitation, so if player somewhere far-far away, than faction camp can be little more useful, but normally player just lives at same place, where 'collected' npc as well.

PatrikLundell commented 9 months ago

There are numerous issues with construction zones:

On the camp transformation tangent: I don't think camps should provide any unique functionality. However, I think they could serve a purpose for automating chores, such as husbandry (milking, feeding, producing animal feed, processing milk, collecting and processing eggs, etc.) and other tasks. I consider the current situation where companions don't need food unless they work on a camp to be a deficiency brought by because of the current inability to have a way for companions to feed themselves. Once that's fixed there will probably be a food parity. However, there should also be a way to make use of companions in an efficient manner at that time without excessive micro management.

IdleSol commented 9 months ago

They'd actually work as construction zones

Is that a bad thing? New camp building mechanics. NPCs do not disappear, the player controls the order of construction. All you have to do is check the completion of each construction.

Rokharn commented 9 months ago

New camp building mechanics.

New mechanics are never the easiest thing. For example, how you think to implement add resources to construct, for example, walls, when it more than possible become out of range? New pathfinding as well. And so on. Sure, it can be possible one day in the future, but for now PatrikLundell waiting for an easier way, which this person can achieve (I think so).

PatrikLundell asks solutions and fresh view (before), got some, created this topic and get mostly same things (fields, symbol art, and zones here as fresh one). And any of this ways needs work of tileset artists and implementation new things as well. As I said before - symbol arts is easiest way, even just copy-pasta of 'map preview' from 'rows' lines of mapgen files much better, than nothing. Sure, current 'grass' solution helps with new buildings, but not always (map itself can just have not any, for example). And all this has already been discussed earlier, so there is not many points in repeating.

For zones (zone manager) needs new features like visualization of the zones (and tile support as well). And/or huge rework. For field (things like fog, blood etc) needs brand new field. And so on.

PatrikLundell commented 9 months ago

Changing camp construction to use a hybrid construction zone approach has a number of issues, some of which are non trivial:

Unless @IdleSol implements it, including fixing all of the issues (including the ones not thought of), my prediction is that the core developers would reject the change. I'm not one of them, so it's a prediction, not a verdict.

IdleSol commented 9 months ago

/data/json/mapgen/basecamps/base/modular_hub/version_1/modular_field_palettes.json

...
  {
    "type": "palette",
    "id": "fbmh_tent_palette",
    "terrain": { ";": "t_dirt", ".": "t_dirtfloor", "+": "t_dirtfloor", "w": "t_dirtfloor" },
-   "furniture": { "+": "f_canvas_door", "v": "f_canvas_wall", "w": "f_canvas_wall" }
+   "furniture": { "+": "f_test_cross_777", "v": "f_test_cross_777", "w": "f_test_cross_777" }
  },
....

/data/json/furniture_and_terrain/furniture-fakes.json

...
 {
    "type": "furniture",
    "//": "This furniture object also gets used as a fake workbench whenever a player crafts on the ground anywhere else.",
    "id": "f_ground_crafting_spot",
    "name": "ground crafting spot",
    "looks_like": "tr_firewood_source",
    "description": "A cleared spot on the ground for crafting.  Slower than using a workbench or holding a project in your hands, but readily available.",
    "symbol": "x",
    "color": "white",
    "move_cost_mod": 0,
    "required_str": 0,
    "deconstruct": { "items": [  ] },
    "bash": { "str_min": 0, "str_max": 0, "items": [  ] },
    "flags": [ "PLACE_ITEM", "TRANSPARENT", "EASY_DECONSTRUCT", "NOCOLLIDE" ],
    "examine_action": "workbench",
    "workbench": { "multiplier": 0.7, "mass": 10000000, "volume": "1000L" }
  },
+    {
+    "type": "furniture",
+    "id": "f_test_cross_777",
+    "name": "Area 51",
+    "description": "none",
+    "symbol": "x",
+    "color": "red",
+    "move_cost_mod": 0,
+    "required_str": 0,
+    "flags": [ "PLACE_ITEM", "TRANSPARENT", "NOCOLLIDE" ]
+  },
  {
    "type": "furniture",
    "id": "f_no_item",
...

NPC / modular field camp version 1 / upgrade camp northeast tent

test 1 Before test 2 After test 3

Destroys furniture and construction, doesn't touch item. I don't know how to make it run when a worker is sent. The f_test_cross_777 is based on f_ground_crafting_spot. There may be unrecorded features. If you return deconstruct and "EASY_DECONSTRUCT", you can deconstruct by character.

Implementation would require creating a duplicate file or function to hot-swap.

furniture-fakes.json modular_field_palettes.json

Unless @IdleSol implements it

My skills are at the "if then else" level.

Rokharn commented 9 months ago

Destroys furniture and construction

So 'field' method from the topic header still better than yours because does not destroy current furniture and construction. At least until you resolve this problem. Anyway, you are free to start 'pull request' and see, what's happen. It may resolve issue at unexpected way as well (like one of more skilled person maybe will help, for example).

Interesting moment, currently if furniture appears in place of another piece of furniture via camp task, both can be present at the same place at the same time (for example cabinet and water pump).

PatrikLundell commented 9 months ago

You cannot have two pieces of furniture at the same tile, as the data format has room for exactly one piece of furniture and exactly one piece of terrain. I think a water pump is terrain.