Jump to content

UPK Utils


wghost81

Recommended Posts

Nexus file and git sources updated to v.4.0. Adding new object feature is in, but I don't recommend to use it for actual mods, as now it raises too many compatibility problems (with uninstallation mainly). So the best part of this update is white-spaces handling. :smile: Edited by wghost81
Link to comment
Share on other sites

  • Replies 235
  • Created
  • Last Reply

Top Posters In This Topic

  • 4 weeks later...

Hi everyone,

I'm new here, great stuff!

 

Been looking into modding the class assignment to be a bit dependent on soldier stats, so will probably need to modify LevelUp/PickAClass somehow.

 

I was having trouble expanding the function using EXPAND_FUNCTION (error was always "Replacement code does not fit current scope!"),

finally tried OBJECT=XGStrategySoldier.LevelUp:AUTO and it seemed to work fine.

So, a couple more questions, apologies beforehand if this is not the best place to ask:

* is it possible to add new function params or otherwise pass some data to another function?

* if so, does adding (optional) params require other calls to that func to be rewritten?

* Is it possible to add new static vars to an object?

 

Thanks!

Link to comment
Share on other sites

EXPAND_FUNCTION requires you to specify not the size of the code, but the size of the whole export data. The best way to fully re-write a function is to use AUTO specifier with REPLACEMENT_CODE.

 

It is possible to add new objects, but I wouldn't recommend to use this feature, as it will make your mod incompatible with the others. Plus, there's no uninstall feature for those changes. Try to construct your code so it won't require any new variables. It is possible in almost all situations.

 

Random Pods mod is a working example of complex PatchUPK script with functions rewriting and variables re-purposing. There also is a class assignment mod which is a part of Interface and Gameplay Tweaks collection. You can take those as examples and write your own version.

Edited by wghost81
Link to comment
Share on other sites

Thanks for the info, I guess I'll need to spend a bit more time learning this stuff.

 

It looks like you are referring to "ClassProbability" Install/tweak? as it uses MODDED_HEX i'll need to compare to the original hex, but im sure ill learn something.

 

I was hoping to NOT have to rewrite the whole thing, but I guess there is no way (yet) to add code at the start and have all the other JMP references updated...

(That would be an awesome feature!)

 

Again thanks for all the work.

Link to comment
Share on other sites

You can use labels with REPLACEMENT_CODE and forget about jump offsets calculation. :wink: EU version of class probability mod uses all the new PatchUPK features. Even has an example of changing the property type. So you can use it as a reference.

 

If I knew what exactly are you trying to do, may be I could help with the code. :wink:

Edited by wghost81
Link to comment
Share on other sites

  • 3 weeks later...

I have a few questions on the REPLACEMENT_CODE formatting mostly in regards to struct referencing, likely as a result of me not fully understanding the hex side of things yet (this is my first mod attempt). Unfortuantely the doco at http://wiki.tesnexus.com/index.php/Hex_editing_UPK_files stops at the data structures and conditional controls sections, which is what I really need. Most of the rest of it is self explanatory.

 

Here is an example from the Alien Squad Size Randomized:

// kSquad.arrPods[0].eMain = 6;
0F 35 <XComGame.XGGameData.TAlienPod.eMain> <XComGame.XGGameData.TAlienPod> 00 00 10 2C 00 35 <XComGame.XGGameData.TAlienSquad.arrPods> <XComGame.XGGameData.TAlienSquad> 00 01 00 <.kSquad> 24 06

A similar line in the stock version of that function is:

// kSquad.arrPods[kSquad.arrPods.Length - 1].eMain = 6
0F 35 07 FF FF FF B6 F9 FF FF 00 00 10 93 36 35 E1 FF FF FF B5 F9 FF FF 00 00 00 40 52 00 00 26 16 35 E1 FF FF FF B5 F9 FF FF 00 01 00 40 52 00 00 24 06

