hl2dm crossbow arrows with a fire flame.

A place for requesting new Source.Python plugins to be made for your server.

Please request only one plugin per thread.
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

hl2dm crossbow arrows with a fire flame.

Postby daren adler » Sun Sep 20, 2020 3:36 pm

Hello python script makers :cool:, Is there a way to get fire flames on the crossbow arrows?. :eek: :cool:
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: hl2dm crossbow arrows with a fire flame.

Postby VinciT » Tue Sep 22, 2020 5:38 am

This should do the trick:

Syntax: Select all

# ../fiery_bolts/fiery_bolts.py

# Python
import random

# Source.Python
from engines.precache import Model
from engines.sound import Sound
from entities.constants import (EntityStates, RenderMode, RenderEffects,
MoveType, WORLD_ENTITY_INDEX)
from entities.dictionary import EntityDictionary
from entities.entity import Entity
from entities.helpers import index_from_pointer
from entities.hooks import EntityPreHook, EntityCondition
from events import Event
from listeners import OnNetworkedEntityCreated
from players.entity import Player
from stringtables import string_tables


# Material/sprite used for the trail.
TRAIL_MODEL = Model('materials/sprites/laser.vmt')


class Bolts(EntityDictionary):
"""Modified EntityDictionary class for storing Bolt instances."""

def on_automatically_removed(self, index):
"""Called when an index is automatically removed."""
self[index].detach_effects()


class BoltEffects(EntityDictionary):
"""Class used for cleaning up after the particle and trail effects."""

def on_automatically_removed(self, index):
"""Called when an index is automatically removed."""
effect = self[index]

try:
# Try to get the Bolt instance the effect was parented to.
bolt = bolts.from_inthandle(effect.parent_inthandle)
except (KeyError, OverflowError):
# KeyError: Bolt instance no longer exists.
# OverflowError: Invalid parent_inthandle (-1).
return

# Remove the reference to the removed effect from the Bolt instance.
setattr(
object=bolt,
name='flame' if 'particle' in effect.classname else 'trail',
value=None
)


# Dictionary used to store Bolt instances.
bolts = Bolts(None)

# Dictionary used to store Entity instances for 'info_particle_system' and
# 'env_sprite_trail' entities.
bolt_effects = BoltEffects(None)


is_crossbow_bolt = EntityCondition.equals_entity_classname('crossbow_bolt')


@Event('player_death')
def player_death(event):
"""Called when a player dies."""
player = Player.from_userid(event['userid'])
# Was the player on fire prior to dying?
if player.get_property_int('m_fFlags') & EntityStates.ONFIRE:
# Extinguish them.
player.ignite_lifetime(0)


@OnNetworkedEntityCreated
def on_networked_entity_created(entity):
"""Called when a networked entity gets created."""
if 'crossbow_bolt' not in entity.classname:
return

# Create a Bolt instance.
bolt = Bolt(entity.index)
# Some properties are still uninitialized - delay the creation of the
# flame effect for a single frame.
bolt.delay(0, bolt.flame_on)


@EntityPreHook(is_crossbow_bolt, 'start_touch')
def start_touch_pre(stack_data):
try:
bolt = bolts[index_from_pointer(stack_data[0])]
except KeyError:
return

index = index_from_pointer(stack_data[1])
# Did the bolt hit the world?
if index == WORLD_ENTITY_INDEX:
return

try:
# Try to ignite the entity that was hit.
Entity(index).ignite()
except AttributeError:
pass


class Bolt(Entity):
"""Extended Entity class for manipulating the 'crossbow_bolt' entity.

Args:
index (int): A valid Entity index.
caching (bool): Check for a cached instance?

Attributes:
flame (Entity): Instance of the 'info_particle_system' entity.
trail (Entity): Instance of the 'env_sprite_trail' entity.
sound (Sound): Looping sound used for the projectile.
"""
# Alternative particle effects:
# burning_engine_fire
# burning_gib_01
# burning_gib_01_follower1
# burning_gib_01_follower2
# fire_medium_02_nosmoke
# fire_small_02
# fire_small_03
effect_name = 'fire_small_01'
# Colors used for the bolt trail.
trail_colors = ('255 162 2', '255 95 12', '255 129 33', '255 100 0')

