Inheritance: MonoBehaviour
    public bool RemoveItem(Pickupable item)
    {
        int index = -1;

        for(int i = 0; i < _inventory.Count; i ++)
        {
            if (_inventory[i].objectName == item.objectName)
            {
                index = i;
                break;
            }
        }

        if (index == -1)
            return false;

        _inventory.RemoveAt(index);
        GameObject.Find("Inventory Slot " + (index + 1).ToString()).transform.FindChild("Image").GetComponent<Image>().sprite = new Sprite();
        for (int i = index; i < _inventory.Count; i ++)
        {
            GameObject.Find("Inventory Slot " + (i + 1).ToString()).transform.FindChild("Image").GetComponent<Image>().sprite = GameObject.Find("Inventory Slot " + (i + 2).ToString()).transform.FindChild("Image").GetComponent<Image>().sprite;
        }
        GameObject.Find("Inventory Slot " + (_inventory.Count + 1).ToString()).transform.FindChild("Image").GetComponent<Image>().sprite = new Sprite();

        return true;
    }
    void Update()
    {
        int i = -1;

        if (Input.GetKeyDown(KeyCode.Alpha1))
            i = 0;
        else if (Input.GetKeyDown(KeyCode.Alpha2))
            i = 1;
        else if (Input.GetKeyDown(KeyCode.Alpha3))
            i = 2;
        else if (Input.GetKeyDown(KeyCode.Alpha4))
            i = 3;

        if (i != -1 && _inventory.Count >= i + 1)
        {
            if (usingItem && i != selectedIndex || !usingItem)
            {
                StopUse();
                usingItem = true;
                currentSelection = _inventory[i];
                selectedIndex = i;
                GameObject.Find("Inventory Slot " + (i + 1).ToString()).GetComponent<Image>().color = Color.yellow;
                Interaction.OutputMessage(currentSelection.description);
            }
            else
                StopUse();
        }
    }
Beispiel #3
0
	private void TryPlace(){

		Collider[] colliders;
		colliders = Physics.OverlapBox(this.transform.position + (player.GetDirection() * 1f), new Vector3(0.4f, 0.4f, 0.4f), Quaternion.identity, mask);
		PlaceLocation placeLocation = null;
		float closestDistance = float.MaxValue;

		foreach (Collider collider in colliders){
		    float distance = Vector3.Distance(transform.position, collider.transform.position);
			if (distance < closestDistance && collider.GetComponent<PlaceLocation>() != null) {
				closestDistance=distance;
				placeLocation = collider.GetComponent<PlaceLocation>();
			}
		}

		if (placeLocation != null){
			if (placeLocation.TryPlace(pickedUpObject)){
				GameObject.Destroy(pickedUpObject.gameObject);
				pickedUpObject = null;
			}
		}

		if (placeLocation == null && colliders.Length == 0){
			pickedUpObject.transform.parent = null;
			pickedUpObject.transform.position = this.transform.position + (player.GetDirection()  * 1f);
			pickedUpObject = null;
		}
	}
Beispiel #4
0
    public void GrabObbject(Pickupable pickupable)
    {
        pickupable.OnGrabbed();

        _State.JustPickedUp = true;
        _State.PickupInHand = pickupable;
        _State.PickupInHandTrans = pickupable.Trans;

        pickupable.Body.isKinematic = true;

        var oldParent = _State.PickupInHandTrans.parent;
        _State.PickupInHandTrans.parent = Trans;

        _State.PickupInHandTrans.localPosition = -pickupable.ControllerMountingPos.localPosition;
        _State.PickupInHandTrans.localRotation = Quaternion.Inverse(pickupable.ControllerMountingPos.localRotation);

        var vec = pickupable.ControllerMountingPos.position - pickupable.Trans.position;
        _State.PickupInHandTrans.localPosition = -Trans.InverseTransformVector(vec);

        _State.HoldPosOffset = _State.PickupInHandTrans.localPosition;
        _State.HoldRotOffset = _State.PickupInHandTrans.rotation;
        _State.ParentStartRot = Trans.rotation;

        _State.PickupInHandTrans.parent = oldParent;
    }
Beispiel #5
0
	public bool TryPlace(Pickupable pickupable){
		if (Pickups[nextInLine] == pickupable){
			spriteRenderer.material = Materials[nextInLine];
			nextInLine++;
			if (nextInLine == Pickups.Length){
				if (OnSequenceComplete != null){
					OnSequenceComplete();
				}
			}
			return true;
		}
		return false;
	}
    public bool AddItem(Pickupable itemToAdd)
    {
        if (_inventory.Count >= 4)
            return false;
        
        _inventory.Add(itemToAdd);

        GameObject.Find("Inventory Slot " + _inventory.Count.ToString()).transform.FindChild("Image").GetComponent<Image>().sprite = Resources.Load<Sprite>(itemToAdd.iconPath);

        if (itemToAdd.objectName == "Stick")
            GameObject.Find("Player Head").GetComponent<Interaction>().AdvanceTutorial(2);

        return true;
    }
Beispiel #7
0
    public void GrabObbject(Pickupable pickupable, bool gotObjectByGrab, Transform objParent)
    {
        pickupable.OnGrabbed();

        _State.JustPickedUp = true;
        _State.PickupInHand = pickupable;
        _State.PickupInHandBody = pickupable.Body;
        _State.PickupInHandTrans = pickupable.Trans;
        _State.PickupInHandOldTrans = objParent;

        _State.PickupInHandBody.isKinematic = true;
        _State.PickupInHandTrans.parent = Trans;

        _State.PickupInHandTrans.localPosition = -pickupable.ControllerMountingPos.localPosition;
        _State.PickupInHandTrans.localRotation = Quaternion.Inverse(pickupable.ControllerMountingPos.localRotation);

        var vec = pickupable.ControllerMountingPos.position - pickupable.Trans.position;
        _State.PickupInHandTrans.localPosition = -Trans.InverseTransformVector(vec);
    }
Beispiel #8
0
	private bool GetPickupable(out Pickupable pickupable){
		Collider[] colliders = Physics.OverlapSphere(this.transform.position, 1.5f);
		float closestDistance = float.MaxValue;
		Pickupable closestPickupable = null;

		foreach (Collider collider in colliders){
		    float distance = Vector3.Distance(transform.position, collider.transform.position);
			if (distance < closestDistance && collider.GetComponent<Pickupable>() != null) {
				closestDistance=distance;
				closestPickupable = collider.GetComponent<Pickupable>();
			}
		}

		if (closestPickupable == null){
			pickupable = null;
			return false;
		}
		pickupable = closestPickupable;
		return true;
	}
Beispiel #9
0
    private bool TryUseItem(Pickupable item, Entity target)
    {
        OutputMessage(target.UseItem(item));

        sceneHandler.GetComponent<InventoryHandler>().StopUse();
        return false;
    }
