Upgradable Arms

Credit to Windex
Authored by Postal

Intermediate

DOWNLOAD ZIP

Howdy, there. If you are new to coding or don't know how to use UEd, ignore this, because this does not go over basics, and presumes that you understand what I am talking about.

Firstly I am going to start off with the Windex shotgun, like in irc log 3 and in my shotgun tutorial, here is its code, please note I made some changes.

//=============================================================================
// WoD Quad-ShotGun.
//=============================================================================
class WoDQSG expands TournamentWeapon;
//
Var Int Loads, Shots, LoadCount;
var vector OrigFireOff;
Var() Int HitDamage;
Var Bool bCase;

Var(SFX) Bool bHudAmmo;
//
function PostBeginPlay()
{
OrigFireOff=FireOffset;
LoadCount=1;
}
//
function PlayPostSelect()
{
// PlayAnim('Loading', 1.3, 0.05);
// Owner.PlaySound(Misc2Sound, SLOT_None,1.3*Pawn(Owner).SoundDampening);
GoToState('Reload');
}
//
simulated function PostRender( canvas Canvas )
{
Local Int Clip;

If (bHudAmmo)
{
If (AmmoType.AmmoAmount <= ReloadCount) Clip = AmmoType.AmmoAmount;
Else Clip = LoadCount;
Canvas.Style = ERenderStyle.STY_Normal;
Canvas.SetPos(0.5 * Canvas.ClipX, 0.8 * Canvas.ClipY);
Canvas.Font = Canvas.SmallFont;
if(LoadCount <= 1)
{
Canvas.DrawColor.R = 255;
Canvas.DrawColor.G = 0;
Canvas.DrawColor.B = 0; 
}
else
{
Canvas.DrawColor.R = 0;
Canvas.DrawColor.G = 255;
Canvas.DrawColor.B = 0;
}
Canvas.DrawText("Shells: "$LoadCount);
}
}
//
function Fire( float Value )
{
// if (AmmoType.UseAmmo(1))
if (AmmoType.UseAmmo(LoadCount))
{
GoToState('NormalFire');
}
}

function AltFire( float Value )
{
// if (AmmoType.UseAmmo(1))
if (AmmoType.AmmoAmount>0)
{
if (LoadCount < 4)
{
LoadCount++;
GoToState('Reload');
}
Else If (AmmoType.UseAmmo(LoadCount))
{
GoToState('NormalFire');
}
}
// Else GoToState('NormalFire');
}
//
state NormalFire
{
ignores Fire, AltFire;
Begin:
CheckVisibility();
bPointing=True;
if ( PlayerPawn(Owner) != None )
{
PlayerPawn(Owner).ClientInstantFlash( -0.4, vect(650, 450, 190));
PlayerPawn(Owner).ShakeView(ShakeTime, ShakeMag, ShakeVert);
}
// Owner.MakeNoise(2.0 * Pawn(Owner).SoundDampening);

for(loads=0;loads<LoadCount;Loads++)
{
bCase=True;
SetShotPattern(LoadCount, loads);
for(shots=0;shots<10;shots++)
{
TraceFire(1.7);
}
}

PlayAnim( 'Fire', 0.9, 0.05);
Owner.PlaySound(Sound'UnrealShare.flak.shot1',
SLOT_None,Pawn(Owner).SoundDampening*4.0);

LoadCount=1;
GoToState('ReLoad');
Finish();
}
//
function SetShotPattern( int LoadCount, int ShotNum )
{
FireOffset = OrigFireOff;
if (LoadCount==1) return;
else if (LoadCount==2)
{
if (ShotNum==1) FireOffset.Y -= 30;
if (ShotNum==2) FireOffset.Y += 30;
}
else if (LoadCount==3)
{
if (ShotNum==1) FireOffset.Y -= 30;
if (ShotNum==2) FireOffset.Y += 30;
if (ShotNum==3) FireOffset.Z += 30;
}
else
{
if (ShotNum==1) FireOffset.Y -= 30;
if (ShotNum==2) FireOffset.Y += 30;
if (ShotNum==3) FireOffset.Z += 30;
if (ShotNum==4) FireOffset.Z -= 30;
}
}
//
function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z)
{
If (bCase) EjectCase(X, Y, Z);

if (Other == Level)
Spawn(class'UT_LightWallHitEffect',,, HitLocation+HitNormal*9, Rotator(HitNormal));
else if ((Other != self) && (Other != Owner) && (Other != None) ) 
{
if ( FRand() < 0.2 ) X *= 5;
Other.TakeDamage(HitDamage, Pawn(Owner), HitLocation, 3000.0*X, 'shot');
if ( !Other.IsA('Pawn') && !Other.IsA('Carcass') )
spawn(class'SpriteSmokePuff',,,HitLocation+HitNormal*9);
} 
}

