Placing graphically appealing objects on adventure map

In 0.96, decorative objects in RMG are selected totally randomly. But it looks ugly.

In OH3, there’s defined matrix of ALL possible object pairs and the chance go choose one depends on that value. However, this approach will fail for new objects that are added in the future.
Another issue is that we don’t know algorithm to place obstacles based on these values.

The problem to solve is as follows:

  • Allow picking random obstacles
  • make sure close obstacles are similiar to each other
  • Allow to add new obstacles, including obstacle sets
  • Handle specia cases, for example water/lava rivers linked to waterwheels and lava pools

Possible solutions:

1. Define set of parametrs that describe the appearance of each object. Choose random objects based on their common parameters.

Advantages:

  • Ability to fit each object perfectly
  • Ability to meet special conditions, eg. place water objects only near rivers or vice versa

Disadvantages:

  • It’s difficult to make arbitrary list of such parameters
  • A lot of work to dfine parameters for all objects
  • Exact selection algorithm is still uknown
  • Possibly significant complexity of such algorithm

2. Define object groups with common appearance. Choose random objects that belong to one (or a few) groups.

In this idea, groups are divided into three categories: large (eg. mountains), medium (eg. trees) and small (details). The number of groups and their size is arbitrary, one object may appear in multiple groups.
The algorithm first tries to place object from “large” group, if it doesn’t fit then takes medium group, then small group. Small group must include 1-tile objects to make sure they always fit.

Advantages:

  • Small overhead
  • Simplicity
  • Possibility to have various styles for different zones on same terrain
  • Ease of adding new groups of objects
  • Less work needed to desribe groups that objects

Disadvantages:

  • No way to match special conditions, such as placing waterwheel near river or vice versa

I’m in favour of the second solution, which I came up wit recently.

Still, it will take a lot of work to put all these objects in config files. Some help is needed.

Why not add “tags”?


{
	"myCoolObjectTemplate" : 
	{

		// TODO, default - empty
		// tags from object type are always present (???)
		// List of tags that can be used to locate object in map editor
		"tags":"dirt", "sand", "mine"],
	}
}

Like “tags”: “treeGroup1”, “tree”] ?
but it’s better to add “groupTags”.

For example we will have 4 trees:

1: “groupTags”: “swampTreeGroup1”,“swampTreeGroup2”,“swampTreeGroup3”]
2: “groupTags”: “swampTreeGroup1”,“swampTreeGroup2”]
3: “groupTags”: “swampTreeGroup1”,“swampTreeGroup2”,“swampTreeGroup3”,“swampTreeGroup4”,“swampTreeGroup5”]
4: “groupTags”: “swampTreeGroup0”,“swampTreeGroup1”,“swampTreeGroup2”,“swampTreeGroup3”,“swampTreeGroup4”,“swampTreeGroup5”]

When RMG places on map new tree 2, then it will place tree 1, because list of tags more closely to tree 2 (there 2 identical tags, not 1 or 0).

I like solution 2. But I`d like to add “density parameters” to obstacles as well. F.e. zone may have hundreds of mountains but should not have hundreds of volcanoes.

ADD.

Tag similarity by Macron is also good idea but I`m afraid algorithm will be quite complex.

IMO rivers would need special handling in any case. So perhaps we should exclude them from this system and generate them after placing obstacles - draw line from lake to water, break it a few times call it a river.

Your 2nd approach sounds similar to H3 (see Rand_trn.txt). It defines relations between groups of objects - how likely one will appear near other one, chance for overlapping, etc.
BTW - moving volcanoes into separate group with low chance to appear next to “volcano” and high - near “mountains” will allow to implement AVS idea.

These groups should not be size-based but be based on appearance - mountains, lakes, forests and such. With small number of groups (5-10) defining full table of relations would be quite easy. They can be implemented as tags or as a separate field.

Internally placing large-first is a good idea but I don’t think that this should be defined in configs or something like that.

Problem is river-related objects like Water Mill - when and where to put them? Before rivers and then connect them with rivers (river may look weird after that) or after rivers in random river tile (this may break zone tiles connectivity).

  1. During obstacle placement determine which obstacles can be “river sources”
  2. Define region in which we can place river (~5 tiles-wide area from river source to sea)
  3. During object placement place water mills only in this region.
  4. Generate river from source to mill and then from mill to estuary. If river is long - add river delta object as well.

If treasure objects should be placed before obstacles - then during obstacle placement RMG must place some “river sources” near river region.

Already implemented large obstacles first.

Now, the issue in configurable obstacles is that:

  • We want to have user-defined obstacle sets.
  • We need to have always large obstacles (as they look good) and 1-tile obstacles to always fill in gaps.

My current proposal is to have custom-defined obstacle sets that must meet both conditions.

Most of WoG obstacles are so ugly and out of place they never not spawn even if they match terrain (walls :confused: ).

  1. Why not use something like this:

Each object will be assigned to a group/tag. Relations between different groups will be defined separately in a mod-friendly form so mods can both add objects to existing groups as well as define new groups.

