Mostly Harmless

Legacy:Aphelion/Developer Journal

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search

Journal of a Mod making coder

Introduction[edit]

So I saw this page of journals and thought, wtf, I'll write something. After all, I've recently started writing for a mod that's going to come out for UT2K3. Yes, it's a while off, but there's the whole gametype to write for this mod and that's my task. Oh well, to start from the beginning...

The mod is Unreal Command, or uCOM for short. It was started a while ago by an ex-member of the UnrealFortress mod, which I had fun playing and for which I learnt UScript so I could modify the gameplay, create map objects for one or two maps I tried to make and generally see if I could learn a whole language as a challenge. Anyway, after a while wondering what I was going to do with my extremely non-elite coding skills, I was pointed in the way of uCOM by a friend, Highlander, who promptly joined the team shortly after me (which was nice).

The aim of the mod is to create a mod with a commander for each team. This commander issues orders, builds vehicles and generally is the boss. He has a load of unwitting recruits to his cause, members of his own team who are the grunts, who he gets to order around and fight for him/her, alongside and possibly in the vehicles. Sort of like RTS meets unreal.

Anyway, after looking at the mod, liking what I saw, I looked at the page of team members and, lo and behold, they needed a coder. Well, I thought, this sounds good, apart from the experience bit. Oh well, I send off an application emial with all that I know and can do on it and find, to my amazement, that I'm a developer, just like that, welcome to the team. Bit surprised, the e-mail back said that I had experience in all the things they lacked, like gametypes and coding map actors. Well, that was a bit surprising. Anyway, my task lay before me! To code the gametype and map actors for uCOM. And this is where the journal begins...

Now what have I let myself in for![edit]

Well, there I'm sitting, realising that I have been lumbered with a mass coding effort. Good stuff, and I was planning to do lots of work this summer for my physics degree... Oh well! So the mod is for UT2K3, a game that hasn't been writen... This puts a dampener on things, especially as I have an attention span the size of a goldfishe's! But for now, I have to do something, before all my raw enthusiasm is used up!

So, question 1: How similar will the gametype code in UT2K3 be to UT?

Completely uninformed opinion: Well, they can't actually change THAT much, can they? The code was pretty simple and had not too many limitations... Well, to my inexperienced eyes. But they could change the subclasses and so on. So, first move, why not list the functions in GameInfo, assume that they have to have the same or stuff that fufills similar functions and then go for it in UT1!

Yey!, after looking at the code it seems this was a good move, lots of functions, they all do obvious things like restart the game and find you start locations, so even if the specifics are different, the thought's go to be the same in UT2K3... right?

Ok, by now, Highlander (High for short) had joined the team. A few words about him, because he becomes important here. Highlander is a prolific and (in my opinion) good mapper, who learnt how to code because he knew other programming languages and set me my first major task for one of his maps. After I showed and explained the code I wrote, Highlander went out and found some sites for learning UScript and, of course, was from that day, a fairly competent coder without really trying... Anyway, one problem (or should I say fun thing) is that High is always coming up with crazy whacked ideas continually, then actually trying to get them to work. This means he has come to continually but his head against the UT1 engine's limits, and done some impressive things including skyboxes that are dangerous to gameplay (i.e. you stop and go, "ooh, pretty skybox" kersplat!!!!). Anyway, with him on the team, the uCOM gamecode had better be flexible, very flexible, because if it wasn't High certainly would be coming to me and bugging me to do stuff (or, coding it himself, depending on what) later on and not being able to strut his funky stuff. So that's one thing I need to think about. Flexibility...

