Example #1
0
 public override void ServerOnPilotDamage(
     WeaponFinalCache weaponCache,
     IDynamicWorldObject vehicle,
     ICharacter pilotCharacter,
     double damageApplied)
 {
     if (damageApplied > 0)
     {
         // drop from hoverboard on any damage
         VehicleSystem.ServerCharacterExitCurrentVehicle(pilotCharacter, force: true);
     }
 }
Example #2
0
        private void ServerRemote_CreateUnstuckRequest()
        {
            var character = ServerRemoteContext.Character;

            if (serverRequests.ContainsKey(character))
            {
                this.CallClient(character, _ => _.ClientRemote_UnstuckAlreadyQueued());
                return;
            }

            if (PlayerCharacter.GetPublicState(character).IsDead ||
                PlayerCharacter.GetPrivateState(character).IsDespawned)
            {
                // character is dead/despawned
                this.CallClient(character, _ => _.ClientRemote_UnstuckFailedDead());
                return;
            }

            var vehicle = character.SharedGetCurrentVehicle();

            if (vehicle is not null)
            {
                VehicleSystem.ServerCharacterExitCurrentVehicle(character, force: true);

                if (vehicle.GetPublicState <VehiclePublicState>().PilotCharacter is not null)
                {
                    // cannot quit vehicle here, cannot unstuck
                    this.CallClient(character, _ => _.ClientRemote_UnstuckImpossible());
                    return;
                }
            }

            var delay = LandClaimSystem.SharedIsPositionInsideOwnedOrFreeArea(character.TilePosition,
                                                                              character,
                                                                              requireFactionPermission: false)
                            ? UnstuckDelaySecondsTotal
                            : UnstuckDelaySecondsOnEnemyBaseTotal;

            var unstuckTime = Server.Game.FrameTime + delay;

            PlayerCharacter.GetPublicState(character).UnstuckExecutionTime = unstuckTime;

            serverRequests.Add(character,
                               new CharacterUnstuckRequest(
                                   unstuckAfter: unstuckTime,
                                   initialPosition: character.Position));
        }
Example #3
0
        /// <summary>
        /// Moves the character to service area so a respawn will be required on login.
        /// There will be no penalties (such as loot drop or "weakened" status effect).
        /// </summary>
        public static void DespawnCharacter(ICharacter character)
        {
            var privateState = PlayerCharacter.GetPrivateState(character);

            if (privateState.IsDespawned)
            {
                return;
            }

            VehicleSystem.ServerCharacterExitCurrentVehicle(character, force: true);
            CharacterDamageTrackingSystem.ServerClearStats(character);

            ServerTeleportPlayerCharacterToServiceArea(character);

            privateState.LastDeathPosition = Vector2Ushort.Zero;
            privateState.LastDeathTime     = null;
        }
Example #4
0
        public static void ServerSwitchToSpectatorMode(ICharacter character)
        {
            if (character.ProtoCharacter.GetType() == typeof(PlayerCharacterSpectator))
            {
                return;
            }

            VehicleSystem.ServerCharacterExitCurrentVehicle(character, force: true);

            // restore stamina so the spectator can "run"
            var stats = character.GetPublicState <PlayerCharacterPublicState>()
                        .CurrentStatsExtended;

            stats.SharedSetStaminaCurrent(stats.StaminaMax);

            // the order of calls is important here
            Server.Characters.SetSpectatorMode(character, isSpectator: false, reinitialize: false);
            Server.Characters.SetProto(character, GetProtoEntity <PlayerCharacterSpectator>());
            character.ServerRemoveAllStatusEffects();
        }
