Beispiel #1
0
        private static double ServerGetLowestEquipmentDurabilityFraction(IEnumerable <IItem> items)
        {
            var lowestDurabilityFraction = 1.0;

            foreach (var item in items)
            {
                if (!(item.ProtoItem is IProtoItemEquipment protoItemEquipment))
                {
                    // not an equipment
                    continue;
                }

                switch (protoItemEquipment.EquipmentType)
                {
                case EquipmentType.FullBody:
                case EquipmentType.Head:
                case EquipmentType.Chest:
                case EquipmentType.Legs:
                    // consider these equipment item types for the durability check
                    break;

                default:
                    // don't consider implants, devices and other (future?) slots
                    continue;
                }

                var durabilityFraction = ItemDurabilitySystem.SharedGetDurabilityFraction(item);
                if (durabilityFraction < lowestDurabilityFraction)
                {
                    lowestDurabilityFraction = durabilityFraction;
                }
            }

            return(lowestDurabilityFraction);
        }
Beispiel #2
0
        protected override void ServerOnDegradeWeapon(
            ICharacter character,
            IItem weaponItem,
            IProtoItemWeapon protoWeapon,
            List <WeaponHitData> hitObjects)
        {
            if (hitObjects.Count == 0)
            {
                // no objects were hit
                return;
            }

            var decrease = this.DurabilityDecreasePerAction;

            foreach (var hit in hitObjects)
            {
                var protoObject = hit.WorldObject.ProtoWorldObject;
                if (protoObject is IProtoObjectWall ||
                    protoObject is IProtoObjectDoor ||
                    protoObject is IProtoObjectTradingStation)
                {
                    // hit wall, door or station
                    decrease *= 5;
                    break;
                }
            }

            ItemDurabilitySystem.ServerModifyDurability(
                weaponItem,
                delta: -decrease);
        }
        protected override void SharedOnActionCompletedInternal(WateringActionState state, ICharacter character)
        {
            var worldObject      = (IStaticWorldObject)state.TargetWorldObject;
            var protoPlant       = (IProtoObjectPlant)worldObject.ProtoWorldObject;
            var itemWateringCan  = state.ItemWateringCan;
            var protoWateringCan = (IProtoItemToolWateringCan)itemWateringCan.ProtoItem;

            if (IsServer)
            {
                protoPlant.ServerOnWatered(character,
                                           worldObject,
                                           wateringDuration: protoWateringCan.WateringDuration.TotalSeconds);
            }

            protoWateringCan.SharedOnWatered(itemWateringCan, worldObject);

            if (IsServer)
            {
                character.ServerAddSkillExperience <SkillFarming>(SkillFarming.ExperienceForWatering);

                // notify tool was used
                ServerItemUseObserver.NotifyItemUsed(character, itemWateringCan);

                // reduce watering can durability
                ItemDurabilitySystem.ServerModifyDurability(itemWateringCan, delta: -1);
            }
        }
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var item = data.GameObject;

            if (!(item.Container?.ProtoItemsContainer is ItemsContainerGeneratorSolar))
            {
                // the panel is not installed
                return;
            }

            var worldObjectGenerator = item.Container.OwnerAsStaticObject;

            if (worldObjectGenerator == null ||
                worldObjectGenerator.IsDestroyed)
            {
                return;
            }

            // The panel is installed.
            // Decrease durability proportionally to the generation rate
            // (degrade only during the daytime and only if active).
            var rate = ProtoObjectGeneratorSolar.SharedGetElectricityProductionRate(worldObjectGenerator);

            if (rate <= 0)
            {
                return;
            }

            var decrease = this.DurabilityDecreasePerMinuteWhenInstalled * (data.DeltaTime / 60.0);

            decrease *= rate;

            ItemDurabilitySystem.ServerModifyDurability(item,
                                                        delta: -(int)decrease);
        }