On top of everything, despite being made a member of the design team, CE (that's Cyber-Emperor for non-lazy people), our illustrious leader, had barely exchanged more then 2 words with me about what the hell was going on. So, with only the website to go on, and CE off on a short break of a few days, flexibility seemed like the way to least get into trouble... :-)

Next problem is thinking about the design... How to design the gametype. Well, UnrealFortress had a mapinfo. The gameinfo subclass uses the mapinfo to achieve different gametypes with only one gameinfo subclass. Nice idea. Unfortunately, messy and a lot of work to replace lots of mapinfo code... However, the idea had hit me before that it would be nice to have a mapinfo where most of the gameinfo code was called from. Definitely something a mapper/coder like High could have fun with. But what about straight mappers, they'd want to create their own gametypes and not code anything. Then the idea hit me! Use objects for each and every function in the gameinfo. Each object could be placed in the map and at startup the mapinfo could detect each of these objects (rule modules I called them) and the gameinfo could call them through the mapinfo. Then mappers could mix and match gametypes, and assault restart here, a CTF objective there, domination like scoring, whatever!

Then, what really clinched it was the fact that, with such modular code, I could transfer lots of it direct to UT2K3. I was well pleased with myself... :-) Then I realised a flaw... Modular bot AI. This could work well, or it could go catastrophically wrong. Oh well, may aswell try...

So, with this in mind I started coding...

Highlander: See all the trouble i caused? and the skybox wasnt that purty I just went overboard with the attach movers. And yes i guess it is my fault that Aph started coding in uscript. (Just dont hurt me ok.. it was an accident :P)

Starting to code a mod[edit]

Well, there I am sitting in front of UnrealEd looking at the gameinfo subclasses thinking, well, here I am, having to write a mod... It's a pretty daunting bit, you know, when you have nothing there... And making the first step aswell, secure in the knowledge that whatever you do, somewhere along the way, if your mod becomes popular, you're going to be regretting every little thing you didn't think about properly along the way...

Actually going through GameInfo earlier and writing down all the functions helped a heck of a lot. With that done, and what they did (more or less), it was easier to see what I needed to achieve, what my code was actually going to do. So I made the first big decision, where to subclass this new mod... Well, since it was a team mod, the answer seemed simple enough, TeamGamePlus looked damn good...

Starting to code though, still was quite hard. There was lots of "and I'll reference to this actors which... doesn't exist yet..." concrete examples being the mapinfo and map objectives. However, comments are a coder's best friend. When the greatest impediment is design, writing lots of comments and very little code may seem as not making much progress, but it helped me to cut the ice and get the brain going as to HOW exactly everything was going to work...

Jumping to other actors soon provided the stimulus to uncomment many lines of code that referenced to them, but my code was getting unwieldy and I gave up commenting anything that didn't exist yet, so my code became uncompilable... Given that people say to compile your code every few lines, this, I thought, was not good...

I said above that the idea to modularise had hit me suddenly, and in a way it had, but it wasn't clear until I started work on the MapInfo itself. At this point I started creating the basis of what really would be the mod. In effect, it had been a bit of a mistake to start with the gameinfo, because, with the mapinfo going, I knew how I was going to code it all and had to go back to the gameinfo and practically wipe most of it. Still it was progress and I got to where I am about now.

Anyway, I think I've managed to nearly catch up with the present enough to start a day by day (or near enough) journal, which is how this will progress from here...

15/08/02 Start of Journal in day by day=[edit]

Writing descriptions of your code for complete non-coders should be easy, no? Well, that's what I thought... But that's not what I discovered. Having writen lots of this modularised code system, I thought I'd better write a technical document describing how to create maps with this thing... Not only would this be useful down the line, but it would allow me to put down in black and white what I was going to do and allow me to compose my thoughts a bit more.

Well, the major difficulty I encountered today was just trying to describe this situation to a non-coder:

