public static void OnFishCaughtOrFishingCancelled(
            ICharacter character,
            [CanBeNull] IProtoItem protoItemFishCaught,
            Vector2D fishingTargetPosition,
            float caughtFishSizeValue)
        {
            ClientTimersSystem.AddAction(
                FishingCompletedAnimationDelay,
                () =>
            {
                ComponentFishingVisualizer.TryGetFor(character, out var fishingVisualizer);
                if (fishingVisualizer is null)
                {
                    return;
                }

                if (fishingVisualizer.FishingCompletedVisualizer is null)
                {
                    Api.Client.Scene.CreateSceneObject(nameof(ComponentFishingCompletedVisualizer))
                    .AddComponent <ComponentFishingCompletedVisualizer>()
                    .Setup(fishingTargetPosition,
                           character,
                           protoItemFishCaught,
                           caughtFishSizeValue);
                }
                else if (protoItemFishCaught is not null)
                {
                    fishingVisualizer.FishingCompletedVisualizer
                    .SetupFish(protoItemFishCaught, caughtFishSizeValue);
                }
            });
        }
示例#2
0
        public static void ShowNotificationControl
        <TNotificationControl>(TNotificationControl notificationControl)
            where TNotificationControl : UIElement, IHudNotificationControl
        {
            var panelControl = instance;

            if (notificationControl.IsAutoHide)
            {
                panelControl.HideSimilarNotifications(notificationControl);
            }

            panelControl.stackPanelChildren.Add(notificationControl);

            if (notificationControl.IsAutoHide)
            {
                // hide the notification control after delay
                ClientTimersSystem.AddAction(
                    NotificationHideDelaySeconds,
                    () =>
                {
                    if (notificationControl.IsAutoHide)     // still configured as auto hide
                    {
                        notificationControl.Hide(quick: false);
                    }
                });
            }

            panelControl.HideOldNotificationsIfTooManyDisplayed();
        }
示例#3
0
        protected override void InitControl()
        {
            this.grid = this.GetByName <Grid>("Grid");

            // wrap the content into a hotbar extension control
            this.Content = null;
            this.Content = new HotbarItemSlotExtensionControl()
            {
                SlotContent = this.grid
            };

            this.storyboardAnimationSignalPing = this.grid.GetResource <Storyboard>("StoryboardAnimationSignalPing");
            this.storyboardAnimationSignalPong = this.grid.GetResource <Storyboard>("StoryboardAnimationSignalPong");

            // we cannot seek Storyboard in NoesisGUI yet https://www.noesisengine.com/bugs/view.php?id=1484
            // apply a workaround
            this.grid.Visibility = Visibility.Hidden;
            this.storyboardAnimationSignalPing.Begin(this.grid);
            this.storyboardAnimationSignalPong.Begin(this.grid);

            ClientTimersSystem.AddAction(
                Math.Max(this.storyboardAnimationSignalPing.Duration.TimeSpan.TotalSeconds,
                         this.storyboardAnimationSignalPong.Duration.TimeSpan.TotalSeconds),
                () => this.grid.Visibility = Visibility.Visible);
        }
示例#4
0
            private void RefreshNotification()
            {
                if (this.notification is null ||
                    this.IsDestroyed ||
                    this.activeEvents.TrueForAll(e => e.IsDestroyed))
                {
                    // the notification will be automatically marked to hide after delay when active event is destroyed
                    // (a finished event)
                    return;
                }

                var timeRemains = this.CalculateEventTimeRemains();

                if (timeRemains <= 0)
                {
                    if (!this.notification.IsHiding)
                    {
                        this.RemoveNotification(quick: false);
                    }

                    return;
                }

                this.notification.Message = this.GetUpdatedEventNotificationText(timeRemains);

                // schedule recursive update in a second
                ClientTimersSystem.AddAction(1, this.RefreshNotification);
            }
        private static void ShowNotificationLearnExtraTechnologies(object points)
        {
            var storage = Client.Storage.GetSessionStorage(nameof(ClientLearningPointsNotifier)
                                                           + nameof(ShowNotificationLearnExtraTechnologies));

            if (storage.TryLoad(out bool _))
            {
                // this message was already was displayed once during this play session
                return;
            }

            // remember that we already showed this message once
            storage.Save(true);

            if (IsEditor)
            {
                // do not show this notification in Editor
                return;
            }

            var notification = NotificationSystem.ClientShowNotification(
                CoreStrings.Technology,
                string.Format(NotificationSpendLearningPointsReminder, points),
                icon: NotificationIcon,
                onClick: Menu.Open <WindowTechnologies>,
                autoHide: false);

            notification.SetupAutoHideChecker(
                // hide when menu is opened
                Menu.IsOpened <WindowTechnologies>);

            ClientTimersSystem.AddAction(delaySeconds: 60,
                                         () => notification.Hide(quick: false));
        }
