Example #1
0
    IEnumerator LerpGray()
    {
        float startTime    = Time.time;
        float prevMaxRamp  = maxRampOffset;
        float prevLerpFreq = lerpFrequency;
        float offset       = 0;

        while (true)
        {
            if (!prevMaxRamp.Approx(maxRampOffset))
            {
                prevMaxRamp = maxRampOffset;
            }
            if (!prevLerpFreq.Approx(lerpFrequency))
            {
                prevLerpFreq = lerpFrequency;
                float currLerpParam = Mathf.InverseLerp(0, maxRampOffset, gray.rampOffset);
                float sinVal        = Mathf.Sin(Time.time - startTime);
                float upOrDown      = Mathf.Sign(sinVal);

                startTime = Time.time - (Mathf.Asin(currLerpParam * 2f - 1f) / lerpFrequency);
                //startTime = startTime + 2 * (Mathf.PI / 2 - startTime);
                // if opposite direction, (pi / 2) - startTime
            }
            gray.rampOffset = Mathf.Lerp(0, maxRampOffset, (Mathf.Sin((Time.time - startTime) * lerpFrequency) + 1f) / 2f);
            yield return(null);
        }
    }
Example #2
0
        public bool Iteration()
        {
            var dict = new SortedDictionary <float, float>();

            theta0 = GetIterValue();
            dict.Add(Dist(), GetIterValue()); // 计算当前距离并存放到字典里,以距离作为Key排序

            SetIterValue(theta0 + alpha);     // 计算向前步进后的距离,放进字典
            var dist = Dist();

            if (!dict.ContainsKey(dist))
            {
                dict.Add(dist, GetIterValue()); //(字典里的值是被DOF限制后的)
            }
            SetIterValue(theta0 - alpha);       // 反向
            dist = Dist();
            if (!dict.ContainsKey(dist))
            {
                dict.Add(dist, GetIterValue());
            }

            foreach (var i in dict)
            {
                SetIterValue(i.Value);
                astIK.Rotate();
                break;
            }
            theta1 = GetIterValue();
            return(theta0.Approx(theta1)); // 是否已经接近最佳值
        }
Example #3
0
    internal static float ValueFromSides(this float negativeSide, float positiveSide)
    {
        float v1 = negativeSide.Abs();
        float v2 = positiveSide.Abs();

        if (v1.Approx(v2))
        {
            return(0.0f);
        }
        return((double)v1 > (double)v2 ? -v1 : v2);
    }
Example #4
0
        private void ModeSiphon()
        {
            float moles = metaNode.GasMix.Moles * (IsExpandedRange ? 0.40f : 0.05f) * Effectiveness;             // siphon a portion

            moles = moles.Clamp(0, nominalMolesTransferCap);

            if (moles.Approx(0))
            {
                return;
            }

            GasMix.TransferGas(pipeMix, metaNode.GasMix, moles);
        }
Example #5
0
        public void SetIntegrityLevel(float newLevel)
        {
            Mathf.Clamp(newLevel, 0, 100);

            //0 check
            if (newLevel.Approx(0))
            {
                integritySlider.value = 0;
                return;
            }

            // 0 to 1
            integritySlider.value = newLevel / 100;
        }
Example #6
0
        public void SetPowerLevel(float newLevel)
        {
            Mathf.Clamp(newLevel, 0, 100);

            //0 check
            if (newLevel.Approx(0))
            {
                powerSlider.value = 0;
                return;
            }

            // 0 to 1
            powerSlider.value = newLevel / 100;
        }
Example #7
0
        private static void InternalSetMoles(GasData data, GasSO gasType, float moles, bool isChange)
        {
            lock (data.GasesArray)             //Because it gets the gas and it could be added in between this
            {
                //Try to get gas value if already inside mix
                GetGasType(data, gasType, out var gas);

                if (gas != null)
                {
                    if (isChange)
                    {
                        gas.Moles += moles;
                    }
                    else
                    {
                        gas.Moles = moles;
                    }

                    //Remove gas from mix if less than threshold
                    if (gas.Moles <= AtmosConstants.MinPressureDifference)
                    {
                        data.RemoveGasType(gasType);
                    }

                    return;
                }

                //Gas isn't inside mix so we'll add it

                //Dont add new data for negative moles
                if (Math.Sign(moles) == -1)
                {
                    return;
                }

                //Dont add if approx 0 or below threshold
                if (moles.Approx(0) || moles <= AtmosConstants.MinPressureDifference)
                {
                    return;
                }

                var newValues = GetGasValues();
                newValues.Moles = moles;
                newValues.GasSO = gasType;

                data.GasesArray.Add(newValues);
                data.GasesDict.Add(gasType, newValues);
            }
        }
