/// <summary>
    /// Cause recoil in the specified direction, no effect if shaking
    /// </summary>
    /// <param name="dir">direction to recoil</param>
    /// <param name="cameraRecoilConfig">configuration for the recoil</param>
    public void Recoil(Vector2 dir, CameraRecoilConfig cameraRecoilConfig)
    {
        if (isShaking)
        {
            return;
        }
        this.activeRecoilConfig = cameraRecoilConfig;
        if (recoilOffsetDestination != Vector2.zero)
        {
            //recoil from current position
            Vector2 newRecoilOffsetDestination = recoilOffset + dir.normalized * activeRecoilConfig.Distance;
            //cap it so we don't recoil further than the maximum from our origin
            if (newRecoilOffsetDestination.magnitude > activeRecoilConfig.Distance)
            {
                newRecoilOffsetDestination = dir.normalized * activeRecoilConfig.Distance;
            }

            recoilOffsetDestination = newRecoilOffsetDestination;

            //ensure we will reach our max recoil sooner based on how close we already our to our recoil destination
            float distanceFromDestination = (recoilOffset - recoilOffsetDestination).magnitude;
            float distanceFromOrigin      = recoilOffsetDestination.magnitude;

            recoilTime = activeRecoilConfig.RecoilDuration * (distanceFromDestination / distanceFromOrigin);
        }
        else
        {
            //begin recoiling
            recoilOffsetDestination = dir.normalized * activeRecoilConfig.Distance;
            recoilTime = activeRecoilConfig.RecoilDuration;
        }
    }
Exemple #2
0
    /// <summary>
    /// Perform and display the shot locally (i.e. only on this instance of the game). Does not
    /// communicate anything to other players (unless this is the server, in which case the server
    /// will determine the effects of the bullet). Does not do any validation. This should only be invoked
    /// when displaying the results of a shot (i.e. after receiving a ShootMessage or after this client performs a shot)
    /// or when server is determining the outcome of the shot.
    /// </summary>
    /// <param name="shooter">gameobject of the shooter</param>
    /// <param name="finalDirection">direction the shot should travel (accuracy deviation should already be factored into this)</param>
    /// <param name="damageZone">targeted damage zone</param>
    /// <param name="isSuicideShot">if this is a suicide shot (aimed at shooter)</param>
    public void DisplayShot(GameObject shooter, Vector2 finalDirection,
                            BodyPartType damageZone, bool isSuicideShot)
    {
        //if this is our gun (or server), last check to ensure we really can shoot
        if ((isServer || PlayerManager.LocalPlayer == shooter) &&
            CurrentMagazine.ClientAmmoRemains <= 0)
        {
            if (isServer)
            {
                Logger.LogTrace("Server rejected shot - out of ammo", Category.Firearms);
            }

            return;
        }
        //Add too the cooldown timer to being allowed to shoot again
        FireCountDown += 1.0 / FireRate;
        CurrentMagazine.ExpendAmmo();
        //get the bullet prefab being shot
        GameObject bullet = PoolManager.PoolClientInstantiate(Resources.Load(Projectile.name) as GameObject,
                                                              shooter.transform.position);

        BulletBehaviour b = bullet.GetComponent <BulletBehaviour>();

        if (isSuicideShot)
        {
            b.Suicide(shooter, this, damageZone);
        }
        else
        {
            b.Shoot(finalDirection, shooter, this, damageZone);
        }


        //add additional recoil after shooting for the next round
        AppendRecoil();

        SoundManager.PlayAtPosition(FiringSound, shooter.transform.position);
        //jerk screen back based on recoil angle and power
        if (shooter == PlayerManager.LocalPlayer)
        {
            //Default recoil params until each gun is configured separately
            if (CameraRecoilConfig == null || CameraRecoilConfig.Distance == 0f)
            {
                CameraRecoilConfig = new CameraRecoilConfig
                {
                    Distance         = 0.2f,
                    RecoilDuration   = 0.05f,
                    RecoveryDuration = 0.6f
                };
            }
            Camera2DFollow.followControl.Recoil(-finalDirection, CameraRecoilConfig);
        }


        shooter.GetComponent <PlayerSprites>().ShowMuzzleFlash();
    }
