Jump to content

Modding XCOM under Linux


wghost81

Recommended Posts

Hmmmm... interesting. its good to know its possible. technically with current setup you need to buy only 1 medikit for entie game if you use 1 medic per mission which is a big flaw. perks could be altered to function differently ie fiel medic heals 1 hp bar more, and grenadier can throw nades further.

 

however there would be a problem of only few items per mission. perhaps one grenadier perk coul remain the sme and if doable each time you use grenade one grenade item would be removed from storage. same with medic. could actions be altered in such a way to change item number in storage when performed?

Edited by Amphibious
Link to comment
Share on other sites

  • Replies 77
  • Created
  • Last Reply

Top Posters In This Topic

The XGStorage class which holds all the items is in XComStrategyGame.upk, which is inaccessible during tactical gameplay, as the active "thread" is in XComGame.upk. For example we can't directly access the date/time info in XComStrategyGame, so for the time-based upgrades we have to pack info into the StrategyGameTransport class. The way this works is that the transport class data is filled out while the strategy game has control. StrategyGameTransport is actually defined in XComGame, and has most objects defined as import objects in XComStrategyGame ... hence the strategy game can fill out the data, which persists and is accessible within the tactical game.

 

The StrategyGameTransport holds quite a lot of info, including the TCharacter and TSoldier structures for each soldier (which are also maintained in the strategy side in XGStrategySoldier). The TCharacter structure contains a TInventory structure which contains the basic inventory information for each soldier. TInventory is pretty basic, just containing some arrays of EItem enum values. It allows a unit to have 1 armor item, 1 pistol item, 16 large items, 16 small items, and 16 custom items. However when the tactical game starts up there is a "loadout" process because the necessary machinery to maintain/display items requires more than just an enum for the weapon. Most of this is handled in the XGLoadoutMgr class, which converts the enum values to appropriate XGWeapon and XComWeapon classes, all of which is stored within an instance of the XGInventory class. Each XGUnit has it's own instance of XGInventory.

 

XGInventory has a quite different storage system than TInventory -- it's indexed by the attachments points on the unit pawn. There is a sort of "backpack" attachment point which is invisible and can store multiple items in an array. From what I've seen, regular soldiers only support loading out 2 large items -- the 1st goes into the right-back slot, and the 2nd goes into the left-back slot. Any additional go into the backpack slot. The small items put those items explicitly marked with the eWP_Backpack property into the backpack slot. Other items (e.g grenades) go into three different slots progressively -- any non-backpack item after the 3rd one is discarded (which is the source of the problem with mods that allow for more than 3 small item slots). It also seems that the structure used to save/restore XGInventory only saves up to 4 backpack items, which could also cause issues. MEC secondary weapon systems (which are large items also) use a different system, as each MEC secondary system has a new custom attachment point defined, which is only valid for MEC pawns.

 

Soo... as you can see, it's a bit of a mess with the translation between the strategy and tactical inventory systems. Strategy only uses the TInventory structure, and inventory information is transported to the tactical game using this structure via the StrategyGameTransport class. Once in the tactical game, the TInventory data is mapped into an XGInventory structure using the XGLoadoutMgr class. After the tactical mission is completed, the TCharacter and TSoldier structures attached to the XGUnit are copied back to the StrategyGameTransport which then updates the XGStrategySoldier versions back in the strategy game. In Long War I make use of this to set an upper bit of the Mind Control perk when a soldier successfully mind controls an Ethereal, which in Long War unlocks the ability to train Rift prior to entering the Gollop chamber.

 

So what has to happen would be writing new code in the locations where the items are used that would go through and decrement and repack the TInventory structure for the soldier (for example, if soldier had small items 1 and 2, and used item 1, item 2 has to be repacked into item slot 1 -- I think. Once the XGUnit's TCharacter structure (with it's embedded TInventory structure) is modified, it should automatically update back to the strategy game. This is why I recommend removing items from XGStorage.m_arrItems when equipping them if you want consumable items, as the item is removed from storage when equipped. If the item isn't used, it is unloaded from the soldier back into storage after the mission. If it is used, it simply isn't put back into storage, effectively decrementing the item count correctly.

 

