Amineri Posted March 29, 2013 Author Share Posted March 29, 2013 I'm glad my research was helpful. I wanna try this mod myself, and I'll eventualy do it, but man, I've gotta plan it well, this one is a dirty mod... :P Yes, it's too bad that the changes ranged all over the place. The basic "starter" change (enabling the Loadout Button for SHIVs in the Barracks) is a super-simple one ... just changing a few bytes in one spot. Unfortunately, there were many other places in the code with the assumption that SHIVs didn't get loaded out. The biggest one relates to item categories. There are six item categories, which are assigned in the most hacked up way ... In BuildItems() (the big master call that calls BuildItem() for all 195 items in the game), the XGItemTree class variable m_iCurrentCategory is re-set multiple times. BuildItem() is called to build an item, and then m_iCurrentCategory is read from inside the function call to set the current item's category. It's really very bad programming practice doing it this way, instead of passing the category as a function parameter of BuildItem(). In essence, what this does is make the item category of an item a function of the order in which it is called in BuildItems(). The reason this is important -- the Loadout screen has a hard-code check that only category 1 items are eligible for display in the weapon/item select screen. SHIV weapons were in category 3 (with interceptor weapons). To move them to category 1, I couldn't just change their call parameter -- I actually had to re-arrange the entire call order of BuildItems(). That's why one of the hex code blocks is so huge. Incidentally, this is why the SHIV weapons show up for purchase in with the soldier weapons/equipment in the Engineering purchase UI. The first tab is category 1, second tab is category 2, third tab is category 3. Making the SHIV weapons equippable had the side effect of putting them into the first tab. Another issue is that the items don't store any sort of enumerated value to keep track of what type of item they are. Instead, there are functions that perform hard-checks on their enumerated ID number to determine this. This is why the code to get the SHIV weapon item cards working was so messy. Rather then simply changing an internal field for the SHIV weapons declaring them to be a weapon, I had to modify the ItemIsWeapon() function to return true. It basically checked 1 < item ID < 55 or 84 < item ID < 100. SHIV weapons fall in the block [113, 116]. However, the ItemIsWeapon() call didn't have room to add the extra boolean check. I was lucky (I guess) that the ItemIsAccessory() check was poorly written. It checks each accessory item ID directly ... a la iItem == 76 || (iItem == 80) || (iItem == 88) || (iItem == 85) || (iItem == 79) || (iItem == 77) || (iItem == 82) || (iItem == 81) || (iItem == 78). This easily condenses down to 76 <= item ID <= 82 or item ID == 85 or item ID == 88. This allowed the boolean check "guts" for accessory checking to fit into the space in ItemIsWeapon(). The function ItemIsAccessory() had enough space for the weapon boolean check, including the SHIV weapons, so I put it there, and then swapped the calls. It is totally a hack on top of a hack, and one that I'm not particularly proud of. ~_~ ---------------------------------------------------------------------- Anyhow, a little bit of a rant ... (sorry!). I really just wanted to explain that the original code regarding loadouts, SHIVs, and category is kind of "spaghetti-ish", which lead to needing a lot of little changes to get the thing working. I'll keeping thinking of ways to make the SHIV loadout changes cleaner, but there's definitely limits to what I can do :(. Any suggestions as to simplifying the hex code changes for the mod would be happily accepted. ^_^ P.S. Would this modlet be a good candidate for documenting on the nexus wiki? Link to comment Share on other sites More sharing options...
anUser Posted March 29, 2013 Share Posted March 29, 2013 Yeah I've known of this "assumptions". Today I've been planning a rebalance of techs and foundry projects and they all call functions that check against pre-set values for item requirements and so... quite nasty btw, could it be possible to "unhide" some other equippable item by this method? my other current line of research lies around balancing items and abilities, and I'd really love to have just a few more items A full modlet fuly documented on the wiki? sure! .. but this one maybe under "Advanced Hexscripting: Chapter XIV - decoding spaghettish firaxis' little artworks" :D just kidding, it'll be great Link to comment Share on other sites More sharing options...
Amineri Posted March 29, 2013 Author Share Posted March 29, 2013 It is definitely possible to move items between different categories by altering the call order of the BuildItem() calls in the BuildItems() function. However, the items also have to pass some other checks in order to be equippable. There are some ClassLock checks, which test against some hard-coded item IDs that each class is allowed. Also, different items are allowed into the different slots via some various tests. Unfortunately it's not terribly clear to me where all the test are made. It is also possible to add new BuildItem() calls for items that were deleted. I did this for the Sentry gun for the SHIV. To do this it is necessary to free up space in the function by condensing down some of the other BuildItem() calls. Most non-buildable items have 4 fields set to -1 (each -1 takes 5 bytes). However, I found that only the build time needs to be -1 -- but the # of engineers must be set to -1 or 1 as well. It's another example of some "interesting" programming. The value assigned inside BuildItem() is an int cast of a float multiply of the build time X ABS(# engineers). The item is not buildable if this value exactly equal -1. Good thing there hasn't been any round-off errors :/. This means you can shave 8 or 12 bytes off of each non-buildable item, freeing up enough space to add some additional BuildItem() calls that weren't there. There are item IDs for the following items that aren't built (that I've noticed, anyhow):eItem_PsiGrenadeeItem_FlashBangeItem_PsiAmp ((this might be an alien weapon))eItem_FlameThrower Link to comment Share on other sites More sharing options...
anUser Posted March 29, 2013 Share Posted March 29, 2013 Thanks, I'll def give it a look. And thanks as well for the previous post, many times understanding how certain functionality works is way much harder than what then it is changing it, so much appreciated! Link to comment Share on other sites More sharing options...
Amineri Posted March 29, 2013 Author Share Posted March 29, 2013 I'm pondering the idea of attempting to make some additional items that would go into a SHIV's "off-weapon" slot. One of the tweaks I had to make was to prevent regular pistols from being equippable on SHIVs (with unknown consequences). It might be possible to add in some BuildItem() calls to make some additional "accessory items" for SHIVs. Am thinking of items that give the SHIV various perks or other stat-type tweaks. An early example would be the SHIV Suppression. Rather than giving all SHIVs the Suppression ability when the Foundry project is unlocked, it would unlock the ability to create a "Suppression module". Manufacturing the "SHIV Suppression module" and then equipping it would then give that SHIV the Suppression perk. Possible modules I've thought of:1) Suppression2) Holo-targetting3) Scope4) Extra armor5) Bullet Swarm6) HEAT Ammo7) Rocket or Shredder Rocket It's just an idea I'm kicking around for now ... thought I'd toss it out there and see if anyone had any thoughts on it. Link to comment Share on other sites More sharing options...
dubiousintent Posted March 31, 2013 Share Posted March 31, 2013 Sounds good. Some might think it too unbalancing, but why not a 'Rocket' (to use existing artwork and animations) that does Grenade damage, labelled 'Grenade Launcher' but with more range than the thrown grenade? Then a Foundry upgrade to use Alien Grenades. Probably wouldn't want 'unlimited ammo' but certainly more than just a couple of rounds. Extant technology and I would expect it to really appeal as a cover buster for I/I play. -Dubious- Link to comment Share on other sites More sharing options...
anUser Posted March 31, 2013 Share Posted March 31, 2013 (edited) I'm absolutely in favor of making all of them equippable stuff... I've been exploring the possibility of expanding available items too, but for other purpouses ... and here's what I've seen fo far: #1) knowing firaxis programming practices I have the strong suspicion that when increasing the number of items created (in BuildItems()), if the array's size was pre set, we may be excluding the last elements. Also I suspect some functions that mean to loop through all the items can have the number of iterations pre-set. It's just a thought, it may not be true, but perhaps it's worth checking. #2) despite that, extra items added can only be used as a placeholder for ability charges or some other scripted ability, because there are very limited DGC.ini entries to give each item their properties and abilities. I've managed to make smoke grenades and battle scanners buildables at engineering (they were already "built" by BuildItems()) and now checking the number of equipped items of each of those determines the number of charges of each ability. The trick here is that I've got to give each unit the smoke grenade & battlescanner perk for it to work, so I guess the same applies to the superheavyinfantryvehicles, just giving them an item with the "Holo-targeting" ability won't make them have the ability (actually with this one in particular I've no idea how it works). This trick could work for Rockets though, since it's not enough to have the ability and the item, but you also need item charges that you can set counting the number of certain item in the inventory, as I do for smoke grenades and rockets. Mention appart sectopod weapons, they have an entry in the DGC.ini that you can edit (although it'll affect sectopods as well, I suspect) the problem here is still #1 cause they aren't created in BuildItems. #3 I've traced this functions that determine the kind of weapon and I really think they could use a severe re-writting. I've searched for calls to ItemIsAccessory, ItemIsWeapon and ItemIsArmor, and it seems to me it all starts at XComStrategyGame >> XGSoldierUI >> GetItemCardFromOptionPseudocode: GetItemCardFromOption: if (ItemIsAccessory(eItem)) { BuildEquippableItemCard(eItem); } else { if (ItemIsWeapon(eItem)) { BuildWeaponCard(eItem); add pistol upgrade; } else { BuildItemCard(eItem); } }so first it checks if item is accessory, else check if it's a weapon, else call XComGame >> XGItemCards >> BuildItemCard Pseudocode: BuildItemCard: if (ItemIsWeapon(eItem)) { BuildWeaponCard(eItem); } else { if (ItemIsArmor(eItem)) { return BuildArmorCard(eItem); } else { BuildEquippableItemCard(eItem); } }It seems to me quite redundant. Maybe re-ordering GetItemCardFromOption and working with the ItemIsXxxx functions we can free up completely this last BuildItemCard function for other purpouses. Take next code as an example: BuildItemCard: if (ItemIsArmor(eItem)) { BuildArmorCard(eItem); } else { if (ItemIsWeapon(eItem)) { BuildWeaponCard(eItem); add pistol upgrade; } else { BuildEquipableItemCard(eItem); } }This way we also free up ItemIsAccessory or one of those three functions.The problem is still those ItemIsXxxx, because they're given the item Id, so I would suggest using the smaller of the three to check for armors on the first check (I assume it's the type of item that there'd be the less), then use the largest of the three functions to check for weapons, so it admits customization, and leave the middle one unused and available for some other purpouse. edit: typo Edited March 31, 2013 by anUser Link to comment Share on other sites More sharing options...
Amineri Posted March 31, 2013 Author Share Posted March 31, 2013 I had to work with the Item Card functions when making the primary SHIV weapons equippable. The Item Cards themselves are only for display -- not for any other in-game functionality. The Item Card is what is displayed in the Barracks and in Engineering-Build UIs when you click the little button in the big item button to get the detailed stats for the item. This was why the SHIV weapon (originally) was showing a blank card -- the ItemIsWeapon() call would return false for SHIV weapons. Once I modified it to return true for SHIV weapons, the damage, crit chance, and max damage were correctly displayed. Before putting in those changes, the SHIV weapons still worked correctly in the tactical game. So, I feel pretty confident that the Item Card is only for UI display. That aside, there is a 4th call, ItemIsShipWeapon. All four functions are defined in XcomGame.upk, but are used in XcomStrategyGame.upk (since they ended up being used only to determine what type of Item Card to build). So here is where it gets really fun ... Each function is linked into XcomStrategyGame.upk at compile time based on whether or not it was used (during the final build compile). This means that some functions in a class may be present, and other included (it's NOT class-by-class, but function-by-function). Looking through the Names Table for XcomStrategyGame.upk, only the two functions ItemIsAccessory() and ItemIsWeapon() were linked into XcomStrategyGame.upk. This means there is no way of calling ItemIsArmor() or ItemIsShipWeapon() from there. So we're stuck with the two existing functions ... ~_~ --------------------------------------------------------------- The other big issue that I would have to overcome if I were to implement this is : I still don't know how the Foundry project gives SHIVs the Suppression ability. Clearly it works, but I cannot for the life of me trace out how it works. When the Foundry project completes, it only updates the array of completed Foundry projects. I can see no place in the strategy game where the Suppression perk is given to SHIVs. The foundry history is passed to the tactical game via the StrategyGameTransport structure, but again I can find no place in the accessible code which gives SHIVs the Suppression perk based on the FoundryHistory array. Which is a real shame, since it would open up some more options to play with. Sigh ... Link to comment Share on other sites More sharing options...
anUser Posted April 1, 2013 Share Posted April 1, 2013 omg so unused functions will remain unusable? out of curiosity, could it be possible using current tools to de-compile the whole game and compile it again, so all this functions were referenced somehow and so we can use them? Well anyway by now you've managed to make shivs equippable and working properly, right? That's something. Another way I've found for "customizing" weapons is playing with the abilities that activate them. I'm toying with a laser sniper rifle that doesn't have standard shot and only has headshot (which I've cut down to 1 turn of cooldown). for shivs It could be ok a secondary weapon that only suppresses... but again that means bringing more usable weapons from the depths they're buried in.. I'd def give sectopod weaps a try. if you can use them there's always room in OnTakeDamage to reduce or increase damage depending on the source... just a thought Link to comment Share on other sites More sharing options...
Amineri Posted April 1, 2013 Author Share Posted April 1, 2013 I should clarify about the unused-functions-remaining-unusable thing with some concrete examples: 1) The function ItemIsShipWeapon() is defined in XcomGame.upk, but never called. It is a part of the class XGTacticalGameCore(). ItemIsShipWeapon() has no table reference in XcomStrategyGame.upk, and so can never be called from anywhere in there (directly), but can be called from anywhere in XcomGame.upk. 2) The function DebugAnims() is defined in XcomGame.upk, but never called. It is a part of the class XGUnit(). DebugAnims() retains a table reference in XcomGame.upk, and so can be called from anywhere within that upk, that is in scope. Link to comment Share on other sites More sharing options...
Recommended Posts