[HL2:DM] Crossbow

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

Please request only one plugin per thread.
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

[HL2:DM] Crossbow

Postby Painkiller » Mon Apr 13, 2020 9:00 am

Hello SourcePython Team and Community,

could somebody turn that into SP for me?

It causes the file to make an orange circle at the point of impact, which lights up and flashes.

Syntax: Select all

event event_bullet_impact
{
es_xset vector2 0
es_xset vector1 0
es_createvectorstring vector1 event_var(x) event_var(y) event_var(z)
es est_effect_18 #a 0 server_var(vector1) 255 88 00 08 200 100 150
}


I find this:

Syntax: Select all

import spe
import es

from spe import HookAction
from spe import HookType
from spe import Conventions

PATH_RES = 'addons/eventscripts/custom_events/custom_events.res'

def load():
es.loadevents('declare', PATH_RES)
es.loadevents(PATH_RES)
spe.hookFunction(FUNC, 'piS)v', Conventions.CDECL, HookType.Pre,
preHook)

def unload():
spe.unHookFunction(FUNC, HookType.Pre, preHook)

def es_map_start(event_var):
es.loadevents(PATH_RES)


#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#>>>>>>>>>> Bullet Impact
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# event_var['x']
# event_var['y']
# event_var['z']

FUNC = spe.findSymbol('_Z16UTIL_ImpactTraceP10CGameTraceiPKc')

def preHook(args):
x = spe.makeObject('Vector', args[0] + 12)
es.event('initialize', "event_bullet_impact")
es.event('setfloat', "event_bullet_impact", "x", x.x)
es.event('setfloat', "event_bullet_impact", "y", x.y)
es.event('setfloat', "event_bullet_impact", "z", x.z)
es.event('fire', "event_bullet_impact")
return (HookAction.Continue, 0)


#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#>>>>>>>>>> Hitgroups
#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# event_var['hitgroup']
# event_var['attacker']
# event_var['victim']
# event_var['weapon']
# event_var['health']

OFFSET_HITGROUP = 1712 if spe.platform == 'nt' else 1732

def player_hurt(ev):
player = spe.getPlayer(int(ev['userid']))
hitgroup = spe.getLocVal('i', player + OFFSET_HITGROUP)
fire_event(hitgroup, ev['userid'], ev['attacker'], ev['es_attackerweapon'], ev['health'])

def fire_event(hitgroup, userid, attacker, weapon, health):
es.event('initialize', "event_hitgroup")
es.event('setint', "event_hitgroup", "hitgroup", hitgroup)
es.event('setint', "event_hitgroup", "attacker", attacker)
es.event('setint', "event_hitgroup", "victim", userid)
es.event('setstring', "event_hitgroup", "weapon", weapon)
es.event('setint', "event_hitgroup", "health", health)
es.event('fire', "event_hitgroup")
#http://www.eventscripts.com/pages/Hit_Groups


Code: Select all

"custom_events"
{
   "event_bullet_impact"
   {
      "x"   "float"
      "y"   "float"
      "z"   "float"
   }

   "event_hitgroup"
   {
      "hitgroup"   "int"
      "attacker"   "int"
      "victim"     "int"
      "weapon"     "string"
      "health"     "int"
   }
}


Thanks in advance.
Last edited by Painkiller on Fri Apr 17, 2020 9:49 am, edited 1 time in total.
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [HL2:DM] Crossbow

Postby VinciT » Mon Apr 13, 2020 9:17 pm

I'm assuming you want the effect to appear when the crossbow bolt hits something, give this a shot:

Syntax: Select all

# ../bolt_impact/bolt_impact.py

# Source.Python
from colors import Color
from effects.base import TempEntity
from entities.entity import BaseEntity
from entities.hooks import EntityPreHook, EntityCondition
from filters.recipients import RecipientFilter


EFFECT_COLOR = Color(255, 88, 0)


@EntityPreHook(
EntityCondition.equals_entity_classname('crossbow_bolt'), 'start_touch')
def bolt_start_touch_pre(stack_data):
base_entity = BaseEntity._obj(stack_data[0])

