Nguồn: 10-tien-trinh-mo-khoa.md · Cập nhật lần cuối: 2026-09-06 22:46 +07 · sha256 nguồn 898ead25f408
Bản công khai: đã lược bỏ 2 dòng nội bộ (đường dẫn máy, chi tiết kỹ thuật vượt bảo vệ, ghi chú probe). Nội dung học được giữ nguyên.
10 — Tiến trình & thang mở khoá
Nguồn framework: docs/framework/07-progression-managers.md §2–§4,
docs/framework/09-prestige-rebirth.md §2, §3.2,
[liveops catalog: UNLOCK_GATES.md] §1–§5,
[liveops catalog: SCREEN_CATALOG.md] §7,
[liveops catalog: LIVEOPS_SURFACE.md] §4.
Cấp bằng chứng: L1 ANALYSIS — dựng lại clean-room từ disasm + metadata + quan sát runtime; không phải source gốc. Mỗi dòng bên dưới mang nhãn bằng chứng riêng.
Mục tiêu
Bạn muốn làm một game idle có nhiều "phòng" (Rebirth, Mine, Fish, Boss, Pet, Hunt, Trip…) mở dần
theo tiến độ, và mỗi phòng là một hệ thống nhỏ có nâng cấp, gacha, buff, nhiệm vụ riêng.
Recipe này cho biết game gốc mở khoá bằng đúng một con số, tổ chức 35 hệ thống bằng một
khuôn manager lặp lại, và cân bằng bằng bảng đã bake vào scene — kèm tất cả con số thật.
Game gốc làm gì
Biến cổng duy nhất và thang mở khoá 7 nút chính
| Điều game làm |
Con số / hằng số |
Mức bằng chứng |
Nguồn |
Biến cổng trung tâm là Tree_manager.Stage_Value_Max (field 0x30) |
Stage_Value = Level_Now + 10 × Stage_Now; Stage_Value_Max = giá trị cao nhất từng đạt |
VERIFIED |
Tree_manager.Game_Win RVA 0x2B452E4, lệnh 0x2B45520/0x2B45534; UNLOCK_GATES §1.2 |
Stage_Value_Max không bao giờ giảm — chỉ ghi khi >=, và Rebirth() không đụng tới |
monotonic |
VERIFIED |
UNLOCK_GATES §1.2; doc 09 §2 |
Mỗi stage có 5 level: Level_Now chạy 0..4, Stage_Now 0-based |
5 level/stage |
VERIFIED |
Tree_manager.StageAdvance RVA 0x2B45820 |
UI hiển thị 1-based: "Stage {Stage_Now+1}-{Level_Now+1}" |
literal @0x5E94A48 |
VERIFIED |
GameSlider.Stage_Reload RVA 0x2B156E4 |
Hàm cổng: Locked_obj.SetActive(Stage_Value_Max < N) cho 7 nút |
7 ngưỡng |
VERIFIED |
Tree_manager.Contents_Lock_Reload RVA 0x2B4441C |
Hàm nút Content_Btn_* kiểm lại cùng ngưỡng; chưa đủ thì UI_manager.Alert(ScriptLocalization.Alarm.StageUnlock, <số stage>) — đọc trọn 7 handler (G395): N = 3 / 4 / 6 / 10 / 12 / 12 / 35; Alert = round-robin 3 hộp cảnh báo (mọi cảnh báo từng câm trong bản dựng lại) |
7 |
VERIFIED (cả tên lẫn số) |
UNLOCK_GATES §2; doc 07 §2.7 (G395) |
Thang mở khoá (mọi ngưỡng là bội số của 10 ⇒ luôn mở ở level 1 của stage tương ứng):
| # |
Feature (nhãn UI) |
Field ổ khoá |
Stage_Value_Max ≥ |
RVA SetActive |
Handler nút |
Mở tại stage hiển thị |
Mức |
| 1 |
Rebirth |
Rebirth_manager.Rebirth_Btn_Locked_obj (0x30) |
20 |
0x2B444EC |
Content_Btn_Rebirth 0x2B44B58 |
Stage 3-1 |
VERIFIED |
| 2 |
Mine |
Mine_manager.Mine_Btn_Locked_obj (0x50) |
30 |
0x2B44554 |
Content_Btn_Mine 0x2B44CE4 |
Stage 4-1 |
VERIFIED |
| 3 |
Fish |
Fish_manager.Fish_Btn_Locked_obj (0x70) |
50 |
0x2B44520 |
Content_Btn_Fish 0x2B44C10 |
Stage 6-1 |
VERIFIED |
| 4 |
Boss |
Boss_manager.Boss_Btn_Locked_obj (0x38) |
90 |
0x2B44598 |
Content_Btn_Boss 0x2B44DCC |
Stage 10-1 |
VERIFIED |
| 5 |
Pet |
Pet_manager.Pet_Btn_Locked_obj (0x38) |
110 |
0x2B445DC |
Content_Btn_Pet 0x2B44E94 |
Stage 12-1 |
VERIFIED |
| 6 |
Hunt (Monster) |
Monster_manager.Monster_Btn_Locked_obj (0x30) |
110 |
0x2B44620 |
Content_Btn_Monster 0x2B44F54 |
Stage 12-1 |
VERIFIED |
| 7 |
Trip (Adventure) |
Adventure_manager.Adventure_Btn_Locked_obj (0x50) |
340 |
0x2B4466C |
Content_Btn_Adventure 0x2B4501C |
Stage 35-1 |
VERIFIED |
Đối chiếu độc lập: ảnh chụp save thật "Stage 5-4" ⇒ Stage_Value = 3 + 40 = 43 ⇒ Rebirth(20) và
Mine(30) mở, Fish/Boss/Pet/Hunt/Trip khoá — khớp 100 % với ảnh (UNLOCK_GATES §1.5, VERIFIED).
Cổng phụ và nút không có cổng
| Đối tượng |
Điều kiện |
Mức bằng chứng |
Nguồn |
| Nâng cấp Rebirth bằng IAP |
Stage_Value_Max > 988 (⇒ giá trị đạt được kế tiếp 990 ⇒ Stage hiển thị 100-1, quy đổi là suy luận) |
VERIFIED (ngưỡng) |
UpgradeRebirth_IAP_Unlocked_return RVA 0x2B232D0; const UpgradeRebirth_IAP_UnlockStageValue = 989 dump.cs:598987 |
| Trip — mở từng map |
Adventure_manager.instance.Lv >= Adventure_Unlock_Balance[map] (theo Lv của Trip, MaxLv = 15, không phải stage); Adventure_Unlock_Balance = [0, 1, 3, 6, 10] |
VERIFIED (công thức) + runtime + metadata-proven (blob SHA, G353) |
is_Unlock_return RVA 0x2ADB684; doc 07 §2.9 |
| Skin — mở từng skin |
num == 0 luôn mở; còn lại bool[] trong save |
VERIFIED |
Skin_manager.is_Unlock RVA 0x2B3F514 |
| DiaPig |
static[+8] \|\| static[+9] của Shop_manager (2 cờ bool tĩnh) |
công thức VERIFIED; ý nghĩa 2 cờ UNKNOWN |
Shop_manager.is_DiaPig_Unlock RVA 0x2B27764 |
| WeeklyShop VIP |
WeeklyShop.Is_VIP_Unlocked(); const int Unlock_Degree = 3 |
hằng VERIFIED; thân hàm chưa giải mã |
RVA 0x2B3EA58 |
| StepUp banner |
const int Banner_Unlock_Degree = 2; Duration_Days = 7, StepCount = 5 |
hằng VERIFIED |
dump.cs class StepUp |
| PlusPack banner |
const int Banner_Stage_Min = 190 (⇒ Stage hiển thị 20-1) |
hằng VERIFIED |
dump.cs class PlusPack |
| Pet lock group |
khoá do người chơi tự đặt, không phải cổng tiến trình |
VERIFIED |
Pet_manager.IsPetLocked dump.cs:598030 |
Mission SequenceLocked / LuxuryLocked / VIPLocked |
gắn battle-pass Luxury/VIP |
cấu trúc VERIFIED; ngưỡng UNKNOWN |
dump.cs:587516, :587575-587576 |
| Raid |
KHÔNG có cổng nào: không có Raid_Btn, không có mặt trong Contents_Lock_Reload |
VERIFIED (negative) |
SCREEN_CATALOG §6 |
| Lớp tutorial cho hàng 27 nút HUD |
Tutorial_manager.Start: chưa xong tutorial và Lv(Power) < 1 ⇒ tắt bộ 32 object (cả hàng nút); ngược lại CompleteTutorial bật lại tất cả ⇒ hàng nút xuất hiện sau lần nâng Power đầu tiên; HUD tối giản trên save mới là đúng SOT |
disasm-proven |
doc 07 §2.7/§2.8 (G375) |
Máy trạng thái tutorial Upgrade → Challenge → GunOpen → GunBuy → GunEquip → Done; mỗi bước có coroutine kiểm điều kiện; bước Upgrade poll level Power mỗi 0.2 s ⇒ game gốc chịu được việc Start chạy trước khi save nạp xong (tự thoát khi level đã restore) |
6 bước |
disasm-proven |
doc 07 §2.8 (G385) |
Bước mua súng của tutorial nạp dia theo kịch bản: Dia ≤ 99 ⇒ cấp 100 − Dia để lần mua đầu chắc chắn mua được — hướng dẫn, không phải đường kiếm tiền |
100 dia |
disasm-proven |
doc 10 §10 (G385) |
Chế độ Play (SpeedRun): cây clamp(15·stage + 20, 20..190) xếp vòng tròn, bậc ngẫu nhiên 1/1.8/3 trên đường cong stage, 60 s; thắng = cây cuối đổ ⇒ Stage_Now++ (tutorial poll chính số này) + 30 dia (×4 auto, quảng cáo bonus +90); thua = hết giờ; quét tự động khi sức mạnh ≥ máu stage × n × 193 / 100 / 24; map = chủ đề stage % 10 |
60 s / 30 dia |
disasm-proven |
doc 07 §2.11 (G406) |
| Chế độ Raid (ẩn): boss của tuần = tuần kể từ 2024-01-01 mod 5; súng buff theo tuần (EXPLOSIVE → LASER → MISSILE → BLAST_SNIPER → PIERCE); loadout 3 ô tối thiểu 2; 30 s; boss hồi sinh sau mỗi lần giết; điểm ≥ mốc ⇒ 10 dia (20 auto); kết thúc chỉ theo đồng hồ |
5 tuần / 30 s |
disasm-proven |
doc 07 §2.12 (G406) |
Chế độ Hunt (Monster): rào HP = 1 — một con quái chạm rào = thua; mỗi wave 5 level, giết 90/120/160/200/240 con, spawn mỗi 0.35/0.2/0.17/0.12/0.08 s; máu wave ×3 (500 → 1 500 → 4 500…), quái to (xác suất Lv × 0.2) máu ×3; thưởng 30 PetCoin × hệ số gói PlusPack, ×2 auto; quét cần gói Auto; chỉ kết thúc khi thua hoặc bỏ cuộc; nộp điểm Wave × 10 + Lv |
HP 1 / 30 PetCoin |
disasm-proven |
doc 07 §2.13 (G408) |
Chế độ Boss: máu 50 000 → 250 000 → 1.2 M (×5), skin = Stage % 9; 60 s (×2 với gói Time — nhưng thanh thời gian giữ max 60 ⇒ tràn > 100 %, cùng quirk Mine); thắng = Stage++ rồi mới nộp điểm, thưởng 150 dia × hệ số gói, ×3 auto, quảng cáo +2×; quét (không cần gói) khi sức mạnh ≥ máu / max(1, round(timer × 0.7)) |
150 dia / 60 s |
disasm-proven |
doc 07 §2.14 (G408) |
Bản học: hệ số gói PlusPack (Reward_Mult_*, Is_Active = 7 ngày) và Is_RewardBonus_Auto còn stub ⇒ thưởng Hunt/Boss = 0 — lỗi bản dựng lại, đang sửa (R13) |
— |
blocker |
G408 |
Chế độ Mine: màn 60 s; vào bằng vé (Ticket_MaxCount_return từng là return 0 ⇒ không bao giờ vào được); quặng đặt bằng nhiễu Perlin trong vành r 8..20; điểm = dia. Hai quirk của game gốc: lượt có boost PlusPack bắt đầu với thanh thời gian tràn > 100 % (đồng hồ dùng max đã cộng, thanh dùng max thô 60 s); chỉ 100 quặng đầu của pool được xáo nên chỉ chúng có sprite dia |
60 s / 8..20 / 100 |
disasm-proven |
doc 07 §2.10 (G393) |
Dia: mỗi dia nhận được cộng 3 vào sổ gem gửi máy chủ (_getDia += v × 3); tiêu dia không kẹp ở 0 (khác PetCoin, có kẹp) |
×3 |
disasm-proven |
doc 01 §2 (G395) |
Bản địa hoá giá tiền nằm trong static ctor của Shop_manager: bảng 23 tiền tệ → chuỗi định dạng + tập 6 tiền tệ không thập phân KRW, JPY, VND, IDR, CLP, HUF (VND hiện 52,000đ, không 52,000.00đ); cùng ctor cấp danh sách giao dịch đã xử lý / lịch sử mua — thiếu là autosave save mới ném |
23 / 6 |
disasm-proven |
doc 10 §6.3 (G399) |
Nút không có cổng (mở từ Stage 1-1): Shop_Btn, Gun_Btn, Skin_Btn, SpeedRun_Btn (Play),
Mission_Btn, EcoMode_Btn, Auto_Btn, Setting_Btn, DailyCheck_Btn, DiaPig_Btn,
PowerBuff_Btn, MoneyBuff_Btn, Rank_Btn (UNLOCK_GATES §4). Các nút liveops
(StepUp_Btn/DailyGun_Btn/WeeklyShop_Btn/FreeCash_Btn/OfferWall_Btn) mặc định
m_IsActive: 0, bật bởi thời gian/liveops, không phải stage.
Bộ khung manager
| Điều game làm |
Con số / hằng số |
Mức bằng chứng |
Nguồn |
35 singleton *_manager / Gamemanager / UpdateManager / OfflineProgressManager, mỗi cái đúng 1 instance |
35 |
scene-census |
doc 07 §2.1; [report: codegen_lane.md] §1.2 |
Assembly-CSharp có 731 type, chỉ 190 vào scene; tập làm việc 66 class / 1 284 method |
731 / 190 / 66 |
scene-census |
[index: scene_census.json] |
Hai biến thể singleton: field static trần (đa số) và property (Sound_manager) |
— |
metadata-proven |
dump.cs:590265 |
Time_manager, RedeemCode_manager có 0 instance trong scene — dựng lúc chạy |
0 |
scene-census |
codegen_lane.md §1.3 |
Mỗi manager có SaveData_return() + LoadData(SaveData) |
— |
metadata-proven |
Upgrade_manager RVA 0x2B4A68C/0x2B4A750 |
Mỗi manager có Balance_Reload() — nhưng xem "Bẫy" bên dưới: dead code trong 1.1.59 |
— |
disasm-proven + VERIFIED (IDA xrefs) |
doc 07 §2.1; doc 09 §2 |
UI vẽ lại từ state: First_Reload() (một lần) vs Value_Reload() (thường xuyên) |
Mission_Reward_Item.First_Reload 200× / Value_Reload 150× |
runtime-observed |
runtime_ranking.json |
Dữ liệu nhạy cảm dùng ObscuredInt (Anti-Cheat Toolkit, Asset Store 202695) |
Gamemanager.Dia, Rebirth_Upgrade_Info.Lv |
metadata-proven + package-source |
doc 07 §2.1 |
Nâng cấp trong vòng (Upgrade_manager)
| Điều game làm |
Con số / hằng số |
Mức bằng chứng |
Nguồn |
| Trần level |
MaxLv = 10000 |
metadata-proven |
dump.cs:602928 |
| Hằng số thiết kế trong binary |
PowerMultPerLv = 1.08, MoneyMultPerLv = 1.08, SpeedAddPerLv = 8, PriceBase = 50, PriceGrowth = 1.38, PriceSoftCapLv = 5000, PriceLateGrowth = 2, SpeedStagePenalty = 2 |
metadata-proven |
dump.cs:602928 |
Bảng THẬT lúc chạy = mảng serialize trong Main.unity, sinh bằng lặp có cắt v[i] = trunc3(v[i-1] × 1.08) |
0/360 lệch khi tái tạo |
scene-YAML + VERIFIED |
Main.unity:20353425…20413434; doc 09 §3.2; sim mục [M] |
Speed_balance[lv] = 100 + 8·lv (tuyến tính, khớp chính xác) |
Speed_balance[46] = 468 = ảnh chụp |
scene-YAML + observed |
Main.unity:20413434; [device evidence: user_screenshot_stage5-4.png] |
Price_balance[1] = 68, không phải 69 — vì 1.38 là double nhị phân 1.3799999999999998… |
68 |
scene-YAML + VERIFIED |
doc 09 §2 |
AutoUpgrade_All(), Upgrade_Silent(int) — nâng cấp hàng loạt không hiệu ứng |
— |
metadata-proven |
dump.cs:602928 |
Thanh "mua được" của 3 panel nâng cấp (SlicedFilledImage hướng Up, fill = Money / Price) đo với tiền thật trên save đã nạp: 47.7 / 48.5 / 57.2 % chiều cao panel, ổn định |
3 thanh |
build-measured |
G371 |
Buff, súng, relic, skin, nhiệm vụ
| Điều game làm |
Con số / hằng số |
Mức bằng chứng |
Nguồn |
Buff = thời gian còn lại, hai đồng hồ moneyBuffTime @0x28 / powerBuffTime @0x2C |
BUFF_DURATION = 300, BUFF_MAX = 900 |
metadata-proven |
dump.cs:592886 |
Một coroutine BuffTickCoroutine chỉ chạy khi cần; IsPermanentBuff là property riêng |
IsPermanentBuff 103×, IsBuffActive 92× / 40 s |
runtime-observed |
runtime_ranking.json |
| Kho súng cố định |
int[16] Owned_Gun_list, -1 = trống |
metadata-proven |
dump.cs:596607 |
Gacha: DrawRandomGun(Degree), DrawRandom_Normal/Epic, DrawGun_Degree_5 |
— |
metadata-proven |
RVA 0x2B0A278, 0x2B0A410, 0x2B0A92C, 0x2B0A930 |
| Auto-merge có trần cứng |
const int AutoMerge_Exclude_Degree = 7 |
metadata-proven |
dump.cs:596607 |
Bậc súng = gunNum / 5; 10 bậc (Weapon_Get_Counts) |
5 khẩu/bậc, 10 bậc |
disasm-proven + metadata-proven |
Gun_Item_Demo.Reload RVA 0x2B11A18; dump.cs:596607 |
| Súng thưởng quảng cáo có hạn dùng |
AD_GUN_EVENT_GUN_NUM = 14, AD_GUN_EVENT_COOLTIME = 1800 |
metadata-proven |
dump.cs:596607 |
Gun_manager chứa URL Google Sheets export?format=tsv&range=A2:I66 + Request_Sheet() |
65 dòng × 9 cột |
metadata-proven |
dump.cs:596607; LIVEOPS_SURFACE §4 |
Relic_manager phơi 7 static: Dmg_Value, Money_Value, CriDmg_Value (InfVal) + MoveSpeed_Value, Offline_Value, Rebirth_Value, Skip_Value (int) |
DrawPrice = 20 |
metadata-proven |
dump.cs:592186 |
Bảng relic: một đường cong 300 cấp, seed 105, ×1.05/cấp ở 3 chữ số có nghĩa rồi −100, dùng chung Damage/Money/CriDmg; bậc _0/_1/_2 = ×1 / ×1.5 (bỏ thập phân) / ×2; relic đơn: MoveSpeed & Skip = 2·Lv+2, Offline = 10·Lv+10 phút, Rebirth = 5·Lv+5; baseline 100 / 100 / 100 / 0 / 0 / 100 / 0 |
300 cấp |
disasm-proven |
doc 07 §2.4 (G360, G361) |
Value_Reload làm mới có chọn lọc: gọi Cat.Balance_Reload chỉ khi một giá trị chiến đấu đổi; InvalidateMoneyCache chỉ khi Money_Value đổi |
— |
disasm-proven |
G361 |
Skin_manager phơi 3 static int: Damage_Accum, Speed_Accum, Money_Accum; có is_skinValueZero |
3 |
metadata-proven |
dump.cs:601415 |
Mission_Type chỉ 4 giá trị: TreeCount=0, StageClear=1, Rebirth=2, PlayMine=3 |
4 |
metadata-proven |
dump.cs:587114 |
Một API tiến độ: MissionValue_Increase(Mission_Type); người gọi cho cây là Tree_manager.Tree_Destroyed (được Tree.Die_Reload gọi — hai hàm từng bị công cụ gộp làm một, G346); Tree.Die_Reload 85× → 86× |
— |
disasm-proven + runtime-observed |
doc 05 §3.6; runtime_ranking.json |
Mission_manager.HighTier_Gun_Table = [16, 18, 20, 22, 24, 25, 27, 29] (8 khẩu bậc A → SS) và is_Vip là static |
8 |
metadata-proven (blob SHA, G353) + disasm-proven (G329) |
doc 11 §3.1, §8.1; nơi dùng bảng chưa đọc |
Phần thưởng nhận theo thứ tự (is_Reward_SequenceLocked 150×) + hệ mùa (Season_Reload, is_Season_Closed) |
— |
metadata-proven + runtime-observed |
doc 07 §2.5 |
Trip (Adventure_manager): vé, XP, bảng mở khoá — đợt 3
| Điều game làm |
Con số / hằng số |
Mức bằng chứng |
Nguồn |
Vé nạp 1 vé / 4 giờ: Ticket_Charge_Interval = TimeSpan.FromHours(4); Ticket_Max = 20 |
4 h / 20 |
disasm-proven + runtime |
doc 07 §2.9 (G321) |
Quy tắc hai mốc của Ticket_Refresh: dưới trần — mốc nạp tiến đúng số khoảng 4 h nguyên đã tiêu, phần dư mang sang; tại trần — mốc đặt về NOW, phần dư bỏ ⇒ vắng dài không tích vé quá 20 |
— |
disasm-proven |
G321 |
5 bậc mở map theo Trip Lv [0, 1, 3, 6, 10] (static) và 5 thời lượng chuyến [1, 2, 4, 8, 16] giờ (ctor) — hai nguồn độc lập (đọc bộ nhớ runtime + blob tĩnh) trùng nhau |
5 + 5 |
runtime + metadata-proven (blob SHA) |
doc 07 §2.9 (G353) |
XP Trip: thân Exp_Balance_Reload sinh Exp_balance[i] = (20 + 3·i)·i + 50 ⇒ 50, 73, 102, 137, 178, …, 918 (15 cấp, bậc hai) |
15 |
disasm-proven (thân hàm) |
G311 |
✅ Đã giải (G361): bảng scene 10, 60, 100, 130, 180, …, 920 là bảng SỐNG (scene lưu dạng hex blob; HUD EXP 0/10); công thức chỉ là fallback khi mảng null/rỗng — hai điểm gọi trong ContinueLoad đều có guard. Bản dựng lại từng gọi vô điều kiện (ghi đè đường cong designer mỗi lần nạp) — đã sửa |
15 |
disasm-proven + scene-YAML |
doc 07 §2.9 |
Stub Ticket_Charge_Interval trả default(TimeSpan) = 0 từng gây chia cho 0 ở hai method sau — mặc định giá trị nổ ở nơi dùng, không ở nơi khai báo |
— |
bài học khôi phục |
G321 |
Công thức / pseudocode
# Cổng mở khoá — Tree_manager (VERIFIED, RVA 0x2B4441C / 0x2B452E4 / 0x2B45820)
Stage_Value = Level_Now + 10 * Stage_Now # Level_Now 0..4, Stage_Now 0-based
on Game_Win: # G347 — thân hàm đầy đủ ở doc 05 §3.6
StageAdvance(ref Stage_Now, ref Level_Now)
if Random(0,100) < Relic.Skip_Value and Level_Now + 10*Stage_Now < Stage_Value_Max:
StageAdvance(...) # relic "Skip": chỉ nhảy TRONG vùng đã chinh phục
Stage_Value = Level_Now + 10 * Stage_Now
if Stage_Value >= Stage_Value_Max:
Stage_Value_Max = Stage_Value # chỉ tăng, Rebirth không reset
Rank_manager.SubmitScore(...) # [R1] leaderboard
Contents_Lock_Reload()
Contents_Lock_Reload():
Rebirth_Btn_Locked_obj.SetActive(Stage_Value_Max < 20)
Mine_Btn_Locked_obj.SetActive(Stage_Value_Max < 30)
Fish_Btn_Locked_obj.SetActive(Stage_Value_Max < 50)
Boss_Btn_Locked_obj.SetActive(Stage_Value_Max < 90)
Pet_Btn_Locked_obj.SetActive(Stage_Value_Max < 110)
Monster_Btn_Locked_obj.SetActive(Stage_Value_Max < 110)
Adventure_Btn_Locked_obj.SetActive(Stage_Value_Max < 340)
FreeCash_manager.Hud_Reload(); OfferWall_manager.Hud_Reload() # [R1] ad exposure
Content_Btn_X():
if Stage_Value_Max >= N: mở panel X
else: UI_manager.Alert(Format(Alarm.StageUnlock, N/10 + 1)) # số stage hiển thị
StageAdvance(ref stage, ref level):
if level >= 4: level = 0; stage += 1
else: level += 1
// Khuôn manager lặp lại ở ~30 hệ thống (doc 07 §3.1)
public class X_manager : MonoBehaviour
{
public static X_manager instance; // field static trần, Awake: instance = this
public void Balance_Reload() { … } // sinh bảng — DEAD CODE trong 1.1.59, bảng thật nằm trong scene
public int[] SaveData_return() { … } // xuất state
public void LoadData(SaveData data) { … } // nạp state
public void First_Reload() { … } // thiết lập 1 lần (sprite, tên)
public void Value_Reload() { … } // cập nhật thường xuyên (số, tiến độ, khoá)
public static T X_return() { … } // phơi giá trị dẫn xuất cho hệ khác
}
# Buff (doc 07 §3.4) — thời gian còn lại có trần, không phải danh sách instance
AddBuff(type): remaining[type] = min(remaining[type] + 300, 900)
IsBuffActive(t): IsPermanentBuff || remaining[t] > 0
# Súng (doc 07 §3.3)
degree(gunNum) = gunNum / 5 # 10 bậc, 5 khẩu/bậc
DrawRandomGun(d) -> slot = FindFirstEmptyOwned() # int[16], -1 = trống
-> Owned_Gun_list[slot] = gunNum; Weapon_Get_Counts[d]++
TryStartAutoMerge(): limit = min(AutoMerge_Degree, Max_Collected_Degree); bậc >= 7 KHÔNG BAO GIỜ tự ghép
# Quota theo ngày (doc 07 §3.7) — khuôn dùng chung cho điểm danh, vé, lượt rút thưởng
Quota_Reload(key, maxPending):
if savedDate.Date >= Today: return # Today = giờ local ĐÃ HIỆU CHỈNH, không phải giờ máy
if !CanRolloverDaily(key, maxPending): return # bị chặn -> KHÔNG ghi ngày mới, lần sau thử lại
RecordGain(key); used = 0; savedDate = Today # ghi sổ TRƯỚC, phát SAU, đánh dấu CUỐI
OnClockSynced(): savedDate = ClampFutureLocalDate(savedDate) # trần = Today + 1 ngày
Bẫy đã gặp
Balance_Reload không chạy ở runtime. CodeRefsTo = [] cho Upgrade_manager (0x2B4A02C),
Rebirth_manager (0x2B21CB4), Gun_manager (0x2B0AB4C); không có string literal, không có
UnityEvent trong scene. Bảng thật là mảng serialize trong Main.unity, sinh bằng lặp có cắt
chứ không phải pow(). Dùng 100·1.08^lv sẽ lệch −10.2 % ở lv 50 và ×6.5 ở lv 1 000
(doc 09 §3.2; G138a; CONVERGENCE). Doc 01 §2 và doc 07 §2.1 còn dòng "bảng sinh bằng công thức
lúc chạy" — đó là bản cũ, doc 09 đã đính chính.
- Kết luận "field không được tham chiếu" từ
dump.cs là sai phương pháp. dump.cs chỉ liệt kê
khai báo field, không liệt kê truy cập. Rebirth_Btn_Locked_obj từng bị ghi UNKNOWN vì thế;
thực tế nó được Contents_Lock_Reload điều khiển qua static-instance + offset thô +48
(UNLOCK_GATES §2.3; G139 METHODOLOGY). Muốn chứng minh dead code / dead field: dùng IDA
CodeRefsTo / DataRefsTo.
Stage_Value_Max không reset khi Rebirth — nếu framework của bạn reset nó, nút sẽ khoá lại
sau mỗi lần prestige (VERIFIED, doc 09 §2).
Game_Win gọi Rank_manager.SubmitScore ngay sau khi tăng Stage_Value_Max — mọi probe ghi
field này phải no-op SubmitScore, nếu không sẽ làm bẩn leaderboard production (G148 SAFETY).
- Ràng buộc bảo vệ người chơi phải là
const trong code: AutoMerge_Exclude_Degree = 7.
Designer chỉnh nhầm cấu hình sẽ tự ghép mất súng hiếm (doc 07 §3.3).
- Khớp nối chéo toàn phần: cặp
Tree.Die_Reload → Tree_manager.Tree_Destroyed chạm 5 singleton cho một
cây đổ — không ship được Gamemanager dạng overlay 70 method vì nó kéo theo cả đồ thị (doc 07 §3.1; G129).
- Mặc định giá trị bị công cụ decompile bỏ rơi:
Ticket_Charge_Interval = 0 ⇒ chia cho 0 hai method sau;
GameTime_Max = 0 ⇒ màn thua ở frame 1. Đọc .ctor của mọi class trước (doc 08 §3.6; G306, G321).
- Tích luỹ base-100 rỗng = nhân về 0 trong im lặng (R13).
Relic.Dmg_Value = 0 ⇒ mèo 0 sát thương; Skin_Value_Reload rỗng ⇒ 0 damage, 0 tốc độ;
không ngoại lệ, không cảnh báo. Trước khi ship bất kỳ thứ gì nhân X / 100, truy X tới setter (G359, G361, G363).
- Cân bằng súng có endpoint Google Sheet nhưng 0 code-xref tới
Balance_Reload — HYPOTHESIS là
design-time only; nếu sai, cân bằng súng là remote-driven và kết luận "liveops không ghi đè
kinh tế" phải sửa (G144 OPEN-HIGH-RISK).
- Đừng xếp hạng công việc theo tên class: 731 type, 190 vào scene, 66 class chiếm phần lớn thời
gian chạy (doc 07 §4.10).
- Đánh dấu "đã phát" trước khi phát, ở quota theo ngày. Ghi
savedDate = Today trước khi qua
cổng chống chỉnh giờ ⇒ người chơi mất trắng quota hôm đó và không có lỗi nào hiện ra. Đúng
thứ tự là: kiểm ngày → kiểm cổng trust → ghi sổ → phát → mới đánh dấu ngày (doc 07 §3.7).
- Quên kẹp ngày lưu nằm ở TƯƠNG LAI. Không có bước
ClampFutureLocalDate khi đồng hồ được đồng
bộ, người chơi đẩy giờ máy tới năm sau rồi trả về là quota đóng băng vĩnh viễn (điều kiện
savedDate < Today không bao giờ đúng nữa).
- Dựng đúng một hàm có thể KÍCH HOẠT một stub ở lớp khác đang nằm im.
ClampFutureLocalDate
từng là return default(DateTime) và vô hại — cho tới khi một lô khác dựng đúng OnTimeSynced;
từ đó mỗi lần đồng bộ giờ ghi 0001-01-01 vào ngày lưu, tức reset quota mỗi lần. Trước khi đóng
một lô, quét stub trên toàn bộ callee mà lô vừa mở đường tới, không chỉ các hàm mình viết.
Checklist khi tự làm
- [ ] Một biến tiến độ tổng hợp (
Stage_Value), lưu max từng đạt, không reset khi prestige.
- [ ] Ngưỡng mở khoá là hằng số trong code, bội số của "số level mỗi stage" để luôn mở ở level 1.
- [ ] Cùng một ngưỡng kiểm ở hai chỗ: hàm bật/tắt ổ khoá và handler nút (kèm alert số stage).
- [ ] Gọi hàm cổng ở
Start và ở mỗi lần lập kỷ lục stage; không nối qua UnityEvent nếu muốn tìm được bằng xref.
- [ ] Khuôn manager:
instance + SaveData_return/LoadData + First_Reload/Value_Reload + X_return static.
- [ ] Nếu bake bảng cân bằng vào asset: bảng là nguồn sự thật; hàm sinh là công cụ Editor; ghi rõ luật cắt/tròn và số chữ số.
- [ ] Buff =
float remaining có trần + IsPermanent property; một coroutine chỉ chạy khi có buff.
- [ ] Kho vật phẩm nhỏ: mảng cố định + giá trị lính canh (
-1), quét tuyến tính.
- [ ] Mọi quota theo ngày đi qua một khuôn: giờ đã hiệu chỉnh + sổ nợ có trần theo khoá + giữ nguyên ngày cũ khi bị chặn + kẹp ngày ở tương lai.
- [ ] Gọi
Quota_Reload ở cả hai đường: mỗi lần vẽ lại UI của bề mặt, và khi đồng hồ vừa đồng bộ lúc UI đang đóng.
- [ ] Ràng buộc bảo vệ người chơi (bậc không tự ghép) là
const.
- [ ] Ít loại nhiệm vụ (4 là đủ), một API tăng tiến độ, phần thưởng nhận theo thứ tự.
- [ ] Tách máy móc toàn vẹn (
Time_manager, anti-cheat) khỏi manager kinh tế, sau ITrustedTime.
- [ ] Cấu hình từ xa đi qua
IRemoteConfigService fail-closed; ghi rõ số nào có thể bị ghi đè.
- [ ] Có một cheat panel riêng cho QA (như
Cheat_manager), tắt bằng GameObject; loại cheat cấp tài nguyên khỏi mọi probe tự động.
Điều chưa biết (UNKNOWN)
- ~~Giá trị
Adventure_Unlock_Balance[], Adventure_PetSlot_Unlock_Balance[]~~ — ĐÃ ĐÓNG: [0,1,3,6,10] và [0,2,7] (runtime; Unlock và Duration còn xác nhận tĩnh bằng blob — G353).
- ~~
Adventure_manager.Exp_balance[] mâu thuẫn~~ — ĐÃ GIẢI (G361): mảng scene sống (hex blob), công thức chỉ là fallback khi mảng trống.
HighTier_Gun_Table, MonsterCountPerLevel, SpawnIntervalPerLevel — giá trị đã đọc, nơi dùng chưa đọc (ý nghĩa UNKNOWN; doc 07 §5).
- Ngưỡng Mission
SequenceLocked theo Reward_Degree/Lv — UNKNOWN.
- Ý nghĩa 2 cờ tĩnh trong
Shop_manager.is_DiaPig_Unlock — UNKNOWN.
- 2/5 code-xref còn lại tới
Contents_Lock_Reload — UNKNOWN.
- Có đường mở khoá
Raid nào ở runtime không — bằng chứng tĩnh: KHÔNG; cần probe xác nhận (G142/G153).
- Thân
WeeklyShop.Is_VIP_Unlocked (RVA 0x2B3EA58) — chưa giải mã.
- Thân
Gun_manager.DrawRandomGun (RVA 0x2B0A278) — tỉ lệ rơi gacha UNKNOWN, chưa hề được đọc (doc 07 §5).
- Nội dung Google Sheet 65×9 và việc nó có được nạp ở runtime không — UNKNOWN, HYPOTHESIS "không" (G144).
Request_Sheet có chạy lúc boot không — CHƯA XÁC MINH (không thấy trong cửa sổ trace 40 s).
- ~~Cấu trúc
SaveData~~ — ĐÃ ĐÓNG: bản đồ 22 + 5 + 35 field, thứ tự nạp, vị trí AllowSave — xem 14 Lưu game & offline.
Shop_manager, Adventure_manager, Fish_manager, Monster_manager, Raid_manager — khảo sát một phần (đường nạp save, vé/XP Trip, bể cá, các bảng static — doc 07 §5); Mine_manager, Boss_manager, SpeedRun_manager — chưa khảo sát ngoài số method và field restore.
Relic_manager.Rebirth_Value nhận giá trị từ đâu — UNKNOWN (doc 09 §5).
- Điểm gãy
×1.002 (lv ≥ 14999) của giá node prestige trong mảng scene — UNKNOWN (chỉ tồn tại trong Balance_Reload đã chết).
Đọc thêm
../framework/07-progression-managers.md — bộ khung 35 manager, buff, gacha, nhiệm vụ, ranh giới R1
../framework/09-prestige-rebirth.md — bảng scene vs công thức designer, cổng Rebirth
- 14 — Lưu game & offline — đường nạp save 35 field,
AllowSave, kẹp buff, cửa sổ offline
../framework/01-economy-money.md — mắt Upgrade/Rebirth trong chuỗi thu nhập
[liveops catalog: UNLOCK_GATES.md] — bảng ngưỡng đầy đủ + chuỗi bằng chứng scene YAML
[liveops catalog: SCREEN_CATALOG.md] — kiểm kê màn hình, Raid ẩn, Cheat_manager
[liveops catalog: LIVEOPS_SURFACE.md] — Google Sheet súng (§4), lịch trình shop cố định (§6)
[phân tích nội bộ] — hai phân tích độc lập hội tụ về U1/U4 và Balance_Reload
gap list (nội bộ) — G129, G134, G136, G138a, G139, G144, G147, G148