Jump to content

[Form ID conversion/JSON/HexDec Witchery...] Why my Game.GetFormFromFile fails? :( Help!


Recommended Posts

Ok, 
I am saving Outfits to JSON files with

 

    iFormId      = TempArmor.GetFormID()
    iModIndex    = Math.RightShift(iFormId, 24)                     ; e.g. 0x1B0012B7 becomes 0x1B or the decimal value of 27
    sFileName = Game.GetModName(iModIndex)                             ;Gets Name of Mod eg. Skyrim.esm, Update.esm, Hearthfire.esm, etc.
    
	SetINTValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "ID_slot30", iFormId as int)    
  	SetStringValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "STRING_slot30", sFileName)

 

this works fine.

But when I try to get the items back from the JSON with this:
 

iFormId = GetINTValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "ID_slot31")	
sFileName = GetStringValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "STRING_slot31")		
TempArmor = (Game.GetFormFromFile(iFormId, sFileName) as armor)			

	if TempArmor 
	PlayerRef.AddItem(TempArmor, 1, true)
	PlayerRef.EquipItem(TempArmor, false, true)
	endif

 

in 90% of cases this works, but for some ESPs it fails...
It finds Skyrim stuff and Merged ESPs and Patches, but all of them...

 

talk to me like a noob please.
I tried it manually:

this works
Game.GetFormFromFile(0x01000D64, "TBD - NiseKardiaArmor.esp") as armor

 

but this doesent 

 

Game.GetFormFromFile(-301986460, "TBD - NiseKardiaArmor.esp") as armor

 