Beispiel #10
0
 /// <summary>
 /// Returns the best slot (according to BestSlotForTrait) that is capable of holding
 /// this item (or any arbitrary slot if none of the best slots are capable of holding it).
 /// Returns null if there is no slot in this storage that can fit the item.
 /// Works for indexed and named slots both.
 /// </summary>
 /// <param name="toCheck"></param>
 /// <returns></returns>
 public ItemSlot GetBestSlotFor(Pickupable toCheck)
 {
     return(BestSlotForTrait.Instance.GetBestSlot(toCheck, this, false));
 }
        public override void Process(PlayerHeldItemChanged packet)
        {
            Optional <RemotePlayer> opPlayer = playerManager.Find(packet.PlayerId);

            Validate.IsPresent(opPlayer);

            Optional <GameObject> opItem = NitroxEntity.GetObjectFrom(packet.ItemId);

            Validate.IsPresent(opItem);

            Pickupable pickupable = opItem.Value.GetComponent <Pickupable>();

            Validate.IsTrue(pickupable);

            InventoryItem inventoryItem = (InventoryItem)inventoryItemFromPickupable.GetValue(pickupable);

            Validate.NotNull(inventoryItem);

            ItemsContainer inventory = opPlayer.Value.Inventory;
            PlayerTool     tool      = opItem.Value.GetComponent <PlayerTool>();

            // Copied from QuickSlots
            switch (packet.Type)
            {
            case PlayerHeldItemChanged.ChangeType.DRAW_AS_TOOL:
                Validate.IsTrue(tool);
                ModelPlug.PlugIntoSocket(tool, opPlayer.Value.ItemAttachPoint);
                Utils.SetLayerRecursively(opItem.Value, viewModelLayer);
                foreach (Animator componentsInChild in tool.GetComponentsInChildren <Animator>())
                {
                    componentsInChild.cullingMode = AnimatorCullingMode.AlwaysAnimate;
                }
                if (tool.mainCollider)
                {
                    tool.mainCollider.enabled = false;
                }
                tool.GetComponent <Rigidbody>().isKinematic = true;
                opItem.Value.SetActive(true);
                setHandIK.Invoke(tool, new object[] { true });
                SafeAnimator.SetBool(opPlayer.Value.ArmsController.GetComponent <Animator>(), $"holding_{tool.animToolName}", true);
                opPlayer.Value.AnimationController["using_tool_first"] = packet.IsFirstTime == null;

                if (opItem.Value.TryGetComponent(out FPModel fpModelDraw))     //FPModel needs to be updated
                {
                    fpModelDraw.OnEquip(null, null);
                }
                break;

            case PlayerHeldItemChanged.ChangeType.HOLSTER_AS_TOOL:
                Validate.IsTrue(tool);
                opItem.Value.SetActive(false);
                Utils.SetLayerRecursively(opItem.Value, defaultLayer);
                if (tool.mainCollider)
                {
                    tool.mainCollider.enabled = true;
                }
                tool.GetComponent <Rigidbody>().isKinematic = false;
                inventoryItem.item.Reparent(inventory.tr);
                foreach (Animator componentsInChild in tool.GetComponentsInChildren <Animator>())
                {
                    componentsInChild.cullingMode = AnimatorCullingMode.CullUpdateTransforms;
                }
                SafeAnimator.SetBool(opPlayer.Value.ArmsController.GetComponent <Animator>(), $"holding_{tool.animToolName}", false);
                opPlayer.Value.AnimationController["using_tool_first"] = false;

                if (opItem.Value.TryGetComponent(out FPModel fpModelHolster))     //FPModel needs to be updated
                {
                    fpModelHolster.OnUnequip(null, null);
                }

                break;

            case PlayerHeldItemChanged.ChangeType.DRAW_AS_ITEM:
                inventoryItem.item.Reparent(opPlayer.Value.ItemAttachPoint);
                inventoryItem.item.SetVisible(true);
                Utils.SetLayerRecursively(inventoryItem.item.gameObject, viewModelLayer);
                break;

            case PlayerHeldItemChanged.ChangeType.HOLSTER_AS_ITEM:
                inventoryItem.item.Reparent(inventory.tr);
                inventoryItem.item.SetVisible(false);
                Utils.SetLayerRecursively(inventoryItem.item.gameObject, defaultLayer);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Beispiel #12
0
        /// <summary>
        /// Attempts to move the pickupable to a position better suited for accessibility. If
        /// the pickupable is not inside a solid (and thus does not need moving), nothing
        /// happens.
        /// </summary>
        /// <param name="material">The pickupable to move.</param>
        private static void MovePreferredPosition(Pickupable material)
        {
            int cell = Grid.PosToCell(material);
            var inst = CleanDropManager.Instance;
            var obj  = material.gameObject;
            LastUsedDirection direction;

            if (inst != null && Grid.IsValidCell(cell) && (direction = inst[cell]) !=
                LastUsedDirection.None && obj.GetSMI <DeathMonitor.Instance>()?.IsDead() !=
                false && ((Grid.Solid[cell] && Grid.Foundation[cell]) || Grid.Properties[
                              cell] != 0))
            {
                var tryFirst = ListPool <int, CleanDropManager> .Allocate();

#if DEBUG
                Grid.CellToXY(cell, out int x, out int y);
                PUtil.LogDebug("Item {0} in cell ({1:D}, {2:D}) last direction = {2}".F(
                                   material.PrimaryElement.Element.name, x, y, direction));
#endif
                // Direction based on workable cell; default direction is U D R L
                switch (direction)
                {
                case LastUsedDirection.Down:
                    tryFirst.Add(Grid.CellBelow(cell));
                    tryFirst.Add(Grid.CellDownRight(cell));
                    tryFirst.Add(Grid.CellDownLeft(cell));
                    break;

                case LastUsedDirection.DownLeft:
                    tryFirst.Add(Grid.CellDownLeft(cell));
                    tryFirst.Add(Grid.CellBelow(cell));
                    tryFirst.Add(Grid.CellLeft(cell));
                    break;

                case LastUsedDirection.DownRight:
                    tryFirst.Add(Grid.CellDownRight(cell));
                    tryFirst.Add(Grid.CellBelow(cell));
                    tryFirst.Add(Grid.CellRight(cell));
                    break;

                case LastUsedDirection.Left:
                    tryFirst.Add(Grid.CellLeft(cell));
                    tryFirst.Add(Grid.CellUpLeft(cell));
                    tryFirst.Add(Grid.CellDownLeft(cell));
                    break;

                case LastUsedDirection.Right:
                    tryFirst.Add(Grid.CellRight(cell));
                    tryFirst.Add(Grid.CellUpRight(cell));
                    tryFirst.Add(Grid.CellDownRight(cell));
                    break;

                case LastUsedDirection.Up:
                    tryFirst.Add(Grid.CellAbove(cell));
                    tryFirst.Add(Grid.CellUpRight(cell));
                    tryFirst.Add(Grid.CellUpLeft(cell));
                    break;

                case LastUsedDirection.UpLeft:
                    tryFirst.Add(Grid.CellUpLeft(cell));
                    tryFirst.Add(Grid.CellAbove(cell));
                    tryFirst.Add(Grid.CellLeft(cell));
                    break;

                case LastUsedDirection.UpRight:
                    tryFirst.Add(Grid.CellUpRight(cell));
                    tryFirst.Add(Grid.CellAbove(cell));
                    tryFirst.Add(Grid.CellRight(cell));
                    break;

                default:
                    break;
                }
                foreach (int tryCell in tryFirst)
                {
                    if (Grid.IsValidCell(tryCell) && !Grid.Solid[tryCell])
                    {
                        var position = Grid.CellToPosCBC(tryCell, Grid.SceneLayer.Move);
                        var collider = obj.GetComponent <KCollider2D>();
                        // Adjust for material's bounding box
                        if (collider != null)
                        {
                            position.y += obj.transform.GetPosition().y - collider.bounds.min.y;
                        }
                        obj.transform.SetPosition(position);
                        // Make the pickupable start falling if not a dupe/critter
                        if (obj.GetComponent <Health>() == null)
                        {
                            if (GameComps.Fallers.Has(obj))
                            {
                                GameComps.Fallers.Remove(obj);
                            }
                            GameComps.Fallers.Add(obj, Vector2.zero);
                        }
                        break;
                    }
                }
                // Do not reset the direction to None since multiple items could drop from
                // one workable
                tryFirst.Recycle();
            }
        }
Beispiel #13
0
 private bool CheckCombinedTotal(Pickupable item, bool verbose)
 {
     return(this.Count < MaxChargers);
 }
        public void ManagedUpdate()
        {
            if (timeLastDrilled + 0.5f > Time.time)
            {
                drillable.modelRoot.transform.position = transform.position + new Vector3(Mathf.Sin(Time.time * 60f), Mathf.Cos(Time.time * 58f + 0.5f), Mathf.Cos(Time.time * 64f + 2f)) * 0.011f;
            }
            if (lootPinataObjects.Count > 0 && helper != null)
            {
                List <GameObject> list = new List <GameObject>();

                foreach (GameObject gameObject in lootPinataObjects)
                {
                    if (gameObject == null)
                    {
                        list.Add(gameObject);
                    }
                    else
                    {
                        Vector3 b = helper.MainCab.transform.position + new Vector3(0f, 0.8f, 0f);

                        gameObject.transform.position = Vector3.Lerp(gameObject.transform.position, b, Time.deltaTime * 5f);

                        float num = Vector3.Distance(gameObject.transform.position, b);

                        if (num < 3f)
                        {
                            Pickupable pickupable = gameObject.GetComponentInChildren <Pickupable>();

                            if (pickupable)
                            {
                                if (!helper.HasRoomForItem(pickupable))
                                {
                                    if (helper.IsPiloted())
                                    {
                                        ErrorMessage.AddMessage(Language.main.Get("ContainerCantFit"));
                                    }
                                }
                                else
                                {
                                    string arg = Language.main.Get(pickupable.GetTechName());
                                    ErrorMessage.AddMessage(Language.main.GetFormat("VehicleAddedToStorage", arg));
                                    uGUI_IconNotifier.main.Play(pickupable.GetTechType(), uGUI_IconNotifier.AnimationType.From, null);
                                    pickupable.Initialize();
                                    InventoryItem item = new InventoryItem(pickupable);
                                    helper.GetRoomForItem(pickupable).UnsafeAdd(item);
                                    pickupable.PlayPickupSound();
                                }
                                list.Add(gameObject);
                            }
                        }
                    }
                }

                if (list.Count > 0)
                {
                    foreach (GameObject item2 in list)
                    {
                        lootPinataObjects.Remove(item2);
                    }
                }
            }
        }
        public bool IsEntombed()
        {
            Pickupable component = GetComponent <Pickupable>();

            return((Object)component != (Object)null && component.IsEntombed);
        }
Beispiel #16
0
 private void Awake()
 {
     pickupable = GetComponent <Pickupable>();
     fireSource = GetComponent <FireSource>();
 }
Beispiel #17
0
 public bool IsAllowedToAdd(Pickupable pickupable, bool verbose)
 {
     return(true);
 }
        public void Begin(Precondition.Context context)
        {
            base.sm.fetcher.Set(context.consumerState.gameObject, base.smi);
            chores.Clear();
            chores.Add(rootChore);
            Grid.CellToXY(Grid.PosToCell(rootChore.destination.transform.GetPosition()), out int x, out int y);
            ListPool <Precondition.Context, FetchAreaChore> .PooledList pooledList = ListPool <Precondition.Context, FetchAreaChore> .Allocate();

            ListPool <Precondition.Context, FetchAreaChore> .PooledList pooledList2 = ListPool <Precondition.Context, FetchAreaChore> .Allocate();

            if (rootChore.allowMultifetch)
            {
                GatherNearbyFetchChores(rootChore, context, x, y, 3, pooledList, pooledList2);
            }
            float      num        = Mathf.Max(1f, Db.Get().Attributes.CarryAmount.Lookup(context.consumerState.consumer).GetTotalValue());
            Pickupable pickupable = context.data as Pickupable;

            if ((UnityEngine.Object)pickupable == (UnityEngine.Object)null)
            {
                Debug.Assert(pooledList.Count > 0, "succeeded_contexts was empty");
                Precondition.Context context2   = pooledList[0];
                FetchChore           fetchChore = (FetchChore)context2.chore;
                Debug.Assert(fetchChore != null, "fetch_chore was null");
                DebugUtil.LogWarningArgs("Missing root_fetchable for FetchAreaChore", fetchChore.destination, fetchChore.tags[0]);
                pickupable = fetchChore.FindFetchTarget(context.consumerState);
            }
            Debug.Assert((UnityEngine.Object)pickupable != (UnityEngine.Object)null, "root_fetchable was null");
            List <Pickupable> list = new List <Pickupable>();

            list.Add(pickupable);
            float num2          = pickupable.UnreservedAmount;
            float minTakeAmount = pickupable.MinTakeAmount;
            int   x2            = 0;
            int   y2            = 0;

            Grid.CellToXY(Grid.PosToCell(pickupable.transform.GetPosition()), out x2, out y2);
            int num3 = 6;

            x2 -= num3 / 2;
            y2 -= num3 / 2;
            ListPool <ScenePartitionerEntry, FetchAreaChore> .PooledList pooledList3 = ListPool <ScenePartitionerEntry, FetchAreaChore> .Allocate();

            GameScenePartitioner.Instance.GatherEntries(x2, y2, num3, num3, GameScenePartitioner.Instance.pickupablesLayer, pooledList3);
            Tag prefabTag = pickupable.GetComponent <KPrefabID>().PrefabTag;

            for (int i = 0; i < pooledList3.Count; i++)
            {
                ScenePartitionerEntry scenePartitionerEntry = pooledList3[i];
                if (num2 > num)
                {
                    break;
                }
                Pickupable pickupable2 = scenePartitionerEntry.obj as Pickupable;
                KPrefabID  component   = pickupable2.GetComponent <KPrefabID>();
                if (!(component.PrefabTag != prefabTag) && !(pickupable2.UnreservedAmount <= 0f))
                {
                    component.UpdateTagBits();
                    if (component.HasAllTags_AssumeLaundered(ref rootChore.requiredTagBits) && !component.HasAnyTags_AssumeLaundered(ref rootChore.forbiddenTagBits) && !list.Contains(pickupable2) && rootContext.consumerState.consumer.CanReach(pickupable2))
                    {
                        float unreservedAmount = pickupable2.UnreservedAmount;
                        list.Add(pickupable2);
                        num2 += unreservedAmount;
                        if (list.Count >= 10)
                        {
                            break;
                        }
                    }
                }
            }
            pooledList3.Recycle();
            num2 = Mathf.Min(num, num2);
            if (minTakeAmount > 0f)
            {
                num2 -= num2 % minTakeAmount;
            }
            deliveries.Clear();
            float num4 = Mathf.Min(rootChore.originalAmount, num2);

            if (minTakeAmount > 0f)
            {
                num4 -= num4 % minTakeAmount;
            }
            deliveries.Add(new Delivery(rootContext, num4, OnFetchChoreCancelled));
            float num5 = num4;

            for (int j = 0; j < pooledList.Count; j++)
            {
                if (num5 >= num2)
                {
                    break;
                }
                Precondition.Context context3    = pooledList[j];
                FetchChore           fetchChore2 = context3.chore as FetchChore;
                if (fetchChore2 != rootChore && context3.IsSuccess() && (UnityEngine.Object)fetchChore2.overrideTarget == (UnityEngine.Object)null && (UnityEngine.Object)fetchChore2.driver == (UnityEngine.Object)null && fetchChore2.tagBits.AreEqual(ref rootChore.tagBits))
                {
                    num4 = Mathf.Min(fetchChore2.originalAmount, num2 - num5);
                    if (minTakeAmount > 0f)
                    {
                        num4 -= num4 % minTakeAmount;
                    }
                    chores.Add(fetchChore2);
                    deliveries.Add(new Delivery(context3, num4, OnFetchChoreCancelled));
                    num5 += num4;
                    if (deliveries.Count >= 10)
                    {
                        break;
                    }
                }
            }
            num5 = Mathf.Min(num5, num2);
            float num6 = num5;

            fetchables.Clear();
            for (int k = 0; k < list.Count; k++)
            {
                if (num6 <= 0f)
                {
                    break;
                }
                Pickupable pickupable3 = list[k];
                num6 -= pickupable3.UnreservedAmount;
                fetchables.Add(pickupable3);
            }
            fetchAmountRequested = num5;
            reservations.Clear();
            pooledList.Recycle();
            pooledList2.Recycle();
        }
Beispiel #19
0
        protected override void ConduitTick(float delta)
        {
            UpdateConduitBlockedStatus();
            bool dispensed = false;

            if (!operational.IsOperational && !AlwaysDispense)
            {
                return;
            }
            //Could this have been testing to see how to make water pickupable?
            //foreach (GameObject item in storage.items)
            //{
            //    if (item.GetComponent<PrimaryElement>()?.Element.id == SimHashes.Water)
            //    {
            //        item.AddOrGet<Pickupable>();
            //    }
            //}
            PrimaryElement element = FindSuitableElement();

            if (element != null)
            {
                element.KeepZeroMassObject = true;
                IConduitFlow iConduitManager = GetConduitManager();
                if (iConduitManager == null)
                {
                    Debug.LogError($"[MultiIO] OutputPort.ConduitTick(): Could not retrieve IConduitFlow");
                }
                //Solid Conduits do not use the same kind of flow manager, so the code must be separated
                if (ConduitType == ConduitType.Solid)
                {
                    SolidConduitFlow solidManager = iConduitManager as SolidConduitFlow;
                    if (solidManager == null)
                    {
                        Debug.LogError($"[MultiIO] OutputPort.ConduitTick(): solidManager is null");
                    }
                    //Solid conveyor only needs to take elements with a Pikcupable component. The only difference between Water and Bottled Water is a Pikcupable component.
                    Pickupable pickup = element.gameObject.GetComponent <Pickupable>();
                    if (pickup == null)
                    {
                        return;
                    }
                    if (pickup.PrimaryElement.Mass > SolidOutputMax)
                    {
                        pickup = pickup.Take(SolidOutputMax);
                    }
                    solidManager.AddPickupable(portCell, pickup);
                    dispensed = true;
                }
                else if (ConduitType == ConduitType.Liquid || ConduitType == ConduitType.Gas)
                {
                    ConduitFlow conduitManager = iConduitManager as ConduitFlow;
                    if (conduitManager == null)
                    {
                        Debug.LogError($"[MutiIO] OutputPort.ConduitTick(): conduitManager is null");
                        return;
                    }
                    float amountMoved = conduitManager.AddElement(portCell, element.ElementID, element.Mass, element.Temperature, element.DiseaseIdx, element.DiseaseCount);
                    if (amountMoved > 0f)
                    {
                        float movedRatio   = amountMoved / element.Mass;
                        int   movedDisease = (int)(movedRatio * (float)element.DiseaseCount);
                        element.ModifyDiseaseCount(-movedDisease, "ConduitDispenser.ConduitUpdate");
                        element.Mass -= amountMoved;
                        _parent.Trigger((int)GameHashes.OnStorageChange, element.gameObject);
                        dispensed = true;
                    }
                }
            }
            isDispensing = dispensed;
        }
Beispiel #20
0
        internal static bool Prefix(Equipment __instance, string slot, Pickupable pickupable, bool verbose, ref bool __result)
        {
            TechType techTypeInSlot = pickupable.GetTechType();

            bool isExtendedSeamothSlot = SlotHelper.IsExtendedSeamothSlot(slot);

            if (isExtendedSeamothSlot && techTypeInSlot == TechType.SeamothTorpedoModule)
            {
                // Do not allow torpedo modules in extended slots in Seamoth
                __result = false;
                ErrorMessage.AddDebug("Slot Extender:\nTorpedo module not allowed for this slot!");
                return(false);
            }

            if (techTypeInSlot == TechType.VehicleStorageModule)
            {
                if (__instance.owner.GetComponent <Exosuit>())
                {
                    // Do not allow more than four storage modules in Exosuit slots
                    if (__instance.GetCount(TechType.VehicleStorageModule) >= 4)
                    {
                        __result = false;
                        ErrorMessage.AddDebug("Slot Extender:\nStorage module limit reached!");
                        return(false);
                    }
                }
                else if (SEConfig.STORAGE_SLOTS_OFFSET == 0)
                {
                    if (!isExtendedSeamothSlot)
                    {
                        return(true);
                    }

                    // Do not allow storage modules in extended slots in Seamoth
                    __result = false;
                    ErrorMessage.AddDebug("Slot Extender:\nStorage module not allowed for this slot!");
                    return(false);
                }
                else if (__instance.owner.GetComponent <SeaMoth>() is SeaMoth seamoth)
                {
                    int slotID = int.Parse(slot.Substring(13)) - 1;

                    if (slotID > 3 && (slotID < SEConfig.STORAGE_SLOTS_OFFSET || slotID > SEConfig.STORAGE_SLOTS_OFFSET + 3))
                    {
                        ErrorMessage.AddDebug("Slot Extender:\nStorage module not allowed for this slot!");
                        return(false);
                    }

                    // HACK: trying to swap one storage to another while drag, silently refusing because of ui problems
                    if (seamoth.GetSlotItem(slotID)?.item.GetTechType() == TechType.VehicleStorageModule)
                    {
                        __result = false;
                        return(false);
                    }

                    SeamothStorageInput storageInput = seamoth.storageInputs[slotID % SEConfig.STORAGE_SLOTS_OFFSET];
                    var fieldState = AccessTools.Field(typeof(SeamothStorageInput), "state");
                    __result = !(bool)fieldState.GetValue(storageInput); //already active

                    if (!__result && verbose)
                    {
                        int _slotID = (slotID < 4? slotID + SEConfig.STORAGE_SLOTS_OFFSET: slotID - SEConfig.STORAGE_SLOTS_OFFSET) + 1;
                        ErrorMessage.AddDebug($"Slot Extender:\nStorage module is already in the slot {_slotID}");
                    }

                    return(false);
                }
            }

            return(true);
        }
Beispiel #21
0
 public bool AllowedToRemove(SubRoot cyclops, Pickupable item, bool verbose)
 {
     return(true);
 }
Beispiel #22
0
        public static void SetDefaultPlaceTool(GameObject gameObj, Collider mainCollider = null, Pickupable pickupable = null,
                                               bool onCeiling = false, bool onWalls = false, bool onBase = false, bool alignWithSurface = false)
        {
            if (gameObj == null)
            {
                return;
            }

            if (gameObj.GetComponent <CustomPlaceToolController>() == null)
            {
                gameObj.AddComponent <CustomPlaceToolController>();
            }

            PlaceTool placeTool = gameObj.GetComponent <GenericPlaceTool>();

            if (placeTool == null)
            {
                placeTool = gameObj.GetComponent <PlaceTool>();
            }
            if (placeTool == null)
            {
                placeTool = gameObj.AddComponent <GenericPlaceTool>();
            }

            placeTool.allowedInBase          = true;
            placeTool.allowedOnBase          = onBase;
            placeTool.allowedOnCeiling       = onCeiling;
            placeTool.allowedOnConstructable = true;
            placeTool.allowedOnGround        = true;
            placeTool.allowedOnRigidBody     = true;
            placeTool.allowedOnWalls         = onWalls;
            placeTool.allowedOutside         = ConfigSwitcher.AllowPlaceOutside;
#if BELOWZERO
            placeTool.allowedUnderwater = true;
#endif
            placeTool.reloadMode           = PlayerTool.ReloadMode.None;
            placeTool.socket               = PlayerTool.Socket.RightHand;
            placeTool.rotationEnabled      = true;
            placeTool.hasAnimations        = false;
            placeTool.hasBashAnimation     = false;
            placeTool.hasFirstUseAnimation = false;
            // Try get collider
            if (mainCollider == null)
            {
                mainCollider = gameObj.GetComponent <Collider>();
            }
            if (mainCollider == null)
            {
                mainCollider = gameObj.GetComponentInChildren <Collider>();
            }
            // Associate collider
            if (mainCollider != null)
            {
                placeTool.mainCollider = mainCollider;
            }
            // Try get pickupable
            if (pickupable == null)
            {
                pickupable = gameObj.GetComponent <Pickupable>();
            }
            // Associate pickupable
            placeTool.pickupable    = pickupable;
            placeTool.drawTime      = 0.5f;
            placeTool.dropTime      = 1f;
            placeTool.holsterTime   = 0.35f;
            placeTool.bleederDamage = 3f;
#if BELOWZERO
            placeTool.spikeyTrapDamage = 1f;
#endif
            placeTool.ikAimLeftArm             = false;
            placeTool.ikAimRightArm            = false;
            placeTool.useLeftAimTargetOnPlayer = false;
            placeTool.alignWithSurface         = alignWithSurface;
            placeTool.hideInvalidGhostModel    = false;
            placeTool.hideFlags    = HideFlags.None;
            placeTool.useGUILayout = true;
            placeTool.enabled      = true;
        }
 private static bool AllowTorpedoRemoval(Pickupable pickupable, bool verbose)
 {
     return(true);
 }
Beispiel #24
0
 /// <summary>
 /// Update these slot contents in response to message from server, firing appropriate
 /// hooks.
 /// </summary>
 /// <param name="newContents"></param>
 public void ClientUpdate(Pickupable newContents)
 {
     item = newContents;
     OnSlotContentsChangeClient.Invoke();
 }
Beispiel #25
0
        private static void DetectDataObjectTypeAndPerformConversion(ObjectData data, Pickupable pickup)
        {
            switch (data.DataObjectType)
            {
            case SaveDataObjectType.PlayerTool:

                if (data.PlayToolData.HasBattery)
                {
                    var batteryTechType = data.PlayToolData.BatteryInfo.TechType;
                    var tempBattery     = CraftData.GetPrefabForTechType(batteryTechType);
                    var capacity        = tempBattery?.gameObject.GetComponent <IBattery>()?.capacity;

                    if (data.PlayToolData.HasBattery && capacity != null && capacity > 0)
                    {
                        var energyMixin      = pickup.gameObject.GetComponent <EnergyMixin>();
                        var normalizedCharge = data.PlayToolData.BatteryInfo.BatteryCharge / capacity;
                        if (energyMixin.GetBattery() != null)
                        {
                            QuickLogger.Debug("Battery was already in device destroying");
                        }

                        if (!energyMixin.compatibleBatteries.Contains(batteryTechType))
                        {
                            energyMixin.compatibleBatteries.Add(batteryTechType);
                        }

                        energyMixin.SetBattery(data.PlayToolData.BatteryInfo.TechType,
                                               (float)normalizedCharge);
                    }
                    else
                    {
                        QuickLogger.Error <DSSServerController>(
                            "While trying to get the batter capacity of the battery it returned null or 0.");
                    }
                }

                break;


            case SaveDataObjectType.Eatable:
                //We are not handling decaying items so I dont need to set anything
                break;

            case SaveDataObjectType.Server:
                var server = pickup.gameObject.GetComponent <DSSServerController>();
                server.FCSFilteredStorage.Items = new HashSet <ObjectData>(data.ServerData);
                server.Initialize();
                server.DisplayManager.UpdateDisplay();
                break;

            case SaveDataObjectType.Battery:
                var battery = pickup.gameObject.GetComponent <Battery>();
                battery.charge = data.PlayToolData.BatteryInfo.BatteryCharge;
                break;
            }
        }
Beispiel #26
0
    /// <summary>
    /// Checks if the indicated item can fit in this slot.
    /// </summary>
    /// <param name="toStore"></param>
    /// <param name="ignoreOccupied">if true, does not check if an item is already in the slot</param>
    /// <param name="examineRecipient">if not null, when validation fails, will output an appropriate examine message to this recipient</param>
    /// <returns></returns>
    public bool CanFit(Pickupable toStore, bool ignoreOccupied = false, GameObject examineRecipient = null)
    {
        if (toStore == null)
        {
            return(false);
        }

        ItemStorage       storageToCheck  = itemStorage;
        StorageIdentifier storeIdentifier = toStore.GetComponent <StorageIdentifier>();

        //Check if there is a deny entry for this toStore item
        if (storageToCheck != null && storeIdentifier != null)
        {
            InteractableStorage interactiveStorage = storageToCheck.GetComponent <InteractableStorage>();
            if (interactiveStorage != null)
            {
                if (interactiveStorage.denyStorageOfStorageItems.HasFlag(storeIdentifier.StorageItemName))
                {
                    if (examineRecipient)
                    {
                        Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} can't be placed there!");
                    }
                    return(false);
                }
            }
        }

        //go through this slot's ancestors and make sure none of them ARE toStore,
        //as that would create a loop in the inventory hierarchy
        int count = 0;

        while (storageToCheck != null)
        {
            if (storageToCheck.gameObject == toStore.gameObject)
            {
                Logger.LogTraceFormat(
                    "Cannot fit {0} in slot {1}, this would create an inventory hierarchy loop (putting the" +
                    " storage inside itself)", Category.Inventory, toStore, ToString());
                if (examineRecipient)
                {
                    Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} can't go inside itself!");
                }
                return(false);
            }
            //get parent item storage if it exists
            var pickupable = storageToCheck.GetComponent <Pickupable>();
            if (pickupable != null && pickupable.ItemSlot != null)
            {
                storageToCheck = pickupable.ItemSlot.ItemStorage;
            }
            else
            {
                storageToCheck = null;
            }

            count++;
            if (count > 5)
            {
                Logger.LogTraceFormat(
                    "Something went wrong when adding {0} in slot {1}, aborting!", Category.Inventory, toStore, ToString());
                return(false);
            }
        }

        //if the slot already has an item, it's allowed to stack only if the item to add can stack with
        //the existing item.
        if (!ignoreOccupied && item != null)
        {
            var thisStackable  = item.GetComponent <Stackable>();
            var otherStackable = toStore.GetComponent <Stackable>();
            var stackResult    = thisStackable != null && otherStackable != null &&
                                 thisStackable.CanAccommodate(otherStackable);
            if (!stackResult)
            {
                Logger.LogTraceFormat(
                    "Cannot stack {0} in slot {1}", Category.Inventory, toStore, ToString());
            }
            else
            {
                Logger.LogTraceFormat(
                    "Can stack {0} in slot {1}", Category.Inventory, toStore, ToString());
            }
            return(stackResult);
        }

        //no item in slot and no inventory loop created,
        //check if this storage can fit this according to its specific capacity logic
        var canFit = itemStorage.ItemStorageCapacity.CanFit(toStore, this.slotIdentifier);

        if (canFit)
        {
            return(true);
        }
        if (examineRecipient)
        {
            //if this is going in a player's inventory, use a more appropriate message.
            var targetPlayerScript = ItemStorage.GetComponent <PlayerScript>();
            if (targetPlayerScript != null)
            {
                //going into a top-level inventory slot of a player
                Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} can't go in that slot.");
            }
            else
            {
                //going into something else
                Chat.AddExamineMsg(examineRecipient, $"{toStore.gameObject.ExpensiveName()} doesn't fit in the {ItemStorage.gameObject.ExpensiveName()}.");
            }
        }

        return(false);
    }