The mapinfo at startup searches for the objects that contain the functions for the gameinfo. Each of these objects is a subclass of uCOM_RuleModule which is how I search for them in the level. Now, the subclasses of uCOM_RuleModule are in themselves useless, because they are again subclassed and exist there only for me to use as a variable to refer to when discussing any of the subclasses in the code. However, how do you explain this to a mapper who doesn't code? Hell, I don't think I explained it well here either! I tried an explanation along the lines of branches of the actor tree (go down this branch...). Anyway, considering I thought I had most of the technical document laid out in my head, enough for me to write it, such a thing seemed a really odd problem to crop up... I really can't wait to give this to one of our mappers who's cold on this and see them fall flat (especially on what, I'm sure I'd be very surprised at someof the things they'd find incomprehensable). Which'll be good, because once I set them straight, they can rewrite it for their own kind and then no one else will!

15/08/02=[edit]

Well, people who see this entry are going to think that I screwed up on the date. Not so! Unfortunately, and I think in common with many other coders from what I hear, I have a screwed sleeping pattern. I've been to bed and gotten up since last update. I imagine this won't be the first or last time, so I beg the reader's indulgence...

Since last update, I haven't really done much coding. However, I have been reading some more of this page, which I am eternally grateful that Highlander showed me some weeks ago (and which I only properly got into 4 days or so ago). The sections are Mychaeel/Modding_Etiquette and Mychaeel/Mod_Startups. Basically, they're about how to behave with the general public with your mod (modding etiquette) and homw to get people to join your team when you have a good idea... Anyway, I thought the question of why I joined uCOM probably is a good one.

Well, for one thing, I'd been thinking I wanted to join a mod team somewhere. I thought that writing mutators for Unreal Fortress and generally coding a bit, made me think it would be fun to mod. Well, the link to uCOM was passed to me by Highlander. First thing going for it was that it had a nice website. I realsie that in the guide by Mycheal it says that's one thing you can't really trust is a nicely made web-page, because it doesn't say anything about the game-design abilities of the designer. However, this one was different IMO. It spoke of a level of care, firstly, as it was very finished. It also said the game designer could do graphics! Also, I realise, it really said that the whole page was organised and so the person behind the website would definitely be someone who, whether or not they had any modding ability, be able to grab servers, push the mod etc.

Secondly, there were already people on the team, and people in the forums. These were both good things IMO. It meant other people had already been swayed and people already cared about the mod.

Thirdly, the leader of this project was CE, who had been in Unreal Fortress and left, had made some of the maps that I constantly played on and so I knew was able. On top of that, he was brother to the person who'd led Clan Cannon Fodder, the Unreal Fortress clan I was in, who was also in the Dev team. Now, I dunno what it is about clan leaders, but they're usually not the most exceptionally brilliant people in the chosen game the clan participates in. However, they have something rarer, leadership... So, in that sense, the mod looked like it was on a sound footing in terms of all the little factors beyond actual raw modding talent.

26/08/02[edit]

Back from a big break, part of it completely unexpected :) I was randomly asked by my girlfriend, who went on this scheme run by Oxford University to improve the numbers of state school and ethnic minorities applying to it, to help them out for a week because they were a person down. For some reason Oxford has a reputation for exclusivity that is very, very undeserved. Unfortunately, this reputation is self-perpetuating. Not too many ethnic minorities or state school people apply because of the reputation, so there aren't too many of them in the unversity, so everyone thinks Oxford's reputation is deserved... Were any bright person from England be reading this, wondering whether they should apply or not, I'd unhesitatingly answer, yes!!!! If you can get nearly all As at A-Level, then nothing should stop you!

Well, anyway, time to move on from that little side-track.

DJPaul: Yeah, getting all As is easier said than done :). I've recently got a series of straight Cs at AS level, and am hoping to get one upgraded to a B because the exam boards mark silly :).

Aphelion That was a pretty mess with the exam boards... Hope it didn't cost you any Uni places...

DJPaul: Nup, I may go to Uni. next year. Or sloth off.

UT2003 Relased, Start of Actual Mod 03/10/02[edit]

I'm Back[edit]

Well, UT2003's been released, today in my part of the hills, but I already have the classes and can begin to code, hopefully get the game today though :) Anyway, I've been a bit absent from this journal for a while. I think it's hard to maintain something like this. I've always never managed to maintain a diary ever :)

