Particle effects!

Post Python examples to help other users.
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Particle effects!

Postby L'In20Cible » Tue Apr 15, 2014 6:36 am

Syntax: Select all

from entities.entity import BaseEntity
from events import Event
from mathlib_c import Vector
from tick.delays import TickDelays
from tools_c import ServerTools
from stringtables_c import StringTables

@Event
def hegrenade_detonate(game_event):

# Create a particle system entity...
particle = BaseEntity(ServerTools.create_entity('info_particle_system'))

# Set its effect to an huge explosion...
particle.effect_name = 'bomb_explosion_huge'

# Set the origin of the particle...
particle.edict.set_key_value_vector('origin', Vector(*map(game_event.get_float, 'xyz')))

# Precache the particle and set its index...
particle.edict.set_prop_int('m_iEffectIndex',
StringTables.ParticleEffectNames.add_string('bomb_explosion_huge'))

# Start the particle effect...
particle.Start()

# Delete it later...
TickDelays.delay(3, particle.Kill)

This code will create a huge explosion where an hegrenade is detonating:

Image

Here is a dump of available particles for Counter-Strike: Source:

Code: Select all

Dumping particle list:
 0: mini_firework_flare
 1: achieved
 2: mini_fireworks
 3: blood_impact_red_01_goop
 4: blood_impact_red_01_droplets
 5: blood_impact_yellow_01
 6: blood_impact_red_01_smalldroplets
 7: blood_impact_green_01
 8: blood_impact_green_01_droplets
 9: blood_impact_green_01_chunk
 10: blood_impact_red_01
 11: blood_impact_red_01_mist
 12: blood_impact_red_01_chunk
 13: blood_impact_synth_01
 14: blood_impact_synth_01_droplets
 15: blood_impact_synth_01_armor
 16: blood_impact_synth_01_dust
 17: blood_impact_synth_01_spurt
 18: blood_impact_synth_01_short
 19: vomit_barnacle
 20: vomit_barnacle_b
 21: blood_spurt_synth_01
 22: blood_spurt_synth_01b
 23: blood_drip_synth_01
 24: blood_zombie_split
 25: blood_zombie_split_spray
 26: blood_zombie_split_spray_tiny
 27: blood_zombie_split_spray_tiny2
 28: blood_drip_synth_01b
 29: blood_drip_synth_01c
 30: blood_impact_synth_01_arc_parents
 31: blood_impact_synth_01_arc
 32: blood_impact_synth_01_arc2
 33: blood_impact_synth_01_arc3
 34: blood_impact_synth_01_arc4
 35: blood_impact_synth_01_arc_parent
 36: blood_impact_antlion_01
 37: blood_impact_zombie_01
 38: blood_antlionguard_injured_light
 39: blood_antlionguard_injured_light_tiny
 40: blood_antlionguard_injured_heavy_
 41: blood_antlionguard_injured_heavy_tiny
 42: blood_advisor_shrapnel_impact
 43: blood_advisor_shrapnel_spray_1
 44: blood_advisor_shrapnel_spray_2
 45: blood_advisor_shrapnel_spurt_1
 46: blood_advisor_shrapnel_spurt_2
 47: blood_advisor_puncture_withdraw
 48: blood_advisor_pierce_spray
 49: blood_advisor_pierce_spray_b
 50: blood_advisor_pierce_spray_c
 51: blood_advisor_puncture
 52: blood_impact_antlion_worker_01
 53: blood_impact_green_02_chunk
 54: blood_impact_green_02_droplets
 55: blood_impact_green_02_glow
 56: blood_antlionguard_injured_heavy
 57: smoke_medium_01
 58: fire_medium_01
 59: embers_medium_01
 60: fire_medium_01_glow
 61: fire_medium_02
 62: Smoke_medium_02b
 63: smoke_medium_02
 64: fire_small_01
 65: smoke_small_01
 66: smoke_small_01b
 67: fire_small_base
 68: embers_small_01
 69: embers_medium_03
 70: fire_small_02
 71: fire_small_flameouts
 72: fire_small_03
 73: fire_large_01
 74: embers_large_01
 75: smoke_large_01b
 76: smoke_large_01
 77: fire_medium_heatwave
 78: fire_medium_03
 79: fire_medium_base
 80: fire_medium_burst
 81: Smoke_medium_02b Version #2
 82: smoke_medium_02 Version #2
 83: fire_large_02
 84: fire_large_base
 85: fire_large_02_fillerb
 86: fire_large_02_filler
 87: smoke_large_02b
 88: embers_large_02
 89: smoke_large_02
 90: burning_gib_01_follower1
 91: burning_gib_01
 92: smoke_gib_01
 93: burning_gib_01b
 94: burning_gib_01_follower2
 95: burning_wood_01
 96: burning_wood_01c
 97: burning_wood_01b
 98: smoke_medium_02c
 99: smoke_medium_02d
 100: fire_medium_03_brownsmoke
 101: fire_jet_01_flame
 102: fire_jet_01
 103: burning_gib_01_drag
 104: fire_verysmall_01
 105: burning_engine_01
 106: smoke_burning_engine_01
 107: burning_engine_fire
 108: fire_medium_02_nosmoke
 109: explosion_huge
 110: explosion_huge_d
 111: explosion_huge_e
 112: explosion_huge_b
 113: explosion_huge_burning_chunks
 114: explosion_huge_smoking_chunks
 115: explosion_huge_c
 116: explosion_huge_k
 117: explosion_huge_g
 118: explosion_huge_j
 119: explosion_huge_h
 120: explosion_huge_i
 121: burning_vehicle
 122: smoke_exhaust_01a
 123: explosion_silo
 124: explosion_huge_flames
 125: explosion_huge_flames_b
 126: smoke_exhaust_01
 127: smoke_exhaust_01b
 128: explosion_huge_f
 129: env_fire_small
 130: env_fire_small_b
 131: env_embers_small
 132: env_fire_random_puff
 133: env_fire_medium_b
 134: env_fire_medium
 135: env_embers_medium
 136: env_fire_large
 137: env_fire_large_b
 138: env_embers_large
 139: env_fire_small_smoke
 140: env_fire_medium_smoke
 141: env_fire_large_smoke
 142: env_fire_large_smoke_b
 143: env_fire_medium_spread
 144: env_fire_medium_spread_b
 145: env_embers_medium_spread
 146: env_embers_small_spread
 147: env_fire_small_coverage
 148: env_fire_small_coverage_c
 149: env_fire_small_coverage_b
 150: env_fire_small_coverage_smoke
 151: env_fire_small_coverage_base
 152: env_fire_small_coverage_base_smoke
 153: env_fire_small_base
 154: env_fire_tiny
 155: env_embers_tiny
 156: env_fire_tiny_b
 157: env_fire_tiny_smoke
 158: bomb_explosion_huge
 159: burning_character_c
 160: burning_character_d
 161: burning_character_e
 162: burning_character_b
 163: burning_character
 164: water_splash_01
 165: water_splash_01_surface4
 166: water_splash_01_surface3
 167: water_splash_01_droplets
 168: water_splash_01_refract
 169: water_splash_01_surface1
 170: water_splash_01_surface2
 171: water_trail_medium
 172: water_trail_medium_b
 173: water_splash_02_vertical
 174: water_splash_02_droplets
 175: water_splash_02_refract
 176: water_splash_02_continuous
 177: water_splash_02_froth
 178: water_splash_02_froth2
 179: water_splash_02_surface2
 180: water_splash_02_surface4
 181: water_splash_02_animated
 182: water_splash_02_droplets Version #2
 183: water_impact_bubbles_1
 184: water_impact_bubbles_1d
 185: water_impact_bubbles_1b
 186: water_impact_bubbles_1c
 187: water_bubble_trail_1
 188: water_bubble_ambient_1
 189: water_gunk_1
 190: water_splash_leakypipe_silo
 191: water_splash_leakypipe_silo_froth2
 192: water_splash_leakypipe_vertical
 193: slime_splash_01
 194: slime_splash_01_reversed
 195: slime_splash_01_droplets
 196: slime_splash_01_surface
 197: slime_splash_02
 198: slime_splash_03
 199: water_splash_02
 200: water_splash_03
 201: water_foam_01
 202: water_foam_01d
 203: water_foam_01b
 204: water_foam_01c
 205: water_foam_line_long
 206: water_foam_line_longd
 207: water_foam_line_longb
 208: water_foam_line_longc
 209: water_foam_line_short
 210: water_foam_line_shortd
 211: water_foam_line_shortb
 212: water_foam_line_shortc
 213: muzzle_pistols
 214: muzzle_smgs
 215: muzzle_machinegun
 216: muzzle_rifles
 217: muzzle_shotguns
 218: muzzle_autorifles
 219: error