Beispiel #27
0
 public static void Postfix(Pickupable __instance, Vector3 dropPosition)
 {
     NitroxServiceLocator.LocateService <Item>().Dropped(__instance.gameObject, __instance.GetTechType(), dropPosition);
 }
Beispiel #28
0
    /// <summary>
    /// Checks if the player can currently put the indicated item into a free slot in this storage. Correctly handles logic for client / server side, so is
    /// recommended to use in WillInteract rather than other ways of checking fit.
    /// </summary>
    /// <param name="player">player to check</param>
    /// <param name="storage">storage to check</param>
    /// <param name="toCheck">item to check for fit</param>
    /// <param name="side">network side check is happening on</param>
    /// <param name="ignoreOccupied">if true, does not check if an item is already in the slot</param>
    /// <param name="examineRecipient">if not null, when validation fails, will output an appropriate examine message to this recipient</param>
    /// <returns></returns>
    public static bool CanPutItemToStorage(PlayerScript playerScript, ItemStorage storage, Pickupable toCheck,
                                           NetworkSide side, bool ignoreOccupied = false, GameObject examineRecipient = null)
    {
        var freeSlot = storage.GetBestSlotFor(toCheck);

        if (freeSlot == null)
        {
            return(false);
        }
        return(CanPutItemToSlot(playerScript, freeSlot, toCheck, side, ignoreOccupied, examineRecipient));
    }
