protected override void ClientInitialize(ClientInitializeData data)
 {
     ClientCharacterEquipmentHelper.ClientRebuildAppearance(
         data.GameObject,
         data.ClientState,
         data.PublicState,
         data.PublicState.SelectedItem);
 }
        /// <summary>
        /// Uses in texture procedural generation.
        /// </summary>
        /// <param name="request">Request from ProceduralTexture generator</param>
        /// <param name="textureWidth">Texture width</param>
        /// <param name="textureHeight">Texture height</param>
        /// <param name="spriteQualityOffset">Sprite quality modifier (0 = full size, 1 = x0.5, 2 = x0.25)</param>
        /// <returns></returns>
        public override async Task <ITextureResource> GenerateIcon(
            ProceduralTextureRequest request,
            ushort textureWidth       = 512,
            ushort textureHeight      = 512,
            sbyte spriteQualityOffset = 0)
        {
            if (!(ProtoEntity is IProtoCharacterMob creature)) // Can't be via constructor rule
            {
                Api.Logger.Error("CNEI: creature is not IProtoCharacterMob, but it shouldn't be possible!");
                return(DefaultIcon);
            }
            creature.SharedGetSkeletonProto(null, out var creatureSkeleton, out double _);
            var worldScale = 1.0;

            if (creatureSkeleton is ProtoCharacterSkeletonAnimal animalSkeleton)
            {
                worldScale = animalSkeleton.WorldScale * 2;
            }
            string renderingTag = request.TextureName;

            var renderTarget = Api.Client.Rendering.CreateRenderTexture(renderingTag, textureWidth, textureHeight);
            var cameraObject = Api.Client.Scene.CreateSceneObject(renderingTag);
            var camera       = Api.Client.Rendering.CreateCamera(cameraObject,
                                                                 renderingTag: renderingTag,
                                                                 drawOrder: -10);

            camera.RenderTarget = renderTarget;
            camera.ClearColor   = Color.FromArgb(0, 0, 0, 0);
            camera.SetOrthographicProjection(textureWidth, textureHeight);

            var currentSkeleton = ClientCharacterEquipmentHelper.CreateCharacterSkeleton(
                cameraObject,
                creatureSkeleton,
                worldScale: worldScale,
                spriteQualityOffset: spriteQualityOffset);

            currentSkeleton.PositionOffset = (textureWidth / 2d, -textureHeight * 0.70);
            currentSkeleton.RenderingTag   = renderingTag;

            await camera.DrawAsync();

            cameraObject.Destroy();

            request.ThrowIfCancelled();

            var generatedTexture = await renderTarget.SaveToTexture(
                isTransparent : true,
                qualityScaleCoef : Api.Client.Rendering.CalculateCurrentQualityScaleCoefWithOffset(
                    spriteQualityOffset));

            currentSkeleton.Destroy();
            renderTarget.Dispose();
            request.ThrowIfCancelled();
            return(generatedTexture);
        }
        public async Task <ITextureResource> GenerateIcon(
            ProceduralTextureRequest request,
            ushort textureWidth       = 384,
            ushort textureHeight      = 384,
            sbyte spriteQualityOffset = 0)
        {
            var protoSkeleton = this;

            var scale        = protoSkeleton.IconScale * textureWidth / 256.0;
            var renderingTag = request.TextureName;

            var renderTarget = Api.Client.Rendering.CreateRenderTexture(renderingTag, textureWidth, textureHeight);
            var cameraObject = Api.Client.Scene.CreateSceneObject(renderingTag);
            var camera       = Api.Client.Rendering.CreateCamera(cameraObject,
                                                                 renderingTag: renderingTag,
                                                                 drawOrder: -100);

            camera.RenderTarget = renderTarget;
            camera.ClearColor   = Color.FromArgb(0, 0, 0, 0);
            camera.SetOrthographicProjection(textureWidth, textureHeight);

            var currentSkeleton = ClientCharacterEquipmentHelper.CreateCharacterSkeleton(
                cameraObject,
                protoSkeleton,
                worldScale: scale,
                spriteQualityOffset: spriteQualityOffset);

            currentSkeleton.PositionOffset = (textureWidth / 2.0 + this.IconOffset.X * scale,
                                              -textureHeight * 0.7 + this.IconOffset.Y * scale);
            currentSkeleton.RenderingTag = renderingTag;

            await camera.DrawAsync();

            cameraObject.Destroy();

            request.ThrowIfCancelled();

            var generatedTexture = await renderTarget.SaveToTexture(
                isTransparent : true,
                qualityScaleCoef :
                Api.Client.Rendering.CalculateCurrentQualityScaleCoefWithOffset(
                    spriteQualityOffset));

            currentSkeleton.Destroy();
            renderTarget.Dispose();
            request.ThrowIfCancelled();
            return(generatedTexture);
        }