Tuck
Global Moderator
Posts: 205
Joined: Sat Jul 14, 2012 9:35 pm
Location: Copenhagen

Postby Tuck » Fri May 09, 2014 7:17 pm

from mathlib_c import Vector, has been moved i guess?

Does vector object not have .DistTo anymore?
-Tuck
User avatar
Painkiller
Senior Member
Posts: 726
Joined: Sun Mar 01, 2015 8:09 am
Location: Germany
Contact:

Postby Painkiller » Tue Mar 24, 2015 1:56 pm

Hello,

could you fix this script, it's not working anymore. thanks in advance.

(Test it in HL2DM)


Syntax: Select all

from entities.entity import BaseEntity
from events import Event
from mathlib import Vector
from listeners.tick import tick_delays
from entities.helpers import create_entity
from engines.server import engine_server

@Event
def rpg_missile_detonate(game_event):

# Create a particle system entity...
particle = BaseEntity(create_entity('info_particle_system'))

# Set its effect to an huge explosion...
particle.effect_name = 'bomb_explosion_huge'

# Set the origin of the particle...
particle.set_key_value_vector('origin', Vector(*map(game_event.get_float, 'xyz')))

# Precache the particle and set its index...
particle.set_property_int('m_iEffectIndex', engine_server.precache_decal('bomb_explosion_huge'))