示例#6
0
        public static void Init(ICharacter character)
        {
            if (droppedItemsLocations is not null)
            {
                droppedItemsLocations.ClientElementInserted -= MarkerAddedHandler;
                droppedItemsLocations.ClientElementRemoved  -= MarkerRemovedHandler;
                droppedItemsLocations = null;
            }

            foreach (var notification in Notifications)
            {
                notification.Value.Hide(quick: true);
            }

            Notifications.Clear();

            droppedItemsLocations = PlayerCharacter.GetPrivateState(character)
                                    .DroppedLootLocations;

            droppedItemsLocations.ClientElementInserted += MarkerAddedHandler;
            droppedItemsLocations.ClientElementRemoved  += MarkerRemovedHandler;

            ClientTimersSystem.AddAction(
                delaySeconds: 1,
                () =>
            {
                foreach (var droppedLootInfo in droppedItemsLocations)
                {
                    ShowNotification(droppedLootInfo);
                }
            });
        }
示例#7
0
        private void Update()
        {
            if (this.isDisposeScheduled)
            {
                return;
            }

            if (this.publicState.IsDead ||
                (this.clientState?.IsDisposed ?? true))
            {
                if (this.VisualStateName == "Collapsed")
                {
                    // dispose instantly
                    this.IsReadyForDispose = true;
                    return;
                }

                // dispose after fade out
                this.VisualStateName = "Collapsed";
                ClientTimersSystem.AddAction(0.5,
                                             () => this.IsReadyForDispose = true);
                this.isDisposeScheduled = true;
                return;
            }

            this.VisualStateName = "Visible";
        }
示例#8
0
        private static void UpdateNotificationControlText()
        {
            if (notificationControl is null ||
                serverSaveScheduledTime is null)
            {
                return;
            }

            string message;

            var secondsRemains = serverSaveScheduledTime.Value - Api.Client.CurrentGame.ServerFrameTimeApproximated;

            if (secondsRemains <= 0)
            {
                secondsRemains = 0;
                message        = CoreStrings.AutosaveNotification_Saving;
            }
            else
            {
                message = string.Format(CoreStrings.AutosaveNotification_DelayRemains_Format,
                                        ClientTimeFormatHelper.FormatTimeDuration(secondsRemains));
            }

            notificationControl.Message = NotificationMessageBaseText + message;

            if (secondsRemains > 0)
            {
                ClientTimersSystem.AddAction(1, UpdateNotificationControlText);
            }
        }
        private void Update()
        {
            if (this.IsDisposed)
            {
                return;
            }

            // schedule next update
            ClientTimersSystem.AddAction(1, this.Update);

            var timeRemains = this.characterPublicState.UnstuckExecutionTime
                              - Client.CurrentGame.ServerFrameTimeApproximated;

            timeRemains = Math.Max(timeRemains, 0);
            if (this.lastTimeRemains == timeRemains)
            {
                return;
            }

            this.lastTimeRemains = timeRemains;
            if (timeRemains > 0)
            {
                this.VisibilityUnstuckInfo = Visibility.Visible;
                this.UnstuckInfoMessage    = string.Format(CoreStrings.UnstuckInFormat,
                                                           ClientTimeFormatHelper.FormatTimeDuration(timeRemains));
            }
            else
            {
                this.VisibilityUnstuckInfo = Visibility.Collapsed;
                this.UnstuckInfoMessage    = string.Empty;
            }
        }
