news | about | forums | links | mods | tools | tutorials | contact

Pipebombs - author: [Parser]
Ok, for this tutorial I'll show you how to code a near-perfect pipebomb cannon and a pipebomb. The whole thing is relatively simple so I'll just go straight into the basics with the code. For the weapon, we'll have it fire out multiple pipebombs and have alt-fire detonate them. Here's the code for the weapon complete with comments:

class PipebombCannon expands TournamentWeapon; var bool bAlreadyFiring; // Don't really need this but I'm a lefty so it's nice to see a left handed model :-) function setHand(float Hand) {
Super.SetHand(Hand);
if ( Hand == 1 )
Mesh = mesh(DynamicLoadObject("Botpack.PulseGunL", class'Mesh'));
else
Mesh = mesh'PulseGunR';
}
// Could use rateself but the bots didn't use the gun right
function PlayFiring() // Plays the firing animation
{
Owner.PlaySound(FireSound, SLOT_Misc,2.0*Pawn(Owner).SoundDampening);
PlayAnim( 'Boltend', 0.3 );
bWarnTarget = (FRand() < 0.2);
}
function AltFire( float Value ) // This is the main core of the gun
{
local Vector Start, X,Y,Z;
local Pipebomb PB;
ForEach AllActors(class'PipeBomb', PB) // Calls all pipebomb actors
{
// Used settimer() because Explosion() blows player up
PB.Settimer(0.000001, false);
}
// Necessary otherwise the gun gets jammed
GoToState('AltFiring2');
}
//////////////////////////////////////////////////
// Normal projectile stuff
state NormalFire
{
function Projectile ProjectileFire(class ProjClass, float ProjSpeed, bool bWarn)
{
local Projectile D;
local int i;
local vector Start,X,Y,Z;
local Rotator StartRot, AltRotation;
D = Global.ProjectileFire(ProjClass, ProjSpeed, bWarn);
StartRot = D.Rotation;
Start = D.Location;
// Try changing 4 to 15 for ultimate carnage
for (i = 0; i< 4; i++)
{
if (AmmoType.UseAmmo(1))
{
AltRotation = StartRot;
AltRotation.Pitch += FRand()*3000-1500;
AltRotation.Yaw += FRand()*3000-1500;
AltRotation.Roll += FRand()*9000-4500;
D = Spawn(ProjectileClass,,, Start - 2 * VRand(), AltRotation);
}
}
}
Begin:
FinishAnim();
PlayAnim('Still');
Sleep(0.4);
// Turns the pulsegun barrel at the end of firing
PlayPostSelect();
Finish()
}
///////////////////////////////////////////////////
// This just makes sure that the gun doesn't jam up
state AltFiring2
{
function EndState()
{
Finish();
}
function AnimEnd()
{
Finish();
}
Begin:
GotoState('Idle');
}
///////////////////////////////////////////////////
function PlayIdleAnim()
{
PlayAnim('Still');
}
defaultproperties
{
AmmoName=Class'Botpack.PAmmo'
PickupAmmoCount=40
bAltWarnTarget=True
FireOffset=(X=15.000000,Y=-15.000000,Z=2.000000)
ProjectileClass=Class'Pipebomb'
AltProjectileClass=Class'Botpack.Plasmasphere'br> shakemag=120.000000
AIRating=0.400000
RefireRate=0.800000
FireSound=Sound'UnrealShare.ASMD.TazerFire'
SelectSound=Sound'Botpack.PulseGun.PulsePickup'
Misc1Sound=Sound'UnrealShare.Stinger.EndFire'
DeathMessage="%o was boomed by %k's %w"
AutoSwitchPriority=6
InventoryGroup=6
PickupMessage="You picked up the Pipebomb cannon"
ItemName="Pipebomb cannon"
PlayerViewOffset=(X=1.700000,Z=-2.000000)
PlayerViewMesh=LodMesh'Botpack.PulseGunR'
PickupViewMesh=LodMesh'Botpack.PulsePickup'
ThirdPersonMesh=LodMesh'Botpack.PulseGun3rd'
ThirdPersonScale=0.400000
PickupSound=Sound'UnrealShare.Pickups.WeaponPickup'
Mesh=LodMesh'Botpack.PulsePickup'
bNoSmooth=False
SoundRadius=64
SoundVolume=255
CollisionRadius=27.000000
CollisionHeight=8.000000
}

Ok, so as you can see, altfire is where the real difference is. Now all we need is a pipebomb. Here's the code, the projectile doesn't have to be anything special:

