First we need to set up our new package so that it will compile. In this example I will be using the Magdalena skin and my monster package will be called MyMagdalena. You can download the Magdalena Skin from here if you wish to work with me.
Ok so first we need to create a new folder in the UT2004 base directory called MyMagdalena.This is our package that we will compile into a .u file.
Within that folder create a new folder called “Classes”. This is where we need to put all of our custom classes (.uc files) that we want to compile. And within this folder lets add our first .uc file. Create a new .uc file by right clicking>New>Text Document.
Rename the extension to .uc. Lets name the file MagdalenaMonster. You new file should look like this when created.
Next lets just add a little code to the .uc file to make it compile for the next step. Open the MagdalenaMonster.uc and at the top make our class a subclass of Monster because all monsters need to extend this class. Add the following code to the top of the file.
Class MagdalenaMonster extends Monster;
The package will now compile but first we need to tell unreal to include our package in the list of things to edit when it compiles. We do this by opening the UT2004.ini file which is located in your UT2004\System folder. With this file open, scroll down to the heading [Editor.EditorEngine] and add EditPackages=MyMagdalena to the bottom of the list.
To run the compiler you can open a new command window and navigate to your UT2004\System folder and then type “ucc make” without the quotations. To go down a directory type “cd..” without the quotations. To go up a directory type “cd NameofFolder” without the quotations. To change directories type “DriveLetter:” without the quotations. For example to change to your C: drive simply type “C:” without the quotations. If you have done this correctly you should see something like this.
Or you can download this one-click program that will do all that for you from here. UCC Compiler. To set up the Ucc Compiler open the program and set the directory to your UT2004\System folder.
To run the compiler just hit “Run default UCC make” – don’t worry about the other buttons. If you have done it right you should see something like this.
From now on I will be using the UCC Compiler program. Each time you wish to make a new compile you must delete the old .u file from the UT2004\System folder. (in this case our MyMagdalena.u file) First we need to find a skin that would make a good monster. Got one? Excellent, I will be using the Magdalena Skin, install it and lets move on.
The boring part was setting up the package to be compiled, now we start to create our monster! First we need to set the model and textures. To find the name of the model open up UnrealEd and in the Animation browser open up the animation file that came with your chosen skin. In this case we need to open the Magdalena.ukx file. The model will appear in the viewport. Here we can see the name of the package, the name of the skeletal mesh, the name of the animations, the name of the skins (textures) and even the names of each animations. Remember this because we will need it later! Ok so make a note of the SkeletalMesh name and Skins.
Lets update our monster with this new information. Monsters created with skin models will always be of type SkeletalMesh. Add the following to the defaultproperties of your MagdalenaMonster.uc file.
Class MagdalenaMonster extends Monster; defaultproperties { Mesh=SkeletalMesh'Magdalena.Magdalena' Skins(0)=Texture'MagdalenaTextures.magdalena_body' Skins(1)=Texture'MagdalenaTextures.magdalena_head' }
Default properties can be seen in the editor when you place the monster. Another way to do this visually is in the editor. Because we have compiled our monster it will now appear in the actor list in the actor browser.Actor browser>Actor>Pawn>UnrealPawn>xPawn>Monster>MagdalenaMonster.
Select MagdalenaMonster, subtract a simple cube and right click a surface>Add MagdalenaMonster Here. You will notice our monster looks like Jakob! This is because by default all xPawns and Monsters have Jakobs mesh and skin. Open up our monsters default properties by right clicking our monster>defaultproperties. A small window will open.
We can use this to change how the monster looks and then when we are happy we can copy this into our monsters .uc file. Lets first change the mesh to Magdalenas. Make sure the Magdalena mesh is active in the animation browser then in our monsters defaultproperties in the editor, expand the Display section and next to where it says Mesh you will notice it has Jakobs mesh. Hit the “Use” button next to it and the currently selected mesh in the animation browser will be applied. You will notice that our monster now has the shape of Magdalena but it still has Jakobs textures.
Back in the display section a few properties below the Mesh setting you will notice a Skins line. Expand Skins and you will see that this is why it still has Jakobs textures. All we need to do is change these to match the Skins that the Magdalena model uses. Copy the skin names from the Magdalena model from the Animation browser and paste them over these Jakobs ones in the correct slots. Now the monster looks correct. If you are lazy you can get this information from the Editor into the .uc by right clicking the monster in the viewport>Edit>Copy. You can then paste this into the .uc file at the bottom. You wil notice it pastes a lot of useless information that is only relevant to the editor. We are only interested in the things we changed. Delete the things we don’t need. You should be left with 3 lines of information.
Mesh=SkeletalMesh'Magdalena.Magdalena' Skins(0)=Texture'MagdalenaTextures.magdalena_body' Skins(1)=Texture'MagdalenaTextures.magdalena_head'
Just put these in the defaultproperties like we did before. Other things can be determined in the editor like this. Such as DrawScale, Prepivot (if needed). If you change these values be sure to turn on Radii view and set the correct collision sizes in the defaultproperties also.
With Radii view on you will notice when you select something a red cylinder will appear around the object. This is the collision cylinder.
Ok so the skin and textures are set up. Now we need to make sure our monster plays the correct animations. Most of these are set in the defaultproperties. In the animation browser again simply decide which animations you want to use and set them in the monsters defaults in the .uc file. The animations that need to be set are as follows.
defaultproperties { IdleWeaponAnim= IdleHeavyAnim= IdleRifleAnim= TurnRightAnim= TurnLeftAnim= CrouchAnims(0)= CrouchAnims(1)= CrouchAnims(2)= CrouchAnims(3)= CrouchTurnRightAnim= CrouchTurnLeftAnim= AirStillAnim= AirAnims(0)= AirAnims(1)= AirAnims(2)= AirAnims(3)= TakeoffStillAnim= TakeoffAnims(0)= TakeoffAnims(1)= TakeoffAnims(2)= TakeoffAnims(3)= LandAnims(0)= LandAnims(1)= LandAnims(2)= LandAnims(3)= DodgeAnims(0)= DodgeAnims(1)= DodgeAnims(2)= DodgeAnims(3)= DoubleJumpAnims(0)= DoubleJumpAnims(1)= DoubleJumpAnims(2)= DoubleJumpAnims(3)= MovementAnims(0)= MovementAnims(1)= MovementAnims(2)= MovementAnims(3)= SwimAnims(0)= SwimAnims(1)= SwimAnims(2)= SwimAnims(3)= WalkAnims(0)= WalkAnims(1)= WalkAnims(2)= WalkAnims(3)= WallDodgeAnims(0)= WallDodgeAnims(1)= WallDodgeAnims(2)= WallDodgeAnims(3)= IdleRestAnim= IdleCrouchAnim= IdleSwimAnim= IdleChatAnim= FireHeavyRapidAnim= FireHeavyBurstAnim= FireRifleRapidAnim= FireRifleBurstAnim= }
Where it asks for 4 different ones for the same type, try and put them in the correct order. 0 = F(Front), 1 = B(Back) 2 = L(Left) and 3 = R(Right). For example the walk anims would look like this.
WalkAnims(0)=WalkF WalkAnims(1)=WalkB WalkAnims(2)=WalkL WalkAnims(3)=WalkR
If your monster doesn’t have enough animations of the same type just put in what it does have. For example.
WalkAnims(0)=WalkF WalkAnims(1)=WalkF WalkAnims(2)=WalkF WalkAnims(3)=WalkF
Alot of these might never be used but its a good idea to make sure they have a valid animation otherwise you will get errors in your log file. A lot of errors can really slow the game down. If your skin doesn’t have a particular animation just use the closest match. Ok so my MagdalenaMonster.uc now looks like this. Yours should look very similar.
class MagdalenaMonster extends Monster; defaultproperties { Mesh=SkeletalMesh'Magdalena.Magdalena' Skins(0)=Texture'MagdalenaTextures.magdalena_body' Skins(1)=Texture'MagdalenaTextures.magdalena_head' IdleWeaponAnim="Idle_Biggun" IdleHeavyAnim="Idle_Biggun" IdleRifleAnim="Idle_Rifle" TurnRightAnim="TurnR" TurnLeftAnim="TurnL" CrouchAnims(0)="CrouchF" CrouchAnims(1)="CrouchB" CrouchAnims(2)="CrouchL" CrouchAnims(3)="CrouchR" CrouchTurnRightAnim="Crouch_TurnR" CrouchTurnLeftAnim="Crouch_TurnL" AirStillAnim="Jump_Mid" AirAnims(0)="JumpF_Mid" AirAnims(1)="JumpB_Mid" AirAnims(2)="JumpL_Mid" AirAnims(3)="JumpR_Mid" TakeoffStillAnim="Jump_Takeoff" TakeoffAnims(0)="JumpF_Takeoff" TakeoffAnims(1)="JumpB_Takeoff" TakeoffAnims(2)="JumpL_Takeoff" TakeoffAnims(3)="JumpR_Takeoff" LandAnims(0)="JumpF_Land" LandAnims(1)="JumpB_Land" LandAnims(2)="JumpL_Land" LandAnims(3)="JumpR_Land" DodgeAnims(0)="DodgeF" DodgeAnims(1)="DodgeB" DodgeAnims(2)="DodgeL" DodgeAnims(3)="DodgeR" DoubleJumpAnims(0)="DoubleJumpF" DoubleJumpAnims(1)="DoubleJumpB" DoubleJumpAnims(2)="DoubleJumpL" DoubleJumpAnims(3)="DoubleJumpR" MovementAnims(0)="RunF" MovementAnims(1)="RunB" MovementAnims(2)="RunL" MovementAnims(3)="RunR" SwimAnims(0)="SwimF" SwimAnims(1)="SwimB" SwimAnims(2)="SwimL" SwimAnims(3)="SwimR" WalkAnims(0)="WalkF" WalkAnims(1)="WalkB" WalkAnims(2)="WalkL" WalkAnims(3)="WalkR" WallDodgeAnims(0)="WallDodgeF" WallDodgeAnims(1)="WallDodgeB" WallDodgeAnims(2)="WallDodgeL" WallDodgeAnims(3)="WallDodgeR" IdleRestAnim="Idle_Rest" IdleCrouchAnim="Crouch" IdleSwimAnim="Swim_Thread" IdleChatAnim="idle_chat" FireHeavyRapidAnim="Biggun_Aimed" FireHeavyBurstAnim="Biggun_Burst" FireRifleRapidAnim="Rifle_Aimed" FireRifleBurstAnim="Rifle_Burst" }
Ok so far so good. That is almost all of the animations done. There are a few functions that we need to override with new ones so they play the correct animations. Lets do that next. Paste the following code into your monsters.uc file and change the animation names to match those of your chosen skin.
simulated function PlayDirectionalDeath(Vector HitLoc) { local float Decision; Decision = fRand(); if(Decision < 0.25) { PlayAnim('DeathF',, 0.1); } else if ( Decision > 0.25 && Decision < 0.50) { PlayAnim('DeathB',, 0.1); } else if ( Decision > 0.50 && Decision < 0.75) { PlayAnim('DeathL',, 0.1); } else { PlayAnim('DeathR',, 0.1); } } simulated function PlayDirectionalHit(Vector HitLoc) { local float Decision; Decision = fRand(); if(Decision < 0.25) { PlayAnim('TurnL',, 0.1); } else if ( Decision > 0.25 && Decision < 0.50) { PlayAnim('TurnR',, 0.1); } else if ( Decision > 0.50 && Decision < 0.75) { PlayAnim('TurnL',, 0.1); } else { PlayAnim('TurnR',, 0.1); } }
As you can see Magdalena doesn’t have any real Take Hit animations so I had to use her “TurnL” and “TurnR” animations. Use whichever seems best for your monster. Next we need to fix a bug with monsters and movers. When monsters get hit by a mover you can hear what sounds like Jakob moaning. That pesky Jakob again! We can fix that by over riding the PlayMoverHitSound function and tell it to play the HitSound instead which we will set in the defaults shortly.
function PlayMoverHitSound() { PlaySound(HitSound[0], SLOT_Interact); }
Next on the to-do list is to make the monster not attack other monsters. Monsters sometimes attack eachother by mistake. We can help avoid this by telling our monster who its friends are. We do this in the SameSpeciesAs function. Just add the following code to your monster.
function bool SameSpeciesAs(Pawn P) { //This should make the monster think it is friends with all monsters return (Monster(P) != None); } function bool SameSpeciesAs(Pawn P) { //With RPG this may mean the monster wont attack friendlymonsters. //So we could try to account for that with this code. return ( (Monster(P) != None) && (Monster(P).Controller != None && !Monster(P).Controller.IsA('FriendlyMonster')) ); }
This should tell the monster to not attack other hostile monsters. Compile and test your monster in game. (Don’t forget to delete the old .u file before re-compiling!) It should be looking pretty good. But you will notice a few things still need to be done. The monster is very quiet and although it chases you around, it doesn’t actually attack! Lets add some sound to the monster. The skin you chose might of come with some sounds as well, if it didn’t you will have to find or make your own sounds! You can import your own sounds into the sound browser of the UnrealED and then save it out as your own .uax file or you can import sounds directly into your .u file. This Wiki Page Will show You How. You don’t have to include sounds but it really adds character to the monster. These are the default sounds that should be changed.
defaultproperties { HitSound(0)= HitSound(1)= HitSound(2)= HitSound(3)= DeathSound(0)= DeathSound(1)= DeathSound(2)= DeathSound(3)= ChallengeSound(0)= ChallengeSound(1)= ChallengeSound(2)= ChallengeSound(3)= }
If you plan your monster to fire projectiles you will want to also include “FireSound=” in that list! Magdalena didn’t come with any sounds so i’ve decided to use some sounds that come with the default monsters. These sounds can be found in the UnrealEd>Sound browser> open SkaarjPack_rc in the drop down menu. You can play sounds directly by code when you want them, this will be covered in a further tutorial. Your monsters .uc should look something like this.
class MagdalenaMonster extends Monster; simulated function PlayDirectionalDeath(Vector HitLoc) { local float Decision; Decision = fRand(); if(Decision < 0.25) { PlayAnim('DeathF',, 0.1); } else if ( Decision > 0.25 && Decision < 0.50) { PlayAnim('DeathB',, 0.1); } else if ( Decision > 0.50 && Decision < 0.75) { PlayAnim('DeathL',, 0.1); } else { PlayAnim('DeathR',, 0.1); } } simulated function PlayDirectionalHit(Vector HitLoc) { local float Decision; Decision = fRand(); if(Decision < 0.25) { PlayAnim('TurnL',, 0.1); } else if ( Decision > 0.25 && Decision < 0.50) { PlayAnim('TurnR',, 0.1); } else if ( Decision > 0.50 && Decision < 0.75) { PlayAnim('TurnL',, 0.1); } else { PlayAnim('TurnR',, 0.1); } } function PlayMoverHitSound() { PlaySound(HitSound[0], SLOT_Interact); } function bool SameSpeciesAs(Pawn P) { return (Monster(P) != None); } defaultproperties { Mesh=SkeletalMesh'Magdalena.Magdalena' Skins(0)=Texture'MagdalenaTextures.magdalena_body' Skins(1)=Texture'MagdalenaTextures.magdalena_head' IdleWeaponAnim="Idle_Biggun" IdleHeavyAnim="Idle_Biggun" IdleRifleAnim="Idle_Rifle" TurnRightAnim="TurnR" TurnLeftAnim="TurnL" CrouchAnims(0)="CrouchF" CrouchAnims(1)="CrouchB" CrouchAnims(2)="CrouchL" CrouchAnims(3)="CrouchR" CrouchTurnRightAnim="Crouch_TurnR" CrouchTurnLeftAnim="Crouch_TurnL" AirStillAnim="Jump_Mid" AirAnims(0)="JumpF_Mid" AirAnims(1)="JumpB_Mid" AirAnims(2)="JumpL_Mid" AirAnims(3)="JumpR_Mid" TakeoffStillAnim="Jump_Takeoff" TakeoffAnims(0)="JumpF_Takeoff" TakeoffAnims(1)="JumpB_Takeoff" TakeoffAnims(2)="JumpL_Takeoff" TakeoffAnims(3)="JumpR_Takeoff" LandAnims(0)="JumpF_Land" LandAnims(1)="JumpB_Land" LandAnims(2)="JumpL_Land" LandAnims(3)="JumpR_Land" DodgeAnims(0)="DodgeF" DodgeAnims(1)="DodgeB" DodgeAnims(2)="DodgeL" DodgeAnims(3)="DodgeR" DoubleJumpAnims(0)="DoubleJumpF" DoubleJumpAnims(1)="DoubleJumpB" DoubleJumpAnims(2)="DoubleJumpL" DoubleJumpAnims(3)="DoubleJumpR" MovementAnims(0)="RunF" MovementAnims(1)="RunB" MovementAnims(2)="RunL" MovementAnims(3)="RunR" SwimAnims(0)="SwimF" SwimAnims(1)="SwimB" SwimAnims(2)="SwimL" SwimAnims(3)="SwimR" WalkAnims(0)="WalkF" WalkAnims(1)="WalkB" WalkAnims(2)="WalkL" WalkAnims(3)="WalkR" WallDodgeAnims(0)="WallDodgeF" WallDodgeAnims(1)="WallDodgeB" WallDodgeAnims(2)="WallDodgeL" WallDodgeAnims(3)="WallDodgeR" IdleRestAnim="Idle_Rest" IdleCrouchAnim="Crouch" IdleSwimAnim="Swim_Thread" IdleChatAnim="idle_chat" FireHeavyRapidAnim="Biggun_Aimed" FireHeavyBurstAnim="Biggun_Burst" FireRifleRapidAnim="Rifle_Aimed" FireRifleBurstAnim="Rifle_Burst" HitSound(0)=Sound'SkaarjPack_rc.injur1sk' HitSound(1)=Sound'SkaarjPack_rc.injur1sk' HitSound(2)=Sound'SkaarjPack_rc.injur1sk' HitSound(3)=Sound'SkaarjPack_rc.injur1sk' DeathSound(0)=Sound'SkaarjPack_rc.death1br' DeathSound(1)=Sound'SkaarjPack_rc.death1br' DeathSound(2)=Sound'SkaarjPack_rc.death1br' DeathSound(3)=Sound'SkaarjPack_rc.death1br' ChallengeSound(0)=Sound'SkaarjPack_rc.scuttle1pp' ChallengeSound(1)=Sound'SkaarjPack_rc.scuttle1pp' ChallengeSound(2)=Sound'SkaarjPack_rc.scuttle1pp' ChallengeSound(3)=Sound'SkaarjPack_rc.scuttle1pp' }
Excellent! now all we need to do is decide how our monster will attack. Go back to the Tutorials page and select your chosen monster attack method! If your especially lazy you can click here to take a shortcut!
You can download the MagdalenaMonster.uc file at this stage and use it as a base class if you wish:Magdalana Base Class
TIP – When you cook food for your monster, ensure it is piping hot before consumption!
Recent Comments