93 lines
3.7 KiB
Lua
93 lines
3.7 KiB
Lua
-- Inactive research tool: stage only when the Client is walking, then remove.
|
|
-- Never mutates a live pool, config row, module list or dictionary. Clones use
|
|
-- the same MemberwiseClone/5-argument Invoke path as navigation_profiles.lua.
|
|
do
|
|
local function capture()
|
|
local s=_G.__GAC_GACHA_LIVE_CLONE1 or {phase=1}
|
|
_G.__GAC_GACHA_LIVE_CLONE1=s
|
|
if s.phase>4 then return end
|
|
local log=function(x)CS.UnityEngine.Debug.Log('[GAC_GACHA_LIVE_CLONE] '..tostring(x))end
|
|
local flags=CS.System.Enum.ToObject(typeof(CS.System.Reflection.BindingFlags),60)
|
|
local invoke=CS.System.Enum.ToObject(typeof(CS.System.Reflection.BindingFlags),0)
|
|
local manager=CS.RPG.Client.GlobalVars.s_GamePhaseManager
|
|
local phase=manager and typeof(CS.RPG.Client.GamePhaseManager):GetField('_CurrentPhase',flags):GetValue(manager)
|
|
if not phase or typeof(CS.RPG.Client.BattleGamePhase):IsInstanceOfType(phase) then return end
|
|
if s.phase==1 then
|
|
local page=package.loaded['Ui.Gacha.GachaMainPage']
|
|
if type(page)=='table' and type(page._create_pools_panel)=='function' then
|
|
for i=1,16 do
|
|
local name,value=debug.getupvalue(page._create_pools_panel,i)
|
|
if name==nil then break end
|
|
if name=='_gacha_module' then s.module=value;break end
|
|
end
|
|
end
|
|
if not s.module then s.module=CS.RPG.Client.GlobalVars.s_ModuleManager.GachaModule end
|
|
if not s.module then return end
|
|
local pools=s.module:GetSortedGachaPoolDatas()
|
|
if not pools or pools.Count==0 then return end
|
|
s.template=pools[0]
|
|
s.clone=typeof(CS.System.Object):GetMethod('MemberwiseClone',flags)
|
|
s.empty=CS.System.Array.CreateInstance(typeof(CS.System.Object),0)
|
|
s.pool=s.clone:Invoke(s.template,invoke,nil,s.empty,nil)
|
|
s.row=s.clone:Invoke(s.template.Row,invoke,nil,s.empty,nil)
|
|
local base=s.template:GetType()
|
|
while base and base.FullName~='RPG.Client.BaseGachaPoolData' do base=base.BaseType end
|
|
if not base then error('pool base type absent') end
|
|
s.base=base
|
|
base:GetField('<Row>k__BackingField',flags):SetValue(s.pool,s.row)
|
|
if s.pool==s.template or s.row==s.template.Row or s.pool.GachaID~=s.template.GachaID then
|
|
error('detached clone identity failed')
|
|
end
|
|
log('DETACHED_OK concrete='..s.pool:GetType().FullName..' id='..s.pool.GachaID..' prefab='..s.pool.PrefabPath)
|
|
s.phase=2
|
|
return
|
|
end
|
|
if s.phase==2 then
|
|
local types={s.pool:GetType(),s.base}
|
|
for _,t in ipairs(types) do
|
|
log('TYPE '..t.FullName)
|
|
local fs=t:GetFields(flags)
|
|
for i=0,math.min(fs.Length-1,47) do
|
|
local f=fs[i]
|
|
if f.DeclaringType==t and not f.IsStatic then log('FIELD '..f.Name..' '..f.FieldType.FullName) end
|
|
end
|
|
end
|
|
s.phase=3
|
|
return
|
|
end
|
|
if s.phase==3 then
|
|
local groups=s.module:GetSortedGachaGroupDatas()
|
|
if not groups or groups.Count==0 then error('no initialized groups') end
|
|
local group=groups[0]
|
|
local t=group:GetType()
|
|
log('GROUP concrete='..t.FullName..' id='..group.GroupID)
|
|
for depth=1,3 do
|
|
if not t or t.FullName=='System.Object' then break end
|
|
log('TYPE '..t.FullName)
|
|
local fs=t:GetFields(flags)
|
|
for i=0,math.min(fs.Length-1,47) do
|
|
local f=fs[i]
|
|
if f.DeclaringType==t and not f.IsStatic then log('FIELD '..f.Name..' '..f.FieldType.FullName) end
|
|
end
|
|
t=t.BaseType
|
|
end
|
|
s.phase=4
|
|
return
|
|
end
|
|
local methods=s.module:GetType():GetMethods(flags)
|
|
for i=0,methods.Length-1 do
|
|
local m=methods[i]
|
|
if m.Name=='_AddGachaPoolDataToGroupDict' then
|
|
log('REGISTER_SIGNATURE '..tostring(m))
|
|
end
|
|
end
|
|
log('END no registration or live mutation performed')
|
|
s.module=nil;s.template=nil;s.pool=nil;s.row=nil;s.base=nil;s.phase=5
|
|
end
|
|
local ok,err=pcall(capture)
|
|
if not ok then
|
|
_G.__GAC_GACHA_LIVE_CLONE1={phase=99}
|
|
CS.UnityEngine.Debug.Log('[GAC_GACHA_LIVE_CLONE] ERROR '..tostring(err))
|
|
end
|
|
end
|