class Pipebomb expands Projectile; var bool bCanHitOwner, bHitWater; var float Count, SmokeRate; var ScriptedPawn WarnTarget; var int NumExtraGrenades;
simulated function PostBeginPlay()
{
local vector X,Y,Z;
local rotator RandRot;
Super.PostBeginPlay();
if ( Level.NetMode != NM_DedicatedServer )
PlayAnim('WingIn');
//This'll take a while to blow up
SetTimer(999999+FRand()*1,false);
if ( Role == ROLE_Authority )
{
GetAxes(Instigator.ViewRotation,X,Y,Z);
Velocity = X * (Instigator.Velocity Dot X)*0.4 + Vector(Rotation)
* (Speed + FRand() * 100);
Velocity.z += 210;
RandRot.Pitch = FRand() * 1400 - 700;
RandRot.Yaw = FRand() * 1400 - 700;
RandRot.Roll = FRand() * 1400 - 700;
MaxSpeed = 1000;
Velocity = Velocity >> RandRot;
RandSpin(50000);
bCanHitOwner = False;
if (Instigator.HeadRegion.Zone.bWaterZone)
{
bHitWater = True;
Disable('Tick');
Velocity=0.6*Velocity;
}
}
}
simulated function ZoneChange( Zoneinfo NewZone )
{
local waterring w;
if (!NewZone.bWaterZone || bHitWater) Return;
bHitWater = True;
w = Spawn(class'WaterRing',,,,rot(16384,0,0));
w.DrawScale = 0.2;
w.RemoteRole = ROLE_None;
Velocity=0.6*Velocity;
}
simulated function Timer()
{
// Try to use Explosion in the alt-fire and for some reason the owner blows up
Explosion(Location+Vect(0,0,1)*16);
}
simulated function Landed( vector HitNormal )
{
HitWall( HitNormal, None );
}
simulated function ProcessTouch( actor Other, vector HitLocation )
{
if ( (Other!=instigator) || bCanHitOwner )
Explosion(HitLocation);
}
simulated function HitWall( vector HitNormal, actor Wall )
{
bCanHitOwner = True;
// Reflect off Wall w/damping
Velocity = 0.8*(( Velocity dot HitNormal ) * HitNormal * (-2.0) + Velocity);
RandSpin(100000);
speed = VSize(Velocity);
if ( Level.NetMode != NM_DedicatedServer )
PlaySound(ImpactSound, SLOT_Misc, FMax(0.5, speed/800) );
if ( Velocity.Z > 400 )
Velocity.Z = 0.5 * (400 + Velocity.Z);
else if ( speed < 20 )
{
bBounce = False;
SetPhysics(PHYS_None);
}
}
///////////////////////////////////////////////////////
function BlowUp(vector HitLocation)
{
// Basic damage stuff
HurtRadius(damage, 200, 'corroded', MomentumTransfer, HitLocation);
MakeNoise(1.0);
}
simulated function Explosion(vector HitLocation)
{
local UT_FlameExplosion s;
BlowUp(HitLocation);
s = spawn(class'UT_FlameExplosion',,,HitLocation);
Spawn(Class'UT_Ringexplosion');
s.RemoteRole = ROLE_None;
Destroy();
}
defaultproperties
{
speed=600.000000
MaxSpeed=1000.000000
Damage=90.000000
MomentumTransfer=50000
ImpactSound=Sound'UnrealShare.ASMD.TazerFire'
Physics=PHYS_Falling
RemoteRole=ROLE_SimulatedProxy
AnimSequence=WingIn
Texture=Texture'Botpack.ASMDAlt.ASMDAlt_a00'
DrawScale=0.400000
DrawType=DT_Sprite
Style=STY_Translucent
AmbientGlow=64
bUnlit=True
bBounce=True
bFixedRotationDir=True
DesiredRotation=(Pitch=12000,Yaw=5666,Roll=2334)
}

Ok, so basically what we have is a pulsegun that fires out a bunch of pipebombs. You can then use alt-fire to detonate them prematurely. This can probably be improved, for example there's no code to distinquish the owner of the pipebombs. So in theory any pipebombs on the level shot by anybody can be blown up. However this is just a simple example of a pipebomb weapon. Hope it helps.

suggestions? questions? comments? please send them all to ray@beyondunreal.com

copyright 2001 ray davis. this site and all content belongs to me unless otherwise noted, with the exception of some tutorials. the authors retain the rights to their material, and are hosted here with their express permission. everything else is mine though, so don't steal it. bastards.
privacy