static ClientSoundRepetitionProtectionManager() { if (Api.IsClient) { ClientComponentTimersManager.AddAction(ClientTimerIntervalSeconds, ClientTimerCallback); } }
private void ClientAddShakes(ClientComponentBombCountdown component) { const float shakesInterval = 0.5f, shakesDuration = 1f, shakesDistanceMin = 0.2f, shakesDistanceMax = 0.25f; if (component.IsDestroyed) { return; } var intensity = 1 - component.SecondsRemains / this.ExplosionDelay.TotalSeconds; if (intensity < 0.3) { intensity = 0.3; } ClientComponentCameraScreenShakes.AddRandomShakes(duration: shakesDuration, worldDistanceMin: (float)(intensity * -shakesDistanceMin), worldDistanceMax: (float)(intensity * shakesDistanceMax)); ClientComponentTimersManager.AddAction(shakesInterval, () => this.ClientAddShakes(component)); }
private void TimerTickCallback() { if (IsClient) { ClientComponentTimersManager.AddAction(CheckTimeIntervalSeconds, this.TimerTickCallback); } RegisteredActions.ProcessAndRemove( // remove if cannot interact removeCondition: pair => !IsValidInteraction(pair), // abort action when pair removed due to the interaction check failed removeCallback: pair => pair.Value.FinishAction?.Invoke(isAbort: true)); }
private void RefreshRaidedState() { if (!this.areaPrivateState.LastRaidTime.HasValue) { this.RemoveRaidNotificationControl(); return; } var timeSinceRaid = Api.Client.CurrentGame.ServerFrameTimeRounded - this.areaPrivateState.LastRaidTime.Value; var isRaidedNow = timeSinceRaid < LandClaimSystem.RaidCooldownDurationSeconds; if (this.isRaided == isRaidedNow) { // no changes return; } this.isRaided = isRaidedNow; if (!this.isRaided) { this.RemoveRaidNotificationControl(); return; } var bounds = LandClaimSystem.SharedGetLandClaimAreaBounds(this.area); var x = bounds.X + bounds.Width / 2; var y = bounds.Y + bounds.Height / 2; // add raid mark control to map this.markRaidNotificationControl = new WorldMapMarkRaid(); var canvasPosition = this.GetAreaCanvasPosition(); Canvas.SetLeft(this.markRaidNotificationControl, canvasPosition.X); Canvas.SetTop(this.markRaidNotificationControl, canvasPosition.Y); Panel.SetZIndex(this.markRaidNotificationControl, 11); this.worldMapController.AddControl(this.markRaidNotificationControl); // show text notification NotificationSystem.ClientShowNotification( NotificationBaseUnderAttack_Title, string.Format(NotificationBaseUnderAttack_MessageFormat, x, y), NotificationColor.Bad, icon: Api.GetProtoEntity <ObjectCharredGround>().Icon); // start refresh timer ClientComponentTimersManager.AddAction(1, this.RaidRefreshTimerCallback); }
private void ControlWorldMapMouseRightButtonUpHandler(object sender, MouseButtonEventArgs e) { var mapPositionWithOffset = this.controlWorldMap.WorldMapController.PointedMapPositionWithOffset; this.CloseContextMenu(); var contextMenu = new ContextMenu(); contextMenu.Items.Add(new MenuItem() { Header = ContextMenuCopyCoordinates, Command = new ActionCommand( () => Api.Client.Core.CopyToClipboard(mapPositionWithOffset.ToString())) }); if (ServerOperatorSystem.ClientIsOperator()) { var mapPositionWithoutOffset = this.controlWorldMap.WorldMapController.PointedMapPositionWithoutOffset; contextMenu.Items.Add(new MenuItem() { Header = ContextMenuTeleport, Command = new ActionCommand( () => this.CallTeleport(mapPositionWithoutOffset.ToVector2D())) }); } var position = Mouse.GetPosition(this); contextMenu.PlacementRectangle = new Rect(position.X, position.Y, 0, 0); this.ContextMenu = contextMenu; contextMenu.Closed += ContextMenuOnClosed; contextMenu.IsOpen = true; void ContextMenuOnClosed(object s, RoutedEventArgs _) { contextMenu.Closed -= ContextMenuOnClosed; // remove context menu with the delay (to avoid teleport-on-click when context menu is closed) ClientComponentTimersManager.AddAction( delaySeconds: 0.1, () => { if (this.ContextMenu == contextMenu) { this.ContextMenu = null; } }); } }
protected override void PrepareSystem() { if (IsServer) { // configure time interval trigger TriggerTimeInterval.ServerConfigureAndRegister( interval: TimeSpan.FromSeconds(CheckTimeIntervalSeconds), callback: this.TimerTickCallback, name: "System." + this.ShortId); } else // if (IsClient) { ClientComponentTimersManager.AddAction(CheckTimeIntervalSeconds, this.TimerTickCallback); } }
private void QueueClientElementRemovedHandler( NetworkSyncList <CraftingQueueItem> source, int index, CraftingQueueItem removedValue) { if (this.craftingQueueItems.Count == 0) { // queue finished sounds ClientComponentTimersManager.AddAction( delaySeconds: 0.3, action: () => Client.Audio.PlayOneShot(new SoundResource("UI/Crafting/Completed"))); } this.RemoveControl(removedValue); }
private void TimerUpdateDisplayedTime() { if (this.IsDisposed) { // view model is disposed - stop updating return; } this.UpdateDisplayedTimeNoTimer(); // schedule refresh of the displayed time ClientComponentTimersManager.AddAction( TimerRefreshIntervalSeconds, this.TimerUpdateDisplayedTime); }
private void RaidRefreshTimerCallback() { if (this.IsDisposed || !this.isRaided) { return; } this.RefreshRaidedState(); if (this.isRaided) { // still raided ClientComponentTimersManager.AddAction(delaySeconds: 1, this.RaidRefreshTimerCallback); } }
private HUDNotificationControl ShowInternal( string title, string message, Brush brushBackground, Brush brushBorder, ITextureResource icon, Action onClick, bool autoHide, SoundResource soundToPlay) { Api.Logger.Important( string.Format( "Showing notification:{0}Title: {1}{0}Message: {2}", Environment.NewLine, title, message)); var notificationControl = HUDNotificationControl.Create( title, message, brushBackground, brushBorder, icon, onClick, autoHide, soundToPlay); this.HideSimilarNotifications(notificationControl); this.stackPanelChildren.Add(notificationControl); if (notificationControl.IsAutoHide) { // hide the notification control after delay ClientComponentTimersManager.AddAction( NotificationHideDelaySeconds, () => notificationControl.Hide(quick: false)); } this.HideOldNotificationsIfTooManyDisplayed(); return(notificationControl); }
private static void ClientTimerCallback() { // schedule next callback ClientComponentTimersManager.AddAction(ClientTimerIntervalSeconds, ClientTimerCallback); // calculate expiration time var time = ClientCore.ClientRealTime - EntryLifetimeSeconds; for (var index = 0; index < List.Count; index++) { var entry = List[index]; if (time >= entry.LastAccessedTime) { // entry outdated, remove it List.RemoveAt(index); index--; } } }
private void RefreshCallback() { if (this.IsDisposed) { // stop refreshing return; } try { this.RefreshMetrics(); } finally { // schedule next refresh ClientComponentTimersManager.AddAction(delaySeconds: ViewModelPerformanceMetric.RefreshInterval, this.RefreshCallback); } }
public void Hide(double delaySeconds) { if (this.isHiddenOrHiding) { return; } this.isHiddenOrHiding = true; var hideRequestId = ++this.lastHideRequestId; ClientComponentTimersManager.AddAction( delaySeconds, () => { if (this.isHiddenOrHiding && hideRequestId == this.lastHideRequestId) { VisualStateManager.GoToElementState(this.textBlock, "Hidden", true); } }); }
public static void EnsureOpened() { if (!isClosed) { return; } isClosed = false; var windowRespawn = new WindowRespawn(); instance = windowRespawn; Api.Client.UI.LayoutRootChildren.Add(instance); var loadingSplashScreenState = LoadingSplashScreenManager.Instance.CurrentState; var delay = loadingSplashScreenState == LoadingSplashScreenState.Shown || loadingSplashScreenState == LoadingSplashScreenState.Showing ? 0 : 2; ClientComponentTimersManager.AddAction( delaySeconds: delay, action: () => { windowRespawn.Window.IsCached = false; if (isClosed) { if (ReferenceEquals(instance, windowRespawn)) { instance = null; Api.Client.UI.LayoutRootChildren.Remove(instance); } return; } instance.Window.Open(); }); }
private void ShowInternal(IProtoItem protoItem, int deltaCount) { if (protoItem == null) { throw new ArgumentNullException(nameof(protoItem)); } if (deltaCount == 0) { throw new ArgumentOutOfRangeException(nameof(deltaCount)); } var notificationControl = HUDItemNotificationControl.Create(protoItem, deltaCount); this.stackPanelChildren.Add(notificationControl); // hide after delay ClientComponentTimersManager.AddAction( NotificationHideDelaySeconds, () => notificationControl.Hide(quick: false)); this.HideOldNotificationsIfTooManyDisplayed(); }
public static void Explode(double delaySeconds, Vector2D position) { var tilePosition = position.ToVector2Ushort(); CurrentExplosions.Add(tilePosition); ClientComponentTimersManager.AddAction( delaySeconds, () => { var groundSceneObject = Api.Client.Scene.CreateSceneObject("Temp explosion ground", position); var groundSpriteRenderer = Api.Client.Rendering.CreateSpriteRenderer( groundSceneObject, TextureResource.NoTexture, drawOrder: DrawOrder.FloorCharredGround, spritePivotPoint: (0.5, 0.5), scale: ObjectCharredGround.Scale); if (IsGroundSpriteFlipped(tilePosition)) { groundSpriteRenderer.DrawMode = DrawMode.FlipHorizontally; } var duration = ExplosionGroundDuration; ClientComponentOneShotSpriteSheetAnimationHelper.Setup( groundSpriteRenderer, ExplosionGroundTextureAtlas, duration); groundSceneObject.Destroy(duration); ClientComponentTimersManager.AddAction( duration, () => CurrentExplosions.Remove(tilePosition)); });
public static void ShowOn(ICharacter character, string message) { message = message.ToLowerInvariant(); var positionOffset = (0, character.ProtoCharacter.CharacterWorldHeight + 0.25); if (DisplayedMessages.TryGetValue(character, out var control)) { DisplayedMessages.Remove(character); if (control.isLoaded) { // destroy already displayed message control control.Hide(fast: true); ClientComponentTimersManager.AddAction( 0.075, () => ShowOn(character, message)); return; } } // create and setup new message control control = new CharacterLocalChatMessageDisplay(); control.Setup(message); control.attachedComponent = Api.Client.UI.AttachControl( character, control, positionOffset: positionOffset, isScaleWithCameraZoom: false, isFocusable: false); ClientComponentTimersManager.AddAction(TimeoutSeconds, () => control.Hide(fast: false)); DisplayedMessages.Add(character, control); }
public static void ClientUpdateAnimation( ICharacter character, BaseCharacterClientState clientState, ICharacterPublicState publicState) { var skeletonRenderer = clientState.SkeletonRenderer; if (skeletonRenderer == null) { return; } var activeWeaponProto = publicState.CurrentItemWeaponProto; var protoSkeleton = clientState.CurrentProtoSkeleton; var rendererShadow = clientState.RendererShadow; var wasDead = clientState.IsDead; clientState.IsDead = publicState.IsDead; if (publicState.IsDead) { if (skeletonRenderer.GetCurrentAnimationName(AnimationTrackIndexes.Primary) == "Death") { // already in death animation return; } // character was not dead on client and now become dead skeletonRenderer.ResetSkeleton(); skeletonRenderer.SelectCurrentSkeleton( protoSkeleton.SkeletonResourceFront, "Idle", isLooped: false); skeletonRenderer.SetAnimation(AnimationTrackIndexes.Primary, "Death", isLooped: false); if (!wasDead.HasValue) { // character entered scope and it's dead skeletonRenderer.SetAnimationTime(0, 10000); // hide skeleton completely HideBody(); return; } // character just died // play death sound protoSkeleton.PlaySound(CharacterSound.Death, character); clientState.SoundEmitterLoopCharacter.Stop(); clientState.SoundEmitterLoopMovemement.Stop(); // hide skeleton after timeout ClientComponentTimersManager.AddAction( CorpseTimeoutSeconds, HideBody); void HideBody() { if (!publicState.IsDead) { // the character has been respawned return; } skeletonRenderer.IsEnabled = false; rendererShadow.IsEnabled = false; } return; } skeletonRenderer.IsEnabled = true; rendererShadow.IsEnabled = true; var appliedInput = publicState.AppliedInput; GetCurrentAnimationSetting( protoSkeleton, appliedInput.MoveModes, appliedInput.RotationAngleRad, clientState.LastViewOrientation, out var newAnimationStarterName, out var newAnimationName, out var currentDrawMode, out var aimCoef, out var viewOrientation, out var isIdle); clientState.LastViewOrientation = viewOrientation; // TODO: consider adding new field - HasBackwardAnimations if (!protoSkeleton.HasMoveStartAnimations) { newAnimationStarterName = null; if (newAnimationName == "RunSideBackward") { newAnimationName = "RunSide"; } } var currentSkeleton = viewOrientation.IsUp && protoSkeleton.SkeletonResourceBack != null ? protoSkeleton.SkeletonResourceBack : protoSkeleton.SkeletonResourceFront; if (skeletonRenderer.CurrentSkeleton != currentSkeleton) { // switch skeleton completely skeletonRenderer.SelectCurrentSkeleton( currentSkeleton, // please note: no starter animation in that case! animationName: newAnimationName, isLooped: true); } else { var activeAnimationName = skeletonRenderer.GetLatestAddedAnimationName(trackIndex: AnimationTrackIndexes.Primary); if (newAnimationName != activeAnimationName && newAnimationStarterName != activeAnimationName) { //Api.Logger.WriteDev( // newAnimationStarterName != null // ? $"Changing move animation: {activeAnimationName}->{newAnimationStarterName}->{newAnimationName}" // : $"Changing move animation: {activeAnimationName}->{newAnimationName}"); var hasStarterAnimation = newAnimationStarterName != null; if (hasStarterAnimation) { // add starter animation skeletonRenderer.SetAnimation( trackIndex: AnimationTrackIndexes.Primary, animationName: newAnimationStarterName, isLooped: false); // add looped animation skeletonRenderer.AddAnimation( trackIndex: AnimationTrackIndexes.Primary, animationName: newAnimationName, isLooped: true); } else if (newAnimationName == "Idle" && skeletonRenderer.GetCurrentAnimationName(trackIndex: AnimationTrackIndexes.Primary) .EndsWith("Start")) { // going into idle when playing a start animation - allow to finish it! // remove queued entries skeletonRenderer.RemoveAnimationTrackNextEntries(trackIndex: AnimationTrackIndexes.Primary); // add looped idle animation skeletonRenderer.AddAnimation( trackIndex: AnimationTrackIndexes.Primary, animationName: newAnimationName, isLooped: true); } else { // set looped animation skeletonRenderer.SetAnimation( trackIndex: AnimationTrackIndexes.Primary, animationName: newAnimationName, isLooped: true); } } } if (appliedInput.MoveModes != CharacterMoveModes.None) { // moving mode var animationSpeedMultiplier = appliedInput.MoveSpeed / (protoSkeleton.DefaultMoveSpeed * clientState.CurrentProtoSkeletonScaleMultiplier); skeletonRenderer.SetAnimationSpeed( trackIndex: AnimationTrackIndexes.Primary, speedMultiliper: (float)animationSpeedMultiplier); // moving - remove animation for static firing skeletonRenderer.RemoveAnimationTrack(AnimationTrackIndexes.ItemFiringStatic); } else { skeletonRenderer.SetAnimationSpeed( trackIndex: AnimationTrackIndexes.Primary, speedMultiliper: 1.0f); } skeletonRenderer.DrawMode = currentDrawMode; if (activeWeaponProto != null) { clientState.HasWeaponAnimationAssigned = true; clientState.LastAimCoef = aimCoef; var aimingAnimationName = activeWeaponProto.CharacterAnimationAimingName; if (aimingAnimationName != null) { //Api.Logger.WriteDev( // $"Setting aiming animation: {aimingAnimationName} timePercents: {aimCoef:F2}"); skeletonRenderer.SetAnimationFrame( trackIndex: AnimationTrackIndexes.ItemAiming, animationName: aimingAnimationName, timePositionPercents: aimCoef); } else { skeletonRenderer.RemoveAnimationTrack(AnimationTrackIndexes.ItemAiming); } WeaponSystemClientDisplay.RefreshCurrentAttackAnimation(character); } else { clientState.HasWeaponAnimationAssigned = false; } SetLoopSounds(character, clientState, publicState.AppliedInput, protoSkeleton, isIdle); }
public static void ClientExplode( Vector2D position, ExplosionPreset explosionPreset, float volume = 1.0f) { // add screen shakes ClientComponentCameraScreenShakes.AddRandomShakes( duration: explosionPreset.ScreenShakesDuration, worldDistanceMin: explosionPreset.ScreenShakesWorldDistanceMin, worldDistanceMax: explosionPreset.ScreenShakesWorldDistanceMax); // play sound var explosionSoundEmitter = Client.Audio.PlayOneShot(explosionPreset.SoundSet.GetSound(), worldPosition: position, volume: volume, pitch: RandomHelper.Range(0.95f, 1.05f)); // extend explosion sound distance explosionSoundEmitter.CustomMinDistance = (float)explosionPreset.LightWorldSize / 3; explosionSoundEmitter.CustomMaxDistance = (float)explosionPreset.LightWorldSize; // create explosion renderer var explosionSpriteAnimationDuration = explosionPreset.SpriteAnimationDuration; var explosionSceneObject = Client.Scene.CreateSceneObject("Temp explosion", position); explosionSceneObject.Destroy(delay: explosionSpriteAnimationDuration); var explosionSpriteRenderer = Client.Rendering.CreateSpriteRenderer( explosionSceneObject, TextureResource.NoTexture, drawOrder: DrawOrder.Explosion, spritePivotPoint: (0.5, 0.5)); explosionSpriteRenderer.Color = explosionPreset.SpriteColorMultiplicative; explosionSpriteRenderer.Size = explosionPreset.SpriteSize; if (explosionPreset.SpriteColorAdditive.HasValue // ReSharper disable once CompareOfFloatsByEqualityOperator || explosionPreset.SpriteBrightness != 1) { var renderingMaterial = RenderingMaterial.Create(EffectResourceAdditiveColorEffect); renderingMaterial.EffectParameters .Set("ColorAdditive", explosionPreset.SpriteColorAdditive ?? Colors.Black) .Set("Brightness", explosionPreset.SpriteBrightness); explosionSpriteRenderer.RenderingMaterial = renderingMaterial; } var isFlipped = 0 == PositionalRandom.Get(position.ToVector2Ushort(), minInclusive: 0, maxExclusive: 2, seed: 893243289); if (isFlipped) { explosionSpriteRenderer.DrawMode = DrawMode.FlipHorizontally; } ClientComponentOneShotSpriteSheetAnimationHelper.Setup( explosionSpriteRenderer, explosionPreset.SpriteAtlasResources.TakeByRandom(), explosionSpriteAnimationDuration); // add light source for the explosion var explosionLight = ClientLighting.CreateLightSourceSpot( explosionSceneObject, explosionPreset.LightColor, size: explosionPreset.LightWorldSize, positionOffset: (0, 0), spritePivotPoint: (0.5, 0.5)); ClientComponentOneShotLightAnimation.Setup( explosionLight, explosionPreset.LightDuration); // add blast wave var blastAnimationDuration = explosionPreset.BlastwaveAnimationDuration; if (blastAnimationDuration > 0) { ClientComponentTimersManager.AddAction( explosionPreset.BlastwaveDelay, () => { var blastSceneObject = Client.Scene.CreateSceneObject("Temp explosion", position); blastSceneObject.Destroy(delay: blastAnimationDuration); var blastSpriteRenderer = Client.Rendering.CreateSpriteRenderer( blastSceneObject, new TextureResource("FX/ExplosionBlast"), drawOrder: DrawOrder.Explosion - 1, spritePivotPoint: (0.5, 0.5)); // animate blast wave ClientComponentGenericAnimationHelper.Setup( blastSceneObject, blastAnimationDuration, updateCallback: alpha => { var blastwaveAlpha = (byte)(byte.MaxValue * (1 - alpha)); blastSpriteRenderer.Color = explosionPreset.BlastWaveColor .WithAlpha(blastwaveAlpha); var sizeX = MathHelper.Lerp((float)explosionPreset.BlastwaveSizeFrom.X, (float)explosionPreset.BlastwaveSizeTo.X, alpha); var sizeY = MathHelper.Lerp((float)explosionPreset.BlastwaveSizeFrom.Y, (float)explosionPreset.BlastwaveSizeTo.Y, alpha); blastSpriteRenderer.Size = new Size2F(sizeX, sizeY); }); }); } // add ground explosion animation { ClientGroundExplosionAnimationHelper.Explode( delaySeconds: explosionSpriteAnimationDuration / 2, position: position); } }
private void ScheduleSyncToServer() { ClientComponentTimersManager.AddAction( CommitZoneChangesDelaySeconds / 4.0, () => this.SyncToServer(forceImmediate: false)); }