// TODO dkonik: Immediately, I don't see us needing this for anything other than stun.
    // But this paradigm can be generalized to any state. I.e. have a "forceToState" function
    // which allows any playerto force any other player to a given state. Though if we do this
    // we will have to have some
    /// <summary>
    /// Forces the player to the stun state for everyone
    /// </summary>
    /// <param name="startPosition"></param>
    /// <param name="blowbackVelocity"></param>
    /// <param name="duration"></param>
    public void StunNetworked(Vector2 startPosition, Vector2 blowbackVelocity, float duration, bool stolenFrom)
    {
        if (CurrentState == State.Stun)
        {
            return;
        }

        if (photonView.IsMine)
        {
            // If we are the local player, just serialize out as usual
            StunInformation info = GetStateInformationForWriting <StunInformation>(State.Stun);
            info.StartPosition = startPosition;
            info.Velocity      = blowbackVelocity;
            info.Duration      = duration;
            info.StolenFrom    = stolenFrom;
            TransitionToState(State.Stun, info);
        }
        else
        {
            // TODO dkonik: Using AllViaServer so that photon can guarantee ordering. However, this might
            // not be the right thing to do. The reason I we need to guarantee ordering (or something along those lines)
            // is because if the situation described in the comment in [StunNetworked_Interal], namely: "Say, for example,
            // player 1 destroys player 2s tron wall while they are laying it at the same time that player 3
            // possesses the ball right by player 2. Both player 1 and player 3 will send an RPC to stun player
            // 2" happens, then we need to be able to guarantee ordering.
            photonView.RPC("StunNetworked_Interal", RpcTarget.AllViaServer, startPosition, blowbackVelocity, duration, stolenFrom);
        }
    }
    private void HandleNewPlayerState(State oldState, State newState)
    {
        if (newState == State.Possession)
        {
            StartRumble(duration: ballPossessionRumbleDuration);
        }

        if (newState == State.Stun)
        {
            StunInformation info = stateManager.CurrentStateInformation_Exn <StunInformation>();
            if (info.StolenFrom)
            {
                StartRumble(duration: stealRumbleDuration);
            }
        }
    }
    private void StunNetworked_Interal(Vector2 startPosition, Vector2 blowbackVelocity, float duration, bool stolenFrom, PhotonMessageInfo rpcInfo)
    {
        // Situations can arise where two players try to stun third at roughly the same time. Say, for example,
        // player 1 destroys player 2s tron wall while they are laying it at the same time that player 3
        // possesses the ball right by player 2. Both player 1 and player 3 will send an RPC to stun player
        // 2. Photon guarantees ordering (at least the way we are currently doing it). So we will just have
        // everyoen ignore the second rpc.
        //
        // Or, another situation that might arise is that player 1 stuns player 2, and so sends the RPC out to force
        // player 2 to stun state. Player 2 might get this, and serialize out the stun information before player 3
        // even gets the RPC, in which case we can also ignore it.
        if (CurrentState == State.Stun)
        {
            StunInformation stunInfo          = CurrentStateInformation_Exn <StunInformation>();
            bool            isSameInformation = stunInfo.EventTimeStamp == rpcInfo.timestamp;
            Debug.LogFormat("Got an RPC to enter stun state while already in stun, ignoring. IsSameInformation: {0}", isSameInformation);

            return;
        }

        if (nonOwnerForcedState)
        {
            Debug.Log("Received an RPC forcing to enter Stun state, but we are already in a forced state.");
            return;
        }

        // Just enter stun as usual, except using the rpc timestamp as the timestamp
        // If we are the owner, this will get serialized out as usual as well, which is what we want.
        // If we are not, nonOwnerState will get set to true so we will ignore any other updates
        // from the owner until they confirm the forced state.
        nonOwnerForcedState = !photonView.IsMine;

        StunInformation info = GetStateInformationForWriting <StunInformation>(State.Stun);

        info.StartPosition  = startPosition;
        info.Velocity       = blowbackVelocity;
        info.Duration       = duration;
        info.EventTimeStamp = rpcInfo.timestamp;

        State oldState = CurrentState;

        CurrentState = State.Stun;
        OnStateChange?.Invoke(oldState, CurrentState);
    }
Пример #4
0
    private void DoStunMovement()
    {
        StunInformation info = stateManager.CurrentStateInformation_Exn <StunInformation>();

        StopAllMovementCoroutines(false);

        // If we for some reason transition to the stun state *after*
        // we were supposed to have finished with the stun state, just put
        // the player where they would have ended up
        float timeTravelledSoFar = (float)(PhotonNetwork.Time - info.EventTimeStamp);

        if (timeTravelledSoFar > info.Duration)
        {
            timeTravelledSoFar = info.Duration;
        }

        // Calculate the start position based on the time that has elapsed since
        // the message was sent
        rb2d.position = info.StartPosition + timeTravelledSoFar * info.Velocity;
        rb2d.velocity = info.Velocity;
    }
Пример #5
0
    /// <summary>
    /// Manages the duration of the stun.
    /// NOTE: Does not handle the movement. PlayerMovement will take care of managing
    /// that while in the stun state
    /// </summary>
    /// <returns></returns>
    private IEnumerator Stun()
    {
        StunInformation info = playerStateManager.CurrentStateInformation_Exn <StunInformation>();

        if (info.StolenFrom)
        {
            GameManager.NotificationManager.NotifyMessage(Message.BallWasStolen, this);
        }

        float timeSinceCall = (float)(PhotonNetwork.Time - info.EventTimeStamp);

        if (timeSinceCall < info.Duration)
        {
            yield return(new WaitForSeconds(info.Duration - timeSinceCall));
        }
        else
        {
            Debug.LogError("Entered stun after Duration. This shouldn't happen or should happen very rarely. Look into this");
        }

        playerStateManager.TransitionToState(State.NormalMovement);
    }