The three virtues of a programmer: Laziness, Impatience, and Hubris. – Larry Wall

Legacy:EONSBioRifle

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

Status: Incomplete Functionality. Feel free to help me finish this weapon!

Description: The EONS Bio Rifle is intended as an improved version of the UT2004 Bio Rifle, primarily for use in the ONS gametype where long engagement ranges and the interaction of biogoo with vehicles makes the weapon subpar.

New Features:

1. Single Fire Primary is gone. Primary fire now charges up on hold. Single glob fire can be achieved via tapping the fire button.

2. (Does not work) Using the charged fire mode, the EONS Bio Rifle can be alternated between firing a single concentrated glob and a horizontal line of blobs (number of blobs determined by current charge level).

3. (Currently disabled, seeking a solution to 2.) When the aiming reticle is held on a target for a short period of time, the Bio Rifle automatically primes itself to launch glob projectiles at a higher velocity, giving the weapon additional effectiveness at longer ranges.

4. Secondary fire unleashes a stream of aerosolized bio goo, providing effective destruction in a short range at the expense of quickly expending the weapon's ammo.*

  • This firing mode has a minor error that shows up in UT2004's log,

Current code is provided below.

//===================
// EONSBioRifle
// Alternate Fire uses code modified from Mr. Pants' Excessive Overkill FlamethrowerEX written by Dan 'MadNad' Woodall
//===================
 
class EONSBioRifle extends BioRifle;
 
var Pawn SeekTarget;
var float LockTime, UnLockTime, SeekCheckTime;
var bool bLockedOn, bBreakLock;
var bool bLineSpread;
var Sound LockOnSound, LockBrokenSound;
var() float SeekCheckFreq, SeekRange;
var() float LockRequiredTime, UnLockRequiredTime;
var() float LockAim;
var() Color CrosshairColor;
var() float CrosshairX, CrosshairY;
 
 
replication
{
    reliable if (Role == ROLE_Authority && bNetOwner)
        bLockedOn;
 
    reliable if (Role < ROLE_Authority)
        ServerSetLineSpread, ServerClearLineSpread;
}
 
function Tick(float dt)
{
    local Pawn Other;
    local Vector StartTrace;
    local Rotator Aim;
    local float BestDist, BestAim;
 
    if (Instigator == None || Instigator.Weapon != self)
        return;
 
    if ( Role < ROLE_Authority )
        return;
 
    if ( !Instigator.IsHumanControlled() )
        return;
 
    if (Level.TimeSeconds > SeekCheckTime)
    {
        if (bBreakLock)
        {
            bBreakLock = false;
            bLockedOn = false;
            SeekTarget = None;
        }
 
        StartTrace = Instigator.Location + Instigator.EyePosition();
        Aim = Instigator.GetViewRotation();
 
        BestAim = LockAim;
        Other = Instigator.Controller.PickTarget(BestAim, BestDist, Vector(Aim), StartTrace, SeekRange);
 
        if ( CanLockOnTo(Other) )
        {
            if (Other == SeekTarget)
            {
                LockTime += SeekCheckFreq;
                if (!bLockedOn && LockTime >= LockRequiredTime)
                {
                    bLockedOn = true;
                    PlayerController(Instigator.Controller).ClientPlaySound(LockOnSound);
                 }
            }
            else
            {
                SeekTarget = Other;
                LockTime = 0.0;
            }
            UnLockTime = 0.0;
        }
        else
        {
            if (SeekTarget != None)
            {
                UnLockTime += SeekCheckFreq;
                if (UnLockTime >= UnLockRequiredTime)
                {
                    SeekTarget = None;
                    if (bLockedOn)
                    {
                        bLockedOn = false;
                        PlayerController(Instigator.Controller).ClientPlaySound(LockBrokenSound);
                    }
                }
            }
            else
                 bLockedOn = false;
         }
 
        SeekCheckTime = Level.TimeSeconds + SeekCheckFreq;
    }
}
 
function bool CanLockOnTo(Actor Other)
{
    local Pawn P;
 
    P = Pawn(Other);
 
    if (P == None || P == Instigator || !P.bProjTarget)
        return false;
 
    if (!Level.Game.bTeamGame)
        return true;
 
    if ( (Instigator.Controller != None) && Instigator.Controller.SameTeamAs(P.Controller) )
        return false;
 
    return ( (P.PlayerReplicationInfo == None) || (P.PlayerReplicationInfo.Team != Instigator.PlayerReplicationInfo.Team) );
}
 
simulated event RenderOverlays( Canvas Canvas )
{
    if (bLockedOn)
    {
        Canvas.DrawColor = CrosshairColor;
        Canvas.DrawColor.A = 255;
        Canvas.Style = ERenderStyle.STY_Alpha;
 
        Canvas.SetPos(Canvas.SizeX*0.5-CrosshairX, Canvas.SizeY*0.5-CrosshairY);
        Canvas.DrawTile(Texture'SniperArrows', CrosshairX*2.0, CrosshairY*2.0, 0.0, 0.0, Texture'SniperArrows'.USize, Texture'SniperArrows'.VSize);
    }
 
    Super.RenderOverlays(Canvas);
}
 
simulated function SetLineSpread(bool bNew, optional bool bForce)
{
    if ( (bLineSpread != bNew) || bForce )
    {
        bLineSpread = bNew;
        if ( bLineSpread )
            ServerSetLineSpread();
        else
            ServerClearLineSpread();
    }
}
 
function ServerClearLineSpread()
{
    bLineSpread = false;
}
 
function ServerSetLineSpread()
{
    bLineSpread = true;
}
 
//
 
//This determines Volley/Spread
simulated event ClientStartFire(int Mode)
{
    local int OtherMode;
 
    if ( EONSBioMultiFire(FireMode[Mode]) != None )
    {
        SetLineSpread(false);
    }
    else
    {
        if ( Mode == 0 )
            OtherMode = 1;
        else
            OtherMode = 0;
 
        if ( FireMode[OtherMode].bIsFiring || (FireMode[OtherMode].NextFireTime > Level.TimeSeconds) )
        {
            //if ( FireMode[OtherMode].Load > 0 )
                SetLineSpread(true);
            if ( bDebugging )
                log("No RL reg fire because other firing "$FireMode[OtherMode].bIsFiring$" next fire "$(FireMode[OtherMode].NextFireTime - Level.TimeSeconds));
            return;
        }
    }
    Super.ClientStartFire(Mode);
}
 
simulated function bool StartFire(int Mode)
{
    local int OtherMode;
 
    if ( Mode == 0 )
        OtherMode = 1;
    else
        OtherMode = 0;
    if ( FireMode[OtherMode].bIsFiring || (FireMode[OtherMode].NextFireTime > Level.TimeSeconds) )
        return false;
 
    return Super.StartFire(Mode);
}
 
//
 
 
defaultproperties
{
    ItemName="EONS Bio-Rifle"
 
    FireModeClass(0)=EONSBioMultiFire
    FireModeClass(1)=EONSBioAltFire
    InventoryGroup=3
 
    PickupClass=class'EONSBioRiflePickup'
    EffectOffset=(X=100.0,Y=32.0,Z=-20.0)
    AttachmentClass=class'BioAttachment'
    PutDownAnim=PutDown
 
    DisplayFOV=60
    DrawScale=1.0
    PlayerViewOffset=(X=7,Y=3,Z=0)
    SmallViewOffset=(X=19,Y=9,Z=-6)
 
    PlayerViewPivot=(Pitch=0,Roll=0,Yaw=0)
    SelectSound=Sound'WeaponSounds.FlakCannon.SwitchToFlakCannon'
    SelectForce="SwitchToFlakCannon"
 
    AIRating=+0.55
    CurrentRating=+0.55
 
    SeekCheckFreq=0.2
    SeekRange=10240
    LockRequiredTime=0.4
    UnLockRequiredTime=0.6
    LockAim=0.996 // 5 deg
 
    CustomCrosshairColor=(r=0,g=255,b=0,a=255)
 
    //Lock On Attr
    CrosshairColor=(R=0,G=255,B=0,A=255)
    CrosshairX=32
    CrosshairY=32
    LockOnSound=Sound'WeaponSounds.TAGRifle.TagTargetAquired'
    LockBrokenSound=Sound'WeaponSounds.TAGRifle.TagTargetAquired'
 
    CenteredOffsetY=-8.0
}
//===================
// EONSBioMultiFire
//===================
 
class EONSBioMultiFire extends BioChargedFire;
 
var() float TightSpread, LineSpread;
 
 
event ModeDoFire()
{
    if ( EONSBioRifle(Weapon).bLineSpread || ((Bot(Instigator.Controller) != None) && (FRand() < 0.65)) )
    {
        Spread = LineSpread;
        SpreadStyle = SS_Line;
    }
    else
    {
        SpreadStyle = SS_Ring;
        Spread = TightSpread;
    }
    EONSBioRifle(Weapon).bLineSpread = false;
    Super(ProjectileFire).ModeDoFire();
    NextFireTime = FMax(NextFireTime, Level.TimeSeconds + FireRate);
}
 
/*
function DoFireEffect()
{
 Load = GoopLoad;
 Super.DoFireEffect();
}
*/
 
function DoFireEffect()
{
    local EONSBioGlob FiredGlobs[10];
    local Vector StartProj, StartTrace, X,Y,Z;
    local Rotator Aim;
    local Vector HitLocation, HitNormal,FireLocation;
    local int p;
    local Actor Other;
    local float theta;
 
    if (SpreadStyle != SS_Line)
    {
        Log("DoFireEffect: SpreadStyle != Line");
        Super.DoFireEffect();
        return;
    }
 
    Instigator.MakeNoise(1.0);
    Weapon.GetViewAxes(X,Y,Z);
 
    StartTrace = Instigator.Location + Instigator.EyePosition();
    StartProj = StartTrace + X*ProjSpawnOffset.X + Z*ProjSpawnOffset.Z;
    if ( !Weapon.WeaponCentered() )
        StartProj = StartProj + Weapon.Hand * Y*ProjSpawnOffset.Y;
 
    // check if projectile would spawn through a wall and adjust start location accordingly
    Other = Weapon.Trace(HitLocation, HitNormal, StartProj, StartTrace, false);
    if (Other != None)
    {
        StartProj = HitLocation;
    }
 
    Aim = AdjustAim(StartProj, AimError);
 
    Log("DoFireEffect: SpreadStyle == Line");
    for (p = 0; p < GoopLoad; p++)
        {
            theta = Spread*PI/32768*(p - float(GoopLoad-1)/2.0);
            X.X = Cos(theta);
            X.Y = Sin(theta);
            X.Z = 0.0;
            //SpawnProjectile(StartProj, Rotator(X >> Aim));
            FiredGlobs[p] = EONSBioGlob(SpawnProjectile(FireLocation, Rotator(X >> Aim)));
        }
 
 
}
 
 
function projectile SpawnProjectile(Vector Start, Rotator Dir)
{
    local EONSBioGlob Glob;
 
    GotoState('');
 
    if (GoopLoad == 0) return None;
 
    if (Spread != LineSpread) //(!EONSBioRifle(Weapon).bLineSpread)
    {
       Glob = Weapon.Spawn(class'EONSBioGlob',,, Start, Dir);
       Log("Check 1");
       if ( Glob != None )
       {
          Glob.Damage *= DamageAtten;
          Glob.SetGoopLevel(GoopLoad);
          Glob.AdjustSpeed();
       }
    }
    else
    {
 
       Log("Check 2");
       if ( Glob != None )
       {
          Glob.Damage *= DamageAtten;
          Glob.SetGoopLevel(1);
          Glob.AdjustSpeed();
       }
    }
    GoopLoad = 0;
    if ( Weapon.AmmoAmount(ThisModeNum) <= 0 )
        Weapon.OutOfAmmo();
    return Glob;
}
 
 
defaultproperties
{
    AmmoClass=class'EONSBioAmmo'
    AmmoPerFire=1
 
    FireAnim=AltFire
    FireAnimRate=1.0
 
    ProjectileClass=class'EONSBioGlob'
 
    FlashEmitterClass=class'XEffects.BioMuzFlash1st'
 
    SpreadStyle=SS_Line
    TightSpread=300
    LineSpread=500
 
    ProjSpawnOffset=(X=25,Y=6,Z=-6)
 
    FireSound=Sound'WeaponSounds.BioRifle.BioRifleFire'
 
    FireForce="RocketLauncherFire"  // jdf
 
    FireRate=0.33
    TweenTime=0.0
 
    bFireOnRelease=true
    //MaxHoldTime=10.5 // FireRate*2 + 0.5
 
    bSplashDamage=true
    bRecommendSplashDamage=true
    BotRefireRate=0.6
    WarnTargetPct=+0.9
    bSplashJump=true
 
    ShakeOffsetMag=(X=-20.0,Y=0.00,Z=0.00)
    ShakeOffsetRate=(X=-1000.0,Y=0.0,Z=0.0)
    ShakeOffsetTime=2
    ShakeRotMag=(X=0.0,Y=0.0,Z=0.0)
    ShakeRotRate=(X=0.0,Y=0.0,Z=0.0)
    ShakeRotTime=2
}
//=========================================================================
// EONSBioAltFire
// Alternate Fire uses code modified from Mr. Pants' Excessive Overkill FlamethrowerEX written by Dan 'MadNad' Woodall
// ========================================================================
 
