Skip to content

Instantly share code, notes, and snippets.

@NomadWithoutAHome
Created April 10, 2025 17:57
Show Gist options
  • Select an option

  • Save NomadWithoutAHome/1fc4a18624eb42edff36e7551776ffd4 to your computer and use it in GitHub Desktop.

Select an option

Save NomadWithoutAHome/1fc4a18624eb42edff36e7551776ffd4 to your computer and use it in GitHub Desktop.

Revisions

  1. NomadWithoutAHome created this gist Apr 10, 2025.
    225 changes: 225 additions & 0 deletions core.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,225 @@
    using MelonLoader;
    using UnityEngine;
    using UnityEngine.UI;
    using TMPro;
    using UnityEngine.EventSystems;

    [assembly: MelonInfo(typeof(DohmStashRehydrated.Core), "DohmStashRehydrated", "1.0.0", "DohmBoy64bit", null)]
    [assembly: MelonGame("TVGS", "Schedule I")]

    namespace DohmStashRehydrated
    {
    public class Core : MelonMod
    {
    public static bool policeDisabled = false;
    private bool menuInitialized = false;
    private bool menuVisible = false;
    private GameObject menuObject;
    private EventSystem eventSystem;
    private CanvasScaler canvasScaler;
    private List<GameObject> categoryPanels = new List<GameObject>();

    public override void OnInitializeMelon()
    {
    MelonLogger.Msg("[DohmStash] Initializing mod...");
    }

    public override void OnUpdate()
    {
    if (Input.GetKeyDown(KeyCode.F1))
    {
    if (!menuInitialized)
    {
    InitializeMenu();
    }
    else
    {
    ToggleMenu();
    }
    }
    }

    private void InitializeMenu()
    {
    try
    {
    MelonLogger.Msg("[DohmStash] Creating menu...");

    // Create EventSystem for mouse input
    eventSystem = new GameObject("EventSystem").AddComponent<EventSystem>();
    eventSystem.gameObject.AddComponent<StandaloneInputModule>();

    // Create Canvas
    GameObject canvasObj = new GameObject("MenuCanvas");
    Canvas canvas = canvasObj.AddComponent<Canvas>();
    canvas.renderMode = RenderMode.ScreenSpaceOverlay;
    canvas.sortingOrder = 1000;

    // Add CanvasScaler for proper UI scaling
    canvasScaler = canvasObj.AddComponent<CanvasScaler>();
    canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
    canvasScaler.referenceResolution = new Vector2(1920, 1080);
    canvasScaler.matchWidthOrHeight = 0.5f;

    // Create main menu panel
    menuObject = CreatePanel(canvasObj.transform, "MenuPanel", new Vector2(400, 600), new Vector2(0, 0));
    menuObject.SetActive(false);

    // Create header
    GameObject header = CreatePanel(menuObject.transform, "Header", new Vector2(400, 50), new Vector2(0, 275));
    header.GetComponent<Image>().color = new Color(0.1f, 0.1f, 0.1f, 0.95f);
    CreateText(header.transform, "Title", "DohmStash Menu", 24, TextAlignmentOptions.Center, new Vector2(0, 0));

    // Create close button
    GameObject closeButton = CreateButton(header.transform, "CloseButton", new Vector2(40, 40), new Vector2(180, 0));
    closeButton.GetComponent<Image>().color = new Color(0.8f, 0.2f, 0.2f, 0.95f);
    CreateText(closeButton.transform, "CloseText", "X", 20, TextAlignmentOptions.Center, new Vector2(0, 0));
    closeButton.GetComponent<Button>().onClick.AddListener(() => ToggleMenu());

    // Create category buttons container
    GameObject categoryButtons = CreatePanel(menuObject.transform, "CategoryButtons", new Vector2(120, 500), new Vector2(-140, 0));
    categoryButtons.GetComponent<Image>().color = new Color(0.15f, 0.15f, 0.15f, 0.95f);

    // Create content area
    GameObject contentArea = CreatePanel(menuObject.transform, "ContentArea", new Vector2(260, 500), new Vector2(70, 0));
    contentArea.GetComponent<Image>().color = new Color(0.1f, 0.1f, 0.1f, 0.95f);

    // Create categories
    CreateCategory("Police", categoryButtons.transform, contentArea.transform, new Vector2(0, 200));
    CreateCategory("Player", categoryButtons.transform, contentArea.transform, new Vector2(0, 150));
    CreateCategory("World", categoryButtons.transform, contentArea.transform, new Vector2(0, 100));
    CreateCategory("Settings", categoryButtons.transform, contentArea.transform, new Vector2(0, 50));

    // Initialize first category
    if (categoryPanels.Count > 0)
    {
    categoryPanels[0].SetActive(true);
    }

    menuInitialized = true;
    MelonLogger.Msg("[DohmStash] Menu created successfully");
    }
    catch (System.Exception e)
    {
    MelonLogger.Error($"[DohmStash] Failed to create menu: {e}");
    }
    }

    private void CreateCategory(string name, Transform buttonParent, Transform contentParent, Vector2 buttonPosition)
    {
    // Create category button
    GameObject button = CreateButton(buttonParent, $"{name}Button", new Vector2(100, 40), buttonPosition);
    button.GetComponent<Image>().color = new Color(0.2f, 0.2f, 0.2f, 0.95f);
    CreateText(button.transform, "ButtonText", name, 16, TextAlignmentOptions.Center, new Vector2(0, 0));

    // Create category content panel
    GameObject contentPanel = CreatePanel(contentParent, $"{name}Content", new Vector2(240, 480), new Vector2(0, 0));
    contentPanel.SetActive(false);
    categoryPanels.Add(contentPanel);

    // Add content to the panel
    if (name == "Police")
    {
    CreatePoliceContent(contentPanel.transform);
    }

    // Add button click handler
    button.GetComponent<Button>().onClick.AddListener(() => {
    foreach (var panel in categoryPanels)
    {
    panel.SetActive(false);
    }
    contentPanel.SetActive(true);
    });
    }

    private void CreatePoliceContent(Transform parent)
    {
    // Create police toggle
    GameObject toggleContainer = CreatePanel(parent, "PoliceToggle", new Vector2(220, 40), new Vector2(0, 200));
    toggleContainer.GetComponent<Image>().color = new Color(0.15f, 0.15f, 0.15f, 0.95f);

    GameObject toggle = CreateToggle(toggleContainer.transform, "Toggle", new Vector2(30, 30), new Vector2(-80, 0));
    CreateText(toggleContainer.transform, "ToggleText", "Disable Police", 16, TextAlignmentOptions.Left, new Vector2(40, 0));

    Toggle toggleComponent = toggle.GetComponent<Toggle>();
    toggleComponent.isOn = policeDisabled;
    toggleComponent.onValueChanged.AddListener((value) => {
    policeDisabled = value;
    MelonLogger.Msg($"[DohmStash] Police disabled state changed to: {value}");
    if (value)
    {
    DeactivateAllPolice();
    }
    });
    }

    private GameObject CreatePanel(Transform parent, string name, Vector2 size, Vector2 position)
    {
    GameObject panel = new GameObject(name);
    panel.transform.SetParent(parent, false);
    RectTransform rect = panel.AddComponent<RectTransform>();
    rect.sizeDelta = size;
    rect.anchoredPosition = position;
    panel.AddComponent<Image>();
    return panel;
    }

    private GameObject CreateButton(Transform parent, string name, Vector2 size, Vector2 position)
    {
    GameObject button = CreatePanel(parent, name, size, position);
    button.AddComponent<Button>();
    return button;
    }

    private GameObject CreateToggle(Transform parent, string name, Vector2 size, Vector2 position)
    {
    GameObject toggle = CreatePanel(parent, name, size, position);
    toggle.AddComponent<Toggle>();
    return toggle;
    }

    private void CreateText(Transform parent, string name, string text, int fontSize, TextAlignmentOptions alignment, Vector2 position)
    {
    GameObject textObj = new GameObject(name);
    textObj.transform.SetParent(parent, false);
    TextMeshProUGUI tmp = textObj.AddComponent<TextMeshProUGUI>();
    tmp.text = text;
    tmp.fontSize = fontSize;
    tmp.alignment = alignment;
    tmp.color = Color.white;
    RectTransform rect = textObj.GetComponent<RectTransform>();
    rect.sizeDelta = new Vector2(200, 30);
    rect.anchoredPosition = position;
    }

    private void ToggleMenu()
    {
    menuVisible = !menuVisible;
    menuObject.SetActive(menuVisible);
    Cursor.lockState = menuVisible ? CursorLockMode.None : CursorLockMode.Locked;
    Cursor.visible = menuVisible;
    }

    private void DeactivateAllPolice()
    {
    try
    {
    int deactivatedCount = 0;
    foreach (var officer in ScheduleOne.Police.PoliceOfficer.Officers)
    {
    if (officer != null)
    {
    officer.Deactivate();
    deactivatedCount++;
    }
    }
    MelonLogger.Msg($"[DohmStash] Deactivated {deactivatedCount} police officers");
    }
    catch (System.Exception e)
    {
    MelonLogger.Error($"[DohmStash] Failed to deactivate police officers: {e}");
    }
    }
    }
    }