if 'crossbow_bolt' in base_entity.classname:
create_dynamic_light(
origin=base_entity.origin,
color=EFFECT_COLOR,
radius=200,
life_time=3,
exponent=8,
decay=150
)


def create_dynamic_light(origin, color, radius, life_time, **kwargs):
"""Creates a dynamic light effect at the specified origin.

Args:
origin (Vector): Spawn position of the effect.
color (Color): Color of the effect.
radius (float): How wide the glow is.
life_time (float): How long should the effect last? (in seconds)
**kwargs: Additional attributes.
"""
light = TempEntity('Dynamic Light')
light.origin = origin
light.color = color
light.radius = radius
light.life_time = life_time
# Strength of the glow.
light.exponent = kwargs.get('exponent', 0)
# By how much the radius is lowered each second.
light.decay = kwargs.get('decay', radius / life_time)
# Send the TempEntity to everyone if 'recipients' weren't specified.
light.create(kwargs.get('recipients', RecipientFilter()))
ImageImageImageImageImage
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: [HL2:DM] Crossbow

Postby Painkiller » Tue Apr 14, 2020 2:43 pm

Works good thanks.
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: [HL2:DM] Crossbow

Postby Painkiller » Wed Apr 15, 2020 11:53 am

It's certainly worth a smile, I tried this for the combine_ball.

Is this approach right for future weapons like , grenade_frag?

Syntax: Select all

# ../bolt_impact/bolt_impact.py

# Source.Python
from colors import Color
from effects.base import TempEntity
from entities.entity import BaseEntity
from entities.hooks import EntityPreHook, EntityCondition
from filters.recipients import RecipientFilter


EFFECT_COLOR = Color(255, 88, 0)


@EntityPreHook(
EntityCondition.equals_entity_classname('combine_ball'), 'start_touch')
def combine_ball_start_touch_pre(stack_data):
base_entity = BaseEntity._obj(stack_data[0])

if 'combine_ball' in base_entity.classname:
create_dynamic_light(
origin=base_entity.origin,
color=EFFECT_COLOR,
radius=200,
life_time=3,
exponent=8,
decay=150
)


def create_dynamic_light(origin, color, radius, life_time, **kwargs):
"""Creates a dynamic light effect at the specified origin.

Args:
origin (Vector): Spawn position of the effect.
color (Color): Color of the effect.
radius (float): How wide the glow is.
life_time (float): How long should the effect last? (in seconds)
**kwargs: Additional attributes.
"""
light = TempEntity('Dynamic Light')
light.origin = origin
light.color = color
light.radius = radius
light.life_time = life_time
# Strength of the glow.
light.exponent = kwargs.get('exponent', 0)
# By how much the radius is lowered each second.
light.decay = kwargs.get('decay', radius / life_time)
# Send the TempEntity to everyone if 'recipients' weren't specified.
light.create(kwargs.get('recipients', RecipientFilter()))
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [HL2:DM] Crossbow

Postby VinciT » Wed Apr 15, 2020 6:11 pm

That would work for the npc_grenade_frag, but for the prop_combine_ball, I think we'd need to hook either VPhysicsCollision() or DispatchEffect().
Since DispatchEffect is already available to us, try adding this to the script:

Syntax: Select all

from effects.hooks import TempEntityPreHook
from stringtables import string_tables


@TempEntityPreHook('EffectDispatch')
def effect_dispatch_pre(temp_entity, recipient_filter):
# Get the name of the effect.
effect_name = string_tables.EffectDispatch[temp_entity.effect_name_index]

# Did the 'prop_combine_ball' bounce?
if 'cball_bounce' in effect_name:
# Delay the effect by a single frame, otherwise the server will crash!
temp_entity.entity.delay(0, create_dynamic_light,
(temp_entity.origin, Color(50, 150, 255), 200, 3, 8, 150))

# Or did it explode?
if 'cball_explode' in effect_name:
pass
ImageImageImageImageImage
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: [HL2:DM] Crossbow

