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