Beispiel #5
0
        protected override void ServerUpdate(ServerUpdateData data)
        {
            var publicState = data.PublicState;

            if (!publicState.IsActive)
            {
                return;
            }

            var item = data.GameObject;

            ItemDurabilitySystem.ServerModifyDurability(item,
                                                        -this.DurabilityDecreasePerSecond * data.DeltaTime,
                                                        roundUp: true);

            // check if item is in a hotbar selected slot, if not - make it not active
            var itemOwnerCharacter = item.Container?.OwnerAsCharacter;

            if (itemOwnerCharacter == null ||
                !itemOwnerCharacter.ServerIsOnline ||
                item != itemOwnerCharacter.SharedGetPlayerSelectedHotbarItem())
            {
                Logger.Info(item + " is not in the hotbar selected slot or player is offline - make it inactive");
                publicState.IsActive = false;
                return;
            }

            ServerItemUseObserver.NotifyItemUsed(itemOwnerCharacter, item);

            this.ItemFuelConfig.SharedTryConsumeFuel(item, data.PrivateState, data.DeltaTime, out var isFuelRanOut);
            if (isFuelRanOut)
            {
                publicState.IsActive = false;
            }
        }
Beispiel #6
0
        private void ServerRemote_OnActionCompletedInternal(IItem itemVehicleRemote, ICharacter character, Vector2D mousePosition)
        {
            if (!(itemVehicleRemote.ProtoItem is IProtoItemVehicleRemoteControl protoRemote))
            {
                return;
            }

            if (!CharacterEnergySystem.SharedHasEnergyCharge(character, protoRemote.EngeryUse))
            {
                return;
            }

            List <GarageVehicleEntry> list = VehicleGarageSystem.ServerGetCharacterVehicles(character, false);

            TakeVehicleResult result = TakeVehicleResult.Unknown;

            if (list.Count > 0)
            {
                var privateState = itemVehicleRemote.GetPrivateState <ItemVehicleRemoteControlPrivateState>();
                result = this.ServerTakeVehicle(privateState, character, mousePosition);
            }

            if (result == TakeVehicleResult.Success)
            {
                CharacterEnergySystem.ServerDeductEnergyCharge(character, protoRemote.EngeryUse);

                ItemDurabilitySystem.ServerModifyDurability(itemVehicleRemote, delta: -1);
            }
        }
        private static void ServerOnBatteryItemCharged(IItem item, double energyAdded)
        {
            if (energyAdded <= 0)
            {
                return;
            }

            var container = item.Container;

            // reduce durability proportionally to the added charge
            ItemDurabilitySystem.ServerModifyDurability(item, -(int)Math.Ceiling(energyAdded));

            if (!item.IsDestroyed)
            {
                return;
            }

            // item was destroyed during recharging
            var character = container?.OwnerAsCharacter;

            if (character == null ||
                character.SharedGetPlayerContainerEquipment() != container)
            {
                return;
            }

            // redistribute remaining energy to other energy bank devices
            var energyRemains = SharedGetPrivateState(item).EnergyCharge;

            ServerAddEnergyChargeInternal(character,
                                          energyRemains,
                                          invokeServerOnBatteryItemCharged: false);
        }
Beispiel #8
0
        private void ServerApplyItemsDecay(
            ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState,
            double deltaTime)
        {
            var activationProgress = reactorPrivateState.ActivationProgressPercents / 100.0;

            if (activationProgress <= 0)
            {
                reactorPrivateState.ServerAccumulatedDecayDuration = 0;
                return;
            }

            using var tempItemsList = Api.Shared.WrapInTempList(reactorPrivateState.ItemsContainer.Items);
            if (tempItemsList.Count == 0)
            {
                return;
            }

            reactorPrivateState.ServerAccumulatedDecayDuration += deltaTime;
            if (reactorPrivateState.ServerAccumulatedDecayDuration < ItemDecayIntervalDuration)
            {
                return;
            }

            // apply accumulated decay
            reactorPrivateState.ServerAccumulatedDecayDuration -= ItemDecayIntervalDuration;
            var decayMultiplier     = activationProgress * ItemDecayIntervalDuration;
            var fuelDecayMultiplier = 100.0 / reactorPrivateState.Stats.FuelLifetimePercent;

            foreach (var item in tempItemsList.AsList())
            {
                var protoGameObject = item.ProtoGameObject;
                switch (protoGameObject)
                {
                case ItemReactorFuelRod protoFuelRod:
                {
                    var decayAmount = decayMultiplier
                                      * protoFuelRod.DurabilityMax
                                      / protoFuelRod.LifetimeDuration;

                    decayAmount *= fuelDecayMultiplier;

                    ItemDurabilitySystem.ServerModifyDurability(item, -(int)decayAmount);
                    break;
                }

                case ProtoItemReactorModule protoItemModule:
                {
                    var decayAmount = decayMultiplier
                                      * protoItemModule.DurabilityMax
                                      / protoItemModule.LifetimeDuration;

                    ItemDurabilitySystem.ServerModifyDurability(item, -(int)decayAmount);
                    break;
                }
                }
            }
        }
        public static void ServerDespawnDrone(IDynamicWorldObject objectDrone, bool isReturnedToPlayer)
        {
            var privateState = objectDrone.GetPrivateState <DronePrivateState>();
            var publicState  = objectDrone.GetPublicState <DronePublicState>();

            publicState.ResetTargetPosition();

            if (privateState.IsDespawned)
            {
                return;
            }

            var droneItem      = privateState.AssociatedItem;
            var protoItemDrone = (IProtoItemDrone)droneItem.ProtoItem;
            var characterOwner = privateState.CharacterOwner;
            var world          = Server.World;

            var protoDrone = protoItemDrone.ProtoDrone;

            protoDrone.ServerOnDroneDroppedOrReturned(objectDrone, characterOwner, isReturnedToPlayer);

            // recreate physics (as despawned drone doesn't have any physics)
            privateState.IsDespawned = true;
            world.StopPhysicsBody(objectDrone.PhysicsBody);
            objectDrone.ProtoWorldObject.SharedCreatePhysics(objectDrone);
            world.SetPosition(objectDrone,
                              ServerCharacterDeathMechanic.ServerGetGraveyardPosition().ToVector2D());

            privateState.CharacterOwner = null;
            ServerOnDroneControlRemoved(characterOwner, objectDrone);

            var currentDurability = (int)(objectDrone.GetPublicState <DronePublicState>().StructurePointsCurrent
                                          / protoItemDrone.DurabilityToStructurePointsConversionCoefficient);

            if (currentDurability <= 1)
            {
                currentDurability = 0;
            }

            var deltaDurabilility = (int)(ItemDurabilitySystem.SharedGetDurabilityValue(droneItem)
                                          - currentDurability);

            if (deltaDurabilility <= 0)
            {
                return;
            }

            ItemDurabilitySystem.ServerModifyDurability(droneItem,
                                                        -deltaDurabilility);

            if (droneItem.IsDestroyed)
            {
                // drone item degraded to 100%, notify the player
                ItemDurabilitySystem.Instance.CallClient(characterOwner,
                                                         _ => _.ClientRemote_ItemBroke(droneItem.ProtoItem));
            }
        }
        private static void ServerOnEnergyUsed(IItem item, double energyAmountUsed)
        {
            if (energyAmountUsed <= 0)
            {
                return;
            }

            // reduce durability proportionally to the removed charge
            ItemDurabilitySystem.ServerModifyDurability(item, -(int)Math.Ceiling(energyAmountUsed));
        }
Beispiel #11
0
        private void SharedOnStageCompleted()
        {
            if (Api.IsServer)
            {
                // notify tool was used
                ServerItemUseObserver.NotifyItemUsed(this.Character, this.ItemVehicleRepairKit);

                // reduce tool durability
                ItemDurabilitySystem.ServerModifyDurability(this.ItemVehicleRepairKit, delta: -1);
            }
            else // if client
            {
                Api.Client.Audio.PlayOneShot(VehicleSystem.SoundResourceVehicleRepair);
            }

            this.currentStageDurationSeconds     = this.CalculateStageDurationSeconds(this.Character, isFirstStage: false);
            this.currentStageTimeRemainsSeconds += this.currentStageDurationSeconds;

            var currentStructurePoints = this.VehiclePublicState.StructurePointsCurrent;
            var newStructurePoints     = currentStructurePoints
                                         + this.stageStructureAddValue;

            if (Api.IsServer)
            {
                ((IProtoVehicle)this.Vehicle.ProtoGameObject)
                .ServerOnRepair(this.Vehicle, this.Character);
            }

            if (currentStructurePoints < this.structurePointsMax)
            {
                // repairing is still possible - more stages are available
                this.UpdateProgress();

                if (Api.IsServer &&
                    this.ItemVehicleRepairKit.IsDestroyed)
                {
                    // tool was destroyed (durability 0)
                    this.AbortAction();
                    return;
                }

                return;
            }

            // repairing is absolutely completed
            if (Api.IsServer)
            {
                // TODO: add skill experience for repair
                // this.CharacterPrivateState.Skills.ServerAddSkillExperience<SkillVehicles>(
                //     SkillVehicles.ExperienceAddWhenRepairFinished);
            }

            this.SetCompleted(isCancelled: false);
            VehicleRepairKitSystem.SharedActionCompleted(this.Character, this);
        }
        public override void ServerOnItemDamaged(IItem item, double damageApplied)
        {
            var owner = item.Container.OwnerAsCharacter;

            if (owner != null)
            {
                damageApplied *= owner.SharedGetFinalStatMultiplier(StatName.ImplantDegradationFromDamageMultiplier);
            }

            ItemDurabilitySystem.ServerModifyDurability(item, delta: -(int)damageApplied);
        }
Beispiel #13
0
        private void ServerRemote_RelocateStructure(IStaticWorldObject objectStructure, Vector2Ushort toPosition)
        {
            if (objectStructure.TilePosition == toPosition)
            {
                // relocation not required
                return;
            }

            var character = ServerRemoteContext.Character;

            if (!SharedValidateCanCharacterRelocateStructure(character,
                                                             objectStructure,
                                                             toPosition,
                                                             errorMessage: out _,
                                                             logErrors: true))
            {
                return;
            }

            var fromPosition = objectStructure.TilePosition;

            Api.SafeInvoke(
                () => ServerStructureBeforeRelocating?.Invoke(character, fromPosition, objectStructure));

            Server.World.SetPosition(objectStructure, toPosition);

            try
            {
                // ensure the structure is reinitialized (has its physics rebuilt, etc)
                objectStructure.ServerInitialize();
            }
            catch (Exception ex)
            {
                Logger.Exception(ex);
            }

            ConstructionPlacementSystem.Instance.ServerNotifyOnStructurePlacedOrRelocated(objectStructure, character);

            Api.SafeInvoke(
                () => ServerStructureRelocated?.Invoke(character, fromPosition, objectStructure));

            // let's deduct the tool durability
            if (CreativeModeSystem.SharedIsInCreativeMode(character))
            {
                return;
            }

            // the item in hotbar is definitely a construction tool as it was validated above
            var itemConstructionTool = character.SharedGetPlayerSelectedHotbarItem();

            ItemDurabilitySystem.ServerModifyDurability(
                itemConstructionTool,
                delta: -((IProtoObjectStructure)objectStructure.ProtoGameObject).RelocationToolDurabilityCost);
        }
Beispiel #14
0
 /// <summary>
 /// When the reactor completely shut downs, it will destroy all modules
 /// that have remaining durability below 1%.
 /// </summary>
 private static void ServerOnReactorShutdown(ObjectGeneratorPragmiumReactorPrivateState reactorPrivateState)
 {
     foreach (var item in reactorPrivateState.ItemsContainer.Items.ToList())
     {
         if (item.ProtoGameObject is ProtoItemReactorModule &&
             ItemDurabilitySystem.SharedGetDurabilityPercent(item) < 1)
         {
             ItemDurabilitySystem.ServerBreakItem(item);
         }
     }
 }
        public static double SharedCalculateResultDurabilityFraction(
            IItem inputItem1,
            IItem inputItem2,
            ICharacter character)
        {
            var result = ItemDurabilitySystem.SharedGetDurabilityPercent(inputItem1)
                         + ItemDurabilitySystem.SharedGetDurabilityPercent(inputItem2)
                         + SkillMaintenance.SharedGetCurrentBonusPercent(character);

            result = MathHelper.Clamp(result, 0, 100);
            return(result / 100.0);
        }
        private static void ServerOnEnergyUsed(IItem item, double energyAmountUsed)
        {
            if (energyAmountUsed <= 0)
            {
                return;
            }

            // reduce durability proportionally to the removed charge, durability as int is dropping to fast
            if (RandomHelper.Next(20) == 1)
            {
                ItemDurabilitySystem.ServerModifyDurability(item, -energyAmountUsed, true);
            }
        }
Beispiel #17
0
        private void Refresh()
        {
            if (this.IsDisposed)
            {
                return;
            }

            var character = ClientCurrentCharacterHelper.Character;
            if (ClientCurrentCharacterFinalStatsHelper.FinalStatsCache.IsDirty)
            {
                // refresh will be called again automatically when the new final stats cache is assigned
                return;
            }

            this.PercentSkillText = SkillMaintenance.SharedGetCurrentBonusPercent(character) + "%";

            var inputItem1 = this.containerInput.GetItemAtSlot(0);
            this.PercentInput1Text = GetDurabilityPercentText(inputItem1);

            var inputItem2 = this.containerInput.GetItemAtSlot(1);
            this.PercentInput2Text = GetDurabilityPercentText(inputItem2);

            var outputItem = this.containerOutput.GetItemAtSlot(0);
            if (outputItem != null)
            {
                this.PercentOutputText = string.Empty;
                return;
            }
            else
            {
                if (inputItem1 == null
                    || inputItem2 == null)
                {
                    this.PercentOutputText = "?";
                }
                else
                {
                    var resultPercent = ObjectTinkerTable.SharedCalculateResultDurabilityFraction(inputItem1,
                                                                                                  inputItem2,
                                                                                                  character);
                    this.PercentOutputText = (byte)(100 * resultPercent) + "%";
                }
            }

            string GetDurabilityPercentText(IItem item) =>
                item == null
                    ? string.Empty
                    : ItemDurabilitySystem.SharedGetDurabilityPercent(item) + "%";
        }
Beispiel #18
0
        private static bool SharedTryFindItemsOfType(
            IItemsContainerProvider containers,
            IProtoItem requiredProtoItem,
            uint count,
            out List <IItem> result,
            double minQualityFraction)
        {
            var countToFindRemains = (int)count;

            result = new List <IItem>();
            foreach (var container in containers.ItemsContainers)
            {
                foreach (var item in container.Items)
                {
                    if (item.ProtoItem != requiredProtoItem)
                    {
                        continue;
                    }

                    if (requiredProtoItem is IProtoItemWithDurability &&
                        ItemDurabilitySystem.SharedGetDurabilityFraction(item) < minQualityFraction)
                    {
                        // not enough durability
                        continue;
                    }

                    if (requiredProtoItem is IProtoItemWithFreshness &&
                        ItemFreshnessSystem.SharedGetFreshnessFraction(item) < minQualityFraction)
                    {
                        // not enough durability
                        continue;
                    }

                    result.Add(item);
                    countToFindRemains -= item.Count;
                    if (countToFindRemains <= 0)
                    {
                        break;
                    }
                }

                if (countToFindRemains <= 0)
                {
                    break;
                }
            }

            return(countToFindRemains <= 0);
        }
Beispiel #19
0
        public override void ServerOnCharacterDeath(IItem item, bool isEquipped, out bool shouldDrop)
        {
            // implants never drop on death
            shouldDrop = false;
            if (!isEquipped)
            {
                return;
            }

            // durability reduced on death
            var fraction        = MathHelper.Clamp(this.DurabilityFractionReduceOnDeath, 0, 1);
            var durabilityDelta = (ushort)(this.DurabilityMax * fraction);

            ItemDurabilitySystem.ServerModifyDurability(item, delta: -durabilityDelta);
        }
Beispiel #20
0
        public virtual void ServerOnCharacterDeath(IItem item, bool isEquipped, out bool shouldDrop)
        {
            shouldDrop = true;
            if (!isEquipped)
            {
                return;
            }

            if (item.ProtoItem is IProtoItemWithDurablity protoItemWithDurablity)
            {
                // -10% of durability reduced on death
                const double durabilityFractionReduceOnDeath = 0.1;
                var          durabilityDelta = (ushort)(protoItemWithDurablity.DurabilityMax * durabilityFractionReduceOnDeath);
                ItemDurabilitySystem.ServerModifyDurability(item, delta: -durabilityDelta);
            }
        }
        protected sealed override void ServerUpdate(ServerUpdateData data)
        {
            base.ServerUpdate(data);

            if (this.durabilityDecreasePerServerUpdate <= 0)
            {
                // non-degradeable
                return;
            }

            if (data.DeltaTime <= 0)
            {
                // not processed
                return;
            }

            // try to degrade durability over time and give experience for cybernetic affinity skill
            var item  = data.GameObject;
            var owner = item.Container?.OwnerAsCharacter;

            if (owner is null ||
                !owner.ServerIsOnline ||
                owner.SharedGetPlayerContainerEquipment() != item.Container)
            {
                // player offline or not an equipped item
                return;
            }

            if (CharacterIdleSystem.ServerIsIdlePlayer(owner))
            {
                return;
            }

            var durabilityDecrease = this.durabilityDecreasePerServerUpdate;

            durabilityDecrease *= owner.SharedGetFinalStatMultiplier(StatName.ImplantDegradationSpeedMultiplier);
            ItemDurabilitySystem.ServerModifyDurability(item, -durabilityDecrease, roundUp: false);

            owner.ServerAddSkillExperience <SkillCyberneticAffinity>(
                data.DeltaTime * SkillCyberneticAffinity.ExperienceAddedPerImplantPerSecond);

            if (!item.IsDestroyed)
            {
                this.ServerUpdateInstalledImplant(data);
            }
        }
Beispiel #22
0
        public virtual void ServerOnCharacterDeath(IItem item, bool isEquipped, out bool shouldDrop)
        {
            shouldDrop = true;
            if (!isEquipped)
            {
                return;
            }

            if (item.ProtoItem is IProtoItemWithDurablity protoItemWithDurablity)
            {
                // -10% of durability reduced on death
                var durabilityDelta = protoItemWithDurablity.DurabilityMax * DurabilityFractionReduceOnDeath;
                ItemDurabilitySystem.ServerModifyDurability(item,
                                                            delta: -durabilityDelta,
                                                            roundUp: false);
            }
        }
        public static IItem ClientSelectNextDrone(List <IItem> exceptItems)
        {
            IItem selectedItem      = null;
            var   selectedItemOrder = int.MinValue;
            var   privateState      = ClientCurrentCharacterHelper.PrivateState;

            // find a drone item with the highest order number
            foreach (var item in privateState.ContainerHotbar.Items)
            {
                if (IsValidDroneItem(item, out var order) &&
                    order >= selectedItemOrder)
                {
                    selectedItem      = item;
                    selectedItemOrder = order;
                }
            }

            foreach (var item in privateState.ContainerInventory.Items)
            {
                if (IsValidDroneItem(item, out var order) &&
                    order >= selectedItemOrder)
                {
                    selectedItem      = item;
                    selectedItemOrder = order;
                }
            }

            return(selectedItem);

            bool IsValidDroneItem(IItem item, out int order)
            {
                if (item.ProtoItem is IProtoItemDrone protoItemDrone &&
                    ItemDurabilitySystem.SharedGetDurabilityValue(item) > 0 &&
                    !exceptItems.Contains(item))
                {
                    order = protoItemDrone.SelectionOrder;
                    return(true);
                }

                order = int.MinValue;
                return(false);
            }
        }
Beispiel #24
0
        public virtual void ServerOnCharacterDeath(IItem item, bool isEquipped, out bool shouldDrop)
        {
            // only unequipped items will drop unless full loot system enabled
            shouldDrop = ItemConstants.ServerPvpIsFullLootEnabled ||
                         !isEquipped;

            if (!isEquipped)
            {
                return;
            }

            if (item.ProtoItem is IProtoItemWithDurability protoItemWithDurability)
            {
                // reduce equipped item's durability on death
                var durabilityDelta = protoItemWithDurability.DurabilityMax * DurabilityFractionReduceOnDeath;
                ItemDurabilitySystem.ServerModifyDurability(item,
                                                            delta: -durabilityDelta,
                                                            roundUp: false);
            }
        }
Beispiel #25
0
        private void ServerGatheringSystemGatherHandler(ICharacter character, IStaticWorldObject worldObject)
        {
            if (!(worldObject.ProtoStaticWorldObject is ObjectCorpse))
            {
                return;
            }

            // corpse looted
            var itemDevice = character.SharedGetPlayerContainerEquipment()
                             .GetItemsOfProto(this)
                             .FirstOrDefault();

            if (itemDevice == null)
            {
                // don't have an equipped device
                return;
            }

            ItemDurabilitySystem.ServerModifyDurability(itemDevice, -DurabilityDecreasePerUse);
        }
        public override void ServerOnCharacterDeath(IItem item, bool isEquipped, out bool shouldDrop)
        {
            if (!isEquipped)
            {
                // not installed implants always drop on death
                shouldDrop = true;
                return;
            }

            // installed implants never drop on death
            shouldDrop = false;

            // reduce implant's durability on death
            var fraction        = MathHelper.Clamp(this.DurabilityFractionReduceOnDeath, 0, 1);
            var durabilityDelta = this.DurabilityMax * fraction;

            ItemDurabilitySystem.ServerModifyDurability(item,
                                                        delta: -durabilityDelta,
                                                        roundUp: false);
        }
Beispiel #27
0
        private void TrySendDrone()
        {
            var targetsList =
                Api.Client.World.GetStaticWorldObjectsOfProto <IProtoStaticWorldObject>()
                .Where(IsValidObject)
                .OrderBy(o => CurrentCharacter.Position.DistanceTo(o.TilePosition.ToVector2D()))
                .ToList();

            if (targetsList.Count == 0)
            {
                return;
            }
            int targetN           = 0;
            int droneControlLimit = ((IProtoItemDroneControl)SelectedItem.ProtoGameObject).MaxDronesToControl;
            int droneNumberToSend = Math.Min(
                droneControlLimit - CurrentCharacter.SharedGetCurrentControlledDronesNumber(),
                targetsList.Count);

            using var tempExceptDrones = Api.Shared.GetTempList <IItem>();
            for (var index = 0; index < droneNumberToSend; index++)
            {
                IItem itemDrone;
                do
                {
                    itemDrone = CharacterDroneControlSystem.ClientSelectNextDrone(tempExceptDrones.AsList());
                    if (itemDrone is null)
                    {
                        return;
                    }
                    tempExceptDrones.Add(itemDrone);
                } while (ItemDurabilitySystem.SharedGetDurabilityFraction(itemDrone) < DroneDurabilityThreshold);

                if (!CharacterDroneControlSystem.ClientTryStartDrone(itemDrone,
                                                                     targetsList[targetN].TilePosition,
                                                                     showErrorNotification: false))
                {
                    return;
                }
                targetN++;
            }
        }
        // please note that requiredEnergyAmount is <= ushort.MaxValue
        private static bool ServerDeductEnergyChargeInternal(IDynamicWorldObject vehicle, uint requiredEnergyAmount)
        {
            if (requiredEnergyAmount <= 0)
            {
                return(true);
            }

            using var tempItemsList = SharedGetTempListFuelItemsForVehicle(vehicle);
            if (tempItemsList.Count == 0)
            {
                // there are no battery packs equipped
                return(false);
            }

            // deduct energy
            foreach (var item in tempItemsList.AsList())
            {
                var privateState = SharedGetPrivateState(item);
                var charge       = privateState.DurabilityCurrent;
                if (charge <= 0)
                {
                    // no charge there
                    continue;
                }

                if (charge >= requiredEnergyAmount)
                {
                    // there are more than enough charge available
                    ItemDurabilitySystem.ServerModifyDurability(item, -(int)requiredEnergyAmount);
                    return(true);
                }

                // use all the remaining charge in this item
                requiredEnergyAmount -= charge;
                ItemDurabilitySystem.ServerModifyDurability(item, -(int)charge);
            }

            // probably consumed but not enough energy (remaining requiredEnergyAmount > 0)
            return(false);
        }
Beispiel #29
0
        protected sealed override void ServerUpdate(ServerUpdateData data)
        {
            base.ServerUpdate(data);

            if (this.durabilityDecreasePerServerUpdate <= 0)
            {
                // non-degradeable
                return;
            }

            if (data.DeltaTime <= 0)
            {
                // not processed
                return;
            }

            // try to degrade durability over time
            var item  = data.GameObject;
            var owner = item.Container?.OwnerAsCharacter;

            if (owner == null ||
                !owner.IsOnline ||
                owner.SharedGetPlayerContainerEquipment() != item.Container)
            {
                // player offline or not an equipped item
                return;
            }

            var durabilityDecrease = this.durabilityDecreasePerServerUpdate;

            durabilityDecrease *= owner.SharedGetFinalStatMultiplier(StatName.ImplantDegradationSpeedMultiplier);
            ItemDurabilitySystem.ServerModifyDurability(item,
                                                        -(int)Math.Floor(durabilityDecrease));

            if (!item.IsDestroyed)
            {
                this.ServerUpdateInstalledImplant(data);
            }
        }
        private void CheckItemDurability([NotNull] IItem item)
        {
            double itemDurabilityFraction = ItemDurabilitySystem.SharedGetDurabilityFraction(item);

            if (IsUnequipEnabled &&
                itemDurabilityFraction <= UnequipThreshold)
            {
                if (TryToMoveItem(
                        item: item,
                        toContainer: CurrentCharacter.SharedGetPlayerContainerInventory()))
                {
                    if (item != null)
                    {
                        itemAlerts.Remove(item);
                    }
                    return;
                }
            }

            if (!itemAlerts.ContainsKey(item))
            {
                itemAlerts.Add(item, new AlertDetails());
            }

            if (IsAlertNotificationEnabled &&
                itemDurabilityFraction <= AlertThreshold &&
                (itemAlerts[item].Durability - itemDurabilityFraction >= AlertStep ||
                 (AlertTimeout > 0 &&
                  itemAlerts[item].Time + AlertTimeout < Api.Client.Core.ClientRealTime)))
            {
                itemAlerts[item].Durability = itemDurabilityFraction;
                itemAlerts[item].Time       = Api.Client.Core.ClientRealTime;

                NotificationSystem.ClientShowNotification(
                    title: "Item durability low!",
                    color: NotificationColor.Bad,
                    icon: item.ProtoItem.Icon);
            }
        }