protected sealed override void ServerUpdate(ServerUpdateData data)
        {
            var character    = data.GameObject;
            var privateState = data.PrivateState;
            var publicState  = data.PublicState;

            if (publicState.IsDead)
            {
                // should never happen as the ServerCharacterDeathMechanic should properly destroy the character
                Logger.Error("(Should never happen) Destroying dead mob character: " + character);
                ServerWorld.DestroyObject(character);
                return;
            }

            this.ServerRebuildFinalCacheIfNeeded(character, privateState, publicState);

            ServerUpdateAgroState(privateState, data.DeltaTime);
            this.ServerUpdateMob(data);
            this.ServerUpdateMobDespawn(character, privateState, data.DeltaTime);

            // update weapon state (fires the weapon if needed)
            WeaponSystem.SharedUpdateCurrentWeapon(
                character,
                privateState.WeaponState,
                data.DeltaTime);
        }
        public static CreateItemResult TryDropToCharacterOrGround(
            IReadOnlyDropItemsList dropItemsList,
            ICharacter toCharacter,
            Vector2Ushort tilePosition,
            bool sendNotificationWhenDropToGround,
            double probabilityMultiplier,
            DropItemContext context,
            out IItemsContainer groundContainer)
        {
            var containersProvider = new CharacterAndGroundContainersProvider(toCharacter, tilePosition);

            var result = dropItemsList.Execute(
                (protoItem, count) => Items.CreateItem(protoItem, containersProvider, count),
                context,
                probabilityMultiplier);

            groundContainer = containersProvider.GroundContainer;
            if (groundContainer is null)
            {
                return(result);
            }

            if (groundContainer.OccupiedSlotsCount == 0)
            {
                // nothing is spawned, the ground container should be destroyed
                World.DestroyObject(groundContainer.OwnerAsStaticObject);
                groundContainer = null;
            }
            else
            {
                if (sendNotificationWhenDropToGround && result.TotalCreatedCount > 0)
                {
                    // notify player that there were not enough space in inventory so the items were dropped to the ground
                    NotificationSystem.ServerSendNotificationNoSpaceInInventoryItemsDroppedToGround(
                        toCharacter,
                        protoItemForIcon: result.ItemAmounts
                        .Keys
                        .FirstOrDefault(
                            k => k.Container == containersProvider.GroundContainer)?
                        .ProtoItem);
                }

                WorldObjectClaimSystem.ServerTryClaim(groundContainer.OwnerAsStaticObject,
                                                      toCharacter,
                                                      WorldObjectClaimDuration.GroundItems);
            }

            return(result);
        }
        public static void ServerRemoveAllStatusEffects(this ICharacter character, bool removeOnlyDebuffs = false)
        {
            var statusEffects = InternalServerGetStatusEffects(character);

            for (var index = 0; index < statusEffects.Count; index++)
            {
                var statusEffect = statusEffects[index];
                if (removeOnlyDebuffs &&
                    ((IProtoStatusEffect)statusEffect.ProtoLogicObject).Kind == StatusEffectKind.Buff)
                {
                    continue;
                }

                ServerWorld.DestroyObject(statusEffect);
                statusEffects.RemoveAt(index);
                index--;
            }

            Logger.Important("All status effects removed for " + character);
        }