Simulated function EjectCase(Vector X, Vector Y, Vector Z)
{
local UT_Shellcase s;
local vector realLoc;

realLoc = Owner.Location + CalcDrawOffset();
// s = Spawn(class'UT_ShellCase',, '', realLoc + 20 * X + FireOffset.Y * Y + Z);
s = Spawn(class'UT_ShellCase',, '', realLoc + 20 * X + OrigFireOff.Y * Y + Z);
if ( s != None )
s.Eject(((FRand()*0.3+0.4)*X + (FRand()*0.2+0.2)*Y + (FRand()*0.3+1.0) * Z)*160);
s.DrawScale = 3;
bCase=False;
}
//
State Reload
{
ignores Fire, AltFire;
Begin:
FinishAnim();
PlayAnim( 'Reload', 1.2, 0.05);
Owner.PlaySound(Sound'UnrealI.flak.load1', SLOT_None,0.6*Pawn(Owner).SoundDampening);
FinishAnim();
PlayAnim( 'Fire', 1.2, 0.05);
FinishAnim();
Finish();
}

defaultproperties
{
hitdamage=5
bHudAmmo=True
AmmoName=Class'Botpack.FlakAmmo'
PickupAmmoCount=20
FireOffset=(X=20.000000,Y=-10.000000,Z=-15.000000)
shakemag=350.000000
shaketime=0.150000
shakevert=8.500000
AIRating=0.800000
SelectSound=Sound'UnrealI.flak.pdown'
MessageNoAmmo=" out of shells."
DeathMessage="%o was shot to shreds by %k's %w."
AutoSwitchPriority=8
InventoryGroup=9
PickupMessage="You got a WoD Quad-Shotgun"
ItemName="Quad-Shotgun"
PlayerViewOffset=(X=20.000000,Y=-10.000000,Z=-15.000000)
PlayerViewMesh=LodMesh'UnrealI.QuadShotHeld'
PlayerViewScale=0.700000
PickupViewMesh=LodMesh'UnrealI.QuadShotPickup'
ThirdPersonMesh=LodMesh'UnrealI.QuadShotHeld'
Mesh=LodMesh'UnrealI.QuadShotPickup'
}


Now that you know what I am working with, I will start to explain what I am doing. I am going to make this shotgun upgradeable like the disperson pistol. Unlike the multimag, this is not going to be multimode. Firstly the upgrades:

Explosive Rounds:

With this upgrade, the gun will fire round that do the same damage, but insted of a shotshell, it will be an explosive slug. Ten pellets at 5 damage a peice, can do 50 damage if all of them hit. With this, all you have to do it catch the target in the blast range to score damage.

for(loads=0;loads<LoadCount;Loads++)
{
bCase=True;
SetShotPattern(LoadCount, loads);
If (!bExplosive)
{
for(shots=0;shots<10;shots++)
{
TraceFire(1.7);
}
}
Else TraceFire(1);
}


When set to explosive rounds it will fire one slug insted of 10 pellets, and this slug will be more accurate.

function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z)
{
If (bCase) EjectCase(X, Y, Z);

If (!bExplosive)
{
if (Other == Level)
Spawn(class'UT_LightWallHitEffect',,, HitLocation+HitNormal*9, Rotator(HitNormal));
else if ((Other != self) && (Other != Owner) && (Other != None) ) 
{
if ( FRand() < 0.2 ) X *= 5;
Other.TakeDamage(HitDamage, Pawn(Owner), HitLocation, 3000.0*X, 'shot');
if ( !Other.IsA('Pawn') && !Other.IsA('Carcass') )
spawn(class'SpriteSmokePuff',,,HitLocation+HitNormal*9);
}
}
Else
{
HurtRadius( 50, 200, 'Exploded', 30000, HitLocation );
spawn(class'SpriteBallExplosion',,,HitLocation + HitNormal*16);
}
}