Postby Painkiller » Wed Apr 15, 2020 8:59 pm

There comes this error

Code: Select all

[SP] Caught an Exception:
Traceback (most recent call last):
  File "../addons/source-python/packages/source-python/listeners/tick.py", line 80, in _tick
    self.pop(0).execute()
  File "../addons/source-python/packages/source-python/listeners/tick.py", line 161, in execute
    return self.callback(*self.args, **self.kwargs)
  File "../addons/source-python/packages/source-python/entities/_base.py", line 844, in _callback
    callback(*args, **kwargs)

TypeError: create_dynamic_light() takes 4 positional arguments but 6 were given


I tested that.

Syntax: Select all

# ../bolt_impact/bolt_impact.py

# Source.Python
from colors import Color
from effects.base import TempEntity
from entities.entity import BaseEntity
from entities.hooks import EntityPreHook, EntityCondition
from filters.recipients import RecipientFilter
from effects.hooks import TempEntityPreHook
from stringtables import string_tables


EFFECT_COLOR = Color(255, 88, 0)


@TempEntityPreHook('EffectDispatch')
def effect_dispatch_pre(temp_entity, recipient_filter):
# Get the name of the effect.
effect_name = string_tables.EffectDispatch[temp_entity.effect_name_index]

# Did the 'prop_combine_ball' bounce?
if 'cball_bounce' in effect_name:
# Delay the effect by a single frame, otherwise the server will crash!
temp_entity.entity.delay(0, create_dynamic_light,
(temp_entity.origin, Color(50, 150, 255), 200, 3, 8, 150))

# Or did it explode?
if 'cball_explode' in effect_name:
pass


@EntityPreHook(
EntityCondition.equals_entity_classname('crossbow_bolt'), 'start_touch')
def bolt_start_touch_pre(stack_data):
base_entity = BaseEntity._obj(stack_data[0])

if 'crossbow_bolt' in base_entity.classname:
create_dynamic_light(
origin=base_entity.origin,
color=EFFECT_COLOR,
radius=200,
life_time=3,
exponent=8,
decay=150
)


def create_dynamic_light(origin, color, radius, life_time, **kwargs):
"""Creates a dynamic light effect at the specified origin.

Args:
origin (Vector): Spawn position of the effect.
color (Color): Color of the effect.
radius (float): How wide the glow is.
life_time (float): How long should the effect last? (in seconds)
**kwargs: Additional attributes.
"""
light = TempEntity('Dynamic Light')
light.origin = origin
light.color = color
light.radius = radius
light.life_time = life_time
# Strength of the glow.
light.exponent = kwargs.get('exponent', 0)
# By how much the radius is lowered each second.
light.decay = kwargs.get('decay', radius / life_time)
# Send the TempEntity to everyone if 'recipients' weren't specified.
light.create(kwargs.get('recipients', RecipientFilter()))
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [HL2:DM] Crossbow

Postby VinciT » Wed Apr 15, 2020 10:57 pm

Whoops, my bad. Change the create_dynamic_light() function to this:

Syntax: Select all

def create_dynamic_light(
origin, color, radius, life_time, exponent, decay,
recipients=RecipientFilter()):
"""Creates a dynamic light effect at the specified origin.

Args:
origin (Vector): Spawn position of the effect.
color (Color): Color of the effect.
radius (float): How wide the glow is.
life_time (float): How long should the effect last? (in seconds)
exponent (int): Strength of the glow.
decay (float): By how much the radius is lowered each second.
recipients (RecipientFilter): Players that should see the effect.
"""
light = TempEntity('Dynamic Light')
light.origin = origin
light.color = color
light.radius = radius
light.life_time = life_time
light.exponent = exponent
light.decay = decay
light.create(recipients)
ImageImageImageImageImage
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: [HL2:DM] Crossbow

Postby Painkiller » Thu Apr 16, 2020 9:55 am

Axis One Nothing works there.
There is also no error output.

This is my Test script.

