diff --git a/addons/source-python/data/source-python/entities/csgo/CBasePlayer.ini b/addons/source-python/data/source-python/entities/csgo/CBasePlayer.ini index 48eea053a..b07f976a6 100755 --- a/addons/source-python/data/source-python/entities/csgo/CBasePlayer.ini +++ b/addons/source-python/data/source-python/entities/csgo/CBasePlayer.ini @@ -58,8 +58,16 @@ srv_check = False offset_windows = 372 +# TODO: Remove when outdated. [instance_attribute] + [[assists]] + offset_windows = 4024 + offset_linux = 4048 + type = INT + + +[based_attribute] # from memory import alloc # from players.entity import Player @@ -74,8 +82,8 @@ srv_check = False # break # print('Offset of Player.assists is:', offset) [[assists]] - offset_windows = 4024 - offset_linux = 4048 + base = m_iFrags + offset = 4 type = INT diff --git a/addons/source-python/data/source-python/entities/csgo/CCSPlayer.ini b/addons/source-python/data/source-python/entities/csgo/CCSPlayer.ini index 90dae8df8..f9454fa3d 100755 --- a/addons/source-python/data/source-python/entities/csgo/CCSPlayer.ini +++ b/addons/source-python/data/source-python/entities/csgo/CCSPlayer.ini @@ -57,6 +57,7 @@ srv_check = False on_rescue_zone_touch = OnRescueZoneTouch +# TODO: Remove when outdated. [instance_attribute] [[mvps]] @@ -75,6 +76,24 @@ srv_check = False type = STRING_ARRAY +[based_attribute] + + [[mvps]] + base = m_bIsHoldingLookAtWeapon + offset = 11 + type = INT + + [[score]] + base = m_bIsHoldingLookAtWeapon + offset = 51 + type = INT + + [[clan_tag]] + base = m_flGroundAccelLinearFracLastTime + offset = 140 + type = STRING_ARRAY + + [property] stamina = cslocaldata.m_flStamina diff --git a/addons/source-python/data/source-python/entities/orangebox/cstrike/CCSPlayer.ini b/addons/source-python/data/source-python/entities/orangebox/cstrike/CCSPlayer.ini index 233f4df1c..83d0e60cf 100644 --- a/addons/source-python/data/source-python/entities/orangebox/cstrike/CCSPlayer.ini +++ b/addons/source-python/data/source-python/entities/orangebox/cstrike/CCSPlayer.ini @@ -50,6 +50,7 @@ on_rescue_zone_touch = OnRescueZoneTouch +# TODO: Remove when outdated. [instance_attribute] [[mvps]] @@ -63,6 +64,19 @@ type = STRING_ARRAY +[based_attribute] + + [[mvps]] + base = cslocaldata.m_bPlayerDominatingMe.065 + offset = 4 + type = INT + + [[clan_tag]] + base = m_flFlashDuration + offset = -28 + type = STRING_ARRAY + + [property] stamina = cslocaldata.m_flStamina diff --git a/addons/source-python/packages/source-python/entities/classes.py b/addons/source-python/packages/source-python/entities/classes.py index 3ce665fc7..9ee55c82e 100644 --- a/addons/source-python/packages/source-python/entities/classes.py +++ b/addons/source-python/packages/source-python/entities/classes.py @@ -37,6 +37,7 @@ from memory import DataType from memory import get_object_pointer from memory import make_object +from memory.helpers import Key from memory.helpers import Type from memory.manager import CustomType from memory.manager import TypeManager @@ -332,6 +333,38 @@ def _get_server_class(self, class_name, datamap): instance, name, offset, property_contents, _supported_descriptor_types[desc.type]) + # Loop through all based attributes + for name, data in manager_contents.get('based_attribute', {}).items(): + + # Resolve the method to register this attribute + method = getattr(self, data.get('method', 'instance_attribute')) + + # Resolve the offset of this attribute + offset = Key.as_int( + self, + data.get('offset_' + PLATFORM, data.get('offset', 0)) + ) + + # Resolve the base offset of this attribute + base = data.get('base_' + PLATFORM, data.get('base')) + try: + offset += instance.properties[base].offset + except KeyError: + raise NameError( + f'"{base}" is not a valid property ' + + f'for attribute "{class_name}.{name}".' + ) + + # Generate the attribute + attribute = method( + Key.as_attribute_type(self, data['type']), + offset, + data.get('doc') + ) + + # Assign the attribute to the instance + setattr(instance, name, attribute) + # Get a list of all properties for the current server class properties = list(instance.properties) @@ -485,7 +518,8 @@ def _add_property( value = self.instance_attribute(prop_type, offset) # Add the property to the properties dictionary - instance.properties[name] = EntityProperty(value, prop_type, networked) + instance.properties[name] = EntityProperty( + value, prop_type, networked, offset) # Is the property not a named property? if name not in contents: diff --git a/addons/source-python/packages/source-python/entities/datamaps.py b/addons/source-python/packages/source-python/entities/datamaps.py index f1a88b2ca..ec08df4c1 100644 --- a/addons/source-python/packages/source-python/entities/datamaps.py +++ b/addons/source-python/packages/source-python/entities/datamaps.py @@ -103,11 +103,12 @@ class TypeDescriptionFlags(IntFlag): class EntityProperty(object): """Class used to store property information for verification.""" - def __init__(self, instance, prop_type, networked): + def __init__(self, instance, prop_type, networked, offset): """Store the base attributes on instantiation.""" self._instance = instance self._prop_type = prop_type self._networked = networked + self._offset = offset @property def instance(self): @@ -123,3 +124,9 @@ def prop_type(self): def networked(self): """Return whether the property is networked.""" return self._networked + + @property + def offset(self): + """Returns the offset of the property.""" + return self._offset +