Sorry for the rather long post, but it's the whole process is a little bit complex.

Link to comment
Share on other sites

Thanks for explaining Amineri. It's seems a lot of work.

 

Do you know perhaps how SW total loss option works? It only removes items equipped on soldier who die, right? Then the function is probably something like "if soldierstatus = dead then remove soldierinventory". Could it be enable as vanilla option and then reworked in a way to make you lose only equipment on dead soldiers if mission result is fail - function would have to be something like "if soldierstatus = dead and missionstatus = fail then remove soldierinventory". Could it be done without messing up the original total loss function?

 

My problem is I+m on Linux so UE explorer won't work natively to search for right part of the code. If someone could post the part of the code that enables and makes tl function i'd be very grateful.

 

This would make you lose equipment of dead soldiers if missiom has failed.

Link to comment
Share on other sites

The vanilla Total Loss is enabled in the XGFacility_Barracks.MoveToMorgue function. There is an m_bMIA flag potentially set for each soldier returning from a mission, although I feel the vanilla implementation is a bit messed up. In vanilla m_bMIA is set from m_bLeftBehind, which is only set when aborting a mission, and the soldier is outside the dropzone volume. In vanilla if the mission is a complete squadwipe then no gear is lost.

 

Mechanically how it is implemented in vanilla is that XGStorage has two different functions, ReleaseLoadout and RemoveLoadout. ReleaseLoadoud simply decrements the m_arrClaims counter, allowing the item to be claimed by another soldier. RemoveLoadout both decrements m_arrClaims and m_arrItems. If only m_arrItems were updated, the count of claimed items would be off.

Link to comment
Share on other sites

Each armor has it's number of small item slots configured individually in the DefaultGameCore.ini, so giving extra small item slots to particular armors is easy.

 

The tricky part is making particular slots only have particular item types available. This is possible though, as the large item code allows only non-rocket launcher large items in large item slot 0, and only rocket-launcher large items in large item slot 1. The function that has to be modded is XGFacility_Lockers.GetLockerItems. This function returns a list of all possible equippable items based on the item slot type and index (type = armor, large item, pistol, or small item, while index is the slot position within that category). This will basically require a rewrite of the hex code in the function to make it happen.

 

As an example, I'm putting the UPKmodder code below that we use in Long War to handle the MEC and SHIV item equipping. Note that we had to resize the function to fit in all of our goodies.

 

 

 

MODFILEVERSION=4
UPKFILE=XComStrategyGame.upk
GUID=BB 93 C6 C8 D2 91 82 44 87 9B 79 9B 49 5B 8D E9 // XComStrategyGame EW Patch 3.upk
FUNCTION=GetLockerItems@XGFacility_Lockers
RESIZE=5c

// rewrite to filter display of items 