Example #5
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var character    = data.GameObject;
            var publicState  = data.PublicState;
            var privateState = data.PrivateState;

            publicState.IsOnline = character.ServerIsOnline;

            // update selected hotbar item
            SharedRefreshSelectedHotbarItem(character, privateState);

            if (publicState.IsDead)
            {
                VehicleSystem.ServerCharacterExitCurrentVehicle(character, force: true);

                // dead - stops processing character
                var world = Server.World;
                world.SetDynamicObjectMoveSpeed(character, 0);
                world.SetDynamicObjectPhysicsMovement(character,
                                                      accelerationVector: Vector2D.Zero,
                                                      targetVelocity: 0);
                character.PhysicsBody.Friction = 100000;
                world.StopPhysicsBody(character.PhysicsBody);
                return;
            }

            // character is alive
            this.ServerRebuildFinalCacheIfNeeded(privateState, publicState);
            this.SharedApplyInput(character, privateState, publicState);

            // update weapon state (fires the weapon if needed)
            WeaponSystem.SharedUpdateCurrentWeapon(character, privateState.WeaponState, data.DeltaTime);
            // update current action state (if any)
            privateState.CurrentActionState?.SharedUpdate(data.DeltaTime);
            // update crafting queue
            CraftingMechanics.ServerUpdate(privateState.CraftingQueue, data.DeltaTime);
            // consumes/restores stamina
            CharacterStaminaSystem.SharedUpdate(character, publicState, privateState, data.DeltaTime);
        }
Example #6
0
        /// <summary>
        /// Service area (aka "graveyard") is an area in the bottom right corner of the map.
        /// </summary>
        public static void ServerTeleportPlayerCharacterToServiceArea(ICharacter character)
        {
            if (character.IsNpc)
            {
                return;
            }

            // disable the visual scope so the player cannot see anyone and nobody could see the player
            Api.Server.Characters.SetViewScopeMode(character, isEnabled: false);

            var privateState = PlayerCharacter.GetPrivateState(character);

            if (privateState.IsDespawned)
            {
                // already despawned, only fix the position
                MoveToServiceArea();
                return;
            }

            privateState.IsDespawned = true;
            VehicleSystem.ServerCharacterExitCurrentVehicle(character, force: true);
            MoveToServiceArea();

            Api.Logger.Important("Character despawned", character);

            // recreate physics (as despawned character doesn't have any physics)
            character.ProtoCharacter.SharedCreatePhysics(character);

            void MoveToServiceArea()
            {
                var serviceAreaPosition = ServerGetServiceAreaPosition();

                if (character.TilePosition != serviceAreaPosition)
                {
                    Server.World.SetPosition(character, (Vector2D)serviceAreaPosition);
                }
            }
        }
Example #7
0
        private static void TeleportToBed(ICharacter character, IStaticWorldObject bedObject)
        {
            var bedPosition = bedObject.TilePosition.ToVector2D()
                              + bedObject.ProtoStaticWorldObject.Layout.Center;

            var neighborTiles = bedObject.OccupiedTiles
                                .SelectMany(t => t.EightNeighborTiles)
                                .Concat(bedObject.OccupiedTiles)
                                .Distinct()
                                .ToList();

            neighborTiles.Shuffle();

            var bedTileHeight = bedObject.OccupiedTile.Height;

            neighborTiles.SortBy(t => t.Position.ToVector2D()
                                 .DistanceSquaredTo(bedPosition));
            var physicsSpace = Server.World.GetPhysicsSpace();

            foreach (var neighborTile in neighborTiles)
            {
                if (neighborTile.Height != bedTileHeight)
                {
                    continue;
                }

                var spawnPosition = neighborTile.Position.ToVector2D() + (0.5, 0.5);
                using (var objectsNearby = physicsSpace.TestCircle(
                           spawnPosition,
                           radius: 0.5,
                           collisionGroup: CollisionGroups.Default))
                {
                    if (objectsNearby.Count > 0)
                    {
                        // invalid tile - obstacles
                        continue;
                    }
                }

                if (!LandClaimSystem.SharedIsPositionInsideOwnedOrFreeArea(neighborTile.Position,
                                                                           character,
                                                                           requireFactionPermission: false))
                {
                    // invalid tile - it's claimed by another player
                    continue;
                }

                // valid tile found - respawn here
                // ensure the character has quit the current vehicle
                VehicleSystem.ServerCharacterExitCurrentVehicle(character, force: true);
                if (PlayerCharacter.GetPublicState(character).CurrentVehicle is not null)
                {
                    Logger.Important($"{character} cannot be teleported to bed as it cannot exit the current vehicle");
                    return;
                }

                Server.World.SetPosition(character, spawnPosition);
                Logger.Important($"{character} teleported to bed {bedObject}");
                return;
            }

            Logger.Important($"{character} cannot be teleported to bed {bedObject}");
        }