Last monday I made my way to the local EB and forced them to happily sell me a copy of UT2k3 before they were ready to put it up on display. In the days since, I have spent unhealthy amounts of time studying the new codebase, and can thus far only conclude this:
I am shocked and APPALLED that they have removed the "Fatness" actor display property.
In spite of this tragedy, I feel it is my duty to not only myself but to the greater UT community that I continue in my efforts to contribute. Thus we take our first steps toward the As-yet-unnamed "XCTF"-based mod.
My working idea for constructing this mod is to use a series of mutators, each responsible for specific rules. The reason why I chose this is because 1.) A basic CTF gametype already exists in 2k3, and 2.) the additional rules (full weapons), are general enough that they can be effectively applied to virtually any other gametype as well. Avoid redundancy and insure consistency.
The only real sticking point here is the Grapple. The difficult part isn't the implementation of the grapple itself, but effective application to the Bot AI. Would we be able to get away with using mutators for this? In UT I implemented bot grappling by co-opting the actions induced by the translocator – none of the AI changes were made to the Bots themselves. I haven't looked through the 2k3 code in depth yet, but in UT translocation was handled specifically by the navgationpoints and the X-loc itself: the navigationpoint forced the bot to switch to the X-loc and then fire. Keeping it short, my implementation of the grapple involved simply replacing the X-loc and tweaking where the bot aimed.
So yes, it's possible to get a bot to use a grapple to get to unreachable places without gutting the bot AI. But something that sticks out in my mind about 2k3 is the way bots USE the X-loc. As a means of normal travel, even if it's just to the other side of a room. If we're going to have a grapple, it's only right that we have the bots use it in the same *intelligent* manner it uses the X-loc... which raises the issue of whether or not the same hack can be used. When using the X-loc to travel, are bots still using navpoints? Or are they just using fuzzy logic to guess how best to get to their destination?
If it's the latter, then we might have to go the route of tweaking the bot controller AI. Which is where we have to decide about mutator use. Would a mutator be the best way to swap controllers? (Is it even possible with a mutator?)
Mutator construction itself is still pretty straightforward. Game Rules – player stats, scoring, and damage modification – have now been split off from GameInfo. Thus for a mutator to hook into any of the GameRules functions, you now need to accompany the mutator with GameRules subclass. It's otherwise pretty much unchanged.
The DE particle emission class == cool. It’s about damn time UT had some proper support for beam effects.
So the grapple is in and more or less functional. Interesting exercise in aquinting myself with the new structure for weapons; there’s now something like 5 different classes to deal with. The weapon as an inventory class is still intact, but really now just exists to serve the same purpose as ammo – to show that the weapon exists in the player’s inventory. Facets of the weapon have been abstracted into wholely separate classes, including ones which represent the weapon as viewed as either a pickup or 3pp, and ones which control the actual weapon behavior. Which actually makes a whole lot of sense, particularly the different pickup and 3pp classes, but makes things a bit more difficult to keep track of.
The grapple is more or less based on various previous UT implementations, mostly my own. The weapon fires a projectile which, when it lands, adds a velocity to the player which draws him near. One nice thing about the WeaponFire class is that the abstraction supports firing modes that are contingent upon the player holding the fire button down; no need for any kind of tick-bound “if ( bFire != 0 )” checks. Thus the grapple can have two modes: the first is a Quake-style automatic recall on buttonup, the alternate fire is a normal fire/recall. The rope is implemented using an xEmitter subclass, largely based on the Ion Painter beam.
I subclassed the xPlayer controller class in order to put in an exec function which grabs the grapple in inventory and co-opts its WeaponFire. I’m using the alt mode, so calling the “hook” function once will fire the hook, and calling it again, or “unhook”, will recall it. There’s our offhand grapple. I’m considering removing this and placing it in an inventory item instead – it would make an offhand/no offhand gametype configuration easier to implement, I think.
The keybinding for the grapple goes to an alias… don’t have my user.ini open right now, but it’s something like “hook | onbuttonup unhook” I’m a bit trepid about going this route – somehow it evokes that shock combo binding used by people who aren’t coordinated enough to move two fingers. For a while I was considering implementing another input byte… but then, that would also require using a similar alias, and on top of that, could get pretty nasty code-wise with the grapple needing some controller-specific code; it counters the abstraction I’d like to maintain. Choose the lesser of two evils, I guess.
Net code is probably a bigger priority than bot support. Arbitrarily calling AddVelocity for the purpose of pawn locomotion isn’t the most client-friendly thing to do. Player movement prediction is pretty much how I had it figured while toying with the idea of changing player physics on M:R – all taken care of in the controller’s PlayerMove() function which makes one call to the client and one call to the server – though it’s nice that they now have comments which confirm this. I’m thinking more and more that I’m going to have to go with a new movement state. (Hey, if we’re going to mess around with the controller, might as well go all the way.)
Um… [I got distracted].
Anyway. I ended up going with a new movement state for the playerpawn.
Each time the user manually presses a key to move in any direction, an acceleration is applied to the pawn. This acceleration is what causes the player to move – the player’s velocity is what results. Client prediction doesn’t care about the velocity – the player’s position over time – but instead uses the acceleration – the player’s velocity over time. That way it can not only determine the client’s position, but also where it will likely be in the next update.
Arbitrarily using AddVelocity doesn’t work, since velocity is neither replicated nor predicted. The new version of the grapple instead tells the player to accelerate in a given vector and sends the player to the new state, “Hooked”. There the controller uses state-specific versions of PlayerMove and ProcessMove to handle the changes. The Hooked state itself is extended from the PlayerFlying state, as we basically want the same thing – to have the player fly – only in this case the player’s acceleration will only be affected by the grapple and no player input.
The magnitude of acceleration for grappling players is 2048, the same amount used for all pawn movenent with the exception of jumping, which I believe is something like 6000. The latter is more than sufficient, though, as with such a player can easily do instant 180-degree turns and start running in the opposite direction without missing a beat. The grapple tells the player to cap the maximum air speed at 700, so a grappling player will never move at more than twice as fast as his running speed. This value will most likely undergo further tweaking.
Oh, and bots can grapple-walk. Basically done by hacking up the xloc-hop code and refitting it for use with the grapple. Bots use manual fire on the immediate next node they want to travel to, and when they are pulled close enough, the grapple unhooks. The grapple will automatically unhook and drop the bot after two seconds anyway, just to insure that the bot doesn’t somehow get stuck. Still needs some tweaking – need to write up some better logic for the bots’s grapple aiming. Keep it from shooting the hook off into space while aiming at an uphill target. Things like that. Need to work on getting the bots to grapple on to actual targets, ie high platforms, next.
Seeing the bots use the grapple to get around is extremely, extremely gratifying.
And then I passed everything off to the guys at the [Coliseum] to tweak to their hearts' content.
If anyone else is interested in the sources, drop me a note and I'll hook you up. (Ba-dum-bum-crash!)
Something I hacked together, based on a discussion from sometime back.
Some tweaking of the textures and placement. Another screenshot:
What I'd like is to be able to somehow hook into however standard coronas are rendered and have the flares mirror that behavior. I suspect it's somewhere in the native code, though, so I may be SOL.