Syntax: Select all

# ../bolt_impact/bolt_impact.py

# Source.Python
from colors import Color
from effects.base import TempEntity
from entities.entity import BaseEntity
from entities.hooks import EntityPreHook, EntityCondition
from filters.recipients import RecipientFilter
from effects.hooks import TempEntityPreHook
from stringtables import string_tables


@TempEntityPreHook('EffectDispatch')
def effect_dispatch_pre(temp_entity, recipient_filter):
# Get the name of the effect.
effect_name = string_tables.EffectDispatch[temp_entity.effect_name_index]

# Did the 'prop_combine_ball' bounce?
if 'cball_bounce' in effect_name:
# Delay the effect by a single frame, otherwise the server will crash!
temp_entity.entity.delay(0, create_dynamic_light,
(temp_entity.origin, Color(50, 150, 255), 200, 3, 8, 150))

# Or did it explode?
if 'cball_explode' in effect_name:
pass


EFFECT_COLOR = Color(255, 88, 0)


def create_dynamic_light(
origin, color, radius, life_time, exponent, decay,
recipients=RecipientFilter()):
"""Creates a dynamic light effect at the specified origin.

Args:
origin (Vector): Spawn position of the effect.
color (Color): Color of the effect.
radius (float): How wide the glow is.
life_time (float): How long should the effect last? (in seconds)
exponent (int): Strength of the glow.
decay (float): By how much the radius is lowered each second.
recipients (RecipientFilter): Players that should see the effect.
"""
light = TempEntity('Dynamic Light')
light.origin = origin
light.color = color
light.radius = radius
light.life_time = life_time
light.exponent = exponent
light.decay = decay
light.create(recipients)


That would be a setting variation.

Code: Select all

   }

   "prop_combine_ball"
   {
      "light"   "1"
      "light_color" "000 191 255"
      "light_distance" "50"
      "light_brightness" "5"
      "light_spotlight_radius" "25.0"
   }


Thanks in Advance
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [HL2:DM] Crossbow

Postby VinciT » Thu Apr 16, 2020 6:39 pm

That's strange. Here's the script I used:

Syntax: Select all

# ../ball_impact/ball_impact.py

# Source.Python
from colors import Color
from effects.base import TempEntity
from effects.hooks import TempEntityPreHook
from filters.recipients import RecipientFilter
from stringtables import string_tables


EFFECT_COLOR = Color(0, 191, 255)


@TempEntityPreHook('EffectDispatch')
def effect_dispatch_pre(temp_entity, recipient_filter):
# Get the name of the effect.
effect_name = string_tables.EffectDispatch[temp_entity.effect_name_index]

# Did the 'prop_combine_ball' bounce?
if 'cball_bounce' in effect_name:
# Delay the effect by a single frame, otherwise the server will crash!
temp_entity.entity.delay(0, create_dynamic_light,
(temp_entity.origin, EFFECT_COLOR, 200, 3, 8, 150))

# Or did it explode?
if 'cball_explode' in effect_name:
pass


def create_dynamic_light(
origin, color, radius, life_time, exponent, decay, *recipients):
"""Creates a dynamic light effect at the specified origin.

Args:
origin (Vector): Spawn position of the effect.
color (Color): Color of the effect.
radius (float): How wide the glow is.
life_time (float): How long should the effect last? (in seconds)
exponent (int): Strength of the glow.
decay (float): By how much the radius is lowered each second.
recipients (RecipientFilter): Players that should see the effect.
"""
light = TempEntity('Dynamic Light')
light.origin = origin
light.color = color
light.radius = radius
light.life_time = life_time
light.exponent = exponent
light.decay = decay
light.create(RecipientFilter(*recipients))


Painkiller wrote:That would be a setting variation.

Code: Select all

   }

   "prop_combine_ball"
   {
      "light"   "1"
      "light_color" "000 191 255"
      "light_distance" "50"
      "light_brightness" "5"
      "light_spotlight_radius" "25.0"
   }


