def _on_player_victim(self, attacker, victim, **kwargs): if attacker.dead or self.level == 0: return info = TakeDamageInfo() info.inflictor = victim.index info.damage = self.reflect_damage attacker.on_take_damage(info)
def _on_player_victim(self, attacker, victim, **kwargs): if attacker.dead or randint(0, 101) > (self.level * 2) or self.level == 0: return info = TakeDamageInfo() info.inflictor = victim.index info.damage = self.reflect_damage attacker.on_take_damage(info) send_wcs_saytext_by_index( self._msg_a.format(damage=self.reflect_damage, name=attacker.name), victim.index)
def take_damage(self, damage, attacker, weapon=None, skip_hooks=True): # TODO: This method should not have been called if the victim is already dead assert not self.player.dead if not self.player.dead: global _global_bypass _global_bypass = skip_hooks take_damage_info = TakeDamageInfo() take_damage_info.attacker = attacker if weapon is None: index = set_weapon_name('point_hurt', None) else: index = set_weapon_name(weapon) take_damage_info.weapon = index take_damage_info.inflictor = index take_damage_info.damage = damage take_damage_info.type = DamageTypes.GENERIC try: self.player.on_take_damage(take_damage_info) finally: _global_bypass = False
def take_damage(self, damage, attacker, weapon=None, skip_hooks=True): # TODO: This method should not have been called if the victim is already dead assert not self.player.dead if not self.player.dead: global _global_bypass _global_bypass = skip_hooks take_damage_info = TakeDamageInfo() take_damage_info.attacker = attacker global _global_weapon_entity if _global_weapon_entity is None: _global_weapon_entity = Entity.create('info_target') if weapon is None: _global_weapon_entity.set_key_value_string('classname', 'point_hurt') else: _global_weapon_entity.set_key_value_string('classname', f'wcs_{weapon}') take_damage_info.weapon = _global_weapon_entity.index take_damage_info.inflictor = _global_weapon_entity.index take_damage_info.damage = damage take_damage_info.type = DamageTypes.GENERIC try: self.player.on_take_damage(take_damage_info) finally: _global_bypass = False
def take_damage( self, damage, damage_type=DamageTypes.GENERIC, attacker_index=None, weapon_index=None, hitgroup=HitGroup.GENERIC, skip_hooks=False, **kwargs): """Method used to hurt the entity with the given arguments.""" # Import Entity classes # Doing this in the global scope causes cross import errors from weapons.entity import Weapon # Is the game supported? if not hasattr(self, 'on_take_damage'): # Raise an error if not supported raise NotImplementedError( '"take_damage" is not implemented for {0}'.format(GAME_NAME)) # Store values for later use attacker = None weapon = None # Was an attacker given? if attacker_index is not None: # Try to get the Entity instance of the attacker with suppress(ValueError): attacker = Entity(attacker_index) # Was a weapon given? if weapon_index is not None: # Try to get the Weapon instance of the weapon with suppress(ValueError): weapon = Weapon(weapon_index) # Is there a weapon but no attacker? if attacker is None and weapon is not None: # Try to get the attacker based off of the weapon's owner with suppress(ValueError, OverflowError): attacker_index = index_from_inthandle(weapon.current_owner) attacker = Entity(attacker_index) # Is there an attacker but no weapon? if attacker is not None and weapon is None: # Try to use the attacker's active weapon with suppress(AttributeError, ValueError, OverflowError): weapon = Weapon(index_from_inthandle(attacker.active_weapon)) # Try to set the hitgroup with suppress(AttributeError): self.hitgroup = hitgroup # Get a TakeDamageInfo instance take_damage_info = TakeDamageInfo() # Is there a valid weapon? if weapon is not None: # Is the weapon a projectile? if weapon.classname in _projectile_weapons: # Set the inflictor to the weapon's index take_damage_info.inflictor = weapon.index # Is the weapon not a projectile and the attacker is valid? elif attacker_index is not None: # Set the inflictor to the attacker's index take_damage_info.inflictor = attacker_index # Set the weapon to the weapon's index take_damage_info.weapon = weapon.index # Is the attacker valid? if attacker_index is not None: # Set the attacker to the attacker's index take_damage_info.attacker = attacker_index # Set the damage amount take_damage_info.damage = damage # Set the damage type value take_damage_info.type = damage_type # Loop through the given keywords for item in kwargs: # Set the offset's value setattr(take_damage_info, item, kwargs[item]) if skip_hooks: self.on_take_damage.skip_hooks(take_damage_info) else: self.on_take_damage(take_damage_info)
def take_damage(self, damage, damage_type=DamageTypes.GENERIC, attacker_index=None, weapon_index=None, hitgroup=HitGroup.GENERIC, skip_hooks=False, **kwargs): """Deal damage to the entity. :param int damage: Amount of damage to deal. :param DamageTypes damage_type: Type of the dealed damage. :param int attacker_index: If not None, the index will be used as the attacker. :param int weapon_index: If not None, the index will be used as the weapon. This method also tries to retrieve the attacker from the weapon, if ``attacker_index`` wasn't set. :param HitGroup hitgroup: The hitgroup where the damage should be applied. :param bool skip_hooks: If True, the damage will be dealed directly by skipping any registered hooks. """ # Import Entity classes # Doing this in the global scope causes cross import errors from weapons.entity import Weapon # Is the game supported? if not hasattr(self, 'on_take_damage'): # Raise an error if not supported raise NotImplementedError( '"take_damage" is not implemented for {0}'.format(GAME_NAME)) # Store values for later use attacker = None weapon = None # Was an attacker given? if attacker_index is not None: # Try to get the Entity instance of the attacker with suppress(ValueError): attacker = Entity(attacker_index) # Was a weapon given? if weapon_index is not None: # Try to get the Weapon instance of the weapon with suppress(ValueError): weapon = Weapon(weapon_index) # Is there a weapon but no attacker? if attacker is None and weapon is not None: # Try to get the attacker based off of the weapon's owner with suppress(ValueError, OverflowError): attacker_index = index_from_inthandle(weapon.owner_handle) attacker = Entity(attacker_index) # Is there an attacker but no weapon? if attacker is not None and weapon is None: # Try to use the attacker's active weapon with suppress(AttributeError): weapon = attacker.active_weapon # Try to set the hitgroup with suppress(AttributeError): self.hitgroup = hitgroup # Get a TakeDamageInfo instance take_damage_info = TakeDamageInfo() # Is there a valid weapon? if weapon is not None: # Is the weapon a projectile? if weapon.classname in _projectile_weapons: # Set the inflictor to the weapon's index take_damage_info.inflictor = weapon.index # Is the weapon not a projectile and the attacker is valid? elif attacker_index is not None: # Set the inflictor to the attacker's index take_damage_info.inflictor = attacker_index # Set the weapon to the weapon's index take_damage_info.weapon = weapon.index # Is the attacker valid? if attacker_index is not None: # Set the attacker to the attacker's index take_damage_info.attacker = attacker_index # Set the damage amount take_damage_info.damage = damage # Set the damage type value take_damage_info.type = damage_type # Loop through the given keywords for item in kwargs: # Set the offset's value setattr(take_damage_info, item, kwargs[item]) if skip_hooks: self.on_take_damage.skip_hooks(take_damage_info) else: self.on_take_damage(take_damage_info)
def on_take_damage_alive_pre(stack_data): """Creates a FloatingNumber when a player takes damage.""" # Get the Player instance of the victim. player_v = player_instances[index_from_pointer(stack_data[0])] # Get the CTakeDamageInfo instance. info = TakeDamageInfo._obj(stack_data[1]) # Get the index of the entity that caused the damage. index_a = info.attacker # Did the player take damage from the world? if index_a == 0: # Are damage numbers disabled for world damage (world_damage set to 0)? if not world_damage.get_int(): return number_origin = player_v.get_number_origin() unique_data = [] for player in player_instances.values(): # There's no need for bots to see the FloatingNumber. if player.is_bot(): continue # Is the player not looking at the position where the # FloatingNumber is going to spawn? if not player.is_in_fov(target=number_origin): continue distance = number_origin.get_distance(player.origin) # Add this player's unique data to the list. unique_data.append({ 'angle': player.view_angle, 'size': 10 + distance * DISTANCE_MULTIPLIER, 'recipient': player.userid }) # Will no one be able to see this FloatingNumber? if not unique_data: # Don't bother spawning it. return FloatingNumber.world_damage( origin=number_origin, # Since `info.damage` is a float, convert it to an integer before # converting it to a string to get rid of the decimal part. number=str(int(info.damage)), color=WHITE, unique_data=unique_data ) # Or from a player? else: try: # Try to get the Player instance of the attacker. player_a = player_instances[index_a] except ValueError: # Damage was caused indirectly (grenade, projectile). try: # Try to get a Player instance again, but this time using the # the owner inthandle of the entity that caused the damage. player_a = player_instances.from_inthandle( Entity(info.inflictor).owner_handle) except (ValueError, OverflowError): # ValueError: not a player. # OverflowError: invalid owner inthandle (-1). return # Is the attacker a bot? if player_a.is_bot(): return # Self inflicted damage? if player_v is player_a: return number_origin = player_v.get_number_origin() velocity = None # Did the bullet go through another entity before hitting the player? if info.penetrated and wall_bangs.get_int(): # Let's check if that entity is the world. trace = GameTrace() engine_trace.clip_ray_to_entity( # Create a Ray() from the attacker's eyes to the hit position. Ray(player_a.eye_location, info.position), ContentMasks.ALL, Entity(WORLD_ENTITY_INDEX), trace ) # Is this an actual wall-bang (bullet went through world)? if trace.did_hit(): # Calculate the directional vector from the wall to the player. from_wall = trace.start_position - trace.end_position # Calculate the offset for the FloatingNumber's new origin. origin_offset = 10 + from_wall.length * 0.01 # Normalize it. # Vector(368.52, 40.71, -7.77) -> Vector(0.99, 0.10, -0.02) from_wall.normalize() # Change the origin of the FloatingNumber so it spawns in front # of the wall where the wall-bang took place. number_origin = trace.end_position + origin_offset * from_wall right, up = Vector(), Vector() from_wall.get_vector_vectors(right, up) velocity = from_wall * 25 + ( right * 35 * player_a.next_direction) # If the bullet went through something else (another player) # before hitting the wall, adjust how high the FloatingNumber # gets pushed. velocity.z = 75 * info.penetrated distance = number_origin.get_distance(player_a.origin) # TODO: Figure out a better way to allow other plugins to change the # color of the FloatingNumber. Or hardcode the colors to unused # DamageTypes (e.g. AIRBOAT = YELLOW, PHYSGUN = BLUE)? color = YELLOW if info.type == DamageTypes.AIRBOAT else WHITE FloatingNumber( origin=number_origin, number=str(int(info.damage)), # Change the color if it's a headshot. color=RED if player_v.last_hitgroup == 1 else color, angle=player_a.view_angle, # Increase the size depending on the distance. size=10 + distance * DISTANCE_MULTIPLIER, recipient=player_a.userid, velocity=velocity )
def take_damage( self, damage, damage_type=DamageTypes.GENERIC, attacker_index=None, weapon_index=None, hitgroup=HitGroup.GENERIC, skip_hooks=False, **kwargs): """Deal damage to the entity. :param int damage: Amount of damage to deal. :param DamageTypes damage_type: Type of the dealed damage. :param int attacker_index: If not None, the index will be used as the attacker. :param int weapon_index: If not None, the index will be used as the weapon. This method also tries to retrieve the attacker from the weapon, if ``attacker_index`` wasn't set. :param HitGroup hitgroup: The hitgroup where the damage should be applied. :param bool skip_hooks: If True, the damage will be dealed directly by skipping any registered hooks. """ # Import Entity classes # Doing this in the global scope causes cross import errors from weapons.entity import Weapon # Is the game supported? if not hasattr(self, 'on_take_damage'): # Raise an error if not supported raise NotImplementedError( '"take_damage" is not implemented for {0}'.format(GAME_NAME)) # Store values for later use attacker = None weapon = None # Was an attacker given? if attacker_index is not None: # Try to get the Entity instance of the attacker with suppress(ValueError): attacker = Entity(attacker_index) # Was a weapon given? if weapon_index is not None: # Try to get the Weapon instance of the weapon with suppress(ValueError): weapon = Weapon(weapon_index) # Is there a weapon but no attacker? if attacker is None and weapon is not None: # Try to get the attacker based off of the weapon's owner with suppress(ValueError, OverflowError): attacker_index = index_from_inthandle(weapon.owner_handle) attacker = Entity(attacker_index) # Is there an attacker but no weapon? if attacker is not None and weapon is None: # Try to use the attacker's active weapon with suppress(AttributeError): weapon = attacker.active_weapon # Try to set the hitgroup with suppress(AttributeError): self.hitgroup = hitgroup # Get a TakeDamageInfo instance take_damage_info = TakeDamageInfo() # Is there a valid weapon? if weapon is not None: # Is the weapon a projectile? if weapon.classname in _projectile_weapons: # Set the inflictor to the weapon's index take_damage_info.inflictor = weapon.index # Is the weapon not a projectile and the attacker is valid? elif attacker_index is not None: # Set the inflictor to the attacker's index take_damage_info.inflictor = attacker_index # Set the weapon to the weapon's index take_damage_info.weapon = weapon.index # Is the attacker valid? if attacker_index is not None: # Set the attacker to the attacker's index take_damage_info.attacker = attacker_index # Set the damage amount take_damage_info.damage = damage # Set the damage type value take_damage_info.type = damage_type # Loop through the given keywords for item in kwargs: # Set the offset's value setattr(take_damage_info, item, kwargs[item]) if skip_hooks: self.on_take_damage.skip_hooks(take_damage_info) else: self.on_take_damage(take_damage_info)
def take_damage(entity, damage, attacker): take_damage_info = TakeDamageInfo() take_damage_info.attacker = attacker.index take_damage_info.damage = damage take_damage_info.type = DamageTypes.BLAST entity.on_take_damage(take_damage_info)