Anyway, I'd thought I'd start from here a bit more rigorously. The mod's website is http://www.unreal-command.com just so you know what the mods about. From here on, hopefully there'll be more information about the mod and the coding problems I face and overcome (so should get some tutorial sections out of this, hopefully) and a bit more about writing large chunck of code.

Importance of Planning[edit]

Well, I'm sure anyone who's read this far may be wondering, did the writing of the code in UT help at all? To that, I have to say emphatically, yes.

First off, the code of the UT2003 GameInfo was similar to the UT one in many ways. So this guess had paid off and this was good. However, I designed a nice system to modularise the UT1 GameInfo, and so had Epic, in a different way, that's incompatible. I have to face the choice that the GameRules may not work with uCOM and spend time thinking about overcoming this.

Despite this problem, coding in UT1 was still good as it had given me the idea of HOW I wanted to code the Gametypes of the mod. By that I mean, not the code itself, but the philosophy behind it. In short, I had some kind of plan behind my motivations.

Secondly, any method of tackling a problem has its own disadvantages compared to other methods. But, it's easy to forget that each method has advantages aswell, advantages that one may not forsee... So, by coding, I found out a few things that were not obvious. By coding the gametypes modularly, it would be exceptionally easy to change gametype midway. This is an alright thing to have, but really, it would be more useful to have in campaign type RTSs, where one map determines the outcome of the next. I realised that wouldn't be hard to add in extra.

These kind of things, are the type that crop up as you code, and I found by coding, I got to spot the above, and a few other things. Problem with cropping up as you code is that it's unplanned. However, I've not yet started to code and I know how it works, have talked it over with others at the mod and know how it will be implemented. I think this is good and saves being messy.

10/10/02 The big blank page... 2-team limits[edit]

Above, I said starting wasn't easy. Well, I've got the big blank page before me once again. The main initial problem I've faced before even starting to code is that the UT2003 Team game code doesn't support more then two teams. This seems a bit limiting to me. First off, uCOM really should have support for four teams. It doesn't really need it yet and there arent big plans to have 4 team games, but the option should be there... On top of that, uCOM needs to have civilians and there should be something for map specified extras, so that's 6 teams in all uCOM needs to see. This means I must resort to using Deathmatch as superclass of the mod gamecode or dump these ideas for >2 teams. Personally, I don't like having that level of inflexibility and the existance of arrays like TeamInfo[2] would make it hell to extand later on, so I'm going for the second options.