where "-301986460" is the form id I save to the JSON as int and get back as int.
again, what bugs me is this works on one item but not on another :(
also tried on new game so my usual fucking around with ESP order should not be the issue here.

 

thx 

IMPORTANT: I need an LE solution... cannot use SE stuff :(
 

Link to comment
46 minutes ago, Nymra said:

but this doesent 

 

Game.GetFormFromFile(-301986460, "TBD - NiseKardiaArmor.esp") as armor

 

I am guessing its failing because the function GetFormFromFile requires a hexdecimal value to work

 

GetFormFromFile disregards the first two bytes of the full "01000D64" address and just uses D64 to locate the armor. I am assuming something is going wrong in the conversion to int and back again.
 

Link to comment

Oh boy where to begin. You will not be able to solve this issue due to an LE engine limitation.

This reddit post explains it more thorughly:

 

Quote

this works
Game.GetFormFromFile(0x01000D64, "TBD - NiseKardiaArmor.esp") as armor

That is because the address is called as a hexadecimal value and is within the boundaries of the 32 bit maximum address size.

 

Quote

 

Game.GetFormFromFile(-301986460, "TBD - NiseKardiaArmor.esp") as armor

 

where "-301986460" is the form id I save to the JSON as int and get back as int.
again, what bugs me is this works on one item but not on another :(
also tried on new game so my usual fucking around with ESP order should not be the issue here.

 

 

This andress call is an integer that if you translate into hexadecimal then you get: FFFF FFFF EE00 0D64

That is a 64 bit address that the LE engine can not handle. Also ESL formats can only contain only 2048 entries in total, any above that limit can not be called. This ESL limit rule applies to the sum total of ALL ESL entries.

 

EDIT:

Just to clarify SSE has some unofficial patches that increase this limit but the only way to get around the ESL limit is merge patches.

Edited by z3r0
Link to comment
4 minutes ago, wareware said:

 

I am guessing its failing because the function GetFormFromFile requires a hexdecimal value to work

 

GetFormFromFile disregards the first two bytes of the full "01000D64" address and just uses D64 to locate the armor. I am assuming something is going wrong in the conversion to int and back again.
 

 

but "01000D64" works and -301986460 

does not.
in the calculator it turns into "EE000D64" so I guess I have to do something before converting the armor item (GetWornFrom) into an int...
there is the math shifting that some ppl mentioned, but I have less than no idea how to use it in this case and if it helps.
There are mods that do this, but I look at their scripts and its literally nothing even remotely similar to my code, sigh... :(

Link to comment
Posted (edited)
3 minutes ago, z3r0 said:

Oh boy where to begin. You will not be able to solve this issue due to an LE engine limitation.

This reddit post explains it more thorughly:

 

That is because the address is called as a hexadecimal value and is within the boundaries of the 32 bit maximum address size.

 

 

This andress call is an integer that if you translate into hexadecimal then you get: FFFF FFFF EE00 0D64

That is a 64 bit address that the LE engine can not handle. Also ESL formats can only contain only 2048 entries in total, any above that limit can not be called. This ESL limit rule applies to the sum total of ALL ESL entries.

 

hmnm, so can I somehow transform this into a LE format?

I also do not understand how I get 64 bit adresses while running on LE with my poor 254 ESPs?! 
Is there a different way to obtain the correct 32 bit adress? 

EDIT: ah, the reddit post did not show up first. but it offers no solution?! :( 

Edited by Nymra
Link to comment
11 minutes ago, Nymra said:

 

but "01000D64" works and -301986460 

does not.
in the calculator it turns into "EE000D64" so I guess I have to do something before converting the armor item (GetWornFrom) into an int...
there is the math shifting that some ppl mentioned, but I have less than no idea how to use it in this case and if it helps.
There are mods that do this, but I look at their scripts and its literally nothing even remotely similar to my code, sigh... :(

 

If you try "16780644" instead of "-301986460" does it work?

 

EDIT: Is the armor plugin "TBD - NiseKardiaArmor.esp" esl flagged?

Edited by wareware
Link to comment
Posted (edited)
7 minutes ago, wareware said:

 

If you try "16780644" instead of "-301986460" does it work?

 

yes!
magic :P

how did you convert his?
do I need 500 lines of code for it? :(

EDIT: 
ESL flag: no. I m also on LE, no ESLs here afaik. 

Edited by Nymra
Link to comment
22 minutes ago, Nymra said:

but "01000D64" works and -301986460 does not.

It looks like you just got a solution, but I was going to say that if you're just trying to convert 0x01000D64 to decimal, ignore the first two digits (as wareware said) and use a tool like Windows calculator to convert D64 to decimal:  3428.  I'm not sure why you were using a negative value, but I don't think that's ever appropriate.

 

20 minutes ago, Nymra said:

I also do not understand how I get 64 bit adresses while running on LE with my poor 254 ESPs?! 

You don't need to use 64-bit addresses.  The first two digits are ignored (unneeded because you supply the mod name, "TBD - NiseKardiaArmor.esp" in this case).

Edited by HexBolt8
Link to comment
Posted (edited)
7 minutes ago, HexBolt8 said:

It looks like you just got a solution, but I was going to say that if you're just trying to convert 0x01000D64 to decimal, ignore the first two digits (as wareware said) and just a tool like Windows calculator to convert D64 to decimal:  3428.  I'm not sure why you were using a negative value, but I don't think that's ever appropriate.

 

I did not convert 0x01000D64 to decimal, the engine did. it what the json reads when I save it there.
I dont know how to ignore the first two digits with scripts. Is that like math.leftshift or something? that is the only lead I had. 
I cannot manually do this, I want the script to auto-convert it so that people can transfer saved outfits from one save game/one profile to the other.
Inte did it with Skyrim Utility Mod, but his code is higher magic for me, I am only a beginner :D

I also dont understand the logic behind the numbers and dec/hex/proof anyway, I can only follow examples and then work with those, sorry :(

 

 

EDIT:

i understand as much:

 

iFormId      = TempArmor.GetFormID()    ---> iFormId = int  -301986460      

here be the magic that makes -301986460  to 16780644 so I can save that to the json?

iModIndex    = Math.RightShift(iFormId, 24)                   

Game.GetModName(iModIndex)    ---> iFormId =  string TBD - NiseKardiaArmor.esp  (the part that works)                      

 

SetINTValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "ID_slot30", iFormId as int)      

SetStringValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "STRING_slot30", sFileName)

Edited by Nymra
Link to comment
2 minutes ago, Nymra said:

I cannot manually do this, I want the script to auto-convert it so that people can transfer saved outfits from one save game/one profile to the other.

That's easy, just use the decimal format.  SE can use hex or decimal.

Link to comment
4 minutes ago, HexBolt8 said:

It looks like you just got a solution, but I was going to say that if you're just trying to convert 0x01000D64 to decimal, ignore the first two digits (as wareware said) and use a tool like Windows calculator to convert D64 to decimal:  3428.  I'm not sure why you were using a negative value, but I don't think that's ever appropriate.

 

On further reading thats not applicable here. GetFormFromFile reads values as int WITH the load order so if you were to use 3428 it should bug out.

 

https://ck.uesp.net/wiki/GetFormFromFile_-_Game

 

12 minutes ago, Nymra said:

 

yes!
magic :P

how did you convert his?
do I need 500 lines of code for it? :(

EDIT: 
ESL flag: no. I m also on LE, no ESLs here afaik. 

 

I just converted it using a calculator lol. Something is going wrong with converting the formID to int with the plugin in question. LE cannot read ESLs true but if the plugin is ESL flagged ESP it might be doing weird things as the formIDs of ESLs starts with FExx which might be throwing your game for a loop.

 

Can you link the page from where you got the TBD - NiseKardiaArmor.esp plugin?

 

 

Link to comment

Try this:

iModIndex    = Math.RightShift(iFormId, 18)

Syntax might be retarded and is reading the value as HEX and not as integer HEX 18 = INT 24

Actually ran into the same issue with Calculator.....

 

image.png

Link to comment
5 minutes ago, z3r0 said:

Try this:

iModIndex    = Math.RightShift(iFormId, 18)

Syntax might be retarded and is reading the value as HEX and not as integer HEX 18 = INT 24

 

 

That doesn't seem to be the issue here. The RightShift function is just extracting the load order from the form ID.

Link to comment

yeah, this did not work.

 

But when the right shift can extract the LoadOrder, 

can it not somehow also ignore the loadorder? 

I got this from the online tool...

now I need to get from 0x01000D64 to 01000D64 via script somehow?

2024-01-09 04_22_13-Hexadecimal to Decimal Converter - Vivaldi.jpg

Link to comment

Figured it out. You have to chop the first two characters off the armors ID.

Try this code

    iFormId      = Math.LeftShift(TempArmor.GetFormID(), 8)
    iModIndex    = Math.RightShift(TempArmor.GetFormID(), 24)                     ; e.g. 0x1B0012B7 becomes 0x1B or the decimal value of 27
    sFileName = Game.GetModName(iModIndex)                             ;Gets Name of Mod eg. Skyrim.esm, Update.esm, Hearthfire.esm, etc.
    
	SetINTValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "ID_slot30", iFormId as int)    
  	SetStringValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "STRING_slot30", sFileName)

When it looks for the armor it will look in ModIndex 01 and then look for FormId 01000D64 inside that mod, this will cause it to go out of bounds as the final form will be: 0101000D64. This causes the load issue, you are actually looking for FormId 000D64 inside ModIndex 01 when you want to load it back.

Edited by z3r0
Link to comment
6 minutes ago, wareware said:

You don't want to ignore the load order as without the load order bits the decimal value is "3428"

 

Does the number "3428" work for retrieving the outfit?

 

positive.

3428 works too. 

 

now how to get to that one via papyrus? :D

Link to comment
4 minutes ago, Nymra said:

 

positive.

3428 works too. 

 

now how to get to that one via papyrus? :D

 

iFormId = Math.RightShift(Math.LeftShift(TempArmor.GetFormID(), 8),8)

Retarded solution but it should work

Edited by wareware
Link to comment

try

6 minutes ago, z3r0 said:

Figured it out. You have to chop the first two characters off the armors ID.

Try this code

    iFormId      = Math.LeftShift(TempArmor.GetFormID(), 8)
    iModIndex    = Math.RightShift(TempArmor.GetFormID(), 24)                     ; e.g. 0x1B0012B7 becomes 0x1B or the decimal value of 27
    sFileName = Game.GetModName(iModIndex)                             ;Gets Name of Mod eg. Skyrim.esm, Update.esm, Hearthfire.esm, etc.
    
	SetINTValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "ID_slot30", iFormId as int)    
  	SetStringValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "STRING_slot30", sFileName)

When it looks for the armor it will look in ModIndex 01 and then look for FormId 01000D64 inside that mod, this will cause it to go out of bounds as the final form will be: 0101000D64. This causes the load issue, you are actually looking for FormId 000D64 inside ModIndex 01 when you want to load it back.

 

trying this now...

I see I really miss ALL the basics...
MathLeftShift 1 bit... I was like WTF do they mean with 1 bit and why do they write a 4?!. Now I see, 1 bit is 4, 6 bit is 24. loool. I feel stupid. 

 

Link to comment
    TempId       = TempArmor.GetFormID()
    iFormId      = Math.RightShift(Math.LeftShift(TempId,8),8)
    iModIndex    = Math.RightShift(TempId, 24)                     ; e.g. 0x1B0012B7 becomes 0x1B or the decimal value of 27
    sFileName    = Game.GetModName(iModIndex)                             ;Gets Name of Mod eg. Skyrim.esm, Update.esm, Hearthfire.esm, etc.
    
	SetINTValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "ID_slot30", iFormId as int)    
  	SetStringValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "STRING_slot30", sFileName)

Made an error in the first version @wareware is correct, you need to shift it back and forth to get rid of the first 2 characters in HEX what is essentially the mod index byte.

Edited by z3r0
Link to comment
23 minutes ago, wareware said:

On further reading thats not applicable here. GetFormFromFile reads values as int WITH the load order so if you were to use 3428 it should bug out.

It actually does work.

 

I'm a little confused about what you meant by "with the load order", but the example that you cited ignores the first two digits (the load index), which is correct.  The only relevant part of the ID is the last 6 digits, and leading zeroes can be ignored.

 

As a test, since it's best to go on hard evidence, I tried accessing a form from a mod with this line:

 

    Form loveSicknessEffect = Game.GetFormFromFile(3437, "Love Sickness.esp")
    MiscUtil.PrintConsole("Name: " + loveSicknessEffect.GetName())

 

It printed the name for the perk, indicating that it got the right form.  The thing to keep in mind is that 3437 and 0x00000D6D are the same ID.  The "0x" prefix tells the game that it's a hex value.

Link to comment

This worked!

thank you all so very much... this is the line that my brainz just cannot cross and I really appreciate the fast and competent support.
much appreciated and good night! (oh I will sleep well now ^^) 
 

10 minutes ago, z3r0 said:
    TempId       = TempArmor.GetFormID()
    iFormId      = Math.RightShift(Math.LeftShift(TempId,8),8)
    iModIndex    = Math.RightShift(TempId, 24)                     ; e.g. 0x1B0012B7 becomes 0x1B or the decimal value of 27
    sFileName    = Game.GetModName(iModIndex)                             ;Gets Name of Mod eg. Skyrim.esm, Update.esm, Hearthfire.esm, etc.
    
	SetINTValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "ID_slot30", iFormId as int)    
  	SetStringValue("../Naked Defeat/outfit" +OutfitNum+ ".json", "STRING_slot30", sFileName)

Made an error in the first version @wareware is correct, you need to shift it back and forth to get rid of the first 2 characters in HEX what is essentially the mod index byte.

 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use