Thanks in Advance
These settings look like they belong to a different entity/effect, maybe a point_spotlight? What do you want to appear when the combine ball bounces?
Last edited by VinciT on Fri Apr 17, 2020 2:33 pm, edited 1 time in total.
ImageImageImageImageImage
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: [HL2:DM] Crossbow

Postby Painkiller » Fri Apr 17, 2020 6:53 am

I used her script, it doesn't work for me.
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [HL2:DM] Crossbow

Postby L'In20Cible » Fri Apr 17, 2020 9:12 am

The problem is there:

VinciT wrote:

Syntax: Select all

recipients=RecipientFilter()):


Only the players that are connected at the time the plugin was loaded will ever see the effect (nobody if it was loaded on server start).
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [HL2:DM] Crossbow

Postby VinciT » Fri Apr 17, 2020 2:34 pm

L'In20Cible wrote:The problem is there:

VinciT wrote:

Syntax: Select all

recipients=RecipientFilter()):


Only the players that are connected at the time the plugin was loaded will ever see the effect (nobody if it was loaded on server start).
Oooh, so default arguments are only evaluated once? Good to know.
I've updated the code in my previous post.
ImageImageImageImageImage
User avatar
satoon101
Project Leader
Posts: 2697
Joined: Sat Jul 07, 2012 1:59 am

Re: [HL2:DM] Crossbow

Postby satoon101 » Fri Apr 17, 2020 2:55 pm

For future reference in regards to default arguments in Python:
https://docs.quantifiedcode.com/python- ... ument.html
Image
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: [HL2:DM] Crossbow

Postby Painkiller » Fri Apr 17, 2020 3:49 pm

So far so good, I need some more help.

I'd like to apply it to grenades, like health kits and suits.
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [HL2:DM] Crossbow

Postby VinciT » Fri Apr 17, 2020 5:34 pm

satoon101 wrote:For future reference in regards to default arguments in Python:
https://docs.quantifiedcode.com/python- ... ument.html
Thank you for the link. Can't believe I hadn't seen this site before.

Painkiller wrote:So far so good, I need some more help.
I'd like to apply it to grenades, like health kits and suits.
Alright so, do you want the dynamic light to be on these entities the whole time? Like, when the player throws the grenade, should it glow from the moment it spawns? Same goes for the other entities (item_battery, item_healthkit, item_healthvial).
ImageImageImageImageImage
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: [HL2:DM] Crossbow

Postby Painkiller » Fri Apr 17, 2020 10:18 pm

Permanent glow: item_battery, item_healthkit, item_healthvial

grenades maybe only when touches walls and floors
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [HL2:DM] Crossbow

Postby VinciT » Tue Apr 21, 2020 6:40 pm

Update to the latest version of SP to receive the needed offsets and try this:

Syntax: Select all

# ../lights/lights.py

# Source.Python
from colors import Color
from effects.base import TempEntity
from effects.hooks import TempEntityPreHook
from entities.entity import Entity, BaseEntity
from entities.hooks import EntityPreHook, EntityCondition
from filters.recipients import RecipientFilter
from filters.entities import BaseEntityIter
from listeners import OnEntityOutput, OnEntitySpawned, OnEntityDeleted
from mathlib import QAngle
from stringtables import string_tables


# Colors when the 'prop_combine_ball' bounces and explodes.
COLOR_BALL_BOUNCE = Color(0, 191, 255)
COLOR_BALL_EXPLODE = Color(170, 0, 255)
# Color when the 'crossbow_bolt' bounces.
COLOR_BOLT_BOUNCE = Color(255, 88, 0)
# Color when the 'npc_grenade_frag' bounces.
COLOR_FRAG_BOUNCE = Color(0, 255, 88)

# How wide should the 'point_spotlight' beam be?
SPOTLIGHT_DEFAULT_WIDTH = 20
# How tall should the 'point_spotlight' beam be?
SPOTLIGHT_DEFAULT_LENGTH = 300


