The three virtues of a programmer: Laziness, Impatience, and Hubris. – Larry Wall
I've come to start working with the Unreal Engine, using not an Unreal game, but actually Groove Games/BrainBox's Land of the Dead game. It's difficult to find things that don't depend on the game-specific things, but there are some good ones around here on the Wiki.
I've been programming virtually all my life, though the usefulness of programs that I wrote when I was 5 is .. well, nil. For that matter, it was nil then. Most all of my programming has been modifications for games, or communications things (BBS software back in the day, and I wrote the first DOS IRC client, back in the days when Windows was barely functional.. though some would argue that's still true). I re-coded and greatly enhanced the C-Net 64 BBS Empire game, created a web-based version of another BBS-era game, and most pertinent to what I'm doing with LotD/Unreal Engine, is that I wrote the entire codebase for a MUD (in the MUD's LPC programming language, which is actually quite similar to UnrealScript, though I think it was quite a bit more advanced than US is..). Unfortunatly, none of the work that I have done has survived the ages, so I really don't have much of an example (you can still find my old IRC client online, but there's not much hope of using it for anything anymore). My mods to LotD are normally released on www.undeadgames.com ..
I would also like to help improve the Wiki, as I've noticed that a LOT of its pages are pure data, with no actual description of what/why something is useful, what it's used for, etc.
Another thing that I've noticed is that although it's called "The Unreal Engine Documentation Site", it's almost completely concerned with the actual Unreal games, excepting for Deus Ex and Postal 2. And it seems that lots of things are being updated for UT2k4, with previous documentation phasing out. I think that everything should have a listing for where and when and what it was implemented in, which functions work in which engine versions, so on so forth.. I (obviously) still need to learn to do real Wiki formatting, but I would very much intend to document everything that I discover about how everything works..
Things that I'm making notes of for LotD, for whatever reason:
- Setting StdTraceDistance to 0 from AdvancedWeapon, even with AltTraceDistance set, causes the Alt-Fire to fail to function.
Probably need to actually check and see what the hell those two things do. (appears to need to be around 100 or so for the Alt-Fire to function)
- Karma parameters do not seem to replicate - adjusting them after the fact only works in NM_StandAlone
- The function called Notify_MeleeDamage(), called somewhere in the Weapon tree is somewhere around useless, and definitely misleading. It is called when the weapon swings, rather than when damage is done. (to achieve knowing when damage is done, you must subclass DOTZMeleeWeapon, or something else somewhere in the tree, and jam your own call into the ProcessTraceHitOnMat)
- It appears to be virtually impossible to create a Pickup that has editable parameters, that can be injected into a weapon, as the function that creates the weapon and gives it to a player is private, and can't be overridden. Therefore, one would have to subclass, and then re-create the -entire- pickup code, otherwise it will be calling in the wrong object in the tree, if it will even allow it at all.
- It would've been a lot better design idea for pickups to be invisible generic placemarkers on the level that actually spawn (and re-spawn if needed) the actual object they are set for, which then handles the inventory code, instead of this bizarre method that they are now, in which case they are an action-driven (or walk over in other games) item that spawns an object directly into a players inventory. Totally bizarre.
- Why didn't anyone think of a Caller reference, that would return whatever the heck object is calling you? and/or something that would return back whatever the heck caused your entire current chain of execution?
- Player.PlayerReplicationInfo.GamerTag is used instead of PlayerName, this is apparently something involving the Xbox support. I can't figure out how GamerTag is set from the ?XgamerTag= option that the game is given.
- We can override DOTZPlayerController.ToggleObjectivesDisplay() to actually work in multiplayer properly, when we get around to objective based multiplayer missions
- If DOTZPlayerController.PostNetBeginPlay() calls StopAllMusic(0), why does level specified music work? Someone did report that the music gets weird at time during multiplayer play, so maybe that has something to do with it.
- There seems to be some sort of "Profiler" class built into the engine (since nothing for it seems to exist in Uscript) that handles remembering user profiles. I'm thinking it is also part of the Xbox support, but have no idea for sure.
- The game does not by default allow you to carry more than one melee or thrown weapon, but does allow for several guns. In multiplayer, you can only have two guns, one melee, and one thrown. I'm thinking this is somehow handled in inventory, as there is code in DOTZPlayerController to actually deal with multiple melee and thrown and guns being in inventory at the same time.
- It seems to have some kind of weather support. It appears that you setup some kind of emitter for your weather, put a WeatherEffect into your level, and assign the emitter to that WeatherEffect's "WeatherEffect" setting in the editor. It appears that this causes the weather effect to play clientside, not serverside. This would be very handy to level designers, if we had any idea how it actually works. It does not appear at a first glance, that it supports multiple weather effects, and that the last one that it finds will override any previous ones. it seems very odd that this would not be a zone-dependent thing.
- bShowInventory in AdvancedPawn (WHY not playercontroller? argh) causes the weapon-info to be displayed in HUD, and has nothing to do with any other inventory functions that are not particularly used in this game
- Attempting to subclass any of the DOTZGUI components causes a compiler crash, ala:
Assertion failed: FriendlyName!=NAME_None [File:UnClass.cpp] [Line: 682]
- Who decided to build a system like this that doesn't support multiple inheritance? If I ever meet them.... there will be a clash :D
List of functions called by the Engine, in UnrealScript
- Level.Game.InitGame(String Options, out String Error) - called very quickly after startup, along with the game's command line. Set the Error string to something, and the engine will die with that error. Strangely, InitGame() is not called when a game is Loaded. I wonder how to get command line when loading a game?
- Level.Game.Login(string Portal, string Options, out String Error) - called when a person attempts to login. Return an error string if login is not allowed. Options is the command line the user used to connect with. Expects a return type of PlayerController.
- Level.Game.PostLogin(PlayerController NewPlayer) - called after Login() in the Gameinfo, if there was no error. I think I'd read somewhere that it was not safe to call functions in the NewPlayer controller, until this function. PostLogin() -seems- to get called sometimes with NewPlayer == None, sometimes, for no obvious reason.
- PostRender(Canvas C) - called in a user's HUD (and other places?) immediatly after rendering each frame, usually used to draw the HUD.
- WorldSpaceOverlays() - ? apparently called in HUD somewhere, no further information at this time
- Tick(float delta) - called every Game Tick, in every actor, with a delta being the time (in ms?) since last tick
- PostNetReceive() - called in each actor after the client receives network update
- Landed(vector X) - called in any actor when it lands on something after previously being airborne, X being a vector containing information about your landing
- ZoneChange(ZoneInfo NewZone) - called in any actor when it reaches a new map zone, newzone = the new zone information
- Kimpact(actor Other, vector Pos, vector ImpactVel, vector ImpactNorm) - Called when an object has physics set to PHYS_KARMA, and it hits something else in the world that blocks Karma actors
- PostLoad() - Called in PlayerController (and others?) after a new level or a saved game is loaded. In LotD, it is used to register a Motion Blur camera effect
- PreClientTravel() - Called in PlayerController (and others?) before a new level is loaded.
- FellOutOfWorld(eKillZType KillType) - Called in any actor that finds itself outside of the level geometry. Should either destroy the object, or teleport it to a known good location.
- PreBeginPlay() - called before an object is put into the world
- PostBeginPlay() - Called in any actor, after it is dropped into the world
- Touch(actor Other) - called in one object whenever another object is touching it. (so it would be called in both objects when they are touching each other). Other is the object that is touching this one. This gets called for every tick that the objects are touching.
- TakeDamage(int Damage, Pawn instigatedBy, vector HitLocation, vector Momentum, class<damageType> DamageType) - called to cause an object to take damage. I'm not sure why this is in the engine, it seems much more a lib type thing (and it is called in several places in LotD's lib)
- Timer() - called by the engine, after a SetTimer() call is made
- BeginState() - called in state code, immediatly after a statechange is made, such as with GotoState()
- EndState() - called in state code, immediatly before BeginState() of a new state is called when state changes.
- PreSaveGame() - called in (all?) actors immediatly before saving a game
- PostSaveGame() - called in (all?) actors immediatly after a game is saved
- UnTouch(Actor Other) - called in touching objects, the moment they are no longer touching each other, with Other being the object that used to be touching this object.
- MultiTimer(int slotID) - called in response to a SetMultiTimer() call
- NotifyLevelChange() - called in all (GUIs? objects? actors?) when we need to be ready for a level change
- Destroyed() - called in all Actors when they are to be destroyed
- GainedChild(actor Other) - called in any object that becomes the owner of a brand new object thanks to a Spawn() call setting it as owner
- LostChild(actor Other) - called in any object that loses a child due to it's child being destroyed
- Bump(actor Other) - called in any object when it runs into something (how does this differ from Touch? it appears to be called tons of times)
- Tornoff() - called in any actor when bTearoff is set, meaning it will be deleted from the server, but kept on clients until it's Lifetime expires
- PostNetBeginPlay() - called after PostBeginPlay(), if it is a network game
- ConnectFailure(String FailCode, String URL) - called in HUD when a connection fails
- ShowUpgradeMenu() - called in HUD when you have a lower version than the MinNetVer of the server you connect to - unused in LotD, as there is only one engine version for this game
- Initialized() - called in Interaction classes after they have been created and initialized
- DetourWeight(Pawn Other, float Pathweight)
- SpecialCost(Pawn Other, ReachSpec Path)
- SuggestMovePreparation(Pawn Other)
- these are called in PathNode actors during movement by the AI ?
- ClientLostConnection() - called in PlayerController when it becomes disconnected from the server
- SetProgressMessage(int Index, string S, color C) - called in PlayerController while downloading content from a server, also called while playing demos
- SetProgressTime(float T) - called in PlayerController - Having something to do with the above call?
... this is probably highly incomplete, and may be inaccurate, but it's what i see from some quick searching. If this info is already archived somewhere on the Wiki, I can't find it, and it'd be really handy.
I'm moving a bunch of stuff to EricBlade/Developer Journal now that I've discovered that category.
EricBlade/ZombieZilla ; Mutator originally written for Land of the Dead, but should be easily applicable to any UE game.. Easily alter the size of your enemies :D
Tarquin: Hi. Welcome to the wiki! We're cool with stuff about older games, but there's not as many people interested in adding material on those. Go ahead with making improvements as you see fit. If you make a mistake, don't worry, someone will help guide you along :)
SuperApe: Howdy. :) Looks like you're well-versed in programming. Great to have you around. Welcome.
Wormbo: You can always get the options via GetUrlOption("option name") or via the Level.Get*Url() functions. The LevelInfo functions probably include a server IP or map name.