Kaldreth88 Posted March 19, 2015 Share Posted March 19, 2015 I've been looking into changing how the game flags special soldiers and I found the function XGStrategySoldier.IsASpecialSoldier in XComStrategyGame.upk. I understand how it flags Zhang, Annette, and Van Doorn so I don't want to change that. What I would like to do is add another condition that flags the Easter Egg heroes as special soldiers, too. There just doesn't seem to be enough space left for that. I noticed this function in Long War is bigger compared to the vanilla function. How do I go about increasing the size of the function, and what are some practices to determine the correct byte and virtual memory size? From reading through the forums, I have a vague understanding of how this is done. The wiki doesn't provide enough information on how this works or what the downsides are. In XGStrategySoldier.IsASuperSoldier , m_eEasterEggChar has the values for each Super Soldier. I rewrote that function so it doesn't flag the easter egg heroes as super soldiers. I figured in XGStrategySoldier.IsASpecialSoldier I would just add a line that states if m_eEasterEggChar is greater than 0 it would should be a Special Soldier. I haven't figured out exactly how I'll write that script out since I'm still learning how unreal script works, but I'll get around to it. If there's an alternative (easier) way to go about this, I wouldn't mind doing that instead. Thanks in advance. Link to comment Share on other sites More sharing options...
wghost81 Posted March 19, 2015 Share Posted March 19, 2015 Which tool do use for modding? PatcherGUI/PatchUPK or UPKModder? Both can deal with resizing an object, but in a different manner. Link to comment Share on other sites More sharing options...
Kaldreth88 Posted March 19, 2015 Author Share Posted March 19, 2015 PatcherGui. I never got around to figuring out UPKModder. Link to comment Share on other sites More sharing options...
wghost81 Posted March 19, 2015 Share Posted March 19, 2015 (edited) OK. So there are different ways to resize an object in Patcher, all of them are described in PatchUPK_Readme.txt. It is preferable to use AUTO modifier to make Patcher automatically check ans resize the object if necessary. Example:OBJECT=XGStrategyAI.GetAltWeapon:AUTO If you are using pseudo-code auto resize will adjust both serial and memory sizes for you, but if you are using hex, it will adjust serial size only and you'll need to calculate and set memory size manually. If you are rewriting the whole function and using pseudo-code the best way is to use AUTO modifier and [REPLACEMENT_CODE] section. In this case Patcher will resize the function to fit replacement code size and adjust all the sizes. Another way to resize a function is to use EXPAND_FUNCTION key:EXPAND_FUNCTION=XGStrategyAI.GetPossibleAliens:5828 5828 here is the size of the whole function object, not just the script. Edited March 19, 2015 by wghost81 Link to comment Share on other sites More sharing options...
Kaldreth88 Posted March 19, 2015 Author Share Posted March 19, 2015 That's a lot of information. I'm at a loss on where to go from here. Pseudo-code seems to be the easiest way but I don't know how it works, and I don't want to rewrite the entire function. I'm only looking to insert a line and expanding the function size. If that involves rewriting the entire function in psuedo-code that sounds impossible to me, at the moment. I'd probably have an easier time testing out my changes in hex code, but I still don't understand how I "set memory size manually". And how do I calculate the memory size of the original and the modified version? is it by adding this line to the file? EXPAND_FUNCTION=XGStrategyAI.GetPossibleAliens:5828 Link to comment Share on other sites More sharing options...
wghost81 Posted March 20, 2015 Share Posted March 20, 2015 It depends on the function and the code. If there are jump offsets, for example, you'll need to re-calculate them because the newly inserted code will shift serial and memory positions. Can you post the unreal or hex code here? So I could see what will be the easiest way in your case. Here's the similar question about memory size I answered recently: http://forums.nexusmods.com/index.php?/topic/2686094-my-mod-looks-right-when-decompiled-with-ue-explorer-but-it-crashes-the-game-on-start-up/?p=23578279 Link to comment Share on other sites More sharing options...
Kaldreth88 Posted March 20, 2015 Author Share Posted March 20, 2015 (edited) Here it is from XcomStrategygame.upk>XGStrategySoldier.IsASpecialSoldier (000/000) [0F 00 C6 53 00 00 21 16 36 00 00 00 00 00 00]L(19/15) -> LV(9/5) -> NC(9/9)nmZhang = 'ZhangSoldier'(013/00F) [0F 00 C5 53 00 00 21 44 01 00 00 00 00 00 00]L(19/15) -> LV(9/5) -> NC(9/9)nmAnnette = 'Annette'(026/01E) [07 50 01 84 9A 35 07 FB FF FF B1 F9 FF FF 00 00 35 BC F8 FF FF A5 F9 FF FF 00 00 01 60 53 00 00 19 2E 58 FE FF FF 19 12 20 C6 FE FF FF 0A 00 8E FA FF FF 00 1C 3D FD FF FF 16 0A 00 90 FA FF FF 00 1B 8D 11 00 00 00 00 00 00 16 15 00 C2 FB FF FF 00 1C A8 FC FF FF 24 04 00 C6 53 00 00 16 16 18 91 00 9A 35 07 FB FF FF B1 F9 FF FF 00 00 35 BC F8 FF FF A5 F9 FF FF 00 00 01 60 53 00 00 19 2E 58 FE FF FF 19 12 20 C6 FE FF FF 0A 00 8E FA FF FF 00 1C 3D FD FF FF 16 0A 00 90 FA FF FF 00 1B 8D 11 00 00 00 00 00 00 16 15 00 C2 FB FF FF 00 1C A8 FC FF FF 24 04 00 C5 53 00 00 16 16 16]JIN(296/192) -> NF(293/189) -> NF(144/92) -> SM(47/27) -> SM(28/16) -> IV(9/5) -> C(95/63) -> CDC(62/42) -> C(53/37) -> CC(31/19) -> OC(9/5) -> FF(10/6) -> EFP(1/1) -> VF(10/10) -> EFP(1/1) -> FF(21/13) -> BC(2/2) -> LV(9/5) -> EFP(1/1) -> EFP(1/1) -> S(147/95) -> NF(144/92) -> SM(47/27) -> SM(28/16) -> IV(9/5) -> C(95/63) -> CDC(62/42) -> C(53/37) -> CC(31/19) -> OC(9/5) -> FF(10/6) -> EFP(1/1) -> VF(10/10) -> EFP(1/1) -> FF(21/13) -> BC(2/2) -> LV(9/5) -> EFP(1/1) -> EFP(1/1) -> EFP(1/1)if((m_kSoldier.kAppearance.iHead == XComContentManager(class'Engine'.static.GetEngine().GetContentManager()).GetContentIdFromTag(4, nmZhang)) || m_kSoldier.kAppearance.iHead == XComContentManager(class'Engine'.static.GetEngine().GetContentManager()).GetContentIdFromTag(4, nmAnnette))(14E/0DE) [04 27]R(2/2) -> T(1/1)return true(150/0E0) [07 80 01 7A 35 F0 F8 FF FF A5 F9 FF FF 00 01 01 60 53 00 00 1F 54 68 65 20 47 65 6E 65 72 61 6C 00 16]JIN(46/34) -> NF(43/31) -> SM(28/16) -> IV(9/5) -> SC(13/13) -> EFP(1/1)if(m_kSoldier.strNickName == "The General")(17E/102) [04 27]R(2/2) -> T(1/1)return true(180/104) [04 28]R(2/2) -> F(1/1)return false(182/106) [04 3A C7 53 00 00]R(10/6) -> RN(9/5)return ReturnValue(18C/10C) [53]EOS(1/1) I'm reading through that post, atm. It's making more sense. Edited March 20, 2015 by Kaldreth88 Link to comment Share on other sites More sharing options...
wghost81 Posted March 21, 2015 Share Posted March 21, 2015 (edited) That's the original LW code, as far as I can see. It would be better if I could see the modified one. :wink: But regardless, as you wrote earlier, you're trying to add some code here. If adding it to the end of the function is OK, you can try using before/after style:OBJECT=XGStrategySoldier.IsASpecialSoldier:AUTO [BEFORE_CODE] 04 27 04 28 04 3A <.ReturnValue> [AFTER_CODE] 04 27 //fit your new code here //if you use pseudo-code, patcher will recalculate both memory and serial sizes automatically //but since you are inserting a code, not rewriting a whole script, //you still need to calculate all the jump offsets in your code manually (use UEE tokens view for help) //no recalculations are needed for original code, though, as new code is added to the end of the script 04 28 04 3A <.ReturnValue> If you don't like pseudo-code, you can do this in hex:OBJECT=XGStrategySoldier.IsASpecialSoldier:AUTO [BEFORE_HEX] 04 27 04 28 04 3A C7 53 00 00 [AFTER_HEX] 04 27 //fit your new code here //patcher will recalculate serial size automatically, but memory size will be wrong //you will need to calculate memory size and //all the jump offsets in your code manually (use UEE tokens view for help) 04 28 04 3A C7 53 00 00 REL_OFFSET=0x28 UNSIGNED=//manually calculated memory size here BTW, a piece of good news for those who fear of pseudo-code. :wink: I was working on hex2pseudocode decompiler for the last week and I almost finished it. Here's an example of vanilla XGStrategySoldier.IsASpecialSoldier function converted to pdeudo-code:/*(0x0000/0x0000)*/ 0F 00 <.nmZhang> 21 <ZhangSoldier> /*(0x0013/0x000F)*/ 0F 00 <.nmAnnette> 21 <Annette> /*(0x0026/0x001E)*/ 07 [@label_0x0150] 84 9A 35 <XComGame.XGTacticalGameCoreNativeBase.TAppearance.iHead> <XComGame.XGTacticalGameCoreNativeBase.TAppearance> 00 00 35 <XComGame.XGTacticalGameCoreNativeBase.TSoldier.kAppearance> <XComGame.XGTacticalGameCoreNativeBase.TSoldier> 00 00 01 <@m_kSoldier> 19 2E <XComGame.XComContentManager> 19 12 20 <Engine.Engine> 0A 00 <Engine.Engine.GetEngine.ReturnValue> 00 1C <Engine.Engine.GetEngine> 16 0A 00 <Engine.Engine.GetContentManager.ReturnValue> 00 1B <GetContentManager> 16 15 00 <XComGame.XComContentManager.GetContentIdFromTag.ReturnValue> 00 1C <XComGame.XComContentManager.GetContentIdFromTag> 24 04 00 <.nmZhang> 16 16 18 [@label_0x0091] 9A 35 <XComGame.XGTacticalGameCoreNativeBase.TAppearance.iHead> <XComGame.XGTacticalGameCoreNativeBase.TAppearance> 00 00 35 <XComGame.XGTacticalGameCoreNativeBase.TSoldier.kAppearance> <XComGame.XGTacticalGameCoreNativeBase.TSoldier> 00 00 01 <@m_kSoldier> 19 2E <XComGame.XComContentManager> 19 12 20 <Engine.Engine> 0A 00 <Engine.Engine.GetEngine.ReturnValue> 00 1C <Engine.Engine.GetEngine> 16 0A 00 <Engine.Engine.GetContentManager.ReturnValue> 00 1B <GetContentManager> 16 15 00 <XComGame.XComContentManager.GetContentIdFromTag.ReturnValue> 00 1C <XComGame.XComContentManager.GetContentIdFromTag> 24 04 00 <.nmAnnette> 16 16 16 /*(0x014E/0x00DE)*/ 04 27 [#label_0x0150] /*(0x0150/0x00E0)*/ 04 28 /*(0x0152/0x00E2)*/ 04 3A <XGStrategySoldier.IsASpecialSoldier.ReturnValue> /*(0x015C/0x00E8)*/ 53 Now existing functions will be easy to rewrite, as all the references and jumps are decompiled and replaced with labels. Edited March 21, 2015 by wghost81 Link to comment Share on other sites More sharing options...
Recommended Posts