• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[C#] Mapmaking in csharp

Level 18
Joined
Jan 1, 2018
Messages
728
I'm attaching the whole map.

If you remove the region from the map, the map successfully loads.
Lua:
CreateRegions = function ()
    gg_rct_Region_000 = Rect(-128, 160, -32, 352)
    SetSoundPosition(, -80, 256, 0)
    RegisterStackedSound(, true, 96, 192)
end
Guess my library sucks, will fix asap.

Edit: Should be fixed now, packages have been updated.
 
Last edited:
Level 4
Joined
Jul 30, 2014
Messages
18
Dude, I love your C# compiler, I grabbed War3Net version 8190dfc3bbad82b38d603f40665d8729c30af84a - it was perfect.
The only slightly painful thing was to manually create globalvariables, ie units, doodads, regions etc that you needed in the map. You still need to do that, but also delete them from map script in the original basemap, otherwise it will be copied into the final script.
Now, you need to set half of the things in the map manually, like tileset, camera bounds.
Furthermore, my old map won't load now. After running compiler on it it just breaks it and it doesn't launch. (Launching base map from the editor, however, does the trick, obviously without CSharp code it's useless).
CSharp translator is now broken and just doesn't work. For example,
C#:
public class File
    {
        public static int ReadCount = 0;
        public static readonly int AbilID = FourCC("SaLo");
        /// <summary>
        /// Hard limit appears to be 255 (sendsync) 220 (write).
        /// </summary>
        public const int ChunkLen = 150; // you can fit upto 15,000 long stirng
        public readonly string Path;
        public readonly NoxPlayer TargetPlayer;

        public File(string path, NoxPlayer forWhatPlayer)
        {
            TargetPlayer = forWhatPlayer;
            Path = path;
        }

        public void Write(string payload)
        {
            int len = payload.Length;
            int level = 0;
            if (GetLocalPlayer() == TargetPlayer.PlayerRef)
            {
                PreloadGenClear();
                PreloadGenStart();
                for (int i = 0; i < len;) // yet another translator bug
                {
                    string chunk = SubString(payload, i, i + ChunkLen);
                    Preload("\")\ncall BlzSetAbilityExtendedTooltip(" + I2S(AbilID) + ",\"" + chunk + "\"," + I2S(level) + ")\n//");
                    level++;
                    i += ChunkLen;
                }
                Preload("\")\nendfunction\nfunction emptyfun takes nothing returns nothing\n//");
                PreloadGenEnd(Path);
            }
        }
}
Rather simple file IO does not work anymore. It just won't create file.
I really wish you could just revert some of the hard work you do and support reforged format with the old perfectly working base :(

Thank you very much for the CSharp tho. As it is at least right now.
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
I grabbed War3Net version 8190dfc3bbad82b38d603f40665d8729c30af84a
Hmm that's a quite old version (221 commits when latest has 500). Since you're linking the commit ID, I assume you're adding the projects to your solution instead of referencing the War3Net.Build package?
It would be easier for me to help you out if you used PackageReference instead of ProjectReference. You should probably start with 0.2.1, then upgrade from there and see if you run into issues.

The only slightly painful thing was to manually create globalvariables, ie units, doodads, regions etc that you needed in the map. You still need to do that, but also delete them from map script in the original basemap, otherwise it will be copied into the final script.
Latest version of the library supports parsing units (war3mapUnits.doo), doodads (war3map.doo), and regions (war3map.w3r). It will also generate the main and config functions for you now. This means you don't have to rely on the WE-generated war3map.lua anymore.

Now, you need to set half of the things in the map manually, like tileset, camera bounds.
Assuming you're using a basemap, you can still let these fields be set automatically, by using the war3map.w3i file from your basemap.

Furthermore, my old map won't load now. After running compiler on it it just breaks it and it doesn't launch. (Launching base map from the editor, however, does the trick, obviously without CSharp code it's useless).
CSharp translator is now broken and just doesn't work. For example,
Rather simple file IO does not work anymore. It just won't create file.
As I said above, this kind of stuff is easiest to debug when you start at a version that was working and slowly upgrade. Going from somewhere around v0.2.1 to v1.1.2 is a big leap, so it's not really surprising when there are issues.
You must also keep in mind though that your versions of war3net.build and csharplua.coresystem packages are compatible. I don't know exactly which versions match, so you'd have to look at the release dates on nuget.

I really wish you could just revert some of the hard work you do and support reforged format with the old perfectly working base :(

Thank you very much for the CSharp tho. As it is at least right now.
If you find that new versions aren't working for you, you can always roll back (can't say the same about warcraft III).
Of course, I am always available to help out if you're having problems with the latest package version, all you need to do is ask (and give enough information ^^).
 
Level 4
Joined
Jul 30, 2014
Messages
18
Dude, I'm speechless. Thanks for a reply!:thumbs_up:
I was really desperate yesterday because I spent a whole day trying to convert my map from an old version to a new one.
Only today (a few minutes ago) I decided to just pull the template and replace everything with the old files.
Apparently, the latest packages (launcher)
<PackageReference Include="War3Net.Build" Version="1.1.2" />
<PackageReference Include="War3Net.CSharpLua" Version="1.5.9" />
<PackageReference Include="War3Net.CSharpLua.CoreSystem" Version="1.2.1" />
and (source)
<PackageReference Include="War3Api.Common" Version="1.32.0.4-beta1" />
<PackageReference Include="War3Api.Blizzard" Version="1.32.0.4-beta1" />
fixed everything!:thumbs_up::thumbs_up:
Literally everything, except for units and regions tho :ugly:
You mentioned that the units can be accessed in the source script.
Back in day (8190dfc3bbad82b38d603f40665d8729c30af84a), I used to do something like this
C#:
internal static class ScriptManager
    {
public static void InitUnits()
        {
            unit u;
            player p;
            float life;
            // Player 0-3
            // Player 0
            p = Player(0);
            Selectors[0] = CreateUnit(p, FourCC("hpea"), 9150.6f, 13140.6f, 227.140f);
}
}

public static class GlobalVars
    {

        public static unit[] Selectors = new unit[6];
       
    }

Then, from program main I run ScriptManager.InitUnits();
And can instantly access Selectors[0] from example and manipulate it.
How can this be done in new framework?

PS thank you for your work!!
Lok wat I mek for comunity: Azureus0/NoxRaven :ugly::ugly:
 
Level 18
Joined
Jan 1, 2018
Messages
728
You mentioned that the units can be accessed in the source script.
Back in day (8190dfc3bbad82b38d603f40665d8729c30af84a), I used to do something like this
Then, from program main I run ScriptManager.InitUnits();
And can instantly access Selectors[0] from example and manipulate it.
How can this be done in new framework?
For regions, it generates a global variable similar to how the world editor does it:
Lua:
CreateRegions = function ()
    gg_rct_Region_000 = Rect(-128, 160, -32, 352)
end
Preplaced units and doodads currently don't generate global variables, but it shouldn't be too hard to add this.

To access the generated rect global variable in C#, you should be able to do something like:
C#:
/// @CSharpLua.Template = "gg_rct_Region_000"
public static rect Region_000;
This is probably very inconvenient though (also why I personally like to avoid using preplaced regions/units/etc). If you have a suggestion for how to approach this, I'd love to hear it.
 
Level 4
Joined
Jul 30, 2014
Messages
18
You can theoretically have a daemon running, that checks for timestamp changes to map's war3map.lua and from there it will put in source project extra file like War3MapGlobalVars.cs, this static class will have all global variables that are accessible from the C#script.
Although the daemon will obviously be a separate project, that needs to be run on the system :ugly:
Another solution is to include this extra API in War3Net.CodeAnalysis.Common which replaces references at runtime, eg. War3Net.CodeAnalysis.Common.GetObject<unit>("Peon_0001")
Again not the best idea, because you need to look up that name in the editor first. So... :ugly:
 
Level 18
Joined
Jan 1, 2018
Messages
728
You can theoretically have a daemon running, that checks for timestamp changes to map's war3map.lua and from there it will put in source project extra file like War3MapGlobalVars.cs, this static class will have all global variables that are accessible from the C#script.
Although the daemon will obviously be a separate project, that needs to be run on the system :ugly:
Another solution is to include this extra API in War3Net.CodeAnalysis.Common which replaces references at runtime, eg. War3Net.CodeAnalysis.Common.GetObject<unit>("Peon_0001")
Again not the best idea, because you need to look up that name in the editor first. So... :ugly:
Thanks for the suggestions. I think a good solution for now would be to have some War3MapGlobalVars.cs like you said. As I said before though, the library can now handle a lot more, so there's no need to check the base map (which may not exist at all) for changes to war3map.lua, I'd rather check the input war3mapUnits.doo etc files and autogenerate the C# API for those.

EDIT: Tried implementing this, what I got so far is something like this:
C#:
namespace War3Map.Template.Generated
{
    public static class war3mapUnits
    {
        /// @CSharpLua.Template = "hpea0000"
public static War3Api.Common.unit hpea0000;
        /// @CSharpLua.Template = "hpea0001"
public static War3Api.Common.unit hpea0001;
        /// @CSharpLua.Template = "hpea0002"
public static War3Api.Common.unit hpea0002;
        /// @CSharpLua.Template = "hpea0003"
public static War3Api.Common.unit hpea0003;
        /// @CSharpLua.Template = "hpea0004"
public static War3Api.Common.unit hpea0004;
        /// @CSharpLua.Template = "hpea0005"
public static War3Api.Common.unit hpea0005;
        /// @CSharpLua.Template = "hpea0006"
public static War3Api.Common.unit hpea0006;
        /// @CSharpLua.Template = "hpea0007"
public static War3Api.Common.unit hpea0007;
        /// @CSharpLua.Template = "hpea0008"
public static War3Api.Common.unit hpea0008;
        /// @CSharpLua.Template = "hpea0009"
public static War3Api.Common.unit hpea0009;
        /// @CSharpLua.Template = "hpea0010"
public static War3Api.Common.unit hpea0010;
        /// @CSharpLua.Template = "hpea0011"
public static War3Api.Common.unit hpea0011;
        /// @CSharpLua.Template = "hpea0012"
public static War3Api.Common.unit hpea0012;
        /// @CSharpLua.Template = "hpea0013"
public static War3Api.Common.unit hpea0013;
        /// @CSharpLua.Template = "hpea0014"
public static War3Api.Common.unit hpea0014;
        /// @CSharpLua.Template = "hpea0015"
public static War3Api.Common.unit hpea0015;
        /// @CSharpLua.Template = "hpea0016"
public static War3Api.Common.unit hpea0016;
        /// @CSharpLua.Template = "hpea0017"
public static War3Api.Common.unit hpea0017;
        /// @CSharpLua.Template = "sloc0018"
public static War3Api.Common.unit sloc0018;
    }
}
I'd still have to define these global variables in war3map.lua to get it working though.

Also since I haven't mentioned this yet, there's was a minor bugfix to War3Api.Common, so latest version for that package is now 1.32.0.1
 
Last edited:
Level 5
Joined
Mar 8, 2012
Messages
44
Let me first just say that I love this project. Thank you for this. I have one thing I'd like to suggest, however.

Right now, if you want to work with unit orders, you either need to look up some resource that lists all the order ids (less than ideal to use vague magic numbers in code), look up the order strings with e.g. Channel, or just know them by heart. If they could be added as constants like "ORDER_BLINK", using their integer values (as I presume this is faster), it'd be ideal. This seems to me like it could just be added to the common class. Then you can simply rely on IntelliSense to quickly find the order ID that you need.

This is basically in a similar trend as the constants for object editor stuff discussed earlier, but since this isn't something that you need to generate (since it will never change anyway, at most a new id will be added at some point) it should be pretty easy to add.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Let me first just say that I love this project. Thank you for this. I have one thing I'd like to suggest, however.

Right now, if you want to work with unit orders, you either need to look up some resource that lists all the order ids (less than ideal to use vague magic numbers in code), look up the order strings with e.g. Channel, or just know them by heart. If they could be added as constants like "ORDER_BLINK", using their integer values (as I presume this is faster), it'd be ideal. This seems to me like it could just be added to the common class. Then you can simply rely on IntelliSense to quickly find the order ID that you need.

This is basically in a similar trend as the constants for object editor stuff discussed earlier, but since this isn't something that you need to generate (since it will never change anyway, at most a new id will be added at some point) it should be pretty easy to add.
Thanks for the suggestion. The Common class is in namespace War3Api, so it's only intended to contain identifiers that exist in common.j or common.ai (some exceptions for lua stuff like FourCC).
I think an addition like this would be more suited for War3Lib (though I don't have much time to work on this project so it's a bit useless still).
In the meantime, you could define these constants yourself. You can find them here.
 
Level 5
Joined
Mar 8, 2012
Messages
44
I feel like there's little reason not to include them here though, considering that the order ids are basically just hardcoded constants. It's like how UnitAlive was manually added, since we know it exists, even if it isn't defined in common.j for whatever reason. It's something that Blizzard should have added already.
But for now I'll just add them manually I suppose. I've already made a program to do similar things for custom object editor data, but I felt this one should just be added natively.
 
Level 18
Joined
Jan 1, 2018
Messages
728
I feel like there's little reason not to include them here though, considering that the order ids are basically just hardcoded constants. It's like how UnitAlive was manually added, since we know it exists, even if it isn't defined in common.j for whatever reason. It's something that Blizzard should have added already.
But for now I'll just add them manually I suppose. I've already made a program to do similar things for custom object editor data, but I felt this one should just be added natively.
I understand it may be inconvenient to not have all order IDs available in the API, but the condition for something to be in War3Api is simple: it should be a Warcraft III method/field. In practice, this means it has to be declared using '/// @CSharpLua.Template = "something"', which simply isn't the case for order IDs (and for UnitAlive it is, because it's declared in common.ai).
 
Level 5
Joined
Mar 8, 2012
Messages
44
Alright, other topic. I noticed that MathF isn't implemented. This is rather bothersome, since Math converts stuff to doubles, and all of the WC3 methods require floats. For the most part I can get around that via using the natives instead (which just map to the same Lua functions anyway), but it doesn't have all the functionality.

I'm guessing this is more of a problem on the side of the converter, which I realise isn't written by you, but I figured I'd raise the issue here first anyway.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Alright, other topic. I noticed that MathF isn't implemented. This is rather bothersome, since Math converts stuff to doubles, and all of the WC3 methods require floats. For the most part I can get around that via using the natives instead (which just map to the same Lua functions anyway), but it doesn't have all the functionality.

I'm guessing this is more of a problem on the side of the converter, which I realise isn't written by you, but I figured I'd raise the issue here first anyway.
Unfortunately, I can't really help you with that. Like you say, this is related to the transpiler, so I recommend you open an issue here.
 

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
Hey how do I set up a custom loading screen? I see there's a loadingscreenpath on map info, but just setting that to point to the absolute path or the relative path from my assets directory of my tga didn't work. Looking through old tutorials im seeing recommendations that your loading screen be sliced into multiple parts and used alongside a loadingscreen.mdx file but im not sure the extent to which this also applies to reforged/wc3c#
 
Level 18
Joined
Jan 1, 2018
Messages
728
Hey how do I set up a custom loading screen? I see there's a loadingscreenpath on map info, but just setting that to point to the absolute path or the relative path from my assets directory of my tga didn't work. Looking through old tutorials im seeing recommendations that your loading screen be sliced into multiple parts and used alongside a loadingscreen.mdx file but im not sure the extent to which this also applies to reforged/wc3c#
The loading screen path needs to be a model, not a texture. For example, in one of my maps I have the following:
C#:
mapInfo.LoadingScreenPath = @"UI\LoadScreen.mdx";
Slicing the screen in multiple files is no longer required, but it depends on your loading screen model. I tried searching for one that uses a single file but only found the one that has it sliced in 10+ parts, so I'm attaching the one I use. The path for its texture is "FullScreen.blp".
 

Attachments

  • LoadScreen.mdx
    1.3 KB · Views: 56
Level 18
Joined
Jan 1, 2018
Messages
728
Quick update, I have uploaded War3Api v1.31.1.3 packages that you can use to not accidentally use 1.32 stuff. If you're targeting 1.31, use:
Code:
  <ItemGroup>
    <PackageReference Include="War3Api.Common" Version="[1.31.1.3,1.32)" />
  </ItemGroup>
Note that since War3Net.Build targets 1.32, you can not do this if you're using the current structure of War3Map.Template, where the launcher project references the source project. However, this reference can safely be removed, since it was only added to force the source project to build when you run the launcher, allowing you to see if there are build errors in the source project. So if you remove the project reference, the launcher will run even if there are build errors in your source. You can see these errors by building the source project/the entire solution, or by viewing the diagnostics in the BuildResult object returning from MapBuilder.Build().

Also note that earlier versions of War3Api (before 1.31.1.3) are NOT compatible with the latest version of War3Net.Build.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Does this include functionality to check object usage or is it just checking script/api usage?
Correct me if I'm wrong, but I feel like this question is related to my map downgrade project, which is a separate project from (but uses) War3Net.Build. Either way, both are currently unable to handle object editor data, but I'm working on adding this functionality to allow validation and code-based object data generation.
 
Level 18
Joined
Jan 1, 2018
Messages
728
ah ok. I was gonna say for my map it's only warning me about the lack of a .w3s file but is crashing in 1.31
I checked your map's war3map.w3u again, using auto-generated code from 1.29.2 .slk files (don't have them for 1.31 since I need CASC software to extract them), and I found that the property rawcodes 'uabs' and 'uhas' are not recognized.
EDIT: Also checked the other object files now. Only unrecognized rawcode I found was 'ausk' in ability object data.
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
hm. I cant find those IDs in object editor and it allows me to create new custom units/abilities with them.
They are property IDs, not object IDs. For example 'ubpx' is the button position X property.

EDIT: Just for clarification, I can make a new unit with ID 'ubpx' because it does not conflict with property IDs, but I cannot make a new unit with for example ID 'hpea', which is already in use by peasant.

I also extracted 1.31.1 PTR CASC .slk files and got the same results, so the unit properties 'uhas' and 'uabs', and the ability property 'ausk', are exclusive to reforged. You can see for yourself using my tool here.
I'm not 100% sure if this is what causes the loading screen crash though.
 
Last edited:

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
Ok those are....

uhas - HeroAbilitySkinList - I believe this was added to support the hero skins you can unlock. I can try clearing this list, I'm not sure whether or not its necessary. Basically a second list of abilities for the skinned version for some reason.
uabs - AbilitySKinList - same for unit type abilities
ausk - UnitSkinId - I guess if an ability is associated with a particular skin you set it here? Dunno. These properties are confusing and seem redundant?

I'll try and check if clearing the skin ability lists fixes the crash but I'm not feeling super hopeful that it will. Ausk is never set by any of my custom abilities but still appearing.
 
Level 18
Joined
Jan 1, 2018
Messages
728
@qbz I have updated my tool to allow object data to be 'downgraded' (by removing the incompatible objects (none in your case) and properties). With these changes, the map no longer crashes on load screen. Some heroes now have a missing (green) icon though, so you'll have to fix that.
 

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
Is there a way I can check I'm on 1.31? Or if any icon loads failed? It might be the case I can replace some hq icons with other similar ones but I wouldn't want to downgrade to old wc3 quality. Or maybe I just need to identify the problem icons and include copies of them as custom data? I imagine that's kosher w/ whatever relevant eula/tos
 
Level 18
Joined
Jan 1, 2018
Messages
728
Is there a way I can check I'm on 1.31?
To check this in map script, this may be helpful: Detect Game Version (GetPatchLevel)

Or if any icon loads failed?
I'm not aware of any method to do this.

It might be the case I can replace some hq icons with other similar ones but I wouldn't want to downgrade to old wc3 quality. Or maybe I just need to identify the problem icons and include copies of them as custom data? I imagine that's kosher w/ whatever relevant eula/tos
With reforged you can import assets as HD (which prefixes the file path with some string), so you can have a SD and HD version of a file. You may be able to use this feature. It will also affect the map when playing with classic graphics on reforged though (which is a good thing). If you use wc3 internal assets (and the file has an SD and HD version in reforged, but on 1.31 the file does not exist or the path is different) you could just import the file so it works on 1.31 too.
 

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
Thanks. Alright I've got a repro environment set up. Downgrader seems to work, allows me to run on 1.31. However, not sure if its a backcompat issue or an issue with the app, the downgraded map does not load in 1.32 anymore. It hits a crash during loading screen.

Also unfortunately a bit wider than just icons. a handful of models are missing too. Seems straightforward to extract and reimport icons, less sure I'm gonna be able to extract and reimport models and skeletons and stuff. Also good icons against classic icons probably fine but good models against classic models is gonna look weird. And also might break old technical limitations. Ugh some special effects are also not working. Not testing with sound but I would guess the .flacs I dynamically try to play also wont work.

I could just try to replace some models with versions that hopefully also have a classic version but that seems tedious guess and test, not sure of any way to check that.

I think the easiest solution might just be to create a classic graphics version maybe. Although I originally tested on the offline 1.31 version the same graphics issues are present just by switching to classic graphics in reforged. In a world where that's just a built-in toggle it seems like there should be fallbacks for every built-in blizzard asset but I guess that's asking too much.
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
It's unfortunate that there are still so many issues. Since the graphical issues are also present in classic reforged, it should at least be a bit easier to check compatibility.
I think the easiest way to find out which assets are HD-only is by comparing the listfiles of 1.31 and 1.32, or checking 1.32's listfile if it lists both SD and HD paths. You can use CascView to extract the listfile, which gives you something like this:
Code:
...
war3.w3mod:replaceabletextures\ashenvaletree\icecanopytreeblight.blp
war3.w3mod:replaceabletextures\barrenstree\barrenstree.blp
war3.w3mod:replaceabletextures\barrenstree\barrenstreeblight.blp
war3.w3mod:replaceabletextures\cameramasks\black_mask.blp
war3.w3mod:replaceabletextures\cameramasks\diagonalslash_mask.blp
war3.w3mod:replaceabletextures\cameramasks\dreamfilter_mask.blp
war3.w3mod:replaceabletextures\cameramasks\groundfog_mask.blp
war3.w3mod:replaceabletextures\cameramasks\hazeandfogfilter_mask.blp
war3.w3mod:replaceabletextures\cameramasks\hazefilter_mask.blp
war3.w3mod:replaceabletextures\cameramasks\panda-n-cub.blp
war3.w3mod:replaceabletextures\cameramasks\scope_mask.blp
war3.w3mod:replaceabletextures\cameramasks\specialpowmask.blp
war3.w3mod:replaceabletextures\cameramasks\specialsplatmask.blp
war3.w3mod:replaceabletextures\cameramasks\white_mask.blp
war3.w3mod:replaceabletextures\citycliffs\city_cliffsquaretilesdark.blp
war3.w3mod:replaceabletextures\cliff\cliff0.blp
war3.w3mod:replaceabletextures\cliff\cliff00.blp
war3.w3mod:replaceabletextures\cliff\cliff1.blp
war3.w3mod:replaceabletextures\cliff\lords_cliffdirt.blp
war3.w3mod:replaceabletextures\cliff\lords_cliffdirtnew.blp
war3.w3mod:replaceabletextures\cliff\north_cliffice.blp
war3.w3mod:replaceabletextures\commandbuttons\btn3m1.blp
war3.w3mod:replaceabletextures\commandbuttons\btn3m2.blp
war3.w3mod:replaceabletextures\commandbuttons\btn3m3.blp
war3.w3mod:replaceabletextures\commandbuttons\btnabomination.blp
...

Getting a list of which assets your map uses may be a bit tricker though. If you use custom paths they can easily found in object data, otherwise you'd need to know which object data is used and what the default paths are. You also need to parse the map script for special effect paths.

If all this sounds like more effort than it's worth, you can also lock you map to HD-mode, by setting MapInfo.SupportedModes to HD. That way, users should not be able to play the map when using classic graphics in reforged.
 

qbz

qbz

Level 4
Joined
Dec 1, 2019
Messages
80
Yeah I think I'm gonna take a crack at trying to get a good idea of the scope of the affected assets and their potential alternative replacements to see how much work it's actually gonna be. I think I'll update to require HD in the meantime though until fixed if I decide its reasonable to fix. Thanks for the info.

Edit: Confirmed with this set, the map starts in HD even if the wc3 was set to SD mode before starting. Thanks!
 
Last edited:
Level 4
Joined
Oct 22, 2019
Messages
32
Is there object editing functionality present now? As in, could I create say a new unit from within C#?

Edit: Are there plans to support hot code reload? Seems like in Lua it's more simple to do than one may think: read the changes via a local file and call the `load` Lua function with the file contents.
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
Is there object editing functionality present now? As in, could I create say a new unit from within C#?
Yes, but in its current state it's quite useless. I'm currently working on creating a better API that uses the object editor .slk files.

Edit: Are there plans to support hot code reload? Seems like in Lua it's more simple to do than one may think: read the changes via a local file and call the `load` Lua function with the file contents.
No plans currently, but I might look into it when I'm done with the object editing stuff.
 
Level 3
Joined
Nov 12, 2010
Messages
43
Hi guys, this project seems awesome but I can't find any documentation about it, Is there a way to use it for compiling a map for 1.29 version?.
Just downloaded the Tutorial template and generated correctly the map.w3x but when it's launched only a black screen is showed in the warcraft and an empty dialog box then the game is closed.

Added this to scriptCompilerOptions
scriptCompilerOptions.TargetPatch = GamePatch.v1_29_2;
and compiler says : error CS0103: El nombre 'GamePatch' no existe en el contexto actual (the name GamePatch doesn't exist in current context)

Some help would be appreciated.

edit > updated the packages :
<ItemGroup>
<PackageReference Include="War3Net.Build" Version="1.3.2" />
<PackageReference Include="War3Net.CSharpLua.CoreSystem" Version="1.2.2" />
</ItemGroup>

in template map >
<ItemGroup>
<PackageReference Include="War3Api.Common" Version="1.32.3" />
<PackageReference Include="War3Api.Blizzard" Version="1.32.2" />
</ItemGroup>

Now,the compiler is happy but still can't run the map, same black screen and empty dialog box :C
 

Attachments

  • generado.w3x
    139.6 KB · Views: 45
  • bsod.png
    bsod.png
    52.2 KB · Views: 55
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
Hi guys, this project seems awesome but I can't find any documentation about it, Is there a way to use it for compiling a map for 1.29 version?
Sorry about lack of documentation. The project uses CSharpLua to transpile C# source code to lua. Since lua support was only added since patch 1.31, you can not use it for 1.29.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Update:
I have finally released War3Api.Object! Current version is v1.31.1-rc1.
This package allows you to generate object editor data through C# code. Your modifications are automatically tracked in a singleton database, but you create your own as well.
Use the following code to extract your object data from the database and create the .w3u/etc files:
C#:
var objectData = ObjectDatabase.DefaultDatabase.GetAllData();
objectData.UnitData?.SerializeTo(File.Create(Path.Combine(outputFolder, MapUnitObjectData.FileName)));
objectData.ItemData?.SerializeTo(File.Create(Path.Combine(outputFolder, MapItemObjectData.FileName)));
objectData.DestructableData?.SerializeTo(File.Create(Path.Combine(outputFolder, MapDestructableObjectData.FileName)));
objectData.DoodadData?.SerializeTo(File.Create(Path.Combine(outputFolder, MapDoodadObjectData.FileName)));
objectData.AbilityData?.SerializeTo(File.Create(Path.Combine(outputFolder, MapAbilityObjectData.FileName)));
objectData.BuffData?.SerializeTo(File.Create(Path.Combine(outputFolder, MapBuffObjectData.FileName)));
objectData.UpgradeData?.SerializeTo(File.Create(Path.Combine(outputFolder, MapUpgradeObjectData.FileName)));

War3Net.Build was also updated to v1.3.3
 
Level 18
Joined
Jan 1, 2018
Messages
728
Quick update: I have uploaded a new version of War3Api.Object: v1.31.1-rc2.
This is a breaking change, since it renames all properties to have the category prefixed, for example: 'unit.Normal' becomes 'unit.AbilitiesNormal'.
If you've already been using the package, you can easily rename stuff using ctrl+spacebar.

EDIT: Bugfix -> v1.31.1-rc3
EDIT2: Another bugfix -> v1.31.1-rc4
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
Edit: Are there plans to support hot code reload? Seems like in Lua it's more simple to do than one may think: read the changes via a local file and call the `load` Lua function with the file contents.
Been trying to get this working today, my conclusion so far is that the lua implementation of .NET library is not built around supporting this.
Right now I'm getting an error at line 1404:
Lua:
assert(modules[name] == nil, name)
What this line does is check if the namespace doesn't already exist. But we're reloading code so... of course it already exists.

It should still be possible to implement code reloading, but it'll require some changes to the lua library.
 
Level 18
Joined
Jan 1, 2018
Messages
728
Update:
I have added an experimental new feature to the transpiler: you can now decompile the code from packages into C# source code, allowing it to be transpiled to lua. This should make creating and using packages a lot more convenient.
To enable this feature, set DecompilePackageLibs to true in your build options. Note that if you enable this, you must use the latest version of War3Api, or it will break your map.

Latest versions:
- War3Net.Build: v1.3.4
- War3Net.CSharpLua: v1.6.1
- War3Net.CSharpLua.CoreSystem: v1.2.4
- War3Api: v1.32.3.1 (or v1.31.1.4)
 
Level 18
Joined
Jan 1, 2018
Messages
728
Quick update, I have split off some stuff from War3Net.Build into War3Net.Build.Core, so that I can re-use the code for some of my other projects without the dependency on CSharpLua. This should not cause any compatibility issues. Latest version is now v1.3.6
 
Level 14
Joined
Aug 31, 2009
Messages
775
So as of a couple of days ago, it's no longer creating the map file (the .w3x) nor running when set to Debug mode.

Really not sure what's going on here.

It might be on our side, so I'm gonna check it over and see what's going on.

EDIT:
Okay, so after some checking, we think we've found the issue:

Basically, when the C# code is compiled into Lua, it has to do a work around for creating objects.

So for example, this code in C#:
C#:
arena = new Arena
            {
                ArenaName = "Offence, Defence, Pocket 3v3",
                ArenaType = ArenaType.Teams,
                SpawnRegions = new List<Rect>(),
                HasNeutrals = false,
                NeutralSpawnRegions = null,
                CameraBounds = new Rect(12032, 2720, 17632, 4224)
            };

Gets turn into:
Lua:
      local default = class.Arena()
      default.ArenaName = "Offence, Defence, Pocket 3v3"   
      default.ArenaType = 2 --[[ArenaType.Teams]]   
      default.SpawnRegions = ListRect()    
      default.HasNeutrals = false    
      default.NeutralSpawnRegions = nil    
      default.CameraBounds = System.new(FortWarsSourceData.Rect, 2, - 9536, 6464, - 4800, 9280)
      local arena = default

So the C# to Lua compiler is using the reserved word "default" as its temporary identifier. If the method contains more than 17 unique temporary identifiers (default, using, out, try, case, void, byte, char, uint, lock, using, fixed, constant, object, internal, virtual), the C# to Lua compiler simply crashes.

Evidently, this list of words are all banned keywords in C#, and were chosen as to not create any conflicts with your own variable names during the conversion.

But hot damn. I'm surprised this hasn't been noticed before.

Weirdly, the list of actually banned terms for C# is way bigger than 17 terms. And that seems like a strangely arbitrary point to stop at.
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
So as of a couple of days ago, it's no longer creating the map file (the .w3x) nor running when set to Debug mode.
There should be an error/exception in BuildResult.Diagnostics.

EDIT:
Okay, so after some checking, we think we've found the issue
Good job finding the issue, but to have it fixed I suggest you make an example that reproduces it and open an issue here: yanghuan/CSharp.lua
When it gets fixed I'll merge it into my fork and update the packages.
 
Level 5
Joined
Mar 8, 2012
Messages
44
Hello again! I'm happy to see this still going.
Damage up there has been garnering some attention for a few of the systems I've built for him, and I decided to put them online as a NuGet package.

I can't seem to get a NuGet package to work properly when imported however. By default, it just does not transpile the package and creates a bunch of broken references. I figured the "DecompilePackageLibs" options would be a fix for this, but it seems to try and import War3Api.Common and fail there before even getting to my package.
I'm also seeing various pieces in the War3Net source code that seem to indicate that the War3Api packages are hardcoded to be imported, as well as that it seems to import csproj's in the same solution, but I don't see anything for NuGet packages outside of that?
Am I missing something, or is there currently no support for importing external libraries like this?
 
Last edited:
Level 18
Joined
Jan 1, 2018
Messages
728
I can't seem to get a NuGet package to work properly when imported however. By default, it just does not transpile the package and creates a bunch of broken references. I figured the "DecompilePackageLibs" options would be a fix for this, but it seems to try and import War3Api.Common and fail there before even getting to my package.
I'm also seeing various pieces in the War3Net source code that seem to indicate that the War3Api packages are hardcoded to be imported, as well as that it seems to import csproj's in the same solution, but I don't see anything for NuGet packages outside of that?
Am I missing something, or is there currently no support for importing external libraries like this?
The 'DecompilePackageLibs' was an expiremental feature but currently it does not work, because it decompiles everything and that causes errors. To get it to work, I should probably add a whitelist (packages that should be compiled) and/or a blacklist (packages that should not be decompiled), but I haven't given this feature a lot of priority since I wasn't sure anyone would want to use it in the first place.

Anyways, another solution than using 'DecompilePackageLibs' is to publish the NuGet package as a 'Sources' package, where the .cs files are included in the package, allowing them to get transpiled to lua.
You can take a look at the .csproj files here to see how to set it up: Drake53/War3Lib
Example package: War3Lib.UI.Sources 1.0.5
 
Level 5
Joined
Mar 8, 2012
Messages
44
I've more or less got that to work, but I think I'm having issues because of library interdependence. The main package uses a utils package. Admittedly the utils package being separate doesn't have much of a purpose right now because it gets auto imported anyway, but well, I'm new to nuget authoring. But it seems this would pose a problem to future packages regardless, as it seems that you'd both need a source-included (for direct referencing in the map project) and a source-excluded version (for references between libraries)?

That said it seems to work fine for the War3Api ones, so I'm guessing there should be an easier fix.
 
Level 18
Joined
Jan 1, 2018
Messages
728
I've more or less got that to work, but I think I'm having issues because of library interdependence. The main package uses a utils package. Admittedly the utils package being separate doesn't have much of a purpose right now because it gets auto imported anyway, but well, I'm new to nuget authoring. But it seems this would pose a problem to future packages regardless, as it seems that you'd both need a source-included (for direct referencing in the map project) and a source-excluded version (for references between libraries)?

That said it seems to work fine for the War3Api ones, so I'm guessing there should be an easier fix.
I think I understand what you mean.
se.png

Since you're referencing one .Sources packages from another .Sources package, the 'main' package includes all .cs files instead of only its own. As a result, in C:\Users\<User>\.nuget\packages\wcsharp\1.0.1\contentFiles\cs\netstandard2.1\WCSharp and the solution explorer, it also includes the files from the Utils package. Instead you'd probably want the Utils package as a separate 'linked' folder, just like the 'WCSharp' folder in the solution explorer.

I never tried this myself before, so can't give you a solution right now, but at least for now it all seems to work.

When I made my .Sources packages I used this: X.Y.Z.Sources nuget package
In the comments the property 'SuppressDependenciesWhenPacking' is mentioned, you may be able to use that to prevent WCSharp.Utils files from being added to the contentfiles of WCSharp's package, haven't tested it myself obviously so not sure if that'd work and what side-effects it may have.

Also, I'm not sure if you're actually using any of the patch 1.32 natives, but if not, you could reference War3Api 1.31.1.4 instead, otherwise a project using that version of War3Api will get a NU1605 error.
 
Top