def __init__(self, index, caching=True):
"""Initializes the object."""
super().__init__(index, caching)

self.flame = None
self.trail = None
self.sound = Sound(
sample=f'ambient/fire/fire_small_loop{random.randint(1, 2)}.wav',
index=index,
attenuation=0.85
)

# Add the Bolt instance to the dictionary.
bolts[index] = self

def flame_on(self):
"""Creates the fire particle effect, as well as the sprite trail."""
self.flame = Entity.create('info_particle_system')
self.flame.effect_name = Bolt.effect_name
self.flame.effect_index = string_tables.ParticleEffectNames.add_string(
Bolt.effect_name)

self.flame.origin = self.origin
self.flame.set_parent(self)
self.flame.start()
# Save the 'info_particle_system' instance in a dictionary.
bolt_effects[self.flame.index] = self.flame

self.trail = create_sprite_trail(
origin=self.origin,
sprite_path=TRAIL_MODEL.path,
start_width=15,
end_width=5,
color_str=random.choice(Bolt.trail_colors),
life_time=1
)

self.trail.set_parent(self)
# Save the 'env_sprite_trail' instance in a dictionary.
bolt_effects[self.trail.index] = self.trail

self.sound.play()

def detach_effects(self):
"""Detaches the particle effect and trail from the bolt."""
# Save the last known position of the bolt.
last_origin = self.origin

try:
# Try to detach the sprite trail.
self.trail.clear_parent()
self.trail.teleport(origin=last_origin)
# Freeze it in place.
self.trail.move_type = MoveType.NONE
# Remove it after a short delay.
self.trail.delay(1.5, self.trail.remove)
except AttributeError:
pass

try:
# Try to detach the particle effect.
self.flame.clear_parent()
self.flame.teleport(origin=last_origin)
self.flame.move_type = MoveType.NONE
self.flame.delay(1.2, self.flame.remove)
except AttributeError:
pass

# Stop the looping sound.
self.sound.stop()


def create_sprite_trail(
origin, sprite_path, start_width, end_width, color_str, life_time):
"""Creates an 'env_spritetrail' entity.

Args:
origin (Vector): Spawn position.
sprite_path (string): Path to the sprite material.
start_width (float): Starting width of the trail.
end_width (float): Ending width of the trail.
color_str (str): String containing the RGB values of the color.
(e.g. '255 255 255' for white)
life_time (float): How long does the trail last before it starts to
fade (in seconds)?

Returns:
Entity: The entity instance of the created 'env_spritetrail'.

"""
trail = Entity.create('env_spritetrail')
trail.sprite_name = sprite_path
trail.origin = origin

trail.life_time = life_time
trail.start_width = start_width
trail.end_width = end_width

trail.render_mode = RenderMode.TRANS_ADD
trail.render_amt = 255
trail.render_fx = RenderEffects.NONE
trail.set_key_value_string('rendercolor', color_str)
trail.spawn()

# Texture resolution of the trail.
trail.texture_res = 0.05
return trail
Last edited by VinciT on Sun Oct 11, 2020 4:45 pm, edited 4 times in total.
ImageImageImageImageImage
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: hl2dm crossbow arrows with a fire flame.

Postby L'In20Cible » Tue Sep 22, 2020 6:29 am

VinciT wrote:This should do the trick:

Syntax: Select all

# Dictionary used to store Bolt instances.
bolts = {}

@OnEntityDeleted
def on_entity_deleted(base_entity):
"""Called when an entity gets deleted."""
try:
index = base_entity.index
except ValueError:
return

try:
# Unparent the particle effect and trail before the 'crossbow_bolt'
# gets removed to avoid them bugging out.
bolts.pop(index).detach_effects()
except KeyError:
pass


Sounds like a perfect situation to use an EntityDictionary.on_automatically_removed callback. :smile:

Syntax: Select all

class Bolts(EntityDictionary):
def on_automatically_removed(self, index):
self[index].detach_effects()

bolts = Bolts()
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: hl2dm crossbow arrows with a fire flame.

Postby daren adler » Tue Sep 22, 2020 7:20 am

