Loadout File Changes Additional Items Mod XCOM:EU - 2012

From Nexus Mods Wiki
Revision as of 03:36, 29 May 2013 by Amineri (talk | contribs) (ApplyLoadout)
Jump to: navigation, search

Overview

This contains the file changes to the soldier loadout process.


Back to Additional Items Mod

Details

These changes are required in order to use:

  • Alien items
    • Sectoid Grenade, ThinMan Grenade, Muton Grenade, Cyberdisc Grenade, and Floater Grenade
  • ItemsIDs that do not have corresponding XGWeapon_<type> class definitions
    • These items will not apply any stats in the tactical game without these changes
    • For example, eItem_BEGIN_ALIEN_GRENADES, eItem_BEGIN_GRENADES, or eItem_PlaceholderGrenade0

Any perks set by any item will be reflected in the tactical game regardless of whether any hex changes made in this section are applied or not.

This package contains five distinct hex changes:

  1. Alter ItemType to return the local variable m_eType instead of default.m_eType
  2. Rewrite ApplyOverheatIncrement to set m_eType
  3. Alter ConvertTInventoryToSoldierLoadout to store the item ID instead of the class (for Backpack items only)
  4. Alter GetItem to return the class'XGWeapon_TargetingModule' for any ItemID with an undefined class
  5. Alter ApplyLoadout to retrieve+spawn the class for backpack items, then immediately set the ItemID

File Changes

These hex changes are applied to the XComGame.upk


ItemType

This change to XGItem.ItemType alters the function to return the current value of m_eType instead of the default value.

XGItem.ItemType
original: 04 02 E3 9B 00 00 04 3A E4 9B 00 00 53
new: 04 01 E3 9B 00 00 04 3A E4 9B 00 00 53

Decompiled Code

XGItem.ItemType

Original Code
static simulated function XGGameData.EItemType ItemType()
{
    return default.m_eType;
    //return ReturnValue;    
}

New Code
 
static simulated function XGGameData.EItemType ItemType()
{
    return m_eType;
    //return ReturnValue;    
}
 


ApplyOverheatIncrement

This function completely rewrites the XGWeapon.ApplyOverheatIncrement function to allow setting the class variable m_eType, defined in the parent class XGItem.

The m_eType variable is a protected variable, so it cannot be set from outside of the XGItem class or any child class descended from XGItem.

XGWeapon.ApplyOverheatIncrement
original: 58 B9 00 00 50 55 00 00 00 00 00 00 41 B9 00 00 00 00 00 00 00 00 00 00 43 B9 00 00 00 00 00 00 ED 00 00 00 A7 1C 00 00 C8 00 00 00 90 00 00 00 07 C5 00 1B 9A 36 00 00 00 00 00 00 2C 0B 16 0F 01 1D B9 00 00 FB 92 01 1D B9 00 00 00 42 B9 00 00 16 25 2C 64 16 07 C5 00 19 19 2E FE 2C 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 F0 2C 00 00 00 01 F0 2C 00 00 1F 00 BD 76 00 00 00 1B F1 0E 00 00 00 00 00 00 38 3A 1B 92 30 00 00 00 00 00 00 16 01 1D B9 00 00 16 1B C2 57 00 00 00 00 00 00 00 43 B9 00 00 16 04 0B 53
new: 58 B9 00 00 50 55 00 00 00 00 00 00 41 B9 00 00 00 00 00 00 00 00 00 00 43 B9 00 00 00 00 00 00 ED 00 00 00 A7 1C 00 00 98 00 00 00 90 00 00 00 0F 01 E3 9B 00 00 38 3D 00 42 B9 00 00 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 04 0B 53

Decompiled Code

XGWeapon.ApplyOverheatIncrement