[BEFORE_HEX]
[HEADER]
42 07 00 00 2A 05 00 00 
[/HEADER]
[CODE]
//if(iSlotType == 0)
07 DD 01 9A 00 08 39 00 00 25 16 

	//arrItems = STORAGE().GetItemsInCategory(2, 0)
	0F 00 04 39 00 00 19 1B 01 2F 00 00 00 00 00 00 16 0E 00 3E 4E 00 00 00 1B 58 12 00 00 00 00 00 00 2C 02 25 4A 16 

	//I = 0
	0F 00 01 39 00 00 25 

	//if(I < arrItems.Length)
	07 DA 01 96 00 01 39 00 00 36 00 04 39 00 00 16 

		//kLockerItem = GetLockerItem(byte(iSlotType), arrItems[I], kSoldier)
		0F 00 02 39 00 00 1B 68 12 00 00 00 00 00 00 38 3D 00 08 39 00 00 10 00 01 39 00 00 00 04 39 00 00 00 06 39 00 00 16 

		//if(kLockerItem.bClassLocked || kLockerItem.bTechLocked)
		07 B5 01 84 2D 35 9D 38 00 00 A1 38 00 00 00 00 00 02 39 00 00 18 1E 00 2D 35 9E 38 00 00 A1 38 00 00 00 00 00 02 39 00 00 16 

			//if(!XComGameReplicationInfo(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kGameCore.ItemIsMecArmor(arrItems[I].iItem) || kSoldier.GetClass() == 6)
			07 B2 01 84 81 19 19 2E 55 FE FF FF 19 12 20 C6 FE FF FF 0A 00 8F FA FF FF 00 1C 3E FD FF FF 16 09 00 77 FA FF FF 00 01 77 FA FF FF 09 00 46 FA FF FF 00 01 46 FA FF FF 30 00 30 FF FF FF 00 1B C7 18 00 00 00 00 00 00 35 69 03 00 00 6C 03 00 00 00 00 10 00 01 39 00 00 00 04 39 00 00 16 16 18 28 00 9A 38 3A 19 00 06 39 00 00 0A 00 30 54 00 00 00 1B 7A 11 00 00 00 00 00 00 16 38 3A 24 06 16 16 

				//arrLockerItems.AddItem(kLockerItem)
				55 00 03 39 00 00 0A 00 00 02 39 00 00 16 

		//else
		06 CC 01 

			//arrLockerItems.InsertItem(0, kLockerItem)
			57 00 03 39 00 00 0B 00 25 00 02 39 00 00 16 

		//++ I
		A5 00 01 39 00 00 16 

		//Loop Continue
		06 48 00 