VinciT wrote:This should do the trick:

Syntax: Select all

# ../fiery_bolts/fiery_bolts.py

# Python
import random

# Source.Python
from engines.precache import Model
from engines.sound import Sound
from entities.constants import (RenderMode, RenderEffects, MoveType,
WORLD_ENTITY_INDEX)
from entities.entity import Entity
from entities.helpers import index_from_pointer
from entities.hooks import EntityPreHook, EntityCondition
from listeners import OnEntityCreated, OnEntityDeleted
from stringtables import string_tables


# Material/sprite used for the trail.
TRAIL_MODEL = Model('materials/sprites/laser.vmt')

# Dictionary used to store Bolt instances.
bolts = {}


is_crossbow_bolt = EntityCondition.equals_entity_classname('crossbow_bolt')


@OnEntityCreated
def on_entity_created(base_entity):
"""Called when an entity gets created."""
try:
index = base_entity.index
except ValueError:
return

if 'crossbow_bolt' in base_entity.classname:
# Create a Bolt instance.
bolt = Bolt(index)
# Some properties are still uninitialized - delay the creation of the
# flame effect for a single frame.
bolt.delay(0, bolt.flame_on)


@OnEntityDeleted
def on_entity_deleted(base_entity):
"""Called when an entity gets deleted."""
try:
index = base_entity.index
except ValueError:
return

try:
# Unparent the particle effect and trail before the 'crossbow_bolt'
# gets removed to avoid them bugging out.
bolts.pop(index).detach_effects()
except KeyError:
pass


@EntityPreHook(is_crossbow_bolt, 'start_touch')
def start_touch_pre(stack_data):
try:
bolt = bolts[index_from_pointer(stack_data[0])]
except KeyError:
return

index = index_from_pointer(stack_data[1])
# Did the bolt hit the world?
if index == WORLD_ENTITY_INDEX:
return

# Ignite the entity that was hit.
Entity(index).ignite()
bolt.detach_effects()


class Bolt(Entity):
"""Extended Entity class for manipulating the 'crossbow_bolt' entity.

Args:
index (int): A valid Entity index.
caching (bool): Check for a cached instance?

Attributes:
flame (Entity): Instance of the 'info_particle_system' entity.
trail (Entity): Instance of the 'env_sprite_trail' entity.
sound (Sound): Looping sound used for the projectile.
"""
# Alternative particle effects:
# burning_engine_fire
# burning_gib_01
# burning_gib_01_follower1
# burning_gib_01_follower2
# fire_medium_02_nosmoke
# fire_small_02
# fire_small_03
effect_name = 'fire_small_01'
# Colors used for the bolt trail.
trail_colors = ('255 162 2', '255 95 12', '255 129 33', '255 100 0')

def __init__(self, index, caching=True):
"""Initializes the object."""
super().__init__(index, caching)

self.flame = None
self.trail = None
self.sound = Sound(
sample=f'ambient/fire/fire_small_loop{random.randint(1, 2)}.wav',
index=index,
attenuation=0.85
)

# Add the Bolt instance to the dictionary.
bolts[index] = self

def flame_on(self):
"""Creates the fire particle effect, as well as the sprite trail."""
particle = Entity.create('info_particle_system')
particle.effect_name = Bolt.effect_name
particle.effect_index = string_tables.ParticleEffectNames.add_string(
Bolt.effect_name)

particle.origin = self.origin
particle.set_parent(self)
particle.start()

self.trail = create_sprite_trail(
origin=self.origin,
sprite_path=TRAIL_MODEL.path,
start_width=15,
end_width=5,
color_str=random.choice(Bolt.trail_colors),
life_time=1
)

self.trail.set_parent(self)
self.sound.play()

def detach_effects(self):
"""Detaches the particle effect and trail from the bolt."""
# Save the last known position of the bolt.
last_origin = self.origin

try:
# Try to detach the sprite trail.
self.trail.clear_parent()
self.trail.teleport(origin=last_origin)
# Freeze it in place.
self.trail.move_type = MoveType.NONE
# Remove it after a short delay.
self.trail.delay(1.5, self.trail.remove)
except AttributeError:
pass