And that code make the explosion insted of the normal tracehit.

Accuracy:

for(loads=0;loads<LoadCount;Loads++)
{
bCase=True;
SetShotPattern(LoadCount, loads);
If (!bExplosive)
{
for(shots=0;shots<10;shots++)
{
TraceFire(1.7 * AccAlt);
}
}
Else TraceFire(1 * AccAlt);
}


You see, AccAlt is normally one, but when the gun is upgraded that is changed to 0.5 so the gun spread is a good bit smaller.

Head Shots:

else if ((Other != self) && (Other != Owner) && (Other != None) ) 
{
if ( FRand() < 0.2 ) X *= 5;
// Other.TakeDamage(HitDamage, Pawn(Owner), HitLocation, 3000.0*X, 'shot');
if ( Other.IsA('Pawn') && (HitLocation.Z - Other.Location.Z > 0.62 * Other.CollisionHeight) && bAllowHeadHit)
Other.TakeDamage(HitDamage * 2, Pawn(Owner), HitLocation, 35000 * X, 'decapitated');
else Other.TakeDamage(HitDamage, Pawn(Owner), HitLocation, 30000.0*X, 'shot');
if ( !Other.IsA('Pawn') && !Other.IsA('Carcass') )
spawn(class'SpriteSmokePuff',,,HitLocation+HitNormal*9);
}


So if bAllowHeadHit is True, pellets that hit ones head do 2x damage.

Speed:

PlayAnim( 'Reload', 1.2*Swift, 0.05);

I understand the number in the playanim is the frames per second. So I have this variable called "Swift". When I set "Swift" to 2 the gun now fires much quicker.

And the most important one:

You are probably thinking, "I can do that, why is that crazed idiot droning on and on so long?" Well I'm just wasting your precious time with examples. Here's the important stuff:

function bool HandlePickupQuery( inventory Item )
{
If (bUpgradable == True)
{
if ( Item.IsA('MiniGun2') )
{ 
PlayerPawn(Owner).ClientMessage("Weapon Upgraded: Speed.",'Event',true);
Swift=2;
Item.SetRespawn();
return true;
}
if ( Item.IsA('UT_Eightball') )
{ 
PlayerPawn(Owner).ClientMessage("Weapon Upgraded: Explosive.",'Event',true);
bExplosive=True;
Item.SetRespawn();
return true;
}
if ( Item.IsA('SniperRifle') )
{ 
PlayerPawn(Owner).ClientMessage("Weapon Upgraded: Accuracy.",'Event',true);
AccAlt= 0.5;
Item.SetRespawn();
return true;
}
if ( Item.IsA('Ripper') )
{ 
PlayerPawn(Owner).ClientMessage("Weapon Upgraded: Decapitation.",'Event',true);
bAllowHeadHit=True;
Item.SetRespawn();
return true;
}
if ( Item.IsA('WoDUQSG') )
{ 
PlayerPawn(Owner).ClientMessage("Weapon Downgraded: Reset.",'Event',true);
bExplosive=False;
Swift=1;
AccAlt=1;
AmmoType.AddAmmo(AmmoType.MaxAmmo);
Item.SetRespawn();
return true;
}
else return Super.HandlePickupQuery(Item);
}
else return Super.HandlePickupQuery(Item);
}


So you see, I have this set so when you run over one of these weapons, you gun gets upgraded, and the weapon is set to respawn. As well if you happen to grab another WoD Upgradeable Quad-Shotgun the gun is reset to its default setting, but you get full ammo. You could easily alter this to keep people from having certain weapon combinations, or set it any number of other ways. Notice in this setup, I have it so you don't get the weapon, but the weapon still disappears, you could change that. Hope you got the idea, playing around with HandlePickupQuery can be quite fun. Good luck and go postal!



Visitors Since December 26, 2000