//else
06 2D 07 

	//if(iSlotType == 1)
	07 58 03 9A 00 08 39 00 00 26 16 

		//arrItems = STORAGE().GetItemsInCategory(1, 0)
		0F 00 04 39 00 00 19 1B 01 2F 00 00 00 00 00 00 16 0D 00 3E 4E 00 00 00 1B 58 12 00 00 00 00 00 00 26 25 4A 16 

		//I = 0
		0F 00 01 39 00 00 25 

		//if(I < arrItems.Length)
		07 55 03 96 00 01 39 00 00 36 00 04 39 00 00 16 

			//iItem = arrItems[I].iItem
			0F 00 00 39 00 00 35 69 03 00 00 6C 03 00 00 00 00 10 00 01 39 00 00 00 04 39 00 00 

			//if(TACTICAL().WeaponHasProperty(iItem, 2))
			07 47 03 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 02 16 

				//kLockerItem = GetLockerItem(byte(iSlotType), arrItems[I], kSoldier)
				0F 00 02 39 00 00 1B 68 12 00 00 00 00 00 00 38 3D 00 08 39 00 00 10 00 01 39 00 00 00 04 39 00 00 00 06 39 00 00 16 

				//if(kLockerItem.bClassLocked || kLockerItem.bTechLocked)
				07 30 03 84 2D 35 9D 38 00 00 A1 38 00 00 00 00 00 02 39 00 00 18 1E 00 2D 35 9E 38 00 00 A1 38 00 00 00 00 00 02 39 00 00 16 

					//arrLockerItems.AddItem(kLockerItem)
					55 00 03 39 00 00 0A 00 00 02 39 00 00 16 

				//else
				06 47 03 

					//arrLockerItems.InsertItem(0, kLockerItem)
					57 00 03 39 00 00 0B 00 25 00 02 39 00 00 16 

			//++ I
			A5 00 01 39 00 00 16 

			//Loop Continue
			06 24 02 

	//else
	06 2D 07 

		//if(iSlotType == 3)
		07 3F 05 9A 00 08 39 00 00 2C 03 16 

			//arrItems = STORAGE().GetItemsInCategory(1, 0)
			0F 00 04 39 00 00 19 1B 01 2F 00 00 00 00 00 00 16 0D 00 3E 4E 00 00 00 1B 58 12 00 00 00 00 00 00 26 25 4A 16 

			//I = 0
			0F 00 01 39 00 00 25 

			//if(I < arrItems.Length)
			07 3C 05 96 00 01 39 00 00 36 00 04 39 00 00 16 

				//iItem = arrItems[I].iItem
				0F 00 00 39 00 00 35 69 03 00 00 6C 03 00 00 00 00 10 00 01 39 00 00 00 04 39 00 00 

				//if(TACTICAL().GetTWeapon(iItem).iSize == 0)
				07 2E 05 9A 35 BC FA FF FF A2 F9 FF FF 01 00 19 1B CB 2F 00 00 00 00 00 00 16 13 00 BF F8 FF FF 00 1B 92 13 00 00 00 00 00 00 00 00 39 00 00 16 25 16 

					//if(iItem == 82)
					07 3D 04 9A 00 00 39 00 00 2C 52 16 

					//else
					06 2E 05 

						//if(TACTICAL().WeaponHasProperty(iItem, 2))
						07 6E 04 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 02 16 

						//else
						06 2E 05 

							//if(iItem == 184)
							07 81 04 9A 00 00 39 00 00 2C B8 16 

							//else
							06 2E 05 

								//kLockerItem = GetLockerItem(byte(iSlotType), arrItems[I], kSoldier)
								0F 00 02 39 00 00 1B 68 12 00 00 00 00 00 00 38 3D 00 08 39 00 00 10 00 01 39 00 00 00 04 39 00 00 00 06 39 00 00 16 

								//if(kLockerItem.bClassLocked || kLockerItem.bTechLocked)
								07 17 05 84 2D 35 9D 38 00 00 A1 38 00 00 00 00 00 02 39 00 00 18 1E 00 2D 35 9E 38 00 00 A1 38 00 00 00 00 00 02 39 00 00 16 

									//arrLockerItems.AddItem(kLockerItem)
									55 00 03 39 00 00 0A 00 00 02 39 00 00 16 

								//else
								06 2E 05 

									//arrLockerItems.InsertItem(0, kLockerItem)
									57 00 03 39 00 00 0B 00 25 00 02 39 00 00 16 

				//++ I
				A5 00 01 39 00 00 16 

				//Loop Continue
				06 A0 03 

		//else
		06 2D 07 

			//if(iSlotType == 2)
			07 2D 07 9A 00 08 39 00 00 2C 02 16 

				//arrItems = STORAGE().GetItemsInCategory(1, 0)
				0F 00 04 39 00 00 19 1B 01 2F 00 00 00 00 00 00 16 0D 00 3E 4E 00 00 00 1B 58 12 00 00 00 00 00 00 26 25 4A 16 

				//I = 0
				0F 00 01 39 00 00 25 

				//if(I < arrItems.Length)
				07 2D 07 96 00 01 39 00 00 36 00 04 39 00 00 16 

					//iItem = arrItems[I].iItem
					0F 00 00 39 00 00 35 69 03 00 00 6C 03 00 00 00 00 10 00 01 39 00 00 00 04 39 00 00 

					//if(TACTICAL().GetTWeapon(iItem).iSize == 1)
					07 1F 07 9A 35 BC FA FF FF A2 F9 FF FF 01 00 19 1B CB 2F 00 00 00 00 00 00 16 13 00 BF F8 FF FF 00 1B 92 13 00 00 00 00 00 00 00 00 39 00 00 16 26 16 

						//if((iSlotIndex == 0) && TACTICAL().WeaponHasAbility(iItem, 19))
						07 53 06 82 9A 00 07 39 00 00 25 16 18 2C 00 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2E FF FF FF 00 1B 24 35 00 00 00 00 00 00 00 00 39 00 00 2C 13 16 16 

						//else
						06 1F 07 

						//if((iSlotIndex == 1) && !TACTICAL().WeaponHasAbility(iItem, 19))
						07 97 06 82 9A 00 07 39 00 00 26 16 18 2E 00 81 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2E FF FF FF 00 1B 24 35 00 00 00 00 00 00 00 00 39 00 00 2C 13 16 16 16 

						//else
						06 1F 07 

							//if(TACTICAL().WeaponHasProperty(iItem, 14))
							07 C8 06 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 0E 16 

							//else
							06 1F 07 

								//kLockerItem = GetLockerItem(byte(iSlotType), arrItems[I], kSoldier)
								0F 00 02 39 00 00 1B 68 12 00 00 00 00 00 00 38 3D 00 08 39 00 00 10 00 01 39 00 00 00 04 39 00 00 00 06 39 00 00 16 

								//AddLargeItemToLockerList(kLockerItem, arrLockerItems)
								1B C3 00 00 00 00 00 00 00 00 02 39 00 00 00 03 39 00 00 16 

					//++ I
					A5 00 01 39 00 00 16 

					//Loop Continue
					06 87 05 