# Start the particle effect...
particle.Start()

# Delete it later...
tick_delays.delay(3, particle.Kill)
User avatar
satoon101
Project Leader
Posts: 2698
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Tue Mar 24, 2015 3:16 pm

Well, first, I don't believe rpg_missile_detonate is even an event, so you will need to find another way to know when this happens. To do that, you can use the following to show when an event is fired (if you have direct access to the server's console):

Code: Select all

sv_cheats 1
net_showevents 2


Second, we have changed the way inputs are called, so Start and Kill will not work:
http://forums.sourcepython.com/showthread.php?736

Lastly, I'm not sure if bomb_explosion_huge is a particle effect for HL2:DM, but I cannot remember how to get the particle effect dump L'In20Cible showed above.
Image
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Wed Mar 25, 2015 3:14 am

satoon101 wrote:Lastly, I'm not sure if bomb_explosion_huge is a particle effect for HL2 :D M, but I cannot remember how to get the particle effect dump L'In20Cible showed above.
That dump was the result of "dump_particlemanifest" but they removed that command, apparently.

However, that code is wrong. He need to add the effect to the ParticleEffectNames string table, not precaching it as a decal.
User avatar
satoon101
Project Leader
Posts: 2698
Joined: Sat Jul 07, 2012 1:59 am

Postby satoon101 » Wed Mar 25, 2015 3:32 am

L'In20Cible wrote:That dump was the result of "dump_particlemanifest" but they removed that command, apparently.

Is there any other way we can access the particle names?
Image
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Wed Mar 25, 2015 4:02 am

By hand, you could extract the file ../particles/particles_manifest.txt from the VPK directory and then decompile all the listed PCF files to see the specific names they are exporting. From a dynamic way, I will see what I can find in the binaries when I get the chance to. I remember I saw an interface to query particles in the SDK, could worth looking into exposing it.
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Fri Mar 27, 2015 7:09 pm

Hey I made it work again with the following code:

Syntax: Select all

from entities.entity import BaseEntity
from entities.helpers import create_entity
from entities.helpers import spawn_entity

from players.entity import PlayerEntity
from players.helpers import index_from_userid

from events import Event
from listeners.tick import tick_delays

from stringtables import string_tables


@Event
def player_say(game_event):
if game_event.get_string('text') != '!test':
return
# these are from hl2 pcf files:
#blood_advisor_puncture_withdraw
#embers_small_01
#explosion_huge_burning_chunks
userid = game_event.get_int('userid')
index = index_from_userid(userid)
player = PlayerEntity(index)
player.targetname = 'player_%s'%userid
particle = BaseEntity(create_entity('info_particle_system'))
particle.set_key_value_string('Particle System Name', 'explosion_huge_burning_chunks')
particle.origin = player.origin
#particle.parentname = player.targetname
particle.set_property_int('m_iEffectIndex', string_tables.ParticleEffectNames.add_string('explosion_huge_burning_chunks'))
particle.call_input('SetParent', player.targetname)
particle.call_input('Start')
tick_delays.delay(3, particle.remove)


I'm trying now to attach the particle effect to a player so it's moving with the player but this code does not work. I also tried "SetParentAttachment" with the targetname.
Always gives me this error: Entity info_particle_system(info_particle_system) has bad parent player_2
Any ideas?
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Fri Mar 27, 2015 11:36 pm

