Added Gun details to inventory listing and additional filtering rules. It may not interest you but added it here just in case.
Code: Select all
<?xml version="1.0" encoding="utf-8"?>
<CheatTable>
<CheatEntries>
<CheatEntry>
<ID>116563</ID>
<Description>"Inventory"</Description>
<Options moHideChildren="1" moDeactivateChildrenAsWell="1"/>
<Color>00FF00</Color>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
-- key/values in iFields are just ones I thought to bring in that were object types. Did not dig in to find out more about each <shrug>
-- I will leave it to others if you want to expand this more. I just did this for my own amusement.
-- Added sublayer to keep order intact since first match is generally the main object type
-- Note: The order is not the Field ID but weight I put on the object type
InvGV_iFields = {
{0x60, 'BlueprintItemUnlock'},
{0x1B0, 'NarrativeCollectibleItem'},
{0x298, 'RecipeItem'},
{0x1E0, 'ResearchItem'},
{0x190, 'Knowledge'},
{0x160, 'GunItem'},
{0x38, 'AmmoItem'},
{0x40, 'AmmoCasingItem'},
{0x50, 'BearSpearItem'},
{0x58, 'Bed'},
{0x78, 'BowItem'},
{0x48, 'ArrowItem'},
{0x98, 'CharcoalItem'},
{0xA8, 'ClothingItem'},
{0x100, 'FirstAidItem'},
{0xD8, 'EmergencyStim'},
{0xF8, 'FireStarterItem'},
{0x118, 'FlareItem'},
{0x110, 'FlareGunRoundItem'},
{0x120, 'FlashLightItem'},
{0x188, 'KeroseneLampItem'},
{0x248, 'TorchItem'},
{0x1A0, 'MatchesItem'},
{0x150, 'FuelSourceItem'},
{0x128, 'FoodItem'},
{0x140, 'ForceLockItem'},
{0x158, 'HandheldShortwaveItem'},
{0x1E8, 'Respirator'},
{0x1F0, 'RespiratorCanister'},
{0x1F8, 'RopeItem'},
{0x240, 'ToolsItem'},
{0x218, 'SnareItem'},
{0x88, 'CanOpeningItem'},
{0x250, 'Travois'},
{0x260, 'WildlifeItem'},
{0x2A0, 'InsulatedFlask'},
{0x2A8, 'HeatPadItem'},
{0x1D0, 'PurifyWater'},
{0x258, 'WaterSupply'},
{0x198, 'LiquidItem'},
{0x1B8, 'NoiseMakerItem'},
{0x1C0, 'ShowOnMapItem'},
{0x90, 'CarryCapacityBuff'},
{0xB0, 'ConditionOverTimeBuff'},
{0xB8, 'ConditionRestBuff'},
{0xF0, 'FatigueBuff'},
{0x148, 'FreezingBuff'},
{0x268, 'WolfIntimidationBuff'},
{0x270, 'ClimbingBuff'},
{0x278, 'ProtectionBuff'},
{0x280, 'WeightReductionBuff'},
{0x238, 'StruggleBonus'},
{0xE0, 'EnergyBoost'},
{0xD0, 'DegradeOnUse'},
{0x1C8, 'PowderItem'},
{0x170, 'IceFishingHoleClearItem'},
{0x178, 'InProgressCraftItem'},
{0x288, 'LureItem'},
{0x290, 'BaitItem'},
{0x230, 'StoneItem'},
{0xC8, 'CookingPotItem'},
{0x220, 'SprayPaintCan'},
{0x168, 'Harvest'},
{0x138, 'ForageItem'},
{0x80, 'BreakDownItem'},
{0x68, 'BodyHarvestItem'},
{0x70, 'BodyHarvest'},
{0x200, 'Scent'},
{0x1D8, 'Repairable'},
{0x208, 'Sharpenable'},
{0x210, 'SmashableItem'},
{0x228, 'StackableItem'},
{0xA0, 'Cleanable'},
{0xC0, 'Cookable'},
{0x1A8, 'Millable'},
{0x108, 'FirstPersonItem'},
{0x180, 'Inspect'},
}
InvGV_iGroups = {
[0] = {['Unlock / Knowledge / Collectible'] = {0x60, 0x190, 0x1B0, 0x1E0, 0x298}},
[1] = {['Buffs'] = {0x90, 0xB0, 0xB8, 0xF0, 0x148, 0x268, 0x270, 0x278, 0x280}},
[2] = {['Clothing & Equippable gear'] = {0xA8, 0x1E8, 0x1F0}},
[3] = {['Weapon / Ammo (excluding rocks)'] = {0x50, 0x78, 0x160, 0x38, 0x40, 0x48}},
[4] = {['Tools / Utility / Hunting / Fishing'] = {0x1F8, 0x218, 0x240, 0x288, 0x290}},
[5] = {['Fire / Light related'] = {0xF8, 0x110, 0x118, 0x120, 0x150, 0x188, 0x1A0, 0x248}},
[6] = {['Food, Cooking and Recovery/Health related items'] = {0xC0, 0xC8, 0x128, 0x198, 0xD8, 0xE0, 0x100}},
[7] = {['Other (catch-all)'] = {}}
}
local fgHeader = 'Filter: Apply Item group filter (Area only)'
invGV_fGroups = {}
-- Populate IGroups entries under InvGV_GHeader
local tmrGHeader = AddressList.getMemoryRecordByDescription(fgHeader)
if tmrGHeader == nil then
error(' Unable to find record with description "'..fgHeader..'"')
end
for i=tmrGHeader.Count-1,0,-1 do
tmrGHeader.Child[i].delete()
end
local k1,v1,k2,v2
for k1,v1 in pairs(InvGV_iGroups) do
for k2,v2 in pairs(v1) do
local GrItem = AddressList.createMemoryRecord()
GrItem.description = k2
GrItem.IsGroupHeader = true
GrItem.Color = 0x00A400
GrItem.Active = k1 < 5 -- my defaults, ignoring fire/food/other if filtered (normally not)
GrItem.appendToEntry(tmrGHeader)
invGV_fGroups[k1] = GrItem.ID
end
end
-- when you disable this, The collapsable folder with parameters is collapsed by default. Open it back up
AddressList.getMemoryRecordByID(memrec.Id)[0].Collapsed = false
{$asm}
alloc(newmem,$100)
label(inv_IncludeArea inv_MaxLimit inv_Repairitems inv_SetMinCnt inv_MinStackableCnt inv_IgnoreTouched inv_ApplyGroupFilter inv_ApplyGFilter_Player)
registersymbol(inv_IncludeArea inv_MaxLimit inv_Repairitems inv_SetMinCnt inv_MinStackableCnt inv_IgnoreTouched inv_ApplyGroupFilter inv_ApplyGFilter_Player)
newmem:
inv_IncludeArea: // 1 byte - 0/1
db 1
inv_MaxLimit: // 4 byte - integer
dd #200
inv_Repairitems: // 1 byte - 0/1
db 0
inv_SetMinCnt: // 1 byte - 0/1
db 0
inv_MinStackableCnt: // 4 byte - integer
dd 4
inv_IgnoreTouched: // 1 byte - 0/1
db 1
inv_ApplyGroupFilter: // 1 byte - 0/1
db 0
inv_ApplyGFilter_Player: // 1 byte - 0/1
db 0
[DISABLE]
{$lua}
-- clear global variables set here
InvGV_iFields = nil
InvGV_iGroups = nil
invGV_fGroups = nil
{$asm}
unregistersymbol(*)
dealloc(*)
</AssemblerScript>
<CheatEntries>
<CheatEntry>
<ID>117987</ID>
<Description>"Get/Update Inventory List based on Parameters set below"</Description>
<Options moManualExpandCollapse="1" moDeactivateChildrenAsWell="1"/>
<Color>00FF00</Color>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>[ENABLE]
{$lua}
if syntaxcheck then return end
local mr_inv = AddressList.getMemoryRecordByDescription('InventoryBasePtr')
for i=mr_inv.Count-1,0,-1 do
mr_inv.Child[i].delete()
end
local function SetFlagStrings(ObjectAddr)
local ItemFlags = {
{0xd0, 'Degrade on use'},
{0x31, 'Hidden'},
{0x30, 'Locked'},
{0x23, 'In Satchel/Container'},
{0x28, 'In Satchel/Container'},
{0x1c, 'Touched by player'},
{0x1d, 'Touched by player'},
{0x1f, 'Touched by player'},
{0x21, 'Touched by player'}
}
local flagValues = {}
local k,v
for k,v in pairs(ItemFlags) do
if readBytes(ObjectAddr+v[1], 1, false) == 1 then
flagValues[v[2]] = v[2]
end
end
--return table.concat(flagValues, ', ')
-- I tried other ways but seems table.concat is not working here so built string this way
local Result = ''
for k,v in pairs(flagValues) do
Result = Result..v..', '
end
return string.sub(Result,1,-3)
end
local function TrimFirstUnderScore(tStrVal)
local Result = 'No name found' -- in case tStrVal is nil
if tStrVal ~= nil then
-- used or to replace nil value with 0. This way if no match, will show entire string instead of error
Result = string.sub(tStrVal, (string.find(tStrVal,'_') or 0)+1)
end
return Result
end
--table.sort not working as intended so using old fashioned quicksort
local function qsTopMemoryRecords(mrGroup, istart, iend)
local Result, ipivot
istart = istart or 1
iend = iend or #mrGroup
if iend - istart < 1 then
Result = mrGroup
else
ipivot = istart
for i = istart + 1, iend do
if mrGroup[i].description <= mrGroup[ipivot].description then
if i == ipivot + 1 then
mrGroup[ipivot],mrGroup[ipivot+1] = mrGroup[ipivot+1],mrGroup[ipivot]
else
mrGroup[ipivot],mrGroup[ipivot+1],mrGroup[i] = mrGroup[i],mrGroup[ipivot],mrGroup[ipivot+1]
end
ipivot = ipivot + 1
end
end
mrGroup = qsTopMemoryRecords(mrGroup, istart, ipivot - 1)
Result = qsTopMemoryRecords(mrGroup, ipivot + 1, iend)
end
return Result
end
local function ParseTableChildrenToMR(mrParent, srcTable)
local tmr,k,v
if srcTable.Children ~= nil then
for _,tmr in pairs(srcTable.Children) do
-- check if description matches evolve
local mr = AddressList.createMemoryRecord()
for k,v in pairs(tmr) do
if string.sub(k,1,1) ~= '_' and k ~= 'Children' and k ~= 'Offset' then
-- _*, Children & Offset are handled separately. Could not just do type in this case
mr[k] = v
end
end
mr.appendToEntry(mrParent)
-- now add offset if it exists
if tmr.OffsetCount ~= nil then
mr.OffsetCount = tmr.OffsetCount
for k,v in pairs(tmr.Offset) do
mr.Offset[k] = v
end
end
-- add children
ParseTableChildrenToMR(mr, tmr)
-- try to close if have children
if mr.count > 0 then
mr.Collapsed = true
end
end
end
end
local function RepairTgtItem(iBaseAStr)
local iMaxHP = readFloat('[['..iBaseAStr..']+340]+50')
local iCurHPPtr = '['..iBaseAStr..']+338'
local ClothingWetPtr = '[['..iBaseAStr..']+A8]+98'
local ClothingFrozenPtr = '[['..iBaseAStr..']+A8]+9C'
if iMaxHP ~= nil and iMaxHP ~= 0 and readFloat(iCurHPPtr) > 0 then
writeFloat(iCurHPPtr, iMaxHP)
end
if readFloat(ClothingWetPtr) ~= nil and readFloat(ClothingFrozenPtr) ~= nil then
writeFloat(ClothingWetPtr, 0)
writeFloat(ClothingFrozenPtr, 0)
end
end
local function SetMinStackCnt(iBaseAStr, MinStackCnt)
local StackCntPtr = '[['..iBaseAStr..']+228]+18'
local StackCnt = readInteger(StackCntPtr)
if StackCnt ~= nil and StackCnt > 0 and StackCnt < MinStackCnt then
writeInteger(StackCntPtr, MinStackCnt)
end
end
local function GetMainGrpId(iBaseAStr)
local Result = nil
local k1,v1,k2,v2,k3,v3
for k1,v1 in pairs(InvGV_iGroups) do
for k2,v2 in pairs(v1) do
for k3,v3 in pairs(v2) do
if readQword('['..iBaseAStr..']+'..string.format('%x',v3)) ~= 0 then
Result = k1
break
end
end
if Result ~= nil then
break
end
end
if Result ~= nil then
break
end
end
if Result == nil then
Result = #InvGV_iGroups -- the last row in #InvGV_iGroups shoule have empty table (catch-all)
end
return Result
end
local function IsSkipItem(iBaseAStr)
local iPlayerTouched = {0x1c,0x1d,0x1f,0x21}
local Result = false
local k,v
for k,v in pairs(iPlayerTouched) do
if readBytes('['..iBaseAStr..']+'..string.format('%x',v),1,false) == 1 then
Result = true
break
end
end
return Result
end
local function GetSubItemInfo(mrTemplate, grpColor)
local Result = {}
local k,v
if mrTemplate.description ~= nil then
Result.description = mrTemplate.description
if mrTemplate.IsAddressGroupHeader ~= nil then
Result.IsAddressGroupHeader = mrTemplate.IsAddressGroupHeader == true
end
if mrTemplate.address ~= nil then
Result.Address = mrTemplate.address
end
if mrTemplate.valueType ~= nil then
Result.Type = mrTemplate.valueType
end
if mrTemplate.offsetTable ~= nil and #mrTemplate.offsetTable > 0 then
Result.OffsetCount = #mrTemplate.offsetTable
Result.Offset = {}
for k,v in pairs(mrTemplate.offsetTable) do
Result.Offset[k - 1] = v
end
end
if mrTemplate.Children ~= nil and type(mrTemplate.Children) == 'table' then
Result.Children = {}
for k,v in pairs(mrTemplate.Children) do
local tmrL1 = GetSubItemInfo(v, grpColor)
if tmrL1.description ~= nil and string.len(tmrL1.description) > 0 then
table.insert(Result.Children, tmrL1)
end
end
if #Result.Children > 0 then
Result.Color = grpColor
Result.options = 'moManualExpandCollapse'
end
end
end
return Result
end
--[[
mrTableFormat: description, IsAddressGroupHeader, address, valueType, offsetTable,children
description is text
IsAddressGroupHeader is bool. If false, then isGroupHeader. If missing, then not set
address if empty or missing, then not set
valueType if empty or missing, then not set
offsetTable is table of offsets in reverse order of entry (offsetcount will be calculated from this). if empty or missing, not set
children is array of mrTableFormat. If none, then value (key is unused here) should be {}
Note:
* color and options are based on Top level design in code
* Any item entry with children will have moManualExpandCollapse option set and set to collapse initially in code, not in template below
table iSubInfo should be in format of [addr offsetcheck] = {mrTableFormat}
]]
local iSubInfo = {
[0xA8] = {
['description'] = 'Clothing Stats',
['IsAddressGroupHeader'] = true,
['address'] = '+0',
['valueType'] = vtQword,
['offsetTable'] = {0xA8},
['Children'] = {
{
['description'] = 'Warmth %',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x30}
},
{
['description'] = 'Windproof %',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x38}
},
{
['description'] = 'Toughness',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x3C}
},
{
['description'] = 'Waterproofness %',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x44}
},
{
['description'] = 'Wet %',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x98}
},
{
['description'] = 'Frozen %',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x9C}
}
}
},
[0xE8] = {
['description'] = 'Evolve Stats',
['IsAddressGroupHeader'] = true,
['address'] = '+0',
['valueType'] = vtQword,
['offsetTable'] = {0xE8},
['Children'] = {
{
['description'] = 'Gear Item to become',
['IsAddressGroupHeader'] = true,
['address'] = '+0',
['valueType'] = vtString,
['offsetTable'] = {0x26,0x10,0x68,0x340,0x20}
},
{
['description'] = 'Start Evolve %',
['address'] = '+0',
['valueType'] = vtDword,
['offsetTable'] = {0x28}
},
{
['description'] = 'Time To Evolve Game Days',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x2C}
},
{
['description'] = 'Time spent evolving (Game Hours)',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x34}
}
}
},
[0x160] = {
['description'] = 'Gun/Rifle Stats',
['IsAddressGroupHeader'] = true,
['address'] = '+0',
['valueType'] = vtQword,
['offsetTable'] = {0x160},
['Children'] = {
{
['description'] = 'Is Jammed',
['address'] = '+0',
['valueType'] = vtByte,
['offsetTable'] = {0xE8}
},
{
['description'] = 'Rounds in clip',
['address'] = '+0',
['valueType'] = vtDword,
['offsetTable'] = {0x34}
},
{
['description'] = 'Clip size',
['address'] = '+0',
['valueType'] = vtDword,
['offsetTable'] = {0x38}
},
{
['description'] = 'Rounds to reload/clip',
['address'] = '+0',
['valueType'] = vtDword,
['offsetTable'] = {0x3C}
},
{
['description'] = 'Damage HP',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x40}
},
{
['description'] = 'Firing rate/sec',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x44}
},
{
['description'] = 'Reload cooldown (sec)',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x48}
},
{
['description'] = 'Accuracy Range',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x54}
},
{
['description'] = 'Detailed Aim/fire Info',
['IsAddressGroupHeader'] = false,
['Children'] = {
{
['description'] = 'Aim assist min distance',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x58}
},
{
['description'] = 'Aiming Multiplier',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0xEC}
},
{
['description'] = 'Fire Multiplier',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0xF0}
},
{
['description'] = 'Reload Multiplier',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0xF4}
},
{
['description'] = 'Sway (no fatigue)',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0xF8}
},
{
['description'] = 'Sway (max fatigue)',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0xFC}
},
{
['description'] = 'Sway increase/sec',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x100}
},
{
['description'] = 'Sway decrease/sec',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x104}
},
{
['description'] = 'Sway enerby boost bonus',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x108}
},
{
['description'] = 'Sway enerby stim bonus',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x10C}
},
{
['description'] = 'Aiming Sway drop threshold %',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x114}
},
{
['description'] = 'Recoil - Pitch Min',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x118}
},
{
['description'] = 'Recoil - Pitch Max',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x11C}
},
{
['description'] = 'Recoil - Yaw Min',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x120}
},
{
['description'] = 'Recoil - Yaw Max',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x124}
},
{
['description'] = 'Sway',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x128}
},
{
['description'] = 'Sway Recovery Timer',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x12C}
}
}
}
}
},
[0x188] = {
['description'] = 'Kerosene Lamp Stats',
['IsAddressGroupHeader'] = true,
['address'] = '+0',
['valueType'] = vtQword,
['offsetTable'] = {0x188},
['Children'] = {
{
['description'] = 'Max Fuel',
['address'] = '+0',
['valueType'] = vtQword,
['offsetTable'] = {0x18}
},
{
['description'] = 'Current Fuel',
['address'] = '+0',
['valueType'] = vtQword,
['offsetTable'] = {0x68}
},
{
['description'] = 'Current Light Intensity',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x44}
},
{
['description'] = 'Dynamic Intensity (0/1)',
['address'] = '+0',
['valueType'] = vtByte,
['offsetTable'] = {0x1C}
},
{
['description'] = 'Indoor Intensity',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x38}
},
{
['description'] = 'Outdoor Intensity',
['address'] = '+0',
['valueType'] = vtSingle,
['offsetTable'] = {0x3C}
}
}
}
}
-- will have these be values in CE table later
local clrBaseItem = 0xFFFF00
local clrSubPropGrp = 0x808000
local clrItemTypes = 0x008000
local clrROField = 0xC0C0C0
local clrTouched = 0x008080
local clrLockedHidden = 0x4080FF
local clrCollKnowGrp = 0x00FFFF
local maxItemsList = readInteger("inv_MaxLimit") or 100
local ShowAreaItems = readBytes("inv_IncludeArea",1,false) > 0
local RepairItems = readBytes("inv_Repairitems",1,false) > 0
local SetMinCnt = readBytes("inv_SetMinCnt",1,false) > 0
local MinStackCnt = readInteger("inv_MinStackableCnt") or 4
local SkipPlayerTouched = readBytes("inv_IgnoreTouched",1,false) > 0
local ApplyGFilter = readBytes("inv_ApplyGroupFilter",1,false) > 0
local ApplyGFilter_Player = readBytes("inv_ApplyGFilter_Player",1,false) > 0
local IsPlayerItem = false
local iMainGrpId
local iSeq = 0
local continueLoop = true
local showItemID = false
local ceTable = {}
local iCntPlayer = 0
local iCntPlayerNF = 0
local iCntArea = 0
local iCntAreaNF = 0
local SkipItem = false
while continueLoop == true do
local iBaseAStr = '[[[[GameAssembly.dll+421E880]+b8]]+10]+20+8*'..string.format('%x',iSeq)
local iBaseAddr = readQword(iBaseAStr)
if iBaseAddr ~= 0 then
-- identify if player or area item (0x20 = m_InPlayerInventory)
IsPlayerItem = readBytes(iBaseAddr+0x20, 1, false) == 1
-- set iMainGrpId (used for filtering)
iMainGrpId = GetMainGrpId(iBaseAStr)
if IsPlayerItem == true then
iCntPlayerNF = iCntPlayerNF + 1
SkipItem = iCntPlayer >= maxItemsList
SkipItem = SkipItem or ApplyGFilter_Player and AddressList.getMemoryRecordByID(invGV_fGroups[iMainGrpId]).active ~= true
if SkipItem == false then
iCntPlayer = iCntPlayer + 1
end
else
iCntAreaNF = iCntAreaNF + 1
SkipItem = iCntArea >= maxItemsList or not ShowAreaItems
SkipItem = SkipItem or SkipPlayerTouched and IsSkipItem(iBaseAStr)
SkipItem = SkipItem or ApplyGFilter and AddressList.getMemoryRecordByID(invGV_fGroups[iMainGrpId]).active ~= true
-- only update iCntArea if not filtered out
if SkipItem == false then
iCntArea = iCntArea + 1
end
end
-- skip this item if exceeds max (still add to count but not list items)
if not SkipItem then
tmr = {}
local iName = TrimFirstUnderScore(readString('[[[['..iBaseAStr..']+340]+68]+10]+14', 128, true))
if showItemID then
tmr.description = iSeq..': '..iName
else
tmr.description = iName
end
tmr.Type = vtQword
tmr.Address = iBaseAStr
tmr.Color = clrBaseItem
tmr.IsAddressGroupHeader = true
tmr.options = 'moManualExpandCollapse'
tmr._IsPlayerItem = IsPlayerItem
tmr._IsStackable = readQword('['..iBaseAStr..']+228') ~= 0
tmr._IsClothing = readQword('['..iBaseAStr..']+A8') ~= 0
tmr.Children = {}
-- now identify flags and append to description (Only if not in player inventory)
if not IsPlayerItem then
local FlagStr = SetFlagStrings(iBaseAddr)
if string.len(FlagStr) > 0 then
tmr.description = tmr.description..' ('..FlagStr..')'
-- change color if touched by player (means you probably dropped it for a reason, its not a new item)
if string.find(string.lower(FlagStr),'player') ~= nil then
tmr.Color = clrTouched
elseif string.find(string.lower(FlagStr),'hidden') ~= nil or string.find(string.lower(FlagStr),'locked') ~= nil then
tmr.Color = clrLockedHidden
end
end
end
if tmr._IsStackable == true then
local tmrL1 = {}
tmrL1.description = 'Stack Count'
tmrL1.Type = vtDword
tmrL1.Address = '+0'
tmrL1.OffsetCount = 2
tmrL1.Offset = {}
tmrL1.Offset[1] = 0x228
tmrL1.Offset[0] = 0x18
table.insert(tmr.Children, tmrL1)
end
local tmrL1 = {}
tmrL1.description = 'Quality (HP)'
tmrL1.Type = vtSingle
tmrL1.Address = '+0'
tmrL1.OffsetCount = 1
tmrL1.Offset = {}
tmrL1.Offset[0] = 0x338
table.insert(tmr.Children, tmrL1)
local tmrL1 = {}
tmrL1.description = 'Max Quality (HP)'
tmrL1.Type = vtSingle
tmrL1.Address = '+0'
tmrL1.OffsetCount = 2
tmrL1.Offset = {}
tmrL1.Offset[1] = 0x340
tmrL1.Offset[0] = 0x50
tmrL1.Color = clrROField
table.insert(tmr.Children, tmrL1)
local tmrL1 = {}
tmrL1.description = 'Is Worn out'
tmrL1.Type = vtByte
tmrL1.Address = '+0'
tmrL1.OffsetCount = 1
tmrL1.Offset = {}
tmrL1.Offset[0] = 0x371
table.insert(tmr.Children, tmrL1)
-- Now add subItemDetails that were defined in iSubInfo
local k,v
for k,v in pairs(iSubInfo) do
if readQword('['..iBaseAStr..']+'..string.format('%x',k)) ~= 0 then
local tmrL1 = GetSubItemInfo(v, clrSubPropGrp)
if tmrL1.description ~= nil and string.len(tmrL1.description) > 0 then
table.insert(tmr.Children, tmrL1)
end
end
end
-- create header containing all objectFields that contain a pointer to use for filtering and expanding content in Inventory if you choose to do so
local iObjList = {}
local k,v
for k,v in pairs(InvGV_iFields) do
if readQword(iBaseAddr+v[1]) ~= 0 then
table.insert(iObjList, v) --v[2] for specifics but going to use this for cross reference on iGroups table
end
end
if #iObjList > 0 then
tmr.description = tmr.description..' ['..iObjList[1][2]..']'
local tmrL1 = {}
tmrL1.description = 'Valid Object Fields (Object count: '..#iObjList..')'
tmrL1.Color = clrSubPropGrp
tmrL1.IsGroupHeader = true
tmrL1.options = 'moManualExpandCollapse'
tmrL1.Children = {}
for _,v in pairs(iObjList) do
local tmrL2 = {}
tmrL2.description = v[2]
tmrL2.Color = clrItemTypes
tmrL2.IsGroupHeader = true
table.insert(tmrL1.Children, tmrL2)
end
table.insert(tmr.Children, tmrL1)
end
-- Although I did do the work to someday expand this to filter / group items based on identified categories, I am just going to highlight the Collectible/Research/Unlock one for now with identified color instead
if iMainGrpId == 0 then -- 0 = 'Unlock / Knowledge / Collectible'
tmr.Color = clrCollKnowGrp
end
table.insert(ceTable, tmr)
end
iSeq = iSeq + 1
continueLoop = iCntPlayer < maxItemsList or iCntArea < maxItemsList
else
continueLoop = false
end
end
-- if is collectible, research or ... then color is 00C4C4 (gold) or perhaps yellow
-- first group. Maybe add option to set flags or color based on user preference
-- now sort tables before adding as memory records
ceTable = qsTopMemoryRecords(ceTable)
-- create main headers (Player, Area)
local mrPlayerInv = AddressList.createMemoryRecord()
mrPlayerInv.description = 'Player Inventory'
mrPlayerInv.IsGroupHeader = true
mrPlayerInv.options = 'moManualExpandCollapse'
mrPlayerInv.appendToEntry(mr_inv)
local mrAreaInv = AddressList.createMemoryRecord()
mrAreaInv.description = 'Area Inventory'
mrAreaInv.IsGroupHeader = true
mrAreaInv.options = 'moManualExpandCollapse'
mrAreaInv.appendToEntry(mr_inv)
local mrTarget
local k,v
-- Now that the content has been sorted, I can start adding the memoryrecords
for _,tmr in pairs(ceTable) do
if tmr._IsPlayerItem then
mrTarget = mrPlayerInv
else
mrTarget = mrAreaInv
end
local mr = AddressList.createMemoryRecord()
for k,v in pairs(tmr) do
if string.sub(k,1,1) ~= '_' and k ~= 'Children' and k ~= 'Offset' then
-- _*, Children & Offset are handled separately. Could not just do type in this case
mr[k] = v
end
end
mr.appendToEntry(mrTarget)
local mrCollapse = true
-- Perhaps add logic later where if criteria met, will expand section you are looking for
ParseTableChildrenToMR(mr, tmr)
mr.Collapsed = mrCollapse
-- now check if minstack & repairs need to be done (only on player items)
if tmr._IsPlayerItem == true and tmr._IsStackable and SetMinCnt == true then
SetMinStackCnt(tmr.Address,MinStackCnt)
end
if tmr._IsPlayerItem == true and RepairItems == true then
RepairTgtItem(tmr.Address)
end
end
-- Update each inv with count & collapse
mrPlayerInv.description = mrPlayerInv.description..' (Item count: '..mrPlayerInv.count..'; Unfiltered count: '..iCntPlayerNF..')'
mrPlayerInv.Collapsed = true
mrAreaInv.description = mrAreaInv.description..' (Item count: '..mrAreaInv.count..'; Unfiltered count: '..iCntAreaNF..')'
mrAreaInv.Collapsed = true
-- Collapse the parameter filter when this is active. Open again when disabled (Collapse seems not to work when this is the active one...)
AddressList.getMemoryRecordByID(memrec.Id).Collapsed = true
{$asm}
[DISABLE]
{$lua}
if syntaxcheck then return end
local mr_inv = AddressList.getMemoryRecordByDescription('InventoryBasePtr')
for i=mr_inv.Count-1,0,-1 do
mr_inv.Child[i].delete()
end
-- Collapse the parameter filter when this is active. Open again when disabled
AddressList.getMemoryRecordByID(memrec.Id).Collapsed = false
{$asm}
</AssemblerScript>
<CheatEntries>
<CheatEntry>
<ID>117989</ID>
<Description>"Filter: Show area items?"</Description>
<DropDownList ReadOnly="1" DescriptionOnly="1" DisplayValueAsItem="1">0:False
1:True
</DropDownList>
<ShowAsSigned>0</ShowAsSigned>
<Color>008000</Color>
<VariableType>Byte</VariableType>
<Address>inv_IncludeArea</Address>
</CheatEntry>
<CheatEntry>
<ID>117988</ID>
<Description>"Filter: Max Inventory Count (Player / Area)"</Description>
<ShowAsSigned>0</ShowAsSigned>
<Color>008000</Color>
<VariableType>4 Bytes</VariableType>
<Address>inv_MaxLimit</Address>
</CheatEntry>
<CheatEntry>
<ID>118815</ID>
<Description>"Filter: Exclude items already inspected/viewed by player (Area only)"</Description>
<DropDownList ReadOnly="1" DescriptionOnly="1" DisplayValueAsItem="1">0:False
1:True
</DropDownList>
<ShowAsSigned>0</ShowAsSigned>
<Color>008000</Color>
<VariableType>Byte</VariableType>
<Address>inv_IgnoreTouched</Address>
</CheatEntry>
<CheatEntry>
<ID>118817</ID>
<Description>"Filter: Apply Item group filter (Area only)"</Description>
<DropDownList ReadOnly="1" DescriptionOnly="1" DisplayValueAsItem="1">0:False
1:True
</DropDownList>
<ShowAsSigned>0</ShowAsSigned>
<Color>008000</Color>
<VariableType>Byte</VariableType>
<Address>inv_ApplyGroupFilter</Address>
<CheatEntries>
<CheatEntry>
<ID>120260</ID>
<Description>"Unlock / Knowledge / Collectible"</Description>
<Color>00A400</Color>
<GroupHeader>1</GroupHeader>
</CheatEntry>
<CheatEntry>
<ID>120261</ID>
<Description>"Buffs"</Description>
<Color>00A400</Color>
<GroupHeader>1</GroupHeader>
</CheatEntry>
<CheatEntry>
<ID>120262</ID>
<Description>"Clothing & Equippable gear"</Description>
<Color>00A400</Color>
<GroupHeader>1</GroupHeader>
</CheatEntry>
<CheatEntry>
<ID>120263</ID>
<Description>"Weapon / Ammo (excluding rocks)"</Description>
<Color>00A400</Color>
<GroupHeader>1</GroupHeader>
</CheatEntry>
<CheatEntry>
<ID>120264</ID>
<Description>"Tools / Utility / Hunting / Fishing"</Description>
<Color>00A400</Color>
<GroupHeader>1</GroupHeader>
</CheatEntry>
<CheatEntry>
<ID>120265</ID>
<Description>"Fire / Light related"</Description>
<Color>00A400</Color>
<GroupHeader>1</GroupHeader>
</CheatEntry>
<CheatEntry>
<ID>120266</ID>
<Description>"Food, Cooking and Recovery/Health related items"</Description>
<Color>00A400</Color>
<GroupHeader>1</GroupHeader>
</CheatEntry>
<CheatEntry>
<ID>120267</ID>
<Description>"Other (catch-all)"</Description>
<Color>00A400</Color>
<GroupHeader>1</GroupHeader>
</CheatEntry>
</CheatEntries>
</CheatEntry>
<CheatEntry>
<ID>120259</ID>
<Description>"Filter: Apply item group filter to Player Inventory"</Description>
<DropDownList ReadOnly="1" DescriptionOnly="1" DisplayValueAsItem="1">0:False
1:True
</DropDownList>
<ShowAsSigned>0</ShowAsSigned>
<Color>008000</Color>
<VariableType>Byte</VariableType>
<Address>inv_ApplyGFilter_Player</Address>
</CheatEntry>
<CheatEntry>
<ID>117990</ID>
<Description>"Update: Repair/max health items & clear wet/frozen status for clothing? (Player only)"</Description>
<DropDownList ReadOnly="1" DescriptionOnly="1" DisplayValueAsItem="1">0:False
1:True
</DropDownList>
<ShowAsSigned>0</ShowAsSigned>
<Color>FF8080</Color>
<VariableType>Byte</VariableType>
<Address>inv_Repairitems</Address>
</CheatEntry>
<CheatEntry>
<ID>117991</ID>
<Description>"Update: Set minimum count (Stackable only)"</Description>
<DropDownList ReadOnly="1" DescriptionOnly="1" DisplayValueAsItem="1">0:False
1:True
</DropDownList>
<ShowAsSigned>0</ShowAsSigned>
<Color>FF8080</Color>
<VariableType>Byte</VariableType>
<Address>inv_SetMinCnt</Address>
<CheatEntries>
<CheatEntry>
<ID>117992</ID>
<Description>"Minimum Stackable Count - don't get greedy :P (Only if "Update: Set minimum count" is TRUE)"</Description>
<ShowAsSigned>0</ShowAsSigned>
<VariableType>4 Bytes</VariableType>
<Address>inv_MinStackableCnt</Address>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
</CheatEntry>
<CheatEntry>
<ID>116561</ID>
<Description>"InventoryBasePtr"</Description>
<ShowAsHex>1</ShowAsHex>
<ShowAsSigned>0</ShowAsSigned>
<GroupHeader>1</GroupHeader>
<Address>[[[GameAssembly.dll+421E880]+b8]]+10</Address>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
</CheatTable>