try:
# Try to detach the particle effect.
self.flame.clear_parent()
self.flame.teleport(origin=last_origin)
self.flame.move_type = MoveType.NONE
self.flame.delay(1.2, self.flame.remove)
except AttributeError:
pass

# Stop the looping sound.
self.sound.stop()


def create_sprite_trail(
origin, sprite_path, start_width, end_width, color_str, life_time):
"""Creates an 'env_spritetrail' entity.

Args:
origin (Vector): Spawn position.
sprite_path (string): Path to the sprite material.
start_width (float): Starting width of the trail.
end_width (float): Ending width of the trail.
color_str (str): String containing the RGB values of the color.
(e.g. '255 255 255' for white)
life_time (float): How long does the trail last before it starts to
fade (in seconds)?

Returns:
Entity: The entity instance of the created 'env_spritetrail'.

"""
trail = Entity.create('env_spritetrail')
trail.sprite_name = sprite_path
trail.origin = origin

trail.life_time = life_time
trail.start_width = start_width
trail.end_width = end_width

trail.render_mode = RenderMode.TRANS_ADD
trail.render_amt = 255
trail.render_fx = RenderEffects.NONE
trail.set_key_value_string('rendercolor', color_str)
trail.spawn()

# Texture resolution of the trail.
trail.texture_res = 0.05
return trail


Thank you. I will give it a try tomarow, again thank you for all your help. =UPDATE= Works great :wink: :cool: You do a very good job :wink:

Just got this error

Code: Select all

