专栏文章
作弊器
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mmdaclc7
- 此快照首次捕获于
- 2026/03/05 17:51 5 天前
- 此快照最后确认于
- 2026/03/05 17:51 5 天前
2026年2月24日--OJ运营模拟器 作弊器 v5
用法: F12 → Console → 粘贴整段 → 回车
快捷键:Ctrl + Shift + H 显示/隐藏;Esc 立即隐藏
OJ 作弊器 v5代码
JAVASCRIPT(() => {
const HOTKEY_TOGGLE = { ctrl: true, shift: true, key: "H" };
const HOTKEY_HIDE = { key: "Escape" };
if (window.__OJ_CHEAT_PANEL_V5__) {
window.__OJ_CHEAT_PANEL_V5__.toggle?.();
console.log("[OJ Cheat] v5 已存在:已切换显示。");
return;
}
const resolveGlobals = () => {
let G, U;
try { G = (typeof game !== "undefined") ? game : undefined; } catch { G = undefined; }
try { U = (typeof ui !== "undefined") ? ui : undefined; } catch { U = undefined; }
if (!G) G = window.game;
if (!U) U = window.ui;
return { G, U };
};
const mustHaveGlobals = () => {
const { G, U } = resolveGlobals();
if (!G || !U) {
toast("未检测到 game/ui:请确认已进入游戏页面且脚本加载完成(建议刷新后再执行)。", "bad");
return false;
}
return true;
};
const css = (el, obj) => Object.assign(el.style, obj);
const h = (tag, attrs = {}, children = []) => {
const el = document.createElement(tag);
for (const [k, v] of Object.entries(attrs)) {
if (k === "style") css(el, v);
else if (k.startsWith("on") && typeof v === "function") el[k] = v;
else if (k === "class") el.className = v;
else el.setAttribute(k, v);
}
for (const c of children) el.appendChild(typeof c === "string" ? document.createTextNode(c) : c);
return el;
};
const parseNum = (s) => {
if (s == null) return NaN;
const t = String(s).trim().replaceAll(",", "");
if (!t) return NaN;
const n = Number(t);
return Number.isFinite(n) ? n : NaN;
};
const getRoot = (name) => {
const { G, U } = resolveGlobals();
if (name === "game") return G;
if (name === "ui") return U;
if (name === "window") return window;
if (name === "globalThis") return globalThis;
return undefined;
};
const getPath = (path) => {
const seg = path.split(".");
let cur = getRoot(seg[0]);
if (cur == null) return undefined;
for (let i = 1; i < seg.length; i++) {
cur = cur?.[seg[i]];
if (cur == null && i !== seg.length - 1) return undefined;
}
return cur;
};
const setPath = (path, value) => {
const seg = path.split(".");
let cur = getRoot(seg[0]);
if (cur == null) return false;
for (let i = 1; i < seg.length - 1; i++) {
cur = cur?.[seg[i]];
if (cur == null) return false;
}
const last = seg[seg.length - 1];
if (cur == null) return false;
cur[last] = value;
return true;
};
const addPath = (path, delta) => {
const old = getPath(path);
if (!Number.isFinite(old)) return false;
return setPath(path, old + delta);
};
const LOCKS = new Map(); // path -> number
let patchedUpdate = false;
const applyLocks = () => {
for (const [path, val] of LOCKS.entries()) {
setPath(path, val);
}
};
const patchUiUpdateOnce = () => {
if (patchedUpdate) return;
const { U } = resolveGlobals();
if (!U?.update || typeof U.update !== "function") return;
const original = U.update.bind(U);
U.update = function(...args) {
const ret = original(...args);
try { applyLocks(); } catch {}
try { original(...args); } catch {}
return ret;
};
patchedUpdate = true;
};
const safeUpdate = () => {
const { U } = resolveGlobals();
patchUiUpdateOnce();
try { U?.update?.(); } catch {}
try { U?.renderRD?.(); } catch {}
try { U?.renderClasses?.(); } catch {}
};
const mountWhenReady = (fn) => {
if (document.body) fn();
else window.addEventListener("DOMContentLoaded", fn, { once: true });
};
const style = h("style", {}, [`
#oj-cheat-v5{
position: fixed;
top: 92px;
right: 22px;
width: 420px;
height: 560px;
z-index: 2147483647;
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji";
color: rgba(20,23,30,.92);
}
#oj-cheat-v5 *{ box-sizing: border-box; }
#oj-cheat-v5 .card{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
border-radius: 18px;
border: 1px solid rgba(15,23,42,.10);
background: linear-gradient(180deg, rgba(255,255,255,.92), rgba(248,250,252,.88));
box-shadow:
0 28px 80px rgba(2,6,23,.18),
0 6px 16px rgba(2,6,23,.10);
backdrop-filter: blur(10px);
overflow: hidden;
resize: both;
min-width: 360px;
min-height: 420px;
}
#oj-cheat-v5 .hdr{
display:flex; justify-content:space-between; align-items:center;
padding:12px 12px 10px 12px;
user-select:none;
cursor: move;
background: linear-gradient(135deg, rgba(59,130,246,.10), rgba(236,72,153,.08));
border-bottom: 1px solid rgba(15,23,42,.08);
}
#oj-cheat-v5 .title b{
font-size: 14px;
letter-spacing: .2px;
display: block;
}
#oj-cheat-v5 .subtitle{
font-size: 11px;
margin-top: 2px;
color: rgba(15,23,42,.58);
}
#oj-cheat-v5 .chipRow{ display:flex; gap:6px; margin-top:8px; flex-wrap:wrap; }
#oj-cheat-v5 .chip{
font-size:11px;
padding:3px 8px;
border-radius:999px;
border:1px solid rgba(15,23,42,.10);
background: rgba(255,255,255,.70);
color: rgba(15,23,42,.70);
}
#oj-cheat-v5 .body{
padding:12px;
overflow:auto;
flex: 1;
}
#oj-cheat-v5 .sec{
border:1px solid rgba(15,23,42,.08);
background: rgba(255,255,255,.70);
border-radius:16px;
padding:10px;
margin-top:10px;
}
#oj-cheat-v5 .sec:first-child{ margin-top:0; }
#oj-cheat-v5 h4{
margin:0 0 8px 0;
font-size:12px;
letter-spacing:.2px;
color: rgba(15,23,42,.88);
display:flex; align-items:center; justify-content:space-between;
}
#oj-cheat-v5 .hint{
margin-top:8px;
font-size:11px;
color: rgba(15,23,42,.55);
line-height:1.35;
}
#oj-cheat-v5 .grid{
display:grid;
grid-template-columns: 1fr 152px;
gap:10px;
align-items:start;
margin-bottom:10px;
}
#oj-cheat-v5 .row{
display:grid;
grid-template-columns: 92px 1fr;
gap:8px;
align-items:center;
}
#oj-cheat-v5 .label{
font-size:12px;
color: rgba(15,23,42,.72);
}
#oj-cheat-v5 input{
width:100%;
padding:9px 10px;
border-radius:12px;
border:1px solid rgba(15,23,42,.10);
background: rgba(255,255,255,.90);
color: rgba(15,23,42,.92);
outline:none;
font-size:12px;
}
#oj-cheat-v5 input:focus{
border-color: rgba(59,130,246,.35);
box-shadow: 0 0 0 3px rgba(59,130,246,.12);
}
#oj-cheat-v5 .btn{
border:1px solid rgba(15,23,42,.10);
background: rgba(255,255,255,.92);
color: rgba(15,23,42,.88);
padding:8px 10px;
border-radius:12px;
font-size:12px;
cursor:pointer;
transition: transform .06s ease, box-shadow .15s ease, border-color .15s ease;
box-shadow: 0 2px 8px rgba(2,6,23,.05);
}
#oj-cheat-v5 .btn:hover{ border-color: rgba(15,23,42,.18); box-shadow: 0 6px 18px rgba(2,6,23,.08); }
#oj-cheat-v5 .btn:active{ transform: translateY(1px); }
#oj-cheat-v5 .btn.primary{
background: rgba(59,130,246,.10);
border-color: rgba(59,130,246,.18);
}
#oj-cheat-v5 .btn.good{
background: rgba(16,185,129,.10);
border-color: rgba(16,185,129,.18);
}
#oj-cheat-v5 .btn.bad{
background: rgba(239,68,68,.10);
border-color: rgba(239,68,68,.18);
}
#oj-cheat-v5 .btn.ghost{
background: rgba(255,255,255,.65);
}
#oj-cheat-v5 .btnbar{ display:flex; gap:8px; flex-wrap:wrap; }
#oj-cheat-v5 .footer{
padding:10px 12px;
border-top: 1px solid rgba(15,23,42,.08);
background: rgba(255,255,255,.72);
display:flex;
justify-content:space-between;
align-items:center;
gap:10px;
}
#oj-cheat-v5 .kbd{
font-size:11px;
color: rgba(15,23,42,.55);
display:flex; gap:6px; align-items:center; flex-wrap:wrap;
}
#oj-cheat-v5 .kbd code{
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
font-size:11px;
padding:2px 6px;
border-radius:8px;
border:1px solid rgba(15,23,42,.10);
background: rgba(255,255,255,.85);
color: rgba(15,23,42,.72);
}
#oj-cheat-v5 .toast{
margin-top:8px;
padding:8px 10px;
border-radius:12px;
font-size:12px;
line-height:1.35;
border:1px solid rgba(15,23,42,.10);
background: rgba(255,255,255,.78);
}
#oj-cheat-v5 .meta{
margin-top:6px;
display:flex;
gap:10px;
flex-wrap:wrap;
font-size:11px;
color: rgba(15,23,42,.58);
}
#oj-cheat-v5 .mono{
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
}
#oj-cheat-v5 .preview{
margin-top:6px;
font-size:11px;
color: rgba(15,23,42,.62);
display:flex;
gap:8px;
align-items:center;
flex-wrap:wrap;
}
#oj-cheat-v5 .pill{
padding:2px 7px;
border-radius: 999px;
border:1px solid rgba(15,23,42,.10);
background: rgba(255,255,255,.85);
}
#oj-cheat-v5 .pill.locked{
border-color: rgba(59,130,246,.22);
background: rgba(59,130,246,.10);
color: rgba(30,64,175,.85);
}
`]);
// ------- toast -------
let toastArea;
const toast = (msg, type = "info") => {
if (!toastArea) return;
const map = {
info: { bd: "rgba(59,130,246,.22)", bg: "rgba(59,130,246,.08)" },
ok: { bd: "rgba(16,185,129,.20)", bg: "rgba(16,185,129,.08)" },
warn: { bd: "rgba(245,158,11,.22)", bg: "rgba(245,158,11,.08)" },
bad: { bd: "rgba(239,68,68,.22)", bg: "rgba(239,68,68,.08)" },
};
const c = map[type] || map.info;
const t = h("div", { class: "toast", style: { borderColor: c.bd, background: c.bg } }, [msg]);
toastArea.appendChild(t);
setTimeout(() => t.remove(), 2400);
};
// ------- panel builder -------
mountWhenReady(() => {
document.head.appendChild(style);
const root = h("div", { id: "oj-cheat-v5" });
const card = h("div", { class: "card" });
const btnFold = h("button", { class: "btn ghost", title: "折叠/展开" }, ["折叠"]);
const btnHide = h("button", { class: "btn bad", title: "隐藏(Ctrl+Shift+H 可恢复)" }, ["隐藏"]);
const header = h("div", { class: "hdr" }, [
h("div", { class: "title" }, [
h("b", {}, ["🧪 作弊器 v5"]),
h("div", { class: "subtitle" }, ["来自Trie2025(uid:1271480)"]),
h("div", { class: "chipRow" }, [
h("span", { class: "chip" }, ["设置/增量"]),
h("span", { class: "chip" }, ["原值→新值预览"]),
h("span", { class: "chip" }, ["字段锁定"])
])
]),
h("div", { style: { display: "flex", gap: "8px" } }, [btnFold, btnHide])
]);
const body = h("div", { class: "body" });
toastArea = h("div");
// --- value line helpers ---
const makeCurrent = (path) => {
const el = h("span", { class: "mono" }, ["—"]);
const refresh = () => {
const v = getPath(path);
el.textContent = (v === undefined) ? "undefined" : String(v);
};
refresh();
return { el, refresh };
};
const makeSetterSection = ({ title, icon, items }) => {
const sec = h("div", { class: "sec" }, [
h("h4", {}, [
`${icon} ${title}`,
h("span", { style: { fontSize: "11px", color: "rgba(15,23,42,.55)" } }, ["(设置=覆盖,增量=加/减)"])
])
]);
const refreshers = [];
for (const it of items) {
const current = makeCurrent(it.path);
refreshers.push(current.refresh);
const inp = h("input", { placeholder: it.placeholder ?? "如:1e6 / -250 / 0.5 / 1,000,000" });
const preview = h("div", { class: "preview" }, [
h("span", { class: "pill" }, ["原值"]),
h("span", { class: "mono" }, ["—"]),
h("span", { class: "pill" }, ["→"]),
h("span", { class: "pill" }, ["新值"]),
h("span", { class: "mono" }, ["—"])
]);
const [oldEl, newEl] = preview.querySelectorAll(".mono");
const updatePreview = () => {
const oldV = getPath(it.path);
oldEl.textContent = (oldV === undefined) ? "undefined" : String(oldV);
const n = parseNum(inp.value);
newEl.textContent = Number.isFinite(n) ? String(n) : "(无效)";
};
inp.addEventListener("input", updatePreview);
updatePreview();
const lockPill = h("span", { class: "pill" }, ["未锁定"]);
const refreshLockPill = () => {
const locked = LOCKS.has(it.path);
lockPill.textContent = locked ? "已锁定" : "未锁定";
lockPill.classList.toggle("locked", locked);
};
refreshLockPill();
const btnSet = h("button", {
class: "btn primary",
onclick: () => {
if (!mustHaveGlobals()) return;
const v = parseNum(inp.value);
if (!Number.isFinite(v)) return toast(`【${it.name}】输入无效:${inp.value}`, "bad");
const ok = setPath(it.path, v);
if (!ok) return toast(`无法写入:${it.path}`, "bad");
// 如果已锁定,同步锁定值
if (LOCKS.has(it.path)) LOCKS.set(it.path, v);
safeUpdate();
current.refresh();
updatePreview();
toast(`已设置【${it.name}】= ${v}`, "ok");
}
}, ["设置"]);
const btnAdd = h("button", {
class: "btn",
onclick: () => {
if (!mustHaveGlobals()) return;
const d = parseNum(inp.value);
if (!Number.isFinite(d)) return toast(`【${it.name}】增量无效:${inp.value}`, "bad");
const ok = addPath(it.path, d);
if (!ok) return toast(`无法累加(目标不是数值?)${it.path}`, "bad");
// 如果已锁定,更新锁定值为“累加后”的真实值
if (LOCKS.has(it.path)) {
const vNow = getPath(it.path);
if (Number.isFinite(vNow)) LOCKS.set(it.path, vNow);
}
safeUpdate();
current.refresh();
updatePreview();
toast(`已对【${it.name}】增量:${d}`, "ok");
}
}, ["增量"]);
const btnLock = h("button", {
class: "btn",
title: "锁定后:每次 ui.update() 都会把该字段回写为锁定值(防 nextMonth / calculateReputation 重算打回)",
onclick: () => {
if (!mustHaveGlobals()) return;
patchUiUpdateOnce();
if (LOCKS.has(it.path)) {
LOCKS.delete(it.path);
refreshLockPill();
toast(`已解除锁定:${it.name}`, "warn");
return;
}
const vNow = getPath(it.path);
if (!Number.isFinite(vNow)) return toast(`无法锁定:当前值不是数值(${it.path})`, "bad");
LOCKS.set(it.path, vNow);
refreshLockPill();
toast(`已锁定:${it.name} = ${vNow}`, "ok");
}
}, ["锁定"]);
const left = h("div", {}, [
h("div", { class: "row" }, [
h("div", { class: "label" }, [it.name]),
inp
]),
h("div", { class: "meta" }, [
h("span", { class: "pill" }, ["当前"]),
h("span", { class: "mono" }, [current.el]),
lockPill
]),
preview
]);
sec.appendChild(
h("div", { class: "grid" }, [
left,
h("div", { style: { display: "flex", gap: "8px", justifyContent: "flex-end", flexWrap: "wrap" } }, [
btnSet, btnAdd, btnLock
])
])
);
}
sec.appendChild(h("div", { class: "hint" }, [
"输入支持:科学计数法(1e6、2.5e3)、逗号(1,000,000)、负数(-1e4)。",
" 若发现“改了马上被打回去”,请对该字段使用【锁定】。"
]));
return { sec, refreshAll: () => refreshers.forEach(fn => fn()) };
};
const sec1 = makeSetterSection({
title: "资源与状态",
icon: "⚙️",
items: [
{ name: "资金", path: "game.money" },
{ name: "AP", path: "game.ap" },
{ name: "研发点", path: "game.resources.rd" },
{ name: "学术点", path: "game.resources.acad" },
{ name: "社区点", path: "game.resources.comm" },
{ name: "声誉", path: "game.stats.reputation", placeholder: "提示:声誉会在 nextMonth() 中重算,建议需要时锁定" }
]
});
const sec2 = makeSetterSection({
title: "用户与题库",
icon: "📊",
items: [
{ name: "普通用户", path: "game.stats.users.normal" },
{ name: "活跃用户", path: "game.stats.users.active" },
{ name: "核心用户", path: "game.stats.users.core" },
{ name: "高质题数", path: "game.stats.problems.high" },
{ name: "普通题数", path: "game.stats.problems.mid" },
{ name: "低质题数", path: "game.stats.problems.low" }
]
});
const secOps = h("div", { class: "sec" }, [
h("h4", {}, ["🧩 判定 / 解锁 / 修复"]),
h("div", { class: "btnbar" }, [
h("button", {
class: "btn good",
onclick: () => {
if (!mustHaveGlobals()) return;
const btn = document.getElementById("next-month-btn");
if (btn) btn.disabled = false;
toast("已解除“进入下个月”按钮禁用(若存在)。", "ok");
}
}, ["解除按钮禁用"]),
h("button", {
class: "btn",
onclick: () => {
if (!mustHaveGlobals()) return;
const { G } = resolveGlobals();
G.stats.consecutive_failure_months = 0;
safeUpdate();
toast("已清零:连续故障月数。", "ok");
}
}, ["清故障月数"]),
h("button", {
class: "btn",
onclick: () => {
if (!mustHaveGlobals()) return;
const { G } = resolveGlobals();
G.stats.comm_fail_months = 0;
safeUpdate();
toast("已清零:社区违规累计月数。", "ok");
}
}, ["清社区违规月数"]),
h("button", {
class: "btn primary",
onclick: () => {
if (!mustHaveGlobals()) return;
const { G } = resolveGlobals();
for (const k in G.features_unlocked) G.features_unlocked[k] = true;
safeUpdate();
toast("已全部解锁功能(features_unlocked)。", "ok");
}
}, ["全部解锁"]),
h("button", {
class: "btn",
onclick: () => {
if (!mustHaveGlobals()) return;
const { G } = resolveGlobals();
if (G.flags) {
G.flags.fundraising_penalty_val = 0;
G.flags.temp_rep_penalty = 0;
}
safeUpdate();
toast("已清除:募捐惩罚/临时声誉惩罚。", "ok");
}
}, ["清惩罚值"]),
h("button", {
class: "btn",
onclick: () => {
LOCKS.clear();
toast("已清空所有锁定字段。", "warn");
}
}, ["清空锁定"])
]),
h("div", { class: "hint" }, [
"说明:锁定机制会在 ui.update() 后自动回写,适合测试“逻辑重算覆盖写”的漏洞面。"
])
]);
body.appendChild(sec1.sec);
body.appendChild(sec2.sec);
body.appendChild(secOps);
body.appendChild(toastArea);
const footer = h("div", { class: "footer" }, [
h("div", { class: "kbd" }, [
"快捷键:",
h("code", {}, ["Ctrl"]), "+", h("code", {}, ["Shift"]), "+", h("code", {}, ["H"]),
"切换;",
h("code", {}, ["Esc"]), "隐藏"
]),
h("div", { style: { display: "flex", gap: "8px" } }, [
h("button", {
class: "btn",
onclick: () => {
if (!mustHaveGlobals()) return;
safeUpdate();
sec1.refreshAll(); sec2.refreshAll();
toast("已刷新 UI & 当前值。", "ok");
}
}, ["刷新UI/值"])
])
]);
card.appendChild(header);
card.appendChild(body);
card.appendChild(footer);
root.appendChild(card);
document.body.appendChild(root);
// ------- fold/hide -------
let folded = false;
const setFold = (v) => {
folded = v;
body.style.display = folded ? "none" : "block";
footer.style.display = folded ? "none" : "flex";
btnFold.textContent = folded ? "展开" : "折叠";
};
btnFold.onclick = () => setFold(!folded);
const setVisible = (v) => { root.style.display = v ? "block" : "none"; };
btnHide.onclick = () => { setVisible(false); toast("面板已隐藏(Ctrl+Shift+H 可恢复)。", "warn"); };
let dragging = false, dx = 0, dy = 0;
header.addEventListener("mousedown", (e) => {
dragging = true;
const rect = root.getBoundingClientRect();
dx = e.clientX - rect.left;
dy = e.clientY - rect.top;
root.style.left = rect.left + "px";
root.style.top = rect.top + "px";
root.style.right = "auto";
e.preventDefault();
});
const onMove = (e) => {
if (!dragging) return;
root.style.left = Math.max(8, e.clientX - dx) + "px";
root.style.top = Math.max(8, e.clientY - dy) + "px";
};
const onUp = () => dragging = false;
document.addEventListener("mousemove", onMove);
document.addEventListener("mouseup", onUp);
// ------- hotkeys -------
const onKeydown = (e) => {
if (
e.ctrlKey === !!HOTKEY_TOGGLE.ctrl &&
e.shiftKey === !!HOTKEY_TOGGLE.shift &&
e.key.toUpperCase() === HOTKEY_TOGGLE.key
) {
e.preventDefault();
setVisible(root.style.display === "none");
return;
}
if (e.key === HOTKEY_HIDE.key) setVisible(false);
};
document.addEventListener("keydown", onKeydown, true);
// ------- expose handle -------
window.__OJ_CHEAT_PANEL_V5__ = {
show() { setVisible(true); },
hide() { setVisible(false); },
toggle() { setVisible(root.style.display === "none"); },
fold(v) { setFold(!!v); },
refresh() { safeUpdate(); sec1.refreshAll(); sec2.refreshAll(); },
locks: LOCKS,
remove() {
try { document.removeEventListener("keydown", onKeydown, true); } catch {}
try { document.removeEventListener("mousemove", onMove); } catch {}
try { document.removeEventListener("mouseup", onUp); } catch {}
root.remove();
delete window.__OJ_CHEAT_PANEL_V5__;
}
};
console.log("[OJ Cheat] v5 已加载:window.__OJ_CHEAT_PANEL_V5__(Ctrl+Shift+H / Esc)");
toast("面板已加载:可拖拽(标题栏)、可拉伸(右下角拖拽/resize)。", "ok");
try { sec1.refreshAll(); sec2.refreshAll(); } catch {}
});
})();
✅ 2026年1月15日--OItrainer 作弊器3.4.1
用法: 安装油猴后,将代码完整复制后,点击新建脚本,覆盖模板代码。
快捷键: Ctrl + Shift + H 显示/隐藏
OItrainer 作弊器3.4.1代码
HTML// ==UserScript==
// @name OItrainer 作弊器3.4.1
// @namespace https://seve42.github.io/OItrainer/
// @version 3.4.1
// @description ---
// @match https://seve42.github.io/OItrainer/game.html*
// @run-at document-end
// @grant unsafeWindow
// ==/UserScript==
(function () {
'use strict';
const W = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;
const REPUTATION_LOCK = 100;
let stressLockEnabled = false;
let timeFrozen = false;
let panelVisible = false;
const state = {
width: 420,
lastRenderSig: '',
hidden: false,
};
const LS_KEY_HIDE_ALL = '__oi_hide_all_ui__';
const BAR_H = 56;
const BAR_TOP = 10;
const GAP = 10;
const PANEL_TOP = BAR_TOP + BAR_H + GAP;
const stressDescStore = new WeakMap();
let weekKey = null;
let frozenWeekValue = null;
let weekOrigDesc = null;
let weekFreezeMode = 'define';
function getWeekKey(game) {
const keys = ['week', 'time', 'turn', 'round'];
for (const k of keys) {
if (k in game && typeof game[k] === 'number') return k;
}
for (const k of Object.keys(game)) {
if (typeof game[k] === 'number' && /week|turn|round|time/i.test(k)) return k;
}
return null;
}
function freezeTime(game) {
if (!weekKey) weekKey = getWeekKey(game);
if (!weekKey) {
toast('未找到周数变量(week/time/turn/round)');
timeFrozen = false;
return;
}
if (frozenWeekValue == null) frozenWeekValue = game[weekKey];
if (weekOrigDesc == null) {
try { weekOrigDesc = Object.getOwnPropertyDescriptor(game, weekKey) || null; } catch { weekOrigDesc = null; }
}
try {
Object.defineProperty(game, weekKey, {
configurable: true,
get() { return frozenWeekValue; },
set(_) {}
});
weekFreezeMode = 'define';
} catch {
weekFreezeMode = 'assign';
try { game[weekKey] = frozenWeekValue; } catch {}
}
timeFrozen = true;
}
function unfreezeTime(game) {
if (!weekKey) weekKey = getWeekKey(game);
if (!weekKey) {
timeFrozen = false;
frozenWeekValue = null;
weekOrigDesc = null;
weekFreezeMode = 'define';
return;
}
try {
if (weekOrigDesc) {
Object.defineProperty(game, weekKey, weekOrigDesc);
} else {
//
try { delete game[weekKey]; } catch {}
if (frozenWeekValue != null) {
try { game[weekKey] = frozenWeekValue; } catch {}
}
}
} catch {
//
}
timeFrozen = false;
frozenWeekValue = null;
weekOrigDesc = null;
weekFreezeMode = 'define';
toast('时间已恢复流动');
}
function loadHideState() {
try {
const v = localStorage.getItem(LS_KEY_HIDE_ALL);
if (v === '1') state.hidden = true;
else if (v === '0') state.hidden = false;
} catch {}
}
function saveHideState() {
try { localStorage.setItem(LS_KEY_HIDE_ALL, state.hidden ? '1' : '0'); } catch {}
}
function waitFor(fn, t = 20000) {
const s = Date.now();
return new Promise((res, rej) => {
const id = setInterval(() => {
try {
if (fn()) { clearInterval(id); res(true); }
else if (Date.now() - s > t) { clearInterval(id); rej(new Error('timeout')); }
} catch {}
}, 50);
});
}
const el = (tag, css, html) => {
const e = document.createElement(tag);
if (css) e.style.cssText = css;
if (html != null) e.innerHTML = html;
return e;
};
const fmt = (n) => {
try { return Number(n).toLocaleString('zh-CN'); } catch { return String(n); }
};
const parseNum = (s) => {
if (s == null) return null;
s = String(s).trim().replace(/[,,\s_]/g, '');
const v = Number(s);
return Number.isFinite(v) ? v : null;
};
function safeText(s) {
return String(s ?? '').replace(/[&<>"']/g, (m) => ({
'&': '&', '<': '<', '>': '>', '"': '"', "'": '''
}[m]));
}
function getBudget(g) { return g.budget ?? g.money ?? g.fund ?? g.cash ?? 0; }
function setBudget(g, v) {
if ('budget' in g) g.budget = v;
else if ('money' in g) g.money = v;
else if ('fund' in g) g.fund = v;
else if ('cash' in g) g.cash = v;
}
function getStudents(g) { return g.students ?? g.studentList ?? g.roster ?? g.players ?? []; }
function getStudentCount(g) { const a = getStudents(g); return Array.isArray(a) ? a.length : 0; }
function trySetRep(g, v) {
const keys = ['reputation', 'rep', 'prestige', 'fame'];
for (const k of keys) { if (k in g) g[k] = v; }
if (g.school) for (const k of keys) { if (k in g.school) g.school[k] = v; }
}
function lockNum(o, k, v) {
try {
Object.defineProperty(o, k, { configurable: true, get() { return v; }, set(_) {} });
o[k] = v;
} catch {}
}
function applyRepLock(g) {
const keys = ['reputation', 'rep', 'prestige', 'fame'];
keys.forEach(k => { if (k in g) lockNum(g, k, REPUTATION_LOCK); });
if (g.school) keys.forEach(k => { if (k in g.school) lockNum(g.school, k, REPUTATION_LOCK); });
trySetRep(g, REPUTATION_LOCK);
}
function initials(name) {
const str = String(name ?? '').trim();
if (!str) return 'S';
const c = str[0];
return c.toUpperCase ? c.toUpperCase() : c;
}
function lockStudentStress(student) {
if (!student || typeof student !== 'object') return;
let stored = stressDescStore.get(student);
if (!stored) {
const hadStress = Object.prototype.hasOwnProperty.call(student, 'stress');
const hadPressure = Object.prototype.hasOwnProperty.call(student, 'pressure');
stored = {
hadStress,
hadPressure,
stress: hadStress ? Object.getOwnPropertyDescriptor(student, 'stress') : null,
pressure: hadPressure ? Object.getOwnPropertyDescriptor(student, 'pressure') : null,
};
stressDescStore.set(student, stored);
}
try { student.stress = 0; } catch {}
try { student.pressure = 0; } catch {}
try { Object.defineProperty(student, 'stress', { configurable: true, get() { return 0; }, set(_) {} }); } catch {}
try { Object.defineProperty(student, 'pressure', { configurable: true, get() { return 0; }, set(_) {} }); } catch {}
}
function unlockStudentStress(student) {
if (!student || typeof student !== 'object') return;
const stored = stressDescStore.get(student);
if (!stored) return;
try {
if (stored.hadStress) {
if (stored.stress) Object.defineProperty(student, 'stress', stored.stress);
else delete student.stress;
} else delete student.stress;
} catch {}
try {
if (stored.hadPressure) {
if (stored.pressure) Object.defineProperty(student, 'pressure', stored.pressure);
else delete student.pressure;
} else delete student.pressure;
} catch {}
stressDescStore.delete(student);
}
function applyStressLock(game) {
const arr = getStudents(game);
for (const s of arr) lockStudentStress(s);
}
function removeStressLock(game) {
const arr = getStudents(game);
for (const s of arr) unlockStudentStress(s);
}
function addStyle() {
const s = el('style', null, `
:root{
--ui-bg: rgba(255,255,255,.92);
--ui-bg2: rgba(245,245,245,.88);
--ui-border: rgba(180,180,180,.28);
--ui-text: #1f1f1f;
--ui-sub: rgba(0,0,0,.58);
--ui-line: rgba(0,0,0,.06);
--ui-shadow: 0 10px 32px rgba(0,0,0,.08);
--ui-shadow2: 0 10px 26px rgba(0,0,0,.10);
--ui-radius: 16px;
--ui-radius2: 12px;
--ui-blur: blur(12px);
--ui-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono","Courier New", monospace;
--bar-top: ${BAR_TOP}px;
--bar-h: ${BAR_H}px;
--panel-top: ${PANEL_TOP}px;
}
#__oi_bar__, #__oi_panel__{
font-family: ui-sans-serif,system-ui,-apple-system,"PingFang SC","Microsoft YaHei",Arial,sans-serif;
color: var(--ui-text);
}
#__oi_bar__{
position: fixed; top: var(--bar-top); left: 10px; right: 10px;
height: var(--bar-h);
display:flex; align-items:center; justify-content:space-between;
padding: 0 14px;
border-radius: var(--ui-radius);
border: 1px solid var(--ui-border);
background: linear-gradient(180deg,var(--ui-bg),var(--ui-bg2));
box-shadow: var(--ui-shadow);
backdrop-filter: var(--ui-blur);
z-index: 99999;
}
#__oi_bar__ .left{
display:flex; align-items:center; gap:10px;
font-weight: 750; letter-spacing:.2px;
}
#__oi_bar__ .badge{
height: 26px; padding: 0 10px;
display:inline-flex; align-items:center; gap:8px;
border: 1px solid var(--ui-border);
border-radius: 999px;
background: rgba(255,255,255,.6);
box-shadow: 0 6px 18px rgba(0,0,0,.04);
font-size: 12.5px;
color: var(--ui-sub);
user-select:none;
}
#__oi_bar__ .money{
font-weight: 900;
font-size: 16px;
letter-spacing: .2px;
font-family: var(--ui-mono);
}
#__oi_bar__ .mid{
display:flex; align-items:center; gap:10px;
min-width: 420px;
justify-content: center;
}
#__oi_bar__ .right{
display:flex; align-items:center; gap:8px;
}
#__oi_bar__ button{
height: 34px; padding: 0 12px;
border-radius: var(--ui-radius2);
border: 1px solid var(--ui-border);
background: rgba(255,255,255,.75);
color: var(--ui-text);
font-size: 13px;
cursor:pointer;
transition: transform .12s ease, background .12s ease, border-color .12s ease, box-shadow .12s ease;
}
#__oi_bar__ button:hover{
background: rgba(255,255,255,.92);
border-color: rgba(120,120,120,.28);
box-shadow: 0 10px 20px rgba(0,0,0,.06);
transform: translateY(-1px);
}
#__oi_bar__ button:active{ transform: translateY(0px); box-shadow: none; }
#__oi_panel__{
position: fixed;
top: var(--panel-top);
right: calc(-1px - var(--panel-w, 420px));
width: var(--panel-w, 420px);
height: calc(100% - var(--panel-top));
z-index: 99998;
border-left: 1px solid var(--ui-border);
background: rgba(255,255,255,.95);
backdrop-filter: var(--ui-blur);
box-shadow: var(--ui-shadow2);
display:flex; flex-direction:column;
transition: right .28s ease;
border-top-left-radius: var(--ui-radius);
border-bottom-left-radius: var(--ui-radius);
overflow: hidden;
}
#__oi_panel__.show{ right: 0; }
#__oi_panel__ .hdr{
padding: 14px 14px 12px 14px;
border-bottom: 1px solid var(--ui-line);
display:flex; align-items:center; justify-content:space-between;
gap: 10px;
background: linear-gradient(180deg, rgba(255,255,255,.92), rgba(245,245,245,.86));
}
#__oi_panel__ .hdr .title{
font-size: 14.5px; font-weight: 800;
display:flex; align-items:center; gap:10px;
}
#__oi_panel__ .hdr .sub{
font-size: 12px; color: var(--ui-sub);
margin-top: 2px;
}
#__oi_panel__ .hdr .actions{
display:flex; align-items:center; gap:8px;
}
#__oi_panel__ .iconbtn{
width: 34px; height: 34px;
border-radius: 12px;
border: 1px solid var(--ui-border);
background: rgba(255,255,255,.75);
cursor:pointer;
display:flex; align-items:center; justify-content:center;
transition: background .12s ease, transform .12s ease;
}
#__oi_panel__ .iconbtn:hover{ background: rgba(255,255,255,.92); transform: translateY(-1px); }
#__oi_panel__ .body{
padding: 12px 12px 14px 12px;
overflow:auto;
flex: 1;
}
.pill{
display:inline-flex; align-items:center; gap:6px;
padding: 2px 8px;
border-radius: 999px;
border: 1px solid var(--ui-border);
background: rgba(255,255,255,.7);
font-size: 12px;
color: var(--ui-sub);
}
.cards{
display:flex;
flex-direction:column;
gap: 10px;
}
.card{
border: 1px solid var(--ui-line);
border-radius: 14px;
background: rgba(255,255,255,.86);
box-shadow: 0 10px 20px rgba(0,0,0,.04);
overflow:hidden;
}
.card:hover{ border-color: rgba(120,120,120,.22); }
.card-h{
display:flex; align-items:center; justify-content:space-between;
gap: 10px;
padding: 10px 10px;
user-select:none;
}
.avatar{
width: 34px; height: 34px;
border-radius: 12px;
border: 1px solid var(--ui-border);
background: linear-gradient(180deg, rgba(255,255,255,.9), rgba(245,245,245,.85));
box-shadow: 0 10px 18px rgba(0,0,0,.04);
display:flex; align-items:center; justify-content:center;
font-weight: 900;
font-family: var(--ui-mono);
color: rgba(0,0,0,.55);
flex: 0 0 auto;
}
.h-main{
display:flex; align-items:center; gap:10px;
min-width: 0;
flex: 1;
}
.name{
font-weight: 850;
font-size: 13.6px;
letter-spacing: .2px;
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
.meta{
display:flex; gap:6px; flex-wrap:wrap;
margin-top: 2px;
}
.chip{
display:inline-flex; align-items:center; gap:6px;
padding: 2px 8px;
border-radius: 999px;
border: 1px solid var(--ui-border);
background: rgba(255,255,255,.72);
color: var(--ui-sub);
font-size: 12px;
}
.v{
font-family: var(--ui-mono);
color: rgba(0,0,0,.70);
}
#__oi_resizer__{
position: fixed;
top: var(--panel-top);
right: calc(var(--panel-w, 420px));
width: 10px;
height: calc(100% - var(--panel-top));
z-index: 99999;
cursor: ew-resize;
display:none;
}
#__oi_resizer__.show{ display:block; }
#__oi_toast__{
position: fixed;
left: 12px;
bottom: 12px;
padding: 10px 12px;
border-radius: 14px;
border: 1px solid var(--ui-border);
background: rgba(255,255,255,.9);
box-shadow: var(--ui-shadow);
backdrop-filter: var(--ui-blur);
color: var(--ui-text);
font-size: 12.5px;
z-index: 100000;
opacity: 0;
transform: translateY(10px);
transition: opacity .18s ease, transform .18s ease;
pointer-events: none;
}
#__oi_toast__.show{ opacity: 1; transform: translateY(0px); }
`);
document.head.appendChild(s);
}
function toast(msg) {
const t = document.getElementById('__oi_toast__');
if (!t) return;
t.textContent = msg;
t.classList.add('show');
clearTimeout(toast._id);
toast._id = setTimeout(() => t.classList.remove('show'), 1100);
}
function ensureToast() {
if (document.getElementById('__oi_toast__')) return;
const t = el('div', '', '');
t.id = '__oi_toast__';
document.body.appendChild(t);
}
function setPanelWidth(px) {
const w = Math.max(320, Math.min(720, px | 0));
state.width = w;
document.documentElement.style.setProperty('--panel-w', `${w}px`);
const r = document.getElementById('__oi_resizer__');
if (r) r.style.right = `${w}px`;
}
function updateVisibility() {
const bar = document.getElementById('__oi_bar__');
const panel = document.getElementById('__oi_panel__');
const resizer = document.getElementById('__oi_resizer__');
const toastEl = document.getElementById('__oi_toast__');
const display = state.hidden ? 'none' : '';
if (bar) bar.style.display = display;
if (panel) panel.style.display = display;
if (resizer) resizer.style.display = state.hidden ? 'none' : (panelVisible ? 'block' : 'none');
if (toastEl) toastEl.style.display = display;
}
function makePanel() {
if (document.getElementById('__oi_panel__')) return;
document.documentElement.style.setProperty('--panel-w', `${state.width}px`);
const panel = el('div', '', '');
panel.id = '__oi_panel__';
panel.innerHTML = `
<div class="hdr">
<div>
<div class="title">
学生
<span class="pill" style="margin-left:6px;">作弊器</span>
<span id="__oi_countpill__" class="pill">0 人</span>
</div>
<div class="sub">拖拽左侧调宽度 · Ctrl+Shift+H 隐藏/显示整个插件</div>
</div>
<div class="actions">
<button class="iconbtn" id="__oi_refresh__">⟳</button>
<button class="iconbtn" id="__oi_close__">✕</button>
</div>
</div>
<div class="body" id="__oi_body__"></div>
`;
document.body.appendChild(panel);
const resizer = el('div', '', '');
resizer.id = '__oi_resizer__';
document.body.appendChild(resizer);
panel.querySelector('#__oi_close__').onclick = () => togglePanel(false);
panel.querySelector('#__oi_refresh__').onclick = () => { state.lastRenderSig = ''; toast('已刷新'); };
let dragging = false, startX = 0, startW = state.width;
const onMove = (e) => {
if (!dragging) return;
const x = e.clientX ?? (e.touches && e.touches[0] && e.touches[0].clientX);
if (typeof x !== 'number') return;
const dx = startX - x;
setPanelWidth(startW + dx);
e.preventDefault?.();
};
const onUp = () => {
if (!dragging) return;
dragging = false;
document.body.style.userSelect = '';
toast(`侧栏宽度:${state.width}px`);
window.removeEventListener('mousemove', onMove);
window.removeEventListener('mouseup', onUp);
window.removeEventListener('touchmove', onMove, { passive: false });
window.removeEventListener('touchend', onUp);
};
const onDown = (e) => {
dragging = true;
startX = e.clientX ?? (e.touches && e.touches[0] && e.touches[0].clientX) ?? 0;
startW = state.width;
document.body.style.userSelect = 'none';
window.addEventListener('mousemove', onMove);
window.addEventListener('mouseup', onUp);
window.addEventListener('touchmove', onMove, { passive: false });
window.addEventListener('touchend', onUp);
e.preventDefault?.();
};
resizer.addEventListener('mousedown', onDown);
resizer.addEventListener('touchstart', onDown, { passive: false });
window.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && panelVisible) togglePanel(false);
});
setPanelWidth(state.width);
}
function togglePanel(on) {
panelVisible = (typeof on === 'boolean') ? on : !panelVisible;
const panel = document.getElementById('__oi_panel__');
const resizer = document.getElementById('__oi_resizer__');
if (!panel || !resizer) return;
if (state.hidden) return;
panel.classList.toggle('show', panelVisible);
resizer.classList.toggle('show', panelVisible);
if (panelVisible) {
state.lastRenderSig = '';
toast('侧栏已打开');
} else {
toast('侧栏已关闭');
}
}
function renderPanel(game) {
if (!panelVisible || state.hidden) return;
const body = document.getElementById('__oi_body__');
const pill = document.getElementById('__oi_countpill__');
if (!body || !pill) return;
const list = getStudents(game);
let sig = `${list.length}|`;
for (let i = 0; i < Math.min(10, list.length); i++) {
const s = list[i] || {};
sig += `${s.name ?? s.nick ?? ''}|${s.stress ?? s.pressure ?? ''}||`;
}
if (sig === state.lastRenderSig) return;
state.lastRenderSig = sig;
pill.textContent = `${list.length} 人`;
const rows = list.map((s, idx) => {
const obj = (s && typeof s === 'object') ? s : {};
const name = (('name' in obj) ? obj.name : (('nick' in obj) ? obj.nick : `学生${idx + 1}`));
const stress = (('stress' in obj) ? obj.stress : (('pressure' in obj) ? obj.pressure : '-'));
return { name, stress };
});
let html = `<div class="cards">`;
for (const r of rows) {
html += `
<div class="card">
<div class="card-h">
<div class="h-main">
<div class="avatar">${safeText(initials(r.name))}</div>
<div style="min-width:0;">
<div class="name">${safeText(r.name)}</div>
<div class="meta">
<span class="chip">压力 <span class="v">${safeText(r.stress)}</span></span>
</div>
</div>
</div>
</div>
</div>
`;
}
html += `</div>`;
body.innerHTML = html;
}
function makeBar(game) {
if (document.getElementById('__oi_bar__')) return;
const bar = el('div', '', '');
bar.id = '__oi_bar__';
const left = el('div', '', `
<div class="left">
<span>作弊器</span>
<span class="badge">声誉锁 100</span>
<span class="badge">
来源:
<a href="https://www.luogu.com.cn/user/1271480"
target="_blank" rel="noopener"
style="color:inherit;text-decoration:none;font-weight:700;">
Trie2025
</a>
</span>
</div>
`);
const mid = el('div', '', `
<div class="mid">
<span class="money" id="__oi_money__">¥0</span>
<span class="badge" id="__oi_info__">学生:0 | 压力锁:关 | 周数:-</span>
</div>
`);
const right = el('div', 'display:flex;align-items:center;gap:8px;', '');
const mkBtn = (txt, fn) => {
const b = el('button', '', txt);
b.onclick = fn;
return b;
};
right.appendChild(mkBtn(' 改经费', () => {
const cur = getBudget(game);
const input = prompt('输入经费(支持科学计数法,如 2e9、1.5e8)', String(cur));
const v = parseNum(input);
if (v == null) return;
setBudget(game, v);
toast('经费已更新');
if (W.renderAll) try { W.renderAll(); } catch {}
state.lastRenderSig = '';
}));
right.appendChild(mkBtn('压力锁', () => {
stressLockEnabled = !stressLockEnabled;
if (stressLockEnabled) applyStressLock(game);
else removeStressLock(game);
toast(`压力锁:${stressLockEnabled ? '开(恒为0)' : '关'}`);
state.lastRenderSig = '';
}));
right.appendChild(mkBtn('时间定格', () => {
if (!timeFrozen) {
weekKey = null;
weekOrigDesc = null;
frozenWeekValue = null;
freezeTime(game);
if (timeFrozen) toast(`时间已定格(${weekKey ?? 'week'} = ${frozenWeekValue})`);
} else {
unfreezeTime(game);
}
}));
right.appendChild(mkBtn('学生侧栏', () => {
togglePanel();
}));
bar.append(left, mid, right);
document.body.appendChild(bar);
document.body.insertBefore(el('div', `height:${PANEL_TOP}px;`), document.body.firstChild);
let lastMoney = null, lastCnt = null, lastStress = null, lastFreeze = null, lastWeekText = null;
function tick() {
trySetRep(game, REPUTATION_LOCK);
if (stressLockEnabled) applyStressLock(game);
if (timeFrozen) {
freezeTime(game);
if (weekFreezeMode === 'assign' && weekKey && frozenWeekValue != null) {
try { game[weekKey] = frozenWeekValue; } catch {}
}
}
if (state.hidden) return;
const money = getBudget(game);
const cnt = getStudentCount(game);
if (money !== lastMoney) {
const m = document.getElementById('__oi_money__');
if (m) m.textContent = `¥${fmt(money)}`;
lastMoney = money;
}
if (!weekKey) weekKey = getWeekKey(game);
const weekVal = (weekKey && (weekKey in game)) ? game[weekKey] : '-';
const weekText = `${weekVal}${(timeFrozen && frozenWeekValue != null) ? '(定格)' : ''}`;
if (cnt !== lastCnt || lastStress !== stressLockEnabled || lastFreeze !== timeFrozen || lastWeekText !== weekText) {
const i = document.getElementById('__oi_info__');
if (i) i.textContent = `学生:${cnt} | 压力锁:${stressLockEnabled ? '开' : '关'} | 周数:${weekText}`;
lastCnt = cnt;
lastStress = stressLockEnabled;
lastFreeze = timeFrozen;
lastWeekText = weekText;
}
renderPanel(game);
}
tick();
setInterval(tick, 600);
}
function bindHideHotkey() {
window.addEventListener('keydown', (e) => {
const key = (e.key || '').toLowerCase();
if (e.ctrlKey && e.shiftKey && key === 'h') {
state.hidden = !state.hidden;
saveHideState();
if (state.hidden) {
toast('插件已隐藏(再次按 Ctrl+Shift+H 显示)');
setTimeout(updateVisibility, 80);
} else {
updateVisibility();
toast('插件已显示(Ctrl+Shift+H 可再次隐藏)');
}
e.preventDefault?.();
}
}, true);
}
loadHideState();
addStyle();
ensureToast();
bindHideHotkey();
waitFor(() => !!W.game).then(() => {
const g = W.game;
applyRepLock(g);
makePanel();
makeBar(g);
updateVisibility();
if (!state.hidden) toast('作弊器 UI 已加载');
}).catch(() => {});
})();
更多游戏的作弊器将持续更新
提示:代码由ChatGpt辅助完成,请谨慎食用。
如果你觉得这篇文章很好,请给我一个关注,谢谢。
*✅表示作者以同意制作。(若作者不同意欢迎私信删除)
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...