Worst-case scenario: the UEd Goblin wipes the map and burns down your house.

Legacy:Trystan/11 17 02c

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search

11/17/02 Adding a Weapon

Parts of a weapon

M16A2X.uc 
The main weapon class.
M16A2Fire.uc 
The class that handles primary fire.
M16A2AltFire.uc 
The class that handles secondary fire.
M16A2Pickup.uc 
The class that handles a player or bot picking the item up.
M16Arena.uc 
The class that substitutes your weapon for another, based on the XPaks.

Notes

Examining the structure of a weapon I think I'm ready to discuss how to add one without first dissecting Actor.uc, Inventory.uc, and Weapon.uc. I'll still examine them soon but I'm itching to get some solid results in.

There's two parts to a weapon: the weapon itself and the bullet it fires. We're not going to be using instant hit weapons; every weapon we create will be a projectile based weapon. So the first class we create is going to be M16A2X.

//=============================================================================
// M16A2
//=============================================================================
class M16A2X extends Weapon
    config(user);
 
defaultproperties
{
	FireModeClass(0)	=	Class'M16A2Fire'
    FireModeClass(1)	=	Class'M16A2AltFire'
    PickupClass			=	Class'M16A2Pickup'
    SelectAnim			=	"Pickup"
    PutDownAnim			=	"PutDown"
    SelectSound			=	Sound'WeaponSounds.FlakCannon.SwitchToFlakCannon'
    SelectForce			=	"SwitchToFlakCannon"
    AIRating			=	0.750000
    CurrentRating		=	0.750000
    EffectOffset		=	(X=200.000000,Y=32.000000,Z=-25.000000)
    DisplayFOV			=	60.000000
    Priority			=	8
    DefaultPriority		=	8
    InventoryGroup		=	7
    PlayerViewOffset	=	(X=-7.000000,Y=8.000000)
    PlayerViewPivot		=	(Yaw=16884,Roll=200)
    BobDamping			=	1.400000
    AttachmentClass		=	Class'XWeapons.FlakAttachment'
    IconMaterial		=	Texture'InterfaceContent.HUD.SkinA'
    IconCoords			=	(X1=322,Y1=100,X2=444,Y2=200)
    ItemName			=	"M16A2"
    LightType			=	LT_Steady
    LightEffect			=	LE_NonIncidence
    LightBrightness		=	150.000000
    LightRadius			=	4.000000
    LightHue			=	30
    LightSaturation		=	150
    Mesh				=	SkeletalMesh'Weapons.Flak_1st'
    UV2Texture			=	Shader'XGameShaders.WeaponShaders.WeaponEnvShader'
}

We extend Weapon, and leave it at that. This is pretty much a complete rip of FlakCannon.uc as you can tell by the defaultproperties. We don't have an M16 model, bullet, or sounds yet – we're just itching to play around. Two important things I noted were the FireModeClass(0) and FireModeClass(1). They specify what class is called with primary or alternate fire is called. The pickup class is the class that happens when you actually pick the weapon up. What that means will make more sense in a few seconds I think.

Next class up is M16A2Fire.uc.

class M16A2Fire extends ProjectileFire;
 
function InitEffects()
{
	Super.InitEffects();
	if( FlashEmitter != None )
		Weapon.AttachToBone(FlashEmitter, 'tip');
}
 
defaultproperties
{
	ProjPerFire			=	1 // was 9
	ProjSpawnOffset		=	(X=25.000000,Y=5.000000,Z=-6.000000)
	FireEndAnim			=	"None"
	FireSound			=	SoundGroup'WeaponSounds.FlakCannon.FlakCannonFire'
	FireForce			=	"FlakCannonFire"
	FireRate			=	0.150000
	AmmoClass			=	Class'XWeapons.FlakAmmo'
	AmmoPerFire			=	1
	ShakeRotTime		=	2.000000
	ShakeOffsetMag		=	(X=-20.000000)
	ShakeOffsetRate		=	(X=-1000.000000)
	ShakeOffsetTime		=	2.000000
	ProjectileClass		=	Class'WorldAtWar.Bullet556mm'
	BotRefireRate		=	0.700000
	FlashEmitterClass	=	Class'XEffects.FlakMuzFlash1st'
	Spread 				=	40.000000
	SpreadStyle			=	SS_Random
}

We extend ProjectileFire and leave it pretty well at that. This code was based on FlakCannonFire.uc. One of the things that needs to be investigated more in the above code is SpreadStyle. For the M16A2 we don't really want a random spread style but we'll leave it alone for now. Declared herein is the ProjectileClass that's used when this gun fires, in this case Bullet556mm. We'll define that class in a second. AmmoPerFire and ProjPerFire are both important as well. They specify, respectively, the ammunition consumed per click of the fire button and the number of projectiles issued by each click. They can be different for various reasons.

Next up is M16A2AltFire.uc.

class M16A2AltFire extends ProjectileFire;
 
function InitEffects()
{
	Super.InitEffects();
	if( FlashEmitter != None )
		Weapon.AttachToBone(FlashEmitter, 'tip');
}
 
defaultproperties
{
	ProjPerFire			=	3 // was 9
	ProjSpawnOffset		=	(X=25.000000,Y=5.000000,Z=-6.000000)
	FireEndAnim			=	"None"
	FireSound			=	SoundGroup'WeaponSounds.FlakCannon.FlakCannonFire'
	FireForce			=	"FlakCannonFire"
	FireRate			=	0.150000
	AmmoClass			=	Class'XWeapons.FlakAmmo'
	AmmoPerFire			=	3
	ShakeRotTime		=	2.000000
	ShakeOffsetMag		=	(X=-20.000000)
	ShakeOffsetRate		=	(X=-1000.000000)
	ShakeOffsetTime		=	2.000000
	ProjectileClass		=	Class'WorldAtWar.Bullet556mm'
	BotRefireRate		=	0.700000
	FlashEmitterClass	=	Class'XEffects.FlakMuzFlash1st'
	Spread 				=	40.000000
	SpreadStyle			=	SS_Random
}

Here we've run into an interesting problem. I had wanted the M16A2's alternate fire to be semi auto so I used 3 for AmmoPerFire and 3 for ProjPerFire. The problem is that all three projectiles are fired at once, in what appears to be a large lump. I've yet to figure this out but I'm sure I will.

Problem found: Apparently no game time passes while you're in UnrealScript. So all three projectiles seem to be fired at the same time, at the same velocity, at the same angle. The solutions I've seen posted include setting a timer for whatever duration you want in between each bullet, and having the timer fire the bullets.

Mychaeel: You might want to look into state code and latent functions – with that you can code sequences like that which are meant to progress over (game) time straightforwardly:
Trystan: oooooooooooooooooooooo.. thank you.
state FiringThreeProjectiles {
  Begin:
    FireOneProjectile();
    Sleep(0.5);  // Sleep is a latent function
    FireOneProjectile();
    Sleep(0.5);
    FireOneProjectile();
}

M16A2Pickup.uc

class M16A2Pickup extends WeaponPickup;
 
function SetWeaponStay()
{
	bWeaponStay = true;
}
 
function float GetRespawnTime()
{
	return 5.0000;
}
 
defaultproperties
{
    InventoryType=Class'M16A2X'
    PickupMessage="You got the M16A2."
}

This is fairly simple. Of note is the SetWeaponStay() (does the weapon disappear after someone picks it up?) and the respawn time (only used if the weapon does not stay). In default properties you can see we specify the class attached to this weapon (M16A2X.uc) and the message given to the player when they pick an object of this type up.

We've defined our weapon, now we just have to give it ammunition to fire.



Return to Trystan/Developer Journal.