2020-09-22 10:44:25 - sp   -   EXCEPTION   
[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\plugins\fiery_bolts\fiery_bolts.py", line 73, in start_touch_pre
    Entity(index).ignite()
  File "..\addons\source-python\packages\source-python\entities\_base.py", line 231, in __getattr__
    raise AttributeError('Attribute "{0}" not found'.format(attr))

AttributeError: Attribute "ignite" not found
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: hl2dm crossbow arrows with a fire flame.

Postby VinciT » Thu Sep 24, 2020 6:15 pm

daren adler wrote:Thank you. I will give it a try tomarow, again thank you for all your help. =UPDATE= Works great :wink: :cool: You do a very good job
Glad it works for you! I've updated the code in my previous post to fix the error you got.

L'In20Cible wrote:Sounds like a perfect situation to use an EntityDictionary.on_automatically_removed callback.
I wholeheartedly agree, I wanted to use that at first, but this part of the plugin made me go with the default dictionary:

Syntax: Select all

@EntityPreHook(is_crossbow_bolt, 'start_touch')
def start_touch_pre(stack_data):
try:
bolt = bolts[index_from_pointer(stack_data[0])]
except KeyError:
return
I guess I could replace the try/except with an if and retrieve the instance later.. Do you think the performance would be any different?
ImageImageImageImageImage
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: hl2dm crossbow arrows with a fire flame.

Postby daren adler » Thu Sep 24, 2020 6:26 pm

VinciT wrote:
daren adler wrote:Thank you. I will give it a try tomarow, again thank you for all your help. =UPDATE= Works great :wink: :cool: You do a very good job
Glad it works for you! I've updated the code in my previous post to fix the error you got.

L'In20Cible wrote:Sounds like a perfect situation to use an EntityDictionary.on_automatically_removed callback.
I wholeheartedly agree, I wanted to use that at first, but this part of the plugin made me go with the default dictionary:

Syntax: Select all

@EntityPreHook(is_crossbow_bolt, 'start_touch')
def start_touch_pre(stack_data):
try:
bolt = bolts[index_from_pointer(stack_data[0])]
except KeyError:
return
I guess I could replace the try/except with an if and retrieve the instance later.. Do you think the performance would be any different?


Thank you,,and yes it fixed it,,thank you again :wink: :wink:
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: hl2dm crossbow arrows with a fire flame.

Postby L'In20Cible » Thu Sep 24, 2020 8:08 pm

VinciT wrote:
daren adler wrote:I wholeheartedly agree, I wanted to use that at first, but this part of the plugin made me go with the default dictionary:

Syntax: Select all

@EntityPreHook(is_crossbow_bolt, 'start_touch')
def start_touch_pre(stack_data):
try:
bolt = bolts[index_from_pointer(stack_data[0])]
except KeyError:
return
I guess I could replace the try/except with an if and retrieve the instance later.. Do you think the performance would be any different?


You could simply override __missing__ to disable the factory:

Syntax: Select all

class Bolts(EntityDictionary):
def __missing__(self, index):
raise KeyError

def on_automatically_removed(self, index):
self[index].detach_effects()

bolts = Bolts()


Or use a None factory and catch TypeError:

Syntax: Select all

class Bolts(EntityDictionary):
def on_automatically_removed(self, index):
self[index].detach_effects()

bolts = Bolts(None)

try:
...
except TypeError:
return


Though it doesn't make much sense to catch a TypeError when retrieving a key from a dictionary. I'm thinking about changing EntityDictionary.__missing__ to the following to ensure it only ever raise a KeyError since this is what you should expect when retrieving a key failed:

Syntax: Select all

def __missing__(self, index):
"""Add and return the entity instance for the given index."""
# Get the factory
factory = self._factory

# Let's mimic dict's behaviour if the factory is set to None
if factory is None:
raise KeyError(index)

# For uniformity reasons, ensure we only raise a KeyError
try:
instance = factory(index, *self._args, **self._kwargs)
except Exception as e:
raise KeyError(str(e))

# Only cache entities that are not marked for deletion.
# This is required, because if someone request an entity instance
# after we invalidated our cache but before the engine processed
# the deletion we would now have an invalid instance in the cache.
if not instance.is_marked_for_deletion():
self[index] = instance

return instance
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: hl2dm crossbow arrows with a fire flame.

Postby daren adler » Sat Sep 26, 2020 12:28 am

Error still

Code: Select all

2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'alpha_props'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'alpha_props'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'fiery_bolts'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'fiery_bolts'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'npc_points'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'npc_points'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'sawblade_trail'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'sawblade_trail'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'silent_hill'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'silent_hill'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'weapon_effects'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'weapon_effects'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'weapon_manger'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'weapon_manger'.
2020-09-25 19:10:26 - sp   -   EXCEPTION   
[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\plugins\fiery_bolts\fiery_bolts.py", line 55, in on_entity_deleted
    bolts.pop(index).detach_effects()
  File "..\addons\source-python\plugins\fiery_bolts\fiery_bolts.py", line 151, in detach_effects
    self.trail.clear_parent()
  File "..\addons\source-python\packages\source-python\entities\_base.py", line 216, in __getattr__
    value = getattr(instance, attr)
  File "..\addons\source-python\packages\source-python\entities\classes.py", line 542, in fget
    return InputFunction(desc, make_object(BaseEntity, pointer))

RuntimeError: Access violation - no RTTI data!


I dont know what it is, i am thinking it might be the kill of a bot or the npc's. I just cant figer it out.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: hl2dm crossbow arrows with a fire flame.

Postby L'In20Cible » Sat Sep 26, 2020 2:11 am

daren adler wrote:Error still

Code: Select all

2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'alpha_props'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'alpha_props'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'fiery_bolts'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'fiery_bolts'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'npc_points'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'npc_points'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'sawblade_trail'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'sawblade_trail'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'silent_hill'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'silent_hill'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'weapon_effects'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'weapon_effects'.
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Loading plugin 'weapon_manger'...
2020-09-25 19:05:46 - sp   -   MESSAGE   [SP] Successfully loaded plugin 'weapon_manger'.
2020-09-25 19:10:26 - sp   -   EXCEPTION   
[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\plugins\fiery_bolts\fiery_bolts.py", line 55, in on_entity_deleted
    bolts.pop(index).detach_effects()
  File "..\addons\source-python\plugins\fiery_bolts\fiery_bolts.py", line 151, in detach_effects
    self.trail.clear_parent()
  File "..\addons\source-python\packages\source-python\entities\_base.py", line 216, in __getattr__
    value = getattr(instance, attr)
  File "..\addons\source-python\packages\source-python\entities\classes.py", line 542, in fget
    return InputFunction(desc, make_object(BaseEntity, pointer))

RuntimeError: Access violation - no RTTI data!


I dont know what it is, i am thinking it might be the kill of a bot or the npc's. I just cant figer it out.


You get this error because the trail has been removed before the bolt it was parented to so its pointer has been freed at that point. Changing this:

Syntax: Select all

except AttributeError:


To:

Syntax: Select all

except (AttributeError, RuntimeError):


Should prevent this error. Clearing it from its parent when it is removed would be the best option though.
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: hl2dm crossbow arrows with a fire flame.

Postby daren adler » Sat Sep 26, 2020 2:48 am

OK :grin: , i will give it a try. Thank you :smile: -update- Works without errors now. :wink: Thank you. You guys are the reason i have these great plugins :cool: :cool: Stay kool and have a great weekend :smile:
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: hl2dm crossbow arrows with a fire flame.

Postby VinciT » Mon Sep 28, 2020 5:53 am

L'In20Cible wrote:You could simply override __missing__ to disable the factory:
Man.. I'm so used to using the OnEntityDeleted listener, I completely forgot that I could do that. Thanks for the tip!

L'In20Cible wrote:Clearing it from its parent when it is removed would be the best option though.
I'll add that in tomorrow. :tongue:
ImageImageImageImageImage
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: hl2dm crossbow arrows with a fire flame.

Postby L'In20Cible » Mon Sep 28, 2020 6:55 am

VinciT wrote:Man.. I'm so used to using the OnEntityDeleted listener

You will have to get unused to use it because you probably won't even use it anymore. :tongue:

Side note, I made the changes to EntityDictionary so that the factory can be set to None to explicitly disable it:

Syntax: Select all

from entities.dictionary import EntityDictionary

ents = EntityDictionary(None)
ents[0]

# KeyError: 0


And that no matter why the construction fails it always trigger a KeyError:

Syntax: Select all

from entities.dictionary import EntityDictionary

ents = EntityDictionary()
ents[123456789]

# KeyError: 'Conversion from "Index" (123456789) to "BaseEntity" failed.'

ents = EntityDictionary(lambda index: 1/0)
ents[0]

# KeyError: 'division by zero'


So that if retrieving a key fails the exception can be uniformly caught without going on a case-by-case basis when using custom factory class or functions.
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: hl2dm crossbow arrows with a fire flame.

Postby daren adler » Mon Sep 28, 2020 7:26 am

I did find out that if shot by arrow and you are still on fire before you die, then when you re-spawn, you are still on fire and kills you again and again, dont do it everytime, just 2 or 3 times a map. Anyway to fix that?
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: hl2dm crossbow arrows with a fire flame.

Postby VinciT » Tue Sep 29, 2020 1:52 am

L'In20Cible wrote:Side note, I made the changes to EntityDictionary so that the factory can be set to None to explicitly disable it:
Awesome! Guess I'll go ahead and start using that straight away. :smile:

daren adler wrote:I did find out that if shot by arrow and you are still on fire before you die, then when you re-spawn, you are still on fire and kills you again and again, dont do it everytime, just 2 or 3 times a map. Anyway to fix that?
I've updated the plugin in my original post to include L'In20Cible's suggestions, a fix for the particle effect (the instance wasn't being stored in self.flame), as well as a fix for the burning issue. Make sure to update to the latest Source.Python version - as the plugin requires the recent EntityDictionary changes.
ImageImageImageImageImage
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: hl2dm crossbow arrows with a fire flame.

Postby L'In20Cible » Tue Sep 29, 2020 4:20 am

VinciT wrote:Awesome! Guess I'll go ahead and start using that straight away. :smile:

Something else that was added is the following from:

VinciT wrote:

Syntax: Select all

@OnEntityCreated
def on_entity_created(base_entity):
"""Called when an entity gets created."""
try:
index = base_entity.index
except ValueError:
return

if 'crossbow_bolt' in base_entity.classname:
# Create a Bolt instance.
bolt = Bolt(index)
# Some properties are still uninitialized - delay the creation of the
# flame effect for a single frame.
bolt.delay(0, bolt.flame_on)

To:

Syntax: Select all

@OnNetworkedEntityCreated
def on_networked_entity_created(entity):
"""Called when a networked entity gets created."""
if 'crossbow_bolt' not in entity.classname:
return

# Create a Bolt instance.
bolt = Bolt(entity.index)
# Some properties are still uninitialized - delay the creation of the
# flame effect for a single frame.
bolt.delay(0, bolt.flame_on)

Not only it is shorter, but faster due to the internal caching. :smile:

Syntax: Select all

from time import time

from entities.entity import BaseEntity
from entities.entity import Entity
from listeners import OnNetworkedEntityCreated

t = time()
for i in range(1000000):
index = BaseEntity(0).index
print(time() - t)

t = time()
for i in range(1000000):
index = Entity(0).index
print(time() - t)

"""
21.112711906433105
0.706554651260376
"""
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: hl2dm crossbow arrows with a fire flame.

Postby VinciT » Tue Sep 29, 2020 4:30 am

L'In20Cible wrote:Not only it is shorter, but faster due to the internal caching. :smile:
Jeez.. look at those numbers! Amazing stuff L'In20Cible! Plugin has been supercharged in the original post. :tongue:
ImageImageImageImageImage
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: hl2dm crossbow arrows with a fire flame.

Postby daren adler » Tue Sep 29, 2020 7:27 am

Nice, works great,,you scripters do a very good job. Thank you.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: hl2dm crossbow arrows with a fire flame.

Postby L'In20Cible » Tue Sep 29, 2020 12:18 pm

VinciT wrote:Jeez.. look at those numbers! Amazing stuff L'In20Cible! Plugin has been supercharged in the original post. :tongue:

Well, that code alone is likely to have similar performance, but sure is a global optimization for when there are many plugins using them. :tongue:

About the following:

Syntax: Select all

# Some properties are still uninitialized - delay the creation of the
# flame effect for a single frame.
bolt.delay(0, bolt.flame_on)


Perhaps they are set when the entity actually spawns as opposed to being created?

daren adler wrote:you scripters do a very good job

I deserve no credit here; I'm just an annoying critic. :wink:
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: hl2dm crossbow arrows with a fire flame.

Postby VinciT » Thu Oct 01, 2020 6:00 am

L'In20Cible wrote:Perhaps they are set when the entity actually spawns as opposed to being created?
Just tested it - the OnEntitySpawned/OnNetworkedEntitySpawned listener doesn't even get called when a crossbow_bolt spawns. Looking back at some requests I've done, I'm pretty sure I've had to use the single frame delay even with the OnEntitySpawned listener, at least when I needed to modify certain properties.

Sometimes it works without the delay, most of the time it doesn't. It's really inconsistent.

L'In20Cible wrote:I deserve no credit here; I'm just an annoying critic. :wink:
A critic - sure, but not an annoying one. You've helped me improve both my programming and problem solving skills a ton. I'm very grateful for that, and I always look forward to your suggestions and pointers. :grin:
ImageImageImageImageImage
User avatar
daren adler
Senior Member
Posts: 328
Joined: Sat May 18, 2019 7:42 pm

Re: hl2dm crossbow arrows with a fire flame.

Postby daren adler » Sat Oct 10, 2020 10:15 pm

I get this now

Code: Select all

2020-10-10 16:26:58 - sp   -   EXCEPTION   
[SP] Caught an Exception:
Traceback (most recent call last):
  File "..\addons\source-python\packages\source-python\entities\dictionary.py", line 135, in _on_networked_entity_deleted
    self.on_automatically_removed(index)
  File "..\addons\source-python\plugins\fiery_bolts\fiery_bolts.py", line 30, in on_automatically_removed
    self[index].detach_effects()
  File "..\addons\source-python\plugins\fiery_bolts\fiery_bolts.py", line 185, in detach_effects
    self.trail.clear_parent()
  File "..\addons\source-python\packages\source-python\entities\_base.py", line 216, in __getattr__
    value = getattr(instance, attr)
  File "..\addons\source-python\packages\source-python\entities\classes.py", line 542, in fget
    return InputFunction(desc, make_object(BaseEntity, pointer))

Return to “Plugin Requests”

Who is online

Users browsing this forum: No registered users and 11 guests