From ed5bf4acf3995b92d27d6c34794e3225332bc851 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Tue, 8 Oct 2019 22:14:18 +0200 Subject: [PATCH] client-side gs-entbase updates for TW. --- src/gs-entbase/client.src | 5 + src/gs-entbase/client/env_cubemap.cpp | 17 +-- src/gs-entbase/client/env_glow.cpp | 80 +++++++------ src/gs-entbase/client/env_particle.cpp | 93 +++++++++++++++ src/gs-entbase/client/env_sound.cpp | 15 ++- src/gs-entbase/client/env_soundscape.cpp | 93 +++++++++++++++ src/gs-entbase/client/info_notnull.cpp | 20 ++++ src/gs-entbase/client/point_message.cpp | 26 +++-- src/gs-entbase/client/prop_dynamic.cpp | 71 ++++++++++++ src/gs-entbase/client/prop_rope.cpp | 138 +++++++++++++++++++++++ 10 files changed, 500 insertions(+), 58 deletions(-) create mode 100644 src/gs-entbase/client/env_particle.cpp create mode 100644 src/gs-entbase/client/env_soundscape.cpp create mode 100644 src/gs-entbase/client/info_notnull.cpp create mode 100644 src/gs-entbase/client/prop_dynamic.cpp create mode 100644 src/gs-entbase/client/prop_rope.cpp diff --git a/src/gs-entbase/client.src b/src/gs-entbase/client.src index fde31a15..b2beca1f 100644 --- a/src/gs-entbase/client.src +++ b/src/gs-entbase/client.src @@ -4,9 +4,14 @@ client/baseentity.cpp client/env_cubemap.cpp client/env_glow.cpp client/env_sound.cpp +client/env_soundscape.cpp +client/env_particle.cpp client/sky_camera.cpp server/func_ladder.cpp server/trigger_gravity.cpp +client/info_notnull.cpp client/point_message.cpp +client/prop_dynamic.cpp +client/prop_rope.cpp client/worldspawn.cpp #endlist diff --git a/src/gs-entbase/client/env_cubemap.cpp b/src/gs-entbase/client/env_cubemap.cpp index 2882f7c4..57aa213c 100644 --- a/src/gs-entbase/client/env_cubemap.cpp +++ b/src/gs-entbase/client/env_cubemap.cpp @@ -93,7 +93,7 @@ CMap_Shoot(void) strReflectcube, tmp.m_iSize)); self.think = CMap_Check; - self.nextthink = time; + self.nextthink = time + 0.5f; } else { print("^2Cubemaps done...\n"); localcmd("mod_findcubemaps\nvid_reload\n"); @@ -112,18 +112,9 @@ CMap_Check void CMap_Check(void) { - if (whichpack(sprintf( - "textures/env/%s_%d_%d_%d.dds", - mapname, - g_vecCubePos[0], - g_vecCubePos[1], - g_vecCubePos[2]))) - { - self.owner = find(self.owner, classname, "env_cubemap"); - self.think = CMap_Shoot; - self.nextthink = time + 0.25f; /* because sigh */ - } - self.nextthink = time; + self.owner = find(self.owner, classname, "env_cubemap"); + self.think = CMap_Shoot; + self.nextthink = time + 0.25f; /* because sigh */ } /* diff --git a/src/gs-entbase/client/env_glow.cpp b/src/gs-entbase/client/env_glow.cpp index e5e60eda..3197b78d 100644 --- a/src/gs-entbase/client/env_glow.cpp +++ b/src/gs-entbase/client/env_glow.cpp @@ -40,21 +40,29 @@ class env_glow:CBaseEntity float env_glow::predraw(void) { + vector vecPlayer; + +#ifdef WASTES + vecPlayer = viewClient.vecPlayerOrigin; +#else + int s = (float)getproperty(VF_ACTIVESEAT); + pSeat = &seats[s]; + vecPlayer = pSeat->vPlayerOrigin; +#endif + m_flAlpha = bound(0, m_flAlpha, 1.0f); if (m_flAlpha > 0) { vector forg; vector fsize; float falpha; - int s = (float)getproperty(VF_ACTIVESEAT); - pSeat = &seats[s]; /* Scale the glow somewhat with the players distance */ fsize = m_vecSize * m_flScale; - fsize *= vlen(pSeat->vPlayerOrigin - origin) / 256; + fsize *= vlen(vecPlayer - origin) / 256; /* Fade out when the player is starting to move away */ - falpha = 1 - bound(0, vlen(pSeat->vPlayerOrigin - origin) / 1024, 1); + falpha = 1 - bound(0, vlen(vecPlayer - origin) / 1024, 1); falpha *= m_flAlpha; /* Clamp the alpha by the glows' renderamt value */ @@ -62,7 +70,7 @@ float env_glow::predraw(void) makevectors(view_angles); /* Nudge this slightly towards the camera */ - makevectors(vectoangles(origin - pSeat->vPlayerOrigin)); + makevectors(vectoangles(origin - vecPlayer)); forg = origin + (v_forward * -16); /* Project it, always facing the player */ @@ -85,24 +93,31 @@ float env_glow::predraw(void) void env_glow::customphysics(void) { + vector vecPlayer; + +#ifdef WASTES + vecPlayer = viewClient.vecPlayerOrigin; +#else int s = (float)getproperty(VF_ACTIVESEAT); pSeat = &seats[s]; + vecPlayer = pSeat->vPlayerOrigin; +#endif - if (checkpvs(pSeat->vPlayerOrigin, this) == FALSE) { - m_flAlpha -= frametime; + if (checkpvs(vecPlayer, this) == FALSE) { + m_flAlpha -= clframetime; return; } other = world; - traceline(this.origin, pSeat->vPlayerOrigin, MOVE_OTHERONLY, this); + traceline(this.origin, vecPlayer, MOVE_OTHERONLY, this); /* If we can't trace against the player, or are two close, fade out */ - if (trace_fraction < 1.0f || vlen(origin - pSeat->vPlayerOrigin) < 128) { - m_flAlpha -= frametime; + if (trace_fraction < 1.0f || vlen(origin - vecPlayer) < 128) { + m_flAlpha -= clframetime; return; } - m_flAlpha += frametime; + m_flAlpha += clframetime; } void env_glow::env_glow(void) @@ -111,32 +126,33 @@ void env_glow::env_glow(void) m_flMaxAlpha = 1.0f; m_vecColor = [1,1,1]; drawmask = MASK_ENGINE; + setorigin(this, origin); Init(); } void env_glow::SpawnKey(string strField, string strKey) { switch (strField) { - case "shader": - m_strSprite = strKey; - precache_pic(m_strSprite); - m_vecSize = drawgetimagesize(m_strSprite) / 2; - break; - case "model": - m_strSprite = sprintf("%s_0.tga", strKey); - m_vecSize = drawgetimagesize(m_strSprite) / 2; - break; - case "scale": - m_flScale = stof(strKey); - break; - case "rendercolor": - case "rendercolour": - m_vecColor = stov(strKey) / 255; - break; - case "renderamt": - m_flMaxAlpha = stof(strKey) / 255; - break; - default: - CBaseEntity::SpawnKey(strField, strKey); + case "shader": + m_strSprite = strKey; + precache_pic(m_strSprite); + m_vecSize = drawgetimagesize(m_strSprite) / 2; + break; + case "model": + m_strSprite = sprintf("%s_0.tga", strKey); + m_vecSize = drawgetimagesize(m_strSprite) / 2; + break; + case "scale": + m_flScale = stof(strKey); + break; + case "rendercolor": + case "rendercolour": + m_vecColor = stov(strKey) / 255; + break; + case "renderamt": + m_flMaxAlpha = stof(strKey) / 255; + break; + default: + CBaseEntity::SpawnKey(strField, strKey); } } diff --git a/src/gs-entbase/client/env_particle.cpp b/src/gs-entbase/client/env_particle.cpp new file mode 100644 index 00000000..72f67030 --- /dev/null +++ b/src/gs-entbase/client/env_particle.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016-2019 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 env_particle (1 0 0) (-8 -8 -8) (8 8 8) +"message" Particle material to use. +"wait" Delay between emits. +"target" Name of target, like an info_notnull (client-side) +"velocity" Speed in units. +"count" Number of particles to emit. + +Client-side particle effect. Active at runtime, fully client-side. +Cannot be triggered. +*/ + +class env_particle:CBaseEntity +{ + entity m_eTarget; + float m_flNextTime; + float m_flPartID; + float m_flVelocity; + float m_flWait; + int m_iCount; + string m_strTarget; + + void() env_particle; + virtual void() customphysics; + virtual void(string, string) SpawnKey; +}; + +void env_particle::customphysics(void) +{ + if (checkpvs(viewClient.vecPlayerOrigin, this) == FALSE) { + return; + } + + if (!m_flVelocity) { + m_flVelocity = 1.0f; + } + + if (m_flNextTime > time) { + return; + } + + if (m_strTarget) { + m_eTarget = find(world, ::targetname, m_strTarget); + makevectors(vectoangles(m_eTarget.origin - origin) * -1); + angles = v_forward; + } + pointparticles(m_flPartID, origin, angles * m_flVelocity, m_iCount); + m_flNextTime = time + m_flWait; +} + +void env_particle::env_particle(void) +{ + drawmask = MASK_ENGINE; + Init(); +} + +void env_particle::SpawnKey(string strField, string strKey) +{ + switch (strField) { + case "message": + m_flPartID = particleeffectnum(strKey); + break; + case "wait": + m_flWait = stof(strKey); + break; + case "target": + m_strTarget = strKey; + break; + case "velocity": + m_flVelocity = stof(strKey); + break; + case "count": + m_iCount = stoi(strKey); + break; + default: + CBaseEntity::SpawnKey(strField, strKey); + } +} diff --git a/src/gs-entbase/client/env_sound.cpp b/src/gs-entbase/client/env_sound.cpp index 60d2b273..b49646cc 100644 --- a/src/gs-entbase/client/env_sound.cpp +++ b/src/gs-entbase/client/env_sound.cpp @@ -148,21 +148,28 @@ class env_sound:CBaseEntity void env_sound::customphysics(void) { + vector vecPlayer; + +#ifdef WASTES + vecPlayer = viewClient.vecPlayerOrigin; +#else int s = (float)getproperty(VF_ACTIVESEAT); pSeat = &seats[s]; - - if (checkpvs(pSeat->vPlayerOrigin, this) == FALSE) { + vecPlayer = pSeat->vPlayerOrigin; +#endif + + if (checkpvs(vecPlayer, this) == FALSE) { return; } - float fDist = vlen(pSeat->vPlayerOrigin - this.origin); + float fDist = vlen(vecPlayer - this.origin); if (g_flDSPCheck > time) { return; } other = world; - traceline(this.origin, pSeat->vPlayerOrigin, MOVE_OTHERONLY, this); + traceline(this.origin, vecPlayer, MOVE_OTHERONLY, this); if (trace_fraction < 1.0f) { return; diff --git a/src/gs-entbase/client/env_soundscape.cpp b/src/gs-entbase/client/env_soundscape.cpp new file mode 100644 index 00000000..0c716091 --- /dev/null +++ b/src/gs-entbase/client/env_soundscape.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016-2019 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 env_soundscape (1 0 0) (-8 -8 -8) (8 8 8) +"radius" Radius in units. +"shader" Sound shader to play. + +Client-side environmental soundscape modifier. +*/ + +int g_iSoundscape; +float g_flSoundscapeCheck; +int Sound_Precache(string shader); + +class env_soundscape:CBaseEntity +{ + int m_iShader; + int m_iRadius; + + virtual void() customphysics; + virtual void(string, string) SpawnKey; +}; + +void env_soundscape::customphysics(void) +{ + vector vecPlayer; + +#ifdef WASTES + vecPlayer = viewClient.vecPlayerOrigin; +#else + int s = (float)getproperty(VF_ACTIVESEAT); + pSeat = &seats[s]; + vecPlayer = pSeat->vPlayerOrigin; +#endif + + if (checkpvs(vecPlayer, this) == FALSE) { + return; + } + + float fDist = vlen(vecPlayer - this.origin); + + if (g_flSoundscapeCheck > time) { + return; + } + + other = world; + traceline(this.origin, vecPlayer, MOVE_OTHERONLY, this); + + if (trace_fraction < 1.0f) { + return; + } + + if (fDist <= m_iRadius) { + if (g_iSoundscape == m_iShader) { + return; + } + dprint(sprintf("[DSP] Soundscape changed to %i\n", m_iShader)); + g_iSoundscape = m_iShader; + g_flSoundscapeCheck = time + 0.5; + } +} + +void env_soundscape::SpawnKey(string strField, string strKey) +{ + switch (strField) { + case "shader": + m_iShader = Sound_Precache(strKey); + break; + case "radius": + m_iRadius = stoi(strKey); + break; + default: + CBaseEntity::SpawnKey(strField, strKey); + } +} + +void DSP_UpdateSoundscape(void) +{ + +} diff --git a/src/gs-entbase/client/info_notnull.cpp b/src/gs-entbase/client/info_notnull.cpp new file mode 100644 index 00000000..6250f6c0 --- /dev/null +++ b/src/gs-entbase/client/info_notnull.cpp @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016-2019 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. + */ + +class info_notnull:CBaseEntity +{ + +}; diff --git a/src/gs-entbase/client/point_message.cpp b/src/gs-entbase/client/point_message.cpp index 9b6308d9..cb74be39 100644 --- a/src/gs-entbase/client/point_message.cpp +++ b/src/gs-entbase/client/point_message.cpp @@ -1,14 +1,22 @@ -/*** -* -* Copyright (c) 2016-2019 Marco 'eukara' Hladik. All rights reserved. -* -* See the file LICENSE attached with the sources for usage details. -* -****/ +/* + * Copyright (c) 2016-2019 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 point_message (1 0 0) (-8 -8 -8) (8 8 8) -"message" The message to display. -"radius" The radius in which it will appear. +"message" The message to display. +"radius" The radius in which it will appear. Client-side overlay/message that is projected in relation to its position in 3D space. diff --git a/src/gs-entbase/client/prop_dynamic.cpp b/src/gs-entbase/client/prop_dynamic.cpp new file mode 100644 index 00000000..ec6f6969 --- /dev/null +++ b/src/gs-entbase/client/prop_dynamic.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016-2019 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 prop_dynamic (1 0 0) (-8 -8 -8) (8 8 8) +"model" Model file that will be displayed by the entity. +"modelscale" Scale modifier of the model. Default is '1'. +"angles" Sets the pitch, yaw and roll angles of the model. +"_cs" Toggles if the prop casts a shadow or not. + +Client-side decorative model entity. +*/ + + +class prop_dynamic:CBaseEntity { + virtual void() Init; + virtual void() PhysicsFrame; + /*virtual float() predraw;*/ + virtual void(string, string) SpawnKey; +}; + +void prop_dynamic::SpawnKey(string strField, string strKey) +{ + switch (strField) { + case "modelscale": + scale = stof(strKey); + break; + case "angle": + angles[1] = stof(strKey); + break; + default: + CBaseEntity::SpawnKey(strField, strKey); + } +} + +/*float prop_dynamic::predraw(void) +{ + if (checkpvs(viewClient.vecPlayerOrigin, this) == TRUE) { + addentity(this); + } + return PREDRAW_NEXT; +}*/ + +void prop_dynamic::Init(void) +{ + CBaseEntity::Init(); + + precache_model(model); + setmodel(this, model); + setorigin(this, origin); + setsize(this, mins * scale, maxs * scale); + drawmask = MASK_ENGINE; +} + +void prop_dynamic::PhysicsFrame(void) +{ + //angles[1] += clframetime * 60; +} diff --git a/src/gs-entbase/client/prop_rope.cpp b/src/gs-entbase/client/prop_rope.cpp new file mode 100644 index 00000000..f7c71b9b --- /dev/null +++ b/src/gs-entbase/client/prop_rope.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016-2019 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. + */ + +var int autocvar_rope_debug = FALSE; + +class prop_rope:CBaseEntity +{ + string m_strShader; + float m_flSag; + float m_flSwingFactor; + + void() prop_rope; + virtual float() predraw; + virtual void(vector, vector) draw_segment; + virtual void(string, string) SpawnKey; +}; + +void prop_rope::draw_segment(vector start, vector end) +{ + vector fsize = [3,3]; + vector lit1 = /*[0.1,0.1,0.1] */ getlight(start) / 255; + vector lit2 = /*[0.1,0.1,0.1] */ getlight(end) / 255; + + if (autocvar_rope_debug == TRUE) { + R_BeginPolygon("", 0, 0); + R_PolygonVertex(start, [0,1], lit1, 1); + R_PolygonVertex(end, [1,1], lit2, 1); + R_EndPolygon(); + return; + } + + makevectors(view_angles); + + vector tex1, tex2, tex3, tex4; + vector eyepos = getproperty(VF_ORIGIN); + vector dir = normalize(start-end); + vector eyevector = normalize(start - eyepos); + vector tangent = crossproduct(dir, eyevector); + + tex1 = start + tangent * fsize[0]; + tex2 = start - tangent * fsize[1]; + + eyevector = normalize(end - eyepos); + tangent = crossproduct(dir, eyevector); + + tex3 = end - tangent * fsize[0]; + tex4 = end + tangent * fsize[1]; + + R_BeginPolygon(m_strShader, 0, 0); + R_PolygonVertex(tex1, [1,1], lit1, 1.0f); + R_PolygonVertex(tex2, [0,1], lit1, 1.0f); + + R_PolygonVertex(tex3, [1,0], lit2, 1.0f); + R_PolygonVertex(tex4, [0,0], lit2, 1.0f); + R_EndPolygon(); + +} + +float prop_rope::predraw(void) +{ + vector pos1; + vector pos2; + float travel; + float segments; + + if (checkpvs(getproperty(VF_ORIGIN), this) == FALSE) { + return; + } + + pos1 = origin; + + entity x = find(world, ::targetname, target); + + if (!x) { + print("prop_rope without target.\n"); + remove(this); + return PREDRAW_NEXT; + } + + segments = 16; + + travel = vlen(origin - x.origin) / segments; + + float sc = 0; + for (float i = 0; i < segments; i++) { + float sag = cos(sc) * m_flSag - 1; + + /* get the direction */ + makevectors(vectoangles(x.origin - origin)); + + /* travel further and sag */ + pos2 = pos1 + (v_forward * travel) + (v_up * -sag); + + draw_segment(pos1, pos2); + pos1 = pos2; + + sc += (M_PI * (1 / segments)); + } + + addentity(this); + return PREDRAW_NEXT; +} + +void prop_rope::SpawnKey(string strField, string strKey) +{ + switch (strField) { + case "sag": + m_flSag = stof(strKey); + break; + case "shader": + m_strShader = strKey; + precache_pic(m_strShader); + break; + default: + CBaseEntity::SpawnKey(strField, strKey); + } +} + +void prop_rope::prop_rope(void) +{ + m_flSwingFactor = 1.0f; + m_flSag = 15.0f; + drawmask = MASK_ENGINE; + Init(); +}