diff --git a/platform/test_maps.pk3dir/maps/test_particles.bsp b/platform/test_maps.pk3dir/maps/test_particles.bsp new file mode 100644 index 00000000..988bd92f Binary files /dev/null and b/platform/test_maps.pk3dir/maps/test_particles.bsp differ diff --git a/platform/test_maps.pk3dir/maps/test_particles.map b/platform/test_maps.pk3dir/maps/test_particles.map new file mode 100644 index 00000000..b7ce7856 --- /dev/null +++ b/platform/test_maps.pk3dir/maps/test_particles.map @@ -0,0 +1,140 @@ + +// entity 0 +{ +"classname" "worldspawn" +// brush 0 +{ +( 248 192 -64 ) ( 248 -192 -64 ) ( -264 192 -64 ) measure/floor [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 256 192 8 ) ( -256 192 8 ) ( 256 192 0 ) measure/floor [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 256 192 8 ) ( 256 192 0 ) ( 256 -192 8 ) measure/floor [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -256 -192 -128 ) ( 256 -192 -128 ) ( -256 192 -128 ) measure/floor [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( -256 -192 0 ) ( -256 -192 8 ) ( 256 -192 0 ) measure/floor [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -256 -192 0 ) ( -256 192 0 ) ( -256 -192 8 ) measure/floor [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +} +// brush 1 +{ +( 248 192 192 ) ( 248 -192 192 ) ( -264 192 192 ) measure/floor [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 256 192 264 ) ( -256 192 264 ) ( 256 192 256 ) measure/floor [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 256 192 264 ) ( 256 192 256 ) ( 256 -192 264 ) measure/floor [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -256 -192 128 ) ( 256 -192 128 ) ( -256 192 128 ) measure/floor [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( -256 -192 256 ) ( -256 -192 264 ) ( 256 -192 256 ) measure/floor [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -256 -192 256 ) ( -256 192 256 ) ( -256 -192 264 ) measure/floor [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +} +// brush 2 +{ +( 184 192 192 ) ( 184 -192 192 ) ( -328 192 192 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 192 192 264 ) ( -320 192 264 ) ( 192 192 256 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -256 192 8 ) ( -256 192 0 ) ( -256 -192 8 ) measure/wall128gr [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -768 -192 -128 ) ( -256 -192 -128 ) ( -768 192 -128 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( -320 -192 256 ) ( -320 -192 264 ) ( 192 -192 256 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -320 -192 256 ) ( -320 192 256 ) ( -320 -192 264 ) measure/wall128gr [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +} +// brush 3 +{ +( 760 192 192 ) ( 760 -192 192 ) ( 248 192 192 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 768 192 264 ) ( 256 192 264 ) ( 768 192 256 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 320 192 8 ) ( 320 192 0 ) ( 320 -192 8 ) measure/wall128gr [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -192 -192 -128 ) ( 320 -192 -128 ) ( -192 192 -128 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 256 -192 256 ) ( 256 -192 264 ) ( 768 -192 256 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 256 -192 256 ) ( 256 192 256 ) ( 256 -192 264 ) measure/wall128gr [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +} +// brush 4 +{ +( 184 -192 192 ) ( 184 -576 192 ) ( -328 -192 192 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 192 -192 264 ) ( -320 -192 264 ) ( 192 -192 256 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 320 96 8 ) ( 320 96 0 ) ( 320 -288 8 ) measure/wall128gr [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -768 -576 -128 ) ( -256 -576 -128 ) ( -768 -192 -128 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 272 -256 256 ) ( 272 -256 264 ) ( 784 -256 256 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -320 -576 256 ) ( -320 -192 256 ) ( -320 -576 264 ) measure/wall128gr [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +} +// brush 5 +{ +( 184 256 192 ) ( 184 -128 192 ) ( -328 256 192 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 192 256 264 ) ( -320 256 264 ) ( 192 256 256 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 320 544 8 ) ( 320 544 0 ) ( 320 160 8 ) measure/wall128gr [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -768 -128 -128 ) ( -256 -128 -128 ) ( -768 256 -128 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 272 192 256 ) ( 272 192 264 ) ( 784 192 256 ) measure/wall128gr [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( -320 -128 256 ) ( -320 256 256 ) ( -320 -128 264 ) measure/wall128gr [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +} +} +// entity 1 +{ +"classname" "info_player_start" +} +// entity 2 +{ +"classname" "info_player_deathmatch" +} +// entity 3 +{ +"classname" "light" +"origin" "192.000000 128.000000 64.000000" +"light" "50" +} +// entity 4 +{ +"classname" "light" +"origin" "192.000000 -128.000000 64.000000" +"light" "50" +} +// entity 5 +{ +"classname" "func_button" +"OnPressed" "foobar,Stop,,0,-1" +// brush 0 +{ +( 88 -40 0 ) ( 88 -80 0 ) ( 48 -40 0 ) next/rusty7 [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 88 -48 72 ) ( 48 -48 72 ) ( 88 -48 64 ) next/rusty7 [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 80 -40 72 ) ( 80 -40 64 ) ( 80 -80 72 ) next/rusty7 [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 48 -80 -64 ) ( 88 -80 -64 ) ( 48 -40 -64 ) next/rusty7 [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 40 -80 64 ) ( 40 -80 72 ) ( 80 -80 64 ) next/rusty7 [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 48 -80 64 ) ( 48 -40 64 ) ( 48 -80 72 ) next/rusty7 [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +} +} +// entity 6 +{ +"classname" "func_button" +"OnPressed" "foobar,Start,,0,-1" +// brush 0 +{ +( 88 152 0 ) ( 88 112 0 ) ( 48 152 0 ) next/rusty7 [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 88 144 72 ) ( 48 144 72 ) ( 88 144 64 ) next/rusty7 [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 80 152 72 ) ( 80 152 64 ) ( 80 112 72 ) next/rusty7 [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 48 112 -64 ) ( 88 112 -64 ) ( 48 152 -64 ) next/rusty7 [ 1 0 0 0 ] [ -0 -1 -0 0 ] -0 0.5 0.5 0 0 0 +( 40 112 64 ) ( 40 112 72 ) ( 80 112 64 ) next/rusty7 [ 1 0 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +( 48 112 64 ) ( 48 152 64 ) ( 48 112 72 ) next/rusty7 [ 0 1 0 0 ] [ -0 -0 -1 0 ] -0 0.5 0.5 0 0 0 +} +} +// entity 7 +{ +"classname" "light" +"origin" "-192.000000 128.000000 64.000000" +"light" "25" +} +// entity 8 +{ +"classname" "light" +"origin" "-192.000000 -64.000000 64.000000" +"light" "25" +"style" "9" +} +// entity 9 +{ +"classname" "point_message" +"origin" "64.000000 128.000000 32.000000" +"message" "Particle Emitter: On" +} +// entity 10 +{ +"classname" "point_message" +"origin" "64.000000 -64.000000 32.000000" +"message" "Particle Emitter: Off" +} +// entity 11 +{ +"classname" "info_particle_system" +"origin" "128.000000 32.000000 32.000000" +"targetname" "foobar" +"effect_name" "test.ball" +"interval" "0.25" +} diff --git a/src/client/entry.c b/src/client/entry.c index ef5f7ead..7d71cf74 100644 --- a/src/client/entry.c +++ b/src/client/entry.c @@ -838,7 +838,6 @@ CSQC_Ent_Update(float new) } spr.ReceiveEntity(readfloat()); break; - break; case ENT_SPRAY: Spray_Parse(); break; @@ -862,6 +861,13 @@ CSQC_Ent_Update(float new) } l.ReceiveEntity(readfloat()); break; + case ENT_PARTSYSTEM: + info_particle_system ips = (info_particle_system)self; + if (new) { + spawnfunc_info_particle_system(); + } + ips.ReceiveEntity(readfloat()); + break; default: if (Game_Entity_Update(t, new) == FALSE) { error("Unknown entity type update received.\n"); diff --git a/src/gs-entbase/client/info_particle_system.cpp b/src/gs-entbase/client/info_particle_system.cpp new file mode 100644 index 00000000..af660c24 --- /dev/null +++ b/src/gs-entbase/client/info_particle_system.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* this has to match gs-entbase/server/info_particle_system.cpp! */ +enumflags +{ + DLIGHTFL_CHANGED_ORIGIN, + DLIGHTFL_CHANGED_ANGLES, + DLIGHTFL_CHANGED_LIGHT, + DLIGHTFL_CHANGED_INTENSITY, + DLIGHTFL_CHANGED_INNERCONE, + DLIGHTFL_CHANGED_CONE, + DLIGHTFL_CHANGED_DISTANCE, + DLIGHTFL_CHANGED_RADIUS, + DLIGHTFL_CHANGED_STYLE, + DLIGHTFL_CHANGED_STATE +}; + +class info_particle_system +{ + vector m_vecLight; + float m_flIntensity; + float m_flInnerCone; + float m_flCone; + float m_flDistance; + float m_flRadius; + float m_flStyle; + int m_iState; + + void(void) info_particle_system; + + virtual void(float) ReceiveEntity; +}; + +float +info_particle_system::predraw(void) +{ + if (!m_iState) { + return PREDRAW_NEXT; + } + + /* TODO: We need to handle the second cone light */ + dynamiclight_add(origin, m_flDistance, m_vecLight, m_flStyle); + + addentity(this); + return PREDRAW_NEXT; +} + +void +info_particle_system::ReceiveEntity(float flFlags) +{ + if (flFlags & DLIGHTFL_CHANGED_ORIGIN) { + origin[0] = readcoord(); + origin[1] = readcoord(); + origin[2] = readcoord(); + setorigin(this, origin); + } + + if (flFlags & DLIGHTFL_CHANGED_ANGLES) { + angles[0] = readcoord(); + angles[1] = readcoord(); + angles[2] = readcoord(); + } + + if (flFlags & DLIGHTFL_CHANGED_LIGHT) { + m_vecLight[0] = readbyte() / 255; + m_vecLight[1] = readbyte() / 255; + m_vecLight[2] = readbyte() / 255; + } + + if (flFlags & DLIGHTFL_CHANGED_INTENSITY) + m_flIntensity = readfloat(); + if (flFlags & DLIGHTFL_CHANGED_INNERCONE) + m_flInnerCone = readfloat(); + if (flFlags & DLIGHTFL_CHANGED_CONE) + m_flCone = readfloat(); + if (flFlags & DLIGHTFL_CHANGED_DISTANCE) + m_flDistance = readfloat(); + if (flFlags & DLIGHTFL_CHANGED_RADIUS) + m_flRadius = readfloat(); + if (flFlags & DLIGHTFL_CHANGED_STYLE) + m_flStyle = readbyte(); + if (flFlags & DLIGHTFL_CHANGED_STATE) + m_iState = readbyte(); + + classname = "info_particle_system"; +} + +void +info_particle_system::info_particle_system(void) +{ + drawmask = MASK_ENGINE; +} diff --git a/src/gs-entbase/server/light_dynamic.cpp b/src/gs-entbase/server/light_dynamic.cpp index 0375ecb3..6fd8ecf9 100644 --- a/src/gs-entbase/server/light_dynamic.cpp +++ b/src/gs-entbase/server/light_dynamic.cpp @@ -82,11 +82,8 @@ light_dynamic::ParentUpdate(void) if (m_parent) { entity p = find(world, ::targetname, m_parent); - if (!p) { - return; - } - - SetOrigin(p.origin); + if (p) + SetOrigin(p.origin); } } diff --git a/src/gs-entbase/shared.src b/src/gs-entbase/shared.src index de58f8d1..d9495554 100644 --- a/src/gs-entbase/shared.src +++ b/src/gs-entbase/shared.src @@ -7,4 +7,5 @@ shared/decals.cpp shared/spraylogo.cpp shared/func_friction.cpp shared/trigger_gravity.cpp +shared/info_particle_system.cpp #endlist diff --git a/src/gs-entbase/shared/baseentity.cpp b/src/gs-entbase/shared/baseentity.cpp index f6ab702e..afce16af 100644 --- a/src/gs-entbase/shared/baseentity.cpp +++ b/src/gs-entbase/shared/baseentity.cpp @@ -131,6 +131,7 @@ CBaseEntity::RenderFXPass(void) } #endif +var int autocvar_r_showSkeleton = 0; float CBaseEntity::predraw(void) { @@ -142,6 +143,23 @@ CBaseEntity::predraw(void) RenderFXPass(); #endif + if (autocvar_r_showSkeleton == 1) { + for (int i = 1; i < 64; i++) { + vector v1 = gettaginfo(this, i); + + if (v1 != this.origin) { + makevectors(input_angles); + R_BeginPolygon("textures/dev/model_bone", 0, 0); + R_PolygonVertex(v1 + v_right * 1 - v_up * 1, [1,1], [1,1,1], 1.0f); + R_PolygonVertex(v1 - v_right * 1 - v_up * 1, [0,1], [1,1,1], 1.0f); + R_PolygonVertex(v1 - v_right * 1 + v_up * 1, [0,0], [1,1,1], 1.0f); + R_PolygonVertex(v1 + v_right * 1 + v_up * 1, [1,0], [1,1,1], 1.0f); + R_EndPolygon(); + alpha = 0.25f; + } + } + } + /* mouth flapping action */ bonecontrol5 = getchannellevel(this, CHAN_VOICE) * 20; m_flBaseTime = frame1time; @@ -695,11 +713,8 @@ CBaseEntity::ParentUpdate(void) if (m_parent) { entity p = find(world, ::targetname, m_parent); - if (!p) { - return; - } - - SetOrigin(p.origin); + if (p) + SetOrigin(p.origin); } } diff --git a/src/gs-entbase/shared/info_particle_system.cpp b/src/gs-entbase/shared/info_particle_system.cpp new file mode 100644 index 00000000..c2772d09 --- /dev/null +++ b/src/gs-entbase/shared/info_particle_system.cpp @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/*QUAKED info_particle_system (1 0 0) (-8 -8 -8) (8 8 8) +"targetname" Name +"effect_name" Name of the particle effect to spawn +"start_active" Whether or not the entity needs to be triggered first +"interval" Override for spawn intervals. +"spawncount" Override for the amount of particles that will be emitted + +An entity that's spawns particles from the engine's particle system. + +Trivia: +This entity was introduced in The Orange Box (2007). +*/ + +#define PSFL_STARTACTIVE 1 + +enumflags +{ + PARTSYSFL_CHANGED_ORIGIN, + PARTSYSFL_CHANGED_ANGLES, + PARTSYSFL_CHANGED_EFFECT, + PARTSYSFL_CHANGED_STATUS, + PARTSYSFL_CHANGED_INTERVAL, + PARTSYSFL_CHANGED_COUNT +}; + +#ifdef CLIENT +class info_particle_system +#else +class info_particle_system:CBaseTrigger +#endif +{ + string m_strEffectName; + float m_flInterval; + int m_iSpawnCount; + + void(void) info_particle_system; + +#ifdef CLIENT + int m_iValue; + int m_iEffectID; + + virtual void(void) Emit; + virtual void(float) ReceiveEntity; +#else + virtual void(void) Respawn; + virtual void(void) ParentUpdate; + virtual float(entity, float) SendEntity; + virtual void(string, string) SpawnKey; + virtual void(entity, int) Trigger; + virtual void(entity, string, string) Input; +#endif +}; + +#ifdef CLIENT +void +info_particle_system::Emit(void) +{ + if (m_iValue) + if (m_iSpawnCount) + pointparticles((float)m_iEffectID, origin, angles, m_iSpawnCount); + else + pointparticles((float)m_iEffectID, origin, angles, 1); + + nextthink = time + m_flInterval; +} + +void +info_particle_system::ReceiveEntity(float flFlags) +{ + if (flFlags & PARTSYSFL_CHANGED_ORIGIN) { + origin[0] = readcoord(); + origin[1] = readcoord(); + origin[2] = readcoord(); + } + + if (flFlags & PARTSYSFL_CHANGED_ANGLES) { + angles[0] = readfloat(); + angles[1] = readfloat(); + angles[2] = readfloat(); + } + + if (flFlags & PARTSYSFL_CHANGED_EFFECT) { + m_strEffectName = readstring(); + m_iEffectID = particleeffectnum(m_strEffectName); + } + + if (flFlags & PARTSYSFL_CHANGED_STATUS) { + m_iValue = readbyte(); + } + + if (flFlags & PARTSYSFL_CHANGED_INTERVAL) { + m_flInterval = readfloat(); + nextthink = time + m_flInterval; + } + + if (flFlags & PARTSYSFL_CHANGED_COUNT) + m_iSpawnCount = readbyte(); + + classname = "info_particle_system"; + + setorigin(this, origin); + setsize(this, mins, maxs); +} +#else +float +info_particle_system::SendEntity(entity ePVSEnt, float flFlags) +{ + WriteByte(MSG_ENTITY, ENT_PARTSYSTEM); + WriteFloat(MSG_ENTITY, flFlags); + + if (flFlags & PARTSYSFL_CHANGED_ORIGIN) { + WriteCoord(MSG_ENTITY, origin[0]); + WriteCoord(MSG_ENTITY, origin[1]); + WriteCoord(MSG_ENTITY, origin[2]); + } + + if (flFlags & PARTSYSFL_CHANGED_ANGLES) { + WriteFloat(MSG_ENTITY, angles[0]); + WriteFloat(MSG_ENTITY, angles[1]); + WriteFloat(MSG_ENTITY, angles[2]); + } + + if (flFlags & PARTSYSFL_CHANGED_EFFECT) + WriteString(MSG_ENTITY, m_strEffectName); + + if (flFlags & PARTSYSFL_CHANGED_STATUS) + WriteByte(MSG_ENTITY, m_iValue); + + if (flFlags & PARTSYSFL_CHANGED_INTERVAL) + WriteFloat(MSG_ENTITY, m_flInterval); + + if (flFlags & PARTSYSFL_CHANGED_COUNT) + WriteByte(MSG_ENTITY, m_iSpawnCount); + + return TRUE; +} + +void +info_particle_system::ParentUpdate(void) +{ + if (net_origin != origin) { + net_origin = origin; + SendFlags |= PARTSYSFL_CHANGED_ORIGIN; + } + + if (net_angles != angles) { + net_angles = angles; + SendFlags |= PARTSYSFL_CHANGED_ANGLES; + } + + if (m_parent) { + entity p = find(world, ::targetname, m_parent); + + if (p) + SetOrigin(p.origin); + } +} + +void +info_particle_system::Trigger(entity act, int state) +{ + switch (state) { + case TRIG_OFF: + m_iValue = 0; + break; + case TRIG_ON: + m_iValue = 1; + break; + default: + m_iValue = 1 - m_iValue; + } + + SendFlags |= PARTSYSFL_CHANGED_STATUS; +} + +void +info_particle_system::Input(entity eAct, string strInput, string strData) +{ + switch (strInput) { + case "Start": + Trigger(eAct, TRIG_ON); + break; + case "Stop": + Trigger(eAct, TRIG_OFF); + break; + /* out of spec */ + case "Toggle": + Trigger(eAct, TRIG_TOGGLE); + break; + default: + CBaseTrigger::Input(eAct, strInput, strData); + } +} + +void +info_particle_system::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "effect_name": + m_strEffectName = strValue; + break; + case "start_active": + spawnflags |= stoi(strValue); + break; + /* out of spec */ + case "interval": + m_flInterval = stof(strValue); + break; + case "spawncount": + m_iSpawnCount = stoi(strValue); + break; + default: + CBaseTrigger::SpawnKey(strKey, strValue); + } +} + +void +info_particle_system::Respawn(void) +{ + SetSolid(SOLID_NOT); + SetSize([-16,-16,-16], [16,16,16]); + SetOrigin(m_oldOrigin); + SetAngles(m_oldAngle); + + SendFlags = PARTSYSFL_CHANGED_ORIGIN | \ + PARTSYSFL_CHANGED_ANGLES | \ + PARTSYSFL_CHANGED_EFFECT | \ + PARTSYSFL_CHANGED_STATUS | \ + PARTSYSFL_CHANGED_INTERVAL | \ + PARTSYSFL_CHANGED_COUNT; +} +#endif + +void +info_particle_system::info_particle_system(void) +{ +#ifdef CLIENT + drawmask = MASK_ENGINE; + think = Emit; +#elif SERVER + CBaseTrigger::CBaseTrigger(); +#endif +} diff --git a/src/shared/entities.h b/src/shared/entities.h index 57ebbed3..8db058f4 100644 --- a/src/shared/entities.h +++ b/src/shared/entities.h @@ -22,6 +22,7 @@ enum ENT_AMBIENTSOUND, ENT_DLIGHT, ENT_ENVLASER, + ENT_PARTSYSTEM, ENT_SPRITE, ENT_SPRAY, ENT_DECAL,