Drakous79 Posted January 20, 2016 Share Posted January 20, 2016 (edited) Inspired by SpazmoJones' magic in Enhanced Soldier Customization (for Long War) mod and XCOM 2 character customization YouTube video, I've started to explore EU/EW customization options again. Here is some info on integers - need to sort it in my head too. Warning, maybe old news for someone. --- Quick recap of tokens (Hex values XCOM Modding at Nexus Wiki):0x25 IntZero (size 1 byte, value 0)0x26 IntOne (size 1 byte, value 1)0x2C IntConstByte (size 1 byte, value <= 255)0x?? IntConstShort (size 2 bytes, value <= 65535)0x1D IntConst (size 4 bytes, value <= 4294967295) Four byte integer code 1D FF FF FF FF can hold values like:1 - 4 integers <= 255 (4x 1 byte)1 - 2 integers <= 255 and 1 integer <= 65535 (2x 1 byte and 1x 2 bytes)1 integer <= 255 and 1 integer <= 16777215 (1x 1 byte and 1x 3 bytes)2 integers <= 65535 (2x 2 bytes)1 integer <= 4294967295 (1x 4 bytes)A number of stored integers depends on your needs (amount and size of desired ints). I'd like to store 4 ints <= 255 in NewIdx now, 4 various indexes to one color palette without going crazy with checkpoint records. Setting all four values for the first time is easy. Just set all four bytes. // PatcherGUI code 0F 00 <.NewIdx> // NewIdx = 1D <%b 10> <%b 20> <%b 30> <%b 40> // 757274895 // Decompiled code NewIdx = 757274895; Or alternatively: // PatcherGUI code 0F 00 <.NewIdx> // NewIdx = 92 92 92 // + + + 94 // << shift left 1D <%u 40> 2C <%b 24> // (40 << 24) 16 94 // << shift left 1D <%u 30> 2C <%b 16> // (30 << 16) 16 16 94 // << shift left 1D <%u 20> 2C <%b 8> // (20 << 8) 16 16 1D <%u 10> // 10 16 // Decompiled code NewIdx = (((40 << 24) + (30 << 16)) + (20 << 8)) + 10; 3 of 4 values must be shifted, so they land at the correct byte. How to shift is set by a direction and a number of bits.the 1st byte - no shiftthe 2nd byte - shift in a direction by 1 byte (8 bits)the 3rd byte - shift in a direction by 2 bytes (16 bits)the 4th byte - shift in a direction by 3 bytes (24 bits)Tokens:0x94 LessLess_IntInt - shift left0x95 GreaterGreater_IntInt - shift rightShifting is quite fun, because Unreal Engine 3 uses little endian approach (reads a lot of stuff from right to left; backwards). As it may be good and effective for machines, it is confusing and not so comfortable for non-programming human beings. Lets check integer code again so we can understand the magic of bitwise operations: 0A 14 1E 28 // in byte code 10 20 30 40 // decimal values order in byte code 28 1E 14 0A // in the game 40 30 20 10 // decimal values order in the game // NewIdx shifted by 0 = 10 // NewIdx shifted by 8 = 20 // NewIdx shifted by 16 = 30 // NewIdx shifted by 24 = 40 .Setting just single value is more tricky. I'll show it on example, where is 10 20 30 40 set in the code. & (and) operator with a mask is used on already set integer and compared with help | (or) operator with new shifted value. In the mask I will FF all values I don't want to change and 00 the value I want to change, the third byte as defined in byte code to 33 in this case. The mask follows byte code values order. // PatcherGUI code 0F 00 <.NewIdx> // NewIdx = 9E // | OR 9C // & AND 00 <.NewIdx> 1D FF FF 00 FF // (NewIdx & -16711681) the mask 16 94 // << shift left 1D <%u 33> 2C <%b 16> // (33 << 16) 16 16 // Decompiled code NewIdx = (NewIdx & -16711681) | (33 << 16); The | (or) operator looks at each bit and returns 1 if the bit is 1 in either of the inputs. In this case I masked 30 with zeros, so the result is: 00000000 | 00100001 = 00100001 // 0 | 33 = 33Without the mask would happen this: 00011110 | 00100001 = 00111111 // 30 | 33 = 63Shoud be possible to invert the mask, FF the value to change and use & (and) operator instead, but I haven't tried it. Or to multiply the third value of NewIdx by zero first and then just add the shifted value. Tokens:0x9C And_IntInt - &0x9D Xor_IntInt - ^0x9E Or_IntInt - | Retrieving values is done with help of shifts and masks too. While setting values requires shift to the left, reading values requires shift to the right :smile: If you know Ultima Online, that would be Por Ort Grav words of powah. The mask is simple this time, just FF (255 in decimal). NewInt variable in the next example isn't used in the game, but I used it to demonstrate the retrieval in the code. I'm using LogInternal heavily and checking real time log (Steam's launch parameter -log). Here goes the code: // PatcherGUI code 0F 00 <.NewInt> // NewInt = 9C // & AND 00 <.NewIdx> 2C FF // (NewIdx & 255) 16 0F 00 <.NewInt> // NewInt = 9C // & AND 95 // >> shift right 00 <.NewIdx> 2C <%b 8> 16 2C FF // ((NewIdx >> 8) & 255) 16 0F 00 <.NewInt> // NewInt = 9C // & AND 95 // >> shift right 00 <.NewIdx> 2C <%b 16> 16 2C FF // ((NewIdx >> 16) & 255) 16 0F 00 <.NewInt> // NewInt = 9C // & AND 95 // >> shift right 00 <.NewIdx> 2C <%b 24> 16 2C FF // ((NewIdx >> 24) & 255) 16 // Decompiled code NewInt = (NewIdx & 255); NewInt = ((NewIdx >> 8) & 255); NewInt = ((NewIdx >> 16) & 255); NewInt = ((NewIdx >> 24) & 255); // --- // PatcherGUI code E7 // LogInternal A8 // Join strings 1F <%t "********** D79 debug ********** XGCustomizeUI.AdvanceArmorTint NewIdx 16 ="> 38 53 // IntToString 9C // & AND 95 // >> shift right 00 <.NewIdx> 2C <%b 16> 16 2C <%b 255> 16 16 // Close join strings 16 // Close LogInternal // Decompiled code LogInternal("********** D79 debug ********** XGCustomizeUI.AdvanceArmorTint NewIdx 16=" @ string((NewIdx >> 16) & 255)); You can use 2C <%b 255> // instead of 2C FF for better orientation in pseudo code. Well, that would be all. Hopefully I understand it right, but if you see some inaccurate or wrong info, feel free to correct or explain :smile: 4 values instead of one, that may be armor's primary, secondary, weapon's and helmet color stored. One link with good explanation of AND, OR and shift operations: Bitwise operation at Wikipedia. --- Edit: Corrected speculation part about inverting the mask in Setting just single value section and added Wikipedia link to Bitwise operation. Edited January 20, 2016 by Drakous79 Link to comment Share on other sites More sharing options...
FieryIce Posted January 21, 2016 Share Posted January 21, 2016 (edited) Hello! I made UE3 compiler and decompiler with a handy utilities set. Part of the utilities are using UPKTools as a backend (thanks to wghost81 for a such good tool set!).I'll release it soon. So no more problems with integers or floats, etc. anymore. :smile: Example tokens: float: FloatConst(("0.4059738695"))integer: IntConst(("2325839"))integer HEX: IntConst((09 0f 04 a0))string: StringConst(("色の良いセット Ывдлфо адЦыфо у sljf aeOirJa rfjh "))auto label: @to_label(35)named label: @to_label("Script Ret") Code between /*DESCRIPTION_BEGIN*/ and /*DESCRIPTION_END*/ tags is for a dev-helping purposes and ignored by a compiler. Example of formatted code: Divide_FloatFloat( IntToFloat( InstanceVariable( (IntProperty'XGAbility_Targeted.m_iHitChance') ) ), FloatConst( ("27.0") ), EndFP() ) Example mod: Using this compiler I made http://www.nexusmods.com/xcom/mods/663/?. You may use it as an example.Source code you can see and download here:https://github.com/FI-Mihej/Realistic-Damage-Model-mod-for-Long-War Diff-installable: https://github.com/FI-Mihej/Realistic-Damage-Model-mod-for-Long-War/blob/master/Release/Universal/UCB%20Source%20Code/XComGame.XGAbility_Targeted.RollForHit.ucbFull function: https://github.com/FI-Mihej/Realistic-Damage-Model-mod-for-Long-War/blob/master/Src/Work/LongWar/15f/XComGame.XGAbility_Targeted.RollForHit.ucbUCB source code files can be highlighted by https://github.com/FI-Mihej/UCB-Source-Code-highlighter Edited January 21, 2016 by FieryIce Link to comment Share on other sites More sharing options...
Recommended Posts