item_colors = {
'item_battery': Color(255, 255, 25),
'item_healthkit': Color(25, 255, 55),
'item_healthvial': Color(25, 255, 55)
}

# Entities for which we hooked 'start_touch', along with the effect arguments.
start_touch_entities = {
'crossbow_bolt': (COLOR_BOLT_BOUNCE, 200, 3, 8, 150),
'npc_grenade_frag': (COLOR_FRAG_BOUNCE, 100, 3, 8, 50)
}


spotlight_pairs = {}
# Angle to make the 'point_spotlight' point upwards.
SPOTLIGHT_ANGLE = QAngle(-90, 0, 0)


def load():
"""Called when the plugin is loaded."""
# In case of a late plugin load, find the items that need spotlights.
for base_entity in BaseEntityIter(item_colors.keys()):
create_item_spotlight(
base_entity.classname, base_entity.index, base_entity.origin)


def unload():
"""Called when the plugin is unloaded."""
# Go through all the 'point_spotlight' entities and remove them.
for spotlight in spotlight_pairs.values():
spotlight.remove()


# =============================================================================
# >> DYNAMIC_LIGHT: crossbow_bolt, prop_combine_ball, npc_grenade_frag
# =============================================================================
@TempEntityPreHook('EffectDispatch')
def effect_dispatch_pre(temp_entity, recipient_filter):
# Get the name of the effect.
effect_name = string_tables.EffectDispatch[temp_entity.effect_name_index]

# Did the 'prop_combine_ball' bounce?
if 'cball_bounce' in effect_name:
# Delay the effect by a single frame, otherwise the server will crash!
temp_entity.entity.delay(0, create_dynamic_light,
(temp_entity.origin, COLOR_BALL_BOUNCE, 200, 3, 8, 150))

# Or did it explode?
if 'cball_explode' in effect_name:
temp_entity.entity.delay(0, create_dynamic_light,
(temp_entity.origin, COLOR_BALL_EXPLODE, 600, 1, 8, 600))


@EntityPreHook(
EntityCondition.equals_entity_classname('crossbow_bolt'), 'start_touch')
def bolt_touch_pre(stack_data):
entity = Entity._obj(stack_data[0])

# Is this an entity we're looking for? (crossbow_bolt, npc_grenade_frag)
if entity.classname in start_touch_entities:
create_dynamic_light(
entity.origin, *start_touch_entities[entity.classname])

parent = entity.parent
if parent is not None:
parent.start_touch.skip_hooks(stack_data[1])
return False


def create_dynamic_light(
origin, color, radius, life_time, exponent, decay, *recipients):
"""Creates a dynamic light effect at the specified origin.

Args:
origin (Vector): Spawn position of the effect.
color (Color): Color of the effect.
radius (float): How wide the glow is.
life_time (float): How long should the effect last? (in seconds)
exponent (int): Strength of the glow.
decay (float): By how much the radius is lowered each second.
recipients (RecipientFilter): Players that should see the effect.
"""
light = TempEntity('Dynamic Light')
light.origin = origin
light.color = color
light.radius = radius
light.life_time = life_time
light.exponent = exponent
light.decay = decay
light.create(RecipientFilter())


# =============================================================================
# >> POINT_SPOTLIGHT: item_battery, item_healthkit, item_healthvial
# =============================================================================
class Spotlight(Entity):
"""Modified Entity class for properly removing a 'point_spotlight'."""
caching = True

def remove(self):
"""Turns off the 'point_spotlight' before removing it."""
self.call_input('LightOff')
super().remove()


def create_spotlight(origin, color, **kwargs):
"""Creates a 'point_spotlight' at the specified origin.

Args:
origin (Vector): Spawn position of the 'point_spotlight'.
color (Color): Color of the light.
**kwargs: Additional keywords arguments.
"""
spotlight = Spotlight.create('point_spotlight')
spotlight.origin = origin
spotlight.angles = kwargs.get('angle', SPOTLIGHT_ANGLE)
spotlight.color = color