Thus, my first start is to copy the teamgame code into my uCOM_GameInfo (that's the name of my GameInfo derivative class) and see where the limiting number 2 crops up in both properties and functions:

  • var UnrealTeamInfo Teams[2]
  • var RedTeamName, BlueTeamName: Used for loading premade teams. More for the single player I guess.
  • var TeamAIType[2]
  • var TempSymbols[2]: Note, there is also TeamSymbols[2] in GameRepInfo.
  • function PostBeginPlay: Creates settings for Teams[i]
  • function OtherTeam: Returns the other team, useless if >2 teams
  • function Preloadbots: Accesses functions in each Teams[i]
  • function GetBlueTeam: Creates a TeamInfo for the blue team. Mainly single player part
  • function GetRedTeam: Calls super with EnemyRosterName being the same as RedTeamName, so look up that in DeathMatch.
  • function InitGame: Inits the TeamAIType. Parses options for red and blue team names and symbols
  • function RestartPlayer: balances teams with bots.
  • function NotifyKilled: Accesses Teams[i]
  • function CheckEndGame: Works out winner between 0 and 1.
  • function GetBotTeam: Explicitly references each TeamInfo
  • function FindTeamFor: Calls functions in Teams[i]
  • function PickTeam: Another sorting function which just sorts out which team is bigger and picks the smaller team.
  • function PlayEndOfMatchMessage: Accesses Teams[i]
  • function FindTeamDesignation: Accesses Teams[i] in the GameRepInfo. Means GRI needs to be recoded too...
  • function FindNewObjectives: Again, accesses Teams[i], would need to be extended.
  • function AnnounceScore: Sorts out teams into scoring team and other team (a concept that's not going to work in >2 teams). Then works out what messages to send (e.g. taken the lead if scores were equal)
  • function PostLogin: Announces teamchange of a newly entered player, switches between 0 and 1

Well, that's it. Other segments that need to be changed include the GameRepInfo but, as pointed out by Flashman below, there's likely to be more...

Flashman: Just a word of advice: i've been reading different bits about the player models in UT2k3, and the fact that team skinning might be a limitation: only two team skins? If this is also the case (I'm no expert mind) you might want to check out any classes that deal with the Player itself - if there's going to be too much work (including getting your team to make new skins and player models if they arent already) just to get >2 teams in the game?

Aphelion: Thank you for your advice. It's worth looking into. Currently, I'm not too bothered, because uCOM will only have to work with 2 teams in the beginning. Any code now is trying to save work in the uCOM_GameInfo later on. Later on, though, if what you say is true.... As I find any errors, I'll post them up. I'm pretty sure given the big discussion about creating a new unified MCTF mod, noneof this will be wasted. At worst, anyway, we can have 2 textures, because we can get away with it as the textures are different for each team in not just colour (both teams look radically different, as you might expect from an RTS mod :) ) and then use labelling and lights and so on. In fact, thinking about it, that could just be the quickest solution... Hmmm... /me goes away to think.

17/10/02[edit]

Finished looking at TeamInfo. Will start coding the uCOM_GameInfo now... Damn my uni work.... Everyone else in uCOM is so far ahead of me now...

08/12/02 Converting strings to names, other random pieces of info[edit]

Although there's not been much in this journal, I've been doing some coding in among the mass work of Uni and, at least until next term and my dreaded finals, I'm free! Anyway, time to write down any random bits of useful info I can think of:

Converting Strings to Names:

Highlander needed to change a string to a name and talked to a few people about it, advice ranging from dunno to native coding (!?) solutions were flung his way. There is a simpler way, so here it is:

In object, there's a functions defined called SetProperty( string, string). What this does is set any property in a UScript class based on the name of the property (in string format) and it's value (in string format). This works for names. So, if I want to set the name variable Tag to a string variable called TagString, I need to simply do the call Self.SetProperty( "Tag", TagString ).

TeamGame Garbage:

Most of the TeamGame class is just unneccessary. I'm saying that just in case you find yourself subclassing the deathmatch class to get more teams and wade through tons of intimidating code. Most of the TeamGame stuff deals with the single player game and team rosters and contains lots of code that's easy to get lost in. So, in case you're some unfortunate sod in the position of going through that, don't get downhearted and remember that the InitGame (to set start variables), the ReduceDamage (how else do you not kill your team mates?) and the scorekill (to win) are really the heart, plus some crap to create TeamInfos...

01/02/03[edit]

Well, this is a bit of a unique date to write down in European format, probably ausipcious or something, then again maybe not.

Been away from this journal for a while. Main reason is I want to write something useful, but then I've only been doing grunt level codework for the mod. Anyway, recently I delved into the GUI code so I think I have some stuff to write about.

GUI[edit]

Overview of the GUI:

The GUI classes are all of those that extend from GUI which subclasses Object. GUI itself is just an organisational class containing some structs but is subclassed by three child classes:

  1. GUIComponent
  2. GUIFont
  3. GUIStyles

GUIComponent is the actual class that the graphical menus and in-game menus of ut2003 are made out of and as its name suggests, corresponds to actual components in the menu, like buttons, images, lists and arrows.

GUIFont contains information about fonts. Used when specifying fonts in GUIComponent.

GUIStyles contains information about how a particular GUIComponent should be displayed. Display information (like fonts and images) comes in arrays, each array element corresponding to one focus states. More about focus lower down.

GUIComponent:

