Pingz
I'm a professional game developer gone indie.
- Home page
- http://www.pingz.com
- Work page
- http://www.sickheadgames.com
- E-Mail address
- tom@pingz.com
Questions To The Wikites
Scripting Language Within UScript?
I believe i saw someone discussing a scripting language they wrote in Unreal Script, but i can't seem to find it. Anyone remember where this was at?
Mychaeel: BruteForce I'd say.
Pingz: Ah ha... yea that's it. Thanks.
Where should i put global functions?
I built alot of Quaternion functions which i currently have just laying about in my PlayerController class. Does anyone have any suggestions of a better place to put them where it's reasonably easy to access them from other all objects? Epic puts their math functions in the base Object class so it's global to everything, but i don't see a way for me to do the same. Maybe i could create a class like QuatLib with static functions for all my globals. Any other ideas? I'm still fairly new to UnrealScript, so maybe i'm missing something.
Foxpaw: The static function method is a good one but the additional class.static that you have to put in every time you want to use the function takes longer and more importantly, makes your code appear complicated. You also will have to use DependsOn to use the structs in the library, if any. (In my experience dependson causes a lot of failed compiles.) If you aren't going to be using them in other classes, you could just keep them in the playercontroller class. Optionally, you can use the static function library method and use a wrapper to make it look less complicated, like so:
// Looks complicated! function Quat DoSomeStuff( vector AnArgument ) { if ( !class'FunctionLib'.static.ProcessThis( AnArgument ) || class'FunctionLib'.static.IgnoreMe( self, owner, AnArgument ) ) return class'FunctionLib'.static.FindReturn( AnArgument ) } // Longer, but more sensical. I use comment blocks like below to make it clear that these // functions are not part of the actual 'functionality' of the class. It kind of makes your // eyes skip over that section when you are looking at the code. /********************************************************************************************/ /********************************************************************************************/ /********************************************************************************************/ /********************************************************************************************/ function bool Process( vector Arg ) { return class'FunctionLib'.static.ProcessThis( Arg ); } function bool IgnoreMe( vector Arg ) { return class'FunctionLib'.static.IgnoreMe( Self, Owner, Arg ); } function Quat FindReturn( vector Arg ) { return class'FunctionLib'.static.FindReturn( Arg ); } /********************************************************************************************/ /********************************************************************************************/ /********************************************************************************************/ /********************************************************************************************/ function Quat DoSomeStuff( vector AnArgument ) { if ( !ProcessThis( AnArgument ) || IgnoreMe( AnArgument ) ) return FindReturn( AnArgument ) }
Pingz: Yea that's a freaking mess. There has got to be a better way than just copying my functions to multiple classes or writing a ton of wrapper junk. Maybe i should break down and create my own Quaternion class which can easily convert to UT2K3 Quat structs. At least then the only extra work is saying
local Quaternion my_quat; my_quat = new Quaternion;
A small price to pay i guess, but i wonder if this will thrash memory if i create and destroy several temporary quat classes every frame.
There has to be a better solution still.
Mychaeel: Something like this, perhaps – while it does have the disadvantage of needlessly instantiating an object, it reads pretty neatly:
var FunctionLib FunctionLib; function MyFunction() { if (!FunctionLib.ProcessThis(AnArgument) || FunctionLib.IgnoreMe(AnArgument)) return FunctionLib.FindReturn(AnArgument); } defaultproperties { Begin Object Name=FunctionLibInstance Class=FunctionLib End Object FunctionLib = FunctionLib'FunctionLibInstance'; }
As an additional bonus, you could even make your FunctionLib accept certain "parameters" in terms of FunctionLib class variables that affect the outcome of its functions and define them in the "Begin Object" block without any additional overhead.
Pingz: I emailed Tim on this, but never got a response... must have been busy. I've still have not found a better solution than the one Mychaeel suggested above.
Trigger collision
Is there a way to have a brush or static mesh act as the collision shape for a trigger instead of using CollisionHeight and CollisionRadius? There must be, but after several hours of searching the Wiki i find no mention of how to do it.
Foxpaw: You could write a custom volume class to do this. Actors will "collide" with the edges of the volume when they first enter it.
Pingz: In the end i learned that not all Actors are equal. Alot of the behavior and capabilities of derived Actor objects are native within the engine itself which you can't change even though the script interface looks like it could.
Foxpaw: Trust me, you can use a volume to do that, but you will need to custom script it. I THINK that could use use a static mesh too, if you made a class with an invisible static mesh.. that works with Karma. I dont' know if it will work with the proprietary physics or not though.
Wormbo: You can use a Volume's AssociatedActorTag to forward the volume's Touch and UnTouch events to a Trigger which triggers the actual event.
Pingz: I wasn't clear there... in the end i did do as Foxpaw suggested and created a derived volume class. I tried several times to get it to fire off a trigger, but ended up overloaded my volume's Touch event to just call a function on other if it was my pawn type.
Dynamically Loaded Textures & Resizable Geometry
Ok two fairly weird things i'm trying to do in UT2K3 that i'm thinking is impossible, but i want to hear what people suggest.
First i have a need to at runtime load a texture that isn't in a package. My guess is that it isn't allowed for security reasons, but if anyone has a crazy hack idea to make it work for an offline demo let me know. My current crazy idea is to use LibHTTP to fetch the encoded texture data from a local webserver and recreate the texture via ScriptedTexture. Very crazy, but it should work fine for my needs. Still anything obvious that i may be missing?
Second issue is i'm needing to resize level geometry at runtime. I believe this is simple to do with a StaticMeshActor and DrawScale (i assume this scales the collision info too), but i've yet to test this theory. Am i correct in believing that i cannot scale either the entire level or individual world geometry at runtime? I have workarounds for some of this as i can build just about everything important with StaticMeshes, but not the sky box. Any suggestions or comments on this?
If your wondering what this is for all i can say is that it's just a prototype of something that isn't a game. So far UT2K3 has been a great place to prototype non-game 3d stuff as long as you can work around some of the limits.
Foxpaw: I don't believe there is any way to resize the BSP at runtime. Though simple in concept, the BSP information gets flaky if it isn't stored as multiples of 8, so arbitrarily resizing the world would cause lots of problems.
Pingz: That's what i figure too. Luckily i think i can static mesh all of the most important resizing parts. And for the textures i'm just gonna implement my own TCP server in C and a custom TCP client which can request the binary data and stuff it into a ScriptedTexture ( i can draw pixels into these with DrawTile right? ). Gonna be really interesting to see how slow that all is... good thing that doesn't matter too much.
Foxpaw: If speed is not an issue, you can use a constantcolor material for this: set the color of it, draw it on at 1x1 pixels, change color to the next pixel color, etc. However, doing this will mean that your textures will have no mipmaps.
Mychaeel: Also, since a Material's properties stick for the remainder of a frame after they've been used (probably because the material has been uploaded into video memory by its first use), you'd only be able to draw pixels in a single color each frame. Better (and most likely a lot more efficient) to use the Color
parameter in the DrawTile
method while drawing a "white" texture tile.
O-GL: Pingz, I was just curious if ScriptedTexture actually worked for you when creating a texture one texel at a time. Im also wondering if it is possible to read individual pixel colors from a texture. Such a simple request but I just cannot seem to find a solution.
Mychaeel: I've successfully drawn monochrome bitmaps loaded from a BMP file on a ScriptedTexture (mostly because it's easy to optimize the drawing process by drawing a whole byte's worth of pixels – eight pixels in a row – in one step) for my eternally-work-in-progress SprayPaint mutator (see my Developer Journal). You could use the same mechanism to draw full-color textures pixel by pixel, but I suppose that would be prohibitively slow (but I've never tried it). Of course, if you have the time (in the game), you can somewhat lessen the impact of the task by only drawing a small portion of the texture each frame and using what you've drawn as a starting point in the next frame.
As for reading a pixel's color, I looked for a solution for that myself in vain when I was implementing the scoreboard minimap for Jailbreak 2003. (I wanted to generate a minimap using DrawPortal and do some shader magic with another ScriptedTexture to make the black pixels surrounding the level geometry on the minimap transparent.) As far as I recall, my search was utterly unsuccessful.
Guestbook
Wormbo: Welcome to the Wiki, Pingz. Feel free to add yourself to the Project Contributors list if you didn't already do that.
EntropicLqd: Hello and welcome. Enjoy your stay .
Pingz: Hi all. Thanks. I'm still getting a feel for this whole wiki thing.
Highlander: Hi and welcome to the Wiki.
Tarquin: Hi there. "Pingz: Is there a compelling reason to make 'rebuild' and 'build' two different topics? They do the same thing." – rebuild is a basic procedure page: it gives just the simple steps for newbs.
GRAF1K: I know that you're quite an advocate of .PNG files, but Unreal server pinging would also be a possible. Did either of those influence your name – I've just been wondering for awhile.
Pingz: Actually it comes from my Quake playing days. I went by Pingzero for a long time and shortened it after my clan mates kept calling me that in IRC.