Beispiel #29
0
    // Token: 0x06000006 RID: 6 RVA: 0x0000250C File Offset: 0x0000070C
    public override Object LoadResource()
    {
        bool flag = this.Resource == null;

        if (flag)
        {
            GameObject gameObject = Resources.Load <GameObject>("WorldEntities/Eggs/JellyrayEgg");
            Debug.Log("hhhh " + (AssetBundle.LoadedBundle == null).ToString());
            GameObject          gameObject2         = AssetBundleLoader.LoadedBundle.LoadAsset("Capsule") as GameObject;
            SkinnedMeshRenderer componentInChildren = gameObject.GetComponentInChildren <SkinnedMeshRenderer>();
            gameObject2.name = "GhostRayBlueEgg";
            PrefabIdentifier prefabIdentifier = gameObject2.AddComponent <PrefabIdentifier>();
            gameObject2.AddComponent <LargeWorldEntity>().cellLevel = LargeWorldEntity.CellLevel.Near;
            prefabIdentifier.ClassId = this.Key;
            Rigidbody component = gameObject2.GetComponent <Rigidbody>();
            component.isKinematic = true;
            Pickupable  pickupable  = gameObject2.AddComponent <Pickupable>();
            CreatureEgg creatureEgg = gameObject2.AddComponent <CreatureEgg>();
            creatureEgg.daysBeforeHatching = 1.5f;
            gameObject2.AddComponent <EntityTag>().slotType = EntitySlot.Type.Small;
            WorldForces worldForces = gameObject2.AddComponent <WorldForces>();
            worldForces.handleGravity     = true;
            worldForces.underwaterGravity = 2f;
            worldForces.useRigidbody      = component;
            worldForces.aboveWaterGravity = 9.81f;
            worldForces.underwaterDrag    = 1f;
            worldForces.aboveWaterDrag    = 0.1f;
            worldForces.handleDrag        = true;
            SkyApplier   skyApplier = gameObject2.AddComponent <SkyApplier>();
            MeshRenderer component2 = gameObject2.GetComponent <MeshRenderer>();
            skyApplier.renderers = new Renderer[]
            {
                component2
            };
            skyApplier.anchorSky = Skies.Auto;
            Texture mainTexture  = component2.sharedMaterial.mainTexture;
            Texture mainTexture2 = component2.material.mainTexture;
            component2.material.shader       = componentInChildren.material.shader;
            component2.material.color        = new Color(0f, 0.490196079f, 0.490196079f);
            component2.sharedMaterial.shader = componentInChildren.sharedMaterial.shader;
            component2.material.SetFloat("_SpecInt", 16f);
            component2.material.SetFloat("_Shininess", 7.5f);
            component2.material.SetTexture("_SpecText", mainTexture2);
            LiveMixin liveMixin = gameObject2.AddComponent <LiveMixin>();
            liveMixin.data = ScriptableObject.CreateInstance <LiveMixinData>();
            LiveMixinData data = liveMixin.data;
            liveMixin.health      = 25f;
            data.maxHealth        = 25f;
            data.knifeable        = true;
            data.destroyOnDeath   = true;
            data.explodeOnDestroy = true;
            ResourceTracker resourceTracker = gameObject2.AddComponent <ResourceTracker>();
            resourceTracker.overrideTechType = TechType.GenericEgg;
            resourceTracker.prefabIdentifier = prefabIdentifier;
            resourceTracker.rb          = component;
            resourceTracker.pickupable  = pickupable;
            creatureEgg.overrideEggType = (TechType)9998;
            Animator animator = gameObject2.AddComponent <Animator>();
            creatureEgg.animator         = animator;
            creatureEgg.hatchingCreature = TechType.GhostRayBlue;
            gameObject2.AddComponent <ScaleFixer>().scale = new Vector3(0.5f, 0.5f, 0.5f);
            this.Resource = gameObject2;
        }
        return(this.Resource);
    }
Beispiel #30
0
 /// <summary>
 /// Checks if the player can currently put the indicated item in this slot. Correctly handles logic for client / server side, so is
 /// recommended to use in WillInteract rather than other ways of checking fit.
 /// </summary>
 /// <param name="player">player performing the interaction</param>
 /// <param name="itemSlot">slot to check</param>
 /// <param name="toCheck">item to check for fit</param>
 /// <param name="side">network side check is happening on</param>
 /// <param name="ignoreOccupied">if true, does not check if an item is already in the slot</param>
 /// <param name="examineRecipient">if not null, when validation fails, will output an appropriate examine message to this recipient</param>
 /// <returns></returns>
 public static bool CanPutItemToSlot(PlayerScript playerScript, ItemSlot itemSlot, Pickupable toCheck, NetworkSide side,
                                     bool ignoreOccupied = false, GameObject examineRecipient = null)
 {
     if (toCheck == null || itemSlot.Item != null)
     {
         Logger.LogTrace("Cannot put item to slot because the item or slot are null", Category.Inventory);
         return(false);
     }
     if (!CanInteract(playerScript.gameObject, side, true))
     {
         Logger.LogTrace("Cannot put item to slot because the player cannot interact", Category.Inventory);
         return(false);
     }
     if (!CanFit(itemSlot, toCheck, side, ignoreOccupied, examineRecipient))
     {
         Logger.LogTraceFormat("Cannot put item to slot because the item {0} doesn't fit in the slot {1}", Category.Inventory,
                               toCheck.name, itemSlot);
         return(false);
     }
     return(true);
 }