Example #8
0
        private void ModeScrub()
        {
            // Scrub out a portion of each specified gas.
            // If all these gases exceed transfer amount, reduce each gas scrub mole count proportionally.

            float scrubbableMolesAvailable = 0;

            lock (metaNode.GasMix.GasesArray)                         //no Double lock
            {
                foreach (GasValues gas in metaNode.GasMix.GasesArray) //doesn't appear to modify list while iterating
                {
                    if (FilteredGases.Contains(gas.GasSO))
                    {
                        scrubbingGasMoles[gas.GasSO] = gas.Moles * (IsExpandedRange ? 0.05f : 0.20f) * Effectiveness;
                        scrubbableMolesAvailable    += scrubbingGasMoles[gas.GasSO];
                    }
                }
            }

            if (scrubbableMolesAvailable.Approx(0))
            {
                return;                                                 // No viable gases found
            }
            float molesToTransfer = scrubbableMolesAvailable.Clamp(0, nominalMolesTransferCap * Effectiveness);
            float ratio           = molesToTransfer / scrubbableMolesAvailable;

            ratio = ratio.Clamp(0, 1);

            // actual scrubbing
            for (int i = 0; i < Gas.Gases.Count; i++)
            {
                GasSO gas            = Gas.Gases[i];
                float transferAmount = scrubbingGasMoles[i] * ratio;
                if (transferAmount.Approx(0))
                {
                    continue;
                }

                metaNode.GasMix.RemoveGas(gas, transferAmount);
                if (selfSufficient == false)
                {
                    pipeMix.AddGas(gas, transferAmount);
                }
            }
            Array.Clear(scrubbingGasMoles, 0, scrubbingGasMoles.Length);
        }
 public bool Approx(Float2 other, float maxDifference = .0001f)
 => X.Approx(other.X, maxDifference) && Y.Approx(other.Y, maxDifference);
Example #10
0
    /// <summary>
    /// Pulls in the desired gas, as well as others, from the specified gas mix and adds them to the blood stream
    /// </summary>
    /// <param name="gasMix">The gas mix to breathe in from</param>
    /// <param name="blood">The blood to put gases into</param>
    /// <returns> True if breathGasMix was changed </returns>
    private bool BreatheIn(GasMix breathGasMix, ReagentMix blood, float efficiency)
    {
        if (RelatedPart.HealthMaster.RespiratorySystem.CanBreathAnywhere)
        {
            blood.Add(RelatedPart.requiredReagent, RelatedPart.bloodType.GetSpareGasCapacity(blood));
            return(false);
        }

        ReagentMix toInhale   = new ReagentMix();
        var        Available  = RelatedPart.bloodType.GetGasCapacityOfnonMeanCarrier(blood);
        var        TotalMoles = breathGasMix.Moles;

        foreach (var gasValues in breathGasMix.GasData.GasesArray)
        {
            var gas = gasValues.GasSO;
            if (GAS2ReagentSingleton.Instance.DictionaryGasToReagent.ContainsKey(gas) == false)
            {
                continue;
            }

            // n = PV/RT
            float gasMoles = breathGasMix.GetPressure(gas) * LungSize / (8.314f * breathGasMix.Temperature);

            // Get as much as we need, or as much as in the lungs, whichever is lower
            Reagent gasReagent    = GAS2ReagentSingleton.Instance.GetGasToReagent(gas);
            float   molesRecieved = 0;
            if (gasReagent == RelatedPart.bloodType.CirculatedReagent)
            {
                molesRecieved = Mathf.Min(gasMoles, RelatedPart.bloodType.GetSpareGasCapacity(blood, gasReagent));
            }
            else
            {
                if (gasMoles == 0)
                {
                    molesRecieved = 0;
                }
                else
                {
                    molesRecieved = Available / (TotalMoles / gasMoles);
                    molesRecieved = Mathf.Min(molesRecieved, gasMoles);
                }
            }

            if (molesRecieved.Approx(0) == false)
            {
                toInhale.Add(gasReagent, molesRecieved * efficiency);
            }

            //TODO: Add pressureSafeMax check here, for hyperoxia
        }

        RelatedPart.HealthMaster.RespiratorySystem.GasExchangeToBlood(breathGasMix, blood, toInhale);

        // Counterintuitively, in humans respiration is stimulated by pressence of CO2 in the blood, not lack of oxygen
        // May want to change this code to reflect that in the future so people don't hyperventilate when they are on nitrous oxide
        var   inGas           = GAS2ReagentSingleton.Instance.GetGasToReagent(requiredGas);
        float bloodCap        = RelatedPart.bloodType.GetGasCapacity(RelatedPart.BloodContainer.CurrentReagentMix);
        float foreignCap      = RelatedPart.bloodType.GetGasCapacityForeign(RelatedPart.BloodContainer.CurrentReagentMix);
        float bloodSaturation = 0;

        if (bloodCap + foreignCap == 0)
        {
            bloodSaturation = 0;
        }
        else
        {
            var ratioNativeBlood = bloodCap / (bloodCap + foreignCap);
            bloodSaturation = RelatedPart.BloodContainer[RelatedPart.requiredReagent] * ratioNativeBlood / bloodCap;
        }
        if (bloodSaturation >= RelatedPart.HealthMaster.CirculatorySystem.BloodInfo.BLOOD_REAGENT_SATURATION_OKAY)
        {
            currentBreatheCooldown = breatheCooldown;             //Slow breathing, we're all good
            RelatedPart.HealthMaster.HealthStateController.SetSuffocating(false);
        }
        else if (bloodSaturation <= RelatedPart.HealthMaster.CirculatorySystem.BloodInfo.BLOOD_REAGENT_SATURATION_BAD)
        {
            RelatedPart.HealthMaster.HealthStateController.SetSuffocating(true);
            if (Random.value < 0.2)
            {
                Chat.AddActionMsgToChat(RelatedPart.HealthMaster.gameObject, "You gasp for breath", $"{RelatedPart.HealthMaster.PlayerScriptOwner.visibleName} gasps");
            }
        }

        //Debug.Log("Gas inhaled: " + toInhale.Total + " Saturation: " + saturation);
        return(toInhale.Total > 0);
    }
