Загрузка данных
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using UnityEngine;
using UnityEngine.SceneManagement;
[BepInPlugin("my.cheatmenu", "CheatMenu", "1.7")]
public class Plugin : BasePlugin
{
public static ManualLogSource L;
public override void Load()
{
L = Log;
ClassInjector.RegisterTypeInIl2Cpp<MenuBehaviour>();
AddComponent<MenuBehaviour>();
Log.LogInfo("CheatMenu loaded, press Insert");
}
}
public class MenuBehaviour : MonoBehaviour
{
public MenuBehaviour(IntPtr ptr) : base(ptr) { }
bool open, fly, stamina;
float flySpeed = 15f;
Transform player;
CharacterController cc;
Rigidbody rb;
int scenePage = 0;
float nextApply;
// режим шахеда
bool drone, exploding;
float droneSpeed = 30f, crashSpeed = 20f, spinSpeed = 360f;
float droneStartTime, respawnAt, explodeTime = -100f;
Vector3 startPos;
GameObject flash;
AudioClip boomClip, buzzClip, musicClip;
AudioSource buzzSrc, musicSrc, remoteBuzz, remoteMusic;
string lastHit = "-";
string soundStatus = "звуки не загружены";
string statsStatus = "";
// размеры, выбор, грабители
Transform sel;
string selInfo = "Выбрано: ничего";
float selfScale = 1f, selScale = 1f, robberScale = 1f;
string robberKey = "robber";
string lastRobberKey = null;
bool aiOff;
int robbersFound = 0;
float nextRobber;
// список объектов
string filter = "";
string lastFilter = null;
bool rootOnly = true;
bool lastRootOnly = true;
int listOffset = 0;
int listRows = 18;
Rect listRect = new Rect(0, 0, 0, 0);
string spawnStatus = "";
// свой ввод текста: 0 нет, 1 поиск, 2 имя грабителя, 3 IP друга
int focus = 0;
static readonly List<GameObject> found = new List<GameObject>();
static readonly List<string> foundLabels = new List<string>();
static readonly Dictionary<int, Vector3> origScale = new Dictionary<int, Vector3>();
static readonly List<Behaviour> disabledAI = new List<Behaviour>();
static readonly HashSet<string> guiErrors = new HashSet<string>();
// сеть
static UdpClient udp;
static Thread thr;
static volatile bool netOn;
static string friendIp = "";
static int netPort = 27777;
static string netStatus = "выключена";
static readonly ConcurrentQueue<string> inbox = new ConcurrentQueue<string>();
// стамина
static Assembly gameAsm;
static readonly Dictionary<string, Type> typeCache = new Dictionary<string, Type>();
static readonly Dictionary<string, double> best = new Dictionary<string, double>();
static readonly HashSet<string> loggedSet = new HashSet<string>();
static readonly string[] StaminaWords = { "stamina", "energy" };
static readonly string[] BadWords = { "regen", "rate", "damage", "cost", "drain", "speed", "time", "delay", "max", "min", "percent", "ratio", "fov", "view", "camera", "zoom", "field", "bar", "text", "ui", "image", "slider" };
// ---------- звук ----------
bool ClipOk(AudioClip c)
{
if (c == null) return false;
try { return c.length > 0f; } catch { return false; }
}
void EnsureSounds()
{
if (!ClipOk(boomClip)) boomClip = LoadWav("boom.wav");
if (!ClipOk(boomClip)) { boomClip = MakeBoom(); }
if (!ClipOk(buzzClip)) buzzClip = LoadWav("buzz.wav");
if (!ClipOk(musicClip)) musicClip = LoadWav("music.wav");
soundStatus = "boom:" + (ClipOk(boomClip) ? "ok" : "нет")
+ " buzz:" + (ClipOk(buzzClip) ? "ok" : "нет")
+ " music:" + (ClipOk(musicClip) ? "ok" : "нет");
}
AudioClip MakeClip(string name, float[] d, int ch, int rate)
{
var clip = AudioClip.Create(name, d.Length / ch, ch, rate, false);
clip.SetData((Il2CppStructArray<float>)d, 0);
clip.hideFlags = HideFlags.HideAndDontSave;
return clip;
}
AudioClip MakeBoom()
{
try
{
int rate = 22050, n = rate * 2;
var d = new float[n];
var r = new System.Random(1);
for (int i = 0; i < n; i++)
{
float t = (float)i / rate;
d[i] = ((float)r.NextDouble() * 2f - 1f) * Mathf.Exp(-t * 3f) * 0.9f;
}
return MakeClip("boom_gen", d, 1, rate);
}
catch (Exception e) { Plugin.L.LogInfo("MakeBoom error: " + e.Message); return null; }
}
AudioClip LoadWav(string name)
{
try
{
using (var s = Assembly.GetExecutingAssembly().GetManifestResourceStream(name))
{
if (s == null) { Plugin.L.LogInfo("No embedded sound: " + name); return null; }
var ms = new MemoryStream();
s.CopyTo(ms);
byte[] b = ms.ToArray();
int pos = 12, ch = 1, rate = 44100, bits = 16, fmt = 1, dataPos = -1, dataLen = 0;
while (pos + 8 <= b.Length)
{
string id = Encoding.ASCII.GetString(b, pos, 4);
int size = BitConverter.ToInt32(b, pos + 4);
if (id == "fmt ")
{
fmt = BitConverter.ToInt16(b, pos + 8);
ch = BitConverter.ToInt16(b, pos + 10);
rate = BitConverter.ToInt32(b, pos + 12);
bits = BitConverter.ToInt16(b, pos + 22);
}
else if (id == "data") { dataPos = pos + 8; dataLen = Math.Min(size, b.Length - dataPos); break; }
pos += 8 + size + (size % 2);
}
if (dataPos < 0) { Plugin.L.LogInfo(name + ": no data chunk"); return null; }
if (fmt != 1 && fmt != 65534) { Plugin.L.LogInfo(name + ": unsupported format " + fmt + " (need PCM)"); return null; }
if (bits != 16) { Plugin.L.LogInfo(name + ": need 16-bit, got " + bits); return null; }
int samples = dataLen / 2;
var f = new float[samples];
for (int i = 0; i < samples; i++) f[i] = BitConverter.ToInt16(b, dataPos + i * 2) / 32768f;
var clip = MakeClip(name, f, ch, rate);
Plugin.L.LogInfo("Loaded sound: " + name + " (" + ch + "ch, " + rate + "Hz, " + samples + " samples)");
return clip;
}
}
catch (Exception e) { Plugin.L.LogInfo("LoadWav error (" + name + "): " + e.Message); return null; }
}
AudioSource MakeLoopSource(string name, AudioClip clip, float volume)
{
var g = new GameObject(name);
UnityEngine.Object.DontDestroyOnLoad(g);
var src = g.AddComponent<AudioSource>();
src.clip = clip;
src.loop = true;
src.spatialBlend = 0f;
src.volume = volume;
src.ignoreListenerPause = true;
src.Play();
return src;
}
void KillSource(ref AudioSource src)
{
if (src == null) return;
try { src.Stop(); UnityEngine.Object.Destroy(src.gameObject); } catch { }
src = null;
}
void StopDroneSounds()
{
KillSource(ref buzzSrc);
KillSource(ref musicSrc);
}
void PlayMusic()
{
EnsureSounds();
StopDroneSounds();
if (ClipOk(buzzClip)) buzzSrc = MakeLoopSource("DroneBuzz", buzzClip, 1f);
if (ClipOk(musicClip)) musicSrc =