[Document]翻Projectile Weapon的时候发现的一些可能有用的东西

Firing Mode Definition

/************************************************************************************
 * Firing Mode Definition
 ***********************************************************************************/

/**
 * This enum defines the firing type for the weapon.
 *	EWFT_InstantHit  - The weapon traces a shot to determine a hit and immediately causes an effect
 *	EWFT_Projectile  - The weapon spawns a new projectile pointed at the crosshair
 *	EWFT_Custom      - Requires a custom fire sequence
 */

enum EWeaponFireType
{
	EWFT_InstantHit,
	EWFT_Projectile,
	EWFT_Custom,
	EWFT_None
};

The Class of Projectile to spawn

/** The Class of Projectile to spawn */
var				Array< class<Projectile> >	WeaponProjectiles;

Returns the type of projectile to spawn

/**
 * Returns the type of projectile to spawn.  We use a function so subclasses can
 * override it if needed (case in point, homing rockets).
 */
function class<Projectile> GetProjectileClass()
{
	return (CurrentFireMode < WeaponProjectiles.length) ? WeaponProjectiles[CurrentFireMode] : None;
}

Perform all logic associated with firing a shot

/**
 * FireAmmunition: Perform all logic associated with firing a shot
 * - Fires ammunition (instant hit or spawn projectile)
 * - Consumes ammunition
 * - Plays any associated effects (fire sound and whatnot)
 *
 * Network: LocalPlayer and Server
 */

simulated function FireAmmunition()
{
    // Use ammunition to fire
    ConsumeAmmo( CurrentFireMode );

    // Handle the different fire types
    switch( WeaponFireTypes[CurrentFireMode] )
    {
        case EWFT_InstantHit:
            InstantFire();
            break;

        case EWFT_Projectile:
            ProjectileFire();
            break;

        case EWFT_Custom:
            CustomFire();
            break;
    }

    NotifyWeaponFired( CurrentFireMode );
}

Fires a projectile.

/**
 * Fires a projectile.
 * Spawns the projectile, but also increment the flash count for remote client effects.
 * Network: Local Player and Server
 */

simulated function Projectile ProjectileFire()
{
    local vector        StartTrace, EndTrace, RealStartLoc, AimDir;
    local ImpactInfo    TestImpact;
    local Projectile    SpawnedProjectile;

    // tell remote clients that we fired, to trigger effects
    IncrementFlashCount();

    if( Role == ROLE_Authority )
    {
        // This is where we would start an instant trace. (what CalcWeaponFire uses)
        StartTrace = Instigator.GetWeaponStartTraceLocation();
        AimDir = Vector(GetAdjustedAim( StartTrace ));

        // this is the location where the projectile is spawned.
        RealStartLoc = GetPhysicalFireStartLoc(AimDir);

        if( StartTrace != RealStartLoc )
        {
            // if projectile is spawned at different location of crosshair,
            // then simulate an instant trace where crosshair is aiming at, Get hit info.
            EndTrace = StartTrace + AimDir * GetTraceRange();
            TestImpact = CalcWeaponFire( StartTrace, EndTrace );

            // Then we realign projectile aim direction to match where the crosshair did hit.
            AimDir = Normal(TestImpact.HitLocation - RealStartLoc);
        }

        // Spawn projectile
        SpawnedProjectile = Spawn(GetProjectileClass(), Self,, RealStartLoc);
        if( SpawnedProjectile != None && !SpawnedProjectile.bDeleteMe )
        {
            SpawnedProjectile.Init( AimDir );
        }

        // Return it up the line
        return SpawnedProjectile;
    }

    return None;
}

returns the world location for spawning the projectile

/**
 * This function returns the world location for spawning the projectile, pulled in to the Pawn's collision along the AimDir direction.
 */
simulated native event vector GetPhysicalFireStartLoc(optional vector AimDir);

 This is the default Firing State

/*********************************************************************************************
 * state WeaponFiring
 * This is the default Firing State.  It's performed on both the client and the server.
 *********************************************************************************************/
