• 0

    posted a message on Request: UI, Terrain, Skin, or Model artist

    Greetings!

    Have an interest in art design, but unsure of what sort of map to make, or not really thrilled about the inner workings of gameplay coding? The map team I'm on is looking for an artist with an interest in user interface, terrain, skin, or model design. You can download and try out a development version of the map on the project page here. You can have the freedom to do what you enjoy - creative artwork - without being bogged down by all the other elements that go into a map.

    If you might be interested, just send me a private message.

    Posted in: Artist Tavern
  • 0

    posted a message on Import / export library feature broken

    If you export a library from a map, then import it to a new map, all the grammar and hint text is erased.

    Workaround

    1. Export the library from the source map.
    2. Import it into your destination map.
    3. Delete the contents of the library in the destination map (everything but the folder it's in).
    4. Ensure the destination library ID matches the source library ID (trigger module menu > Data > Library > Change Library ID).
    5. Copy the contents from the source map library folder
    6. Paste the contents into the library folder in your destination map.

    This method also ensures any "Labels" are preserved.

    Posted in: Galaxy Editor Bugs and Feedback
  • 0

    posted a message on Passing lists of multiple numbers to functions

    Passing multiple integers to a function is something I needed to do, so came up with the simple library in the attached map in a few minutes' time.

    Technically, the editor and galaxy language don't allow us to pass arrays to functions. Strings are arrays however, and as such can substitute as arrays. We have very limited functionality dealing with strings, but basic storage can be done easily, if inefficiently.

    If we had more powerful tools, a better solution could be created... we could even create our own dynamic allocation system using strings as a memory space. There doesn't appear to be a way to access characters of a string by index however, nor are there atoi or itoa functions, nor even a logarithm function to easily get the position of values in an integer, and implicit casting is disallowed. I was attempting to create a system where the integers would be converted into byte values with an ascii character representation, but got frustrated with the roadblocks of the galaxy language, so stuck with this. The list isn't something I use often or store large values in, so simply converting integers to strings is good enough for my purposes.

    The functions here can also be easily extended to use floating point values or other numbers as well, if you need to do that. Any sort of lists involving spaces (such as unit names) will need a different solution for storage however.

    I've also included some examples in the map using the functions.

    Note: The import/export library functions of the editor are broken (hint and grammar text erase when you use import), so follow the method detailed in this post: Library Import/Export Bug

    Hope this is useful for you.

    Test
        Events
            Timer - Elapsed time is 0.25 Game Time seconds
        Local Variables
            Test List <Integer List>
        Actions
            Variable - Set Test List = ((1), (2), (3))
            List - Do stuff with list (Test List)
            Variable - Set Test List = ((0), Test List)
            Variable - Set Test List = (Test List, (4))
            List - Do stuff with list (Test List)
            UI - Display (Text(Test List)) for (All players) to Debug area
    
    
    Do Stuff with List
        Options: Action
        Parameters
            List <Integer List>
        Local Variables
            Index = 1 <Integer>
        Actions
            General - For each integer Index from 1 to (Size of List) with increment 1, do (Actions)
                Actions
                    UI - Display (Text(List[Index])) for (All players) to Debug area
    
    Posted in: Miscellaneous Development
  • 0

    posted a message on Character data type

    Is there any way to use the char data type?

    Posted in: Miscellaneous Development
  • 0

    posted a message on Map no longer loads?

    @Fullachain: Go

    When you load the map in the editor, does the editor say there's a problem reading map info? If so, likely this bug here. If you're not getting that map info message, then I dunno.

    Posted in: Miscellaneous Development
  • 0

    posted a message on How to include parenthesis in strings?

    @xhatix: Go

    Yes, exactly that. I looked through all their preprocessor usage in the libraries, but wasn't able to find anything that might be useful. They might have simply never implemented parsing single quotes as force string or escape characters because they didn't anticipate people using function calls in macros...

    I'm attempting to do something similar:

    gf_GroupBases(IntToString(#PARAM(val,") + IntToString("));
    

    More complex than that, but it's the basic idea. If backslash is used:

    gf_GroupBases(IntToString(#PARAM(val,"\) + IntToString("));
    

    After the preprocessor runs, the result of passing 0, 1, 2 is:

    gf_GroupBases(IntToString(012 + IntToString("));
    

    There could very well be some non-standard escape character or method we just don't know about due to it not being used in the game's libraries . . .

    Posted in: Miscellaneous Development
  • 0

    posted a message on How to include parenthesis in strings?

    I noticed Blizzard assigned parenthesis a higher precedence than the double quote character " for their Galaxy Editor trigger parser (the parenthesis are evaluated first, even if they're in a string). How can I include a parenthesis in a preprocessor directive string?

    I tried the standard escape characters \ and /, and the "force string and don't process" operator (single quote) instead of double quotes. I even tried backquotes, none of it worked, the parenthesis were always processed first.

    Posted in: Miscellaneous Development
  • 0

    posted a message on Flag Operators Library (Updated May 20)



    I suppose this is a project so I'm posting here, though it's a library, not a map. Flags are lists of properties you can check-mark, like the "flags" entry of a units in the data editor. The operators are missing from the editor, and are necessary to use bit flag presets, so I created a library of basic functions:

    • Variable - Modify Flags (set, clear, shift)
    • General - For Each Flag
    • General - For Each Flag by Index
    • General - For Each Flag Matching Conditions
    • General - For Each Flag Matching Conditions by Index
    • Conversions - Convert Preset to Integer
    • Index - Index of Single Flag
    • Logic - Flags Match Filters (any, all)
    • Logic - Flags And/Or
    • Logic - Flags Exclusive Or
    • Logic - Flags Not

    All these but "index of bit flag" internally use a concept called macros, so there's no overhead compared to scripting it directly1. I also included an example bit flag preset variable, and functions useful to work around the editor bug with assigning flag values. If you're using one specific preset a lot, you can set the "number of flags" in the For Each Flag functions to default to some function or global where you store the number of flags for your preset.

    Note: The import/export library functions of the editor are broken (hint and grammar text erase when you use import), so follow the method detailed in this post: Library Import/Export Bug

    If you have any questions or problems, just ask.

    Update:

    I've updated the functions using new discoveries of how Blizzard does their macros. I combined several of the functions. Set, clear, shift left, and shift right are now all in the "modify flags" function, for example. I've also categorized the functions with similar functions. All the 'for each' loops are now in the General category with other loops.






    1 With macros, the function calls are replaced by the actual operations when compiled, and the functions vanish entirely - they aren't even defined. You can see this by compiling your map in the script test window. If we had a log<sub>2</sub>x function in galaxy (or any logarithm at all), could make "index of single flag" a macro too.

    Posted in: Trigger Libraries & Scripts
  • 0

    posted a message on Trigger module bug: Custom script action definitions

    Action definitions with custom script option enabled are bugged.

    1. Create a new map
    2. Create a new action definition (menus Data > New > Action Definition)
    3. Enable the custom script option for the action definition
    4. Add the action to a trigger

    Regardless of the grammar text or custom script in the action, all that shows in the UI is:

    Custom Script: (None)
    




    Workaround

    Use the sub-functions option instead of the custom script option, and it works correctly.

    Posted in: Galaxy Editor Bugs and Feedback
  • 0

    posted a message on Give actor/unit no model?

    @s3rius: Go

    I think it's the power splat that shows up (power is the actor, and it's categorized as a splat). The unit in particular is a deployed warp prism, and if I add the no draw flag, the power grid also disappears. My attempts to use the power splat directly have been unsuccessful.

    The invisible unit model is excellent, thank you for mentioning that! Do you know any way to selectively apply it to specific units? I attempted to make the actor itself have the invisible model and then attach the visible one to origin, overhead, and other points using AttachModelToUnit, but that didn't work.

    The purpose of this whole endeavor is to allow multiple people to use the same unit, and since that's likely not possible, simulate it with the method described in my post above. It works fine for various other buildings I use this for, but this particular unit has a power grid I want to remain visible.

    Posted in: Miscellaneous Development
  • 0

    posted a message on [Trigger] Multithreading and AI
    Quote from Toadcop: Go

    The only thing i can mention is that alot context switches (locks) are expensive. so you need wisely to design your threading. otherwise you can even get lower with performance. etc. etc. so actually it's a complex task. but yes it's cool what gaylaxy allows to thread your script...

    Good point. That's why I made the wait between checks have a slight random range to alleviate potential performance hits with many simultaneous accesses; same principal as collision avoidance in ethernet. The frequency and spread of the checks can be varied to balance performance with responsiveness.

    The separate timer and critical section aren't even necessary for this situation, but I included them to give an example of synchronization. It'd be more efficient (and unit responses would look more realistic) for all the threads to simply wait a random 5-10 seconds between processing cycles.


    I was asked a question in PM's, and with the sender's permission I'm reposting my response here.

    Quote from tardcartrider:

    Saw your post on multithreading & AI. First, great post I certainly appreciate it and I'm sure many others do as well. I am very interested in learning more about how to write an AI - specifically unit behaviors for a map that I am working on. Nothing too complicated (yet) I'd like to start with some simple actions like having a high templar cast Psi Storm when he encounters a group of enemies and then retreat during cooldown. I can pick up on a lot of the framework from your post, but obviously not enough to accomplish what I am trying to achieve.

    I am sure you are busy with your own projects (if you're looking for more let me know =P ), so I would like to know if you know of any other resources that would help me to learn this. Thanks again for the post you made and I would appreciate any other information you can point me in the direction of,

    TC




    Well, here's what I'd do off the top of my head. It might not be the most efficient method since my experience is with other things, not really any in-depth AI, but this is some basics that might help.

    A global preset (data > new preset) like this:

    Action
        Value Type: Integer
        Values
            Advancing
            Retreating
    

    In the AI action, create local variables like these:

    • Current Action <Action>
    • Target <Point array[2]>
    • Nearby Units <Unit Group>

    Then in the "core AI" section indicated in the tutorial, add actions like these:

    switch (Current Action)

    • if (Advancing)
      • set Nearby Units = all enemy units within (sight range of templar)
      • if (number of units in Nearby Units > somenumber) and (templar has enough energy)
        • cast psi storm on (random unit from Nearby Units)
        • set Current Action = Retreating
        • set Target[Retreating] = pick some point, could be directly away from Target[Advancing]. To calculate distance, you can get the cooldown of psi storm and movement speed of the templar, and time * speed = distance. I think the Data Table functions might be able to do it directly, or you could store them in variables.
        • wait 2 seconds or so for psi storm to cast
        • order the templar to move to Target[Retreating]
      • else
        • order templar to move to Target[Advancing]
    • if (Retreating)
      • if (distance from position of unit to Target <= some range)
        • set Current Action = Advancing
        • order templar to move to Target[Advancing]
      • else
        • order templar to move to Target[Retreating]

    You'll also want to put your stuff in there telling the unit what point it should be advancing to and such, check if its psi storm target is visible, maybe even loop through all NearbyUnits to check if a certain number of units are around that picked unit, to make sure Psi Storm would be effective there. There's a "center of unit group" function that could be useful for that. Depending on your map terrain, you might also need to be careful with picking the Target[Retreating] so your unit doesn't try to go up cliffs or somewhere else inaccessible. There might be a way to do some of this with orders directly, but after looking into that a bit it seemed difficult to set up, so I went with simple presets.

    You can send your unit AI instructions from outside the function by using custom values on the unit (set unit custom value action). I'd create another preset to store the indexes of various things you might want to use to control the unit, like this:

    Custom Unit Value Indexes
        Value Type: Integer
        Values
            Advance Point X
            Advance Point Y
    

    Then set those custom values from outside the function (set custom unit value "Advance Point X" to somevalue) and read them from inside the function (set (X of point Target[Advancing]) = custom unit value "Advance Point X").

    I don't really know where to find a general guide to AI, but you can probably locate a lot of info with google searches. Sorry I can't help you more, my knowledge is mostly with other things, not AI specifically.

    Do you mind if I copy this into the thread for others with similar questions?


    Posted in: Tutorials
  • 0

    posted a message on Trigger module bug: Defining variables causes crash

    The specific combination of variables in the attached map below causes the game to freeze, then crash, immediately after the loading screen. If a single one of the variables are removed (or the variables are used on a different map!) the freeze does not occur. It's some combination of events here that's causing a game crash bug to occur.

    PlayerGroup = (Empty player group) <Player Group[16]>
    Record1Type
        Variables
            UnitGroup = (Empty unit group) <Unit Group>
    Record2Type
        Variables
            Timer = (New timer) <Timer>
            UnitGroup = (Empty unit group) <Unit Group[20]>
            Record1 <Record1Type[40]>
    Record3Type
        Variables
            Record2 <Record2Type[20]>
    Record2 <Record2Type[21]>
    Record3 <Record3Type[21]>
    Timer = (New timer) <Timer[20]>
    UnitGroup = (Empty unit group) <Unit Group[20][20]>
    

    There is nothing else in the trigger module, and the script generated by the trigger editor can be seen below. No custom script is used.

    The names don't matter, I changed them to these generic names for demonstration purposes. Needless to say, this took hours to narrow down out of all the variables and triggers I had in my map. Easily the most bizzare bug I've seen so far!

    //==================================================================================================
    // 
    // Generated Map Script
    // 
    // Name:   Storm the Base
    // Author: Zerahan & Thalassicus
    // 
    //==================================================================================================
    include "TriggerLibs/NativeLib"
    
    //--------------------------------------------------------------------------------------------------
    // Library Initialization
    //--------------------------------------------------------------------------------------------------
    void InitLibs () {
        libNtve_InitLib();
    }
    
    //--------------------------------------------------------------------------------------------------
    // Global Structures
    //--------------------------------------------------------------------------------------------------
    struct gs_Record1Type {
        unitgroup lv_unitGroup;
    };
    
    struct gs_Record2Type {
        timer lv_timer;
        unitgroup[21] lv_unitGroup;
        gs_Record1Type[41] lv_record1;
    };
    
    struct gs_Record3Type {
        gs_Record2Type[21] lv_record2;
    };
    
    //--------------------------------------------------------------------------------------------------
    // Global Variables
    //--------------------------------------------------------------------------------------------------
    playergroup[17] gv_playerGroup;
    gs_Record2Type[22] gv_record2;
    gs_Record3Type[22] gv_record3;
    timer[21] gv_timer;
    unitgroup[21][21] gv_unitGroup;
    
    void InitGlobals () {
        int init_i;
        int init_j;
        int init_i1;
        int init_i2;
    
        init_i = 0;
        while (init_i <= 16) {
            gv_playerGroup[init_i] = PlayerGroupEmpty();
            init_i = init_i + 1;
        }
        init_i = 0;
        while (init_i <= 21) {
            gv_record2[init_i].lv_timer = TimerCreate();
            init_i1 = 0;
            while (init_i1 <= 20) {
                gv_record2[init_i].lv_unitGroup[init_i1] = UnitGroupEmpty();
                init_i1 = init_i1 + 1;
            }
            init_i1 = 0;
            while (init_i1 <= 40) {
                gv_record2[init_i].lv_record1[init_i1].lv_unitGroup = UnitGroupEmpty();
                init_i1 = init_i1 + 1;
            }
            init_i = init_i + 1;
        }
        init_i = 0;
        while (init_i <= 21) {
            init_i1 = 0;
            while (init_i1 <= 20) {
                gv_record3[init_i].lv_record2[init_i1].lv_timer = TimerCreate();
                init_i2 = 0;
                while (init_i2 <= 20) {
                    gv_record3[init_i].lv_record2[init_i1].lv_unitGroup[init_i2] = UnitGroupEmpty();
                    init_i2 = init_i2 + 1;
                }
                init_i2 = 0;
                while (init_i2 <= 40) {
                    gv_record3[init_i].lv_record2[init_i1].lv_record1[init_i2].lv_unitGroup = UnitGroupEmpty();
                    init_i2 = init_i2 + 1;
                }
                init_i1 = init_i1 + 1;
            }
            init_i = init_i + 1;
        }
        init_i = 0;
        while (init_i <= 20) {
            gv_timer[init_i] = TimerCreate();
            init_i = init_i + 1;
        }
        init_i = 0;
        while (init_i <= 20) {
            init_j = 0;
            while (init_j <= 20) {
                gv_unitGroup[init_i][init_j] = UnitGroupEmpty();
                init_j = init_j + 1;
            }
            init_i = init_i + 1;
        }
    }
    
    //--------------------------------------------------------------------------------------------------
    // Map Initialization
    //--------------------------------------------------------------------------------------------------
    void InitMap () {
        InitLibs();
        InitGlobals();
    }
    

    Attachments

    Posted in: Galaxy Editor Bugs and Feedback
  • 0

    posted a message on [Trigger] Multithreading and AI

    @UmbraLamina: Go

    Good point UmbraLamina and thank you, that's something I forgot to mention. If there's a need for more than 1 type of lock in a thread, it's a good idea to research advanced topics in multithreading - can check the wiki articles and other resources for starters:

    http://en.wikipedia.org/wiki/Multithreading
    http://en.wikipedia.org/wiki/Deadlock

    If a thread only requests 1 type of lock (like the examples in the tutorial), there's no worry of deadlocks, since circular waits like described above won't occur. Requesting and releasing the same lock several times in a thread is ok too.

    Posted in: Tutorials
  • 0

    posted a message on Validator error messages

    I'd like to also get rid of some other error messages (like 'need more supply')... it's really unfortunate all validator errors appears to be hardcoded. I haven't found anything that might be able to change them in weeks now.

    Posted in: Miscellaneous Development
  • 0

    posted a message on Give actor/unit no model?

    @xenrathe: Go

    Ahh.

    Well, what I have is 1 visible unit, and on top of its position, 1 invisible unit of the same type for each player. The visible one selects the appropriate invisible one. Ideally I'd like to do it with just one unit/actor/etc... so as to not spend two hours duplicating a half dozen units and trying to ensure all the actors are appropriately linked.

    Posted in: Miscellaneous Development
  • To post a comment, please or register a new account.