//return arrLockerItems
04 00 03 39 00 00 

//return ReturnValue
04 3A 05 39 00 00 

//EOS
53 
[/CODE]
[/BEFORE_HEX]

// using local variable from XGFacility_Lockers.DisableSmallSlot
// local int iLength   00 30 38 00 00 
// from XComHeadquartersCheatManager.LowerPanic
//   local int iCountry  00 F8 21 00 00
[AFTER_HEX]
[HEADER]
42 07 00 00 86 05 00 00 
[/HEADER]
[CODE]
//if(iSlotType == 0)
07 40 00 9A 00 08 39 00 00 25 16 

	//arrItems = STORAGE().GetItemsInCategory(2, 0);
	0F 00 04 39 00 00 19 1B 01 2F 00 00 00 00 00 00 16 0E 00 3E 4E 00 00 00 1B 58 12 00 00 00 00 00 00 2C 02 25 4A 16 

//else
06 b8 00 

	//arrItems = STORAGE().GetItemsInCategory((kSoldier.IsATank() || kSoldier.IsAugmented () ? 3 : 1), 0);
	0F 00 04 39 00 00 19 1B 01 2F 00 00 00 00 00 00 16 34 00 3E 4E 00 00 00 1B 58 12 00 00 00 00 00 00 45 84 19 00 06 39 00 00 0A 00 C1 53 00 00 00 1B 93 17 00 00 00 00 00 00 16 18 20 00 19 00 06 39 00 00 0A 00 BF 53 00 00 00 1B 8C 17 00 00 00 00 00 00 16 16 02 00 2C 03 02 00 2C 01 25 4A 16 
																													   	
//I = 0;
0F 00 01 39 00 00 25 

//if(I < arrItems.Length)
07 24 07 96 00 01 39 00 00 36 00 04 39 00 00 16 

	//iItem = arrItems[I].iItem
	0F 00 00 39 00 00 35 69 03 00 00 6C 03 00 00 00 00 10 00 01 39 00 00 00 04 39 00 00 

	// iCountry = 1
	0F 00 FD 21 00 00 26 

	// switch(iSlotType)
	05 08 39 00 00 00 00 08 39 00 00 

		// case 0: // armor slot
		0A 4b 02 2C 00 

			//if(TACTICAL().ArmorHasProperty(iItem, 1)) // armor property eAP_Tank
			07 8e 01 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2C FF FF FF 00 1B 67 01 00 00 00 00 00 00 00 00 39 00 00 2C 01 16 

				//if(!kSoldier.IsATank())
				07 8b 01 81 19 00 06 39 00 00 0A 00 BF 53 00 00 00 1B 8C 17 00 00 00 00 00 00 16 16 

					// iCountry = 0 // tank armor and soldier is not a tank
					0F 00 FD 21 00 00 25 
					
			// else 
			06 bb 01 

				// if(kSoldier.IsATank())
				07 bb 01 19 00 06 39 00 00 0A 00 BF 53 00 00 00 1B 8C 17 00 00 00 00 00 00 16 

					// iCountry = 0  // not tank armor and the soldier is a tank
					0F 00 FD 21 00 00 25 

			//if(TACTICAL().ArmorHasProperty(iItem, 9))// armor property eAP_Mec
			07 1b 02 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2C FF FF FF 00 1B 67 01 00 00 00 00 00 00 00 00 39 00 00 2C 09 16 

				//if(!kSoldier.IsAugmented())
				07 18 02 81 19 00 06 39 00 00 0A 00 C1 53 00 00 00 1B 93 17 00 00 00 00 00 00 16 16 
                                
					// iCountry = 0   // MEC armor and soldier is not a MEC
					0F 00 FD 21 00 00 25 

			//else 
			06 48 02 

				// if(kSoldier.IsAugmented())
				07 48 02 19 00 06 39 00 00 0A 00 C1 53 00 00 00 1B 93 17 00 00 00 00 00 00 16 

					// iCountry = 0  // regular armor and soldier is not a regular soldier
					0F 00 FD 21 00 00 25 

			//break; // end case 0 armor slot
			06 5a 06 

		// case 1: // pistol slot
		0A 8e 02 2C 01 

			//if(!TACTICAL().WeaponHasProperty(iItem, 2))
			07 8b 02 81 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 02 16 16 

				// iCountry = 0  // weapon does not have eWP_Pistol
				0F 00 FD 21 00 00 25 

			//break; // end case 1 pistol slot
			06 5a 06 

		// case 2: // large item slot
		0A f1 04 2C 02 

			//if(TACTICAL().GetTWeapon(iItem).iSize != 1)
			07 e0 02 9B 35 BC FA FF FF A2 F9 FF FF 01 00 19 1B CB 2F 00 00 00 00 00 00 16 13 00 BF F8 FF FF 00 1B 92 13 00 00 00 00 00 00 00 00 39 00 00 16 26 16 

				// iCountry = 0  // item is not large
				0F 00 FD 21 00 00 25 

			//if(TACTICAL().WeaponHasProperty(iItem, 14))
			07 3d 03 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 0E 16 

				//if(!kSoldier.IsATank())
				07 3d 03 81 19 00 06 39 00 00 0A 00 BF 53 00 00 00 1B 8C 17 00 00 00 00 00 00 16 16 

					// iCountry = 0  // weapon is tank weapon and soldier is not a tank
					0F 00 FD 21 00 00 25 

			//if(kSoldier.IsAugmented())
			07 23 04 19 00 06 39 00 00 0A 00 C1 53 00 00 00 1B 93 17 00 00 00 00 00 00 16 

				//if(!TACTICAL().WeaponHasProperty(iItem, 20) ) // 	20 = eWP_Mec
				07 9a 03 81 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 14 16 16 

						// iCountry = 0  // weapon not a MEC weapon
						0F 00 FD 21 00 00 25 

				//if(iSlotIndex == 0)
				07 e5 03 9A 00 07 39 00 00 25 16 

					//if(TACTICAL().WeaponHasProperty(iItem, 1)) // 	1 = eWP_Secondary
					07 e2 03 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 01 16 

						// iCountry = 0  // weapon secondary in slot 0
						0F 00 FD 21 00 00 25 

				//else
				06 20 04 

					//if(!TACTICAL().WeaponHasProperty(iItem, 1)) // 	1 = eWP_Secondary
					07 20 04 81 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 01 16 16 

						// iCountry = 0  // non-secondary item in upper slot > 0
						0F 00 FD 21 00 00 25 

			//else  // non-MEC soldier
			06 ee 04 

				//if(TACTICAL().WeaponHasProperty(iItem, 20))
				07 5c 04 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 14 16 

					// iCountry = 0  // weapon is a MEC weapon and soldier isn't a MEC
					0F 00 FD 21 00 00 25 

				//if(TACTICAL().WeaponHasAbility(iItem, 19))
				07 a4 04 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2E FF FF FF 00 1B 24 35 00 00 00 00 00 00 00 00 39 00 00 2C 13 16 

					//if(iSlotIndex == 0)
					07 a4 04 9A 00 07 39 00 00 25 16 

						// iCountry = 0  // weapon is rocket launcher and slot index is 0
						0F 00 FD 21 00 00 25 

				//if(!TACTICAL().WeaponHasAbility(iItem, 19))
				07 ee 04 81 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2E FF FF FF 00 1B 24 35 00 00 00 00 00 00 00 00 39 00 00 2C 13 16 16 

					//if(iSlotIndex == 1)
					07 ee 04 9A 00 07 39 00 00 26 16 

						// iCountry = 0  // weapon isn't a rocket launcher and slot index is 1
						0F 00 FD 21 00 00 25 

			//break; // end case 2 large item slot
			06 5a 06 

		// case 3: // small item slot
		0A 54 06 2C 03 

			//if(TACTICAL().GetTWeapon(iItem).iSize != 0)
			07 43 05 9B 35 BC FA FF FF A2 F9 FF FF 01 00 19 1B CB 2F 00 00 00 00 00 00 16 13 00 BF F8 FF FF 00 1B 92 13 00 00 00 00 00 00 00 00 39 00 00 16 25 16 

				// iCountry = 0  // item isn't small
				0F 00 FD 21 00 00 25 

			//if(kSoldier.IsATank())
			07 a0 05 19 00 06 39 00 00 0A 00 BF 53 00 00 00 1B 8C 17 00 00 00 00 00 00 16 

				//if(!TACTICAL().WeaponHasProperty(iItem, 14))
				07 a0 05 81 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 0E 16 16 

					// iCountry = 0  // soldier is Tank and item isn't eWP_Integrated
					0F 00 FD 21 00 00 25 

			//if(kSoldier.IsAugmented())
			07 fd 05 19 00 06 39 00 00 0A 00 C1 53 00 00 00 1B 93 17 00 00 00 00 00 00 16 

				//if(!TACTICAL().WeaponHasProperty(iItem, 20) ) // 	20 = eWP_Mec
				07 fd 05 81 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 14 16 16 

						// iCountry = 0  // soldier is a MEC and item isn't eWP_Mec
						0F 00 FD 21 00 00 25 

			//if(TACTICAL().WeaponHasProperty(iItem, 2))
			07 36 06 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2D FF FF FF 00 1B 25 35 00 00 00 00 00 00 00 00 39 00 00 2C 02 16 

				// iCountry = 0  // item is a pistol
				0F 00 FD 21 00 00 25 

			//if(iItem == 184) // 184 = eItem_SkeletonKey
			07 51 06 9A 00 00 39 00 00 2C B8 16 

				// iCountry = 0  // item is a skeleton key
				0F 00 FD 21 00 00 25 

			//break;
			06 5a 06 

		// case default:
		0A FF FF 

			//break;
			06 5a 06 

	// if(iCountry == 1)
	07 16 07 9A 00 FD 21 00 00 26 16 
			  
		//kLockerItem = GetLockerItem(byte(iSlotType), arrItems[I], kSoldier);
		0F 00 02 39 00 00 1B 68 12 00 00 00 00 00 00 38 3D 00 08 39 00 00 10 00 01 39 00 00 00 04 39 00 00 00 06 39 00 00 16 

		//if(kLockerItem.bClassLocked || kLockerItem.bTechLocked)
		07 ff 06 84 2D 35 9D 38 00 00 A1 38 00 00 00 00 00 02 39 00 00 18 1E 00 2D 35 9E 38 00 00 A1 38 00 00 00 00 00 02 39 00 00 16 

			//arrLockerItems.AddItem(kLockerItem);
			55 00 03 39 00 00 0A 00 00 02 39 00 00 16 

		//else
		06 16 07 

			//arrLockerItems.InsertItem(0, kLockerItem);
			57 00 03 39 00 00 0B 00 25 00 02 39 00 00 16 

	//++ I;
	A5 00 01 39 00 00 16 

	//goto J0x9F; // [Loop Continue]
	06 c3 00 