So object types will get property named “tags” or “rmgGroup” and these groups will be defined in file similar to H3 Rand_trn.txt like this:

{
    "forest" : {
        "mountain" : { "near" : 100, "overlap" : 0 } // mountains can be near forests but should not overlap
        "forest" : { "near" : 100, "overlap" : 100 } // forests can be placed near each other, including overlaps
    }
}
  1. Perhaps it is better to keep size split internal? E.g. consider obstacles that block 10+ tiles as large (or any other number) and do split in runtime? That’s assuming that simple large-first selection is not enough here.

And on wog objects - I think this can be fixed by changing txt from which vcmi reads obstacles - WoG defines 3 files z*bjects.txt for editor, RMG and game. I can run a comparison to see which one in more suitable for us. (check wogfileoverrides.json from wog mod)

This change shouldn’t break anything - H3M already contains all this information so loading map with WoG walls will work even if walls are not defined in objects.txt

Yes, of course. The problem is if an user defines custom obstacle set(s) and we choose random sets out of available, it may not contain aby large obstacles at all. What then?

Will take a look at WoG obstacle configs.

EDIT: It looks like ZEOBJTS.txt is the correct one. All obstacles are fine, plus we get animated trees :wink:

Don’t do anything and just place what we have - small obstacles? To decrease likelihood of such situation vcmi should not pick obstacle set but instead generate weighted list of allowed obstacles from multiple sets. In this case we (almost) always will have something to choose from due to big enough amount of H3 obstacles.

One situation that may actually result in no large obstacles to choose from is new terrain that would need entirely new set of obstacles from modders. But in this case it is obviously modders’ responsibility to provide “graphically appealing” set(s) of obstacles, both big and small. All we can do here is provide tips on how to make “nice” obstacle set.

BTW - one more thing that adds a lot to graphical appealing is that H3 RMG also overlaps some objects like mountains or forests. Current screenshots ave too much emptyness between obstacles due to lack of that.

I guess the current solution is good enough to place map obstacles - no weighthing and other complex tricks needed.
What I wnat to do is to divide them into subsets so not all of them would be used in every zone. This could also easily allow adding new subsets to the mix.

My proposal is as follows:

  • Large obstacles, eg. mountains
  • Medium obstacles, eg. trees, lakes, chasms
  • Small obstacles - flowers, animals and bones, one-tile objects

It’s only about visuals and has nothing to do with actual implementation. Objects are already sorted and placed by size.

Now I wonder how to actually do this - somehow def names (accessible for modders / config authors) must be mapped to object ID / subID.

But they are already mapped - see last fields in objects.txt (type & subtype). During import vcmi will load them into appropriate objects/subobjects.

Another question is how to handle new obstacles - currently there is no way to add new templates into existing objects. Simplest approach would be let modders create new objects. In this case there will be separate “mountains” object in H3 and separate “mountains” object accessible for modders but as long as we don’t hardcode their id’s this shouldn’t be a problem.

Here’s an example of what I mean:


But why you can’t turn this into a property of object type? (the one that has ID/sub ID and list of templates). All decorations (mountains, forests, lakes, etc) are already split into types in H3 - see last 2 colums in objects.txt. You just need to assign them to some sort of subsets. Add this field to every decoration in our object json’s and read it into object types during loading. Or am I missing something?

Grouping objects by ID and subID may give good results, or may not. I want to give modders ability to define their own obstacle sets based on their talent or taste.

Another possible feature is to allow certain sets to spawn only in native town area- for example Cove debris or Forge wastelands (seen both). For that reason there must be a group with editable property.

How about adding “faction” field to map objects/templates?
Then if “faction” : “cove”, than this object will spawn in zones with Cove towns (or on Cove terrains).
If faction is “neutral”, it will be placed everywhere.

Why this won’t work with existing ID/subID?

Modders that want to add some generic mountains will define new object that will have { “mountain”, “big” } tags/groups and will put all his obstacles in this new object (or they can reuse any existing object and avoid redefining tags)

Modders that want to add some unique obstacles will create new object as well but instead will add some unique tags, e.g. { “forceField”, “small”}

(don’t know if multiple tags are necessary - one group may work just as well )

This can be implemented as a separate property alongside tags, e.g.
“filter” : “faction”, “castle” ] // using my json expressions similar to buildings/victory conditions

Yes, this will apply to entire object and not just specific template. So what? VCMI should be OK with adding hundreds of object types - IMO templates/appearances should be only used for objects with same properties. We already have ID/subID for different behavior in game ( or RMG ).

When it comes to terrain objects, we don’t want just to drop hundeds of totally different objects. The point is to pick a subset of objects that match each other visually and put them together.

It doesn’t have anything to do with mechanics, only visual outcome.

I’d like to add def name -> ID/subID map, then list object groups by def name. Then will need someone to fill the list :unamused:

This could be handy for editor, but doesn’t avoid the problem of having too many distinct objects in one zone.