Beispiel #31
0
 public override string UseItem(Pickupable item)
 {
     if(objectName == "Campfire" && item.objectName == "Stick")
     {
         GameObject.Find("Scene Handler").GetComponent<InventoryHandler>().RemoveItem(item);
         GameObject.Find("Scene Handler").GetComponent<InventoryHandler>().AddItem(GameObject.Find("Torch Pickupable").GetComponent<Pickupable>());
         GameObject.Find("Player Head").GetComponent<Interaction>().AdvanceTutorial(3);
         return "You light the torch on the campfire!";
     }
     else if (objectName == "Door" && item.objectName == "Key")
     {
         transform.Translate(0, 100, 0);
         isInteractable = false;
         locked = false;
         GameObject.Find("Scene Handler").GetComponent<InventoryHandler>().RemoveItem(item);
         return "You open the door with the key!";
         Destroy(gameObject);
     }
     else if (objectName == "Bin" && item.objectName.Contains("Potion"))
     {
         GameObject.Find("Scene Handler").GetComponent<InventoryHandler>().RemoveItem(item);
         return "You throw away the potion.";
     }
     else if (objectName == "Bin" && item.objectName.Contains("Vial"))
     {
         GameObject.Find("Scene Handler").GetComponent<InventoryHandler>().RemoveItem(item);
         return "You throw away the vial.";
     }
     else if (objectName == "Bin")
     {
         return "You don't want to throw this away...";
     }
     else if(objectName == "Red Pedestal" && item.objectName == "Red Orb")
     {
         redOrb.SetActive(true);
         if (GameObject.Find("Blue Orb") != null && GameObject.Find("Red Orb") != null)
         {
             purplePort.SetActive(true);
         }
         GameObject.Find("Scene Handler").GetComponent<InventoryHandler>().RemoveItem(item);
         GameObject.Find("Player Head").GetComponent<Interaction>().redOrbDown = true;
         return "You place the orb on the pedestal";
     }
     else if (objectName == "Blue Pedestal" && item.objectName == "Blue Orb")
     {
         blueOrb.SetActive(true);
         if (GameObject.Find("Blue Orb") != null && GameObject.Find("Red Orb") != null)
         {
             purplePort.SetActive(true);
         }
         GameObject.Find("Scene Handler").GetComponent<InventoryHandler>().RemoveItem(item);
         GameObject.Find("Player Head").GetComponent<Interaction>().blueOrbDown = true;
         return "You place the orb on the pedestal";
     }
     else if (objectName == "Mould" && item.objectName.Contains("Potion"))
     {
         if (mixerContents.Count < 2)
         {
             GameObject.Find("Scene Handler").GetComponent<InventoryHandler>().RemoveItem(item);
             mixerContents.Add(item.objectName);
             GetComponent<AudioSource>().clip = mixPotion;
             GetComponent<AudioSource>().Play();
             return "You pour the potion into the mould.";
         }
         else if (mixerContents.Count == 2)
         {
             GameObject.Find("Scene Handler").GetComponent<InventoryHandler>().RemoveItem(item);
             mixerContents.Add(item.objectName);
             GetComponent<AudioSource>().clip = mixPotion;
             GetComponent<AudioSource>().Play();
             if (mixerContents[0] == "Red Potion" && mixerContents[1] == "Green Potion" && mixerContents[2] == "Blue Potion")
             {
                 key.SetActive(true);
                 gameObject.SetActive(false);
                 return "You pour the potion into the mould. It hardens into a key.";
             }
             else
             {
                 return "The mould is now full, but it isn't hardening.";
             }
         }
         else if (mixerContents.Count == 2)
         {
             return "The mould is full, you cannot add any more potions.";
         }
     }
     return "Nothing Happens...";
 }
Beispiel #32
0
 public void OnInventorySlotSet(Pickupable prevItem, Pickupable newItem)
 {
     //If we have any actions stored, invoke em. (Health V2)
     ServerInventoryItemSlotSet?.Invoke(prevItem, newItem);
 }
Beispiel #33
0
 protected override void Awake()
 {
     base.Awake();
     pickupable       = GetComponent <Pickupable>();
     itemAttributesV2 = GetComponent <ItemAttributesV2>();
 }
Beispiel #34
0
 public virtual string UseItem(Pickupable item)
 {
     return "Nothing Happens";
 }
Beispiel #35
0
 private void Awake()
 {
     spriteRenderer = GetComponentInChildren <SpriteRenderer>();
     pickupable     = GetComponent <Pickupable>();
     itemAttributes = GetComponent <ItemAttributesV2>();
 }
Beispiel #36
0
 public static void Postfix(Pickupable __instance, Vector3 dropPosition)
 {
     Multiplayer.Logic.Item.Dropped(__instance.gameObject, __instance.GetTechType(), dropPosition);
 }
Beispiel #37
0
        public static bool AllowedToAdd_Prefix(Equipment __instance, ref bool __result, string slot, Pickupable pickupable, bool verbose)
        {
            TechType      objTechType = pickupable.GetTechType();
            EquipmentType slotType    = Equipment.GetSlotType(slot);

            if (slotType == EquipmentType.BatteryCharger && ModdedBatteriesFixer.BatteriesTechTypes().Contains(objTechType))
            {
#if BELOWZERO
                EquipmentType eType = TechData.GetEquipmentType(objTechType);
#else
                EquipmentType eType = CraftData.GetEquipmentType(objTechType);
#endif
                if (eType == EquipmentType.Hand || eType == EquipmentType.BatteryCharger)
                {
#if DEBUG_PLACE_TOOL
                    Logger.Log("DEBUG: AllowedToAdd battery charger for " + objTechType.AsString(false));
#endif
                    bool result = ((IItemsContainer)__instance).AllowedToAdd(pickupable, verbose);
                    __result = result;
                    return(false);
                }
            }
            else if (slotType == EquipmentType.PowerCellCharger && ModdedBatteriesFixer.PowercellsTechTypes().Contains(objTechType))
            {
#if BELOWZERO
                EquipmentType eType = TechData.GetEquipmentType(objTechType);
#else
                EquipmentType eType = CraftData.GetEquipmentType(objTechType);
#endif
                if (eType == EquipmentType.Hand || eType == EquipmentType.PowerCellCharger)
                {
#if DEBUG_PLACE_TOOL
                    Logger.Log("DEBUG: AllowedToAdd powercell charger for " + objTechType.AsString(false));
#endif
                    __result = ((IItemsContainer)__instance).AllowedToAdd(pickupable, verbose);
                    return(false);
                }
            }
            return(true);
        }
Beispiel #38
0
        internal bool CanAddItem(Pickupable item)
        {
            bool allowed = CanTakeAnyItem() || IsTypeAllowed(item.GetTechType());

            return(allowed && container.container.HasRoomFor(item));
        }
Beispiel #39
0
	private void Pickup(Pickupable pickupable){
		pickedUpObject = pickupable;
		pickedUpObject.transform.parent = this.transform;
		pickedUpObject.transform.localPosition = new Vector3(0,1,0);
    }