spotlight.set_key_value_bool('disablereceiveshadows', False)
spotlight.set_key_value_float('HDRColorScale', 1)
spotlight.set_key_value_int('rendermode', 0)
spotlight.set_key_value_int('renderamt', 0)
spotlight.set_key_value_int('renderfx', 0)
spotlight.set_key_value_int(
'spotlightwidth', kwargs.get('width', SPOTLIGHT_DEFAULT_WIDTH))
spotlight.set_key_value_int(
'spotlightlength', kwargs.get('length', SPOTLIGHT_DEFAULT_LENGTH))

# Make sure the 'point_spotlight' spawns turned on.
spotlight.spawn_flags = 1
spotlight.spawn()
return spotlight


def create_item_spotlight(classname, index, origin):
# Is there a color set for this item?
if classname in item_colors:
spotlight = create_spotlight(origin, item_colors[classname])
# Store the 'point_spotlight' instance in a dictionary, but tie it to
# the index of the specified item.
spotlight_pairs[index] = spotlight


@OnEntityOutput
def on_entity_output(output, activator, caller, value, delay):
# Items (item_battery, item_healthkit) send out 'OnPlayerTouch' whenever
# they are applied to a player.
if output == 'OnPlayerTouch':
index = caller.index

# Is there a 'point_spotlight' for this item?
if index in spotlight_pairs:
spotlight = spotlight_pairs[index]
# Delay the removal by a single frame to avoid crashing the server.
spotlight.delay(0, spotlight.remove)
# Remove the Spotlight instance from the dictionary.
del spotlight_pairs[index]


@EntityPreHook(
EntityCondition.equals_entity_classname('item_battery'), 'materialize')
def item_materialize_pre(stack_data):
"""Called when an item (item_battery, item_healthkit) becomes enabled."""
base_entity = BaseEntity._obj(stack_data[0])
create_item_spotlight(
base_entity.classname, base_entity.index, base_entity.origin)


@OnEntitySpawned
def on_entity_spawned(base_entity):
"""Called when an entity is spawned."""
try:
index = base_entity.index
except ValueError:
return

create_item_spotlight(
base_entity.classname, base_entity.index, base_entity.origin)


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

# Does this entity have a 'point_spotlight' tied to it?
if index in spotlight_pairs:
spotlight_pairs[index].remove()
del spotlight_pairs[index]

Image Image
Last edited by VinciT on Thu Apr 23, 2020 4:00 am, edited 1 time in total.
ImageImageImageImageImage
User avatar
Painkiller
Senior Member
Posts: 725
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Re: [HL2:DM] Crossbow

Postby Painkiller » Tue Apr 21, 2020 9:35 pm

Okay, I tested it.

I noticed that some medications are blue instead of green, and some suit kits are yellow instead of blue.

That grenade is not working at all.

Unfortunately I noticed the error under Linux when using an elevator which crashes the server with the plugin.

I gave you something in the first post that you can fix this.

Made by L'In20Cible

Syntax: Select all

from memory import *
from memory.hooks import *

@PreHook(find_binary('server')['_ZN13CCrossbowBolt9BoltTouchEP11CBaseEntity'].make_function(
Convention.THISCALL, (DataType.POINTER, DataType.POINTER), DataType.VOID))
def pre_bolt_touch(stack_data):
base_entity = BaseEntity._obj(stack_data[0])


If you add this in the script, the server should not crash under Linux anymore.

Thanks in Advance
User avatar
L'In20Cible
Project Leader
Posts: 1533
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Re: [HL2:DM] Crossbow

Postby L'In20Cible » Wed Apr 22, 2020 6:41 am

Some information was left out so I will clarify. First of all, the server do not crash but freeze due to the post handler being called infinitely after a recursive call. Basically, the map mentioned above is using a trigger_multiple that triggers a func_door that is parented to a solid prop_dynamic used to lift the players up and down once they step onto it. The issue arise when a player is touching the prop_dynamic, which internally forward the call to the parented func_door. DynamicHooks relies on the ESP register to be unique, but it appears to be re-used for the parent's call, which cause the original frame to never be resumed. This can be seen with the following code on any game/platform:

Syntax: Select all

from time import sleep
from entities.entity import Entity
from entities.hooks import EntityCondition
from entities.hooks import EntityPreHook
from entities.hooks import EntityPostHook
from memory import make_object
from players.entity import Player

entity = Entity.create('prop_dynamic')
entity.target_name = 'CHILD!'

parent = Entity.create('prop_dynamic')
parent.target_name = 'PARENT!'
entity.set_parent(parent)

@EntityPreHook(EntityCondition.equals_entity_classname('prop_dynamic'), 'start_touch')
def pre_start_touch(stack_data):
print('PRE:', stack_data.registers.esp.address.address, make_object(Entity, stack_data[0]).target_name)

@EntityPostHook(EntityCondition.equals_entity_classname('prop_dynamic'), 'start_touch')
def post_start_touch(stack_data, return_value):
print('POST:', stack_data.registers.esp.address.address, make_object(Entity, stack_data[0]).target_name)
sleep(1)

entity.start_touch(Player(1))

Which results into:

Code: Select all

PRE: 439609808 CHILD!
PRE: 439609808 PARENT!
POST: 439609808 PARENT!
POST: 439609808 PARENT!
POST: 439609808 PARENT!
POST: 439609808 PARENT!
...


I suggested to hook CCrossbowBolt::BoltTouch as a workaround until it can be looked further into, but I would rather suggest the following instead:

Syntax: Select all

@EntityPreHook(
EntityCondition.equals_entity_classname('crossbow_bolt'), 'start_touch')
def bolt_start_touch_pre(stack_data):
entity = Entity._obj(stack_data[0])

# Is this an entity we're looking for? (crossbow_bolt, npc_grenade_frag)
if entity.classname in start_touch_entities:
create_dynamic_light(
entity.origin, *start_touch_entities[entity.classname])

parent = entity.parent
if parent is not None:
parent.start_touch.skip_hooks(stack_data[1])
return False

Pretty much the same concept as what was suggested here for CBaseEntity::Touch.
User avatar
VinciT
Senior Member
Posts: 331
Joined: Thu Dec 18, 2014 2:41 am

Re: [HL2:DM] Crossbow

Postby VinciT » Thu Apr 23, 2020 4:02 am

Painkiller wrote:I noticed that some medications are blue instead of green, and some suit kits are yellow instead of blue.
You can change the spotlight colors in the item_colors dictionary:

Syntax: Select all

item_colors = {
'item_battery': Color(255, 255, 25),
'item_healthkit': Color(25, 255, 55),
'item_healthvial': Color(25, 255, 55)
}
Pick a color you like, copy the RGB value, and put it between the parentheses.
Painkiller wrote:That grenade is not working at all.
It appears that it only lights up when touching another entity (and not the world). I'd like to avoid using VPhysicsCollision() if at all possible, as it seems like it gets called quite often. What if the grenade pulsed the effect each second, and every time someone grabs or throws it, as well as when it explodes? Would that be okay?

L'In20Cible wrote:Some information was left out so I will clarify. First of all, the server do not crash but freeze due to the post handler being called infinitely after a recursive call. Basically, the map mentioned above is using a trigger_multiple that triggers a func_door that is parented to a solid prop_dynamic used to lift the players up and down once they step onto it. The issue arise when a player is touching the prop_dynamic, which internally forward the call to the parented func_door. DynamicHooks relies on the ESP register to be unique, but it appears to be re-used for the parent's call, which cause the original frame to never be resumed.
Ah.. So that is why you usually advise against touch hooks. Is there no way this can be adjusted within DynamicHooks? Maybe with a recursion limit?
L'In20Cible wrote:I suggested to hook CCrossbowBolt::BoltTouch as a workaround until it can be looked further into, but I would rather suggest the following instead:
Cheers for the fix, I've updated the code in my previous post.
ImageImageImageImageImage

Return to “Plugin Requests”

Who is online

Users browsing this forum: No registered users and 19 guests