"Games"
{
	"tf"
	{
		"Addresses"
		{
			"g_aConditionNames"
			{
				"signature"		"GetTFConditionName()"
				"linux"
				{
					"read"		"16"
				}
				"windows"
				{
					"read"		"20"
				}
			}
			"&TF_COND_LAST"
			{
				// GetTFConditionName() uses a different value for comparisons on each platform,
				// so we can't just reuse that function
				"signature"		"CTFPlayerShared::RemoveAllCond()"
				"linux"
				{
					"offset"	"37"
				}
				"windows"
				{
					"offset"	"147"
				}
			}
			"offsetof(CTFPlayer::m_aObjects)"
			{
				"linux"
				{
					"signature"		"CTFPlayer::GetObject()"
					"offset"		"18"
				}
				"windows"
				{
					"signature"		"CTFPlayer::AddObject()"
					"offset"		"41"
				}
			}
			"offsetof(CTFPlayer::m_flRespawnTimeOverride)"
			{
				"signature"		"CTFPlayer::IsReadyToSpawn()"
				"linux"
				{
					"offset"	"81"
				}
				"windows"
				{
					"offset"	"137"
				}
			}
		}
		"Keys"
		{
			// space-separated set of hex values corresponding to damage types that are 'damage over time'
			// the game inlines this functionality so we'll have to implement this ourselves
			// 0x03 = TF_CUSTOM_BURNING
			// 0x08 = TF_CUSTOM_BURNING_FLARE
			// 0x11 = TF_CUSTOM_BURNING_ARROW
			// 0x22 = TF_CUSTOM_BLEEDING
			"DOTDamageTypes"		"03 08 11 22"
		}
		"Offsets"
		{
			// virtual offsets
			"CBaseCombatCharacter::Weapon_Switch()"
			{
				"windows"	"274"
				"linux"		"275"
			}
			"CBaseCombatCharacter::Weapon_ShootPosition()"
			{
				"windows"	"275"
				"linux"		"276"
			}
			"CBaseCombatWeapon::GetSlot()"
			{
				"windows"	"333"
				"linux"		"339"
			}
			"CBaseEntity::GetMaxHealth()"
			{
				"windows"	"122"
				"linux"		"123"
			}
			"CBaseEntity::IsBaseCombatWeapon()"
			{
				"windows"	"91"
				"linux"		"92"
			}
			"CBaseEntity::IsWearable()"
			{
				"windows"	"92"
				"linux"		"93"
				"mac"		"93"
			}
			"CBaseEntity::TakeHealth()"
			{
				"windows"	"66"
				"linux"		"67"
			}
			"CTFWeaponBase::CanAttack()"
			{
				"windows"	"425"
				"linux"		"432"
			}
			"CTFWeaponBase::GetMaxClip1()"
			{
				"windows"	"324"
				"linux"		"330"
			}
			"CTFWeaponBase::GetWeaponID()"
			{
				"windows"	"380"
				"linux"		"386"
			}
			"CTFPlayer::EquipWearable()"
			{
				"windows"	"438"
				"linux"		"439"
				"mac"		"439"
			}
			
			// member offsets
			// any resemblance to the names present in official game code is purely coincidental
			// (this excludes names visible via sendprops and symbols, of course)
			"CTFPlayer::m_hMyWearables"
			{
				// CUtlVector<EHandle>, currently offsetof(m_flMaxSpeed) - 0x14
				"linux"		"3848"
				"windows"	"3824"
			}
			"CTFPlayer::m_flLastDamageTime"
			{
				"linux"		"8832"
				"windows"	"8828"
			}
			"CTFPlayerShared::m_pOuter"
			{
				// checked in CTFPlayerShared::HasDemoShieldEquipped()
				"linux"		"396"
				"windows"	"396"
			}
			"CTFPlayerShared::m_ConditionData"
			{
				"linux"		"8"
				"windows"	"8"
			}
			"CTFPlayerShared::m_flBurnDuration"
			{
				// after unique xref to string "mult_wpn_burntime"
				"linux"		"516"
				"windows"	"516"
			}
			"CTFPlayerShared::m_BleedList"
			{
				// in MakeBleed
				"linux"		"520"
				"windows"	"520"
			}
			
			"TFCondInfo_t::m_flDuration"
			{
				"linux"		"8"
				"windows"	"8"
			}
			"TFCondInfo_t::m_hProvider"
			{
				"linux"		"12"
				"windows"	"12"
			}
			
			"sizeof(TFCondInfo_t)"
			{
				"linux"		"20"
				"windows"	"20"
			}
			
			"BleedStruct_t::m_hAttacker"
			{
				"linux"		"0"
				"windows"	"0"
			}
			"BleedStruct_t::m_hWeapon"
			{
				"linux"		"4"
				"windows"	"4"
			}
			"BleedStruct_t::m_flNextTickTime"
			{
				"linux"		"8"
				"windows"	"8"
			}
			"BleedStruct_t::m_flExpireTime"
			{
				"linux"		"12"
				"windows"	"12"
			}
			"BleedStruct_t::m_nDamage"
			{
				"linux"		"16"
				"windows"	"16"
			}
			"BleedStruct_t::m_bPermanent"
			{
				"linux"		"20"
				"windows"	"20"
			}
			"BleedStruct_t::m_nCustomDamageType"
			{
				"linux"		"24"
				"windows"	"24"
			}
			"sizeof(BleedStruct_t)"
			{
				"linux"		"28"
				"windows"	"28"
			}
			
			"CEconWearable::m_bAlwaysValid"
			{
				// CEconWearable ctor
				"linux"		"1476"
				"windows"	"1464"
			}
		}
		"Signatures"
		{
			"CTFPlayerShared::IsImmuneToPushback()"
			{
				// contains unique ref to string "spunup_push_force_immunity"
				"library"	"server"
				"linux"		"@_ZNK15CTFPlayerShared18IsImmuneToPushbackEv"
				"windows"	"\x55\x8B\xEC\x51\x56\x8B\xF1\x57\x6A\x1C"
			}
			"CTFPlayerShared::Burn()"
			{
				// contains unique ref to string "afterburn_immunity"
				"library"	"server"
				"linux"		"@_ZN15CTFPlayerShared4BurnEP9CTFPlayerP13CTFWeaponBasef"
				"windows"	"\x55\x8B\xEC\x83\xEC\x08\x56\x8B\xF1\x8B\x8E\x2A\x01\x00\x00\x8B\x01"
			}
			"CTFPlayer::AddObject()"
			{
				// we only use this to get offsetof(CTFPlayer::m_aObjects) on Windows
				"library"		"server"
				"windows"		"\x55\x8B\xEC\x56\x8B\x75\x08\x57\x8B\xF9\x85\xF6\x74\x2A\x8B\x06\x8B\xCE\xFF\x50\x08\x8B\x00\x89\x45\x08\xEB\x2A\xC7\x45\x08\xFF\xFF\xFF\xFF\x8D\x45\x08\x50\x8D\x8F\xB0\x22\x00\x00"
			}
			"CTFPlayer::GetEntityForLoadoutSlot()"
			{
				// called a few blocks after function with unique x-ref string "enable_misc2_noisemaker"
				"library"	"server"
				"windows"	"\x55\x8B\xEC\x51\x53\x8B\x5D\x2A\x57\x8B\xF9\x89\x7D\x2A\x83\xFB\x07\x74\x2A\x83\xFB\x08\x74\x2A\x83\xFB\x09\x74\x2A\x83\xFB\x0A\x74\x2A"
				"linux"		"@_ZN9CTFPlayer23GetEntityForLoadoutSlotEib"
				"mac"		"@_ZN9CTFPlayer23GetEntityForLoadoutSlotEib"
			}
			"CTFPlayer::GetMaxAmmo()"
			{
				"library"		"server"
				"linux"			"@_ZN9CTFPlayer10GetMaxAmmoEii"
				"windows"		"\x55\x8B\xEC\x8B\x45\x0C\x56\x57\x8B\xF9\x83\xF8\xFF"
			}
			"CTFPlayer::TeamFortress_SetSpeed()"
			{
				// function is x-ref to CTFPlayer::TeamFortress_CalculateMaxSpeed
				"library"		"server"
				"linux"			"@_ZN9CTFPlayer21TeamFortress_SetSpeedEv"
				"windows"		"\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\xEC\x1C\x53"
			}
			"CTFPlayer::GetObject()"
			{
				// we only use this to get offsetof(CTFPlayer::m_aObjects) on Linux
				"library"	"server"
				"linux"		"@_ZNK9CTFPlayer9GetObjectEi"
			}
			"CTFPlayer::IsReadyToSpawn()"
			{
				// Windows signature can be found with a bytescan of "83 BE ?? ?? 00 00 03 5E"
				// (conditional setter at the end of the function)
				// we only use this to get offsetof(CTFPlayer::m_flRespawnTimeOverride)
				"library"	"server"
				"linux"		"@_ZN9CTFPlayer14IsReadyToSpawnEv"
				"windows"	"\x56\x8B\xF1\x80\xBE\x2A\x2A\x00\x00\x00\x74\x04\x32\xC0\x5E\xC3\x8B\x2A\x2A\x2A\x00\x00"
			}
			"CTFPlayerShared::GetMaxBuffedHealth()"
			{
				// unique xref to call containing unique xref string "add_maxhealth"
				"library"		"server"
				"linux"			"@_ZN15CTFPlayerShared18GetMaxBuffedHealthEbb"
				"windows"		"\x55\x8B\xEC\x83\xEC\x08\x56\x8B\xF1\x57\x8B\x8E\x2A\x01\x00\x00"
			}
			"CTFPlayerShared::MakeBleed()"
			{
				// copied from sm-tf2.games
				"library"		"server"
				"linux"			"@_ZN15CTFPlayerShared9MakeBleedEP9CTFPlayerP13CTFWeaponBasefibi"
				"windows"		"\x55\x8B\xEC\x83\xEC\x2C\x57\x8B\xF9\x89\x7D\xF0"
			}
			"CTFPlayerShared::RemoveAllCond()"
			{
				// first non-virtual call after semi-unique xref to "Player.Spawn"
				"library"		"server"
				"linux"			"@_ZN15CTFPlayerShared13RemoveAllCondEv"
				"windows"		"\x55\x8B\xEC\x51\x53\x56\x57\x8B\xF9\x8D\x8F\xE0\x00\x00\x00"
			}
			"GetTFConditionName()"
			{
				"library"		"server"
				"linux"			"@_Z18GetTFConditionName7ETFCond"
				"windows"		"\x55\x8B\xEC\x8B\x45\x08\x3D\x2A\x00\x00\x00\x73\x0D"
			}
			"PointInRespawnRoom()"
			{
				"library"		"server"
				"linux"			"@_Z18PointInRespawnRoomPK11CBaseEntityRK6Vectorb"
				"windows"		"\x55\x8B\xEC\x53\x33\xDB\x56\x57"
			}
		}
	}
}