Exemple #3
0
    /// <summary>
    /// Perform and display the shot locally (i.e. only on this instance of the game). Does not
    /// communicate anything to other players (unless this is the server, in which case the server
    /// will determine the effects of the bullet). Does not do any validation. This should only be invoked
    /// when displaying the results of a shot (i.e. after receiving a ShootMessage or after this client performs a shot)
    /// or when server is determining the outcome of the shot.
    /// </summary>
    /// <param name="shooter">gameobject of the shooter</param>
    /// <param name="finalDirection">direction the shot should travel (accuracy deviation should already be factored into this)</param>
    /// <param name="damageZone">targeted damage zone</param>
    /// <param name="isSuicideShot">if this is a suicide shot (aimed at shooter)</param>
    public void DisplayShot(GameObject shooter, Vector2 finalDirection,
                            BodyPartType damageZone, bool isSuicideShot)
    {
        //if this is our gun (or server), last check to ensure we really can shoot
        if ((isServer || PlayerManager.LocalPlayer == shooter) &&
            CurrentMagazine.ClientAmmoRemains <= 0)
        {
            if (isServer)
            {
                Logger.LogTrace("Server rejected shot - out of ammo", Category.Firearms);
            }

            return;
        }
        //TODO: If this is not our gun, simply display the shot, don't run any other logic
        if (shooter == PlayerManager.LocalPlayer)
        {
            //this is our gun so we need to update our predictions
            FireCountDown += 1.0 / FireRate;
            //add additional recoil after shooting for the next round
            AppendRecoil();

            //Default camera recoil params until each gun is configured separately
            if (CameraRecoilConfig == null || CameraRecoilConfig.Distance == 0f)
            {
                CameraRecoilConfig = new CameraRecoilConfig
                {
                    Distance         = 0.2f,
                    RecoilDuration   = 0.05f,
                    RecoveryDuration = 0.6f
                };
            }
            Camera2DFollow.followControl.Recoil(-finalDirection, CameraRecoilConfig);
        }

        //call ExpendAmmo outside of previous check, or it won't run serverside and state will desync.
        CurrentMagazine.ExpendAmmo();

        //display the effects of the shot

        //get the bullet prefab being shot
        GameObject bullet = Spawn.ClientPrefab(Resources.Load(Projectile.name) as GameObject,
                                               shooter.transform.position).GameObject;
        BulletBehaviour b = bullet.GetComponent <BulletBehaviour>();

        if (isSuicideShot)
        {
            b.Suicide(shooter, this, damageZone);
        }
        else
        {
            b.Shoot(finalDirection, shooter, this, damageZone);
        }
        SoundManager.PlayAtPosition(FiringSound, shooter.transform.position);
        shooter.GetComponent <PlayerSprites>().ShowMuzzleFlash();
    }
Exemple #4
0
        public virtual void OnSpawnServer(SpawnInfo info)
        {
            if (MagInternal)
            {
                //automatic ejection always disabled
                SmartGun = false;
                //ejecting an internal mag should never be allowed
                allowMagazineRemoval = false;
            }

            //Default recoil if one has not been set already
            if (CameraRecoilConfig == null || CameraRecoilConfig.Distance == 0f)
            {
                var Recoil = new CameraRecoilConfig
                {
                    Distance         = 0.2f,
                    RecoilDuration   = 0.05f,
                    RecoveryDuration = 0.6f
                };
                SyncCameraRecoilConfig(CameraRecoilConfig, Recoil);
            }

            if (ammoPrefab == null)
            {
                Logger.LogError($"{gameObject.name} magazine prefab was null, cannot auto-populate.", Category.Firearms);
                return;
            }

            //populate with a full external mag on spawn
            Logger.LogTraceFormat("Auto-populate external magazine for {0}", Category.Firearms, name);
            Inventory.ServerAdd(Spawn.ServerPrefab(ammoPrefab).GameObject, magSlot);

            if (pinPrefab == null)
            {
                Logger.LogError($"{gameObject.name} firing pin prefab was null, cannot auto-populate.", Category.Firearms);
                return;
            }

            Inventory.ServerAdd(Spawn.ServerPrefab(pinPrefab).GameObject, pinSlot);
            FiringPin.gunComp = this;

            if (suppressorPrefab != null && isSuppressed && isSuppressible)
            {
                Inventory.ServerAdd(Spawn.ServerPrefab(suppressorPrefab).GameObject, suppressorSlot);
            }
        }
