swfans / swars

Syndicate Wars port, alternative binary for the classic Bullfrog game
Other
101 stars 14 forks source link

enhancement: Ability to load DAT maps #131

Open mefistotelis opened 10 months ago

mefistotelis commented 10 months ago

Making a map editor which reads MAD files would be a pain - this file format is optimized to be used as "baked" map, having some arrays which cannot be easily resized and including structures which should be auto-generated by the game engine.

We should prepare the ability to load DAT maps - in the format similar to pre-alpha game, also included in few files from the Korean release.

The DAT maps will be automatically converted to MAD before playing.

What is needed:

  1. Write DAT load function (state: initial code made, likely does not load the DATs correctly)
  2. Write pathfinding triangulation re-creation (state: started, looks doable)
  3. Write car traffic re-creation (state: I have no idea how this works; may require considerable work)
  4. Write MAD save function (state: not started, but should be easy)
mefistotelis commented 9 months ago

ad. 2. This is too complex to write in C and just work. My remade code must have already too many errors for reasonable debug.

Instead, I will try to add the missing pathfinding reinitialization, or at least some of it, in original ASM form. To do that, I started working on the le_disasm tool again.

mefistotelis commented 9 months ago

ad 2.

This is harder than I anticipated. While low level functions for adding areas and walls to pathfinding are there, the glue code which parses map data and calls these low level function is missing.

This is similarly missing in all beta versions.

Alternative function exists in pre-alpha binary, but the creation is vastly different there.

mefistotelis commented 9 months ago

The generate_walk_items() function now re-creates connections between walkable faces like the original. Remaining calls to verify and fix:

    update_mapel_collision_columns();
    generate_collision_vects();
    generate_thin_walls();
mefistotelis commented 9 months ago

The update_mapel_collision_columns(void) now generates columns which seem acceptable to me. They are different than what original algorithm generated, but I suspect they're just more accurate. Re-creating the originals exactly would be very difficult.

Still, since columns are generated in a different way, the further steps which use these columns now incorrectly refer to their instances, making the old pathfinding data unusable.

mefistotelis commented 9 months ago

Finally, generated the triangulation data for the simplest map - with one building. Division is different than original - maybe some fixes are required to create triangles of more even size? Original: triangulation-orig Generated: triangulation-rem

mefistotelis commented 8 months ago

Made considerable progress.

I realized it's impossible to achieve what was in original map by just changing order of operations. The mesh created there must be a work of optimization algorithm.

The best known way of merging points into optimal mesh is the Delaunay Algorithm. After I learned how it works, I noticed the original binary does have implementation of such an algorithm.

After some adjustments, and using the pre-existing code correctly, I got pretty close to the original:

trig-miss_0_74-orig trig-miss_0_74-rem

My pathfinding generation is now only missing paths through bridges and buildings - I'm not exactly sure how this is handled. But for the rest, my algorithm is now on par with the original (maybe even better is some corner cases).

Moburma commented 8 months ago

Excellent work, as ever. Is there any chance you could output the pathfinding mesh for the Korean map 65 and the original? I assume this must have been what they changed between versions as I can't see any visual differences on the map, so would be interesting to see what they changed.

mefistotelis commented 8 months ago

you could output the pathfinding mesh for the Korean map 65 and the original?

The original triangulation here is missing some walls, especially around the big domes. This probably causes your agents to bump into the domes rather than going around it, when you click on the other side.

Original: _trig1102-orig Korean: _trig1102-korea Original recreated by my algorithm: _trig1102-rem

To save this bitmap, you need to add something like:

         load_map_bnb(mapno);
         ret = load_map_mad(mapno);
+    save_triangulation_png("_trig-orig.png");
     } else {
Moburma commented 8 months ago

Thanks, this confirms what I suspected before and wrongly attributed to the port (I'd been messing about with the map files and thought I'd set them back to default but clearly did not) - in the Korean Map 65 it's possible to drive the moon mech out of the area it starts in if you head towards the central base area.

mefistotelis commented 8 months ago

That's better than the original, I guess.. but it would be even better to make the bevel lower on one side rather than forcing one of four identical-looking sides to be passable.

For me this also confirms that flag 0x04 within MyMapElement.Flags2 was set (or rather adjusted) manually in the map editor, rather than being re-generated automatically while converting DAT to MAD. (this is the flag which marks a tile as "blocking movement".)

Moburma commented 8 months ago

Yep, I am sure it's deliberate. This is the case in the PS1 version, only in that it can leave via the ramp to the left aside above. Oddly you can also now walk about more on the central structure, although there is no legit way to get up there that I can find.