def _pre_send_user_message(args): message_index = args[2] user_message_hooks = HookUserMessage.hooks[message_index] protobuf_user_message_hooks = HookProtobufUserMessage.hooks[message_index] # No need to do anything behind this if no listener is registered if not user_message_hooks and not protobuf_user_message_hooks: return # Replace original recipients filter tmp_recipients = make_object(BaseRecipientFilter, args[1]) _recipients.update(*tuple(tmp_recipients), clear=True) args[1] = _recipients buffer = make_object(ProtobufMessage, args[3]) protobuf_user_message_hooks.notify(_recipients, buffer) # No need to do anything behind this if no listener is registered if not user_message_hooks: return try: impl = get_user_message_impl(message_index) except NotImplementedError: return data = impl.read(buffer) user_message_hooks.notify(_recipients, data) # Update buffer if data has been changed if data.has_been_changed(): buffer.clear() impl.write(buffer, data)
def _pre_fire_output(args): """Called when an output is about to be fired.""" if not on_entity_output_listener_manager: return # Windows is a bit weird: the function takes 4 additional arguments... if PLATFORM == 'windows': args = (args[0],) + tuple(args)[5:] caller_ptr = args[3] if not caller_ptr: # If we don't know the caller, we won't be able to retrieve the # output name return caller = memory.make_object(BaseEntity, caller_ptr) output_name = find_output_name(caller, args[0]) if output_name is None: return None if caller.is_networked(): caller = memory.make_object(Entity, caller_ptr) value_ptr = args[1] value = (value_ptr or None) and memory.make_object(Variant, value_ptr) activator_ptr = args[2] activator = ((activator_ptr or None) and memory.make_object( BaseEntity, activator_ptr)) if activator is not None and activator.is_networked(): activator = memory.make_object(Entity, activator_ptr) delay = args[4] on_entity_output_listener_manager.notify( output_name, activator, caller, value, delay)
def pre_bump_weapon(self, stack_data): """Switch the player's team if they are a CT picking up the bomb.""" if make_object(Entity, stack_data[1]).classname != 'weapon_c4': return self.bump_player = make_object(Entity, stack_data[0]) if self.bump_player.team == 3: self.bump_player.team_index = 2 else: self.bump_player = None
def on_take_damage(args): info = make_object(TakeDamageInfo, args[1]) if info.type & DamageTypes.HEADSHOT: info.damage *= HEADSHOT_DMG_MULTIPLIER else: victim = make_object(Player, args[0]) if victim.hitgroup in (HitGroup.CHEST, HitGroup.STOMACH): info.damage *= CHEST_DMG_MULTIPLIER else: info.damage *= BASE_DMG_MULTIPLIER
def _callback(stack_data, *args): """Called when the hooked method is called.""" # Get the temp entity instance... temp_entity = make_object(TempEntity, stack_data[0]) # Are we looking for that temp entity? if temp_entity.name == self.name: # Call the registered callback... return callback(temp_entity, make_object( RecipientFilter, stack_data[1]))
def _pre_on_take_damage(args): """ Hooked to a function that is fired any time an entity takes damage. """ player_index = index_from_pointer(args[0]) info = make_object(TakeDamageInfo, args[1]) defender = Player(player_index) attacker = None if not info.attacker else Player(info.attacker) eargs = { 'attacker': attacker, 'defender': defender, 'info': info, 'weapon': Weapon( index_from_inthandle(attacker.active_weapon) ).class_name if attacker and attacker.active_weapon != -1 else '' } if not player_index == info.attacker: defender.hero.execute_skills('player_pre_defend', **eargs) ''' Added exception to check whether world caused damage. ''' if attacker: attacker.hero.execute_skills('player_pre_attack', **eargs)
def _pre_detonate(args): entity = make_object(Entity, args[0]) if entity.index not in _filtered_indexes: return None dissolve(entity) return True
def _pre_on_take_damage(args): info = make_object(TakeDamageInfo, args[1]) entity = Entity(info.attacker) if info.attacker else None if entity is not None and entity.is_player(): attacker = wcgo.player.Player(entity.index) else: attacker = None victim = wcgo.player.Player(index_from_pointer(args[0])) eargs = { 'attacker': attacker, 'victim': victim, 'info': info, } # Adds the weapon argument dependent on scenario if attacker is not None and attacker.active_weapon != -1: eargs['weapon'] = Weapon(index_from_inthandle(attacker.active_weapon)) else: eargs['weapon'] = None if attacker is None or attacker.userid == victim.userid: victim.hero.execute_skills('player_pre_self_injury', player=victim, **eargs) return if not (attacker.steamid == 'BOT' and attacker.hero is None): attacker.hero.execute_skills('player_pre_attack', player=attacker, **eargs) if not (victim.steamid == 'BOT' and victim.hero is None): victim.hero.execute_skills('player_pre_victim', player=victim, **eargs)
def convert(self, name, ptr): """Convert the pointer. Tries to convert a pointer in the following order: Attempts to convert the pointer... 1. to a custom type 2. to a exposed type 3. to a function typedef 4. by using a converter """ cls = self.get_class(name) if cls is not None: # Use the class to convert the pointer return make_object(cls, ptr) # No class was found. Maybe we have luck with a function typedef converter = self.function_typedefs.get(name, None) # Is there no function typedef? if converter is None: converter = self.converters.get(name, None) # Is there no converter? if converter is None: raise NameError( 'No class, function typedef or ' + 'converter found for "{0}".'.format(name)) # Yay, we found a converter or function typedef! return converter(ptr)
def base_client(self): """Return the player's base client instance. :rtype: BaseClient """ from players import BaseClient return make_object(BaseClient, get_object_pointer(self.client) - 4)
def _pre_damage_call_events(stack_data): take_damage_info = make_object(TakeDamageInfo, stack_data[1]) if not take_damage_info.attacker: return entity = Entity(take_damage_info.attacker) attacker = players[entity.index] if entity.is_player() else None victim = players[index_from_pointer(stack_data[0])] event_args = { 'attacker': attacker, 'victim': victim, 'take_damage_info': take_damage_info, } if attacker: if victim.team == attacker.team: attacker.hero.call_events('player_pre_teammate_attack', player=attacker, **event_args) victim.hero.call_events('player_pre_teammate_victim', player=victim, **event_args) return attacker.hero.call_events('player_pre_attack', player=attacker, **event_args) victim.hero.call_events('player_pre_victim', player=victim, **event_args) if victim.health <= take_damage_info.damage: attacker.hero.call_events('player_pre_death', player=victim, **event_args)
def on_take_damage(args): protected_player = protected_player_manager[index_from_pointer(args[0])] if protected_player.dead: return info = make_object(TakeDamageInfo, args[1]) return protected_player._hurt(info)
def _set_property(self, name, prop_type, value): """Verify the type and set the property.""" # Loop through all entity server classes for server_class in self.server_classes: # Is the name a member of the current server class? if name not in server_class.properties: continue # Is the type the correct type? if prop_type != server_class.properties[name].prop_type: raise TypeError('Property "{0}" is of type {1} not {2}'.format( name, server_class.properties[name].prop_type, prop_type)) # Set the property for the entity setattr(make_object( server_class._properties, self.pointer), name, value) # Is the property networked? if server_class.properties[name].networked: # Notify the change of state self.edict.state_changed() # No need to go further return # Raise an error if the property name was not found raise ValueError( 'Property "{0}" not found for entity type "{1}"'.format( name, self.classname))
def __iter__(self): """Iterate over all WeaponInfo instances.""" # Loop through all indexes... for index in range(_weapon_scripts._length): # Yield the WeaponInfo instance at the current slot... yield make_object(WeaponInfo, _weapon_scripts._find(index))
def give_level_weapon(self): """Give the player the weapon of their current level.""" if self.has_level_weapon(): return self.get_weapon(self.level_weapon_classname) return make_object( Weapon, self.give_named_item(self.level_weapon_classname) )
def _pre_take_damage(stack_data): """Store the information for later use.""" take_damage_info = make_object(TakeDamageInfo, stack_data[1]) attacker = Entity(take_damage_info.attacker) if attacker.classname != 'player': return victim = make_object(Player, stack_data[0]) if victim.health > take_damage_info.damage: return KILLER_DICTIONARY[victim.userid] = { 'attacker': userid_from_index(attacker.index), 'end': Vector(*take_damage_info.position), 'projectile': attacker.index != take_damage_info.inflictor, 'color': _team_colors[victim.team], }
def _get_property(self, prop_name, prop_type): """Return the value of the given property name. :param str prop_name: The name of the property. :param SendPropType prop_type: The type of the property. """ # Is the given property not valid? if prop_name not in self.template.properties: # Raise an exception... raise NameError( '"{}" is not a valid property for temp entity "{}".'.format( prop_name, self.name)) # Get the property data... prop, offset, type_name = self.template.properties[prop_name] # Are the prop types matching? if prop.type != prop_type: # Raise an exception... raise TypeError('"{}" is not of type "{}".'.format( prop_name, prop_type)) # Is the property an array? if prop_type == SendPropType.ARRAY: # Return an array instance... return Array(manager, False, type_name, get_object_pointer( self) + offset, prop.length) # Is the given type not supported? if prop_type not in _supported_property_types: # Raise an exception... raise TypeError('"{}" is not supported.'.format(prop_type)) # Is the type native? if Type.is_native(type_name): # Return the value... return getattr( get_object_pointer(self), 'get_' + type_name)(offset) # Otherwise else: # Make the object and return it... return make_object( manager.get_class(type_name), get_object_pointer(self) + offset) # Raise an exception... raise ValueError('Unable to get the value of "{}".'.format(prop_name))
def pre_run_command(args): player = player_manager[make_object(Player, args[0]).index] user_cmd = make_object(UserCmd, args[1]) if not (user_cmd.buttons & PlayerButtons.SCORE and user_cmd.buttons & PlayerButtons.USE): return if get_mine_denial_reason(player) is not None: return trace = player.player.get_trace_ray() distance = (trace.end_position - player.player.origin).length if distance > config_manager['plant_distance']: return use_mine(player, trace.end_position, trace.plane.normal)
def _on_weapon_purchase(args): """Return whether the player is allowed to purchase the weapon.""" # TODO: # In CS:GO it seems like the weapon isn't passed as a string anymore. # Instead it's rather a pointer that might be NULL. If it's not NULL, the # function sets it to some value: #if ( a3 ) # *(_DWORD *)a3 = v16; return weapon_restriction_manager.on_player_purchasing_weapon( make_object(Player, args[0]), args[1 if SOURCE_ENGINE != 'csgo' else 2])
def _pre_take_damage(stack_data): """Change the victim's team if they are on the attacker's team.""" take_damage_info = make_object(TakeDamageInfo, stack_data[1]) attacker = Entity(take_damage_info.attacker) if attacker.classname != 'player': return victim = make_object(Entity, stack_data[0]) if victim.team != attacker.team: return address = stack_data.registers.esp.address.address if address in _take_damage_dict: return _take_damage_dict[address] = (victim.index, victim.team) # Change the player's team by using the m_iTeamNum property victim.team = 5 - victim.team
def _pre_bump_weapon(args): """Switch the player's team if they are a CT picking up the bomb.""" global _bump_player if edict_from_pointer(args[1]).classname != 'weapon_c4': return _bump_player = make_object(Player, args[0]) if _bump_player.team == 3: Entity(_bump_player.index).team = 2 else: _bump_player = None
def pre_send_user_message(args): if args[2] != say_text2_index: return recipient_filter = make_object(RecipientFilter, args[1]) if is_hltv_message(recipient_filter): return buffer = make_object(ProtobufMessage, args[3]) msg_name = buffer.get_string('msg_name') if msg_name in ("Cstrike_Chat_AllDead", "Cstrike_Chat_AllSpec"): recipient_filter.add_all_players() elif msg_name == "Cstrike_Chat_T_Dead": recipient_filter.update(PlayerIter('t')) elif msg_name == "Cstrike_Chat_CT_Dead": recipient_filter.update(PlayerIter('ct'))
def on_pre_drop_weapon(stack_data): """Remove the droppped weapon after about two seconds.""" # Get a Player object for the first stack_data item player = make_object(Player, stack_data[0]) # Get the player's active weapon active_weapon = player.get_active_weapon() # Remove the weapon after two seconds, if it is valid if active_weapon is not None: player.delay(2.0, remove_weapon, (player.get_active_weapon().index,), cancel_on_level_end=True)
def _get_input(target, input_name): """Return input function based on target and input name.""" for server_class in server_classes.get_entity_server_classes(target): if input_name in server_class.inputs: return getattr( make_object( server_class._inputs, target.pointer ), input_name ) return None
def stage_mapgame_equip_weapons(self): weapon_classname = self._settings['weapons'][0] for player in self._players_all: equipment_player = saved_player_manager[player.index] equipment_player.save_weapons() equipment_player.infinite_weapons.clear() weapon = make_object( Weapon, self.guard.give_named_item(weapon_classname)) weapon.clip = 0 weapon.ammo = 0 weapon = make_object( Weapon, self.prisoner.give_named_item(weapon_classname)) weapon.clip = 1 weapon.ammo = 0 register_weapon_drop_filter(self._weapon_drop_filter) register_weapon_pickup_filter(self._weapon_pickup_filter)
def on_pre_bump_weapon(stack_data): """Block bumping into another flashbang, if the player already owns one.""" # Get a Player object from the first stack_data item player = make_object(Player, stack_data[0]) # Get a Weapon object from the second stack_data item weapon = make_object(Weapon, stack_data[1]) # Block bumping into the weapon and remove it later, if it is not a flashbang or a High Explosive grenade if weapon.classname != 'weapon_flashbang': if (player.userid, weapon.classname) not in player_rewards_list: weapon.delay(2.0, remove_weapon, (weapon.index,), cancel_on_level_end=True) return False weapon.delay(0.2, handle_weapon_reward_properties, (weapon,)) # Block bumping into the weapon and remove it later, if the player is currently using the Admin menu if player.userid in admin_menu.users: weapon.delay(2.0, remove_weapon, (weapon.index,), cancel_on_level_end=True) return False
def pre_run_command(args): player = make_object(Player, args[0]) # Is player dead? if player.dead: return # Is player on ladder? if player.move_type & MoveType.LADDER: return # Is player in water deep enough? if player.get_property_uchar('m_nWaterLevel') > 1: return # Is player already on ground? if player.flags & PlayerStates.ONGROUND: return user_cmd = make_object(UserCmd, args[1]) user_cmd.buttons &= ~PlayerButtons.JUMP
def _pre_bump_weapon(stack_data): """Damage player or give extra if bump is from thrown weapon.""" weapon = make_object(Entity, stack_data[1]) if weapon.classname not in _melee_weapons: return index = weapon.index if index not in _throwers: return if index in _marked_for_removal: return player = make_object(Player, stack_data[0]) asleep = weapon.physics_object.asleep attacker_userid = _throwers[index] if attacker_userid == player.userid and not asleep: return weapon.delay(0, weapon.remove) _marked_for_removal.add(weapon.index) Delay(0, _marked_for_removal.remove, (weapon.index, )) if not asleep: player.take_damage( damage=int(melee_damage), # TODO: verify damage type damage_type=DamageTypes.SLASH, attacker_index=index_from_userid(attacker_userid), weapon_index=weapon.index, # TODO: determine how to find hitgroup hitgroup=HitGroup.CHEST, ) return if not bool(allow_pickup): return TextMsg(MESSAGE_STRINGS['Gained']).send(player.index) _available_count[player.userid] += 1
def _pre_fire_output(args): """Called when an output is about to be fired.""" if not on_entity_output_listener_manager: return # Windows is a bit weird: the function takes 4 additional arguments... if PLATFORM == 'windows': args = (args[0], ) + tuple(args)[5:] caller_ptr = args[3] if not caller_ptr: # If we don't know the caller, we won't be able to retrieve the # output name return # Done here to fix cyclic import... from entities.entity import BaseEntity caller = make_object(BaseEntity, caller_ptr) output_name = find_output_name(caller, args[0]) if output_name is None: return None # Done here to fix cyclic import... from entities.entity import Entity if caller.is_networked(): caller = make_object(Entity, caller_ptr) value_ptr = args[1] value = (value_ptr or None) and make_object(Variant, value_ptr) activator_ptr = args[2] activator = ((activator_ptr or None) and make_object(BaseEntity, activator_ptr)) if activator is not None and activator.is_networked(): activator = make_object(Entity, activator_ptr) delay = args[4] on_entity_output_listener_manager.notify(output_name, activator, caller, value, delay)
def _pre_user_message_begin(args): try: # Replace original recipients filter tmp_recipients = make_object(BaseRecipientFilter, args[1]) _recipients.update(*tuple(tmp_recipients), clear=True) except RuntimeError: # Patch for issue #314 tmp_recipients = RecipientFilter() (args[1] + 4).copy( get_object_pointer(tmp_recipients) + 4, get_size(RecipientFilter) - 4) _recipients.update(*tuple(tmp_recipients), clear=True) args[1] = _recipients
def __getattr__(self, attr): """Find if the attribute is valid and returns the appropriate value.""" # Loop through all of the entity's server classes for server_class in self.server_classes: # Does the current server class contain the given attribute? if hasattr(server_class, attr): # Return the attribute's value return getattr(make_object(server_class, self.pointer), attr) # If the attribute is not found, raise an error raise AttributeError('Attribute "{0}" not found'.format(attr))
def _pre_in_same_team(stack_data): """Always return False for bots from InSameTeam.""" other = stack_data[1] if stack_data[0] == other: return entity = make_object(Entity, other) if entity.classname != 'player': return player = Player(entity.index) if player.is_fake_client(): return False
def _pre_message_end(args): # This happens when we initialize our hooks, while a user message is # currently being created if _user_message_data is None: return message_index, buffer_write_ptr = _user_message_data # Retrieve the ListenerManager instances user_message_hooks = HookUserMessage.hooks[message_index] bitbuffer_user_message_hooks = HookBitBufferUserMessage.hooks[ message_index] # No need to do anything behind this if no listener is registered if not user_message_hooks and not bitbuffer_user_message_hooks: return buffer_write = make_object(BitBufferWrite, buffer_write_ptr) buffer_read = BitBufferRead(buffer_write, False) org_current_bit = buffer_write.current_bit # For bitbuffers we need to make sure every callback starts reading and # writing from the very first bit. for callback in bitbuffer_user_message_hooks: buffer_read.seek_to_bit(0) buffer_write.seek_to_bit(0) callback(_recipients, buffer_read, buffer_write) # If none of the above callbacks wrote to the buffer, we need to restore # the current_bit to the original value. if buffer_write.current_bit == 0: buffer_write.seek_to_bit(org_current_bit) # No need to do anything behind this if no listener is registered if not user_message_hooks: return try: impl = get_user_message_impl(message_index) except NotImplementedError: return buffer_read.seek_to_bit(0) data = impl.read(buffer_read) user_message_hooks.notify(_recipients, data) # Update buffer if data has been changed if data.has_been_changed(): buffer_write.seek_to_bit(0) impl.write(buffer_write, data)
def on_pre_drop_weapon(stack_data): """Remove the dropped weapon after one second.""" # Get the weapon dropped weapon_ptr = stack_data[1] # Continue only for valid weapons if weapon_ptr: # Get a Weapon instance for the dropped weapon weapon = make_object(Weapon, weapon_ptr) # Remove it after one second delay_manager(f'drop_{weapon.index}', 1, weapon_manager.remove_weapon, (weapon.index, ))
def _pre_message_end(args): # This happens when we initialize our hooks, while a user message is # currently being created if _user_message_data is None: return message_index, buffer_write_ptr = _user_message_data # Retrieve the ListenerManager instances user_message_hooks = HookUserMessage.hooks[message_index] bitbuffer_user_message_hooks = HookBitBufferUserMessage.hooks[message_index] # No need to do anything behind this if no listener is registered if not user_message_hooks and not bitbuffer_user_message_hooks: return buffer_write = make_object(BitBufferWrite, buffer_write_ptr) buffer_read = BitBufferRead(buffer_write, False) org_current_bit = buffer_write.current_bit # For bitbuffers we need to make sure every callback starts reading and # writing from the very first bit. for callback in bitbuffer_user_message_hooks: buffer_read.seek_to_bit(0) buffer_write.seek_to_bit(0) callback(_recipients, buffer_read, buffer_write) # If none of the above callbacks wrote to the buffer, we need to restore # the current_bit to the original value. if buffer_write.current_bit == 0: buffer_write.seek_to_bit(org_current_bit) # No need to do anything behind this if no listener is registered if not user_message_hooks: return try: impl = get_user_message_impl(message_index) except NotImplementedError: return buffer_read.seek_to_bit(0) data = impl.read(buffer_read) user_message_hooks.notify(_recipients, data) # Update buffer if data has been changed if data.has_been_changed(): buffer_write.seek_to_bit(0) impl.write(buffer_write, data)
def pre_take_damage(args): victim_entity = make_object(Entity, args[0]) try: victim_trip_mine = trip_mine_manager.get_by_prop_index( victim_entity.index) except IndexError: return if not victim_trip_mine.activated: return False info = make_object(TakeDamageInfo, args[1]) if info.attacker == WORLD_ENTITY_INDEX: return False attacker_entity = Entity(info.attacker) if attacker_entity.classname != 'player': return False attacker_player = player_manager[info.attacker] victim_trip_mine.on_prop_damaged(attacker_player.player) return False
def _pre_send_user_message(args): message_index = args[2] user_message_hooks = HookUserMessage.hooks[message_index] protobuf_user_message_hooks = HookProtobufUserMessage.hooks[ message_index] # No need to do anything behind this if no listener is registered if not user_message_hooks and not protobuf_user_message_hooks: return # Replace original recipients filter tmp_recipients = make_object(BaseRecipientFilter, args[1]) _recipients.update(*tuple(tmp_recipients), clear=True) args[1] = _recipients buffer = make_object(ProtobufMessage, args[3]) protobuf_user_message_hooks.notify(_recipients, buffer) # No need to do anything behind this if no listener is registered if not user_message_hooks: return try: impl = get_user_message_impl(message_index) except NotImplementedError: return data = impl.read(buffer) user_message_hooks.notify(_recipients, data) # Update buffer if data has been changed if data.has_been_changed(): buffer.clear() impl.write(buffer, data)
def _pre_player_run_command(args): if (not on_player_run_command_listener_manager and not on_button_state_changed_listener_manager): return player = make_object(Player, args[0]) # https://github.com/Source-Python-Dev-Team/Source.Python/issues/149 use_rtti_fix = SOURCE_ENGINE_BRANCH == 'tf2' and player.is_fake_client() if use_rtti_fix: user_cmd = UserCmd() user_cmd_ptr = get_object_pointer(user_cmd) args[1].copy(user_cmd_ptr, USER_CMD_SIZE) else: user_cmd = make_object(UserCmd, args[1]) if on_player_run_command_listener_manager: on_player_run_command_listener_manager.notify(player, user_cmd) if on_button_state_changed_listener_manager: _handle_button_state_changed(player, player.buttons, user_cmd.buttons) if use_rtti_fix: user_cmd_ptr.copy(args[1], USER_CMD_SIZE)
def get_input(self, name): """Return the InputFunction instance for the given name.""" # Loop through each server class for the entity for server_class in self.server_classes: # Does the current server class contain the input? if name in server_class.inputs: # Return the InputFunction instance for the given input name return getattr( make_object(server_class._inputs, self.pointer), name) # If no server class contains the input, raise an error raise ValueError( 'Unknown input "{0}" for entity type "{1}".'.format( name, self.classname))
def on_take_damage(args): dm_player_victim = player_manager[index_from_pointer(args[0])] if dm_player_victim.protected: return True info = make_object(TakeDamageInfo, args[1]) try: dm_player_attacker = player_manager[info.attacker] except KeyError: return if dm_player_attacker.protected: dm_player_attacker.cancel_protection_delay() dm_player_attacker.unprotect() return True
def fget(pointer): """Retrieve the InputFunction instance.""" func = desc.function # Handle virtual inputs on Linux if PLATFORM == 'linux' and func.address & 1: func = pointer.get_virtual_func((func.address - 1) // 4) # TODO: # Don't use make_function(), but use input_function directly. It's # already callable. function = func.make_function(Convention.THISCALL, (DataType.POINTER, DataType.POINTER), DataType.VOID) return InputFunction(desc, make_object(BaseEntity, pointer))
def pre_on_take_damage(stack): if _global_bypass: return info = make_object(TakeDamageInfo, stack[1]) attacker = info.attacker if 0 < attacker <= global_vars.max_clients: wcsattacker = Player.from_index(attacker) else: wcsattacker = None index = index_from_pointer(stack[0]) wcsvictim = Player.from_index(index) OnTakeDamage.manager.notify(wcsvictim, wcsattacker, info)
def _on_use_add_weapon(stack_data): 'Add items to the inventory which do not have the <use> input.' ## If a <Item> cannot be accessed via the <use> input. We try to find it by ## hooking the player\'s <run_command> and firing a trace ray upon <PlayerButtons.USE> ## being pushed. usercmd = make_object(UserCmd, stack_data[1]) if not usercmd.buttons & PlayerButtons.USE: return player = player_inventories[index_from_pointer(stack_data[0])] trace = player.get_trace_ray() if not trace.did_hit() or trace.entity_index == 0: return item = items.find_by_index(trace.entity_index) if not item or item.entity.classname != 'prop_dynamic': return item.on_remove() item.on_pickup(player)
def _get_property(self, name, prop_type): """Verify the type and return the property.""" # Loop through all entity server classes for server_class in self.server_classes: # Is the name a member of the current server class? if name not in server_class.properties: continue # Is the type the correct type? if prop_type != server_class.properties[name].prop_type: raise TypeError('Property "{0}" is of type {1} not {2}'.format( name, server_class.properties[name].prop_type, prop_type)) # Return the property for the entity return getattr(make_object(server_class._properties, self.pointer), name) # Raise an error if the property name was not found raise ValueError( 'Property "{0}" not found for entity type "{1}"'.format( name, self.classname))
def _pre_damage_call_events(stack_data): take_damage_info = make_object(TakeDamageInfo, stack_data[1]) if not take_damage_info.attacker: return entity = Entity(take_damage_info.attacker) attacker = players[userid_from_index(entity.index)] if entity.is_player() else None victim = players[userid_from_pointer(stack_data[0])] event_args = { 'attacker': attacker, 'victim': victim, 'take_damage_info': take_damage_info, } if attacker: if victim.team == attacker.team: attacker.hero.call_events('player_pre_teammate_attack', player=attacker, **event_args) victim.hero.call_events('player_pre_teammate_victim', player=victim, **event_args) return attacker.hero.call_events('player_pre_attack', player=attacker, **event_args) victim.hero.call_events('player_pre_victim', player=victim, **event_args)
def global_pointer(self, cls, binary, identifier, offset=0, level=0, srv_check=True): """Search for a global pointer and wrap the it.""" manager_logger.log_debug('Retrieving global pointer for {}...'.format( cls.__name__)) # Get the binary binary = find_binary(binary, srv_check) # Get the global pointer ptr = binary.find_pointer(identifier, offset, level) # Raise an error if the pointer is invalid if not ptr: raise ValueError('Unable to find the global pointer.') # Wrap the pointer using the given class and save the instance ptr = self.global_pointers[cls.__name__] = make_object(cls, ptr) return ptr
def make_weapon_can_use(player): return make_object(CCSPlayer, player.pointer).weapon_can_use
def base_client(self): """Return the player's :class:`players.BaseClient` object.""" return memory.make_object(BaseClient, memory.get_object_pointer(self.client) - 4)
def _on_weapon_bump(args): """Return whether the player is allowed to pickup the weapon.""" return weapon_restriction_manager.on_player_bumping_weapon( make_object(Player, args[0]), make_object(Weapon, args[1]).weapon_name)
def _on_weapon_purchase(args): """Return whether the player is allowed to purchase the weapon.""" return weapon_restriction_manager.on_player_purchasing_weapon( make_object(Player, args[0]), args[1])
def __getattr__(self, name): """Return the value of the given alias. :param str name: The alias name. :rtype: object """ # Get the name of the prop... prop_name = self.template.aliases.get(name, None) # Was the given name a valid alias? if prop_name is not None: # Is the name a section? if isinstance(prop_name, Section): # Is the alias a decal? if prop_name['type'] == Decal.__name__: # Return the decal instance... return Decal(string_tables[Decal._precache_table][getattr( self, prop_name['name'])]) # Otherwise, is the alias an entity? elif prop_name['type'] == Entity.__name__: # Return the entity instance... return Entity(getattr(self, prop_name['name'])) # Otherwise, is the alias a player? elif prop_name['type'] == Player.__name__: # Return the player instance... return Player(getattr(self, prop_name['name'])) # Otherwise, is the alias a model? elif prop_name['type'] == Model.__name__: # Get the name of the model... model_name = string_tables[Model._precache_table][getattr( self, prop_name['name'])] # Was the model not precached? if not model_name: # Return an error model... return Model('models/error.mdl') # Return the model instance... return Model(model_name) # Otherwise, is the alias a color? elif prop_name['type'] == Color.__name__: # Get a tuple to store the RGBA values... values = tuple() # Loop through all aliases... for alias in prop_name['name']: # Add the current value to the tuple... values += (getattr(self, alias), ) # Return the color instance... return Color(*values) # Otherwise... else: # Get the data of the property... prop, offset, type_name = self.template.properties[ prop_name['name']] # Return the value of the property... return make_object(manager.get_class(prop_name['type']), get_object_pointer(self) + offset) # Get the data of the property... prop, offset, type_name = self.template.properties[prop_name] # Return the value of the property... return self._get_property(prop_name, prop.type) # Return the value of the given attribute... return super().__getattribute__(name)
def __sub__(self, other): """Return self-value.""" return make_object(self.__class__, Pointer(int(self) - int(other)))
def base_client(self): """Return the player's :class:`players.BaseClient` object.""" from players import BaseClient return make_object(BaseClient, get_object_pointer(self.client) - 4)
def pre_playback_temp_entity(stack_data): """Handle pre hooks.""" temp_entity = TempEntity(stack_data[3]) return temp_entity.template.handle_hook( temp_entity, make_object(RecipientFilter, stack_data[1]))
def _on_weapon_bump(args): """Return whether the player is allowed to pickup the weapon.""" return weapon_restriction_manager.on_player_bumping_weapon( make_object(Player, args[0]), edict_from_pointer(args[1]).classname)
def _pre_game_event(args): """Call pre-event functions if the event is registered.""" # Crashfix for CS:GO: # https://github.com/Source-Python-Dev-Team/Source.Python/issues/230 game_event_ptr = args[1] if not game_event_ptr: return False # Get the GameEvent object game_event = make_object(GameEvent, game_event_ptr) # Get the name of the event event_name = game_event.name # If the current event is not in the dictionary, return if event_name not in pre_event_manager: return # Create a variable to know what to do after all pre-events are called event_action = EventAction.CONTINUE # Loop through all callbacks in the pre-event's list for callback in pre_event_manager[event_name]: # Use try/except in case an error occurs during in the callback try: # Call the callback and get its return value current_action = callback(game_event) # Is the return value invalid? if (current_action is not None and not isinstance(current_action, EventAction)): # Raise an error to exit the try raise ValueError( 'Invalid return value for pre-event "{0}".'.format( current_action)) # Was an error encountered? except: # Print the exception to the console except_hooks.print_exception() # Was no error encountered? else: # Does the current action have a higher priority? if current_action is not None and current_action > event_action: # Change the event action event_action = current_action # Does the return value want to set the dontbroadcast value? if event_action is EventAction.STOP_BROADCAST: # Set the dontbroadcast value args[2] = True # Does the return value want to block the event? elif event_action is EventAction.BLOCK: # Free the event game_event_manager.free_event(game_event) # Block the event return False
def __add__(self, other): """Return self+value.""" return make_object(self.__class__, Pointer(int(self) + int(other)))
def _set_cash(args, return_value): with suppress(ValueError): make_object(Player, args[0]).cash = 0
def _pre_call_global_change_callbacks(args): """Called when a ConVar has been changed.""" convar = make_object(ConVar, args[1]) old_value = args[2] on_convar_changed_listener_manager.notify(convar, old_value)