Example #4
0
        protected override void ClientUpdate(ClientUpdateData data)
        {
            var character   = data.GameObject;
            var clientState = data.ClientState;
            var publicState = data.PublicState;

            if (!character.IsCurrentClientCharacter)
            {
                ClientCharacterEquipmentHelper.ClientRefreshEquipment(character, clientState, publicState);
                base.ClientUpdate(data);
                return;
            }

            // next code is only for the current client character
            var privateState = data.PrivateState;

            if (!publicState.IsDead)
            {
                SharedRefreshSelectedHotbarItem(character, privateState);
            }

            ClientCharacterEquipmentHelper.ClientRefreshEquipment(character, clientState, publicState);

            this.ServerRebuildFinalCacheIfNeeded(privateState, publicState);
            this.SharedApplyInput(character, privateState, publicState);

            ClientCharacterAnimationHelper.ClientUpdateAnimation(
                character,
                clientState,
                publicState);

            if (publicState.IsDead)
            {
                // dead - stops processing character
                WindowRespawn.EnsureOpened();
                return;
            }

            // character is alive - can process its actions
            WindowRespawn.EnsureClosed();
            // 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);
            // consumes/restores stamina
            CharacterStaminaSystem.SharedUpdate(character, publicState, privateState, data.DeltaTime);
        }