示例#10
0
 static ClientSoundRepetitionProtectionManager()
 {
     if (Api.IsClient)
     {
         ClientTimersSystem.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));

            ClientTimersSystem.AddAction(shakesInterval, () => this.ClientAddShakes(component));
        }
示例#12
0
        private void MouseEnterOrLeaveHandler(object sender, MouseEventArgs e)
        {
            var refreshNumber = ++this.expandedStateRefreshScheduledNumber;

            ClientTimersSystem.AddAction(ExpandOrCollapseDelay,
                                         () => this.RefreshState(refreshNumber));
        }
示例#13
0
        private void Refresh()
        {
            this.ViewModelVehicleEnergy?.Dispose();

            var vehicle = this.playerCharacterPublicState.CurrentVehicle;

            if (vehicle is null)
            {
                this.IndicatorVisibility    = Visibility.Collapsed;
                this.ViewModelVehicleEnergy = null;
                return;
            }

            if (!vehicle.IsInitialized)
            {
                // refresh when vehicle will be initialized
                ClientTimersSystem.AddAction(0.1, this.Refresh);

                this.IndicatorVisibility    = Visibility.Collapsed;
                this.ViewModelVehicleEnergy = null;
                return;
            }

            this.ViewModelVehicleEnergy = new ViewModelVehicleEnergy(vehicle);
            this.IndicatorVisibility    = Visibility.Visible;
            this.NotifyPropertyChanged(nameof(this.TooltipFormat));
        }
        private IHudNotificationControl ShowInternal(
            string title,
            string message,
            Brush brushBackground,
            Brush brushBorder,
            ITextureResource icon,
            Action onClick,
            bool autoHide,
            SoundResource soundToPlay,
            bool writeToLog)
        {
            if (writeToLog)
            {
                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);

            var instance = this;

            if (notificationControl.IsAutoHide)
            {
                instance.HideSimilarNotifications(notificationControl);
            }

            instance.stackPanelChildren.Add(notificationControl);

            if (notificationControl.IsAutoHide)
            {
                // hide the notification control after delay
                ClientTimersSystem.AddAction(
                    NotificationHideDelaySeconds,
                    () =>
                {
                    if (notificationControl.IsAutoHide)     // still configured as auto hide
                    {
                        notificationControl.Hide(quick: false);
                    }
                });
            }

            instance.HideOldNotificationsIfTooManyDisplayed();

            return(notificationControl);
        }
        private static void ClientRefreshCurrentUnstuckRequestStatus()
        {
            // invoke self again a second later
            ClientTimersSystem.AddAction(delaySeconds: 1,
                                         ClientRefreshCurrentUnstuckRequestStatus);

            var characterPublicState = ClientCurrentCharacterHelper.PublicState;

            if (ClientCurrentUnstuckNotification != null)
            {
                if (ClientCurrentUnstuckNotification.IsHiding)
                {
                    ClientCurrentUnstuckNotification = null;
                }
                else if (ClientCurrentUnstuckNotification.Tag != characterPublicState)
                {
                    // outdated notification
                    ClientCurrentUnstuckNotification?.Hide(quick: false);
                    ClientCurrentUnstuckNotification = null;
                }
            }

            if (characterPublicState == null)
            {
                ClientCurrentUnstuckNotification?.Hide(quick: false);
                ClientCurrentUnstuckNotification = null;
                return;
            }

            var timeRemains = characterPublicState.UnstuckExecutionTime
                              - Client.CurrentGame.ServerFrameTimeApproximated;

            if (timeRemains <= 0)
            {
                // no active unstuck requests
                ClientCurrentUnstuckNotification?.Hide(quick: false);
                ClientCurrentUnstuckNotification = null;
                return;
            }

            // has active unstuck request, create or update the notification
            var message = string.Format(NotificationUnstuckRequested_MessageFormat,
                                        ClientTimeFormatHelper.FormatTimeDuration(timeRemains));

            if (ClientCurrentUnstuckNotification == null)
            {
                ClientCurrentUnstuckNotification = NotificationSystem.ClientShowNotification(
                    NotificationUnstuckRequested_Title,
                    message,
                    autoHide: false);
                ClientCurrentUnstuckNotification.Tag = characterPublicState;
            }
            else
            {
                ClientCurrentUnstuckNotification.Message = message;
            }
        }