As mentioned, all items displayed on the screen in a menu are [GUIComponent]s. This includes the page for example. However, a page has many buttons, check boxes and images embedded into it. Also, there are other user interface elements that a user would consider to be one item but can in fact be made out of many other GUIComponents like GUIComboBox which is a drop down menu made up of an edit box, a down arrow and a list. Such multi-component systems are made out of GUIComponent's subclass GUIMultiComponent.

GUIMultiComponent:

This class operates by having a dynamic array called Controls which is of class GUIComponent. Thus lots of components can be embedded into a single GUIComponent itself and this is how menu pages and tabs are built, along with other multicomponent menu items.

Focus:

Focus is the concept of which menu item is enabled at any one time and accepting input. Like in Windows or an XWindows server when you have many windows open, only one will accept input from the keyboard. That window is described as having focus and is normally markd by some colour change. UT2003 has 5 levels of focus that each component knows about defined as an enumerator in [GUI]. They are:

MSAT_Blurry  
No focus at all
MSAT_Watched 
Component has mouse over it
MSAT_Focused 
Component is focused
MSAT_Pressed 
Component is pressed
MSAT_Disabled
..is disabled

As mentioned, styles define characteristics of the component for each focus state.

02/02/03[edit]

Writing a GUI[edit]

Introduction:

This section isn't about how to write a GUI in terms of laying it out and so on, something which is probably better not left to most coders (is it me, or does asthetic design just get in the way of coding? :) ). This section is more about the mechanics of it, which I've found to be slightly more complicated then using UScript to position GUIComponents inside a page/tab and getting that displayed. The GUI classes contain a lot of native code and no obvious drawing functions. With most of the functionality "under the bonnet" as it were, life can be fun.

Static and Dynamic GUIs:

There are two types of GUIs you might want to build: static and dynamic. Static GUIs are those where you know what menu components are needed on the screen for all the time your menu will be displayed. Dynamic GUIs don't assume that you know what menu components will be for the time the menu exists. Notice I said menu components, not user menu items or what a user might assume to be a dynamically generated menu. If you don't understand that distinction, then don't worry about it as they'll be explained in a bit more detail below. Dynamic menus are much harder to create then static menus.

Writing a Static GUI:

As mentioned, static GUIs are ones where the person writing the menu knows what menu components are going to be displayed at all times on the menu. Examples of this are, for example, the UT2003 main menu and the settings tabs in general.

To write a menu requires that a multi-component class be declared. In general, this will involve subclassing GUIPage or GUITabPanel to create menu pages and menu tabs respectively. Once you have your class, you need to define the components that go into the menu, namely you have to define what the array Controls is and this is the bit where life gets complicated very quickly.

All [GUIComponent] classes have a function called InitComponent() which is called when a menu is initialised. One might assume that creating the [GUIComponent] with the new function and then initialising it to the neccessary values would be a good way to go about it. However, if this is done, the menu component won't render. To make the menu component work, (remember there is no obvious draw function to update the screen) the component must be declared in the default properties, which does render it. Once there is a decleration, the properties of each component can be edited inside the class you've created. If you haven't seen the syntax, here's an example:

	Begin Object class=GUIImage Name=CharacterDetails
		WinWidth=0.5
		WinHeight=0.943790
		WinLeft=0.021641
		WinTop=0.028105
		Image=Material'InterfaceContent.Menu.BorderBoxD'
		ImageColor=(R=255,G=255,B=255,A=160);
		ImageRenderStyle=MSTY_Alpha
		ImageStyle=ISTY_Stretched
	End Object
	Controls(0)=GUIImage'CharacterDetails'

Notice the basic points, the Begin statement, followed by the class, follow by the name. This is then followed by the default properties of the new menu component being created terminated by an End statement. This defines the object. Lastly, the object is initialised into the Controls array with the syntax of ClassName'Name' .

