PSOBB Addon Plugin (Lua UI addons)

Edit; was able to locate the enabler and disable settings. Took out some folders from addon to reduce clutter.


Re did the steps, seems to be functioning but now am bombarded on start up and cant close the panels (no x on top right)1700942483460.png


Much appreciate the assistance, didn't realize I downloaded an old one.
 
Last edited:
Re did the steps, seems to be functioning but now am bombarded on start up and cant close the panels (no x on top right)View attachment 20743


Much appreciate the assistance, didn't realize I downloaded an old one.
Some of those windows have an X. You can click those.
Some of those windows don't. The convention is that clicking the button for it in the main addon list (the Main window) will toggle visibility.

Most addons have a configuration window that controls whether it's enabled and how/where it is positioned. For example, you see the Monster Reader - Configuration window at the top? Clicking Monster Reader button in the Main list on the left will toggle visibility of that configuration window. That configuration window controls whether the Monster Reader itself is enabled, and there are options for the type of displays.

IMO just close all but the Main addon window first, and then slowly pick which ones you'd like to enable.
 
So using 0x2C4 and 0x2CC are close to the base ATP but not exact. I logged on multiple different characters, unequipped all their gear, and was able to conclude that on a Hunter, these memory addresses are always 10 points lower than the actual base ATP. On Rangers, these numbers are 7 points lower, and on Forces they are 3 points lower. This was tested on a brand new level 1, to take any power materials out of the equation, as well as higher level characters. Equipping a Mag does increase this number, but equipping a weapon does not. 0x2C4 is not affected by Shifta, it always reflects the base ATP (minus points based on class), and 0x2CC DOES reflect Shifta increased ATP.
I only did a brief amount of testing after I saw your question yesterday. I was playing on a Force so I noticed it was 3 points off, but God/Power was updating both of those memory addresses by the correct amount. However, I didn't see either of these values updating when toggling my weapon.

I just checked again to see if I could find weapon ATP, and I think 0xE52 looks promising. The missing 3 ATP appears to be accounted for there as well.

I haven't done extensive testing or analysis so I don't know if that's a stable offset or even a good way of computing ATP. But that's about as much effort as I'm willing to put in at the moment. Feel free to fiddle around with the little addon I made for memory visualization that helped me find these offsets.

C-like:
local _PlayerCount = 0x00AAE168
local _EntityCount = 0x00AAE164
local _EntityArray = 0x00AAD720

local _MonsterIndex = "1"
local _MonsterAddress = ""
local _MonsterMem = {}
local _Now = 0

local function GetMonsterAddress(monsterIndex)
    local playerCount = pso.read_u32(_PlayerCount)
    local entityCount = pso.read_u32(_EntityCount)
    
    return (monsterIndex ~= nil) and pso.read_u32(_EntityArray + 4 * (monsterIndex - 1 + playerCount)) or 0
end

local function GetMonsterData(monsterAddress)
    local monsterMem = {}

    if monsterAddress ~= 0 then
        pso.read_mem(monsterMem, monsterAddress, 0x1000)
    end
    
    return monsterMem
end

local function present()
    local s1, s2
    
    imgui.Begin("Monster Data")
    
    imgui.PushItemWidth(30)
    s1, _MonsterIndex = imgui.InputText("", _MonsterIndex, 3)
    imgui.SameLine(0, 5)
    imgui.PushItemWidth(90)
    s2, _MonsterAddress = imgui.InputText(" ", _MonsterAddress, 11)
    
    if s1 or _MonsterAddress == "" then
        local monsterIndex = tonumber(_MonsterIndex)
        _MonsterAddress = "0x" .. string.format("%08X", GetMonsterAddress(monsterIndex))
    end
    
    local monsterAddress = tonumber(string.sub(_MonsterAddress, 3), 16)
    local success, monsterMem = pcall(GetMonsterData, monsterAddress)
    local k,v
    
    if success then
        for k,v in ipairs(monsterMem) do
            if k % 0x10 == 0x1 then
                imgui.Text(string.format("%04X", k-1))
                imgui.SameLine(0, 5)
            end
            
            if _Now - _MonsterMem[k].lastChange > 5 * 30 then
                imgui.TextColored(1.0, 1.0, 1.0, 1.0, string.format("%02X", v))
            elseif _Now - _MonsterMem[k].lastChange > 2 * 30 then
                imgui.TextColored(1.0, 1.0, 0.0, 1.0, string.format("%02X", v))
            else
                imgui.TextColored(1.0, 0.0, 0.0, 1.0, string.format("%02X", v))
            end
            
            if _MonsterMem[k].value ~= v then
                _MonsterMem[k].value = v
                _MonsterMem[k].lastChange = _Now
            end
            
            if k % 0x10 ~= 0x0 then
                imgui.SameLine(0, 5)
            end
        end
    else
        imgui.Text(monsterMem)
    end
    
    _Now = _Now + 1

    imgui.End()
