Skip to content

Instantly share code, notes, and snippets.

@NomadWithoutAHome
Created April 10, 2025 17:57
Show Gist options
  • Save NomadWithoutAHome/1fc4a18624eb42edff36e7551776ffd4 to your computer and use it in GitHub Desktop.
Save NomadWithoutAHome/1fc4a18624eb42edff36e7551776ffd4 to your computer and use it in GitHub Desktop.
Schedule 1
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}");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment