FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Fri Feb 09, 2018 12:46 pm Post subject: |
|
|
Possibly BOM, though I wouldn't think so... regardless
As for a dropdown list I think something like this would work, basically a script that allocates some memory for a nested memory record (which has the list setup), then generates the dropdown list (really only needs to happen once but) and sets a function that runs when it's value is displayed by CE to copy the value (if it's changed) to the address of the Hero record
Code: | <?xml version="1.0" encoding="utf-8"?>
<CheatTable>
<CheatEntries>
<CheatEntry>
<ID>0</ID>
<Description>"Generate list"</Description>
<Options moHideChildren="1"/>
<LastState Activated="1"/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>[ENABLE]
globalalloc(heroesoffset,4)
{$lua}
local autoChange = false
local mr = memrec.Child[0]
local function getStructureIDByName(name)
local lname = name:lower()
local casematch = nil
local count = getStructureCount()-1
for i=0, count do
local struct = getStructure(i)
-- if there are two structs with the exact same name, not my problem if you get the wrong one!
if struct.Name == name then return i
elseif struct.Name:lower() == lname then
if casematch == nil then casematch = i
-- potentially misses case where exact match exists after two caseinsensitive matches
-- ... can fix easily enough with two loops but... people probably shouldn't have that many
-- structures with the same name right? right? I'll find out I guess lol
else return nil, "more than one structure matches when ignoring case"
end
end
end
if casematch then return casematch else return nil, ("No structure with the name '%s' exists"):format(name) end
end
local function getStructureByName(name)
local id, errmsg = getStructureIDByName(name)
if not id then
return nil, errmsg
else
return getStructure(id)
end
end
local heroesStruct = getStructureByName('Heroes')
-- generate list
mr.DropDownList.Clear()
for i=0, heroesStruct.Count-1 do
local element = heroesStruct.getElement(i)
local new = ('%d:+Heroes.%s'):format(element.Offset, element.Name)
mr.DropDownList.add(new)
end
-- setup function to automatically change base Hero offset
local lastValue = nil
mr.OnGetDisplayValue = function(mr,value)
if lastValue == value then return end
-- otherwise update
lastValue = value
local main = getAddressList().getMemoryRecordByDescription('Hero')
-- try to assign back as +Heroes.Name (should always work since it was generated from structure but)
local hero = heroesStruct.getElementByOffset(value)
if hero then
offset = '+Heroes.' .. hero.Name
else
-- default to hex string
offset = ('+%X'):format(offset)
end
main.Address = offset
end
{$asm}
[DISABLE]
</AssemblerScript>
<CheatEntries>
<CheatEntry>
<ID>1</ID>
<Description>"Hero Selection"</Description>
<DropDownList ReadOnly="1" DescriptionOnly="1" DisplayValueAsItem="1">0:+Heroes.Orrin
</DropDownList>
<LastState Value="173160" RealAddress="05FF0000"/>
<VariableType>4 Bytes</VariableType>
<Address>heroesoffset</Address>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
</CheatTable>
|
|
|