//return arrLockerItems;
04 00 03 39 00 00 

//return ReturnValue
04 3A 05 39 00 00 

// null ops
0B 0B 0B 0B 0B 0B 0B 0B 0B 

//EOS
53 
[/CODE]
[/AFTER_HEX] 

 

 

 

If nothing else, at least having access to all of the vanilla hex broken down line-by-line might be useful.

 

The particular part of the vanilla code that handles rocket launchers is in case 2 :

//if(TACTICAL().GetTWeapon(iItem).iSize == 1)
07 1F 07 9A 35 BC FA FF FF A2 F9 FF FF 01 00 19 1B CB 2F 00 00 00 00 00 00 16 13 00 BF F8 FF FF 00 1B 92 13 00 00 00 00 00 00 00 00 39 00 00 16 26 16 

	//if((iSlotIndex == 0) && TACTICAL().WeaponHasAbility(iItem, 19))
	07 53 06 82 9A 00 07 39 00 00 25 16 18 2C 00 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2E FF FF FF 00 1B 24 35 00 00 00 00 00 00 00 00 39 00 00 2C 13 16 16 

	//else
	06 1F 07 

		//if((iSlotIndex == 1) && !TACTICAL().WeaponHasAbility(iItem, 19))
		07 97 06 82 9A 00 07 39 00 00 26 16 18 2E 00 81 19 1B CB 2F 00 00 00 00 00 00 16 15 00 2E FF FF FF 00 1B 24 35 00 00 00 00 00 00 00 00 39 00 00 2C 13 16 16 16 