Beispiel #4
0
            private static void ServerLoadSystem()
            {
                var database = Server.Database;

                if (!database.TryGet(nameof(ChatSystem),
                                     DatabaseKeyGlobalChatRoomHolder,
                                     out sharedGlobalChatRoomHolder))
                {
                    sharedGlobalChatRoomHolder = ServerCreateChatRoom(new ChatRoomGlobal());
                    database.Set(nameof(ChatSystem), DatabaseKeyGlobalChatRoomHolder, sharedGlobalChatRoomHolder);
                }

                if (!database.TryGet(nameof(ChatSystem),
                                     DatabaseKeyLocalChatRoomHolder,
                                     out sharedLocalChatRoomHolder))
                {
                    sharedLocalChatRoomHolder = ServerCreateChatRoom(new ChatRoomLocal());
                    database.Set(nameof(ChatSystem), DatabaseKeyLocalChatRoomHolder, sharedLocalChatRoomHolder);
                }

                // right now it's not possible to enumerate all the existing chat rooms as this is a bootstrapper
                // schedule a delayed initialization
                ServerTimersSystem.AddAction(
                    0.1,
                    () =>
                {
                    foreach (var chatRoomHolder in ServerWorld
                             .GetGameObjectsOfProto <ILogicObject, ChatRoomHolder>()
                             .ToList())
                    {
                        if (!(SharedGetChatRoom(chatRoomHolder) is ChatRoomPrivate privateChatRoom))
                        {
                            continue;
                        }

                        var characterA = Server.Characters.GetPlayerCharacter(privateChatRoom.CharacterA);
                        var characterB = Server.Characters.GetPlayerCharacter(privateChatRoom.CharacterB);

                        if (characterA == null ||
                            characterB == null)
                        {
                            // incorrect private chat room
                            ServerWorld.DestroyObject(chatRoomHolder);
                            continue;
                        }

                        ServerAddPrivateChatRoomToCharacterCache(characterA, chatRoomHolder);
                        ServerAddPrivateChatRoomToCharacterCache(characterB, chatRoomHolder);
                    }
Beispiel #5
0
        public static void DestroyAllDecals(
            Vector2Ushort tilePosition,
            StaticObjectLayoutReadOnly layout)
        {
            Api.ValidateIsServer();

            foreach (var tileOffset in layout.TileOffsets)
            {
                var tile = World.GetTile(tilePosition.X + tileOffset.X,
                                         tilePosition.Y + tileOffset.Y);
                if (!tile.IsValidTile)
                {
                    continue;
                }

                var staticObjects = tile.StaticObjects;
                if (!HasFloorDecals(staticObjects))
                {
                    continue;
                }

                // remove floor decals
                using (var tempList = Api.Shared.WrapInTempList(staticObjects))
                {
                    foreach (var staticWorldObject in tempList)
                    {
                        if (staticWorldObject.ProtoStaticWorldObject.Kind == StaticObjectKind.FloorDecal)
                        {
                            World.DestroyObject(staticWorldObject);
                        }
                    }
                }
            }

            bool HasFloorDecals(ReadOnlyListWrapper <IStaticWorldObject> staticObjects)
            {
                foreach (var staticWorldObject in staticObjects)
                {
                    if (staticWorldObject.ProtoStaticWorldObject.Kind == StaticObjectKind.FloorDecal)
                    {
                        return(true);
                    }
                }

                return(false);
            }
        }
Beispiel #6
0
        public virtual void ServerOnDeath(ICharacter character)
        {
            this.ServerSendDeathSoundEvent(character);

            ServerWorld.DestroyObject(character);

            var position          = character.Position;
            var tilePosition      = position.ToVector2Ushort();
            var rotationAngleRad  = character.GetPublicState <ICharacterPublicState>().AppliedInput.RotationAngleRad;
            var isLeftOrientation = ClientCharacterAnimationHelper.IsLeftHalfOfCircle(
                angleDeg: rotationAngleRad * MathConstants.RadToDeg);
            var isFlippedHorizontally = !isLeftOrientation;

            var objectCorpse = ServerWorld.CreateStaticWorldObject <ObjectCorpse>(tilePosition);

            ObjectCorpse.ServerSetupCorpse(objectCorpse,
                                           (IProtoCharacterMob)character.ProtoCharacter,
                                           (Vector2F)(position - tilePosition.ToVector2D()),
                                           isFlippedHorizontally: isFlippedHorizontally);
        }
Beispiel #7
0
        private static void DropPlayerLoot(ICharacter character)
        {
            var containerEquipment = character.SharedGetPlayerContainerEquipment();
            var containerHand      = character.SharedGetPlayerContainerHand();
            var containerHotbar    = character.SharedGetPlayerContainerHotbar();
            var containerInventory = character.SharedGetPlayerContainerInventory();

            if (PveSystem.ServerIsPvE)
            {
                // don't drop player loot on death in PvE
                Api.Logger.Important("Player character is dead - reduce durability for the equipped items", character);

                // process items and drop loot
                ProcessContainerItemsOnDeathInPvE(isEquipmentContainer: true,
                                                  fromContainer: containerEquipment);

                ProcessContainerItemsOnDeathInPvE(isEquipmentContainer: false,
                                                  fromContainer: containerHand);

                ProcessContainerItemsOnDeathInPvE(isEquipmentContainer: false,
                                                  fromContainer: containerHotbar);

                ProcessContainerItemsOnDeathInPvE(isEquipmentContainer: false,
                                                  fromContainer: containerInventory);
                return;
            }

            Api.Logger.Important("Player character is dead - drop loot", character);

            CraftingMechanics.ServerCancelCraftingQueue(character);

            var characterContainersOccupiedSlotsCount = containerEquipment.OccupiedSlotsCount
                                                        + containerHand.OccupiedSlotsCount
                                                        + containerHotbar.OccupiedSlotsCount
                                                        + containerInventory.OccupiedSlotsCount;

            if (characterContainersOccupiedSlotsCount == 0)
            {
                Api.Logger.Important("No need to drop loot for dead character (no items to drop)", character);
                return;
            }

            var lootContainer = ObjectPlayerLootContainer.ServerTryCreateLootContainer(character);

            if (lootContainer is null)
            {
                Api.Logger.Error("Unable to drop loot for dead character", character);
                return;
            }

            // set slots count matching the total occupied slots count
            ServerItems.SetSlotsCount(
                lootContainer,
                (byte)characterContainersOccupiedSlotsCount);

            // process items and drop loot
            ProcessContainerItemsOnDeathInPvP(isEquipmentContainer: true,
                                              fromContainer: containerEquipment,
                                              toContainer: lootContainer);

            ProcessContainerItemsOnDeathInPvP(isEquipmentContainer: false,
                                              fromContainer: containerHand,
                                              toContainer: lootContainer);

            ProcessContainerItemsOnDeathInPvP(isEquipmentContainer: false,
                                              fromContainer: containerHotbar,
                                              toContainer: lootContainer);

            ProcessContainerItemsOnDeathInPvP(isEquipmentContainer: false,
                                              fromContainer: containerInventory,
                                              toContainer: lootContainer);

            if (lootContainer.OccupiedSlotsCount <= 0)
            {
                // nothing dropped, destroy the just spawned loot container
                ServerWorld.DestroyObject((IWorldObject)lootContainer.Owner);
                return;
            }

            // set exact slots count
            ServerItems.SetSlotsCount(
                lootContainer,
                (byte)lootContainer.OccupiedSlotsCount);

            SharedLootDropNotifyHelper.ServerOnLootDropped(lootContainer);
            // please note - no need to notify player about the dropped loot, it's automatically done by ClientDroppedItemsNotificationsManager
        }