Пример #1
0
        private List <Collision> TimerStandardSprtFilterPreviousCollisions(List <Collision> currentCollisions, SortedList <long, List <long> > previousCollisions)
        {
            List <Collision> retVal = new List <Collision>();

            bool addIt;

            foreach (Collision collision in currentCollisions)
            {
                addIt = true;

                if (previousCollisions.ContainsKey(collision.Blip1.Token))
                {
                    if (previousCollisions[collision.Blip1.Token].Contains(collision.Blip2.Token))
                    {
                        // These two have already collided.  Don't do it again
                        addIt = false;
                    }
                }
                else if (previousCollisions.ContainsKey(collision.Blip2.Token))
                {
                    if (previousCollisions[collision.Blip2.Token].Contains(collision.Blip1.Token))
                    {
                        // These two have already collided.  Don't do it again
                        addIt = false;
                    }
                }

                if (addIt && _collisionTracker.AddCollision(collision))
                {
                    // These two haven't collided yet
                    retVal.Add(collision);
                }
            }

            // Exit Function
            return(retVal);
        }
Пример #2
0
    public IEnumerator <float> _Dash(Vector2DInt direction, int dashStrength, bool fromCollision = false)
    {
        _stateComponent.SetState(CharacterState.Dashing);         // set state to dashing

        // only play dash sound if this was a volentary dash
        if (!fromCollision)
        {
            Vector2DInt currentPos = currentTile.position;
            Vector2DInt targetPos  = currentTile.GetRelativeTile(direction).position;

            _character.soundComponent.PlaySound(CharacterSoundComponent.CharacterSound.Dash);
            _character.ParticleComponent.EmitTrail(true, (new Vector3(targetPos.x, 1, targetPos.y) - new Vector3(currentPos.x, 1, currentPos.y)).normalized);
        }

        // stop feedback from charge
        _character.ParticleComponent.EmitCharge(false);
        _character.soundComponent.StopSound(CharacterSoundComponent.CharacterSound.Charge);

        // loop over all dash charges
        for (int i = 0; i < dashStrength; i++)
        {
            // get next tile in dash path
            // current tile is corrected before coroutine if lagging so this is safe
            Tile targetTile = currentTile.GetRelativeTile(direction);

            // abort dash if running into non walkable tile
            if (!targetTile.model.data.walkable)
            {
                yield break;
            }

            // Calculate lerp positions
            Vector3 fromPosition   = transform.position;             // interpolate from current position to avoid teleporting if lagging
            Vector3 targetPosition = new Vector3(targetTile.position.x, 1, targetTile.position.y);

            // use the position of current tile instead of position of player to calculate rotation, otherwise we can get crooked rotation if laging
            Vector3 currentTilePos = new Vector3(currentTile.position.x, 1, currentTile.position.y);

            // Calculate lerp rotations
            // note: use last target rotation as base if we was in middle of movement when this dash started from getting hit from other player
            // this will make the rotation that was left from last movement to be added to this rotation and will be caught up
            Vector3    movementDirection = (targetPosition - currentTilePos).normalized;
            Quaternion fromRotation      = transform.rotation;
            Quaternion targetRotation    = Quaternion.Euler(movementDirection * (90 * _model.dashRotationSpeed)) * _lastTargetRotation;

            // if we will hit someone we need the target rotation we had last time becuase we wont start moving towards the future last target
            Quaternion previousLastTargetRotation = _lastTargetRotation;

            _lastTargetRotation = targetRotation;


            if (PhotonNetwork.isMasterClient)             // do collision on master client
            {
                if (targetTile.IsOccupied())
                {
                    // get occupying player and tell it to send an rpc that it got dashed
                    Character playerToDash = targetTile.GetOccupyingPlayer();

                    // save the collision on server so the clients can check that they did not stop their dash locally incorrectly
                    _collisionTracker.AddCollision(playerToDash.photonView.viewID, targetTile.position.x, targetTile.position.y);

                    // tell all clients who got hit
                    playerToDash.movementComponent.OnGettingDashed(targetTile.position, direction, dashStrength - i);

                    // send rpc that we hit other player and cancel all our current movement
                    OnDashingOther(currentTile.position, previousLastTargetRotation, targetTile.position);

                    yield break;
                }
            }

            // stop locally aswell and dubblecheck so we had collision on server, if not the server will restart our dashroutine with the charges that was left
            if (targetTile.IsOccupied())
            {
                // add cooldowns and reset last target rotation becuase we never started interpolation
                StopMovementAndAddCooldowns();
                _lastTargetRotation = previousLastTargetRotation;

                // stop trailParticle
                _character.ParticleComponent.EmitTrail(false, Vector3.zero);

                _collisionTracker.photonView.RPC("CheckServerCollision", PhotonTargets.MasterClient,
                                                 targetTile.GetOccupyingPlayer().photonView.viewID,
                                                 photonView.viewID, currentTile.position.x, currentTile.position.y,
                                                 targetTile.position.x, targetTile.position.y,
                                                 direction.x, direction.y, dashStrength - i);

                // stop and frezze character while waiting for server to register collision
                // this becomes pretty noticable over 150 ping,
                // but is better then keping free movement and be interpolated back when getting corrected by server
                _character.stateComponent.SetState(CharacterState.Frozen);

                yield break;
            }

            // hurt tile if it is destructible(only do break detection on server)
            if (PhotonNetwork.isMasterClient && !currentTile.model.data.unbreakable)
            {
                Match.instance.level.BreakTile(currentTile.position.x, currentTile.position.y);
            }

            // Update tile player references
            SetNewTileReferences(targetTile.position);

            // do the movement itself
            float movementProgress = 0;
            while (movementProgress < 1)
            {
                movementProgress += _model.dashSpeed * Time.deltaTime;
                movementProgress  = Mathf.Clamp01(movementProgress);

                transform.position = Vector3.Lerp(fromPosition, targetPosition, movementProgress);
                transform.rotation = Quaternion.Lerp(fromRotation, targetRotation, movementProgress);

                yield return(Timing.WaitForOneFrame);
            }

            // check if we exited the map after every tile
            // stop movement and flag dead locally and only handle death on server
            // will be corrected by server if say a collision happened on server but not locally that would have prevented us from exiting map
            if (DeadlyEdge())
            {
                if (PhotonNetwork.isMasterClient)
                {
                    photonView.RPC("Die", PhotonTargets.All, currentTile.position.x, currentTile.position.y);
                }
                else
                {
                    _stateComponent.SetState(CharacterState.Frozen);
                }

                yield break;
            }
        }

        // check if we ended up on deadly tile
        // only server handle death detection
        if (PhotonNetwork.isMasterClient && DeadlyTile())
        {
            yield break;
        }

        // add cooldowns and stop feedback
        _character.ParticleComponent.EmitTrail(false, Vector3.zero);
        StopMovementAndAddCooldowns();
    }