//else
06 1F 07

 

The "WeaponHadAbility(iItem, 19), is checking to see if the weapon has 19=eAbility_RocketLauncher attached to it in the DGC.ini. So weapons with Fire Rocket are excluded from slot index 0, and only weapons with Fire Rocket are allowed in slot index 1.

Link to comment
Share on other sites

It'll take some time for me process all of this.

 

I have alreay added second small item slot to medium armors, however I would like to prevent exploits like equipping 2 sets of grenades since my original intention was to allow players to bolster their armor without having to sacrifice other equipment

 

p.s. also a quick question - is this mod compatible with EW? i can't find the codes mentioned there in my upk files

 

edit: also if I add second slot to medium armors will that interfere with tactical rigging upgrade? so I will end up with redundant bugged 3rd slot? or will the number of slots stil remain 2?

 

how many large item slots are there available? could one make 2nd large item slot visible and then relabel nanoarmor vest and similar items as large item?

Edited by Amphibious
Link to comment
Share on other sites

 

I have alreay added second small item slot to medium armors, however I would like to prevent exploits like equipping 2 sets of grenades since my original intention was to allow players to bolster their armor without having to sacrifice other equipment

On a non-technical note, if you can only use the extra slot to increase HP, why not just give the armor extra HP instead of requiring the player to equip an extra HP item (which would be the only option) ?

 

edit: also if I add second slot to medium armors will that interfere with tactical rigging upgrade? so I will end up with redundant bugged 3rd slot? or will the number of slots stil remain 2?

There are some bugs associated with adding a third item slot. Basically the vanilla tactical rigging code assumes the soldier had 1 item slot before, which can cause cause an existing item in item slot 2 to be lost. Honestly off the top of my head I don't remember all the vanilla bugs associated with increasing the number of item slots...

 

how many large item slots are there available? could one make 2nd large item slot visible and then relabel nanoarmor vest and similar items as large item?

Unfortunately the DGC.ini setting for iNumLargeItemSlots doesn't work, and the variable isn't even imported into the XComStrategyGame package, so it's not easy to mod to get working.
In vanilla the trigger for a second large item slot is hard-coded to be only for Heavy class. For Long War I changed the trigger to "has Fire Rocket perk", as well as adding large item slots for MECs to equip their secondary weapon systems (e.g. KSM, Flamethrower). Long War MEC-3 suits have 4 displayed large item slots (1 for rifle, 3 for secondary systems), so there's not really a limit.

 

 

Link to comment
Share on other sites

 

On a non-technical note, if you can only use the extra slot to increase HP, why not just give the armor extra HP instead of requiring the player to equip an extra HP item (which would be the only option) ?
There are some bugs associated with adding a third item slot. Basically the vanilla tactical rigging code assumes the soldier had 1 item slot before, which can cause cause an existing item in item slot 2 to be lost. Honestly off the top of my head I don't remember all the vanilla bugs associated with increasing the number of item slots...

 

Well that's not the point since it's not my intention to boost up hp but I felt nf vest and chitine plate are a waste of space in current format.

 

yes there is a bug i just tested it out. second slot item is removed/lost and grenade is equipped instead. i don't understand how or why that happens tbh. new slot is (3rd one) empty and first one is not touched, so why does grenade gets equipped in 2nd one is unclear to me. is there a way to fix it?

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...