Request for CT Automation Feature

Ask about cheats/tables for single player games here
aSwedishMagyar
Table Makers
Table Makers
Posts: 690
Joined: Mon Jul 06, 2020 3:19 am
Reputation: 1262

Re: Request for CT Automation Feature

Post by aSwedishMagyar »

I don't like the idea of setting pointers before you know they are populated so I've limited this to script type records only. Enable the records you want to save, hit 'Save State' and then disable and Activate 'Enable' to see that the records you saved are reactivated.

It uses table files to save the record names that are currently activated.

Updated with the ability to create and select your own profiles.
Attachments
Save Table State Template.CT
04-07-2021
(8.65 KiB) Downloaded 49 times

User avatar
dreamcactus
Expert Cheater
Expert Cheater
Posts: 144
Joined: Sat Jul 06, 2019 12:21 pm
Reputation: 0

Re: Request for CT Automation Feature

Post by dreamcactus »

nope dont work , once i select enable it dont load previous save, previous table ive posted and that DrummerIX has been trying to get to work is actually the best solution , but as you can see it needs some work to support my request mainly due to it needing a prefix in any cheat you enable, also btw on a sidenote i always first run game then after a few i have said CT start that way all pointers should be populated, also that said Lua Script needs an additional function in a manner that forces/freezes said values either by some sort of check or something that you can set them to be frozen etc, GreenHouse mentioning something about> But if it's LUA settings, then you could add a timer that keeps setting them or that checks each value, not sure how good that would be performance wise though."

not sure :?

aSwedishMagyar
Table Makers
Table Makers
Posts: 690
Joined: Mon Jul 06, 2020 3:19 am
Reputation: 1262

Re: Request for CT Automation Feature

Post by aSwedishMagyar »

dreamcactus wrote:
Sun Jul 04, 2021 9:37 pm
nope dont work , once i select enable it dont load previous save, previous table ive posted and that DrummerIX has been trying to get to work is actually the best solution , but as you can see it needs some work to support my request mainly due to it needing a prefix in any cheat you enable, also btw on a sidenote i always first run game then after a few i have said CT start that way all pointers should be populated, also that said Lua Script needs an additional function in a manner that forces/freezes said values either by some sort of check or something that you can set them to be frozen etc, GreenHouse mentioning something about> But if it's LUA settings, then you could add a timer that keeps setting them or that checks each value, not sure how good that would be performance wise though."

not sure :?
I don't understand how you can't get it to work. You select the records you want enabled, hit save state, enter your profile name and click ok. Then disable everything and hit enable and select your profile name.

Also, by populating pointers I don't mean that the game has loaded, I mean the table itself which is completely different.

User avatar
dreamcactus
Expert Cheater
Expert Cheater
Posts: 144
Joined: Sat Jul 06, 2019 12:21 pm
Reputation: 0

Re: Request for CT Automation Feature

Post by dreamcactus »

yeah i selected my cheats i want enabled , hit save state, entered profile name and then i saved table , then exited table and restarted table...nothing enabled no values loaded

User avatar
dreamcactus
Expert Cheater
Expert Cheater
Posts: 144
Joined: Sat Jul 06, 2019 12:21 pm
Reputation: 0

Re: Request for CT Automation Feature

Post by dreamcactus »

DrummerIX wrote:
Sun Jul 04, 2021 8:24 pm
I won't be able to debug it until Tuesday. If no one has helped you, I will try again then.
thanks man , countin on ya since you seem to be the only one on actually trying to solve it , never is easy with me is it , me and my special requests :?

DrummerIX
ViP
ViP
Posts: 3228
Joined: Wed Mar 22, 2017 6:15 pm
Reputation: 3740

Re: Request for CT Automation Feature

Post by DrummerIX »

I made it back to a computer.

I looked over the code and in theory I removed the check for the AUTO SET in front of memory records. I don't actually have time to fully debug it right now as it is still technically Monday night in USA.

I can see where one might need something like this functionality especially for large tables like some of mine are. I'm probably not allowed to use this code, so will have to code something a little different if I want to add this functionality to some of trainer apps if it works there at all.

Anyway, here is my edit:

Code: Select all

local format = string.format
local strE = string.empty or STRING_EMPTY or ''
local t = translate
if AddressList == nil then
	AddressList = getAddressList()
end
if MainForm == nil then
	MainForm = getMainForm()
end


if getCEVersion == nil or getCEVersion() < 6.5 then
	messageDialog('It is recommended to use at least Cheat Engine 6.7! (Your Version: '..getCEVersion()..')', mtError, mbOK)
end

errorOnLookupFailure(false)
setGlobalDelayBetweenHotkeyActivation(200)
DefaultProccessName = "pcsx2.exe"
strings_add(getAutoAttachList(), DefaultProccessName)

PRIVATETABLE, SWITCHSUPPORT = true, false

function cycleFullCompact(sender,force)
	local state = not(compactmenuitem.Caption == 'Compact View Mode')
	if force~=nil then state = not force end
	compactmenuitem.Caption = state and 'Compact View Mode' or 'Full View Mode'
	getMainForm().Splitter1.Visible = state
	getMainForm().Panel4.Visible = state
	getMainForm().Panel5.Visible = state
end

function addCompactMenu()
	if compactmenualreadyexists then return end
	local parent = getMainForm().Menu.Items
	compactmenuitem = createMenuItem(parent); parent.add(compactmenuitem)
	compactmenuitem.Caption = 'Compact View Mode'
	compactmenuitem.OnClick = cycleFullCompact
	compactmenualreadyexists = 'yes'
end
addCompactMenu()
cycleFullCompact(nil, true)


----
--
---- Logger
	local Logger = {
		LEVELS = {
			OFF = 0,
			FATAL = 1,
			ERROR = 2,
			WARN = 3,
			INFO = 4,
			DEBUG = 5,
			TRACE = 6
		},
		Level = 0,
	}
	for k, v in pairs(Logger.LEVELS) do
		Logger[k:lower()] = function( ... ) return end
		Logger[k:lower() .. 'f'] = function( ... ) return end
		-- Logger[k:lower()] = function(msg, ex) return print(msg, ex) end
		-- Logger[k:lower() .. 'f'] = function(msg, ... ) return print(string.format(msg, ... )) end
	end

--
---- Helpers
	local function split(s, delimiter)
		result = {}
		for match in (s .. delimiter):gmatch('(.-)' .. delimiter) do
			table.insert(result, match)
		end
		return result
	end
	local function interp(s, tbl)
		if s == nil then return end
		return (s:gsub('($%b{})', function(w) return tbl[w:sub(3, -2)] or w end))
	end


--
---- I2CETState
I2CETState = {
	--
	---- Settings
	DefaultState = 'default',
	SaveFileName = 'I2CETState.${StateName}.txt',
	UseMemoryRecordDescriptions = false,
	LineEnd = '\n',
	DisableBeforeLoad = true,
	PrintStatus = false, --true,
	SaveValueMatch = 'AUTO SET:',
	LineDelimiter = '',
	ScriptID = 'I2CETStateSCRIPTID',
	BlackList = {
		['_[  I2CETState  ]_'] = true,
		['_[  Save Table State  ]_'] = true,
		['_[  Load Table State  ]_'] = true,
	},
}


