//============================================================================= // DualMag. // by Smartball // 22-04-07: permission granted for use in FS // 04.10.2007: travel bSlave added /Zora // // hey sorry Z i had to put it back into its old naming state, // i wasn't in the mood of processing 30 maps or so individually replacing every dm's :p /Turbo //============================================================================= class DualMag expands FSWeapon; // Some ideas and coding style were adapted from Bane's AkimboMag // The idle coding and the script to get the guns to fire alternately all came from Bane's // Smartball var() int hitdamage; var float AltAccuracy; var int ClipCount, Fired, NumMags; Var DualMag Slave; var travel bool bSlave; Replication { reliable if( Role == ROLE_Authority ) Slave; } simulated event RenderOverlays( canvas Canvas ) { Super.RenderOverlays(Canvas); if (Slave != None) { Slave.SetLocation(Owner.Location + Slave.CalcDrawOffset() ); Slave.setRotation(Pawn(Owner).ViewRotation); Canvas.DrawActor(Slave, false); } } function AltFire( float Value ) { bPointing=True; AltAccuracy = 0.4; CheckVisibility(); if (AmmoType.UseAmmo(1)) { if ( PlayerPawn(Owner) != None ) PlayerPawn(Owner).ShakeView(ShakeTime, ShakeMag, ShakeVert); PlayAnim('T1', 1.3, 0.05); GotoState('AltFiring'); } } function PlayFiring() { ClipCount++; Owner.PlaySound(FireSound, SLOT_None,2.0*Pawn(Owner).SoundDampening); } /////////////////////////////////////////////////////// state NormalFire { Begin: NumMags = 1; If(Slave != None) NumMags = 2; Fired = 1 - Fired; If((Fired == 1) && (Slave != None)) { if (AnimSequence!='Shoot0') { Slave.PlayAnim('Shoot',2.5, 0.02); Sleep(0.1); } Slave.PlayAnim('Shoot0',0.26, 0.04); Sleep(0.2); } Else { if (AnimSequence!='Shoot0') { PlayAnim('Shoot',2.5, 0.02); If(NumMags == 1) FinishAnim(); Else Sleep(0.1); } PlayAnim('Shoot0',0.26, 0.04); If(NumMags == 1) FinishAnim(); Else Sleep(0.2); } if (ClipCount>15 * NumMags) Owner.PlaySound(Misc1Sound, SLOT_None, 3.5*Pawn(Owner).SoundDampening); if ( bChangeWeapon ) GotoState('DownWeapon'); else if ( PlayerPawn(Owner) == None ) Super.Finish(); else if ( (AmmoType.AmmoAmount<=0) || (Pawn(Owner).Weapon != self) ) GotoState('Idle'); else if (ClipCount>=20 * NumMags) GoToState('NewClip'); else if ( Pawn(Owner).bFire!=0 ) Global.Fire(0); else if ( Pawn(Owner).bAltFire!=0 )Global.AltFire(0); PlayAnim('Shoot2',0.8, 0.0); FinishAnim(); GoToState('Idle'); Finish(); } //////////////////////////////////////////////////////// state NewClip { ignores Fire, AltFire; Begin: if( FSMarine(Owner)!=None ) { PlayAnim('Twiddle',0.6,0.1); while( FSMarine(Owner)!=None && !FSMarine(Owner).CanReloadWeapon() ) Sleep(0.5); if( FSMarine(Owner)!=None ) FSMarine(Owner).NotifyWeaponReload(); } PlayAnim('Eject',1.5,0.05); If(Slave != None) Slave.PlayAnim('Eject',1.5,0.05); Owner.PlaySound(Misc2Sound, SLOT_None,1.0*Pawn(Owner).SoundDampening); FinishAnim(); If(Slave != None) Slave.FinishAnim(); PlayAnim('Down',1.2,0.05); If(Slave != None) Slave.PlayAnim('Down',1.2,0.05); FinishAnim(); If(Slave != None) Slave.FinishAnim(); ClipCount = 0; If(Slave != None) Slave.ClipCount = 0; Owner.PlaySound(SelectSound, SLOT_None,1.0*Pawn(Owner).SoundDampening); PlayAnim('Select',1.6,0.07); If(Slave != None) Slave.PlayAnim('Select',1.6,0.07); FinishAnim(); If(Slave != None) Slave.FinishAnim(); if ( bChangeWeapon ) GotoState('DownWeapon'); else if ( Pawn(Owner).bFire!=0 ) Global.Fire(0); else if ( Pawn(Owner).bAltFire!=0 ) Global.AltFire(0); else GotoState('Idle'); } //////////////////////////////////////////////////////// state AltFiring { ignores Fire, AltFire; Begin: NumMags = 1; If(Slave != None) NumMags = 2; FinishAnim(); PlayAnim('Shot2a', 1.2, 0.05); FinishAnim(); Repeater: if (AmmoType.UseAmmo(1)) { Fired = 1 - Fired; if ( PlayerPawn(Owner) != None ) PlayerPawn(Owner).ShakeView(ShakeTime, ShakeMag, ShakeVert); ClipCount++; Owner.PlaySound(FireSound, SLOT_None,2.0*Pawn(Owner).SoundDampening); TraceFire(AltAccuracy); if ((Fired == 1) && (Slave != None)) Slave.PlayAnim('Shot2b', 0.4, 0.05); else PlayAnim('Shot2b', 0.4, 0.05); if (NumMags == 2) Sleep(0.13); else FinishAnim(); } if ( AltAccuracy < 3 ) AltAccuracy += 0.5; if (ClipCount>15 * NumMags) Owner.PlaySound(Misc1Sound, SLOT_None, 3.5*Pawn(Owner).SoundDampening); if ( bChangeWeapon ) GotoState('DownWeapon'); else if ( Pawn(Owner).Weapon != Self ) GotoState('Idle'); else if ((Pawn(Owner).bAltFire!=0) && AmmoType.AmmoAmount>0 && ClipCount<20 * NumMags) { if ( PlayerPawn(Owner) == None ) Pawn(Owner).bAltFire = int( FRand() < AltReFireRate ); Goto('Repeater'); } else if (ClipCount>=20 * NumMags) GoToState('NewClip'); If((Fired == 1) && (Slave != None)) Slave.PlayAnim('Shot2c', 0.7, 0.05); PlayAnim('Shot2c', 0.7, 0.05); FinishAnim(); If(Slave != None) Slave.PlayAnim('T2', 0.9, 0.05); PlayAnim('T2', 0.9, 0.05); FinishAnim(); Finish(); } function ProcessTraceHit(Actor Other, Vector HitLocation, Vector HitNormal, Vector X, Vector Y, Vector Z) { local shellcase s; local vector realLoc; realLoc = Owner.Location + CalcDrawOffset(); If((Slave != None) && (Fired == 0)) s = Spawn(class'ShellCase',Pawn(Owner), '', realLoc + 20 * X + Slave.FireOffset.Y * Y + Z); else s = Spawn(class'ShellCase',Pawn(Owner), '', realLoc + 20 * X + FireOffset.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); if (Other == Level) Spawn(class'WallHitEffect',,, 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 PlayPostSelect() { ClipCount = 0; } function Finish() { if ( bChangeWeapon ) GotoState('DownWeapon'); else if ( PlayerPawn(Owner) == None ) Super.Finish(); else if ( (AmmoType.AmmoAmount<=0) || (Pawn(Owner).Weapon != self) ) GotoState('Idle'); else if (ClipCount>=20) GoToState('NewClip'); else if ( /*bFireMem ||*/ Pawn(Owner).bFire!=0 ) Global.Fire(0); else if ( /*bAltFireMem ||*/ Pawn(Owner).bAltFire!=0 ) Global.AltFire(0); else GotoState('Idle'); } function PlayAltFiring() { Owner.PlaySound(FireSound, SLOT_None,2.0*Pawn(Owner).SoundDampening); PlayAnim('Shot2b', 0.4, 0.05); } state Idle { function Timer() { local float rnd; if (Slave != None) { rnd=FRand(); if (rnd>0.95 && Slave.AnimSequence!='Twiddle') { Slave.PlayAnim('Twiddle',0.6,0.3); } else if (rnd>0.8 && Slave.AnimSequence!='Sway1') { Slave.LoopAnim('Sway1',0.02, 0.3); } } rnd=Frand(); if (rnd>0.95 && AnimSequence!='Twiddle') { PlayAnim('Twiddle',0.6,0.3); } else if (rnd>0.8 && AnimSequence!='Sway1') { LoopAnim('Sway1',0.02, 0.3); } } Begin: bPointing=False; if ( (AmmoType != None) && (AmmoType.AmmoAmount<=0) ) Pawn(Owner).SwitchToBestWeapon(); //Goto Weapon that has Ammo Disable('AnimEnd'); if (Slave != None) Slave.LoopAnim('Sway1',0.02, 0.1); LoopAnim('Sway1',0.02, 0.1); SetTimer(1.0,True); if ( /*bFireMem ||*/ Pawn(Owner).bFire!=0 ) Global.Fire(0.0); if ( /*bAltFireMem ||*/ Pawn(Owner).bAltFire!=0 ) Global.AltFire(0.0); } function TraceFire( float Accuracy ) { local vector HitLocation, HitNormal, StartTrace, EndTrace, X,Y,Z; local actor Other; local Pawn PawnOwner; PawnOwner = Pawn(Owner); Owner.MakeNoise(PawnOwner.SoundDampening); GetAxes(PawnOwner.ViewRotation,X,Y,Z); If((Slave != None) && (Fired == 0)) StartTrace = Owner.Location + CalcDrawOffset() + Slave.FireOffset.X * X + Slave.FireOffset.Y * Y + Slave.FireOffset.Z * Z; Else StartTrace = Owner.Location + CalcDrawOffset() + FireOffset.X * X + FireOffset.Y * Y + FireOffset.Z * Z; AdjustedAim = PawnOwner.AdjustAim(1000000, StartTrace, 2.75*AimError, False, False); EndTrace = StartTrace + Accuracy * (FRand() - 0.5 )* Y * 1000 + Accuracy * (FRand() - 0.5 ) * Z * 1000; X = vector(AdjustedAim); EndTrace += (10000 * X); Other = PawnOwner.TraceShot(HitLocation,HitNormal,EndTrace,StartTrace); ProcessTraceHit(Other, HitLocation, HitNormal, X,Y,Z); } function SetTwoHands() { if ( Slave == None ) return; if ( (PlayerPawn(Owner) != None) && (PlayerPawn(Owner).Handedness == 2) ) { SetHand(2); return; } if ( Mesh == mesh'AutoMagL' ) SetHand(1); else SetHand(-1); } function setHand(float Hand) { if ( Hand == 2 ) { bHideWeapon = true; Super.SetHand(Hand); return; } if ( Slave != None ) { if ( Hand == 0 ) Hand = -1; Slave.SetHand(-1 * Hand); } bHideWeapon = false; Super.SetHand(Hand); if ( Hand == 1 ) Mesh = mesh'AutoMagL'; else Mesh = mesh'AutoMagR'; } function Dualmag SpawnSecondMag() { Slave = Spawn( class'DualMag' ); if ( Slave != None ) { bSlave = true; Slave.AmmoType = AmmoType; Slave.SetOwner(Owner); Slave.SetHand(255); Slave.BecomeItem(); Slave.BringUp(); SetTwoHands(); } return Slave; } function bool HandlePickupQuery( inventory Item ) { If (Item.Class == Class) { if (Slave == None) { Slave = SpawnSecondMag(); if ( Slave != None ) Pawn(Owner).ClientMessage( "You got another automag!" ); } If(AmmoType != None) AmmoType.AddAmmo(DualMag(Item).PickUpAmmoCount); Item.PlaySound(Item.PickupSound); Item.SetRespawn(); Return True; } Return Super.HandlePickupQuery(Item); } function TweenDown() { if (Slave != None) { if ( (Slave.AnimSequence != '') && (Slave.GetAnimGroup(Slave.AnimSequence) == 'Select') ) TweenAnim( Slave.AnimSequence, Slave.AnimFrame * 0.4 ); else Slave.PlayAnim('Down', 1.0, 0.05); } if ( (AnimSequence != '') && (GetAnimGroup(AnimSequence) == 'Select') ) TweenAnim( AnimSequence, AnimFrame * 0.4 ); else PlayAnim('Down', 1.0, 0.05); } function TweenSelect() { if (Slave != None) Slave.TweenAnim('Select',0.001); TweenAnim('Select',0.001); } function PlaySelect() { if (Slave != None) Slave.PlayAnim('Select',1.0,0.0); Super.PlaySelect(); } function DropFrom(vector StartLocation) { Super.DropFrom(StartLocation); If(Slave != None) Slave.Destroy(); Slave = None; bSlave = false; } function inventory SpawnCopy( pawn Other ) { local inventory Copy; Local Weapon newWeapon; // If ( (bTossedOut == False) && ( Level.Game.ShouldRespawn(self) ) ) If ( ( Level.Game.ShouldRespawn(self) ) ) { Copy = spawn(Class,Other); Copy.Tag = Tag; Copy.Event = Event; GotoState('Sleeping'); } Else { Copy = Self; } Copy.RespawnTime = 0.0; Copy.bHeldItem = true; Copy.GiveTo( Other ); newWeapon = Weapon(Copy); newWeapon.Instigator = Other; newWeapon.GiveAmmo(Other); newWeapon.SetSwitchPriority(Other); if ( !Other.bNeverSwitchOnPickup ) newWeapon.WeaponSet(Other); newWeapon.AmbientGlow = 0; return newWeapon; } //============================================================================= // Inventory travelling across servers (hack for the second mag to spawn across servers). event TravelPostAccept() { Super.TravelPostAccept(); if ( bSlave ) SpawnSecondMag(); } defaultproperties { bTravel=True hitdamage=17 AmmoName=Class'UnrealShare.ShellBox' PickupAmmoCount=50 bInstantHit=True bAltInstantHit=True FireOffset=(X=0.00,Y=-10.00,Z=-4.00), shakemag=200.00 shakevert=4.00 AIRating=0.20 RefireRate=0.70 AltRefireRate=0.90 FireSound=Sound'UnrealShare.AutoMag.shot' AltFireSound=Sound'UnrealShare.AutoMag.shot' CockingSound=Sound'UnrealShare.AutoMag.Cocking' SelectSound=Sound'UnrealShare.AutoMag.Cocking' Misc1Sound=Sound'UnrealShare.flak.Click' Misc2Sound=Sound'UnrealShare.AutoMag.Reload' AutoSwitchPriority=2 InventoryGroup=2 PickupMessage="You got the Automag" ItemName="Automag" ItemArticle="an" PlayerViewOffset=(X=4.80,Y=-1.70,Z=-2.70), PlayerViewMesh=LodMesh'UnrealShare.AutoMagL' PickupViewMesh=LodMesh'UnrealShare.AutoMagPickup' ThirdPersonMesh=LodMesh'UnrealShare.auto3rd' PickupSound=Sound'UnrealShare.Pickups.WeaponPickup' Mesh=LodMesh'UnrealShare.AutoMagPickup' bNoSmooth=False CollisionRadius=25.00 CollisionHeight=10.00 Mass=15.00 }