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); }
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); }
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; } } }