class EONSBioAltFire extends ProjectileFire;
 
var xEmitter BGas;
 
function Projectile SpawnProjectile(Vector Start, Rotator Dir)
{
    local Projectile P;
 
    if ( class'PlayerController'.Default.bSmallWeapons || Level.bClassicView )
       ProjSpawnOffset.Z = -20;
 
    else
       ProjSpawnOffset.Z = default.ProjSpawnOffset.Z;
 
    if( ProjectileClass != None )
        P = Spawn(ProjectileClass,,, Start, Dir);
 
    if( P == None )
        return None;
 
    P.Damage *= DamageAtten;
 
    return P;
 
}
 
event ModeDoFire()
{
	local Vector Dir;
 
	super.ModeDoFire();
 
	Dir = Vector(Weapon.Rotation);
 
	if ( Weapon.AmmoAmount(0) > 1 && !Instigator.isA('Bot') )
	    EONSBioRifle(Weapon).SoundVolume=255;
 
	BGas=spawn(class'EONSBioGasIgnite',Owner,,,);
	Weapon.AttachToBone(BGas, 'tip');
  BGas.mSpeedRange[0]+=Abs(VSize(Instigator.Velocity/VSize(Dir)));
  BGas.mSpeedRange[1]+=Abs(VSize(Instigator.Velocity/VSize(Dir)));
	if ( Weapon.ammoAmount(0) < 2 )
	    EONSBioRifle(Weapon).SoundVolume=0;
}
 
simulated function StopFiring()
{
		EONSBioRifle(Weapon).SoundVolume=0;
}
 
defaultproperties
{
     ProjSpawnOffset=(Y=40.000000)
     bPawnRapidFireAnim=True
     FireForce="minifireb"
     FireRate=0.06
     AmmoClass=Class'EONSBioAmmo'
     AmmoPerFire=1
     ShakeRotMag=(X=15.000000,Y=15.000000,Z=15.000000)
     ShakeRotRate=(X=10000.000000,Y=10000.000000,Z=10000.000000)
     ShakeRotTime=2.000000
     ShakeOffsetMag=(X=-5.000000)
     ShakeOffsetRate=(X=-500.000000)
     ShakeOffsetTime=2.000000
     ProjectileClass=Class'EONSBioGasProj'
     BotRefireRate=0.990000
     aimerror=120.000000
     Spread=2000.000000
}