Sprucing up the Official documentation


  • Developer

    We’re working on sprucing up the official SDK documentation. The idea of the documentation is still mostly to complement the many UE3 editor tutorials out there. Any suggestions would be appreicated.


  • Developer

    Also, for a more specific request: we’re going to throw all the resources we can think of onto https://tornbannerjira.atlassian.net/wi … +Resources ; please post anything you’ve found useful so we can include it on here.



  • Why don’t you allow forum users to edit it?
    It would make it much easier for the community to contribute with your documentation.


  • Developer

    Confluence isn’t well-suited to public editing. Among reasons, we pay for it on a per-user basis. If the community wants to host a public wiki we’ll be happy to link to it.



  • That is a nice update for the SDK folk. Of course a list of remaining issues/enhancements for the SDK to go live would be nice too.



  • @gregcau:

    That is a nice update for the SDK folk. Of course a list of remaining issues/enhancements for the SDK to go live would be nice too.

    +1

    At least give us some info when (approximately) will you release the juicy SDK. Pretty please.



  • Something that I came across months ago and was a pain in the ass to track down.

    If you declare a method such as:

    function MyMethod(optional string ExtraPar = "");
    

    And pass ExtraPar as a string longer than the optional parameter, UDK will crash with a buffer overflow.

    The syntax is correct and the compiler will give you no warnings, but apparently because of some mistake with memory reallocation you will find yourself with an access violation.

    Declaring the same method with the optional string uninitialized will not cause this problem.

    function MyMethod(optional string ExtraPar);
    

    So I guess in the event where you need an initialized optional string and your call can pass a string longer than the optional value, you should do something like this:

    function MyMethod(optional string ExtraPar)
    {
    
        if (ExtraPar == "")
            ExtraPar = "DEFAULT";
    
    }
    

    I assume this would be an useful information for your wiki, as it can be very tricky to track down the source of those crashes.



  • I took a look at your example project at https://github.com/BradyBrenot/swords-and-jetpacks and I have a suggestion here.

    You could use the same trick I did with one of my mods to avoid replicating the same code over and over again and prevent teamworking problems by using the don’t repeat yourself philosophy.
    The code is still replicated, but it will be replicated by the preprocessor, not by yourself.

    https://github.com/GreatOldOne/CMWTKP/tree/Testing

    I forgot to add include guards, but eventually I’ll get to it.


  • Developer

    Yeah, I believe someone else described doing something similar (Nabster?). It makes sense. My project is probably not the best example, unless you’re just looking at the most superficial differences between Chivalry and UDK.



  • @CrustaceanSoup:

    Yeah, I believe someone else described doing something similar (Nabster?). It makes sense. My project is probably not the best example, unless you’re just looking at the most superficial differences between Chivalry and UDK.

    Indeed, includes are basically essential for multiple game-mode mods since we can’t edit the base classes. It can get quite messy, though. For example, attempting to overwrite a method in your “psudeo base class” include file will trip you up (and you have to do some crazy method specific include guard type stuff). Oh and any “base” variables you want to add doesn’t work too well either thanks to UnrealScript having the lovely requirement of placing all your declarations right at the top!

    I’m not sure whether he went for it in the end but I suggest to Knil an alternate solution where you create a kind of buffer classes for includes. That way you can stick all your base content in those and when you come to making other alterations it doesn’t get in the way. It’s definitely not perfect though - 2 new class files for each class you want to inherit starts to get ridiculous with things like base weapon mods.

    I was thinking about making a sort of mod-friendly interface with the pseudo-base include classes all set up but I never got around to it.



  • @NabsterHax:

    Indeed, includes are basically essential for multiple game-mode mods since we can’t edit the base classes. It can get quite messy, though. For example, attempting to overwrite a method in your “psudeo base class” include file will trip you up (and you have to do some crazy method specific include guard type stuff). Oh and any “base” variables you want to add doesn’t work too well either thanks to UnrealScript having the lovely requirement of placing all your declarations right at the top!

    Since the preprocessor runs before the compiler, you can simply subclass the class that includes your headers and just override from there.

    As for class or instance variables in multiple headers, you can have a header just for variables (always included first).

    @NabsterHax:

    I’m not sure whether he went for it in the end but I suggest to Knil an alternate solution where you create a kind of buffer classes for includes. That way you can stick all your base content in those and when you come to making other alterations it doesn’t get in the way. It’s definitely not perfect though - 2 new class files for each class you want to inherit starts to get ridiculous with things like base weapon mods.

    I believe you are talking about abstract classes.
    In any case, I’m talking more about propagating similar or equal code to multiple base classes that are outside our scope.
    It’s certainly not a C/C++ preprocessor. However, it’s not as problematic as you seem to think.
    You can use if and else to control which code should be introduced into your class, and define your own macros before including said headers to tell the preprocessor exactly how we should be including them.

    Example, include all our variables first:

    class MyClass extends AOCGame;
    
    `define IMPORT_DEFINITIONS
    `include(header1.uci)
    `include(header2.uci)
    `include(header3.uci)
    `undefine(IMPORT_DEFINITIONS)
    
    `define IMPORT_VARIABLES
    `include(header1.uci)
    `include(header2.uci)
    `include(header3.uci)
    `undefine(IMPORT_VARIABLES)
    
    ... MyDefs
    ... MyVars
    
    `define IMPORT_METHODS
    `include(header1.uci)
    `include(header2.uci)
    `include(header3.uci)
    `undefine(IMPORT_METHODS)
    
    ... MyMethods
    
    `define IMPORT_DEFAULTS
    
    DefaultProperties
    {
    
    `include(header1.uci)
    `include(header2.uci)
    `include(header3.uci)
    ... MyDefaults
    
    }
    
    `undefine(IMPORT_DEFAULTS)
    
    class MyClass extends AOCGame;
    
    `define GAMEMODE MyClass
    
    `define IMPORT_ALL
    `include(DefaultClass.uci)
    `undefine(IMPORT_ALL)
    
    `define HEADER_DEFINITIONS
    `define HEADER_VARIABLES
    `define HEADER_METHODS
    `define HEADER_DEFAULTS
    
    `if(`notdefined(IMPORT_ALL))
    
        `if(`notdefined(IMPORT_DEFINITIONS))
            `undefine(HEADER_DEFINITIONS)
        `endif
    
        `if(`notdefined(IMPORT_VARIABLES))
            `undefine(HEADER_VARIABLES)
        `endif
    
        `if(`notdefined(IMPORT_METHODS))
            `undefine(HEADER_METHODS)
        `endif
    
        `if(`notdefined(IMPORT_DEFAULTS))
            `undefine(HEADER_DEFAULTS)
        `endif
    
    `endif
    
    /* DEFINITIONS */
    
    `if(`isdefined(HEADER_DEFINITIONS))
    `if(`notdefined(INCLUDED_HEADER1_DEFINITIONS))
    `define INCLUDED_HEADER1_DEFINITIONS
    
    ... defs (enums, structs)
    
    `endif
    `endif
    
    /* DEFINITIONS */
    
    /* VARIABLES */
    
    `if(`isdefined(HEADER_VARIABLES))
    `if(`notdefined(INCLUDED_HEADER1_VARIABLES))
    `define INCLUDED_HEADER1_VARIABLES
    
    ... vars
    
    `endif
    `endif
    
    /* VARIABLES */
    
    /* METHODS */
    
    `if(`isdefined(HEADER_METHODS))
    `if(`notdefined(INCLUDED_HEADER1_METHODS))
    `define INCLUDED_HEADER1_METHODS
    
    ... methods
    
    `endif
    `endif
    
    /* METHODS */
    
    /* DEFAULTS */
    
    `if(`isdefined(HEADER_DEFAULTS))
    `if(`notdefined(INCLUDED_HEADER1_DEFAULTS))
    `define INCLUDED_HEADER1_DEFAULTS
    
    `if(`isdefined(IMPORT_ALL))
    DefaultProperties
    {
    `endif
    
    ... DefaultProperties
    
    `if(`isdefined(IMPORT_ALL))
    }
    `endif
    
    `endif
    `endif
    
    /* DEFAULTS */
    


  • @Cthulhu:

    Since the preprocessor runs before the compiler, you can simply subclass the class that includes your headers and just override from there.

    As for class or instance variables in multiple headers, you can have a header just for variables (always included first).

    I think this is essentially what I suggested Knil should do: class for headers (headers which are essentially base code modifications) then subclass those classes with your specific alterations. The only problem with this is that if I want to make base modifications to, say AOCWeapon code across all weapons, then I will need 30+ new header classes and another 30+ subclasses if I want to make weapon specific alterations (which I do for Chiv+). It just seems a bit excessive.

    In any case, I’m talking more about propagating similar or equal code to multiple base classes that are outside our scope.
    It’s certainly not a C/C++ preprocessor. However, it’s not as problematic as you seem to think.
    You can use if and else to control which code should be introduced into your class, and define your own macros before including said headers to tell the preprocessor exactly how we should be including them.

    This is the solution I am currently using for Chiv+, though not in a particularly standardised way as certain problems only appeared later on. I’ve not run into too many instances where I need to override my headers but when I do it’s pretty easy to just stick in the preprocessor shizzle. Still, it’s not really too elegant, in my opinion.

    Either way, in any sort of “clean” system you end up with a crap load of files for something you’d ideally want to get done in half the amount.



  • @NabsterHax:

    I think this is essentially what I suggested Knil should do: class for headers (headers which are essentially base code modifications) then subclass those classes with your specific alterations. The only problem with this is that if I want to make base modifications to, say AOCWeapon code across all weapons, then I will need 30+ new header classes and another 30+ subclasses if I want to make weapon specific alterations (which I do for Chiv+). It just seems a bit excessive.

    You should use a set of macro flags to customize your code without the need of overriding.

    function MyMethod()
    {
    
        ... // Base code that should be included within all classes.
    
        // Specific code that should be included only if the class requests it.
    
        `if(`isdefined(FLAG1))
    
        ...
    
        `endif /* FLAG1 */
    
        `if(`isdefined(FLAG2))
    
        ...
    
        `endif /* FLAG2 */
    
        `if(`isdefined(FLAG3))
    
        ...
    
        `endif /* FLAG3 */
    
        ... // Base code that should be included within all classes.
    
    }
    

    And while yes, this isn’t such an elegant approach, but considering how shitty Unreal Script is and even more limitations being placed by the SDK, this doesn’t look that bad.

    In C/C++, macro abusing can lead to a nightmare of code managebility and maintainability. It should apply to Unreal Script aswell, so use it wisely.



  • @Cthulhu:

    You should use a set of macro flags to customize your code without the need of overriding.

    Sorry if I wasn’t clear - this is what I already do. :)


Log in to reply