Overview
This Tutorial will show you how to create a melee weapon with existing animations. It will be a simple example. With this tutorial you should be able to create your own simple melee weapons.
Introduction
This Tutorial will show you how to create a melee weapon with existing animations. It will be a simple example. You should be able to create your own simple melee weapons after reading this guide.
You’ll need the Postal Development Kit and maybe a picture editor like Gimp or Photoshop.
Creating a fake Shader
The first step is to create a invisible shader to „hide“ an existing weaponmesh.
Go to Texture Browser and File->New..
It’s up to you how you call the Package, Group and Name but the MaterialClass needs to be „Class’Engine.Shader‘ “
After pressing the „New“-Button, the Shader Properties Window will open.
Change the OutputBlending to „OB_Invisible“ and close the window and save your new texture package.
Choose your Animation
Go to the Animations Browser and open the Package „MP_Weapons“. Inside of this package we have most of the first person weapon animations.
In this case We want to modify the MP_LS_Baton animation:
WARNING: Don’t save any changes in this package. If you want to change something work with a copy of this package!!!
Modify Animation Skins
The default Material on slot 1 is Texture’WeaponSkins.baton_timb‘. We want to change it to our fake shader. That means we change it from Texture’WeaponSkins.baton_timb‘ to Shader’BoneWeaponTex.WeaponFake‘ (or however you called your fakeshader).
After changing the Material, the baton will become invisible.
Adding our new weapon-mesh to the existing animation
Finding the bone name
First we need the bone name of the baton. For this we press the „View bones“- and the „View bone names“-buttons. It will look like this:
Add a new Socket
Setup Socket
Here we see a lot of setting. Important to us are:
- BoneName -> Type in a bone name
- AttachAlias -> any name you want
- TestStaticMesh -> the StaticMesh you want to use as a weapon
- Test_Scale -> sets the scale, similar to DrawScale
- A_Rotation -> sets the rotation of your new weapon
- A_Translation -> sets the location of your new weapon
The boolean ContinuousUpdate helps to see where our new weapon is, when you change any parameter.
For the Boneweapon I use this setting:
- BoneName =“MESH_Baton“
- AttachAlias=“Bone“
- Test_Scale=0.5
- TestStaticMesh= StaticMesh’Timb_mesh.Champ.champ_bone_timb’
- A_Translation : X=-4.0, Y=-1.4, Z=1.0
-
Here you see the result:
Create your own package
Open your POSTAL2Editor folder and create a folder and call it „FlintstoneWeapon“. Feel free to give it a different name. Open your new folder and create another folder called „Classes“. Inside this folder we will put in our scripts.
Create script files
When you create a weapon mod you need:
- a weapon
- a weapon pickup
- a weapon attachment
- weapon ammoinv
- a damagetype
- an actor
- and of cause a mutator
For this mod create *.uc-files with this names:
- „BoneWeapon.uc“
- „BonePickup.uc“
- „BoneAttachment.uc“
- „BoneAmmoInv.uc“
- „BoneDamage.uc“
- „BoneActor.uc“
- „MutFlintstoneWeapon.uc“
Start coding …
Important: The name of your script file needs to be the name of your class!
BoneActor
This is the simplest class. It inherits from Actor and just stores some information needed later.
So fill in your BoneActor.uc with this code and save the file:
//this class actually does nothing special class BoneActor extends Actor; defaultproperties { DrawType=DT_StaticMesh StaticMesh=StaticMesh’Timb_mesh.Champ.champ_bone_timb’ DrawScale=0.5 }
BoneDamage
We make want to make a subclass of the batonweapon so I decide to subclass it’s damagetype.
The code for the class looks like this:
class BoneDamage extends BatonDamage abstract; defaultproperties { DeathString=”%o got hurt by %k’s bones.” }
BonePickup
This class represents the weapon when it lays around or when we drop it.
Here is the code:
class BonePickup extends P2WeaponPickup; defaultproperties { BounceSound=Sound’MiscSounds.Props.woodhitsground1′ InventoryType=Class’BoneWeapon’ PickupMessage=”You picked up a Bone.” //this message is displayed when you pick up the Bone DrawType=DT_StaticMesh StaticMesh=StaticMesh’Timb_mesh.Champ.champ_bone_timb’ //the used static mesh DrawScale=0.500000 //how big the bonepickup should be }
BoneAttachment
The BoneAttachment is used to see the Bone in 3rd person mode:
class BoneAttachment extends P2WeaponAttachment; defaultproperties { WeapClass=Class’BoneWeapon’ //the name of your weaponclass DrawType=DT_StaticMesh FiringMode=”BATON1″ RelativeRotation=(Pitch=0,Yaw=0,Roll=32768) StaticMesh=StaticMesh’Timb_mesh.Champ.champ_bone_timb’ DrawScale=0.5 }
BoneAmmoInv
This class handles he ammo of a weapon. Melee-weapons normally have infinite ammo, that‘s why this class inherits from InfiniteAmmoInv.
The property „Texture“ stores the later inventory icon. You should create your own icon to see a bone inside your inventory.
//this is a slightly changed copy of BatonAmmoInv class BoneAmmoInv extends InfiniteAmmoInv; var Sound BoneHit; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// function ProcessTraceHit(Weapon W, Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z) { local SmokeHitPuff smoke1; local DirtClodsMachineGun dirt1; local SparkHitMachineGun spark1; local Rotator NewRot; local vector mom; local float UseDamage; if ( Other == None ) return; if(Pawn(Other) == None && PeoplePart(Other) == None) { // randomly orient the splat on the wall (rotate around the normal) NewRot = Rotator(-HitNormal); NewRot.Roll=(65536*FRand()); smoke1 = Spawn(class’Fx.SmokeHitPuffMelee’,,,HitLocation, Rotator(HitNormal)); if(FRand()<0.3) { dirt1 = Spawn(class’Fx.DirtClodsMachineGun’,,,HitLocation, Rotator(HitNormal)); } if(FRand()<0.15) { spark1 = Spawn(class’Fx.SparkHitMachineGun’,,,HitLocation, Rotator(HitNormal)); } } if ( (Other != self) && (Other != Owner) ) { Instigator.PlaySound(BoneHit, SLOT_None, 1.0,,TransientSoundRadius,GetRandPitch()); if(Level.Game != None && Level.Game.bIsSinglePlayer) UseDamage = DamageAmount; else UseDamage = DamageAmountMP; if(!P2Weapon(W).bAltFiring) { if(FPSPawn(Other) == None || HurtingAttacker(FPSPawn(Other))) Other.TakeDamage(UseDamage, Pawn(Owner), HitLocation, -MomentumHitMag*Y + MomentumHitMag*vect(0, 0, 1.0)*(FRand() + 0.2), DamageTypeInflicted); } else { if(FPSPawn(Other) == None || HurtingAttacker(FPSPawn(Other))) { mom = VRand(); mom.z=0; mom.x*=0.1; mom.y*=0.1; Other.TakeDamage(UseDamage, Pawn(Owner), HitLocation, -MomentumHitMag*Z + MomentumHitMag*mom, DamageTypeInflicted); } } } } defaultproperties { DamageAmount=10 DamageAmountMP=25 bInstantHit=true Texture= Texture’Engine.S_Actor’ // Your hud icon DamageTypeInflicted=class’BoneDamage’ //your Damagetype MomentumHitMag=30000 BoneHit=Sound’WeaponSounds.baton_hit’//your Sound TransientSoundRadius=80 }
BoneWeapon
We modify the Baton weapon. This code enables us to see the bone instead of the Baton
class BoneWeapon extends BatonWeapon; var BoneActor Bone; simulated function PostNetBeginPlay() { local PlayerController PC; local Pawn P; Super.PostNetBeginPlay(); P = Pawn(Owner); PC = PlayerController(P.Controller); if (P.IsLocallyControlled() && PC!=None && (!PC.bBehindView) ) { Bone = Spawn(Class’BoneActor’); AttachToBone( Bone, ‘MESH_Baton’ ); // Bone.SetRelativeRotation(rot(-2000,0,0)); //-> not needed here Bone.SetRelativeLocation(vect(-4,-1.4,1));//X,Y,Z } } //without this function the bone would remain in your hand function DropFrom(vector StartLocation) { Super.DropFrom(StartLocation); if (Bone != None) { DetachFromBone(Bone); Bone.Destroy(); Bone = None; } } simulated function Destroyed() { Super.Destroyed(); if( Bone != None ) { DetachFromBone(Bone); Bone.Destroy(); Bone = None; } } defaultproperties { GroupOffset=23 AmmoName=Class’BoneAmmoInv’ PickupClass=Class’BonePickup’ AttachmentClass=Class’BoneAttachment’ Skins(0)=Texture’MP_FPArms.LS_arms.LS_hands_dude’ Skins(1)=Shader’BoneWeaponTex.WeaponFake’ //without this assignment you would see the baton ThirdPersonRelativeLocation=(X=5.200000,Y=-2.00000,Z=1.000000) ThirdPersonRelativeRotation=(Pitch=-16384,Yaw=0,Roll=0) ItemName=”Bone” }
MutFlintstoneWeapon
This will be the mutator we see in Postal 2 Workshop. The name oft he class won‘t be displayed inside the game – the FriendlyName will be displayed.
Using the ModifyPlayerInventory-function is the easiest way to access the players inventory.
Class MutFlintstoneWeapon extends P2GameMod; //this is the easiest way to add a new weapon to the players inventory function ModifyPlayerInventory(Pawn Other) { if (P2Pawn(Other) != None) P2Pawn(Other).CreateInventory(“FlintstoneWeapon.BoneWeapon”); Super.ModifyPlayerInventory(Other); } defaultproperties { GroupName=”” FriendlyName=”Boneweapon” Description=”With this mod you get a mighty bone – wow” }
Compiling
How to compile & test a mod is covered in this tutorial:
My first Mod
Result
When you are done the mod will look like this: