Example #1
0
        public override bool Pick(Character picker)
        {
            //return if someone is already trying to pick the item
            if (pickTimer > 0.0f)
            {
                return(false);
            }
            if (picker == null || picker.Inventory == null)
            {
                return(false);
            }

            if (PickingTime > 0.0f)
            {
                var abilityPickingTime = new AbilityValueItem(PickingTime, item.Prefab);
                picker.CheckTalents(AbilityEffectType.OnItemPicked, abilityPickingTime);

                if ((picker.PickingItem == null || picker.PickingItem == item) && PickingTime <= float.MaxValue)
                {
#if SERVER
                    // Set active picker before creating the server event to make sure it's set correctly
                    activePicker = picker;
                    item.CreateServerEvent(this);
#endif
                    pickingCoroutine = CoroutineManager.StartCoroutine(WaitForPick(picker, abilityPickingTime.Value));
                }
                return(false);
            }
            else
            {
                return(OnPicked(picker));
            }
        }
Example #2
0
        public override void Update(float deltaTime, Camera cam)
        {
            var availableIngredients = GetAvailableIngredients();

            if (fabricatedItem == null || !CanBeFabricated(fabricatedItem, availableIngredients, user))
            {
                CancelFabricating();
                return;
            }

            progressState = fabricatedItem == null ? 0.0f : (requiredTime - timeUntilReady) / requiredTime;

            if (GameMain.NetworkMember?.IsClient ?? false)
            {
                hasPower = State != FabricatorState.Paused;
                if (!hasPower)
                {
                    return;
                }
            }
            else
            {
                hasPower = Voltage >= MinVoltage;

                if (!hasPower)
                {
                    State = FabricatorState.Paused;
                    return;
                }
                State = FabricatorState.Active;
            }

            var repairable = item.GetComponent <Repairable>();

            if (repairable != null)
            {
                repairable.LastActiveTime = (float)Timing.TotalTime + 10.0f;
            }

            ApplyStatusEffects(ActionType.OnActive, deltaTime, null);

            if (powerConsumption <= 0)
            {
                Voltage = 1.0f;
            }

            float tinkeringStrength = 0f;

            if (repairable.IsTinkering)
            {
                tinkeringStrength = repairable.TinkeringStrength;
            }
            float fabricationSpeedIncrease = 1f + tinkeringStrength * TinkeringSpeedIncrease;

            timeUntilReady -= deltaTime * fabricationSpeedIncrease * Math.Min(Voltage, 1.0f);

            UpdateRequiredTimeProjSpecific();

            if (timeUntilReady > 0.0f)
            {
                return;
            }

            if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
            {
                fabricatedItem.RequiredItems.ForEach(requiredItem => {
                    for (int usedPrefabsAmount = 0; usedPrefabsAmount < requiredItem.Amount; usedPrefabsAmount++)
                    {
                        foreach (ItemPrefab requiredPrefab in requiredItem.ItemPrefabs)
                        {
                            if (!availableIngredients.ContainsKey(requiredPrefab.Identifier))
                            {
                                continue;
                            }

                            var availablePrefabs = availableIngredients[requiredPrefab.Identifier];
                            var availablePrefab  = availablePrefabs.FirstOrDefault(potentialPrefab =>
                            {
                                return(potentialPrefab.ConditionPercentage >= requiredItem.MinCondition * 100.0f &&
                                       potentialPrefab.ConditionPercentage <= requiredItem.MaxCondition * 100.0f);
                            });

                            if (availablePrefab == null)
                            {
                                continue;
                            }

                            if (requiredItem.UseCondition && availablePrefab.ConditionPercentage - requiredItem.MinCondition * 100 > 0.0f) //Leave it behind with reduced condition if it has enough to stay above 0
                            {
                                availablePrefab.Condition -= availablePrefab.Prefab.Health * requiredItem.MinCondition;
                                continue;
                            }

                            availablePrefabs.Remove(availablePrefab);
                            Entity.Spawner.AddToRemoveQueue(availablePrefab);
                            inputContainer.Inventory.RemoveItem(availablePrefab);
                        }
                    }
                });

                int amountFittingContainer = outputContainer.Inventory.HowManyCanBePut(fabricatedItem.TargetItem, fabricatedItem.OutCondition * fabricatedItem.TargetItem.Health);

                var fabricationValueItem = new AbilityValueItem(fabricatedItem.Amount, fabricatedItem.TargetItem);

                int quality = 0;
                if (user?.Info != null)
                {
                    foreach (Character character in Character.CharacterList.Where(c => c.TeamID == user.TeamID))
                    {
                        character.CheckTalents(AbilityEffectType.OnAllyItemFabricatedAmount, fabricationValueItem);
                    }
                    user.CheckTalents(AbilityEffectType.OnItemFabricatedAmount, fabricationValueItem);

                    quality = GetFabricatedItemQuality(fabricatedItem, user);
                }

                var tempUser = user;
                for (int i = 0; i < (int)fabricationValueItem.Value; i++)
                {
                    float outCondition = fabricatedItem.OutCondition;
                    if (i < amountFittingContainer)
                    {
                        Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * outCondition, quality,
                                                       onSpawned: (Item spawnedItem) =>
                        {
                            onItemSpawned(spawnedItem, tempUser);
                            //reset the condition in case the max condition is higher than the prefab's due to e.g. quality modifiers
                            spawnedItem.Condition = spawnedItem.MaxCondition * outCondition;
                        });
                    }
                    else
                    {
                        Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * outCondition, quality,
                                                       onSpawned: (Item spawnedItem) =>
                        {
                            onItemSpawned(spawnedItem, tempUser);
                            //reset the condition in case the max condition is higher than the prefab's due to e.g. quality modifiers
                            spawnedItem.Condition = spawnedItem.MaxCondition * outCondition;
                        });
                    }
                }
Example #3
0
        private void ProcessItem(Item targetItem, IEnumerable <Item> inputItems, List <DeconstructItem> validDeconstructItems, bool allowRemove = true)
        {
            // In multiplayer, the server handles the deconstruction into new items
            if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient)
            {
                return;
            }

            if (user != null && !user.Removed)
            {
                var abilityTargetItem = new AbilityItem(targetItem);
                user.CheckTalents(AbilityEffectType.OnItemDeconstructed, abilityTargetItem);
            }

            if (targetItem.Prefab.RandomDeconstructionOutput)
            {
                int        amount = targetItem.Prefab.RandomDeconstructionOutputAmount;
                List <int> deconstructItemIndexes = new List <int>();
                for (int i = 0; i < validDeconstructItems.Count; i++)
                {
                    deconstructItemIndexes.Add(i);
                }
                List <float>           commonness = validDeconstructItems.Select(i => i.Commonness).ToList();
                List <DeconstructItem> products   = new List <DeconstructItem>();

                for (int i = 0; i < amount; i++)
                {
                    if (deconstructItemIndexes.Count < 1)
                    {
                        break;
                    }
                    var itemIndex = ToolBox.SelectWeightedRandom(deconstructItemIndexes, commonness, Rand.RandSync.Unsynced);
                    products.Add(validDeconstructItems[itemIndex]);
                    var removeIndex = deconstructItemIndexes.IndexOf(itemIndex);
                    deconstructItemIndexes.RemoveAt(removeIndex);
                    commonness.RemoveAt(removeIndex);
                }

                foreach (DeconstructItem deconstructProduct in products)
                {
                    CreateDeconstructProduct(deconstructProduct, inputItems);
                }
            }
            else
            {
                foreach (DeconstructItem deconstructProduct in validDeconstructItems)
                {
                    CreateDeconstructProduct(deconstructProduct, inputItems);
                }
            }

            void CreateDeconstructProduct(DeconstructItem deconstructProduct, IEnumerable <Item> inputItems)
            {
                float percentageHealth = targetItem.Condition / targetItem.MaxCondition;

                if (percentageHealth < deconstructProduct.MinCondition || percentageHealth > deconstructProduct.MaxCondition)
                {
                    return;
                }

                if (!(MapEntityPrefab.Find(null, deconstructProduct.ItemIdentifier) is ItemPrefab itemPrefab))
                {
                    DebugConsole.ThrowError("Tried to deconstruct item \"" + targetItem.Name + "\" but couldn't find item prefab \"" + deconstructProduct.ItemIdentifier + "\"!");
                    return;
                }

                float condition = deconstructProduct.CopyCondition ?
                                  percentageHealth * itemPrefab.Health :
                                  itemPrefab.Health * Rand.Range(deconstructProduct.OutConditionMin, deconstructProduct.OutConditionMax);

                if (DeconstructItemsSimultaneously && deconstructProduct.RequiredOtherItem.Length > 0)
                {
                    foreach (Item otherItem in inputItems)
                    {
                        if (targetItem == otherItem)
                        {
                            continue;
                        }
                        if (deconstructProduct.RequiredOtherItem.Any(r => otherItem.HasTag(r) || r.Equals(otherItem.Prefab.Identifier, StringComparison.OrdinalIgnoreCase)))
                        {
                            user.CheckTalents(AbilityEffectType.OnGeneticMaterialCombinedOrRefined);
                            foreach (Character character in Character.GetFriendlyCrew(user))
                            {
                                character.CheckTalents(AbilityEffectType.OnCrewGeneticMaterialCombinedOrRefined);
                            }

                            var geneticMaterial1 = targetItem.GetComponent <GeneticMaterial>();
                            var geneticMaterial2 = otherItem.GetComponent <GeneticMaterial>();
                            if (geneticMaterial1 != null && geneticMaterial2 != null)
                            {
                                if (geneticMaterial1.Combine(geneticMaterial2, user))
                                {
                                    inputContainer.Inventory.RemoveItem(otherItem);
                                    OutputContainer.Inventory.RemoveItem(otherItem);
                                    Entity.Spawner.AddToRemoveQueue(otherItem);
                                }
                                allowRemove = false;
                                return;
                            }
                            inputContainer.Inventory.RemoveItem(otherItem);
                            OutputContainer.Inventory.RemoveItem(otherItem);
                            Entity.Spawner.AddToRemoveQueue(otherItem);
                        }
                    }
                }

                int amount = 1;

                if (user != null && !user.Removed)
                {
                    var itemsCreated = new AbilityValueItem(amount, targetItem.Prefab);
                    user.CheckTalents(AbilityEffectType.OnItemDeconstructedMaterial, itemsCreated);
                    amount = (int)itemsCreated.Value;

                    // used to spawn items directly into the deconstructor
                    var itemContainer = new AbilityItemPrefabItem(item, targetItem.Prefab);
                    user.CheckTalents(AbilityEffectType.OnItemDeconstructedInventory, itemContainer);
                }

                for (int i = 0; i < amount; i++)
                {
                    Entity.Spawner.AddToSpawnQueue(itemPrefab, outputContainer.Inventory, condition, onSpawned: (Item spawnedItem) =>
                    {
                        for (int i = 0; i < outputContainer.Capacity; i++)
                        {
                            var containedItem = outputContainer.Inventory.GetItemAt(i);
                            if (containedItem?.Combine(spawnedItem, null) ?? false)
                            {
                                break;
                            }
                        }
                        PutItemsToLinkedContainer();
                    });
                }
            }

            if (targetItem.AllowDeconstruct && allowRemove)
            {
                //drop all items that are inside the deconstructed item
                foreach (ItemContainer ic in targetItem.GetComponents <ItemContainer>())
                {
                    if (ic?.Inventory == null || ic.RemoveContainedItemsOnDeconstruct)
                    {
                        continue;
                    }
                    ic.Inventory.AllItemsMod.ForEach(containedItem => outputContainer.Inventory.TryPutItem(containedItem, user: null));
                }
                inputContainer.Inventory.RemoveItem(targetItem);
                Entity.Spawner.AddToRemoveQueue(targetItem);
                MoveInputQueue();
                PutItemsToLinkedContainer();
            }
            else
            {
                if (!outputContainer.Inventory.CanBePut(targetItem) || (Entity.Spawner?.IsInRemoveQueue(targetItem) ?? false))
                {
                    targetItem.Drop(dropper: null);
                }
                else
                {
                    outputContainer.Inventory.TryPutItem(targetItem, user: null, createNetworkEvent: true);
                }
            }
        }