Always snap to grid
Legacy:TheHealer/TUTHealerFireSource
From Unreal Wiki, The Unreal Engine Documentation Site
TUTHealerFire - The Healer Part 5 of 9 - Complete Source Code[edit]
//------------------------------------------------------------------------------ // class name : TUTHealerFire // class type : Weapon Fire // description: The Healer's Primary Fire mode // author : HSDanClark //------------------------------------------------------------------------------ // TODO : // //------------------------------------------------------------------------------ class TUTHealerFire extends WeaponFire; const NoDamage = 0; var TUTHealerBeamEffect Beam; var Sound MakeLinkSound; var float UpTime; var Pawn LockedPawn; var float LinkBreakTime; var() float LinkBreakDelay; var float LinkScale[6]; var String MakeLinkForce; var() class<DamageType> DamageType; var() int Damage; var() float MomentumTransfer; var() float TraceRange; var() float LinkFlexibility; var bool bDoHit; var() bool bFeedbackDeath; var bool bInitAimError; var bool bLinkFeedbackPlaying; var bool bStartFire; var rotator DesiredAimError, CurrentAimError; simulated function DestroyEffects() { Super.DestroyEffects(); if ( Level.NetMode != NM_Client ) { if (Beam != None) Beam.Destroy(); } } simulated function ModeTick(float dt) { local Vector StartTrace, EndTrace, X,Y,Z; local Vector HitLocation, HitNormal, EndEffect; local Actor Other; local Rotator Aim; local TUTHealer TUTHealer; local float MT, Step; local bot B; local bool bShouldStop; local TUTHealerBeamEffect LB; local Pawn P; if (!bIsFiring) { bInitAimError = true; return; } TUTHealer = TUTHealer(Weapon); if (FlashEmitter != None) { // set muzzle flash color FlashEmitter.Skins[0] = Texture'XEffectMat.link_muz_green'; // adjust muzzle flash size to link size FlashEmitter.mSizeRange[0] = FlashEmitter.default.mSizeRange[0] * 1; FlashEmitter.mSizeRange[1] = FlashEmitter.mSizeRange[0]; } if ( TUTHealer.Ammo[ThisModeNum].AmmoAmount >= AmmoPerFire && ((UpTime > 0.0) || (Instigator.Role < ROLE_Authority)) ) { UpTime -= dt; TUTHealer.GetViewAxes(X,Y,Z); // the to-hit trace always starts right in front of the eye StartTrace = Instigator.Location + Instigator.EyePosition() + X*Instigator.CollisionRadius; TraceRange = default.TraceRange; if ( Instigator.Role < ROLE_Authority ) { if ( Beam == None ) foreach DynamicActors(class'TUTHealerBeamEffect', LB ) if ( !LB.bDeleteMe && (LB.Instigator != None) && (LB.Instigator == Instigator) ) { Beam = LB; break; } if ( Beam != None ) LockedPawn = Beam.LinkedPawn; } if ( LockedPawn != None ) TraceRange *= 1.5; if ( LockedPawn != None ) { EndTrace = LockedPawn.Location + LockedPawn.EyeHeight*Vect(0,0,0.5); // beam ends at approx gun height } if ( LockedPawn == None ) { if ( Bot(Instigator.Controller) != None ) { if ( bInitAimError ) { CurrentAimError = AdjustAim(StartTrace, AimError); bInitAimError = false; } else { BoundError(); CurrentAimError.Yaw = CurrentAimError.Yaw + Instigator.Rotation.Yaw; } // smooth aim error changes Step = 7500.0 * dt; if ( DesiredAimError.Yaw ClockWiseFrom CurrentAimError.Yaw ) { CurrentAimError.Yaw += Step; if ( !(DesiredAimError.Yaw ClockWiseFrom CurrentAimError.Yaw) ) { CurrentAimError.Yaw = DesiredAimError.Yaw; DesiredAimError = AdjustAim(StartTrace, AimError); } } else { CurrentAimError.Yaw -= Step; if ( DesiredAimError.Yaw ClockWiseFrom CurrentAimError.Yaw ) { CurrentAimError.Yaw = DesiredAimError.Yaw; DesiredAimError = AdjustAim(StartTrace, AimError); } } CurrentAimError.Yaw = CurrentAimError.Yaw - Instigator.Rotation.Yaw; if ( BoundError() ) DesiredAimError = AdjustAim(StartTrace, AimError); CurrentAimError.Yaw = CurrentAimError.Yaw + Instigator.Rotation.Yaw; Aim = Rotator(Instigator.Controller.Target.Location - StartTrace); Aim.Yaw = CurrentAimError.Yaw; // save difference CurrentAimError.Yaw = CurrentAimError.Yaw - Instigator.Rotation.Yaw; } else Aim = AdjustAim(StartTrace, AimError); X = Vector(Aim); EndTrace = StartTrace + TraceRange * X; } Other = Trace(HitLocation, HitNormal, EndTrace, StartTrace, true); if (Other != None && Other != Instigator) EndEffect = HitLocation; else EndEffect = EndTrace; if (Beam != None) Beam.EndEffect = EndEffect; if ( Instigator.Role < ROLE_Authority ) return; if (Other != None && Other != Instigator) { // beam is updated every frame, but damage is only done based on the firing rate if (bDoHit) { if (Beam != None) Beam.bLockedOn = false; Instigator.MakeNoise(1.0); if ( !Other.bWorldGeometry ) { P = Pawn(Other); if (Other.Physics == PHYS_Falling || Other.Physics == PHYS_Flying || Other.Physics == PHYS_Swimming) MT = DeathMatch(Level.Game).LinkLockDownFactor * MomentumTransfer; else MT = 0.0; // This is the key, this is where we give health instead of taking damage. P.GiveHealth(3,199); if (Beam != None) Beam.bLockedOn = true; } } } } if ( bShouldStop ) B.StopFiring(); else { // beam effect is created and destroyed when firing starts and stops if ( (Beam == None) && bIsFiring ) Beam = Spawn(class'TUTHealerBeamEffect',Instigator); if (Beam != None) { Beam.LinkColor = 0; Beam.LinkedPawn = LockedPawn; Beam.bHitSomething = (Other != None); Beam.EndEffect = EndEffect; } else { StopFiring(); } } bStartFire = false; bDoHit = false; } function bool BoundError() { CurrentAimError.Yaw = CurrentAimError.Yaw & 65535; if ( CurrentAimError.Yaw > 2048 ) { if ( CurrentAimError.Yaw < 32768 ) { CurrentAimError.Yaw = 2048; return true; } else if ( CurrentAimError.Yaw < 63487 ) { CurrentAimError.Yaw = 63487; return true; } } return false; } function DoFireEffect() { bDoHit = true; UpTime = FireRate+0.1; } function PlayFiring() { if (Weapon.Ammo[ThisModeNum].AmmoAmount >= AmmoPerFire) ClientPlayForceFeedback("BLinkGunBeam1"); Super.PlayFiring(); } function StopFiring() { if (Beam != None) { Beam.Destroy(); Beam = None; } bStartFire = true; bFeedbackDeath = false; StopForceFeedback("BLinkGunBeam1"); } simulated function vector GetFireStart(vector X, vector Y, vector Z) { return Instigator.Location + Instigator.EyePosition() + X*Instigator.CollisionRadius; } function StartBerserk() { // Damage = default.Damage * 1.33; // Damage = default.Damage * 1.33; } function StopBerserk() { // Damage = default.Damage; // Damage = default.Damage; } defaultproperties { NoAmmoSound=Sound'WeaponSounds.P1Reload5' AmmoClass=class'TUTHealerAmmo' AmmoPerFire=1 DamageType=class'DamTypeLinkShaft' Damage=-15 MomentumTransfer=20000.0 bPawnRapidFireAnim=true FireAnim=AltFire FireEndAnim=None MakeLinkSound=Sound'WeaponSounds.LinkGun.LinkActivated' MakeLinkForce="LinkActivated" FlashEmitterClass=class'xEffects.LinkMuzFlashBeam1st' TraceRange=1100 // range of everything LinkFlexibility=0.64 // determines how easy it is to maintain a link. // 1=must aim directly at linkee, 0=linkee can be 90 degrees to either side of you LinkBreakDelay=0.5 // link will stay established for this long extra when blocked (so you don't have to worry about every last tree getting in the way) FireRate=0.2 BotRefireRate=0.99 WarnTargetPct=+0.2 ShakeOffsetMag=(X=0.0,Y=1.0,Z=1.0) ShakeOffsetRate=(X=1000.0,Y=1000.0,Z=1000.0) ShakeOffsetTime=3 ShakeRotMag=(X=0.0,Y=0.0,Z=60.0) ShakeRotRate=(X=0.0,Y=0.0,Z=4000.0) ShakeRotTime=6 bInitAimError=true LinkScale(0)=0.0 LinkScale(1)=0.5 LinkScale(2)=0.9 LinkScale(3)=1.2 LinkScale(4)=1.4 LinkScale(5)=1.5 }