RegularEngine/RegularPawn
Ah, RegularPawn. This is where all the magic happens. And by magic, I mean cheap hackery.
RegularPawn resolves a lot of issues I had with the original Riftwar player class framework. Originally, Riftwar relied heavily on PlayerController vars to determine what species to use in order to override the pawn setup. It was complicated and buggy.
This is a far simpler solution to regulate a pawn's appearance and behavior. Instead of swapping out a lot of things, the Pawn is back in control and sets up everything like it usually would. Except that when the GetPlayerRecord would normally run out and find Lauren's impressive figure - it asks what it's current player class is and completely alters the result of that, as well as update any default properties like RequiredEquip or Health.. The outcome is a pawn that behaves exactly like a normal UT2004 pawn, except for in this one part where we don't want it to.
This is a little incomplete, however - you'll still have to toy with the portrait and voice.
class RegularPawn extends xPawn; var xUtil.PlayerRecord PlayerSetup; var string PlayerClassName; var float ReceivedDamageScaling; // basically ... armor replication { reliable if( Role==ROLE_Authority ) PlayerClassName; } simulated function Setup(xUtil.PlayerRecord rec, optional bool bLoadNow) { rec = GetPlayerRecord(rec); Species = rec.Species; RagdollOverride = rec.Ragdoll; Species.static.Setup(self,rec); ResetPhysicsBasedAnim(); } //determine our player class. PlayerClassName should already be set by the controller. //Then overload/override the PlayerSetup before handing to the pawn for setup. simulated function xUtil.PlayerRecord GetPlayerRecord(xUtil.PlayerRecord PlayerSetup) { LOG("Switching "$PlayerReplicationInfo.PlayerName$" to "$PlayerClassName); if(PlayerClassName ~= "Sniper") { PlayerSetup.MeshName="HumanFemaleA.MercFemaleC"; PlayerSetup.Species=class'xGame.SPECIES_Merc'; PlayerSetup.BodySkinName="PlayerSkins.MercFemaleCBodyA"; PlayerSetup.FaceSkinName="PlayerSkins.MercFemaleCHeadA"; PlayerSetup.Sex="Female"; RequiredEquipment[1]="XWeapons.AssaultRifle"; RequiredEquipment[2]="UTClassic.ClassicSniperRifle"; GroundSpeed=550; ReceivedDamageScaling=1.10; } if(PlayerClassName ~= "Infantry") { PlayerSetup.MeshName="HumanMaleA.MercMaleC"; PlayerSetup.Species=class'xGame.Species_Merc'; PlayerSetup.BodySkinName="PlayerSkins.MercMaleCBodyA"; PlayerSetup.FaceSkinName="PlayerSkins.MercMaleCHeadA"; PlayerSetup.Sex="Male"; RequiredEquipment[1]="XWeapons.AssaultRifle"; RequiredEquipment[2]="XWeapons.MiniGun"; ReceivedDamageScaling=0.95; } if(PlayerClassName ~= "Heavy Arms") { PlayerSetup.MeshName="Jugg.JuggMaleB"; PlayerSetup.Species=class'xGame.Species_Night'; PlayerSetup.BodySkinName="PlayerSkins.JuggMaleBBodyA"; PlayerSetup.FaceSkinName="PlayerSkins.JuggMaleBHeadA"; PlayerSetup.Sex="Male"; RequiredEquipment[1]="XWeapons.AssaultRifle"; RequiredEquipment[2]="XWeapons.RocketLauncher"; GroundSpeed=400; ReceivedDamageScaling=0.85; } if(PlayerClassName ~= "Human Captain") { PlayerSetup.MeshName="XanRobots.XanM02"; PlayerSetup.Species=class'xGame.SPECIES_Bot'; PlayerSetup.BodySkinName="UT2004PlayerSkins.XanM2v2_Body"; PlayerSetup.FaceSkinName="UT2004PlayerSkins.XanM2v2_Head"; PlayerSetup.Sex="Male"; RequiredEquipment[1]="XWeapons.AssaultRifle"; RequiredEquipment[2]="XWeapons.FlakCannon"; } if(PlayerClassName ~= "Trooper") { PlayerSetup.MeshName="SkaarjAnims.Skaarj2"; PlayerSetup.Species=class'xGame.SPECIESSkaarj'; PlayerSetup.BodySkinName="UT2004PlayerSkins.Skaarj2_Body_Rage"; PlayerSetup.FaceSkinName="UT2004PlayerSkins.Skaarj2_Head_Rage"; PlayerSetup.Sex="Male"; RequiredEquipment[1]="XWeapons.AssaultRifle"; RequiredEquipment[2]="XWeapons.LinkGun"; GroundSpeed=550; ReceivedDamageScaling=1.10; } if(PlayerClassName ~= "Specialist") { PlayerSetup.MeshName="SkaarjAnims.Skaarj3"; PlayerSetup.Species=class'xGame.SPECIESSkaarj'; PlayerSetup.BodySkinName="UT2004PlayerSkins.Skakruk_Body"; PlayerSetup.FaceSkinName="UT2004PlayerSkins.Skakruk_Head"; PlayerSetup.Sex="Male"; RequiredEquipment[1]="XWeapons.AssaultRifle"; RequiredEquipment[2]="XWeapons.ShockRifle"; ReceivedDamageScaling=0.95; } if(PlayerClassName ~= "Assault") { PlayerSetup.MeshName="SkaarjAnims.SkaarjUT2004"; PlayerSetup.Species=class'xGame.SPECIESSkaarj'; PlayerSetup.BodySkinName="UT2004PlayerSkins.Skaarj_Body_Tats"; PlayerSetup.FaceSkinName="UT2004PlayerSkins.Skaarj_Head_Tats"; PlayerSetup.Sex="Male"; RequiredEquipment[1]="XWeapons.AssaultRifle"; RequiredEquipment[2]="Onslaught.ONSMineLayer"; GroundSpeed=400; ReceivedDamageScaling=0.75; } if(PlayerClassName ~= "Skaarj Captain") { PlayerSetup.MeshName="SkaarjAnims.Skaarj4"; PlayerSetup.Species=class'xGame.SPECIESSkaarj'; PlayerSetup.BodySkinName="UT2004PlayerSkins.Skaarj4_Body"; PlayerSetup.FaceSkinName="UT2004PlayerSkins.Skaarj4_Head"; PlayerSetup.Sex="Male"; RequiredEquipment[1]="Onslaught.ONSGrenadeLauncher"; RequiredEquipment[2]="XWeapons.LinkGun"; } return PlayerSetup; } defaultproperties { ControllerClass=class'RegularBot' ReceivedDamageScaling=1.0 }
Discussion
Ambershee:Couldn't help but notice a little bug whilst skipping through this. You can't set GroundSpeed from here like that - well, you can, but it the changes don't take effect until the pawns GroundSpeed is alterered the first time. Basically, it will use the default pawn GroundSpeed until the player does something, such as alt-fire a redeemer rocket. When the player returns to their body, then the changes will take effect. I'll correct this at some point if I get the opportunity, or someone doesn't beat me to it.
OlympusMons: Actually I never had a problem with groundspeed myself but I use the species for player classes and what not so you could check that out