Example #5
0
        protected override void ClientInitialize(ClientInitializeData data)
        {
            base.ClientInitialize(data);

            var        character = data.GameObject;
            IProtoItem previousSelectedProtoItem   = null;
            var        currentItemIdleSoundEmitter = Client.Audio.CreateSoundEmitter(character,
                                                                                     SoundResource.NoSound,
                                                                                     isLooped: true,
                                                                                     volume: 0.5f);

            var publicState = data.PublicState;
            var clientState = data.ClientState;

            ClientCharacterEquipmentHelper.ClientRefreshEquipment(character, clientState, publicState);

            if (character.IsCurrentClientCharacter)
            {
                this.ClientInitializeCurrentCharacter(data);
                this.ClientInitializeOtherCharacter(data);
            }
            else
            {
                this.ClientInitializeOtherCharacter(data);
            }

            // subscribe on head style change
            publicState.ClientSubscribe(
                _ => _.FaceStyle,
                _ => ResetRendering(resetSkeleton: false),
                clientState);

            // subscribe on gender change
            publicState.ClientSubscribe(
                _ => _.IsMale,
                _ => ResetRendering(resetSkeleton: true),
                clientState);

            // subscribe on head equipment visibility change
            publicState.ClientSubscribe(
                _ => _.IsHeadEquipmentHiddenForSelfAndPartyMembers,
                _ => ResetRendering(resetSkeleton: false),
                clientState);

            // subscribe on vehicle change
            publicState.ClientSubscribe(
                _ => _.CurrentVehicle,
                _ =>
            {
                // reset input history for lag prediction
                CurrentCharacterInputHistory.Instance.Clear();
                // re-create physics
                this.SharedCreatePhysics(character);
                // re-select current item
                SharedForceRefreshCurrentItem(ClientCurrentCharacterHelper.Character);
                // reset rendering
                ResetRendering(resetSkeleton: false);
            },
                clientState);

            // subscribe on player character public action change
            publicState.ClientSubscribe(
                _ => _.CurrentPublicActionState,
                _ => this.ClientRefreshCurrentPublicActionState(character),
                clientState);

            this.ClientRefreshCurrentPublicActionState(character);

            publicState.ClientSubscribe(
                _ => _.SelectedItem,
                _ =>
            {
                // selected different item
                RefreshCurrentSelectedItem();
            },
                clientState);

            publicState.ClientSubscribe(
                _ => _.IsDead,
                _ =>
            {
                // re-create physics on death state change
                this.SharedCreatePhysics(character);
                ResetRendering();

                if (character.IsCurrentClientCharacter &&
                    publicState.IsDead)
                {
                    Menu.CloseAll();
                }
            },
                clientState);

            RefreshCurrentSelectedItem();

            void RefreshCurrentSelectedItem()
            {
                previousSelectedProtoItem?.SharedGetItemSoundPreset()
                .PlaySound(ItemSound.Deselect, character);

                currentItemIdleSoundEmitter.Stop();
                var currentItem     = publicState.SelectedItem;
                var itemSoundPreset = currentItem?
                                      .ProtoItem
                                      .SharedGetItemSoundPreset();

                previousSelectedProtoItem = currentItem?.ProtoItem;

                if (itemSoundPreset != null)
                {
                    itemSoundPreset.PlaySound(ItemSound.Select, character);

                    var idleSoundResource = itemSoundPreset.GetSound(ItemSound.Idle);
                    if (idleSoundResource != null)
                    {
                        currentItemIdleSoundEmitter.SoundResource = idleSoundResource;
                        currentItemIdleSoundEmitter.Delay         = 0.1;
                        currentItemIdleSoundEmitter.Play();
                    }
                }
            }

            void ResetRendering(bool resetSkeleton = false)
            {
                // reset hash to force updating equipment/skeleton in the next frame
                clientState.LastEquipmentContainerHash = null;
                if (resetSkeleton)
                {
                    clientState.CurrentProtoSkeleton = null;
                }
            }
        }
        protected override void ClientInitialize(ClientInitializeData data)
        {
            base.ClientInitialize(data);

            var        character = data.GameObject;
            IProtoItem previousSelectedProtoItem   = null;
            var        currentItemIdleSoundEmitter = Client.Audio.CreateSoundEmitter(character,
                                                                                     SoundResource.NoSound,
                                                                                     isLooped: true,
                                                                                     volume: 0.5f);

            var publicState = data.SyncPublicState;
            var clientState = data.ClientState;

            ClientCharacterEquipmentHelper.ClientRefreshEquipment(character, clientState, publicState);

            if (character.IsCurrentClientCharacter)
            {
                this.ClientInitializeCurrentCharacter(data);
            }
            else
            {
                this.ClientInitializeOtherCharacter(data);
            }

            // subscribe on head style change
            publicState.ClientSubscribe(
                _ => _.FaceStyle,
                _ => ResetRendering(resetSkeleton: true),
                clientState);

            // subscribe on gender change
            publicState.ClientSubscribe(
                _ => _.IsMale,
                _ => ResetRendering(),
                clientState);

            // subscribe on player character public action change
            publicState.ClientSubscribe(
                _ => _.CurrentPublicActionState,
                _ => this.ClientRefreshCurrentPublicActionState(character),
                clientState);

            this.ClientRefreshCurrentPublicActionState(character);

            publicState.ClientSubscribe(
                _ => _.SelectedHotbarItem,
                _ =>
            {
                // selected different item
                RefreshCurrentSelectedItem();
            },
                clientState);

            publicState.ClientSubscribe(
                _ => _.IsDead,
                _ =>
            {
                // re-create physics on death state change
                this.SharedCreatePhysics(character);
                ResetRendering();
            },
                clientState);

            RefreshCurrentSelectedItem();

            void RefreshCurrentSelectedItem()
            {
                previousSelectedProtoItem?.SharedGetItemSoundPreset()
                .PlaySound(ItemSound.Deselect, limitOnePerFrame: false);

                currentItemIdleSoundEmitter.Stop();
                var currentItem     = publicState.SelectedHotbarItem;
                var itemSoundPreset = currentItem?
                                      .ProtoItem
                                      .SharedGetItemSoundPreset();

                previousSelectedProtoItem = currentItem?.ProtoItem;

                if (itemSoundPreset == null)
                {
                    return;
                }

                itemSoundPreset.PlaySound(ItemSound.Select, limitOnePerFrame: false);
                var idleSoundResource = itemSoundPreset.GetSound(ItemSound.Idle);

                if (idleSoundResource != null)
                {
                    currentItemIdleSoundEmitter.SoundResource = idleSoundResource;
                    currentItemIdleSoundEmitter.Delay         = 0.1;
                    currentItemIdleSoundEmitter.Play();
                }
            }

            void ResetRendering(bool resetSkeleton = false)
            {
                // reset hash to force updating equipment/skeleton in the next frame
                clientState.LastEquipmentContainerHash = null;
                if (resetSkeleton)
                {
                    clientState.CurrentProtoSkeleton = null;
                }
            }
        }