Re: z Baldur's Gate 3
Posted: Wed Jan 24, 2024 11:01 pm
Silly request, but seems the game has an issue where folks are having getting a black haired portrait to a Selune aligned Shadowheart. Was hoping there was a fix via Cheat Engine.
Community Cheat Tables of Cheat Engine
https://fearlessrevolution.com/
quoting the solution to the trader problemSenorPlebeian wrote: ↑Mon Jan 01, 2024 12:20 pmIn further examination of this, I think I figured out how to fix Last Trade Vendor's AOB. After downgrading my version of BG3 to when the script last worked to try to reverse engineer how the function was originally found, I ended up actually looking through Zanzer's script for loading console commands and it made me realize I could just follow the function of ActivateTrade to its function in memory via the address he loads in the register symbol. Sure enough I realized only then (or perhaps it's some strange remnant of the many times I was running through trying to dissect the code) that it also just straight up puts a reference to ActivateTrade for Goto Address.SenorPlebeian wrote: ↑Fri Dec 29, 2023 5:26 amHasn't been working on my end either.ctulloch137 wrote: ↑Thu Dec 28, 2023 8:54 pmIs the last trade vendor cheat working for anyone? most everything else seems to still be working fine for me, but I use that one when I encounter new vendors to be able to go through their full stock (resetting), and clicking it in cheat engine now just does nothing, doesnt expand the options.
Not entirely sure how the AOB for the ActivateTrade function was found as I've mostly only dabbled in finding AOBs via it accessing a value in memory, which in this case I've found 100+ results for a vendor's UUID when doing a string search. The string it's referencing may very well be a value in RAM that's swiftly getting overwritten after the time of the function call and well after my scan, so I haven't really attempted to try to brute force through all the results for a hit. I figured since it hasn't been brought up in the last 100 or so pages on this thread, no one else was running into the issue and it might have just been the table I downloaded down, so I haven't attempted to fix it beyond that.
Thus far my short-term workaround has been to set up the script to instead let me input in the vendor's UUID which I grab off of the unpacked gustav dev files and have the script call the console commands with that instead. Unfortunately, this is a bit of a cumbersome experience without a proper mapping of the vendor to their UUID.
I think that this should have enough wildcards in its AOB to work, I only tested this against one merchant with a few restarts with the sleep deprivation that comes with being up at 4 AM, but I think I managed to get the script working again on my end:
I am using dx11, so I'm not sure if that changes anything with the functions its calling, but replacing the existing script with this worked on my end.Code: Select all
{ ActivateTrade( Player, Trader, CanSell, TradeMode, InitiallySelectedTradeObject, ItemsTagFilter ) } [ENABLE] aobscanmodule(trade,$process,48 33 ?? 48 89 ?? ?? 48 8B ?? 48 8B ?? E8 ?? ?? ?? ?? ?? 8B ?? 48 8D ?? ?? E8 ?? ?? ?? ?? 4C 8B F8) alloc(newmem,$1000,trade) label(tradePC) label(tradeNPC) label(tradeBkp) label(return) newmem: mov rbx,tradePC mov rax,[rdx+08] test rax,rax je @f mov rcx,[rax+00] mov [rbx+00],rcx mov rcx,[rax+08] mov [rbx+08],rcx mov rcx,[rax+10] mov [rbx+10],rcx mov rcx,[rax+18] mov [rbx+18],rcx mov rcx,[rax+20] mov [rbx+20],rcx mov rcx,[rax+28] mov [rbx+28],rcx mov rcx,[rax+30] mov [rbx+30],rcx mov rcx,[rax+38] mov [rbx+38],rcx mov rbx,tradeNPC mov rax,[rdx+18] test rax,rax je @f mov rcx,[rax+00] mov [rbx+00],rcx mov rcx,[rax+08] mov [rbx+08],rcx mov rcx,[rax+10] mov [rbx+10],rcx mov rcx,[rax+18] mov [rbx+18],rcx mov rcx,[rax+20] mov [rbx+20],rcx mov rcx,[rax+28] mov [rbx+28],rcx mov rcx,[rax+30] mov [rbx+30],rcx mov rcx,[rax+38] mov [rbx+38],rcx mov rcx,[rax+40] mov [rbx+40],rcx mov rcx,[rax+48] mov [rbx+48],rcx mov rcx,[rax+50] mov [rbx+50],rcx mov rcx,[rax+58] mov [rbx+58],rcx tradeBkp: readmem(trade+07,6) jmp return align 10 tradePC: dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 tradeNPC: dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 dq 0 trade+07: jmp newmem nop return: registersymbol(trade) registersymbol(tradeBkp) registersymbol(tradePC) registersymbol(tradeNPC) [DISABLE] trade+07: readmem(tradeBkp,6) unregistersymbol(trade) unregistersymbol(tradeBkp) unregistersymbol(tradePC) unregistersymbol(tradeNPC) dealloc(newmem) { // ORIGINAL CODE - INJECTION POINT: bg3.exe+1431352 bg3.exe+143132F: 55 - push rbp bg3.exe+1431330: 41 54 - push r12 bg3.exe+1431332: 41 55 - push r13 bg3.exe+1431334: 41 56 - push r14 bg3.exe+1431336: 41 57 - push r15 bg3.exe+1431338: 48 8D 6C 24 C9 - lea rbp,[rsp-37] bg3.exe+143133D: 48 81 EC A0 00 00 00 - sub rsp,000000A0 bg3.exe+1431344: 48 8B 05 AD F0 1F 04 - mov rax,[bg3.exe+56303F8] bg3.exe+143134B: 48 33 C4 - xor rax,rsp bg3.exe+143134E: 48 89 45 2F - mov [rbp+2F],rax // ---------- INJECTING HERE ---------- bg3.exe+1431352: 48 8B DA - mov rbx,rdx // ---------- DONE INJECTING ---------- bg3.exe+1431355: 33 D2 - xor edx,edx bg3.exe+1431357: 48 8B CB - mov rcx,rbx bg3.exe+143135A: E8 91 0A CA FF - call bg3.exe+10D1DF0 bg3.exe+143135F: 4C 8B E0 - mov r12,rax bg3.exe+1431362: 48 8D 4B 10 - lea rcx,[rbx+10] bg3.exe+1431366: 33 D2 - xor edx,edx bg3.exe+1431368: E8 83 0A CA FF - call bg3.exe+10D1DF0 bg3.exe+143136D: 4C 8B F8 - mov r15,rax bg3.exe+1431370: 4D 85 E4 - test r12,r12 bg3.exe+1431373: 0F 84 CD 01 00 00 - je bg3.exe+1431546 }
I have never gotten this to work. I'm not even sure what it's supposed to do.Valignat49 wrote: ↑Thu Jan 25, 2024 7:58 amfor some reason last trade vendor isn't working. just scans then doesn't activate
Do you mind posting what this site is?Fane the Eternal wrote: ↑Sat Jan 27, 2024 12:39 amnevermind I found an awesome site that has everything finally! a guy from discord showed me it. so I'll never need help again.
[Link]GoAway896 wrote: ↑Sat Jan 27, 2024 1:03 amDo you mind posting what this site is?Fane the Eternal wrote: ↑Sat Jan 27, 2024 12:39 amnevermind I found an awesome site that has everything finally! a guy from discord showed me it. so I'll never need help again.
make sure you run the script 1st (you will get ? value at first)OhPlzKnotMe wrote: ↑Sat Jan 27, 2024 2:57 amOpening the console commands in CE with the bg3.ct doesn't do anything.
loaded a save and still doesn't do anything.
won't let me post a screenshot into this message box so heres the a link to it
Register Commands
are mostly a matter of timing, which is easily solved by using autoloader script.Cheat Table Lua Script
from the Cheat Engine Table
menu and copy/paste the following code into the window, and press Execute script
. Or just download the attached Cheat Table, which is just Zanzer's v14 table, with the below code added.Code: Select all
bg3setting = {}
bg3setting['ConsoleCommandsControlID'] = 4928
bg3setting['RegisterCommandsControlID'] = 357
bg3setting['Executable'] = { 'bg3_dx11.exe', 'bg3.exe' }
bg3setting['TimerInterval'] = 1000 -- Milliseconds between ticks.
MainForm.OnProcessOpened = function (openedPID, processHandle, caption)
--[[ MainForm.OnProcessOpened
Author: EvenLess
Credit:
https://github.com/cheat-engine/cheat-engine/blob/65b383535cba0325c25b95310137e13b409e75ae/Cheat%20Engine/bin/celua.txt#L377C14-L377C14
Disables Register Commands and Console Commands without executing their "disable" code, when CE is attached to a a new game process.
]]
local memoryRecord = AddressList.getMemoryRecordByID(bg3setting['RegisterCommandsControlID'])
memoryRecord.disableWithoutExecute()
local memoryRecord = AddressList.getMemoryRecordByID(bg3setting['ConsoleCommandsControlID'])
memoryRecord.disableWithoutExecute()
end
local function bg3Timer_callback(timer) -- Tick callback function.
--[[ Timer. Check/execute things ad-hoc.
Author: EvenLess
Credit:
https://wiki.cheatengine.org/index.php?title=Tutorials:Lua:Setup_Auto_Attach
Continously checks/executes various tasks.
]]
local bg3Executable = bg3setting['Executable']
--[[ Find the active game process, if any.
EvenLess
Attempt to find process ID for both bg3 executables (in their specified order).
]]
local actualPID = nil
for i = 1, #bg3Executable do
-- Loop through the bg3Executables to get its PID, if the game is running.
actualPID = getProcessIDFromProcessName(bg3Executable[i])
if actualPID ~= nil then
-- Active BG3 process ID is found, so no need to check further.
break
end
end
local openedPID = getOpenedProcessID()
if actualPID ~= openedPID then
-- Process ID have changed.
-- Disable Register Commands without executing associated "disable" code.
local memoryRecord = AddressList.getMemoryRecordByID(bg3setting['RegisterCommandsControlID'])
memoryRecord.disableWithoutExecute()
-- Disable Console Commands without executing associated "disable" code.
local memoryRecord = AddressList.getMemoryRecordByID(bg3setting['ConsoleCommandsControlID'])
memoryRecord.disableWithoutExecute()
if actualPID ~= nil then
-- Attach to the game process.
local result = openProcess(actualPID)
end
end
local memoryRecord = AddressList.getMemoryRecordByID(bg3setting['ConsoleCommandsControlID'])
if memoryRecord.Active == true then
-- The following code is mostly taken from Zanzer's Register Commands code for checking readiness.
local numberOfCommands = nil
local commandList = readPointer("cmdList")
if commandList ~= nil and commandList ~= 0 then
numberOfCommands = readInteger(commandList + 0x2C)
if numberOfCommands > 0 then
if numberOfCommands > 3000 then
numberOfCommands = 3000
end
end
commandList = readPointer(commandList + 0x20)
if commandList ~= nil and commandList ~= 0 then
local memoryRecord = AddressList.getMemoryRecordByID(bg3setting['RegisterCommandsControlID'])
if memoryRecord.Active ~= true then
-- Enable Register Commands.
memoryRecord.Active = true
end
end
end
else
if actualPID == openedPID then
-- Enable Console Commands.
memoryRecord.Active = true
end
end
end
-- Create the timer and attach the callback function.
local bg3Timer = createTimer(getMainForm()) -- Create timer with the main form as its parent.
bg3Timer.Interval = bg3setting['TimerInterval'] -- Set timer interval.
bg3Timer.OnTimer = bg3Timer_callback -- Set timer tick callback function.