function I2CETState.saveTableState(stateName)
	if not inMainThread() then
		synchronize(function(thread)
			I2CETState.saveTableState(stateName)
		end)
		return
	end
	Logger.trace()
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		getLuaEngine().show()
	end
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		print(format('Saving Table State:  %s', stateName))
	end
	local le = I2CETState.LineEnd
	local ld = I2CETState.LineDelimiter
	local sid = I2CETState.ScriptID
	local svm = I2CETState.SaveValueMatch
	if stateName == nil then
		stateName = I2CETState.DefaultState
	end
	local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
	Logger.debugf('Using state file name: "%s"', fileName)
	local fileStr = strE
	for i = 0, AddressList.Count - 1 do
		local mr = AddressList.getMemoryRecord(i)
		if I2CETState.BlackList[mr.Description] ~= true
		and mr.Description:sub(0, 16) ~= 'Load Table State'
		and mr.Description:sub(0, 16) ~= 'Save Table State' then
			local id = tostring(mr.ID)
			if I2CETState.UseMemoryRecordDescriptions then
				id = mr.Description
			end
			if mr.Type == vtAutoAssembler and mr.Active then
				Logger.debugf('Saving script state: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
				fileStr = fileStr..id..ld..sid..ld..tostring(mr.Active)..le
			elseif mr.Value ~= '??' then
				Logger.debugf('Saving value: %d, %d, "%s", %s', mr.Index, mr.ID, mr.Description, mr.Value)
				fileStr = fileStr..id..ld..mr.Value..ld..tostring(mr.Active)..le
			end
		end
	end
	local f, err = io.open(fileName, 'w')
	if err then
		Logger.errorf('The file could not be opened, "%s", %s', fileName, err)
	elseif f and not err then
		f:write(fileStr)
		f:close()
	end
end
saveTableState = I2CETState.saveTableState


function I2CETState.loadTableState(stateName)
	if not inMainThread() then
		synchronize(function(thread)
			I2CETState.loadTableState(stateName)
		end)
		return
	end
	Logger.trace()
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		getLuaEngine().show()
	end
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		print(format('Setting Table State:  %s', stateName))
	end
	local le = I2CETState.LineEnd
	local ld = I2CETState.LineDelimiter
	local sid = I2CETState.ScriptID
	local svm = I2CETState.SaveValueMatch
	if stateName == nil then
		stateName = I2CETState.DefaultState
	end
	local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
	Logger.debugf('Using state file name: "%s"', fileName)
	local fileStr = nil
	local f, err = io.open(fileName, 'r')
	if err then
		Logger.infof('The local file could not be opened, "%s", %s', fileName, err)
		local tableFile = findTableFile(fileName)
		if tableFile == nil then
			Logger.warnf('file not found, "%s"', fileName)
			return
		end
		local stream = tableFile.getData()
		local bytes = stream.read(stream.Size)
		for i = 1, #bytes do
			if fileStr == nil then
				fileStr = strE
			end
			fileStr = fileStr .. string.char(bytes[i])
		end
	elseif f and not err then
		fileStr = f:read('*all')
		f:close()
	else
		Logger.errorf('The file could not be opened, "%s"', fileName)
	end
	if I2CETState.DisableBeforeLoad then
		for i = AddressList.Count - 1, 0, -1 do
			local mr = AddressList.getMemoryRecord(i)
			if I2CETState.BlackList[mr.Description] ~= true
			and mr.Description:sub(0, 16) ~= 'Load Table State'
			and mr.Description:sub(0, 16) ~= 'Save Table State' then
				if mr.Active then
					Logger.infof('Disabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
					if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
						print(format('Disabling:  %s', mr.Description))
					end
					mr.Active = false
					while mr.Async and mr.AsyncProcessing do
						checkSynchronize()
					end
					sleep(0)
				end
			end
		end
		sleep(0)
	end
	if fileStr == nil then
		Logger.info('File string was nil')
		return
	end
	local lines = split(fileStr, I2CETState.LineEnd)
	for i, v in ipairs(lines) do
		if v ~= nil and v ~= strE then
			local data = split(v, I2CETState.LineDelimiter)
			local mr = nil
			if I2CETState.UseMemoryRecordDescriptions then
				mr = AddressList.getMemoryRecordByDescription(data[1])
			else
				mr = AddressList.getMemoryRecordByID(tonumber(data[1]))
			end
			if mr ~= nil then
				if mr.Type == vtAutoAssembler and mr.Active == false
				and data[2] == sid and data[3] == tostring(true) then
					Logger.infof('Enabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
					if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
						print(format('Enabling:  "%s"', mr.Description))
					end
					mr.Active = true
					while mr.Async and mr.AsyncProcessing do
						checkSynchronize()
					end
					sleep(0)
				elseif mr.Type ~= vtAutoAssembler then
					if mr.Value == '??' then
						Logger.warnf('Memory record value not set: %d, %d, "%s", "%s"', mr.Index, mr.ID, mr.Description, mr.Value)
						if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
							print(format('Memory record value not set:  "%s", "%s"', mr.Description, mr.Value))
						end
					else
						Logger.infof('Setting memory record: %d, %d, "%s", %s, %s', mr.Index, mr.ID, mr.Description, data[1], data[2])
						if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
							print(format('Setting:  "%s", %s', mr.Description, data[2]))
						end
						mr.Value = data[2]
						if data[3] == tostring(true) then
							mr.Active = true
						end
					end
				end
			else
				Logger.errorf('Memory record not found: "%s", "%s", "%s"', data[1], data[2], v)
			end
		end
	end
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		print(format('Table State Set:  %s', stateName))
		getLuaEngine().hide()
	end
end
loadTableState = I2CETState.loadTableState
----


PROCESS_NAME = 'pcsx2.exe'
--------
-------- Auto Attach
--------
local autoAttachTimer = nil ---- variable to hold timer object
local autoAttachTimerInterval = 100 ---- Timer intervals are in milliseconds
local autoAttachTimerTicks = 0 ---- variable to count number of times the timer has run
local autoAttachTimerTickMax = 5000 ---- Set to zero to disable ticks max
local function autoAttachTimer_tick(timer) ---- Timer tick call back
	---- Destroy timer if max ticks is reached
	if autoAttachTimerTickMax > 0 and autoAttachTimerTicks >= autoAttachTimerTickMax then
		timer.destroy()
	end
	---- Check if process is running
	if getProcessIDFromProcessName(PROCESS_NAME) ~= nil then
		timer.destroy() ---- Destroy timer
		openProcess(PROCESS_NAME) ---- Open the process
		--
		--
		---- Just a way to do this with the NameList,
		----     thus you can just add to the list to make it work with other memory records.

	end
	autoAttachTimerTicks = autoAttachTimerTicks + 1 ---- Increase ticks
end
autoAttachTimer = createTimer(getMainForm()) ---- Create timer with the main form as it's parent
autoAttachTimer.Interval = autoAttachTimerInterval ---- Set timer interval
autoAttachTimer.OnTimer = autoAttachTimer_tick ---- Set timer tick call back
If this don't work I will actually test it myself tomorrow.

User avatar
dreamcactus
Expert Cheater
Expert Cheater
Posts: 144
Joined: Sat Jul 06, 2019 12:21 pm
Reputation: 0

Re: Request for CT Automation Feature

Post by dreamcactus »

right? good to see im not the only one that needs this feature, been wanting this for a looong time actually just never managed to post up a request , or more like never thought anyone would care to take it up, not many people do requests around the coding community not just CE , theyre usually more of trying to teach folks coding from scratch instead of actually giving a solution :( , thanks man ill get back atcha with test results, really appreciate this , means alot :)

User avatar
dreamcactus
Expert Cheater
Expert Cheater
Posts: 144
Joined: Sat Jul 06, 2019 12:21 pm
Reputation: 0

Re: Request for CT Automation Feature

Post by dreamcactus »

update> ok , nope still dont save settings to whatever profile you choose to have it save to, since for example saving to casual , well the I2CETState.casual.txt is empty , should be showing enabled cheats and values saved , but is empty and on fresh start of CT again , nothing enabled no values entered and frozen, gonna be a tough cookie to crack :mellow: , also no expert but you still seem to have the prefix requirement in the code >


SaveValueMatch = 'AUTO SET:', :|

DrummerIX
ViP
ViP
Posts: 3228
Joined: Wed Mar 22, 2017 6:15 pm
Reputation: 3740

Re: Request for CT Automation Feature

Post by DrummerIX »

I remove the code that uses it though, so do you also just make an option called Save and it calls the save function. Perhaps that is where the mix up is.

I was a little busy making the Final Fantasy XII The Zodiac Age Trainer today, but I'll take a look at this tonight.

DrummerIX
ViP
ViP
Posts: 3228
Joined: Wed Mar 22, 2017 6:15 pm
Reputation: 3740

Re: Request for CT Automation Feature

Post by DrummerIX »

Okay, I have debugged things and tested this as working in one of my tables.

Here is code I put in the Luascript portion of the table. This is in xml format, so I edit my files with a text editor anyway.

Code: Select all

local format = string.format
local strE = string.empty or STRING_EMPTY or ''
local t = translate
if AddressList == nil then
	AddressList = getAddressList()
end
if MainForm == nil then
	MainForm = getMainForm()
end


if getCEVersion == nil or getCEVersion() &lt; 6.5 then
	messageDialog('It is recommended to use at least Cheat Engine 6.7! (Your Version: '..getCEVersion()..')', mtError, mbOK)
end

errorOnLookupFailure(false)
setGlobalDelayBetweenHotkeyActivation(200)
DefaultProccessName = "pcsx2.exe"
strings_add(getAutoAttachList(), DefaultProccessName)

PRIVATETABLE, SWITCHSUPPORT = true, false

----
--
---- Logger
	local Logger = {
		LEVELS = {
			OFF = 0,
			FATAL = 1,
			ERROR = 2,
			WARN = 3,
			INFO = 4,
			DEBUG = 5,
			TRACE = 6
		},
		Level = 0,
	}
	for k, v in pairs(Logger.LEVELS) do
		Logger[k:lower()] = function( ... ) return end
		Logger[k:lower() .. 'f'] = function( ... ) return end
		-- Logger[k:lower()] = function(msg, ex) return print(msg, ex) end
		-- Logger[k:lower() .. 'f'] = function(msg, ... ) return print(string.format(msg, ... )) end
	end

--
---- Helpers
	local function split(s, delimiter)
		result = {}
		for match in (s .. delimiter):gmatch('(.-)' .. delimiter) do
			table.insert(result, match)
		end
		return result
	end
	local function interp(s, tbl)
		if s == nil then return end
		return (s:gsub('($%b{})', function(w) return tbl[w:sub(3, -2)] or w end))
	end


--
---- I2CETState
I2CETState = {
	--
	---- Settings
	DefaultState = 'default',
	SaveFileName = 'I2CETState.${StateName}.txt',
	UseMemoryRecordDescriptions = false,
	LineEnd = '\n',
	DisableBeforeLoad = true,
	PrintStatus = false, --true,
	SaveValueMatch = 'AUTO SET:',
	LineDelimiter = ',',
	ScriptID = 'I2CETStateSCRIPTID',
	BlackList = {
		['_[  I2CETState  ]_'] = true,
		['_[  Save Table State  ]_'] = true,
		['_[  Load Table State  ]_'] = true,
	},
}


function I2CETState.saveTableState(stateName)
	if not inMainThread() then
		synchronize(function(thread)
			I2CETState.saveTableState(stateName)
		end)
		return
	end
	Logger.trace()
	if I2CETState.PrintStatus and Logger.Level &lt;= Logger.LEVELS.WARN then
		getLuaEngine().show()
	end
	if I2CETState.PrintStatus and Logger.Level &lt;= Logger.LEVELS.WARN then
		print(format('Saving Table State:  %s', stateName))
	end
	local le = I2CETState.LineEnd
	local ld = I2CETState.LineDelimiter
	local sid = I2CETState.ScriptID
	local svm = I2CETState.SaveValueMatch
	if stateName == nil then
		stateName = I2CETState.DefaultState
	end
	local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
	Logger.debugf('Using state file name: "%s"', fileName)
	local fileStr = strE
	for i = 0, AddressList.Count - 1 do
		local mr = AddressList.getMemoryRecord(i)
		if I2CETState.BlackList[mr.Description] ~= true
		and mr.Description:sub(0, 16) ~= 'Load Table State'
		and mr.Description:sub(0, 16) ~= 'Save Table State' then
			local id = tostring(mr.ID)
			if I2CETState.UseMemoryRecordDescriptions then
				id = mr.Description
			end
			if mr.Type == vtAutoAssembler and mr.Active then
				Logger.debugf('Saving script state: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
				fileStr = fileStr..id..ld..sid..ld..tostring(mr.Active)..le
			elseif mr.Value ~= '??' then
				Logger.debugf('Saving value: %d, %d, "%s", %s', mr.Index, mr.ID, mr.Description, mr.Value)
				fileStr = fileStr..id..ld..mr.Value..ld..tostring(mr.Active)..le
			end
		end
	end
	local f, err = io.open(fileName, 'w')
	if err then
		Logger.errorf('The file could not be opened, "%s", %s', fileName, err)
	elseif f and not err then
		f:write(fileStr)
		f:close()
	end
end
saveTableState = I2CETState.saveTableState


function I2CETState.loadTableState(stateName)
	if not inMainThread() then
		synchronize(function(thread)
			I2CETState.loadTableState(stateName)
		end)
		return
	end
	Logger.trace()
	if I2CETState.PrintStatus and Logger.Level &lt;= Logger.LEVELS.WARN then
		getLuaEngine().show()
	end
	if I2CETState.PrintStatus and Logger.Level &lt;= Logger.LEVELS.WARN then
		print(format('Setting Table State:  %s', stateName))
	end
	local le = I2CETState.LineEnd
	local ld = I2CETState.LineDelimiter
	local sid = I2CETState.ScriptID
	local svm = I2CETState.SaveValueMatch
	if stateName == nil then
		stateName = I2CETState.DefaultState
	end
	local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
	Logger.debugf('Using state file name: "%s"', fileName)
	local fileStr = nil
	local f, err = io.open(fileName, 'r')
	if err then
		Logger.infof('The local file could not be opened, "%s", %s', fileName, err)
		local tableFile = findTableFile(fileName)
		if tableFile == nil then
			Logger.warnf('file not found, "%s"', fileName)
			return
		end
		local stream = tableFile.getData()
		local bytes = stream.read(stream.Size)
		for i = 1, #bytes do
			if fileStr == nil then
				fileStr = strE
			end
			fileStr = fileStr .. string.char(bytes[i])
		end
	elseif f and not err then
		fileStr = f:read('*all')
		f:close()
	else
		Logger.errorf('The file could not be opened, "%s"', fileName)
	end
	if I2CETState.DisableBeforeLoad then
		for i = AddressList.Count - 1, 0, -1 do
			local mr = AddressList.getMemoryRecord(i)
			if I2CETState.BlackList[mr.Description] ~= true
			and mr.Description:sub(0, 16) ~= 'Load Table State'
			and mr.Description:sub(0, 16) ~= 'Save Table State' then
				if mr.Active then
					Logger.infof('Disabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
					if I2CETState.PrintStatus and Logger.Level &lt;= Logger.LEVELS.WARN then
						print(format('Disabling:  %s', mr.Description))
					end
					mr.Active = false
					while mr.Async and mr.AsyncProcessing do
						checkSynchronize()
					end
					sleep(0)
				end
			end
		end
		sleep(0)
	end
	if fileStr == nil then
		Logger.info('File string was nil')
		return
	end
	local lines = split(fileStr, I2CETState.LineEnd)
	for i, v in ipairs(lines) do
		if v ~= nil and v ~= strE then
			local data = split(v, I2CETState.LineDelimiter)
			local mr = nil
			if I2CETState.UseMemoryRecordDescriptions then
				mr = AddressList.getMemoryRecordByDescription(data[1])
			else
				mr = AddressList.getMemoryRecordByID(tonumber(data[1]))
			end
			if mr ~= nil then
				if mr.Type == vtAutoAssembler and mr.Active == false
				and data[2] == sid and data[3] == tostring(true) then
					Logger.infof('Enabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
					if I2CETState.PrintStatus and Logger.Level &lt;= Logger.LEVELS.WARN then
						print(format('Enabling:  "%s"', mr.Description))
					end
					mr.Active = true
					while mr.Async and mr.AsyncProcessing do
						checkSynchronize()
					end
					sleep(0)
				elseif mr.Type ~= vtAutoAssembler then
					if mr.Value == '??' then
						Logger.warnf('Memory record value not set: %d, %d, "%s", "%s"', mr.Index, mr.ID, mr.Description, mr.Value)
						if I2CETState.PrintStatus and Logger.Level &lt;= Logger.LEVELS.WARN then
							print(format('Memory record value not set:  "%s", "%s"', mr.Description, mr.Value))
						end
					else
						Logger.infof('Setting memory record: %d, %d, "%s", %s, %s', mr.Index, mr.ID, mr.Description, data[1], data[2])
						if I2CETState.PrintStatus and Logger.Level &lt;= Logger.LEVELS.WARN then
							print(format('Setting:  "%s", %s', mr.Description, data[2]))
						end
						mr.Value = data[2]
						if data[3] == tostring(true) then
							mr.Active = true
						end
					end
				end
			else
				Logger.errorf('Memory record not found: "%s", "%s", "%s"', data[1], data[2], v)
			end
		end
	end
	if I2CETState.PrintStatus and Logger.Level &lt;= Logger.LEVELS.WARN then
		print(format('Table State Set:  %s', stateName))
		getLuaEngine().hide()
	end
end
loadTableState = I2CETState.loadTableState
----
I then have these 2 options in the table near the top:

Code: Select all

                <CheatEntry>
                  <ID>198</ID>
                  <Description>"Save Table State"</Description>
                  <Options moHideChildren="1"/>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
{$lua}

I2CETState.saveTableState('casual')

{$asm}

[DISABLE]

</AssemblerScript>
				</CheatEntry>
                <CheatEntry>
                  <ID>199</ID>
                  <Description>"Load Table State"</Description>
                  <Options moHideChildren="1"/>
                  <VariableType>Auto Assembler Script</VariableType>
                  <AssemblerScript>[ENABLE]
{$lua}

I2CETState.loadTableState('casual')

{$asm}

[DISABLE]

</AssemblerScript>
				</CheatEntry>
It worked in my tests. It only saves to one profile, but it works.

User avatar
dreamcactus
Expert Cheater
Expert Cheater
Posts: 144
Joined: Sat Jul 06, 2019 12:21 pm
Reputation: 0

Re: Request for CT Automation Feature

Post by dreamcactus »

thanks man , lemme give it a try

User avatar
dreamcactus
Expert Cheater
Expert Cheater
Posts: 144
Joined: Sat Jul 06, 2019 12:21 pm
Reputation: 0

Re: Request for CT Automation Feature

Post by dreamcactus »

ok so where do i add the 2nd portion of the code , dont quite get it

maybe a CT so i can just simply copy them over to my CTs? if its too much work

DrummerIX
ViP
ViP
Posts: 3228
Joined: Wed Mar 22, 2017 6:15 pm
Reputation: 3740

Re: Request for CT Automation Feature

Post by DrummerIX »

Here are the options in CT format. All you do here is copy and then past it into CE.

Save Table State:

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<CheatTable>
  <CheatEntries>
    <CheatEntry>
      <ID>198</ID>
      <Description>"Save Table State"</Description>
      <Options moHideChildren="1"/>
      <LastState/>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
{$lua}

I2CETState.saveTableState('casual')

{$asm}

[DISABLE]

</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
</CheatTable>
Load Table State:

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<CheatTable>
  <CheatEntries>
    <CheatEntry>
      <ID>199</ID>
      <Description>"Load Table State"</Description>
      <Options moHideChildren="1"/>
      <LastState/>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]
{$lua}

I2CETState.loadTableState('casual')

{$asm}

[DISABLE]

</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
</CheatTable>
Now the LUA code I posted goes in the Lua Table portion of the CT. I do this in the text file, but to do it in CE, do the following:

Go to Table -> Show Cheat Table LUA Script

Paste the following there (It's a little different than above):

Code: Select all

local format = string.format
local strE = string.empty or STRING_EMPTY or ''
local t = translate
if AddressList == nil then
	AddressList = getAddressList()
end
if MainForm == nil then
	MainForm = getMainForm()
end


if getCEVersion == nil or getCEVersion() < 6.5 then
	messageDialog('It is recommended to use at least Cheat Engine 6.7! (Your Version: '..getCEVersion()..')', mtError, mbOK)
end

errorOnLookupFailure(false)
setGlobalDelayBetweenHotkeyActivation(200)
DefaultProccessName = "pcsx2.exe"
strings_add(getAutoAttachList(), DefaultProccessName)

PRIVATETABLE, SWITCHSUPPORT = true, false

----
--
---- Logger
	local Logger = {
		LEVELS = {
			OFF = 0,
			FATAL = 1,
			ERROR = 2,
			WARN = 3,
			INFO = 4,
			DEBUG = 5,
			TRACE = 6
		},
		Level = 0,
	}
	for k, v in pairs(Logger.LEVELS) do
		Logger[k:lower()] = function( ... ) return end
		Logger[k:lower() .. 'f'] = function( ... ) return end
		-- Logger[k:lower()] = function(msg, ex) return print(msg, ex) end
		-- Logger[k:lower() .. 'f'] = function(msg, ... ) return print(string.format(msg, ... )) end
	end

--
---- Helpers
	local function split(s, delimiter)
		result = {}
		for match in (s .. delimiter):gmatch('(.-)' .. delimiter) do
			table.insert(result, match)
		end
		return result
	end
	local function interp(s, tbl)
		if s == nil then return end
		return (s:gsub('($%b{})', function(w) return tbl[w:sub(3, -2)] or w end))
	end


--
---- I2CETState
I2CETState = {
	--
	---- Settings
	DefaultState = 'default',
	SaveFileName = 'I2CETState.${StateName}.txt',
	UseMemoryRecordDescriptions = false,
	LineEnd = '\n',
	DisableBeforeLoad = true,
	PrintStatus = false, --true,
	SaveValueMatch = 'AUTO SET:',
	LineDelimiter = ',',
	ScriptID = 'I2CETStateSCRIPTID',
	BlackList = {
		['_[  I2CETState  ]_'] = true,
		['_[  Save Table State  ]_'] = true,
		['_[  Load Table State  ]_'] = true,
	},
}


function I2CETState.saveTableState(stateName)
	if not inMainThread() then
		synchronize(function(thread)
			I2CETState.saveTableState(stateName)
		end)
		return
	end
	Logger.trace()
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		getLuaEngine().show()
	end
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		print(format('Saving Table State:  %s', stateName))
	end
	local le = I2CETState.LineEnd
	local ld = I2CETState.LineDelimiter
	local sid = I2CETState.ScriptID
	local svm = I2CETState.SaveValueMatch
	if stateName == nil then
		stateName = I2CETState.DefaultState
	end
	local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
	Logger.debugf('Using state file name: "%s"', fileName)
	local fileStr = strE
	for i = 0, AddressList.Count - 1 do
		local mr = AddressList.getMemoryRecord(i)
		if I2CETState.BlackList[mr.Description] ~= true
		and mr.Description:sub(0, 16) ~= 'Load Table State'
		and mr.Description:sub(0, 16) ~= 'Save Table State' then
			local id = tostring(mr.ID)
			if I2CETState.UseMemoryRecordDescriptions then
				id = mr.Description
			end
			if mr.Type == vtAutoAssembler and mr.Active then
				Logger.debugf('Saving script state: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
				fileStr = fileStr..id..ld..sid..ld..tostring(mr.Active)..le
			elseif mr.Value ~= '??' then
				Logger.debugf('Saving value: %d, %d, "%s", %s', mr.Index, mr.ID, mr.Description, mr.Value)
				fileStr = fileStr..id..ld..mr.Value..ld..tostring(mr.Active)..le
			end
		end
	end
	local f, err = io.open(fileName, 'w')
	if err then
		Logger.errorf('The file could not be opened, "%s", %s', fileName, err)
	elseif f and not err then
		f:write(fileStr)
		f:close()
	end
end
saveTableState = I2CETState.saveTableState


function I2CETState.loadTableState(stateName)
	if not inMainThread() then
		synchronize(function(thread)
			I2CETState.loadTableState(stateName)
		end)
		return
	end
	Logger.trace()
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		getLuaEngine().show()
	end
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		print(format('Setting Table State:  %s', stateName))
	end
	local le = I2CETState.LineEnd
	local ld = I2CETState.LineDelimiter
	local sid = I2CETState.ScriptID
	local svm = I2CETState.SaveValueMatch
	if stateName == nil then
		stateName = I2CETState.DefaultState
	end
	local fileName = interp(I2CETState.SaveFileName, { StateName = stateName } )
	Logger.debugf('Using state file name: "%s"', fileName)
	local fileStr = nil
	local f, err = io.open(fileName, 'r')
	if err then
		Logger.infof('The local file could not be opened, "%s", %s', fileName, err)
		local tableFile = findTableFile(fileName)
		if tableFile == nil then
			Logger.warnf('file not found, "%s"', fileName)
			return
		end
		local stream = tableFile.getData()
		local bytes = stream.read(stream.Size)
		for i = 1, #bytes do
			if fileStr == nil then
				fileStr = strE
			end
			fileStr = fileStr .. string.char(bytes[i])
		end
	elseif f and not err then
		fileStr = f:read('*all')
		f:close()
	else
		Logger.errorf('The file could not be opened, "%s"', fileName)
	end
	if I2CETState.DisableBeforeLoad then
		for i = AddressList.Count - 1, 0, -1 do
			local mr = AddressList.getMemoryRecord(i)
			if I2CETState.BlackList[mr.Description] ~= true
			and mr.Description:sub(0, 16) ~= 'Load Table State'
			and mr.Description:sub(0, 16) ~= 'Save Table State' then
				if mr.Active then
					Logger.infof('Disabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
					if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
						print(format('Disabling:  %s', mr.Description))
					end
					mr.Active = false
					while mr.Async and mr.AsyncProcessing do
						checkSynchronize()
					end
					sleep(0)
				end
			end
		end
		sleep(0)
	end
	if fileStr == nil then
		Logger.info('File string was nil')
		return
	end
	local lines = split(fileStr, I2CETState.LineEnd)
	for i, v in ipairs(lines) do
		if v ~= nil and v ~= strE then
			local data = split(v, I2CETState.LineDelimiter)
			local mr = nil
			if I2CETState.UseMemoryRecordDescriptions then
				mr = AddressList.getMemoryRecordByDescription(data[1])
			else
				mr = AddressList.getMemoryRecordByID(tonumber(data[1]))
			end
			if mr ~= nil then
				if mr.Type == vtAutoAssembler and mr.Active == false
				and data[2] == sid and data[3] == tostring(true) then
					Logger.infof('Enabling memory record: %d, %d, "%s"', mr.Index, mr.ID, mr.Description)
					if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
						print(format('Enabling:  "%s"', mr.Description))
					end
					mr.Active = true
					while mr.Async and mr.AsyncProcessing do
						checkSynchronize()
					end
					sleep(0)
				elseif mr.Type ~= vtAutoAssembler then
					if mr.Value == '??' then
						Logger.warnf('Memory record value not set: %d, %d, "%s", "%s"', mr.Index, mr.ID, mr.Description, mr.Value)
						if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
							print(format('Memory record value not set:  "%s", "%s"', mr.Description, mr.Value))
						end
					else
						Logger.infof('Setting memory record: %d, %d, "%s", %s, %s', mr.Index, mr.ID, mr.Description, data[1], data[2])
						if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
							print(format('Setting:  "%s", %s', mr.Description, data[2]))
						end
						mr.Value = data[2]
						if data[3] == tostring(true) then
							mr.Active = true
						end
					end
				end
			else
				Logger.errorf('Memory record not found: "%s", "%s", "%s"', data[1], data[2], v)
			end
		end
	end
	if I2CETState.PrintStatus and Logger.Level <= Logger.LEVELS.WARN then
		print(format('Table State Set:  %s', stateName))
		getLuaEngine().hide()
	end
end
loadTableState = I2CETState.loadTableState
----
That should work I believe.

User avatar
dreamcactus
Expert Cheater
Expert Cheater
Posts: 144
Joined: Sat Jul 06, 2019 12:21 pm
Reputation: 0

Re: Request for CT Automation Feature

Post by dreamcactus »

lemme try that...

User avatar
dreamcactus
Expert Cheater
Expert Cheater
Posts: 144
Joined: Sat Jul 06, 2019 12:21 pm
Reputation: 0

Re: Request for CT Automation Feature

Post by dreamcactus »

yeps works perfect now! , BUT wont autoload on fresh startup , lua code seems to be missing that, seems to be missing autoload last profile settings , since theres only 1 profile setting available atm , and you gots to manually click on load, btw not for me but maybe for others include a option to have multiple different Profile settings, like 3 or 4, so close my dude sooo close , this is gonna make CE ALOT more userfriendly for sure imo, essentially turning CTs into Trainers without the hassle also many CTs out there that never get a full blown Trainer treatment , those folks will then also have the great user-experience , so i recon my finished request will be a positive one for all of us 8-)

btw have you also included a function to make sure set values are always at theyre set value depending on profile , to make sure game doesnt override it? if not would appreciate it, bit of a tall order all of it , but def need this, thanks

Post Reply

Who is online

Users browsing this forum: admantx, Livaliz, samjooma