end

local function init()
    local i
    
    for i=1,0x1000 do
        table.insert(_MonsterMem, { value = 0x00, lastChange = 0 })
    end

    return
    {
        name = "Monster Memory",
        version = "0.1.0",
        author = "staphen",
        description = "Memory dump for monsters",
        present = present,
    }
end

return
{
    __addon =
    {
        init = init
    }
}
 
I only did a brief amount of testing after I saw your question yesterday. I was playing on a Force so I noticed it was 3 points off, but God/Power was updating both of those memory addresses by the correct amount. However, I didn't see either of these values updating when toggling my weapon.

I just checked again to see if I could find weapon ATP, and I think 0xE52 looks promising. The missing 3 ATP appears to be accounted for there as well.

I haven't done extensive testing or analysis so I don't know if that's a stable offset or even a good way of computing ATP. But that's about as much effort as I'm willing to put in at the moment. Feel free to fiddle around with the little addon I made for memory visualization that helped me find these offsets.

C-like:
local _PlayerCount = 0x00AAE168
local _EntityCount = 0x00AAE164
local _EntityArray = 0x00AAD720

local _MonsterIndex = "1"
local _MonsterAddress = ""
local _MonsterMem = {}
local _Now = 0

local function GetMonsterAddress(monsterIndex)
    local playerCount = pso.read_u32(_PlayerCount)
    local entityCount = pso.read_u32(_EntityCount)
   
    return (monsterIndex ~= nil) and pso.read_u32(_EntityArray + 4 * (monsterIndex - 1 + playerCount)) or 0
end

local function GetMonsterData(monsterAddress)
    local monsterMem = {}

    if monsterAddress ~= 0 then
        pso.read_mem(monsterMem, monsterAddress, 0x1000)
    end
   
    return monsterMem
end

local function present()
    local s1, s2
   
    imgui.Begin("Monster Data")
   
    imgui.PushItemWidth(30)
    s1, _MonsterIndex = imgui.InputText("", _MonsterIndex, 3)
    imgui.SameLine(0, 5)
    imgui.PushItemWidth(90)
    s2, _MonsterAddress = imgui.InputText(" ", _MonsterAddress, 11)
   
    if s1 or _MonsterAddress == "" then
        local monsterIndex = tonumber(_MonsterIndex)
        _MonsterAddress = "0x" .. string.format("%08X", GetMonsterAddress(monsterIndex))
    end
   
    local monsterAddress = tonumber(string.sub(_MonsterAddress, 3), 16)
    local success, monsterMem = pcall(GetMonsterData, monsterAddress)
    local k,v
   
    if success then
        for k,v in ipairs(monsterMem) do
            if k % 0x10 == 0x1 then
                imgui.Text(string.format("%04X", k-1))
                imgui.SameLine(0, 5)
            end
           
            if _Now - _MonsterMem[k].lastChange > 5 * 30 then
                imgui.TextColored(1.0, 1.0, 1.0, 1.0, string.format("%02X", v))
            elseif _Now - _MonsterMem[k].lastChange > 2 * 30 then
                imgui.TextColored(1.0, 1.0, 0.0, 1.0, string.format("%02X", v))
            else
                imgui.TextColored(1.0, 0.0, 0.0, 1.0, string.format("%02X", v))
            end
           
            if _MonsterMem[k].value ~= v then
                _MonsterMem[k].value = v
                _MonsterMem[k].lastChange = _Now
            end
           
            if k % 0x10 ~= 0x0 then
                imgui.SameLine(0, 5)
            end
        end
    else
        imgui.Text(monsterMem)
    end
   
    _Now = _Now + 1

    imgui.End()
