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); }
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(); }