Exemple #5
0
    /// <summary>
    /// Perform and display the shot locally (i.e. only on this instance of the game). Does not
    /// communicate anything to other players (unless this is the server, in which case the server
    /// will determine the effects of the bullet). Does not do any validation. This should only be invoked
    /// when displaying the results of a shot (i.e. after receiving a ShootMessage or after this client performs a shot)
    /// or when server is determining the outcome of the shot.
    /// </summary>
    /// <param name="shooter">gameobject of the shooter</param>
    /// <param name="finalDirection">direction the shot should travel (accuracy deviation should already be factored into this)</param>
    /// <param name="damageZone">targeted damage zone</param>
    /// <param name="isSuicideShot">if this is a suicide shot (aimed at shooter)</param>
    public void DisplayShot(GameObject shooter, Vector2 finalDirection,
                            BodyPartType damageZone, bool isSuicideShot)
    {
        //Add too the cooldown timer to being allowed to shoot again
        FireCountDown += 1.0 / FireRate;
        CurrentMagazine.ammoRemains--;
        //get the bullet prefab being shot
        GameObject bullet = PoolManager.PoolClientInstantiate(Resources.Load(Projectile.name) as GameObject,
                                                              shooter.transform.position);
        float angle = Mathf.Atan2(finalDirection.y, finalDirection.x) * Mathf.Rad2Deg;

        BulletBehaviour b = bullet.GetComponent <BulletBehaviour>();

        if (isSuicideShot)
        {
            b.Suicide(shooter, this, damageZone);
        }
        else
        {
            b.Shoot(finalDirection, shooter, this, damageZone);
        }


        //add additional recoil after shooting for the next round
        AppendRecoil(angle);

        SoundManager.PlayAtPosition(FiringSound, shooter.transform.position);
        //jerk screen back based on recoil angle and power
        if (shooter == PlayerManager.LocalPlayer)
        {
            //Default recoil params until each gun is configured separately
            if (CameraRecoilConfig == null || CameraRecoilConfig.Distance == 0f)
            {
                CameraRecoilConfig = new CameraRecoilConfig
                {
                    Distance         = 0.2f,
                    RecoilDuration   = 0.05f,
                    RecoveryDuration = 0.6f
                };
            }
            Camera2DFollow.followControl.Recoil(-finalDirection, CameraRecoilConfig);
        }


        shooter.GetComponent <PlayerSprites>().ShowMuzzleFlash();
    }
Exemple #6
0
        /// <summary>
        /// Perform and display the shot locally (i.e. only on this instance of the game). Does not
        /// communicate anything to other players (unless this is the server, in which case the server
        /// will determine the effects of the bullet). Does not do any validation. This should only be invoked
        /// when displaying the results of a shot (i.e. after receiving a ShootMessage or after this client performs a shot)
        /// or when server is determining the outcome of the shot.
        /// </summary>
        /// <param name="shooter">gameobject of the shooter</param>
        /// <param name="finalDirection">direction the shot should travel (accuracy deviation should already be factored into this)</param>
        /// <param name="damageZone">targeted damage zone</param>
        /// <param name="isSuicideShot">if this is a suicide shot (aimed at shooter)</param>
        public void DisplayShot(GameObject shooter, Vector2 finalDirection,
                                BodyPartType damageZone, bool isSuicideShot, string projectileName, int quantity)
        {
            if (!MatrixManager.IsInitialized)
            {
                return;
            }

            //if this is our gun (or server), last check to ensure we really can shoot
            if (isServer || PlayerManager.LocalPlayer == shooter)
            {
                if (CurrentMagazine.ClientAmmoRemains <= 0)
                {
                    if (isServer)
                    {
                        Logger.LogTrace("Server rejected shot - out of ammo", Category.Firearms);
                    }
                    return;
                }
                CurrentMagazine.ExpendAmmo();
            }
            //TODO: If this is not our gun, simply display the shot, don't run any other logic
            if (shooter == PlayerManager.LocalPlayer)
            {
                //this is our gun so we need to update our predictions
                FireCountDown += 1.0 / FireRate;
                //add additional recoil after shooting for the next round
                AppendRecoil();

                //Default camera recoil params until each gun is configured separately
                if (CameraRecoilConfig == null || CameraRecoilConfig.Distance == 0f)
                {
                    CameraRecoilConfig = new CameraRecoilConfig
                    {
                        Distance         = 0.2f,
                        RecoilDuration   = 0.05f,
                        RecoveryDuration = 0.6f
                    };
                }
                Camera2DFollow.followControl.Recoil(-finalDirection, CameraRecoilConfig);
            }

            if (isSuicideShot)
            {
                GameObject bullet = Spawn.ClientPrefab(projectileName,
                                                       shooter.transform.position, parent: shooter.transform.parent).GameObject;
                var b = bullet.GetComponent <Projectile>();
                b.Suicide(shooter, this, damageZone);
            }
            else
            {
                for (int n = 0; n < quantity; n++)
                {
                    GameObject Abullet = Spawn.ClientPrefab(projectileName,
                                                            shooter.transform.position, parent: shooter.transform.parent).GameObject;
                    var A = Abullet.GetComponent <Projectile>();
                    var finalDirectionOverride = CalcDirection(finalDirection, n);
                    A.Shoot(finalDirectionOverride, shooter, this, damageZone);
                }
            }
            SoundManager.PlayAtPosition(FiringSound, shooter.transform.position, shooter);
            shooter.GetComponent <PlayerSprites>().ShowMuzzleFlash();
        }
