1. Join other hivers in a friendly concept-art contest. The contestants have to create a genie coming out of its container. We wish you the best of luck!
    Dismiss Notice
  2. The Melee Mapping Contest #4: 2v2 - Results are out! Step by to congratulate the winners!
    Dismiss Notice
  3. We're hosting the 15th Mini-Mapping Contest with YouTuber Abelhawk! The contestants are to create a custom map that uses the hidden content within Warcraft 3 or is inspired by any of the many secrets within the game.
    Dismiss Notice
  4. The 20th iteration of the Terraining Contest is upon us! Join and create exquisite Water Structures for it.
    Dismiss Notice
  5. Check out the Staff job openings thread.
    Dismiss Notice

[Wurst] Compile-time objects are not injected into the map

Discussion in 'Triggers & Scripts' started by Robbepop, Feb 17, 2019.

  1. Robbepop

    Robbepop

    Joined:
    Mar 6, 2008
    Messages:
    887
    Resources:
    7
    Maps:
    6
    Spells:
    1
    Resources:
    7
    Hey all,

    I am trying to do my first steps in generating objects during compile-time.
    To be precise I already have them defined in my tower wars map and want to edit/modify them according to some encoded Wurst scripts.

    Note that my knowledge about this topic is very raw and my expectations of how this all works might be way off.
    What I already found out is that I cannot modify existing objects, but instead create new ones based on existing ones.
    So that's what I did for one example creep in my tower wars map.

    Using `@compiletime` and `@objectgen` (from Escape Builder Reloaded) annotations for my functions (all combinations tried) I tried to simply create a new unit definition based on one of my many already existing creep units and set its maximum hp to a different value for testing purposes. Should be simple I thought.

    However, when compiling or running the map I cannot use the new entities even though they show up in the associated .txt files generated in the build directory with the correct stats. So I guess it at least did something.

    When trying to create the entities using their associated IDs no unit is created as if the unit definition was just not there which is what I think is the case. As far as I can imagine the objects are created but the injection of them into the resulting buildmap or runmap file did not happen. Am I supposed to do that manually? I have read in the manual that it is possible to automate this and I was hoping that it was what is happening with my configuration flags:

    -injectobjects
    -opt
    -inline
    -stacktraces
    -runcompiletimefunctions

    What steps do I need to take in order to make this work? :)
     
  2. Jampion

    Jampion

    JASS Reviewer

    Joined:
    Mar 25, 2016
    Messages:
    1,285
    Resources:
    0
    Resources:
    0
    Wurst injects them automatically.

    You should open the compiled map in the editor and search in the object data for the created object. This will tell you whether it was succesful.
    Assuming the object is in the map, make sure you refer to it with the correct id.
    Before creating the unit print the unit's id as raw code and compare it to the one you found in your map compiled.

    You should post your code as well.
     
  3. Robbepop

    Robbepop

    Joined:
    Mar 6, 2008
    Messages:
    887
    Resources:
    7
    Maps:
    6
    Spells:
    1
    Resources:
    7
    Thank you for your response.
    I checked and couldn't find the generated units in the resulting output map file which says to me that they are not injected.
    However, I can clearly see these definitions in their associated .txt files also in the build directory.

    EDIT:

    Code (Text):

    @compiletime function generateCreeps()
       new UnitDefinition('n01X', 'n00E')
           ..setName("FooBar")
          ..setManaMaximum(2000)
     
    Where 'n00E' is a unit that already exists in the input mapfile and 'n01X' is the ID for the resulting unit id that does not already exist.
     
  4. Jampion

    Jampion

    JASS Reviewer

    Joined:
    Mar 25, 2016
    Messages:
    1,285
    Resources:
    0
    Resources:
    0
    I am not sure if you can use a custom unit as original unit. I never needed it personally, so I don't know. I tried your code with a custom unit 'n00E' and a weird object was created for me with lots of missing fields.
    Using a standard unit as original unit works fine though.

    By the way you can also let wurst generate new ids automatically. So you don't have to manually keep track of which ids are unused.
     
  5. Robbepop

    Robbepop

    Joined:
    Mar 6, 2008
    Messages:
    887
    Resources:
    7
    Maps:
    6
    Spells:
    1
    Resources:
    7
    I will try it out on a default unit ID as soon as I am on my laptop again.
    However, there is already a difference between your experience with the above code and mine in that at least something was created for you whereas there was nothing for me.
    I will edit this post as soon as I have results.

    EDIT:

    By the way you can also let wurst generate new ids automatically. So you don't have to manually keep track of which ids are unused.​

    Are these stable so that I can rely on them being the same after every compilation?
    Since otherwise I would prefer having stable IDs so that I can actually work and rely on them in scripts and editor.

    EDIT 2:

    By using IDs of already existing unit definitions, like Sheep 'nshe' I was able to finally get this working.
    Thank you for pointing that out to me!
     
    Last edited: Feb 17, 2019
  6. Frotty

    Frotty

    Wurst Reviewer

    Joined:
    Jan 1, 2009
    Messages:
    1,392
    Resources:
    10
    Models:
    3
    Tools:
    1
    Maps:
    4
    Tutorials:
    1
    Wurst:
    1
    Resources:
    10
    Just take a look at the "object editing" doc sites, they have examples WurstScript • Standard Library.
    Warcraft does not permit extending non default objects, hence you must pass one of those.
    All those IDs are wrapped and you should use those constants from the `Assets` package.
    If you want common attributes you can wrap the definition in your own class.
    You should also not work with raw ids basically ever. Generate them in some way and access via var reference.
     
  7. Robbepop

    Robbepop

    Joined:
    Mar 6, 2008
    Messages:
    887
    Resources:
    7
    Maps:
    6
    Spells:
    1
    Resources:
    7
    @Frotty I have read the standard library documentation and all of the manual beforehand. Unfortunately it is missing some best practices as well as some tips and hints around what is possible and especially what is not. So for example nothing told me there that is just is not possible to use custom unit IDs of preexisting object definitions. That's why I didn't even think about it being not possible and was wondering why the entire thing did not work for me.

    So all in all I must say the docs are impressive - but on the other side you can never have enough good documentation. ;)

    Another question: I think it is wrong to tell people that they should never use non-auto generated unit IDs - why? Because there is a use case for it (as far as my limited understanding goes) - and this use case is for interoperability with legacy (non Wurst) map object definitions that are still in the goo'old object editor. It is pretty hard to convert your entire map to WurstScript automated definitions in the beginning of a conversion. Please proof me wrong!
     
  8. Frotty

    Frotty

    Wurst Reviewer

    Joined:
    Jan 1, 2009
    Messages:
    1,392
    Resources:
    10
    Models:
    3
    Tools:
    1
    Maps:
    4
    Tutorials:
    1
    Wurst:
    1
    Resources:
    10
    Yeah, thanks. The object editing tutorial is still TBD. Feel free to contribute ;)

    Sure, there are a few rare cases like maintaining a legacy map with wurst. But it's arguably rarer and not the main intended use case.
    If you do so, it would be better practice to copy the to-Wurst-translated object definitions from the build folder into packages and then generate the IDs.
    Of course this can be a hassle with many objects. You should at least save those external ids in some public constants then.