end

local function init()
    local i
   
    for i=1,0x1000 do
        table.insert(_MonsterMem, { value = 0x00, lastChange = 0 })
    end

    return
    {
        name = "Monster Memory",
        version = "0.1.0",
        author = "staphen",
        description = "Memory dump for monsters",
        present = present,
    }
end

return
{
    __addon =
    {
        init = init
    }
}
I’ve got the addon loaded but what do you do with it? Is the value on the left supposed to return a memory address on the right? I’m on my ROG Ally so it may not be working due to the virtual keyboard
 
I’ve got the addon loaded but what do you do with it? Is the value on the left supposed to return a memory address on the right? I’m on my ROG Ally so it may not be working due to the virtual keyboard
There are two text boxes. The first one takes the index of a monster, the second one is the hexadecimal memory address you are visualizing. If you update the first text box, it will look up the monster in the entity array and find its address to autopopulate the second text box. However, you can manually put whatever memory address you want in the second text box, and it will ignore the monster index and show you the memory at that location.

So if I want to view the data at playerAddress, I will start by entering 0x00A94254 into the second text box. The first four bytes represent the (little endian) address to my character's data so I type those out in Notepad and then paste that into the second text box. At this point, I can see the values of all the bytes at offsets between 0x0 and 0x1000 and how they change in real time.

You should also be able to tweak the code to use player indexes instead of monster indexes--or even just entity indexes--if that makes it easier for you.
 
There are two text boxes. The first one takes the index of a monster, the second one is the hexadecimal memory address you are visualizing. If you update the first text box, it will look up the monster in the entity array and find its address to autopopulate the second text box. However, you can manually put whatever memory address you want in the second text box, and it will ignore the monster index and show you the memory at that location.

So if I want to view the data at playerAddress, I will start by entering 0x00A94254 into the second text box. The first four bytes represent the (little endian) address to my character's data so I type those out in Notepad and then paste that into the second text box. At this point, I can see the values of all the bytes at offsets between 0x0 and 0x1000 and how they change in real time.

You should also be able to tweak the code to use player indexes instead of monster indexes--or even just entity indexes--if that makes it easier for you.
Oh wow this is great. I’m gonna need to spend a lot of time playing with this to see how it works. I entered 0x00A94254 in the 2nd box and wrote down the first four bytes. I then entered those 8 digits into the 2nd box. At this point all of the offsets cycled from red - yellow - white. I then started to cast buffs and equip/unequip gear but none of the values changed at this point
 
Oh wow this is great. I’m gonna need to spend a lot of time playing with this to see how it works. I entered 0x00A94254 in the 2nd box and wrote down the first four bytes. I then entered those 8 digits into the 2nd box. At this point all of the offsets cycled from red - yellow - white. I then started to cast buffs and equip/unequip gear but none of the values changed at this point
On little endian systems you have to reverse the bytes. If it says 50 C3 CC 12, you have to enter 0x12CCC350.
 
On little endian systems you have to reverse the bytes. If it says 50 C3 CC 12, you have to enter 0x12CCC350.
Thank you for this! I was just now able to find the memory offsets for ATP and they update accurately when items are equipped/unequipped and the player has Shifta/loses Shifta
 
On little endian systems you have to reverse the bytes. If it says 50 C3 CC 12, you have to enter 0x12CCC350.
Do you happen to know how to find out what attribute a monster is? Native/ABeast/Machine/Dark? I was looking through Soly’s Monster Reader but there wasn’t any references to this. I suppose I could try using your addon to find the memory reference but I’d have to find an area where there are 2 monsters of different attributes that I can swap between
 