Were I to swap out the kSquad.arrPods.Length - 1 array parm to the 0 above (and using the int const 0 used in the mod and not the 0 literal), I believe it would look like:

// kSquad.arrPods[0].eMain = 6
// ? maybe ?
0F 35 07 FF FF FF B6 F9 FF FF 00 00 10 2C 00 35 E1 FF FF FF B5 F9 FF FF 00 01 00 40 52 00 00 24 06

So, if I abstract out the codes I know, we end up with a DoubleWord(DW) for <XComGame.XGGameData.TAlienPod.eMain>, <XComGame.XGGameData.TAlienPod>, <XComGame.XGGameData.TAlienSquad.arrPods> and <XComGame.XGGameData.TAlienSquad>

 

So;

 

Question 1: Why do I need both of them (8 bytes, which I assume are two doublewords) for each memory location? I assume one's a class definition and the other's the object location? If that's the case, why don't I need the same thing for the local variable kSquad? It's also a TAlienSquad.

 

Edit: I think I understand it. The token is Struct member, so it's saying that the struct member inside the struct X.

 

Question 2: What is the "00 00" and "00 01" for? Are they some sort of token concatenator for assembling the object member references? If eMain was a struct/class and I had a "mFoo" inside of it I had to reference would "kSquad.arrPods[0].eMain.eFoo" result in a "00 02" before the eFoo reference ?

 

Edit: 00 00 seems a common ending for Struct and Context Tokens. I still don't get what the difference between it and 00 01 is though.

 

Question 3: In the readme it says, "Don't use labels if you mix pure hex with pseudo-code, as references will be wrong!"

 

By this do you mean that you can't use "pure hex" jump references, but it's OK to use variable offsets/data constants/etc in hex? This is what the example beneath it is doing.

 

Thank you in advance for any replies, and for producting such a handy utility.

 

Mercy

Edited by projectmercy
Link to comment
Share on other sites

projectmercy, there is a good post by Amineri about managing structures and classes: http://forums.nexusmods.com/index.php?/topic/1006781-how-to-build-classobject-references/ Another good place to start is UEExplorer decompiled tokens view: it helps a LOT with understanding unreal script bytecode.

 

Code breakdown:

 

 

// kSquad.arrPods[0].eMain = 6;
0F    // =
    35    // struct context
        <XComGame.XGGameData.TAlienPod.eMain> <XComGame.XGGameData.TAlienPod>    // eMain
        00 00    // unknown
        10    // dynamic array element
            2C 00    // index
            35    // struct context
                <XComGame.XGGameData.TAlienSquad.arrPods> <XComGame.XGGameData.TAlienSquad>    // arrPods
                00 01    // unknown
                00 <.kSquad>    // local variable
    24 06    // 6
Your code:

// kSquad.arrPods[kSquad.arrPods.Length - 1].eMain = 6
0F // =
  35 // struct context
    07 FF FF FF B6 F9 FF FF // eMain
    00 00
    10 // dynamic array element
      93 // -
        36 // dynamic array length
          35 // struct context
              E1 FF FF FF B5 F9 FF FF // arrPods
              00 00
              00 40 52 00 00 // local variable kSquad
        26 // const 1
      16 // end of -
    35 // struct context
      E1 FF FF FF B5 F9 FF FF // arrPods
      00 01
      00 40 52 00 00 // local variable kSquad
  24 06
So, kSquad.arrPods can have 00 00 and 00 01 inside. I'm not sure why. Usually I construct a new code using an old one, copied from UE Explorer, and leave all unknown numbers as they are.

 

About question 3. By 'labels' I mean [#label1] and [@label1] codes to reference memory offsets. If you're using hex codes memory offsets will be incorrect, as they are calculated by reference types (patcher doesn't have a decompiler inside). Furthermore, memory size of the function will be incorrect too. So, I strongly recommend to use any *_CODE keys/sections with pseudo-code only. If you need to quickly replace some hex, use BEFORE_HEX/AFTER_HEX or relative offset and MODDED_HEX.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...