Example #11
0
        private static void InternalSetMoles(GasData data, GasSO gasType, float moles, bool isChange)
        {
            //Try to get gas value if already inside mix
            GetGasType(data, gasType, out var gas);

            if (gas != null)
            {
                if (isChange)
                {
                    gas.Moles += moles;
                }
                else
                {
                    gas.Moles = moles;
                }

                //Remove gas from mix if less than threshold
                if (gas.Moles <= AtmosConstants.MinPressureDifference)
                {
                    data.RemoveGasType(gasType);
                }

                return;
            }

            //Gas isn't inside mix so we'll add it

            //Dont add new data for negative moles
            if (Math.Sign(moles) == -1)
            {
                return;
            }

            //Dont add if approx 0 or below threshold
            if (moles.Approx(0) || moles <= AtmosConstants.MinPressureDifference)
            {
                return;
            }

            //Create new array and add old gas values and new gas
            var newValues = new GasValues {
                Moles = moles, GasSO = gasType
            };
            var newArray = new GasValues[data.GasesArray.Length + 1];

            for (int i = 0; i < newArray.Length; i++)
            {
                if (data.GasesArray.Length == i)
                {
                    newArray[i] = newValues;

                    //Should only happen on last index since we are adding only one thing so can break
                    break;
                }

                newArray[i] = data.GasesArray[i];
            }

            data.GasesArray = newArray;
            data.GasesDict.Add(gasType, newValues);
        }
        IEnumerator PerformFollowPath(List <Node> path)
        {
            int node = 1;

            while (node < path.Count)
            {
                if (!activated)
                {
                    yield return(WaitFor.EndOfFrame);

                    yield break;
                }

                if (!movingToTile)
                {
                    if (TickDelay.Approx(0) == false)
                    {
                        yield return(WaitFor.Seconds(TickDelay));
                    }

                    var dir = path[node].position - Vector2Int.RoundToInt(transform.localPosition);
                    if (!registerTile.Matrix.IsPassableAtOneMatrixOneTile(registerTile.LocalPositionServer + (Vector3Int)dir, true, context: gameObject))
                    {
                        var dC = registerTile.Matrix.GetFirst <DoorController>(
                            registerTile.LocalPositionServer + (Vector3Int)dir, true);
                        if (dC != null)
                        {
                            dC.MobTryOpen(gameObject);
                            yield return(WaitFor.Seconds(1f));
                        }
                        else
                        {
                            ResetMovingValues();
                            FollowCompleted();
                            Logger.Log("Path following timed out. Something must be in the way", Category.Movement);
                            yield break;
                        }
                    }

                    if (directional != null)
                    {
                        directional.FaceDirection(Orientation.From(dir));
                    }

                    cnt.Push(dir, context: gameObject);
                    movingToTile = true;
                }
                else
                {
                    if (arrivedAtTile)
                    {
                        movingToTile  = false;
                        arrivedAtTile = false;
                        timeOut       = 0f;
                        node++;
                    }
                    else
                    {
                        //Mob has 5 seconds to get to the next tile
                        //or the AI should do something else
                        timeOut += Time.deltaTime;
                        if (timeOut > 5f)
                        {
                            ResetMovingValues();
                            Logger.Log("Path following timed out. Something must be in the way", Category.Movement);
                            FollowCompleted();
                            yield break;
                        }
                    }
                }

                yield return(WaitFor.EndOfFrame);
            }

            yield return(WaitFor.EndOfFrame);

            ResetMovingValues();
            FollowCompleted();
        }
Example #13
0
 public bool Approx(Float4 other, float maxDifference = .0001f) =>
 X.Approx(other.X, maxDifference) &&
 Y.Approx(other.Y, maxDifference) &&
 Z.Approx(other.Z, maxDifference) &&
 W.Approx(other.W, maxDifference);