예제 #1
0
        IEnumerator LoopRoutine()
        {
            MopSettings.IsModActive = true;

            FramerateRecorder rec = gameObject.AddComponent <FramerateRecorder>();

            rec.Initialize();

            while (MopSettings.IsModActive)
            {
                // Ticks make sure that MOP is still up and running.
                // If the ticks didn't update, that means this routine stopped.
                ++ticks;

                if (!itemInitializationDelayDone)
                {
                    // We are slightly delaying the initialization, so all items have chance to set in place, because f**k MSC and its physics.
                    waitTime++;
                    if (waitTime >= WaitDone)
                    {
                        FinishLoading();
                    }
                }

                isPlayerAtYard = MOP.ActiveDistance.Value == 0 ? Vector3.Distance(player.position, placeManager[0].transform.position) < 100
                    : Vector3.Distance(player.position, placeManager[0].transform.position) < 100 * MopSettings.ActiveDistanceMultiplicationValue;

                // When player is in any of the sectors, MOP will act like the player is at yard.
                if (SectorManager.Instance.IsPlayerInSector())
                {
                    inSectorMode   = true;
                    isPlayerAtYard = true;
                }
                else
                {
                    inSectorMode = false;
                }

                yield return(null);

                int  i;
                long half = worldObjectManager.Count >> 1;
                // World Objects.
                for (i = 0; i < worldObjectManager.Count; ++i)
                {
                    if (i == half)
                    {
                        yield return(null);
                    }

                    try
                    {
                        GenericObject worldObject = worldObjectManager[i];

                        // Check if object was destroyed (mostly intended for AI pedastrians).
                        if (worldObject.GameObject == null)
                        {
                            worldObjectManager.Remove(worldObject);
                            continue;
                        }

                        if (SectorManager.Instance.IsPlayerInSector() && SectorManager.Instance.SectorRulesContains(worldObject.GameObject.name))
                        {
                            worldObject.GameObject.SetActive(true);
                            continue;
                        }

                        // Should the object be disabled when the player leaves the house?
                        if (worldObject.DisableOn.HasFlag(DisableOn.PlayerAwayFromHome) || worldObject.DisableOn.HasFlag(DisableOn.PlayerInHome))
                        {
                            if (worldObject.GameObject.name == "NPC_CARS" && inSectorMode)
                            {
                                continue;
                            }

                            if (worldObject.GameObject.name == "COMPUTER" && worldObject.GameObject.transform.Find("SYSTEM").gameObject.activeSelf)
                            {
                                continue;
                            }

                            worldObject.Toggle(worldObject.DisableOn.HasFlag(DisableOn.PlayerAwayFromHome) ? isPlayerAtYard : !isPlayerAtYard);
                        }
                        else if (worldObject.DisableOn.HasFlag(DisableOn.Distance))
                        {
                            // The object will be disabled, if the player is in the range of that object.
                            worldObject.Toggle(IsEnabled(worldObject.transform, worldObject.Distance));
                        }
                    }
                    catch (Exception ex)
                    {
                        ExceptionManager.New(ex, false, "WORLD_OBJECT_TOGGLE_ERROR");
                    }
                }

                // Safe mode prevents toggling elemenets that MAY case some issues (vehicles, items, etc.)
                if (MopSettings.Mode == PerformanceMode.Safe)
                {
                    yield return(new WaitForSeconds(.7f));

                    continue;
                }

                // So we create two separate lists - one is meant to enable, and second is ment to disable them,
                // Why?
                // If we enable items before enabling vehicle inside of which these items are supposed to be, they'll fall through to ground.
                // And the opposite happens if we disable vehicles before disabling items.
                // So if we are disabling items, we need to do that BEFORE we disable vehicles.
                // And we need to enable items AFTER we enable vehicles.
                itemsToEnable.Clear();
                itemsToDisable.Clear();
                half = ItemsManager.Instance.Count >> 1;
                for (i = 0; i < ItemsManager.Instance.Count; ++i)
                {
                    if (i == half)
                    {
                        yield return(null);
                    }

                    // Safe check if somehow the i gets bigger than array length.
                    if (i >= ItemsManager.Instance.Count)
                    {
                        break;
                    }

                    try
                    {
                        ItemBehaviour item = ItemsManager.Instance[i];

                        if (item == null || item.gameObject == null)
                        {
                            itemsToRemove.Add(item);
                            continue;
                        }

                        // Check the mode in what MOP is supposed to run and adjust to it.
                        bool toEnable = true;
                        if (MopSettings.Mode == 0)
                        {
                            toEnable = IsEnabled(item.transform, FsmManager.IsPlayerInCar() && !isPlayerAtYard ? 20 : 150);
                        }
                        else
                        {
                            toEnable = IsEnabled(item.transform, 150);
                        }

                        if (toEnable)
                        {
                            item.ToggleChangeFix();
                            if (item.ActiveSelf)
                            {
                                continue;
                            }
                            itemsToEnable.Add(item);
                        }
                        else
                        {
                            if (!item.ActiveSelf)
                            {
                                continue;
                            }
                            itemsToDisable.Add(item);
                        }

                        if (item.rb != null && item.rb.IsSleeping())
                        {
                            if (item.IsPartMagnetAttached())
                            {
                                continue;
                            }
                            if (CompatibilityManager.IsInBackpack(item))
                            {
                                continue;
                            }
                            item.rb.isKinematic = true;
                        }
                    }
                    catch (Exception ex)
                    {
                        ExceptionManager.New(ex, false, "ITEM_TOGGLE_GATHER_ERROR");
                    }
                }

                // Items To Disable
                int full = itemsToDisable.Count;
                if (full > 0)
                {
                    half = itemsToDisable.Count >> 1;
                    for (i = 0; i < full; ++i)
                    {
                        if (half != 0 && i == half)
                        {
                            yield return(null);
                        }

                        try
                        {
                            itemsToDisable[i].Toggle(false);
                        }
                        catch (Exception ex)
                        {
                            ExceptionManager.New(ex, false, "ITEM_TOGGLE_DISABLE_ERROR - " + itemsToDisable[i] != null ? itemsToDisable[i].gameObject.name : "null");
                        }
                    }
                }

                // Vehicles (new)
                half = vehicleManager.Count >> 1;
                for (i = 0; i < vehicleManager.Count; ++i)
                {
                    if (half != 0 && i == half)
                    {
                        yield return(null);
                    }

                    try
                    {
                        if (vehicleManager[i] == null)
                        {
                            vehicleManager.RemoveAt(i);
                            continue;
                        }

                        float distance       = Vector3.Distance(player.transform.position, vehicleManager[i].transform.position);
                        float toggleDistance = MOP.ActiveDistance.Value == 0
                            ? MopSettings.UnityCarActiveDistance : MopSettings.UnityCarActiveDistance * MopSettings.ActiveDistanceMultiplicationValue;

                        switch (vehicleManager[i].VehicleType)
                        {
                        case VehiclesTypes.Satsuma:
                            Satsuma.Instance.ToggleElements(distance);
                            vehicleManager[i].ToggleEventSounds(distance < 3);
                            break;

                        case VehiclesTypes.Jonnez:
                            vehicleManager[i].ToggleEventSounds(distance < 2);
                            break;
                        }

                        vehicleManager[i].ToggleUnityCar(IsVehiclePhysicsEnabled(distance, toggleDistance));
                        vehicleManager[i].Toggle(IsVehicleEnabled(distance));
                    }
                    catch (Exception ex)
                    {
                        ExceptionManager.New(ex, false, $"VEHICLE_TOGGLE_ERROR_{i}");
                    }
                }

                // Items To Enable
                full = itemsToEnable.Count;
                if (full > 0)
                {
                    half = full >> 1;
                    for (i = 0; i < full; ++i)
                    {
                        if (half != 0 && i == half)
                        {
                            yield return(null);
                        }

                        try
                        {
                            itemsToEnable[i].Toggle(true);
                        }
                        catch (Exception ex)
                        {
                            ExceptionManager.New(ex, false, "ITEM_TOGGLE_ENABLE_ERROR - " + itemsToEnable[i] != null ? itemsToDisable[i].gameObject.name : "null");
                        }
                    }
                }

                // Places (New)
                full = placeManager.Count;
                half = full >> 1;
                for (i = 0; i < full; ++i)
                {
                    if (i == half)
                    {
                        yield return(null);
                    }

                    try
                    {
                        if (SectorManager.Instance.IsPlayerInSector() && SectorManager.Instance.SectorRulesContains(placeManager[i].GetName()))
                        {
                            continue;
                        }

                        placeManager[i].ToggleActive(IsPlaceEnabled(placeManager[i].transform, placeManager[i].GetToggleDistance()));
                    }
                    catch (Exception ex)
                    {
                        ExceptionManager.New(ex, false, $"PLACE_TOGGLE_ERROR_{i}");
                    }
                }

                // Remove items that don't exist anymore.
                if (itemsToRemove.Count > 0)
                {
                    for (i = itemsToRemove.Count - 1; i >= 0; --i)
                    {
                        ItemsManager.Instance.RemoveAt(i);
                    }

                    itemsToRemove.Clear();
                }

                yield return(new WaitForSeconds(.7f));

                if (retries > 0 && !restartSucceedMessaged)
                {
                    restartSucceedMessaged = true;
                    ModConsole.Log("<color=green>[MOP] Restart succeeded!</color>");
                }
            }
        }