示例#16
0
        public static void OnExplode(double delaySeconds, Vector2D position)
        {
            var tilePosition = position.ToVector2Ushort();

            CurrentExplosions.Add(tilePosition);

            ClientTimersSystem.AddAction(
                delaySeconds + ExplosionGroundDuration,
                () => CurrentExplosions.Remove(tilePosition));
        }
示例#17
0
        private void CurrentFactionChangedHandler()
        {
            this.CloseWindow();

            if (FactionSystem.ClientHasFaction)
            {
                ClientTimersSystem.AddAction(0.1,
                                             Menu.Open <WindowFaction>);
            }
        }
示例#18
0
        private void UpdateText()
        {
            if (this.IsDisposed)
            {
                return;
            }

            this.ProtectionTimeRemainingText = ClientTimeFormatHelper.FormatTimeDuration(this.timeRemaining);
            ClientTimersSystem.AddAction(1, this.UpdateText);
        }
示例#19
0
        private void RefreshByTimer()
        {
            if (this.IsDisposed)
            {
                return;
            }

            this.RefreshDepletion();
            ClientTimersSystem.AddAction(delaySeconds: 1,
                                         this.RefreshByTimer);
        }
示例#20
0
        private void RefreshEnergy()
        {
            if (this.IsDisposed ||
                !this.vehicle.ClientHasPrivateState)
            {
                return;
            }

            this.EnergyCurrent = VehicleEnergySystem.SharedCalculateTotalEnergyCharge(this.vehicle);
            ClientTimersSystem.AddAction(delaySeconds: 0.25, this.RefreshEnergy);
        }
        private void RefreshNextWateringInText()
        {
            if (this.IsDisposed)
            {
                return;
            }

            this.NotifyPropertyChanged(nameof(this.NextWateringInText));
            this.NotifyPropertyChanged(nameof(this.CanTryWateringNow));
            ClientTimersSystem.AddAction(delaySeconds: 1,
                                         this.RefreshNextWateringInText);
        }
示例#22
0
        private void Refresh()
        {
            if (this.IsDisposed)
            {
                return;
            }

            this.NotifyPropertyChanged(nameof(this.ElectricityProductionInfoText));

            ClientTimersSystem.AddAction(delaySeconds: 0.5,
                                         this.Refresh);
        }
示例#23
0
        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()))
            });

            var character = Api.Client.Characters.CurrentPlayerCharacter;

            if (character.ProtoCharacter is PlayerCharacterSpectator ||
                ServerOperatorSystem.SharedIsOperator(character) ||
                CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                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)
                ClientTimersSystem.AddAction(
                    delaySeconds: 0.1,
                    () =>
                {
                    if (this.ContextMenu == contextMenu)
                    {
                        this.ContextMenu = null;
                    }
                });
            }
        }
示例#24
0
        public ViewModelShieldProtectionControl(ILogicObject areasGroup)
        {
            this.areasGroup   = areasGroup;
            this.privateState = LandClaimAreasGroup.GetPrivateState(areasGroup);
            this.publicState  = LandClaimAreasGroup.GetPublicState(areasGroup);

            this.privateState.ClientSubscribe(
                _ => _.ShieldProtectionCurrentChargeElectricity,
                _ =>
            {
                this.NotifyPropertyChanged(nameof(this.ElectricityAmount));
                this.NotifyPropertyChanged(nameof(this.CanActivateShield));
                this.NotifyPropertyChanged(nameof(this.HasFullCharge));
                this.UpdateCurrentDurations();
            },
                this);

            this.privateState.ClientSubscribe(
                _ => _.ShieldProtectionCooldownExpirationTime,
                _ => this.RefreshState(),
                this);

            this.publicState.ClientSubscribe(
                _ => _.ShieldActivationTime,
                _ => this.RefreshState(),
                this);

            this.publicState.ClientSubscribe(
                _ => _.Status,
                _ => this.RefreshState(),
                this);

            this.RefreshState();

            this.IsLandClaimInsideAnotherBase = LandClaimShieldProtectionHelper.SharedIsLandClaimInsideAnotherBase(
                areasGroup);

            FactionSystem.ClientCurrentFactionAccessRightsChanged += this.CurrentFactionAccessRightsChangedHandler;

            UpdateCurrentDurationsEverySecond();

            void UpdateCurrentDurationsEverySecond()
            {
                if (this.IsDisposed)
                {
                    return;
                }

                this.UpdateCurrentDurations();
                ClientTimersSystem.AddAction(1, UpdateCurrentDurationsEverySecond);
            }
        }
示例#25
0
        private void Refresh()
        {
            if (this.IsDisposed ||
                !this.WorldObjectManufacturer.ClientHasPrivateState)
            {
                return;
            }

            this.NotifyPropertyChanged(nameof(this.ElectricityProductionInfoText));

            ClientTimersSystem.AddAction(delaySeconds: 0.5,
                                         this.Refresh);
        }
        private void TimerTickCallback()
        {
            if (IsClient)
            {
                ClientTimersSystem.AddAction(CheckTimeIntervalSeconds, this.TimerTickCallback);
            }

            RegisteredActions.ProcessAndRemove(
                // remove if cannot interact
                removeCondition: pair => !SharedIsValidInteraction(pair),
                // abort action when pair removed due to the interaction check failed
                removeCallback: pair => pair.Value.FinishAction?.Invoke(isAbort: true));
        }
        private void RefreshByTimer()
        {
            if (this.IsDisposed)
            {
                return;
            }

            this.RefreshIsSatisfied();
            this.NotifyPropertyChanged(nameof(this.DurationRemainsText));

            ClientTimersSystem.AddAction(delaySeconds: 1,
                                         this.RefreshByTimer);
        }
示例#28
0
        private void UpdateTimers()
        {
            if (this.IsDisposed)
            {
                return;
            }

            this.Refresh();

            // schedule next update
            ClientTimersSystem.AddAction(
                delaySeconds: 1,
                this.UpdateTimers);
        }
示例#29
0
        private void ActivateNextButtonAfterDelay()
        {
            this.IsButtonNextEnabled = false;
            var requestId = ++this.lastNextButtonEnableRequestId;

            ClientTimersSystem.AddAction(ButtonNextEnableDelay,
                                         () =>
            {
                if (requestId == this.lastNextButtonEnableRequestId)
                {
                    this.IsButtonNextEnabled = true;
                }
            });
        }
        private void FindAndAttackTarget( )
        {
            var fromPos = CurrentCharacter.Position + GetWeaponOffset();

            using var objectsNearby = this.CurrentCharacter.PhysicsBody.PhysicsSpace
                                      .TestCircle(position: fromPos,
                                                  radius: this.GetCurrentWeaponRange(),
                                                  collisionGroup: CollisionGroups.HitboxMelee);
            var objectOfInterest = objectsNearby.AsList()
                                   ?.Where(t => this.EnabledEntityList.Contains(t.PhysicsBody?.AssociatedWorldObject?.ProtoGameObject))
                                   .ToList();

            if (objectOfInterest == null || objectOfInterest.Count == 0)
            {
                return;
            }

            foreach (var obj in objectOfInterest)
            {
                var testWorldObject = obj.PhysicsBody.AssociatedWorldObject as IStaticWorldObject;
                var shape           = obj.PhysicsBody.Shapes.FirstOrDefault(s =>
                                                                            s.CollisionGroup == CollisionGroups.HitboxMelee);
                if (shape == null)
                {
                    Api.Logger.Error("Automaton: target object has no HitBoxMelee shape " + testWorldObject);
                    continue;
                }
                if (!this.AdditionalValidation(testWorldObject))
                {
                    continue;
                }
                var targetPoint = this.ShapeCenter(shape) + obj.PhysicsBody.Position;
                if (this.CheckForObstacles(testWorldObject, targetPoint))
                {
                    this.AttackTarget(testWorldObject, targetPoint);
                    this.attackInProgress = true;
                    ClientTimersSystem.AddAction(this.GetCurrentWeaponAttackDelay(), () =>
                    {
                        if (this.attackInProgress)
                        {
                            this.attackInProgress = false;
                            this.StopItemUse();
                            this.FindAndAttackTarget();
                        }
                    });
                    return;
                }
            }
        }