Do you happen to know how to find out what attribute a monster is? Native/ABeast/Machine/Dark? I was looking through Soly’s Monster Reader but there wasn’t any references to this. I suppose I could try using your addon to find the memory reference but I’d have to find an area where there are 2 monsters of different attributes that I can swap between
4 byte bitmask at offset 0x2e8
Native 0x1
A. Beast 0x2
Machine 0x4
Dark 0x8
"CCA Miniboss" 0x10
Special (hides olga 2 attribute) 0x40

Physical damage function checks for equality with this field, which is why CCA minibosses and Olga 2 don't take extra damage from attributes. The CCA miniboss flag is also used to grant immunity to confusion, which is really weird because flags for immunity to other status effects are not stored in this field.
 
Thanks guys, this is what ive been able to do so far with this data. All able to be calculated in-game based on currently targeted monster, taking into consideration shifta and zalure applied along with attribute % on weapon

Untitled.png

I was able to determine that the +2 in the weapon ATP range and the +1 in the minimum weapon ATP is your class unarmed data that is factored in EVEN WHEN a weapon is equipped. So for example, when a FO is unarmed, there is still at minimum 1 ATP included in your stats as if your fists were a weapon. There is then a 2 ATP range with unarmed combat. So on paper your fists would be 1-3 ATP. The same logic applies to HU and RA classes except HU would be 5-10 unarmed and RA I believe was 4-7. When a weapon is equipped, these unarmed ranges and minimums are ADDED to the equipped weapon figures. That is why my summit moon showed a 12 ATP range when the weapon itself only has a range of 10 ATP between its min and max value.
 
Last edited:
I included below for reference a level 1 hunter, with and without a Saber equipped. Ignore for now the label +2 and +1, thats while I was testing on my FO. Saber ATP is 40-55, so 15 ATP range. When equipped, the game shows a 20 ATP range which includes HU unarmed range. Weapon/gear ATP shows 45 which is the 40 minimum from the weapon and the 5 from HU unarmed.
Ephinea_ Phantasy Star Online Blue Burst 11_26_2023 1_48_55 PM.jpgEphinea_ Phantasy Star Online Blue Burst 11_26_2023 1_48_47 PM.jpg
 
Last edited:
So I haven't played in a couple months and now none of the addons work... I have no idea why. I tried reinstalling, but not even the main window will show up.
 
PSO has an in-game monster reader. Is there a way to disable that one if we are using the LUA monster HP reader? Or is it always going to show up?
 
So I haven't played in a couple months and now none of the addons work... I have no idea why. I tried reinstalling, but not even the main window will show up.
Try the other direct3d renderers in the launcher options. Try 8 first because that's the default one. Also make sure you actually have the base plugin (dinput8.dll inside the folder with psobb.exe).

PSO has an in-game monster reader. Is there a way to disable that one if we are using the LUA monster HP reader? Or is it always going to show up?
No, you can't disable it. You can disable the HP bar in the target window, that's it.
 
Try the other direct3d renderers in the launcher options. Try 8 first because that's the default one. Also make sure you actually have the base plugin (dinput8.dll inside the folder with psobb.exe).


No, you can't disable it. You can disable the HP bar in the target window, that's it.
Ok I changed it back to 8 but now PSO just opens for a sec and then crashes
 
Try the other direct3d renderers in the launcher options. Try 8 first because that's the default one. Also make sure you actually have the base plugin (dinput8.dll inside the folder with psobb.exe).


No, you can't disable it. You can disable the HP bar in the target window, that's it.
Ok so now it's giving me the error "Unicode dinput8 was created, cannot continue"

I saw another post from a few years ago with this same error but it seems like the problem was related to some VPN program or something, which I don't have.
 
So I figured it out, I had to uninstall a vjoy driver that I used for my Clone Hero guitar. Everything works fine again... except Clone Hero lol
 
Back
Top