Original Code
simulated function ApplyOverheatIncrement(XGUnit kUnit, int iAmount)
{
	// End:0xc5 Loop:False
	if(HasProperty(11))
	{
		iOverheatChance = Clamp(iOverheatChance + iAmount, 0, 100);
		// End:0xc5 Loop:False
		if(XComGameReplicationInfo(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kGameCore.CalcWeaponOverheated(GameplayType(), iOverheatChance))
		{
			Overheat(kUnit);
		}
	}
	//return;    
}

New Code
 
simulated function ApplyOverheatIncrement(XGUnit kUnit, int iAmount)
{
    m_eType = byte(iAmount); 
    //return;    
}

ConvertTInventoryToSoldierLoadout

This hex change alters the XGLoadoutMgr.ConvertTInventoryToSoldierLoadout by storing the ItemID in the Loadout.Backpack[] array instead of the class pointer.

This preserves the ItemID until the ApplyLoadout function so that the m_eType variable of the newly spawned copy of the appropriate class can be changed to the appropriate value.

XGLoadoutMgr.ConvertTInventoryToSoldierLoadout
original: 55 35 35 46 00 00 38 46 00 00 00 00 48 D7 A8 00 00 4F 00 13 58 B9 00 00 12 20 04 A7 00 00 30 00 FD A6 00 00 00 1B D1 32 00 00 00 00 00 00 1A 00 D6 A8 00 00 35 C5 0D 00 00 CA 0D 00 00 00 00 00 D8 A8 00 00 16 16
new: 55 35 35 46 00 00 38 46 00 00 00 00 48 D7 A8 00 00 4F 00 1A 00 D6 A8 00 00 35 C5 0D 00 00 CA 0D 00 00 00 00 00 D8 A8 00 00 16 0B 00 D6 A8 00 00 00 D6 A8 00 00 00 D6 A8 00 00 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B

Decompiled Code

XGLoadoutMgr.ConvertTInventoryToSoldierLoadout

Original Code
Loadout.Backpack.AddItem(class<XGWeapon>(class'XGItemLibrary'.static.GetItem(kInventory.arrSmallItems[I])));

New Code
 
Loadout.Backpack.AddItem(kInventory.arrSmallItems[I]);

GetItem

This hex change to XGItemLibrary.GetItem causes the function to return the class'XGWeapon_TargetingModule' if the ItemID passed is not defined.

This makes this class the prototype for any new Backpack item that does not have an existing class.


XGItemLibrary.GetItem
original: 13 A7 00 00 50 55 00 00 00 00 00 00 FC A6 00 00 00 00 00 00 00 00 00 00 FE A6 00 00 00 00 00 00 0B 00 00 00 20 01 00 00 39 00 00 00 25 00 00 00 07 1A 00 99 00 FE A6 00 00 36 02 FC A6 00 00 16 04 2A 04 10 00 FE A6 00 00 02 FC A6 00 00 04 3A FD A6 00 00 53
new: 13 A7 00 00 50 55 00 00 00 00 00 00 FC A6 00 00 00 00 00 00 00 00 00 00 FE A6 00 00 00 00 00 00 0B 00 00 00 20 01 00 00 35 00 00 00 25 00 00 00 04 10 45 77 10 00 FE A6 00 00 02 FC A6 00 00 2A 16 09 00 00 FE A6 00 00 02 00 2C 51 02 FC A6 00 00 0B 0B 0B 53

Decompiled Code

XGItemLibrary.GetItem

Original Code
static simulated function class<XGItem> GetItem(int iItem)
{
	// End:0x1a Loop:False
	if(iItem >= default.m_arrItems.Length)
	{
		return none;
	}
	return default.m_arrItems[iItem];
}

New Code
 
static simulated function class<XGItem> GetItem(int iItem)
{
    return default.m_arrItems[((default.m_arrItems[iItem] != none) ? iItem : 81)];                
}

ApplyLoadout

This hex changes alters XGLoadoutMgr.ApplyLoadout in the following ways:

  1. Assumes that the Loadout array contains an ItemID for Backpack items
  2. Calls XGItemLibrary to retrieve the class for the given item ID
  3. Spawns a copy of the retrieved class
  4. Calls the rewritten helper function GetOverheatIncrement to set the m_eType field of the newly spawned class

Fairly drastic restructuring of this function was required in order to fit these changes into the existing space.

Note that this function is distinct from the function XGUnit.ApplyLoadout

XGLoadoutMgr.ApplyLoadout
original: 0F 00 BA 7C 00 00 19 19 00 BE 7C 00 00 0A 00 56 94 00 00 00 1B C5 34 00 00 00 00 00 00 16 0A 00 40 AC 00 00 00 1B 95 33 00 00 00 00 00 00 16 07 F2 01 19 19 19 2E 64 2D 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 71 2D 00 00 00 01 71 2D 00 00 09 00 A3 9C 00 00 00 01 A3 9C 00 00 0A 00 A8 9F 00 00 00 2D 01 A8 9F 00 00 07 F2 01 82 81 19 01 E6 7B 00 00 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 18 21 00 19 1B 38 34 00 00 00 00 00 00 16 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 07 F2 01 82 82 2D 00 BD 7C 00 00 18 5F 00 77 19 2E 64 2D 00 00 2E FE 2C 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 69 2D 00 00 00 01 69 2D 00 00 2A 16 16 18 74 00 81 19 19 2E 64 2D 00 00 2E FE 2C 00 00 19 12 20 4F FE FF FF 0A 00 D8 F9 FF FF 00 1C F6 FB FF FF 16 09 00 98 F9 FF FF 00 01 98 F9 FF FF 09 00 69 2D 00 00 00 01 69 2D 00 00 0A 00 97 4C 00 00 00 2D 01 97 4C 00 00 16 16 04 25 07 08 02 99 00 BA 7C 00 00 2C 04 16 04 1D FF FF FF FF 0F 00 B9 7C 00 00 93 F9 2C 04 19 19 00 BE 7C 00 00 0A 00 56 94 00 00 00 1B C5 34 00 00 00 00 00 00 16 0A 00 87 AC 00 00 00 1B AD 33 00 00 00 00 00 00 16 16 00 BA 7C 00 00 16 07 39 03 82 82 19 01 E6 7B 00 00 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 18 23 00 81 19 1B 38 34 00 00 00 00 00 00 16 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 16 18 0D 00 97 00 BF 7C 00 00 25 16 16 0F 00 BB 7C 00 00 91 00 BF 7C 00 00 2C 05 16 07 1E 03 99 00 BF 7C 00 00 2C 32 16 A1 00 BB 7C 00 00 F9 2C 1E 90 19 19 01 E6 7B 00 00 0A 00 EB B2 00 00 00 1B 0A 34 00 00 00 00 00 00 16 09 00 DB 93 00 00 00 01 DB 93 00 00 2C 0F 16 16 16 A1 00 BB 7C 00 00 90 00 B9 7C 00 00 2C 0F 16 16 06 18 04 07 18 04 82 81 19 01 E6 7B 00 00 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 18 21 00 19 1B 38 34 00 00 00 00 00 00 16 0A 00 B5 32 00 00 00 1B DB 3D 00 00 00 00 00 00 16 16 0F 00 BB 7C 00 00 90 8F 19 19 1B 38 34 00 00 00 00 00 00 16 0A 00 EB B2 00 00 00 1B 0A 34 00 00 00 00 00 00 16 09 00 DC 93 00 00 00 01 DC 93 00 00 16 2C 0A 16 07 FD 03 82 9A 00 BA 7C 00 00 26 16 18 0B 00 2D 00 BD 7C 00 00 16 0F 00 BB 7C 00 00 8F 00 BF 7C 00 00 16 06 18 04 A1 00 BB 7C 00 00 90 00 B9 7C 00 00 1D E7 FF FF FF 16 16 04 FB 92 00 BF 7C 00 00 00 BB 7C 00 00 16 25 2C 64 16 04 3A BC 7C 00 00 53
new: 0F 00 BB 7C 00 00 25 07 31 00 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 0A 16 04 25 07 55 00 19 01 E8 BB 00 00 0A 00 4D B9 00 00 00 1B D6 3D 00 00 00 00 00 00 16 04 25 07 87 01 81 2D 00 BD 7C 00 00 16 07 94 00 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 08 16 0F 00 BB 7C 00 00 2C 19 07 C4 00 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 04 16 0F 00 BB 7C 00 00 2C 19 07 F4 00 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 02 16 0F 00 BB 7C 00 00 2C 32 07 24 01 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 05 16 0F 00 BB 7C 00 00 2C 22 07 54 01 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 06 16 0F 00 BB 7C 00 00 2C 22 07 84 01 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 07 16 0F 00 BB 7C 00 00 2C 22 06 A7 02 07 B7 01 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 08 16 0F 00 BB 7C 00 00 2C 11 07 E7 01 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 04 16 0F 00 BB 7C 00 00 2C 11 07 17 02 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 02 16 0F 00 BB 7C 00 00 2C 22 07 47 02 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 05 16 0F 00 BB 7C 00 00 2C 14 07 77 02 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 06 16 0F 00 BB 7C 00 00 2C 14 07 A7 02 19 01 E8 BB 00 00 0C 00 4F B9 00 00 00 1B 9A 36 00 00 00 00 00 00 2C 07 16 0F 00 BB 7C 00 00 2C 14 07 CF 02 9A 1B 1E 35 00 00 00 00 00 00 16 2C 11 16 0F 00 BB 7C 00 00 90 2C 02 00 BB 7C 00 00 16 07 F7 02 9A 1B 1E 35 00 00 00 00 00 00 16 2C 0C 16 0F 00 BB 7C 00 00 90 2C 01 00 BB 7C 00 00 16 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 04 00 BB 7C 00 00 53

Decompiled Code

XGLoadoutMgr.ApplyLoadout

Original Code
static function ApplyLoadout(XGUnit kUnit, TLoadout kLoad, bool bLoadFromCheckpoint)
{
	local XGInventoryItem kItem;
	local XGArmor kArmor;
	local XGLoadoutInstances kLoadoutInstances;
	local int I, J;

	kLoadoutInstances = class'Engine'.static.GetCurrentWorldInfo().Spawn(class'XGLoadoutInstances', kUnit.Owner);
	// End:0x173 Loop:False
	if(kLoad.Armor != none)
	{
		kArmor = class'Engine'.static.GetCurrentWorldInfo().Spawn(kLoad.Armor, kUnit.Owner);
		kArmor.Init();
		kArmor.PostInit();
		kLoadoutInstances.m_kArmor = kArmor;
	}
	kLoadoutInstances.m_iNumItems = 0;
	kLoadoutInstances.m_iNumBackpackItems = 0;
	I = 0;
	J0x1be:

	// End:0x47f Loop:True
	if(I < 21)
	{
		// End:0x34b Loop:False
		if(I == 14)
		{
			J = 0;
			J0x1e9:

			// End:0x348 Loop:True
			if(J < kLoad.Backpack.Length)
			{
				// End:0x33a Loop:False
				if(kLoad.Backpack[J] != none)
				{
					kItem = class'Engine'.static.GetCurrentWorldInfo().Spawn(kLoad.Backpack[J], kUnit.Owner);
					kItem.Init();
					kLoadoutInstances.m_aBackpackItems[J] = kItem;
					++ kLoadoutInstances.m_iNumBackpackItems;
				}
				++ J;
				// This is an implied JumpToken; Continue!
				goto J0x1e9;
			}
		}
		// End:0x471
		else
		{
			// End:0x471 Loop:False
			if(kLoad.Items[I] != none)
			{
				kItem = class'Engine'.static.GetCurrentWorldInfo().Spawn(kLoad.Items[I], kUnit.Owner);
				kItem.Init();
				kLoadoutInstances.m_aItems[I] = kItem;
				++ kLoadoutInstances.m_iNumItems;
			}
		}
		++ I;
		// This is an implied JumpToken; Continue!
		goto J0x1be;
	}
	kUnit.ApplyLoadout(kLoadoutInstances, bLoadFromCheckpoint);
}

New Code
 
static function ApplyLoadout(XGUnit kUnit, TLoadout kLoad, bool bLoadFromCheckpoint)
{
    local XGInventoryItem kItem;
    local XGArmor kArmor;
    local XGLoadoutInstances kLoadoutInstances;
    local int I, J;

    kLoadoutInstances = class'Engine'.static.GetCurrentWorldInfo().Spawn(class'XGLoadoutInstances', kUnit.Owner);
    kArmor = class'Engine'.static.GetCurrentWorldInfo().Spawn(kLoad.Armor, kUnit.Owner);
    kArmor.Init();
    kArmor.PostInit();
    kLoadoutInstances.m_kArmor = kArmor;
    kLoadoutInstances.m_iNumItems = 0;
    kLoadoutInstances.m_iNumBackpackItems = 0;
    I = 0;
    J0x19C:
    // End:0x473 [Loop If]
    if(I < 21)
    {
        // End:0x33F
        if(I < kLoad.Backpack.Length)
        {
            kItem = class'Engine'.static.GetCurrentWorldInfo().Spawn(class<XGWeapon>(class'XGItemLibrary'.static.GetItem(kLoad.Backpack[I])), kUnit.Owner);
            kItem.ApplyOverheatIncrement(none, kLoad.Backpack[I]);
            kItem.Init();
            kLoadoutInstances.m_aBackpackItems[I] = kItem;
            ++ kLoadoutInstances.m_iNumBackpackItems;
        }
        // End:0x465
        if(kLoad.Items[I] != none)
        {
            kItem = class'Engine'.static.GetCurrentWorldInfo().Spawn(kLoad.Items[I], kUnit.Owner);
            kItem.Init();
            kLoadoutInstances.m_aItems[I] = kItem;
            ++ kLoadoutInstances.m_iNumItems;
        }
        ++ I;
        // [Loop Continue]
        goto J0x19C;
    }
    kUnit.ApplyLoadout(kLoadoutInstances, bLoadFromCheckpoint);                                
    //return;    
}

References

Referred to by this article:

That refer to this article:

  • <none>