class ERR_CommandArguments { static bool Integer(string text, out int value) { if (text.IsEmpty() || text.Length() > 6) return false; for (int i = 0; i < text.Length(); i++) if ("0123456789".IndexOf(text.Substring(i, 1)) < 0) return false; value = text.ToInt(); return true; } static string Setting(string section, string option) { if (section == "hq") { if (option == "interval") return "reportIntervalSeconds"; if (option == "squads") return "supportSquadLimit"; if (option == "radius") return "responseRadiusMetres"; } if (section == "intel") { if (option == "carrying") return "aiIntelChancePercent"; if (option == "reveal") return "intelRevealChancePercent"; } return ""; } } modded class SCR_PlayerController { protected ChatCommandInvoker m_ERRCommand; protected float m_ERRLastRequest = -1000; protected int m_ERRRegisterAttempts; override void OnControlledEntityChanged(IEntity from, IEntity to) { super.OnControlledEntityChanged(from, to); if (this == GetGame().GetPlayerController() && ERR_GameMode.Get()) ERR_Register(); } protected void ERR_Register() { if (m_ERRCommand || m_ERRRegisterAttempts++ > 40) return; SCR_ChatPanelManager manager = SCR_ChatPanelManager.GetInstance(); if (!manager) { GetGame().GetCallqueue().CallLater(ERR_Register, 250, false); return; } m_ERRCommand = manager.GetCommandInvoker("esc"); if (m_ERRCommand) m_ERRCommand.Insert(ERR_OnCommand); } protected override void ERR_OnObserverMonitorStarted() { super.ERR_OnObserverMonitorStarted(); ERR_Register(); } protected void ERR_OnCommand(SCR_ChatPanel panel, string arguments) { string localCommand = arguments.Trim(); localCommand.ToLower(); if (localCommand == "spectate next" || localCommand == "spectate previous") { int direction = 1; if (localCommand == "spectate previous") direction = -1; ERR_CycleObserver(direction); return; } Rpc(ERR_Request, arguments); } [RplRpc(RplChannel.Reliable, RplRcver.Server)] protected void ERR_Request(string arguments) { ERR_GameMode mode = ERR_GameMode.Get(); if (!Replication.IsServer() || !mode || !SCR_Global.IsAdmin(GetPlayerId())) return; float now = GetGame().GetWorld().GetWorldTime(); if (arguments.Length() > 160 || now - m_ERRLastRequest < 250) return; m_ERRLastRequest = now; arguments = arguments.Trim(); arguments.ToLower(); ERR_HQ hq = ERR_HQ.Cast(mode.Command()); if (arguments == "hq show" || arguments == "status") { string status = "HQ unavailable"; if (hq) status = hq.Status(); ERR_Reply(string.Format("Mission phase=%1; %2", mode.Phase(), status)); return; } if (arguments == "hq log") { if (!hq) { ERR_Reply("HQ unavailable"); return; } array lines = {}; int cursor; hq.Journal().Read(Math.Max(0, hq.Journal().Sequence() - 8), lines, cursor); foreach (string line : lines) ERR_Reply(line); return; } array parts = {}; arguments.Split(" ", parts, true); if (parts.Count() == 3 || parts.Count() == 4) { string key = ERR_CommandArguments.Setting(parts[0], parts[1]); if (!key.IsEmpty()) { if (parts.Count() == 3 && parts[2] == "show") { ERR_Reply(key + "=" + mode.Settings().Get(key).ToString()); return; } int value; if (parts.Count() == 4 && parts[2] == "set" && ERR_CommandArguments.Integer(parts[3], value) && mode.Settings().Set(key, value)) ERR_Reply(key + "=" + value.ToString() + " saved"); else ERR_Reply("Invalid value or settings could not be saved; previous setting retained."); return; } } ERR_Reply("/esc status | hq show | hq log | hq interval|squads|radius show|set N | intel carrying|reveal show|set N"); } protected void ERR_Reply(string text) { Rpc(ERR_Response, text); } [RplRpc(RplChannel.Reliable, RplRcver.Owner)] protected void ERR_Response(string text) { SCR_ChatComponent.RadioProtocolMessage(text); } void ~SCR_PlayerController() { if (GetGame()) GetGame().GetCallqueue().Remove(ERR_Register); if (m_ERRCommand) m_ERRCommand.Remove(ERR_OnCommand); } }