Exemple #7
0
 /// <summary>
 /// Syncs the recoil config.
 /// </summary>
 public void SyncCameraRecoilConfig(CameraRecoilConfig oldValue, CameraRecoilConfig newValue)
 {
     CameraRecoilConfig = newValue;
 }
Exemple #8
0
        /// <summary>
        /// Perform and display the shot locally (i.e. only on this instance of the game). Does not
        /// communicate anything to other players (unless this is the server, in which case the server
        /// will determine the effects of the bullet). Does not do any validation. This should only be invoked
        /// when displaying the results of a shot (i.e. after receiving a ShootMessage or after this client performs a shot)
        /// or when server is determining the outcome of the shot.
        /// </summary>
        /// <param name="shooter">gameobject of the shooter</param>
        /// <param name="finalDirection">direction the shot should travel (accuracy deviation should already be factored into this)</param>
        /// <param name="damageZone">targeted damage zone</param>
        /// <param name="isSuicideShot">if this is a suicide shot (aimed at shooter)</param>
        public void DisplayShot(GameObject shooter, Vector2 finalDirection,
                                BodyPartType damageZone, bool isSuicideShot)
        {
            if (!MatrixManager.IsInitialized)
            {
                return;
            }

            //if this is our gun (or server), last check to ensure we really can shoot
            if ((isServer || PlayerManager.LocalPlayer == shooter) &&
                CurrentMagazine.ClientAmmoRemains <= 0)
            {
                if (isServer)
                {
                    Logger.LogTrace("Server rejected shot - out of ammo", Category.Firearms);
                }

                return;
            }
            if (shooter == PlayerManager.LocalPlayer)
            {
                //this is our gun so we need to update our predictions
                FireCountDown += 1.0 / FireRate;
                //add additional recoil after shooting for the next round
                AppendRecoil();

                //Default camera recoil params until each gun is configured separately
                if (CameraRecoilConfig == null || CameraRecoilConfig.Distance == 0f)
                {
                    CameraRecoilConfig = new CameraRecoilConfig
                    {
                        Distance         = 0.2f,
                        RecoilDuration   = 0.05f,
                        RecoveryDuration = 0.6f
                    };
                }
                Camera2DFollow.followControl.Recoil(-finalDirection, CameraRecoilConfig);

                if (CurrentMagazine == null)
                {
                    Logger.LogWarning($"Why is {nameof(CurrentMagazine)} null for {this} on this client?");
                }
                else
                {
                    //call ExpendAmmo outside of previous check, or it won't run serverside and state will desync.
                    CurrentMagazine.ExpendAmmo();
                }
            }

            MagazineBehaviour magazine = ammoPrefab.GetComponent <MagazineBehaviour>();

            if (isSuicideShot)
            {
                GameObject bullet = Spawn.ClientPrefab(magazine.Projectile.name,
                                                       shooter.transform.position, parent: shooter.transform.parent).GameObject;
                var b = bullet.GetComponent <Projectile>();
                b.Suicide(shooter, this, damageZone);
            }
            else
            {
                for (int n = 0; n < magazine.ProjectilesFired; n++)
                {
                    GameObject Abullet = Spawn.ClientPrefab(magazine.Projectile.name,
                                                            shooter.transform.position, parent: shooter.transform.parent).GameObject;
                    var A = Abullet.GetComponent <Projectile>();
                    var finalDirectionOverride = CalcDirection(finalDirection, n);
                    A.Shoot(finalDirectionOverride, shooter, this, damageZone);
                }
            }
            SoundManager.PlayAtPosition(FiringSound, shooter.transform.position, shooter);
            shooter.GetComponent <PlayerSprites>().ShowMuzzleFlash();
        }