Beispiel #1
0
        protected override void PrepareProtoStatusEffect()
        {
            base.PrepareProtoStatusEffect();

            // cache the tile offsets
            // but select only every third tile (will help to reduce the load without damaging accuracy too much)
            this.serverTileOffsetsCircle = ShapeTileOffsetsHelper
                                           .GenerateOffsetsCircle(EnvironmentalTileHeatLookupAreaDiameter)
                                           .ToArray();

            this.serverTileOffsetsCircle = ShapeTileOffsetsHelper.SelectOffsetsWithRate(
                this.serverTileOffsetsCircle,
                rate: 3);

            this.serverProtoTileLava    = Api.GetProtoEntity <TileLava>();
            this.serverProtoTileVolcano = Api.GetProtoEntity <TileVolcanic>();
        }
        protected void ServerSetMobInput(
            ICharacter character,
            Vector2F movementDirection,
            double rotationAngleRad)
        {
            var movementDirectionNormalized = new Vector2D(
                ClampDirection(movementDirection.X),
                ClampDirection(movementDirection.Y)).Normalized;

            var moveSpeed = character.SharedGetFinalStatValue(StatName.MoveSpeed);

            moveSpeed *= ProtoTile.SharedGetTileMoveSpeedMultiplier(character.Tile);
            Server.Characters.SetMoveSpeed(character, moveSpeed);

            var moveVelocity = movementDirectionNormalized * moveSpeed;

            Server.Characters.SetVelocity(character, moveVelocity);

            var statePublic = GetPublicState(character);

            statePublic.AppliedInput.Set(
                new CharacterInput()
            {
                MoveModes        = CharacterMoveModesHelper.CalculateMoveModes(movementDirectionNormalized),
                RotationAngleRad = (float)rotationAngleRad,
            },
                moveSpeed);

            double ClampDirection(double dir)
            {
                const double directionThreshold = 0.1;

                if (dir > directionThreshold)
                {
                    return(1);
                }

                if (dir < -directionThreshold)
                {
                    return(-1);
                }

                return(0);
            }
        }
Beispiel #3
0
        protected void ServerSetMobInput(
            ICharacter character,
            Vector2F movementDirection,
            double rotationAngleRad)
        {
            var movementDirectionNormalized = new Vector2D(
                ClampDirection(movementDirection.X),
                ClampDirection(movementDirection.Y)).Normalized;

            double moveSpeed;

            if (movementDirection.X != 0 &&
                movementDirection.Y != 0)
            {
                moveSpeed  = character.SharedGetFinalStatValue(StatName.MoveSpeed);
                moveSpeed *= ProtoTile.SharedGetTileMoveSpeedMultiplier(character.Tile);
            }
            else
            {
                moveSpeed = 0;
            }

            Server.World.SetDynamicObjectMoveSpeed(character, moveSpeed);

            var moveAcceleration = movementDirectionNormalized * this.PhysicsBodyAccelerationCoef * moveSpeed;

            Server.World.SetDynamicObjectPhysicsMovement(character,
                                                         moveAcceleration,
                                                         targetVelocity: moveSpeed);

            var statePublic = GetPublicState(character);

            statePublic.AppliedInput.Set(
                new CharacterInput()
            {
                MoveModes        = CharacterMoveModesHelper.CalculateMoveModes(movementDirectionNormalized),
                RotationAngleRad = (float)rotationAngleRad,
            },
                moveSpeed);
Beispiel #4
0
        protected void SharedApplyInput(
            ICharacter character,
            PlayerCharacterPrivateState privateState,
            PlayerCharacterPublicState publicState)
        {
            var characterIsOffline = !character.ServerIsOnline;

            if (characterIsOffline)
            {
                privateState.Input = default;
            }

            var vehicle = publicState.CurrentVehicle;

            if (vehicle is not null)
            {
                if (!vehicle.IsInitialized)
                {
                    return;
                }

                var protoVehicle = (IProtoVehicle)vehicle.ProtoGameObject;
                protoVehicle.SharedApplyInput(vehicle,
                                              character,
                                              privateState,
                                              publicState);
                return;
            }

            // please note - input is a structure so actually we're implicitly copying it here
            var input = privateState.Input;
            // please note - applied input is a class and we're getting it by reference here
            var appliedInput   = publicState.AppliedInput;
            var hasRunningFlag = (input.MoveModes & CharacterMoveModes.ModifierRun) != 0;
            var isRunning      = hasRunningFlag;

            if (isRunning)
            {
                var stats          = publicState.CurrentStatsExtended;
                var wasRunning     = (appliedInput.MoveModes & CharacterMoveModes.ModifierRun) != 0;
                var staminaCurrent = stats.StaminaCurrent;

                if (!wasRunning)
                {
                    // can start running only when the current energy is at least on 10%
                    isRunning = staminaCurrent >= 0.1 * stats.StaminaMax;
                }
                else // if was running
                {
                    // can continue to run while has energy
                    isRunning = staminaCurrent > 0;
                }

                //Logger.WriteDev($"Was running: {wasRunning}; now running: {isRunning}; stamina: {staminaCurrent}");
            }

            double moveSpeed;

            if (characterIsOffline ||
                (privateState.CurrentActionState?.IsBlockingMovement ?? false))
            {
                // offline or current action blocks movement
                moveSpeed       = 0;
                isRunning       = false;
                input.MoveModes = CharacterMoveModes.None;
            }
            else
            {
                var characterFinalStateCache = privateState.FinalStatsCache;
                moveSpeed  = characterFinalStateCache[StatName.MoveSpeed];
                moveSpeed *= ProtoTile.SharedGetTileMoveSpeedMultiplier(character.Tile);

                if (isRunning)
                {
                    if (characterFinalStateCache.HasPerk(StatName.PerkCannotRun))
                    {
                        isRunning = false;
                    }
                    else
                    {
                        var moveSpeedMultiplier = characterFinalStateCache[StatName.MoveSpeedRunMultiplier];
                        if (moveSpeedMultiplier > 0)
                        {
                            moveSpeed = moveSpeed * moveSpeedMultiplier;
                        }
                        else
                        {
                            isRunning = false;
                        }
                    }
                }
            }

            if (!isRunning)
            {
                // cannot run - remove running flag
                input.MoveModes &= ~CharacterMoveModes.ModifierRun;
            }

            if (appliedInput.MoveModes == input.MoveModes &&
                appliedInput.RotationAngleRad == input.RotationAngleRad &&
                publicState.AppliedInput.MoveSpeed == moveSpeed)
            {
                // input is not changed
                return;
            }

            // apply new input
            appliedInput.Set(input, moveSpeed);

            var moveModes = input.MoveModes;

            double directionX = 0, directionY = 0;

            if ((moveModes & CharacterMoveModes.Up) != 0)
            {
                directionY = 1;
            }

            if ((moveModes & CharacterMoveModes.Down) != 0)
            {
                directionY = -1;
            }

            if ((moveModes & CharacterMoveModes.Left) != 0)
            {
                directionX = -1;
            }

            if ((moveModes & CharacterMoveModes.Right) != 0)
            {
                directionX = 1;
            }

            if (directionX == 0 &&
                directionY == 0)
            {
                moveSpeed = 0;
            }

            Vector2D directionVector  = (directionX, directionY);
            var      moveAcceleration = directionVector.Normalized * this.PhysicsBodyAccelerationCoef * moveSpeed;

            if (IsServer)
            {
                Server.World.SetDynamicObjectPhysicsMovement(character,
                                                             moveAcceleration,
                                                             targetVelocity: moveSpeed);
                character.PhysicsBody.Friction = this.PhysicsBodyFriction;
            }
            else // if client
            {
                if (ClientCurrentCharacterLagPredictionManager.IsLagPredictionEnabled)
                {
                    Client.World.SetDynamicObjectPhysicsMovement(character,
                                                                 moveAcceleration,
                                                                 targetVelocity: moveSpeed);
                    character.PhysicsBody.Friction = this.PhysicsBodyFriction;
                }
            }
        }
        protected void SharedApplyInput(
            ICharacter character,
            PlayerCharacterPrivateState privateState,
            PlayerCharacterPublicState publicState)
        {
            var characterIsOffline = !character.IsOnline;

            if (characterIsOffline)
            {
                privateState.Input = default;
            }

            // please note - input is a structure so actually we're implicitly copying it here
            var input = privateState.Input;
            // please note - applied input is a class and we're getting it by reference here
            var appliedInput   = publicState.AppliedInput;
            var hasRunningFlag = (input.MoveModes & CharacterMoveModes.ModifierRun) != 0;
            var isRunning      = hasRunningFlag;

            if (isRunning)
            {
                var stats          = publicState.CurrentStatsExtended;
                var wasRunning     = (appliedInput.MoveModes & CharacterMoveModes.ModifierRun) != 0;
                var staminaCurrent = stats.StaminaCurrent;

                if (!wasRunning)
                {
                    // can start running only when the current energy is at least on 10%
                    isRunning = staminaCurrent >= 0.1 * stats.StaminaMax;
                }
                else // if was running
                {
                    // can continue to run while has energy
                    isRunning = staminaCurrent > 0;
                }

                //Logger.WriteDev($"Was running: {wasRunning}; now running: {isRunning}; stamina: {staminaCurrent}");
            }

            double moveSpeed;

            if (characterIsOffline)
            {
                moveSpeed = 0;
                isRunning = false;
            }
            else
            {
                var characterFinalStateCache = privateState.FinalStatsCache;
                moveSpeed  = characterFinalStateCache[StatName.MoveSpeed];
                moveSpeed *= ProtoTile.SharedGetTileMoveSpeedMultiplier(character.Tile);

                if (isRunning)
                {
                    var moveSpeedMultiplier = characterFinalStateCache[StatName.MoveSpeedRunMultiplier];
                    if (moveSpeedMultiplier > 0)
                    {
                        moveSpeed = moveSpeed * moveSpeedMultiplier;
                    }
                    else
                    {
                        isRunning = false;
                    }
                }
            }

            if (!isRunning)
            {
                // cannot run - remove running flag
                input.MoveModes &= ~CharacterMoveModes.ModifierRun;
            }

            if (appliedInput.MoveModes == input.MoveModes &&
                appliedInput.RotationAngleRad == input.RotationAngleRad &&
                publicState.AppliedInput.MoveSpeed == moveSpeed)
            {
                // input is not changed
                return;
            }

            // apply new input
            appliedInput.Set(input, moveSpeed);

            var moveModes = input.MoveModes;

            double directionX = 0, directionY = 0;

            if ((moveModes & CharacterMoveModes.Up) != 0)
            {
                directionY = 1;
            }

            if ((moveModes & CharacterMoveModes.Down) != 0)
            {
                directionY = -1;
            }

            if ((moveModes & CharacterMoveModes.Left) != 0)
            {
                directionX = -1;
            }

            if ((moveModes & CharacterMoveModes.Right) != 0)
            {
                directionX = 1;
            }

            Vector2D directionVector = (directionX, directionY);
            var      moveVelocity    = directionVector.Normalized * moveSpeed;

            if (IsServer)
            {
                Server.Characters.SetVelocity(character, moveVelocity);
            }
            else // if client
            {
                if (ClientCurrentCharacterLagPredictionManager.IsLagPredictionEnabled)
                {
                    Client.Characters.SetVelocity(character, moveVelocity);
                }
            }
        }