Try:

Syntax: Select all

particle.set_parent(player, -1)
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Sat Mar 28, 2015 12:14 pm

Thanks, will test later. What is the -1 for?
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat Mar 28, 2015 12:26 pm

The attachment index. For example, if you want to attach to the right foot of the player:

Syntax: Select all

particle.set_parent(player, player.lookup_attachment('rfoot'))
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Sat Mar 28, 2015 12:50 pm

Ah nice, didn't know it works like that. Is there any way I can find all attachment points (and their indexes) of any entity? Tried googling, couldn't find anything.
necavi
Developer
Posts: 129
Joined: Wed Jan 30, 2013 9:51 pm

Postby necavi » Sat Mar 28, 2015 7:21 pm

Easiest way to do that from what I remember is to open the model in the HL Model Viewer, it lists the attachment points and shows you where they are on the model.
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Tue Mar 31, 2015 12:00 pm

necavi wrote:Easiest way to do that from what I remember is to open the model in the HL Model Viewer, it lists the attachment points and shows you where they are on the model.


Okay, thanks!



L'In20Cible wrote:The attachment index. For example, if you want to attach to the right foot of the player:

[python]particle.set_parent(player, player.lookup_attachment('rfoot'))[/python]


I've tried player.lookup_attachment() in hl2dm, but it returns always 0, whatever which argument I try. Any idea? Also is there a reason why this method does not exist in csgo?
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Tue Mar 31, 2015 12:03 pm

stonedegg wrote:I've tried player.lookup_attachment() in hl2dm, but it returns always 0, whatever which argument I try. Any idea?
The root (index 0) is returned if the given attachment name is not found.

stonedegg wrote:Also is there a reason why this method does not exist in csgo?
No special reason, I simply didn't take the time to grab a signature for it yet.
stonedegg
Senior Member
Posts: 141
Joined: Sun Aug 12, 2012 11:45 am

Postby stonedegg » Tue Mar 31, 2015 1:22 pm

L'In20Cible wrote:The root (index 0) is returned if the given attachment name is not found.


Okay, well looks like the hl2mp player models are setup different then.

L'In20Cible wrote:No special reason, I simply didn't take the time to grab a signature for it yet.


Ah okay, thought it wouldn't be possible or so.
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Tue Apr 07, 2015 3:01 am

necavi wrote:Easiest way to do that from what I remember is to open the model in the HL Model Viewer, it lists the attachment points and shows you where they are on the model.


Or dump them dynamically. :)

Syntax: Select all

# ../testing/testing.py

# ============================================================================
# >> IMPORTS
# ============================================================================
# Source.Python Imports
# Events
from events import Event
# Players
from players.entity import PlayerEntity
from players.helpers import index_from_userid
# Studio
from studio.cache import model_cache


# ============================================================================
# >> GAME EVENTS
# ============================================================================
@Event
def player_jump(game_event):
"""Fired every time a player jumps."""
# Get the PlayerEntity instance of the player jumping...
player = PlayerEntity(index_from_userid(game_event.get_int('userid')))

# Get the ModelHeader instance of the player model...
model_header = model_cache.get_model_header(model_cache.find_model(
player.model.path))

# Loop through all attachment index...
for i in range(model_header.attachments_count):

# Get the attachment associated with the current index...
attachment = model_header.get_attachment(i)

# Print the attachment name...
print(i, attachment.name)
Still a work in progress so the syntax/names are subject to change but you get the idea.
User avatar
iPlayer
Developer
Posts: 590
Joined: Sat Nov 14, 2015 8:37 am
Location: Moscow
Contact:

Postby iPlayer » Sat Dec 05, 2015 11:16 pm

Any way to make custom particles work in CS:S?

I tried uploading my *.pcf file to a client, but the client doesn't seem to recognize particle systems inside of it
Attemped to precache unknown particle system "my_particle_system"!
...
Attempting to create unknown particle system 'my_particle_system'
User avatar
L'In20Cible
Project Leader
Posts: 1534
Joined: Sat Jul 14, 2012 9:29 pm
Location: Québec

Postby L'In20Cible » Sat Dec 05, 2015 11:21 pm

You need to precache your pcf file:

Syntax: Select all

from engines.server import engine_server
from listeners import OnLevelInit

@OnLevelInit
def on_level_init(map_name):
engine_server.precache_generic('file.pcf', True)

Return to “Code examples / Cookbook”

Who is online

Users browsing this forum: No registered users and 0 guests