Beispiel #40
0
        public static bool Prefix(ref NitrogenLevel __instance)
        {
            if (DeathRun.murkinessDirty)
            {
                if (WaterBiomeManager.main != null)
                {
                    WaterBiomeManager.main.Rebuild();
                    DeathRun.murkinessDirty = false;
                }
            }

            // Nitrogen tracking doesn't start until player leaves the pod (for underwater starts)
            if ((EscapePod.main == null) || (!EscapePod.main.topHatchUsed && !EscapePod.main.bottomHatchUsed))
            {
                return(false);
            }

            if (DeathRun.playerIsDead || (Player.main == null) || (Ocean.main == null) || (Inventory.main == null))
            {
                return(false);
            }

            float depth = Ocean.main.GetDepthOf(Player.main.gameObject);

            // Update our deepest depth for stats
            DeathRun.saveData.runData.Deepest = Mathf.Max(DeathRun.saveData.runData.Deepest, depth);

            //
            // NITROGEN controller
            //
            if (!Config.NORMAL.Equals(DeathRun.config.nitrogenBends) && Time.timeScale > 0f)
            {
                int  ticks = (int)(DayNightCycle.main.timePassedAsFloat * 2);
                bool tick  = (ticks != DeathRun.saveData.nitroSave.oldTicks) && (DeathRun.saveData.nitroSave.oldTicks > 0);
                DeathRun.saveData.nitroSave.oldTicks = ticks;

                Inventory main     = Inventory.main;
                TechType  bodySlot = Inventory.main.equipment.GetTechTypeInSlot("Body");
                TechType  headSlot = Inventory.main.equipment.GetTechTypeInSlot("Head");

                bool isSwimming = Player.main.IsSwimming();

                Vehicle vehicle = Player.main.GetVehicle();

                bool isInVehicle = Player.main.GetCurrentSub()?.isCyclops == true ||
                                   vehicle is SeaMoth ||
                                   vehicle is Exosuit;

                bool isInBase = Player.main.IsInside() && !isInVehicle; //!isSwimming && (depth > 10) && !GameModeUtils.RequiresOxygen();

                bool isSeaglide = (Player.main.motorMode == Player.MotorMode.Seaglide);

                if (!isSeaglide)
                {
                    Pickupable held = Inventory.main.GetHeld();
                    if (held != null && held.gameObject.GetComponent <Seaglide>() != null)
                    {
                        isSeaglide = true;
                    }
                }

                float ascent = __instance.GetComponent <Rigidbody>().velocity.y;                                        // Player's current positive Y velocity is the ascent rate (fastest seems somewhat above 6)
                DeathRun.saveData.nitroSave.ascentRate = ((DeathRun.saveData.nitroSave.ascentRate * 29) + ascent) / 30; // Average based on 30 frames-per-second

                //
                // NITROGEN - Main Nitrogen adjustment calculations - run twice a second.
                //
                if (tick)
                {
                    float modifier;
                    if (isSwimming)
                    {
                        modifier = 1f;
                        if (depth > 0f)
                        {
                            // Increasingly better suits help lower rate of nitrogen accumulation
                            if (bodySlot == ReinforcedSuitsCore.ReinforcedSuit3ID)
                            {
                                modifier = 0.55f;
                            }
                            else if ((bodySlot == ReinforcedSuitsCore.ReinforcedSuit2ID || bodySlot == ReinforcedSuitsCore.ReinforcedStillSuit))
                            {
                                modifier = 0.75f;
                            }
                            else if (bodySlot == TechType.ReinforcedDiveSuit)
                            {
                                modifier = 0.85f;
                            }
                            else if ((bodySlot == TechType.RadiationSuit || bodySlot == TechType.Stillsuit))
                            {
                                modifier = 0.95f;
                            }
                            if (headSlot == TechType.Rebreather)
                            {
                                modifier -= 0.05f;
                            }
                        }
                    }
                    else
                    {
                        modifier = 0.5f;
                    }

                    float num = __instance.depthCurve.Evaluate(depth / 2048f) * 2;

                    float baselineSafe;
                    if (Config.DEATHRUN.Equals(DeathRun.config.nitrogenBends))
                    {
                        baselineSafe = (depth < 0) ? 0 : depth * 3 / 4; // At any given depth our safe equilibrium gradually approaches 3/4 of current depth
                    }
                    else
                    {
                        baselineSafe = ((depth < 0) || !isSwimming) ? 0 : depth * 3 / 4; // At any given depth our safe equilibrium gradually approaches 3/4 of current depth
                    }

                    // "Deco Module" vehicle upgrade
                    if (vehicle != null)
                    {
                        int deco = vehicle.modules.GetCount(DeathRun.decoModule.TechType);
                        if (deco > 0)
                        {
                            baselineSafe = ((deco < 2) && (DeathRun.saveData.nitroSave.safeDepth >= 10)) ? 1 : 0;
                            //CattleLogger.Message("baselineSafe = " + baselineSafe + "    deco=" + deco);
                        }
                    }

                    if (isInBase || Player.main.GetCurrentSub()?.isCyclops == true)
                    {
                        if (Inventory.main.equipment.GetCount(DeathRun.filterChip.TechType) > 0)
                        {
                            baselineSafe = 0;
                        }
                    }

                    // Better dissipation when we're breathing through a pipe, or in a vehicle/base, or riding Seaglide, or wearing Rebreather
                    if ((baselineSafe > 0) && (DeathRun.saveData.nitroSave.atPipe || !isSwimming || isSeaglide || (headSlot == TechType.Rebreather)))
                    {
                        float adjustment = depth * (2 + (!isSwimming ? 1 : 0) + (isSeaglide ? 1 : 0)) / 8;

                        if ((baselineSafe - adjustment <= DeathRun.saveData.nitroSave.safeDepth) && (baselineSafe > 1))
                        {
                            baselineSafe = baselineSafe - adjustment;
                            if (baselineSafe < 1)
                            {
                                baselineSafe = 1;
                            }
                        }

                        if (DeathRun.saveData.nitroSave.atPipe)
                        {
                            float now = DayNightCycle.main.timePassedAsFloat;
                            if ((now > DeathRun.saveData.nitroSave.pipeTime + 1) && (now > DeathRun.saveData.nitroSave.bubbleTime + 3))
                            {
                                DeathRun.saveData.nitroSave.atPipe = false;
                            }
                        }
                    }

                    if ((baselineSafe < DeathRun.saveData.nitroSave.safeDepth) || (DeathRun.saveData.nitroSave.safeDepth < 10))
                    {
                        modifier = 1 / modifier; // If we're dissipating N2, don't have our high quality suit slow it down

                        // Intentionally more forgiving when deeper
                        num = 0.05f + (0.01f * (int)(DeathRun.saveData.nitroSave.safeDepth / 100));
                    }

                    DeathRun.saveData.nitroSave.safeDepth = UWE.Utils.Slerp(DeathRun.saveData.nitroSave.safeDepth, baselineSafe, num * __instance.kBreathScalar * modifier);

                    // This little % buffer helps introduce the concept of N2 (both initially and as a positive feedback reminder)
                    float target;
                    if (Player.main.precursorOutOfWater || (baselineSafe <= 0))
                    {
                        target = 0;
                    }
                    else if ((DeathRun.saveData.nitroSave.safeDepth > 10f) || (depth >= 20))
                    {
                        target = 100;
                    }
                    else if (depth <= 10)
                    {
                        target = 0;
                    }
                    else
                    {
                        target = (depth - 10) * 10; // Transition zone between 10m and 20m
                    }

                    float rate;
                    if (target > 0)
                    {
                        rate = 1 + depth / 50f;
                    }
                    else
                    {
                        rate = (depth <= 1) ? 6 : (DeathRun.saveData.nitroSave.atPipe || !isSwimming) ? 4 : 2;
                    }

                    __instance.nitrogenLevel = UWE.Utils.Slerp(__instance.nitrogenLevel, target, rate * modifier);
                    __instance.nitrogenLevel = Mathf.Clamp(__instance.nitrogenLevel, 0, 100);

                    if (__instance.nitrogenLevel >= 100)
                    {
                        if (DeathRun.saveData.nitroSave.safeDepth <= 10)
                        {
                            DeathRun.saveData.nitroSave.safeDepth = 10.01f;
                        }
                    }
                }

                //
                // DAMAGE - Check if we need to take damage
                //
                if ((__instance.nitrogenLevel >= 100) && (DeathRun.saveData.nitroSave.safeDepth >= 10f) && ((int)depth < (int)DeathRun.saveData.nitroSave.safeDepth))
                {
                    if (!isInVehicle && !isInBase)
                    {
                        if (DeathRun.saveData.nitroSave.n2WarningTicks == 0)
                        {
                            // If we've NEVER had an N2 warning, institute a hard delay before we can take damage
                            DeathRun.saveData.nitroSave.tookDamageTicks = ticks;
                        }

                        if ((DeathRun.saveData.nitroSave.n2WarningTicks == 0) || (ticks - DeathRun.saveData.nitroSave.n2WarningTicks > 60))
                        {
                            if ((DeathRun.saveData.nitroSave.safeDepth >= 13f) || ((int)depth + 1) < (int)DeathRun.saveData.nitroSave.safeDepth) // Avoid spurious warnings right at surface
                            {
                                if (!Config.NEVER.Equals(DeathRun.config.showWarnings))
                                {
                                    if ((DeathRun.saveData.nitroSave.n2WarningTicks == 0) ||
                                        Config.WHENEVER.Equals(DeathRun.config.showWarnings) ||
                                        (Config.OCCASIONAL.Equals(DeathRun.config.showWarnings) && (ticks - DeathRun.saveData.nitroSave.n2WarningTicks > 600)))
                                    {
                                        DeathRunUtils.CenterMessage("Decompression Warning", 5);
                                        DeathRunUtils.CenterMessage("Dive to Safe Depth!", 5, 1);
                                    }
                                }
                                DeathRun.saveData.nitroSave.n2WarningTicks = ticks;
                            }
                        }

                        int   danger = (int)DeathRun.saveData.nitroSave.safeDepth - (int)depth;
                        float deco   = (isSwimming ? 0.0125f : 0.025f);

                        if (danger < 5)
                        {
                            deco /= 2;
                        }
                        if (danger < 2)
                        {
                            deco /= 2;
                        }

                        if (UnityEngine.Random.value < deco)
                        {
                            if ((DeathRun.saveData.nitroSave.tookDamageTicks == 0) || (ticks - DeathRun.saveData.nitroSave.tookDamageTicks > 10))
                            {
                                DecoDamage(ref __instance, depth, ticks);
                                DeathRun.saveData.nitroSave.tookDamageTicks       = ticks;
                                DeathRun.saveData.nitroSave.reallyTookDamageTicks = ticks;
                            }
                        }
                    }
                }
                else
                {
                    if ((__instance.nitrogenLevel <= 90) || ((depth <= 1) && (DeathRun.saveData.nitroSave.ascentRate < 4) && (DeathRun.saveData.nitroSave.safeDepth < 10f)) || ((depth >= DeathRun.saveData.nitroSave.safeDepth + 10) && isSwimming))
                    {
                        DeathRun.saveData.nitroSave.tookDamageTicks = 0;
                    }
                }

                //
                // ASCENT RATE - Check for ascending too quickly while swimming
                //
                if (isSwimming)
                {
                    if (DeathRun.saveData.nitroSave.ascentRate > (isSeaglide ? 3 : 2))
                    {
                        if (DeathRun.saveData.nitroSave.ascentRate > 4)
                        {
                            DeathRun.saveData.nitroSave.ascentWarning++;
                            if (DeathRun.saveData.nitroSave.ascentWarning == 1)
                            {
                                doAscentWarning(ticks);
                            }
                            else if (DeathRun.saveData.nitroSave.ascentRate >= (isSeaglide ? 5.5 : 5))
                            {
                                if (__instance.nitrogenLevel < 100)
                                {
                                    if ((DeathRun.saveData.nitroSave.ascentWarning % (isSeaglide ? 4 : 2)) == 0)
                                    {
                                        if (((DeathRun.saveData.nitroSave.ascentWarning % 8) == 0) || Config.DEATHRUN.Equals(DeathRun.config.nitrogenBends))
                                        {
                                            __instance.nitrogenLevel++;
                                        }
                                    }
                                }
                                else
                                {
                                    if (DeathRun.saveData.nitroSave.ascentWarning >= (isSeaglide ? 90 : 60)) // After about 2 seconds of too fast
                                    {
                                        int tickrate;
                                        if (Config.DEATHRUN.Equals(DeathRun.config.nitrogenBends))
                                        {
                                            tickrate = 10;
                                        }
                                        else
                                        {
                                            tickrate = 20;
                                        }

                                        if (isSeaglide)
                                        {
                                            tickrate = tickrate * 3 / 2;
                                        }

                                        if (DeathRun.saveData.nitroSave.ascentWarning % tickrate == 0)
                                        {
                                            if (DeathRun.saveData.nitroSave.safeDepth < depth * 1.25f)
                                            {
                                                DeathRun.saveData.nitroSave.safeDepth += 1;
                                            }
                                        }
                                    }

                                    if ((DeathRun.saveData.nitroSave.ascentWarning % 120) == 0)
                                    {
                                        doAscentWarning(ticks);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // if returned to slow speed then increase our buffer
                        if (DeathRun.saveData.nitroSave.ascentWarning > 0)
                        {
                            DeathRun.saveData.nitroSave.ascentWarning--;
                        }

                        // Once we've basically stopped, can do a text warning again if we get too fast
                        if (DeathRun.saveData.nitroSave.ascentRate <= 0.5f)
                        {
                            DeathRun.saveData.nitroSave.ascentWarning = 0;
                        }
                    }
                }

                HUDController(__instance, false); // (DeathRun.saveData.nitroSave.ascentRate >= 5) && (DeathRun.saveData.nitroSave.ascentWarning >= 30));
            }
            else
            {
                if (Time.timeScale > 0f)
                {
                    __instance.nitrogenLevel = 0;
                    DeathRun.saveData.nitroSave.safeDepth = 0;
                    BendsHUDController.SetActive(false, false);
                }
            }

            return(false);
        }
Beispiel #41
0
        internal bool CanAddItemByCategoryFilter(Pickupable item)
        {
            bool allowed = IsTypeAllowedByCategoryFilter(item.GetTechType());

            return(allowed && container.container.HasRoomFor(item));
        }
Beispiel #42
0
        private void CreateStatusItems()
        {
            Func <string, object, string> resolveStringCallback = delegate(string str, object data)
            {
                Workable workable3 = (Workable)data;
                if ((UnityEngine.Object)workable3 != (UnityEngine.Object)null)
                {
                    str = str.Replace("{Target}", workable3.GetComponent <KSelectable>().GetName());
                }
                return(str);
            };
            Func <string, object, string> resolveStringCallback2 = delegate(string str, object data)
            {
                Workable workable2 = (Workable)data;
                if ((UnityEngine.Object)workable2 != (UnityEngine.Object)null)
                {
                    str = str.Replace("{Target}", workable2.GetComponent <KSelectable>().GetName());
                    ComplexFabricatorWorkable complexFabricatorWorkable = workable2 as ComplexFabricatorWorkable;
                    if ((UnityEngine.Object)complexFabricatorWorkable != (UnityEngine.Object)null)
                    {
                        ComplexRecipe currentWorkingOrder = complexFabricatorWorkable.CurrentWorkingOrder;
                        if (currentWorkingOrder != null)
                        {
                            str = str.Replace("{Item}", currentWorkingOrder.FirstResult.ProperName());
                        }
                    }
                }
                return(str);
            };

            BedUnreachable = CreateStatusItem("BedUnreachable", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            BedUnreachable.AddNotification(null, null, null, 0f);
            DailyRationLimitReached = CreateStatusItem("DailyRationLimitReached", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            DailyRationLimitReached.AddNotification(null, null, null, 0f);
            HoldingBreath = CreateStatusItem("HoldingBreath", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Hungry        = CreateStatusItem("Hungry", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Unhappy       = CreateStatusItem("Unhappy", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Unhappy.AddNotification(null, null, null, 0f);
            NervousBreakdown = CreateStatusItem("NervousBreakdown", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Bad, false, OverlayModes.None.ID, true, 2);
            NervousBreakdown.AddNotification(null, null, null, 0f);
            NoRationsAvailable       = CreateStatusItem("NoRationsAvailable", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Bad, false, OverlayModes.None.ID, true, 2);
            PendingPacification      = CreateStatusItem("PendingPacification", "DUPLICANTS", "status_item_pending_pacification", StatusItem.IconType.Custom, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            QuarantineAreaUnassigned = CreateStatusItem("QuarantineAreaUnassigned", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            QuarantineAreaUnassigned.AddNotification(null, null, null, 0f);
            QuarantineAreaUnreachable = CreateStatusItem("QuarantineAreaUnreachable", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            QuarantineAreaUnreachable.AddNotification(null, null, null, 0f);
            Quarantined        = CreateStatusItem("Quarantined", "DUPLICANTS", "status_item_quarantined", StatusItem.IconType.Custom, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            RationsUnreachable = CreateStatusItem("RationsUnreachable", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            RationsUnreachable.AddNotification(null, null, null, 0f);
            RationsNotPermitted = CreateStatusItem("RationsNotPermitted", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            RationsNotPermitted.AddNotification(null, null, null, 0f);
            Rotten   = CreateStatusItem("Rotten", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Starving = CreateStatusItem("Starving", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Bad, false, OverlayModes.None.ID, true, 2);
            Starving.AddNotification(null, null, null, 0f);
            Suffocating = CreateStatusItem("Suffocating", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.DuplicantThreatening, false, OverlayModes.None.ID, true, 2);
            Suffocating.AddNotification(null, null, null, 0f);
            Tired = CreateStatusItem("Tired", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Idle  = CreateStatusItem("Idle", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Idle.AddNotification(null, null, null, 0f);
            Pacified = CreateStatusItem("Pacified", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Dead     = CreateStatusItem("Dead", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Dead.resolveStringCallback = delegate(string str, object data)
            {
                Death death = (Death)data;
                return(str.Replace("{Death}", death.Name));
            };
            MoveToSuitNotRequired   = CreateStatusItem("MoveToSuitNotRequired", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            DroppingUnusedInventory = CreateStatusItem("DroppingUnusedInventory", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            MovingToSafeArea        = CreateStatusItem("MovingToSafeArea", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            ToiletUnreachable       = CreateStatusItem("ToiletUnreachable", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            ToiletUnreachable.AddNotification(null, null, null, 0f);
            NoUsableToilets = CreateStatusItem("NoUsableToilets", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            NoUsableToilets.AddNotification(null, null, null, 0f);
            NoToilets = CreateStatusItem("NoToilets", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            NoToilets.AddNotification(null, null, null, 0f);
            BreathingO2 = CreateStatusItem("BreathingO2", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 130);
            BreathingO2.resolveStringCallback = delegate(string str, object data)
            {
                OxygenBreather oxygenBreather2 = (OxygenBreather)data;
                float          averageRate     = Game.Instance.accumulators.GetAverageRate(oxygenBreather2.O2Accumulator);
                return(str.Replace("{ConsumptionRate}", GameUtil.GetFormattedMass(0f - averageRate, GameUtil.TimeSlice.PerSecond, GameUtil.MetricMassFormat.UseThreshold, true, "{0:0.#}")));
            };
            EmittingCO2 = CreateStatusItem("EmittingCO2", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 130);
            EmittingCO2.resolveStringCallback = delegate(string str, object data)
            {
                OxygenBreather oxygenBreather = (OxygenBreather)data;
                return(str.Replace("{EmittingRate}", GameUtil.GetFormattedMass(oxygenBreather.CO2EmitRate, GameUtil.TimeSlice.PerSecond, GameUtil.MetricMassFormat.UseThreshold, true, "{0:0.#}")));
            };
            Vomiting  = CreateStatusItem("Vomiting", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Coughing  = CreateStatusItem("Coughing", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            LowOxygen = CreateStatusItem("LowOxygen", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            LowOxygen.AddNotification(null, null, null, 0f);
            RedAlert = CreateStatusItem("RedAlert", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Sleeping = CreateStatusItem("Sleeping", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Sleeping.resolveTooltipCallback = delegate(string str, object data)
            {
                if (data is SleepChore.StatesInstance)
                {
                    SleepChore.StatesInstance statesInstance2 = (SleepChore.StatesInstance)data;
                    string stateChangeNoiseSource             = statesInstance2.stateChangeNoiseSource;
                    if (!string.IsNullOrEmpty(stateChangeNoiseSource))
                    {
                        string text5 = DUPLICANTS.STATUSITEMS.SLEEPING.TOOLTIP;
                        text5 = text5.Replace("{Disturber}", stateChangeNoiseSource);
                        str  += text5;
                    }
                }
                return(str);
            };
            SleepingInterruptedByNoise = CreateStatusItem("SleepingInterruptedByNoise", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            SleepingInterruptedByLight = CreateStatusItem("SleepingInterruptedByLight", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Eating = CreateStatusItem("Eating", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Eating.resolveStringCallback = resolveStringCallback;
            Digging  = CreateStatusItem("Digging", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Cleaning = CreateStatusItem("Cleaning", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Cleaning.resolveStringCallback = resolveStringCallback;
            PickingUp = CreateStatusItem("PickingUp", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            PickingUp.resolveStringCallback = resolveStringCallback;
            Mopping = CreateStatusItem("Mopping", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Cooking = CreateStatusItem("Cooking", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Cooking.resolveStringCallback = resolveStringCallback2;
            Mushing = CreateStatusItem("Mushing", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Mushing.resolveStringCallback = resolveStringCallback2;
            Researching = CreateStatusItem("Researching", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Researching.resolveStringCallback = delegate(string str, object data)
            {
                TechInstance activeResearch = Research.Instance.GetActiveResearch();
                if (activeResearch != null)
                {
                    return(str.Replace("{Tech}", activeResearch.tech.Name));
                }
                return(str);
            };
            Tinkering = CreateStatusItem("Tinkering", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Tinkering.resolveStringCallback = delegate(string str, object data)
            {
                Tinkerable tinkerable = (Tinkerable)data;
                if ((UnityEngine.Object)tinkerable != (UnityEngine.Object)null)
                {
                    return(string.Format(str, tinkerable.tinkerMaterialTag.ProperName()));
                }
                return(str);
            };
            Storing = CreateStatusItem("Storing", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Storing.resolveStringCallback = delegate(string str, object data)
            {
                Workable workable = (Workable)data;
                if ((UnityEngine.Object)workable != (UnityEngine.Object)null && (UnityEngine.Object)workable.worker != (UnityEngine.Object)null)
                {
                    KSelectable component = workable.GetComponent <KSelectable>();
                    if ((bool)component)
                    {
                        str = str.Replace("{Target}", component.GetName());
                    }
                    Pickupable pickupable = workable.worker.workCompleteData as Pickupable;
                    if ((UnityEngine.Object)workable.worker != (UnityEngine.Object)null && (bool)pickupable)
                    {
                        KSelectable component2 = pickupable.GetComponent <KSelectable>();
                        if ((bool)component2)
                        {
                            str = str.Replace("{Item}", component2.GetName());
                        }
                    }
                }
                return(str);
            };
            Building = CreateStatusItem("Building", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Building.resolveStringCallback = resolveStringCallback;
            Equipping = CreateStatusItem("Equipping", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Equipping.resolveStringCallback = resolveStringCallback;
            WarmingUp = CreateStatusItem("WarmingUp", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            WarmingUp.resolveStringCallback = resolveStringCallback;
            GeneratingPower = CreateStatusItem("GeneratingPower", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            GeneratingPower.resolveStringCallback = resolveStringCallback;
            Harvesting = CreateStatusItem("Harvesting", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Harvesting.resolveStringCallback = resolveStringCallback;
            Uprooting = CreateStatusItem("Uprooting", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Uprooting.resolveStringCallback = resolveStringCallback;
            Emptying = CreateStatusItem("Emptying", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Emptying.resolveStringCallback = resolveStringCallback;
            Toggling = CreateStatusItem("Toggling", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Toggling.resolveStringCallback = resolveStringCallback;
            Deconstructing = CreateStatusItem("Deconstructing", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Deconstructing.resolveStringCallback = resolveStringCallback;
            Disinfecting = CreateStatusItem("Disinfecting", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Disinfecting.resolveStringCallback = resolveStringCallback;
            Upgrading = CreateStatusItem("Upgrading", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Upgrading.resolveStringCallback = resolveStringCallback;
            Fabricating = CreateStatusItem("Fabricating", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Fabricating.resolveStringCallback = resolveStringCallback2;
            Processing = CreateStatusItem("Processing", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Processing.resolveStringCallback = resolveStringCallback2;
            Clearing = CreateStatusItem("Clearing", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Clearing.resolveStringCallback = resolveStringCallback;
            GeneratingPower = CreateStatusItem("GeneratingPower", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            GeneratingPower.resolveStringCallback = resolveStringCallback;
            Cold = CreateStatusItem("Cold", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Cold.resolveTooltipCallback = delegate(string str, object data)
            {
                str = str.Replace("{StressModification}", GameUtil.GetFormattedPercent(Db.Get().effects.Get("ColdAir").SelfModifiers[0].Value, GameUtil.TimeSlice.PerCycle));
                float dtu_s2 = ((ExternalTemperatureMonitor.Instance)data).temperatureTransferer.average_kilowatts_exchanged.GetWeightedAverage * 1000f;
                str = str.Replace("{currentTransferWattage}", GameUtil.GetFormattedHeatEnergyRate(dtu_s2, GameUtil.HeatEnergyFormatterUnit.Automatic));
                AttributeInstance attributeInstance3 = ((ExternalTemperatureMonitor.Instance)data).attributes.Get("ThermalConductivityBarrier");
                string            text3 = "<b>" + attributeInstance3.GetFormattedValue() + "</b>";
                for (int j = 0; j != attributeInstance3.Modifiers.Count; j++)
                {
                    AttributeModifier attributeModifier2 = attributeInstance3.Modifiers[j];
                    text3 += "\n";
                    string text4 = text3;
                    text3 = text4 + "    • " + attributeModifier2.GetDescription() + " <b>" + attributeModifier2.GetFormattedString(attributeInstance3.gameObject) + "</b>";
                }
                str = str.Replace("{conductivityBarrier}", text3);
                return(str);
            };
            Hot = CreateStatusItem("Hot", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            Hot.resolveTooltipCallback = delegate(string str, object data)
            {
                str = str.Replace("{StressModification}", GameUtil.GetFormattedPercent(Db.Get().effects.Get("WarmAir").SelfModifiers[0].Value, GameUtil.TimeSlice.PerCycle));
                float dtu_s = ((ExternalTemperatureMonitor.Instance)data).temperatureTransferer.average_kilowatts_exchanged.GetWeightedAverage * 1000f;
                str = str.Replace("{currentTransferWattage}", GameUtil.GetFormattedHeatEnergyRate(dtu_s, GameUtil.HeatEnergyFormatterUnit.Automatic));
                AttributeInstance attributeInstance2 = ((ExternalTemperatureMonitor.Instance)data).attributes.Get("ThermalConductivityBarrier");
                string            text = "<b>" + attributeInstance2.GetFormattedValue() + "</b>";
                for (int i = 0; i != attributeInstance2.Modifiers.Count; i++)
                {
                    AttributeModifier attributeModifier = attributeInstance2.Modifiers[i];
                    text += "\n";
                    string text2 = text;
                    text = text2 + "    • " + attributeModifier.GetDescription() + " <b>" + attributeModifier.GetFormattedString(attributeInstance2.gameObject) + "</b>";
                }
                str = str.Replace("{conductivityBarrier}", text);
                return(str);
            };
            BodyRegulatingHeating = CreateStatusItem("BodyRegulatingHeating", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            BodyRegulatingHeating.resolveStringCallback = delegate(string str, object data)
            {
                WarmBlooded.StatesInstance statesInstance = (WarmBlooded.StatesInstance)data;
                return(str.Replace("{TempDelta}", GameUtil.GetFormattedTemperature(statesInstance.TemperatureDelta, GameUtil.TimeSlice.PerSecond, GameUtil.TemperatureInterpretation.Relative, true, false)));
            };
            BodyRegulatingCooling = CreateStatusItem("BodyRegulatingCooling", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            BodyRegulatingCooling.resolveStringCallback = BodyRegulatingHeating.resolveStringCallback;
            EntombedChore = CreateStatusItem("EntombedChore", "DUPLICANTS", "status_item_entombed", StatusItem.IconType.Custom, NotificationType.DuplicantThreatening, false, OverlayModes.None.ID, true, 2);
            EntombedChore.AddNotification(null, null, null, 0f);
            EarlyMorning                 = CreateStatusItem("EarlyMorning", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            NightTime                    = CreateStatusItem("NightTime", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            PoorDecor                    = CreateStatusItem("PoorDecor", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            PoorQualityOfLife            = CreateStatusItem("PoorQualityOfLife", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            PoorFoodQuality              = CreateStatusItem("PoorFoodQuality", DUPLICANTS.STATUSITEMS.POOR_FOOD_QUALITY.NAME, DUPLICANTS.STATUSITEMS.POOR_FOOD_QUALITY.TOOLTIP, string.Empty, StatusItem.IconType.Exclamation, NotificationType.Neutral, false, OverlayModes.None.ID, 2);
            GoodFoodQuality              = CreateStatusItem("GoodFoodQuality", DUPLICANTS.STATUSITEMS.GOOD_FOOD_QUALITY.NAME, DUPLICANTS.STATUSITEMS.GOOD_FOOD_QUALITY.TOOLTIP, string.Empty, StatusItem.IconType.Exclamation, NotificationType.Neutral, false, OverlayModes.None.ID, 2);
            Arting                       = CreateStatusItem("Arting", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Arting.resolveStringCallback = resolveStringCallback;
            SevereWounds                 = CreateStatusItem("SevereWounds", "DUPLICANTS", "status_item_broken", StatusItem.IconType.Custom, NotificationType.Bad, false, OverlayModes.None.ID, true, 2);
            SevereWounds.AddNotification(null, null, null, 0f);
            Incapacitated = CreateStatusItem("Incapacitated", "DUPLICANTS", "status_item_broken", StatusItem.IconType.Custom, NotificationType.DuplicantThreatening, false, OverlayModes.None.ID, true, 2);
            Incapacitated.AddNotification(null, null, null, 0f);
            Incapacitated.resolveStringCallback = delegate(string str, object data)
            {
                IncapacitationMonitor.Instance instance = (IncapacitationMonitor.Instance)data;
                float bleedLifeTime = instance.GetBleedLifeTime(instance);
                str = str.Replace("{CauseOfIncapacitation}", instance.GetCauseOfIncapacitation().Name);
                return(str.Replace("{TimeUntilDeath}", GameUtil.GetFormattedTime(bleedLifeTime)));
            };
            Relocating = CreateStatusItem("Relocating", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Relocating.resolveStringCallback = resolveStringCallback;
            Fighting = CreateStatusItem("Fighting", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Bad, false, OverlayModes.None.ID, true, 2);
            Fighting.AddNotification(null, null, null, 0f);
            Fleeing = CreateStatusItem("Fleeing", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Bad, false, OverlayModes.None.ID, true, 2);
            Fleeing.AddNotification(null, null, null, 0f);
            Stressed = CreateStatusItem("Stressed", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Stressed.AddNotification(null, null, null, 0f);
            LashingOut = CreateStatusItem("LashingOut", "DUPLICANTS", string.Empty, StatusItem.IconType.Exclamation, NotificationType.Bad, false, OverlayModes.None.ID, true, 2);
            LashingOut.AddNotification(null, null, null, 0f);
            LowImmunity = CreateStatusItem("LowImmunity", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.BadMinor, false, OverlayModes.None.ID, true, 2);
            LowImmunity.AddNotification(null, null, null, 0f);
            Studying         = CreateStatusItem("Studying", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, false, OverlayModes.None.ID, true, 2);
            Socializing      = CreateStatusItem("Socializing", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Good, false, OverlayModes.None.ID, true, 2);
            Dancing          = CreateStatusItem("Dancing", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Good, false, OverlayModes.None.ID, true, 2);
            Gaming           = CreateStatusItem("Gaming", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Good, false, OverlayModes.None.ID, true, 2);
            Mingling         = CreateStatusItem("Mingling", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Good, false, OverlayModes.None.ID, true, 2);
            ContactWithGerms = CreateStatusItem("ContactWithGerms", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, true, OverlayModes.Disease.ID, true, 2);
            ContactWithGerms.resolveStringCallback = delegate(string str, object data)
            {
                GermExposureMonitor.ExposureStatusData exposureStatusData4 = (GermExposureMonitor.ExposureStatusData)data;
                string name2 = Db.Get().Sicknesses.Get(exposureStatusData4.exposure_type.sickness_id).Name;
                str = str.Replace("{Sickness}", name2);
                return(str);
            };
            ContactWithGerms.statusItemClickCallback = delegate(object data)
            {
                GermExposureMonitor.ExposureStatusData exposureStatusData3 = (GermExposureMonitor.ExposureStatusData)data;
                Vector3 lastExposurePosition2 = exposureStatusData3.owner.GetLastExposurePosition(exposureStatusData3.exposure_type.germ_id);
                CameraController.Instance.CameraGoTo(lastExposurePosition2, 2f, true);
                if (OverlayScreen.Instance.mode == OverlayModes.None.ID)
                {
                    OverlayScreen.Instance.ToggleOverlay(OverlayModes.Disease.ID, true);
                }
            };
            ExposedToGerms = CreateStatusItem("ExposedToGerms", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Neutral, true, OverlayModes.Disease.ID, true, 2);
            ExposedToGerms.resolveStringCallback = delegate(string str, object data)
            {
                GermExposureMonitor.ExposureStatusData exposureStatusData2 = (GermExposureMonitor.ExposureStatusData)data;
                string                       name = Db.Get().Sicknesses.Get(exposureStatusData2.exposure_type.sickness_id).Name;
                AttributeInstance            attributeInstance = Db.Get().Attributes.GermResistance.Lookup(exposureStatusData2.owner.gameObject);
                string                       lastDiseaseSource = exposureStatusData2.owner.GetLastDiseaseSource(exposureStatusData2.exposure_type.germ_id);
                GermExposureMonitor.Instance sMI = exposureStatusData2.owner.GetSMI <GermExposureMonitor.Instance>();
                float num        = (float)exposureStatusData2.exposure_type.base_resistance + GERM_EXPOSURE.EXPOSURE_TIER_RESISTANCE_BONUSES[0];
                float totalValue = attributeInstance.GetTotalValue();
                float resistanceToExposureType = sMI.GetResistanceToExposureType(exposureStatusData2.exposure_type, -1f);
                float contractionChance        = GermExposureMonitor.GetContractionChance(resistanceToExposureType);
                float exposureTier             = sMI.GetExposureTier(exposureStatusData2.exposure_type.germ_id);
                float num2 = GERM_EXPOSURE.EXPOSURE_TIER_RESISTANCE_BONUSES[(int)exposureTier - 1] - GERM_EXPOSURE.EXPOSURE_TIER_RESISTANCE_BONUSES[0];
                str = str.Replace("{Severity}", DUPLICANTS.STATUSITEMS.EXPOSEDTOGERMS.EXPOSURE_TIERS[(int)exposureTier - 1]);
                str = str.Replace("{Sickness}", name);
                str = str.Replace("{Source}", lastDiseaseSource);
                str = str.Replace("{Base}", GameUtil.GetFormattedSimple(num, GameUtil.TimeSlice.None, null));
                str = str.Replace("{Dupe}", GameUtil.GetFormattedSimple(totalValue, GameUtil.TimeSlice.None, null));
                str = str.Replace("{Total}", GameUtil.GetFormattedSimple(resistanceToExposureType, GameUtil.TimeSlice.None, null));
                str = str.Replace("{ExposureLevelBonus}", GameUtil.GetFormattedSimple(num2, GameUtil.TimeSlice.None, null));
                str = str.Replace("{Chance}", GameUtil.GetFormattedPercent(contractionChance * 100f, GameUtil.TimeSlice.None));
                return(str);
            };
            ExposedToGerms.statusItemClickCallback = delegate(object data)
            {
                GermExposureMonitor.ExposureStatusData exposureStatusData = (GermExposureMonitor.ExposureStatusData)data;
                Vector3 lastExposurePosition = exposureStatusData.owner.GetLastExposurePosition(exposureStatusData.exposure_type.germ_id);
                CameraController.Instance.CameraGoTo(lastExposurePosition, 2f, true);
                if (OverlayScreen.Instance.mode == OverlayModes.None.ID)
                {
                    OverlayScreen.Instance.ToggleOverlay(OverlayModes.Disease.ID, true);
                }
            };
            LightWorkEfficiencyBonus = CreateStatusItem("LightWorkEfficiencyBonus", "DUPLICANTS", string.Empty, StatusItem.IconType.Info, NotificationType.Good, false, OverlayModes.None.ID, true, 2);
        }