Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
Hey I was finally able to put some more time into this. So I think I've got a pretty good idea of how this could replace my JASS/triggers, however, I'm less certain what the custom data workflow looks like with this. I was able to get the Jass Spell Tutorial making omnislash working but only unconditionally firing on the blademaster's existing abilities. What does creating a custom unit or spell look like in C#? I suppose I could modify specific units in place to functionally make them custom units but I'm wondering if there's a better way that I'm missing. Similarly, is there a way to combine this with handcrafted terrain? I can see in the perlin example that I could programmatically create terrain but say I want to handcraft my map with terrain and doodads and such, is such a thing supported? Trying to open my c# map with the editor still crashes the editor, and I'm used to doing custom units/spells and handcrafted terrain in the editor.
More generally, is there a hub of code samples for this? Would be happy to contribute my implementation of the omnislash tutorial if it helps people.
Hey I was finally able to put some more time into this. So I think I've got a pretty good idea of how this could replace my JASS/triggers, however, I'm less certain what the custom data workflow looks like with this. I was able to get the Jass Spell Tutorial making omnislash working but only unconditionally firing on the blademaster's existing abilities. What does creating a custom unit or spell look like in C#? I suppose I could modify specific units in place to functionally make them custom units but I'm wondering if there's a better way that I'm missing. Similarly, is there a way to combine this with handcrafted terrain? I can see in the perlin example that I could programmatically create terrain but say I want to handcraft my map with terrain and doodads and such, is such a thing supported? Trying to open my c# map with the editor still crashes the editor, and I'm used to doing custom units/spells and handcrafted terrain in the editor.
Currently War3Net only manages to replace the trigger editor and the import manager. For the terrain and custom data you'll have to keep using the world editor, although you could try external tools for those as well. I haven't tried using these myself, but you might find them useful: HiveWE, Retera's Model Studio (includes object editor).
Since the world editor can't seem to open your maps, you can try if HiveWE can open them, but otherwise the best solution here is to open your WE map in War3Net, instead of your War3Net map in the world editor. This can be done simply by adding the path to your map file (or folder) to the arguments of MapBuilder.Build(). The order in which you add the arguments determines the priority, so if you put the map file last, you can easily overwrite certain files generated by the world editor. It also supports localization (example). The only reason you should use the world editor's import manager is if you need to see the files inside the editor, for example if you replace the terrain textures.
To create spells in C#, you will need the ability's rawcode. In JASS, there is the FourCC syntax: 'A000', but in C# and lua, you'll have to use the FourCC method. If you really care about performance, you can still declare them as constants, which get inlined, but at the cost of readability. Example:
I may implement something like wurst has (example) to define custom object data in code (admittetly I usually focus on functionality I need myself, unless someone specifically asks for something that's easy to add, and my maps are 90% triggers, 9.99% finding assets like music/sounds, 0.01% terrain, and 0% custom object data, so you can imagine this is not high on my priority list right now).
About the terrain editor: creating terrain is fine, but when you start adding destructables/units/rects/cameras (not sure about doodads), this also affects the map script. Do not create rects nor cameras, the whole point of those is to be able to reference them in the trigger editor, which you're not using if you code with C#. Units are supported, but only the bare minimum (creating them, and setting gold amount for gold mines). My advice is to avoid preplacing units entirely, but that's mostly just my personal preference. Destructables are not supported I think (these should defined in war3map.doo, I'm only parsing war3mapUnits.doo right now).
I'm not aware of any code samples yet. I'm currently working on my own C# map to find any issues and port over some libraries when I need them. Currently I have no plans to write tutorials/samples, so if you want to contribute in that area, it would be very much appreciated.
Thanks for the advice. I was able to load a base map made in wc3 editor with custom unit/ability data. However, running into issues with terrain. It is correctly reflected in the map preview and the minimap but doesn't actually show up in game. Pathing with respect to cliffs/ramps/elevation is respected but the entire map appears as elevation level 0 and the dirt terrain. The order of the asset directory vs the map directory doesn't seem to matter. I wonder if they might have renamed terrain textures in reforged? I can try this in classic wc3 later.
Also just FYI, using the minimal template rather than loading an existing map leads to just black square for both the map preview and the minimap. I initially assumed it might just be a reforged problem but seeing it working in this, I guess not. Although those two bright edges on the side of the mini map seem to have some problem. My blademaster can move into those areas but his unit dot disappears from the minimap if he does. Another issue I noticed is that the map description is getting trampled, despite setting it in WC3 editor, the preview screen displays "Just Another Wc3 Map." But I assume I can probably fix that in code if I poke around.
Also, just heads up for other people who might be looking to this thread when ramping up on this tool, the bit packing is in the other order, like...
Sorry if I'm being a pest here, if you point me in the right direction I can try to debug the terrain issue myself. I figure you'd want the issues reported.
It is correctly reflected in the map preview and the minimap but doesn't actually show up in game. Pathing with respect to cliffs/ramps/elevation is respected but the entire map appears as elevation level 0 and the dirt terrain. The order of the asset directory vs the map directory doesn't seem to matter.
Forgot to mention this, but right now the .w3i and .w3e files aren't auto-detected when you add them through assets, so it will generate default ones. This also causes the map name and description to reset to default. To fix this, you need to set their properties manually:
The FileProvider.GetFile method is able to retrieve files even when they are inside a .w3x file, for example @"C:\map.w3x\war3map.w3e".
This should solve all issues you encountered.
I thought it might be like this. It's confusing because it's the other way around in other places, like here.
EDIT: Updated War3Net.Build -> 1.0.0-preview4, War3Net.CSharpLua.CoreSystem -> 1.1.0, this is mostly bugfixes, but I also changed the way MapInfo, MapEnvironment, and MapUnits are handled. It should now detect these files if they are added through assets, but only if the property was set to null. If they are null and also not found in assets, it: throws exception (for MapInfo), generates using MapInfo (for MapEnvironment), and ignores (for MapUnits, which is not a required file). Note that having MapInfo null before would already have thrown NotImplementedException.
EDIT2: Just realized the new feature mentioned above is bugged, will fix asap.
EDIT3: Should be fixed in version 1.0.0-preview4fix (no I did not test it).
Updating my packages and nulling out CompilerOptions.MapEnviornment fixed the terrain for me. Trying to do the same for MapInfo hit an "Unable to read beyond the end of the stream" exception. NuGet isn't getting the source (it looks like the symbols are maybe referencing absolute paths on your computer? Not sure, pretty unfamiliar with packages and stuff) so I don't know the exact issue but call stacks says issue is at
War3Net.Build.dll!War3Net.Build.Info.MapInfo.Parse(System.IO.Stream stream, bool leaveOpen) Line 493 C#
Not really an issue for me, I'm just gonna edit MapInfo.cs, works fine. Now that I can do terrain, custom data, and triggers I've got everything I need to start working. Gonna clean this up and put together a tutorial on how to get to this point from cloning the template. Thanks for all your help and thanks for making this in the first place.
NuGet isn't getting the source (it looks like the symbols are maybe referencing absolute paths on your computer? Not sure, pretty unfamiliar with packages and stuff)
Do you mind uploading your war3map.w3i file? The file format may have changed in reforged (v1.32), and if so, having an example file would help me implementing support for it.
w3i is attached. It wouldn't let me upload as a w3i so I saved a copy as txt. Hopefully still can work, if that messes it up lmk and I can throw it up on dropbox or whatever.
According to the game version, this .w3i file is from v1.31, not sot reforged. I'm guessing you uploaded the file generated with War3Net instead of one generated by the world editor.
Thanks, I managed to fix parsing the reforged .w3i file, but am still clueless what the new values mean.
There appear to be two new values, 3 and 1 in your case (read as int32), and also PlayerData has 2 additional ints (both 0). I'd like to know what they mean before creating the updated package, so feel free to make a guess.
I'm gonna need to do a comparison of the two menus to have an idea. Nothing is jumping out to me as obvious. Unfortunately I don't have an old wc3 on this laptop and idt I can download it on this wifi, hopefully I can update in a few hours when I get to my destination and can download a copy of old wc3
Hm running into a new issue trying to repeat my steps writing this tutorial. Do you have any idea how to control subversion number? Using the same editor that I had working earlier today now it's putting out subversion 9 rather than 11 I guess (looking at Drake53/War3Net) Is that something I can control in map options? Throwing that not supported exception on map build.
EDIT: Figured it out. Kinda bizarre, you need to specify at least one piece of custom data or the map will fail to load
Hm running into a new issue trying to repeat my steps writing this tutorial. Do you have any idea how to control subversion number? Using the same editor that I had working earlier today now it's putting out subversion 9 rather than 11 I guess (looking at Drake53/War3Net) Is that something I can control in map options? Throwing that not supported exception on map build.
EDIT: Figured it out. Kinda bizarre, you need to specify at least one piece of custom data or the map will fail to load
Tried reproducing this issue, it seems that the world editor doesn't save this file with the latest version if the map does not have TFT-expansion-only features (ie if the map can be saved as .w3m). In this case, I'm getting version 7 and subversion 9 (with latest being 8 and 11). I'll have to take a look at some documentation to see if I can support this older version as well. Also, if I'm reading your post correctly, the exception is thrown for the older subversion, so the version is the latest? That seems kinda weird honestly. If you still have/can reproduce a copy of a war3mapUnits.doo file with version 8 and subversion 9, I'd like to add it to my test suite.
Also, here are some of the map options unique to reforged that might explain the new values in the w3i file
Use custom ability skin (Checkbox)
Use accurate probability for calculations (checkbox)
Supported Modes (SD, HD, or SD and HD)
Game Data Version (Reign of Chaos or The Frozen Throne)
For player options the only difference I notice is the second tab is Ally/Enemy properties instead of just ally properties.
That's probably not enough to infer what the values are, I can send you some maps labelled with the status of those various new options being set if that'd be helpful.
If I had to guess, the zeroes represent the two checkboxes. The 1 could indicate the game data version is The Frozen Throne. No idea what the 3 is. Unless they start indexing at 1? The Supported Modes is set to SD and HD, which I would expect to be represented by a 2.
Also, here are some of the map options unique to reforged that might explain the new values in the w3i file
Use custom ability skin (Checkbox)
Use accurate probability for calculations (checkbox)
Supported Modes (SD, HD, or SD and HD)
Game Data Version (Reign of Chaos or The Frozen Throne)
Thanks for helping investigate this. I think the SD/HD mode could be both the 1 or the 3 (in the latter, it would be a flags enum). The first two also seem good candidates for the 1. I'm not sure about the fourth one though, it sounds similar to the Game Data Set, see image:
That's probably not enough to infer what the values are, I can send you some maps labelled with the status of those various new options being set if that'd be helpful.
Did some testing, my guess about HD/SD modes being flags was correct (the first bit is for SD, the second HD). This was UNK0 before. I also discovered that the two new checkboxes are added to MapFlags (0x20000 for the calculations thing, and 0x40000 for custom ability skin).
However, the other variable (UNK1) is a bit trickier. It seems to be 0 for Reign of Chaos and 1 for The Frozen Throne, BUT in one test case it was randomly set to 2, while simultaneously the Game Data Set was set to -1 (which is normally 0 for 'Default').
EDIT2: Just tested GameDataSet in 1.31 editor. It appears that if you don't touch the dropdown (or better yet, don't open map options menu at all) before saving, it will basically save as a separate 'don't care' option instead of the default selection for the dropdown. For GameDataSet, this 'don't care' has value -1, and for GameDataVersion it should be 2.
Also, there might still be another checkbox somewhere that sets the MapFlags at bit 0x10000 (otherwise, there'd be a gap between the flags at 0x8000 and 0x20000).
Today I implemented most of the auto-generated script from war3mapUnits.doo data. There are still some things left unimplemented though (eg. global random unit tables) and some things are done a bit hackily (eg. detecting if a widget code belongs to a unit or item) so they may not work in certain edge cases. If you run into any issues, let me know please.
@qbz I also managed to take a look at the v8 subversion 9 file you sent earlier. It has only a single unit 'sloc' (start location), and in the beginning it all seems normal, until the point where it should parse the _flags (not sure what these indicate normally anyways), but instead it repeats the unit code 'sloc' (note that _flag is normally a single byte), then there's a byte with value 2, followed by 42 zeroes, then bytes 1, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, then some more zeroes until the end of the file. I'm honestly not really sure how to parse this.
EDIT: Almost forgot, War3Net.Build is updated to v1.0.0-preview5.
Maybe I'm just lazy but I'd say it's not worth it and just put a warning in the readme or make the exception more verbose with the mitigation instructions (make the map TFT). I imagine the primary use case of loading an existing map is using custom data. The only case that hits this is if you only want handcrafted terrain and no custom data. Also converting your map to TFT is trivially easy so personally I wouldn't lose sleep over it.
On a different note, I'm noticing some jass functions missing. Are they under a different name or have they just not been added to be supported yet? For example SetUnitFacingToFaceUnitTimed doesn't exist and neither does IsUnitAliveBJ. Not really a problem for my purposes. You can face a unit by getting the atan of the vector between them and BlzIsUnitSelectable can basically serve as IsUnitAlive. Just wondering if they already exist and I'm not looking in the right places or I just need to wait/work around their absence.
If you point me in the right direction I might be able to PR the work to support them if they're not yet supported, but no promises as I have no idea the scope of the work involved.
Maybe I'm just lazy but I'd say it's not worth it and just put a warning in the readme or make the exception more verbose with the mitigation instructions (make the map TFT). I imagine the primary use case of loading an existing map is using custom data. The only case that hits this is if you only want handcrafted terrain and no custom data. Also converting your map to TFT is trivially easy so personally I wouldn't lose sleep over it.
I gave it some more thought and my theory is that all this data is meaningless, and the values (as signed integers) 1, -1, and -1 only exist to support seeking (because the random data has a variable length, so in this case it would be mode 1, which has 8 bytes following it). Still have to verify this theory though, but that's not a priority right now.
On a different note, I'm noticing some jass functions missing. Are they under a different name or have they just not been added to be supported yet? For example SetUnitFacingToFaceUnitTimed doesn't exist and neither does IsUnitAliveBJ. Not really a problem for my purposes. You can face a unit by getting the atan of the vector between them and BlzIsUnitSelectable can basically serve as IsUnitAlive. Just wondering if they already exist and I'm not looking in the right places or I just need to wait/work around their absence.
IsUnitAliveBJ is in a different namespace "War3Api.Blizzard" (you can tell by it ending with BJ). It is also more efficient to use the native "IsUnitAlive" anyways (this appears to be the fastest way to check). However, since that one is defined in common.ai, it's not available by default. The other native you mentioned appears to be new in reforged. For these last two, you can make them available using the same method as the code in the War3Api packages. Note however that the [NativeLuaMemberAttribute] is mostly obsolete now, the preferred method now is this.
If you point me in the right direction I might be able to PR the work to support them if they're not yet supported, but no promises as I have no idea the scope of the work involved.
It's quite simple really, I only need to put the new common.j and Blizzard.j files here (in a new folder obviously), press a button, and it's done. Only problem is I don't have those files yet.
It's quite simple really, I only need to put the new common.j and Blizzard.j files here (in a new folder obviously), press a button, and it's done. Only problem is I don't have those files yet.
Is that something I can help you with? I searched my reforged game directory and it doesn't seem like those files exist in there. Is it a matter of parsing them out of data files like....
"C:\Program Files (x86)\Warcraft III Beta\Data\config\2b\15\2b15bb5c010f0f43df64588ffe49d6cb"
Is that something I can help you with? I searched my reforged game directory and it doesn't seem like those files exist in there. Is it a matter of parsing them out of data files like....
"C:\Program Files (x86)\Warcraft III Beta\Data\config\2b\15\2b15bb5c010f0f43df64588ffe49d6cb"
They will be located in "<user>\Documents\Warcraft III\JassHelper" after running JassHelper in the world editor (either through saving, or validating triggers).
Next update will be slightly delayed. Just found out the new CSharpLua.Template, unlike NativeLuaMemberAttribute, does not work correctly when it is referenced through a .dll (as opposed to being available in source code). I opened an issue for this so hopefully it will be fixed in the next 24 hours.
I haven't gotten a response yet on my issue so decided to fix this myself. It turns out the auto-generated documentation .xml file has a different structure than was expected, so I auto-generated a model for this .xml file structure and cast this to the other model. After some bugfixing everything should work correctly now.
Packages have been updated:
War3Net.Build: 1.0.0-preview6
War3Net.CSharpLua.CoreSystem: 1.1.1
War3Api.Common and War3Api.Blizzard: 1.32.0.4-beta1
I tried upping to 1.32.0.4-beta1 to use IsUnitAliveBJ but I think there's some sort of problem. Running with the newer version causes none of my code in source to be run, not even simple debug printing. Hopping back a commit to before I updated the version and switched to IsUnitAliveBJ I was able to build and run the map with custom functionality working as expected.
I tried upping to 1.32.0.4-beta1 to use IsUnitAliveBJ but I think there's some sort of problem. Running with the newer version causes none of my code in source to be run, not even simple debug printing. Hopping back a commit to before I updated the version and switched to IsUnitAliveBJ I was able to build and run the map with custom functionality working as expected.
Can you check the output war3map.lua and see if there is any "War3Api" in there? It should remove the prefix "War3Api.Common" and "War3Api.Blizzard", but if it's bugged somehow and it keeps those then it won't work. Also, I have now included the native "UnitAlive", so you can use that instead of "IsUnitAliveBJ".
I guess those launcher packages are old now, maybe that's why?Just upgrading to preview6 doesn't solve the issue. Updating CSharpLua to 1.5.4 and CShareLua.CoreSystem 1.1.1 gives an error in PlayerAndForceSettings.cs that PlayerData constructors don't take 0 args. Looks like tried to add default isReforged but it's also complaining about passing a single bool? Might have old source downloaded for PlayerData definition.
Also unrelated question, whats the syntax to construct a boolexpr? Just trying to pass a static bool function taking void as a boolexpr param gives "cannot convert from method group to Common.boolexpr"
Yes, the new template attribute requires the latest version of War3Net.CSharpLua (v1.5.4), which is referenced by War3Net.Build v1.0.0-preview6.
You can probably leave War3Net.Build on an older version and still have it work, as long as you explicitly reference the latest version of War3Net.CSharpLua as well, but the only time that's really required is if I update the latter package but not the former (ie when the latest version of War3Net.Build doesn't target the latest version of War3Net.CSharpLua).
You should also have the CoreSystem package latest version (v1.1.1), otherwise it may be incompatible with War3Net.CSharpLua.
Also unrelated question, whats the syntax to construct a boolexpr? Just trying to pass a static bool function taking void as a boolexpr param gives "cannot convert from method group to Common.boolexpr"
Updating CSharpLua to 1.5.4 and CShareLua.CoreSystem 1.1.1 gives an error in PlayerAndForceSettings.cs that PlayerData constructors don't take 0 args. Looks like tried to add default isReforged but it's also complaining about passing a single bool? Might have old source downloaded for PlayerData definition.
I probably should've mentioned this breaking API change. The PlayerData class used to be sealed, but when I added the ReforgedPlayerData class, I tried to keep it 'sealed' by making the default contructor internal. The way to initialize this object now is with the static 'Create' method.
Nice tutorial, this should be very helpful for those who'd like to get started with C#. When you finished it 100% let me know, so I can link to it in the first post.
I wrote down some feedback while reading through it a second time. Some of it may be subjective or nitpicky though, so keep that in mind, I'm not trying to offend or anything.
There exists a native called 'FourCC' that does the same as your GetId helper function (although I haven't benchmarked yet which one would be faster).
You mention deleting melee init triggers, but this should not be required, because the C# code will overwrite the war3map.lua file.
You also mentioned setting MapEnvironment to null. In the latest version of the template, the MapEnvironment property no longer gets set to default. This is because the MapBuilder.Build method will now automatically set it to "new MapEnvironment(compilerOptions.MapInfo)" if it is not detected.
In the packagereferences part, you explicitly reference War3Net.CSharpLua, which is already implicitly referenced by War3Net.Build.
The warning about subversion should be fixed since I changed the way a .doo file's header gets parsed.
Instead of creating a new custom unit through the context menu, you can simply C'n'P using ctrl+c and ctrl+v.
"You need to follow a particular directory structure to match Warcraft 3's expectations" sounded a bit confusing at first, you may want to clarify that in this case, it's required for warcraft III to be able to detect variations of the same icon.
"Even though you're not using the World Editor, functionality is still represented in triggers." Probably subjective, but I personally find that triggers should generally be avoided when coding in C#. The only thing they're useful for is to subscribe to events. Advanced vJass users will probably also tell you to only use trigger conditions, not trigger actions (because they are slower), but this kind of information probably doesn't belong in a 'getting started' tutorial. In this case, since you still rely on triggers to subscribe to spell events, I'd do something like this:
C#:
private static readonly Dictionary<int, Action> _spells;
static SpellHandler()
{
_spells = new Dictionary<int, Action>();
// Initialize spells (MySpell is a new class)
_spells.Add(MySpell.Rawcode, MySpell.OnCast);
var spellTrigger = CreateTrigger();
// Not sure if using GetLocalPlayer() here is smart thing to do.
TriggerRegisterPlayerUnitEvent(spellTrigger, GetLocalPlayer(), EVENT_PLAYER_UNIT_SPELL_EFFECT, null);
TriggerAddCondition(spellTrigger, Condition(() =>
{
if (_spells.TryGetKey(GetSpellAbilityId(), out var spellFunction))
{
spellFunction.Invoke();
}
}));
}
Use PLAYER_NEUTRAL_AGGRESSIVE instead of Player(26).
You can use Sin and Cos from War3Api.Common (these use math.sin and math.cos from lua's standard library). I haven't benchmarked them, but the benefit of those over System.Math is that they return float instead of double, so you don't have to cast it.
I'd personally advice against using strings instead of rawcodes for creating units.
Avoid using TriggerSleepAction, use timers instead.
The local currentTarget should be declared on the same line as where it's assigned the first time.
Might want to use a constant instead of hardcoding 57.2957f (you can use bj_DEGTORAD for this).
Some more general feedback:
In some cases, you declare a local variable that can be marked constant. The compiler can inline the values if they are constant, so it's worthwhile to do this.
Subjective (I have a huge hateboner for locations): Never use locations. Every native that takes or returns a location should also support using two floats separately. That way you also don't have to worry about removing the location for memory leaks. You could even use a (float,float) tuple, anything's better than locations! Speaking of useless types, I'd also recommend avoiding hashtables, groups (I know you need them sometimes to enumerate, but still), and forces. You can replace them with types from System.Collections.Generic namespace.
Keep up the good work and let me know if there are still any
I wrote down some feedback while reading through it a second time. Some of it may be subjective or nitpicky though, so keep that in mind, I'm not trying to offend or anything.
Nah by all means, I appreciate the feedback and I'm pretty difficult to offend. So I'll do another pass starting with the package versions currently in the template and make most of the changes you suggested. Hopefully can finish tonight, if not, will definitely be finished by the end of this upcoming weekend absent any new problems. I'll let you know if I run into any new issues with updated packages.
Can you elaborate on using timers rather than sleep? Would that be basically converting the while loop into a timer response that potentially restarts the timer?
Can you elaborate on using timers rather than sleep? Would that be basically converting the while loop into a timer response that potentially restarts the timer?
There are three ways to handle it I think. Either you use a repeating timer, or you use a timer that fires only once and use a while loop, or you start a timer only when you need it.
The first one should work well, though in part 5 you'd have to combine it with the third method, because there it uses TriggerSleepAction twice.
For the second one, you would be starting all timers at the same time, so you'd have to use the summed durations when starting them. This approach would be very inconvenient if the spell can be interupted, since you'd have to stop all the timers.
In case of the third method, you may want to add another helper function, similar to this:
Sure makes sense. What's being avoided? Is it just wasteful busy waiting? I think I might put switching to timer here and the fire on successful condition to avoid action register overhead in like a advanced notes section 6 or something
Having issue with new template. Seems like something's mis-configured for War3Api.Blizzard. Including it as a source dependency gives
System.Exception: 'load <doc> xml file wrong at C:\Users\conor\.nuget\packages\War3Api.Blizzard\1.32.0.4-beta1\lib\netstandard1.0\War3Api.Blizzard.xml'
KeyNotFoundException: The given key 'War3Api.Blizzard' was not present in the dictionary.
Here's the callstack
This is from a fresh clone of the template. The only change was supplying the wc3 path. Removing War3Api.Blizzard as a dependency fixes the issue and the map runs and displays hello world as expected
Sure makes sense. What's being avoided? Is it just wasteful busy waiting? I think I might put switching to timer here and the fire on successful condition to avoid action register overhead in like a advanced notes section 6 or something
Problem with TriggerSleepAction is it's not accurate and can cause bugs when the game lags or gets paused, due to measuring in real time instead of game time.
Fixed, I guess I forgot to test after adding War3Api.Blizzard package. It threw an exception because the class War3Api.Blizzard has no documentation, so it's not listed in the .xml file, but its members relied on that to initialize some dictionaries.
Ran into a new issue with the new packages. When I supply a base map path to the map builder call, code from source no longer runs when the map is launched. It does successfully load terrain data though. Removing the base map path from the map builder calls gets the code from source running again. Map properties still say expansion not required, so its probably hitting your 8.9 fix.
Ran into a new issue with the new packages. When I supply a base map path to the map builder call, code from source no longer runs when the map is launched. It does successfully load terrain data though. Removing the base map path from the map builder calls gets the code from source running again. Map properties still say expansion not required, so its probably hitting your 8.9 fix.
Update to War3Net.CSharpLua package (=> v1.5.6): map should now build faster thanks to concurrency, also some bug fixes.
Update to War3Net.CSharpLua.CoreSystem package (=> v1.1.2): added EventArgs class.
Update to War3Net.Build (=> v1.0.0-preview8): support war3map.w3s (sounds) to generate sounds in main function.
With this, War3Net.Build should be able to handle pretty much all data from war3map files that influence the main function.
I will probably wait until Reforged to see if everything is stable, before I release v1.0.0 for War3Net.Build. In the meantime I'll work a bit on documentation maybe. Let me know if anything's not working as expected.
MapBuilder.Build now returns a BuildResult object instead. This object contains diagnostics for the compilation and build process. To keep backwards compatibility, it can be implicitly cast to a boolean.
Removed all references to the War3Net.CodeAnalysis.Common project. This means that the deprecated NativeLuaMemberAttribute can no longer be used. This also greatly reduces the amount of package dependencies, because this package was targeting a 1.x version of .NET Standard.
From now on I will keep the latest package versions updated in the first post of this thread. Keep in mind that if you're not using the latest version of all packages, they may not be compatible with each other.
EDIT: Another quick update: War3Net.Build has been updated to v1.0.0-rc1, which means it is now feature complete. Please try it out and let me know if there are still any issues or bugs.
Do you have any tips for debugging? If I have an error in my source my code just silently stops executing. I added a few different levels of logging so if I turn on verbose its pretty clear around where a problem occurred but I'm wondering if you know some better approaches.
Do you have any tips for debugging? If I have an error in my source my code just silently stops executing. I added a few different levels of logging so if I turn on verbose its pretty clear around where a problem occurred but I'm wondering if you know some better approaches.
There are two ways to do this, the one I usually use is with pcall/xpcall, and the other is with try-catch, which is implemented using xpcall.
I don't think there are any exception subclasses implemented in the coresystem library, so the safest would be to only try to throw/catch a regular exception.
Examples for both approaches:
C#:
private class Program
{
/// @CSharpLua.Template = "pcall({0})"
public static extern bool PInvoke(this Action func, out string errorMessage);
public static void Main()
{
Action func = ...
// Approach 1
if (!PInvoke(func, out var err))
{
DisplayTextToPlayer(GetLocalPlayer(), 0, 0, err);
}
// Approach 2
try
{
func();
}
catch (Exception e)
{
DisplayTextToPlayer(GetLocalPlayer(), 0, 0, e.Message);
}
}
}
Running into a lot of weirdness with BlzSetAbilityExtendedTooltip...
Calling this also sets the normal tooltip. Also if I make the string param too long, the name is empty and the tooltip is random garbage that changes every time you cast the spell.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.