Drake53 / War3Net

A .NET implementation of Warcraft III related libraries.
MIT License
124 stars 27 forks source link

All destructible on compiled maps are duplicated #39

Closed YakaryBovine closed 1 year ago

YakaryBovine commented 1 year ago

When I build a map using MapBuilder, all destructibles on the resulting map are duplicated. You can see it in the following gif. When I hit the tree and it shakes, there's another tree inside it. Animation

If you need me to make a demonstration map I certainly can. Cheers.

Drake53 commented 1 year ago

I'm unable to reproduce this issue, can you provide an example map+code?

YakaryBovine commented 1 year ago

Yep, going to sleep now but will set up a repo tomorrow.

YakaryBovine commented 1 year ago

@Drake53 Here we go: https://github.com/YakaryBovine/DuplicateDestructibleDemonstration/tree/master Note that this is the same as the default WCSharp template. The only exception is that I opened the map, placed some trees and a Peasant, and saved it. I'm using the latest version of WC3 and the editor.

Drake53 commented 1 year ago

Thanks, I managed to reproduce the issue. The resulting map's war3map.doo file isn't changed though, and I don't see any duplicates doodads in the file. Can you test if you can reproduce the issue if you save source.w3x (using the world editor) as mpq archive? I can't test this myself since I'm using patch 1.31.

Drake53 commented 1 year ago

Actually nevermind, just realized the issue is in war3map.lua's CreateAllDestructables function. Normally this function only creates destructables when the destructable can drop an item or if it's referenced by a trigger, but if ForceGenerateGlobalDestructableVariable is true (which is the default when using CSharpLua), all destructables are created through the map script in order to assign them to a ggdest variable (which normally only happens when a trigger references the destructable). The issue is that the game then generates them all a second time from the war3map.doo file.

Drake53 commented 1 year ago

Didn't test it but this should solve the issue:

var map = Map.Open(BASE_MAP_PATH);

var mapScriptBuilder = new MapScriptBuilder();
mapScriptBuilder.SetDefaultOptionsForCSharpLua();

if (map.Doodads is not null && mapScriptBuilder.ForceGenerateGlobalDestructableVariable)
{
    foreach (var doodad in map.Doodads.Doodads)
    {
    doodad.State = DoodadState.NonSolidInvisible;
    }
}

...

var compileResult = map.CompileScript(compiler, mapScriptBuilder, coreSystemFiles, blizzardJ, commonJ);

I tested how the game/world editor normally handles this and it seems that doodads that are referenced by a trigger get the state NonSolidInvisible instead of Normal.

YakaryBovine commented 1 year ago

That worked perfectly for my map. Thanks heaps!

YakaryBovine commented 1 year ago

Spoke slightly too soon. That fix had the unfortunate side-effect of resetting the height on all my doodads. image

However, looking at your explanation, I tried just setting ForceGenerateGlobalDestructableVariable to false since I don't reference any destructables in my map anyway. This seems to have solved the problem. Cheers!