simulated state WeaponFiring
{
    ignores AllowSprinting;

    simulated function BeginState(Name PrevStateName)
    {
        local KFPerk InstigatorPerk;

        InstigatorPerk = GetPerk();
        if( InstigatorPerk != none )
        {
            SetZedTimeResist( InstigatorPerk.GetZedTimeModifier(self) );
        }

        if ( bLoopingFireAnim.Length > 0 || bLoopingFireSnd.Length > 0 )
        {
            StartLoopingFireEffects(CurrentFireMode);
        }

        super.BeginState(PrevStateName);
    }

    simulated event Tick(float DeltaTime)
    {
        Global.Tick(DeltaTime);

        // Stop the looping fire sound if we're in zed time and want to play single fire sounds
        if( bPlayingLoopingFireSnd && ShouldForceSingleFireSound() )
        {
            StopLoopingFireSound(CurrentFireMode);
        }
    }

    /**
     * Timer event, call is set up in Weapon::TimeWeaponFiring().
     * The weapon is given a chance to evaluate if another shot should be fired.
     * This event defines the weapon's rate of fire.
     */
    simulated function RefireCheckTimer()
    {
        local KFPerk InstigatorPerk;

        InstigatorPerk = GetPerk();
        if( InstigatorPerk != none )
        {
            SetZedTimeResist( InstigatorPerk.GetZedTimeModifier(self) );
        }

        super.RefireCheckTimer();
    }

    simulated function EndState(Name NextStateName)
    {
        super.EndState(NextStateName);

        ClearZedTimeResist();

        // Simulate weapon firing effects on the local client
        if( WorldInfo.NetMode == NM_Client )
        {
            Instigator.WeaponStoppedFiring(self, false);
        }

        if ( bPlayingLoopingFireAnim || bPlayingLoopingFireAnim )
        {
            StopLoopingFireEffects(CurrentFireMode);
        }
    }

    /** Override to continue any looping fire anims */
    simulated event OnAnimEnd(AnimNodeSequence SeqNode, float PlayedTime, float ExcessTime)
    {
        local name WeaponFireAnimName;

        if ( WorldInfo.NetMode != NM_DedicatedServer )
        {
            // If loop start or another event such as IronSights transition ended, restart looping fire anim.
            if ( bPlayingLoopingFireAnim )
            {
                WeaponFireAnimName = GetLoopingFireAnim(CurrentFireMode);
                if ( WeaponFireAnimName != '' )
                {
                    PlayAnimation(WeaponFireAnimName, MySkelMesh.GetAnimLength(WeaponFireAnimName), true, 0.f);
                }
            }
        }
    }

    /** don't allow for a pickup to switch the weapon */
    simulated function bool DenyClientWeaponSet()
    {
        return true;
    }

    /** Gets the current animation rate, scaled or not */
    simulated function float GetThirdPersonAnimRate()
    {
        local KFPerk CurrentPerk;
        local float ScaledRate;

        ScaledRate = 1.0f;
        CurrentPerk = GetPerk();
        if( CurrentPerk != none )
        {
            CurrentPerk.ModifyRateOfFire( ScaledRate, self );
        }

        return 1.f / ScaledRate;
    }
}

 Adjusts weapon aiming direction

/**
 * Adjusts weapon aiming direction.
 * Gives controller a chance to modify the aiming of the pawn. For example aim error, auto aiming, adhesion, AI help...
 * Requested by weapon prior to firing.
 *
 * Completely overrides super to support free-aim hip shots going where the muzzle is pointed (modified block is marked)
 *
 * @param    W, weapon about to fire
 * @param    StartFireLoc, world location of weapon fire start trace, or projectile spawn loc.
 * @param    BaseAimRot, original aiming rotation without any modifications.
 */
function Rotator GetAdjustedAimFor( Weapon W, vector StartFireLoc )
{
    local vector    FireDir, HitLocation, HitNormal;
    local actor        BestTarget, HitActor;
    local float        bestAim, bestDist;
    local bool        bNoAimCorrection, bInstantHit;
    local rotator    BaseAimRot;

    bInstantHit = ( W == None || W.bInstantHit );
    BaseAimRot = (Pawn != None) ? Pawn.GetBaseAimRotation() : Rotation;

    if( W != none )
    {
        // Add in the weapon buffer rotation for recoil/sway
        BaseAimRot += WeaponBufferRotation;
    }

    // Clients are done after WeaponBufferRotation unless aim correction is on
    if( Role < ROLE_Authority && !AimingHelp(bInstantHit) )
    {
        return BaseAimRot;
    }

    FireDir    = vector(BaseAimRot);
    HitActor = Trace(HitLocation, HitNormal, StartFireLoc + W.GetTraceRange() * FireDir, StartFireLoc, true);

    if ( (HitActor != None) && HitActor.bProjTarget )
    {
        BestTarget = HitActor;
        bNoAimCorrection = true;
        BestDist = VSize(BestTarget.Location - Pawn.Location);
    }
    else
    {
        // adjust aim based on FOV
        bestAim = 0.90;
        if ( AimingHelp(bInstantHit) )
        {
            bestAim = AimHelpDot(bInstantHit);
        }
        else if ( bInstantHit )
            bestAim = 1.0;

        BestTarget = PickAimAtTarget(bestAim, bestDist, FireDir, StartFireLoc, W.WeaponRange);
        if ( BestTarget == None )
        {
            return BaseAimRot;
        }
    }

    ShotTarget = Pawn(BestTarget);
    if ( !AimingHelp(bInstantHit) )
    {
        return BaseAimRot;
    }

    if ( !bNoAimCorrection && W != None )
    {
        ProcessAimCorrection(ShotTarget, KFWeapon(W), StartFireLoc, BaseAimRot);
    }
    return BaseAimRot;
}

 

posted @ 2017-07-09 17:53  ArHShRn  阅读(452)  评论(0编辑  收藏  举报