Since menu items created via the new comand won't render, it should be possible to see that this limits the menu to containing only the elements declared in the default properties can be used for the menu's duration, what I defined earlier as a static menu. Notice that there is a way around this render problem and there's more on that under the dynamic menu heading but before you rush there (if that's what you want to create) there's some tricks that can be done with static menus to create dynamic effects (see section below).

Notice throughout I've been careful to say that static menus are those in which the menu components are known throughout the menus' durations. I've been careful to say this because there are certain dynamic effects that can be achieved to create basic dynamic tricks. Namely, you can make menu items disappear and generate dynamic menus inside pre-exisiting components. Also, remember all properties of a menu can be changed from their default ones and this will display properly.

"Dynamic" Static Menus:

All components have a property called bVisible which is obvious enough what it does. Just to clarify, this completely removes the control from the screen so that not only is it invisible, but it's not clickable etc. Using this, it's easily possible to have controls/buttons etc that appear and disappear based on input from the user. So, for example, if you want to have two buttons like save and discard pop up when someone clicks on a control, it's easily possible to do that by defining the buttons in the default properties and then making them invisible on start (either in the default properties or in InitComponent) and then making them visible when the time comes.

Combining the above invisibility property with the ability to change the components once rendered without affecting them adversely means that a semi-dynamic menu can be created. To create an example, say you wish to read a map and display selectable starting locations in the form of buttons (assuming there are such playerstart actors in the level, which is NOT true for stock UT2003). By clicking on a button, a player can choose the start location that's written on the button. Assuming that a map will never have more then 10 of these selectable start locations, ten buttons can be defined in default properties. At menu init, the menu scans the map and assigns to each each button one start location up to the max of ten. Each button that's assigned a start location is then made visible. So long as the mapper does not exceed 10 start locations, no one need know that this "dynamic" menu is not really dynamic.

However, say you want to get a dynamic amount of start locations displayed. Can this be done? Well, yes, by using any component that contains a list (GUIList). Lists are individual menu components, so they need to be declared once in the default properties. However, they contain a dynamic array. The dynamic array contains a struct which holds:

  1. The text displayed in the list for that entry
  2. An object associated with the list entry
  3. Some extra string realated to the list entry

Data can be entered into the list during it's initialisation and, providing the list is declared in default properties, the list can be as long as you like (of course, there are some limits, for example, there's a variable for max no of items displayed and the space you can use on a display, go read the class itself). Thus, to take the example, I have a list (or a GUIComboBox which contains a list) in my default properties. On init, the code scans as before for selectable start locations. This time, instead of assigning the name of the start location to a button and making it visible, the code simply adds the start location to a list. If the start location is special, an object can be passed aswell to the list and the onChange delegate in the list can be changed to deal with the object and call functions from it (e.g. to see whether the person's allowed to spawn there) each time a person clicks on it.

The examples are a little specific, but I hope it's easy to see the way in which one should approach building a dynamic menu using existing components.

Dynamic Menus

There are two ways in dealing with a dynamic menu:

The first is to use existing GUI classes and to use the onDraw delegate. This allows the coder to draw directly on the canvas of the menu itself, as with a normal HUD. By returning false, it's possible to stop the native menu drawing code. Returning true just supplements the native code with your instructions.

One important thing to note is that, although created components aren't rendered, they are still there and can be activated etc. This is useful in itself if you want to create a menu over some complex image, say, without too much work.

The second way of dealing with a dynamic menu is to write one's own GUI equivalent classes and have the drawing all handled in the HUD of the player. This is the method that uCOM uses to render the commander's HUD, for example.

The basic principle for this method is that the controls are created as an interaction. The interaction is then used to render and to catch input and to pass the mouse coords and textures based on where the mouse is and what's under it) to the HUD. Then, a class for the actual components themselves, with notification when the mouse is over the component (back to the interaction) and an array to hold other components. I've left this description vague because there's different ways of actually implementing this this, better left to each individual designer according to their needs.

Spark has a tutorial on creating a mouse.