From 8fa85bd1e529d06602fc0d80bf11821de5ea6c7d Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Tue, 22 Mar 2022 22:57:15 -0700 Subject: [PATCH] func_dustcloud: initial implementation. Currently fully client-side, so Inputs and 'StartDisabled' don't work. --- src/gs-entbase/client.src | 1 + src/gs-entbase/client/env_sun.qc | 7 + src/gs-entbase/client/func_dustcloud.qc | 197 ++++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 src/gs-entbase/client/func_dustcloud.qc diff --git a/src/gs-entbase/client.src b/src/gs-entbase/client.src index df6eb810..bfcfbdfd 100644 --- a/src/gs-entbase/client.src +++ b/src/gs-entbase/client.src @@ -17,6 +17,7 @@ client/env_particle.qc client/env_laser.qc client/func_lod.qc client/func_dustmotes.qc +client/func_dustcloud.qc client/light_environment.qc client/infodecal.qc client/sky_camera.qc diff --git a/src/gs-entbase/client/env_sun.qc b/src/gs-entbase/client/env_sun.qc index b6fd03f4..d62525f3 100644 --- a/src/gs-entbase/client/env_sun.qc +++ b/src/gs-entbase/client/env_sun.qc @@ -203,9 +203,13 @@ env_sun_lensflare(vector m_vecLensPos, float m_flLensAlpha, vector vecColor) vector test1, test2; test1 = project(m_vecLensPos); test2 = video_res / 2; + float dist_alpha = 1.0 - bound(0.0, vlen(player_pos - m_vecLensPos) / 1024, 1.0); vector c = (test2 - test1) * 1.25f; m_flLensAlpha = bound(0.0, 1.0 - (vlen(c) / 350), 1.0f) * m_flLensAlpha; + m_flLensAlpha *= dist_alpha; + dist_alpha = 1.0 - bound(0.0, vlen(player_pos - m_vecLensPos) / 512, 1.0); + drawpic(lens_1, "textures/sfx/flare1", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE); drawpic(lens_1 - c * 0.1, "textures/sfx/flare2", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE); @@ -213,4 +217,7 @@ env_sun_lensflare(vector m_vecLensPos, float m_flLensAlpha, vector vecColor) drawpic(lens_1 - c * 0.3, "textures/sfx/flare4", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE); drawpic(lens_1 + c * 0.4, "textures/sfx/flare2", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE); drawpic(lens_1 - c * 0.5, "textures/sfx/flare3", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE); + + m_flLensAlpha = bound(0.0, 1.0 - (vlen(c) / 100), 1.0f) * m_flLensAlpha; + drawfill(video_mins, video_res, vecColor, m_flLensAlpha * dist_alpha); } diff --git a/src/gs-entbase/client/func_dustcloud.qc b/src/gs-entbase/client/func_dustcloud.qc new file mode 100644 index 00000000..4554963a --- /dev/null +++ b/src/gs-entbase/client/func_dustcloud.qc @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2016-2022 Marco Cawthorne + * + * 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 func_dustcloud (0 .5 .8) ? +Dust cloud emitting brush volume. + +-------- KEYS -------- +"count" : Number of cloud particles that will float around on average. +"Alpha" : Transparency of the clouds. Value from 0 to 255. +"SizeMin" : Minimum size of each cloud. In Quake units. +"SizeMax" : Maximum size of each cloud. In Quake units. + +-------- TRIVIA -------- +This entity was introduced in Half-Life 2 (2004). +*/ + +class func_dustcloud:NSEntity +{ + int m_iCount; + int m_iPart; + float m_flNexTime; + + float m_flSizeMin; + float m_flSizeMax; + float m_flAlpha; + vector m_vecColor; + float m_flLifetimeMin; + float m_flLifetimeMax; + + void(void) func_dustcloud; + virtual void(void) Init; + virtual float() predraw; + virtual void(string, string) SpawnKey; +}; + +#if 1 +class func_dustcloud_cloud +{ + float alpha; + vector cloudsize; + float lifetime; + + /* attributes */ + float m_flMaxAlpha; + vector m_vecColor; + float m_flLifeTime; + + void(void) func_dustcloud_cloud; + + virtual float(void) predraw; +}; + +float +func_dustcloud_cloud::predraw(void) +{ + makevectors(view_angles); + + if (lifetime < (m_flLifeTime / 2)) { + alpha = bound(0.0, lifetime / (m_flLifeTime / 2), 1.0); + } else { + alpha = 1.0 - bound(0.0, ((lifetime-(m_flLifeTime / 2)) / (m_flLifeTime / 2)), 1.0); + } + + R_BeginPolygon("textures/sfx/dust2", 1, 0); + R_PolygonVertex(origin + v_right * cloudsize[0] - v_up * cloudsize[1], [1,1], m_vecColor, alpha); + R_PolygonVertex(origin - v_right * cloudsize[0] - v_up * cloudsize[1], [0,1], m_vecColor, alpha); + R_PolygonVertex(origin - v_right * cloudsize[0] + v_up * cloudsize[1], [0,0], m_vecColor, alpha); + R_PolygonVertex(origin + v_right * cloudsize[0] + v_up * cloudsize[1], [1,0], m_vecColor, alpha); + R_EndPolygon(); + + if (lifetime >= 10.0f) { + think = Util_Destroy; + nextthink = time; + } + + lifetime += frametime; + + return PREDRAW_NEXT; +} + +void +func_dustcloud_cloud::func_dustcloud_cloud(void) +{ + setsize(this, [0,0,0], [0,0,0]); + drawmask = MASK_ENGINE; + lifetime = 0.0f; +} +#endif + +float +func_dustcloud::predraw(void) +{ + vector vecPlayer; + + int s = (float)getproperty(VF_ACTIVESEAT); + pSeat = &g_seats[s]; + vecPlayer = pSeat->m_vecPredictedOrigin; + + if (checkpvs(vecPlayer, this) == FALSE) + return (PREDRAW_NEXT); + + if (m_flNexTime > cltime) + return (PREDRAW_NEXT); + + for (int i = 0; i < m_iCount; i++) { + vector vecPos; + vecPos[0] = mins[0] + (random() * (maxs[0] - mins[0])); + vecPos[1] = mins[1] + (random() * (maxs[1] - mins[1])); + vecPos[2] = mins[2] + (random() * (maxs[2] - mins[2])); + + func_dustcloud_cloud cloud = spawn(func_dustcloud_cloud); + setorigin(cloud, vecPos); + cloud.m_vecColor = m_vecColor; + cloud.m_flMaxAlpha = m_flAlpha; + cloud.cloudsize[0] = random(m_flSizeMin, m_flSizeMax); + cloud.cloudsize[1] = random(m_flSizeMin, m_flSizeMax); + cloud.m_flLifeTime = random(m_flLifetimeMin, m_flLifetimeMax); + } + + m_flNexTime = cltime + 1.0f; + + addentity(self); + return (PREDRAW_NEXT); +} + +void +func_dustcloud::Init(void) +{ + super::Init(); + + precache_model(model); + setmodel(this, model); + setorigin(this, origin); + movetype = MOVETYPE_NONE; + drawmask = MASK_ENGINE; + /*m_strParticle = strcat("dustcloud_", ftos(entnum)); + localcmd(sprintf(g_dustcloud_cfg, m_strParticle));*/ +} + +void +func_dustcloud::SpawnKey(string strField, string strKey) +{ + switch (strField) { + case "count": + case "SpawnRate": + m_iCount = stoi(strKey); + break; + case "LifetimeMin": + m_flLifetimeMin = stof(strKey); + break; + case "LifetimeMax": + m_flLifetimeMax = stof(strKey); + break; + case "SizeMin": + m_flSizeMin = stof(strKey); + break; + case "SizeMax": + m_flSizeMax = stof(strKey); + break; + case "Alpha": + m_flAlpha = stof(strKey) / 255; + break; + case "Color": + m_vecColor = stov(strKey) / 255; + break; + default: + super::SpawnKey(strField, strKey); + } +} + +void +func_dustcloud::func_dustcloud(void) +{ +/* + m_iCount = vlen(size) / 100; + m_flSizeMin = 200; + m_flSizeMax = 250; + m_flAlpha = 1.0f; + m_vecColor = [1,1,1]; +*/ + solid = SOLID_NOT; + + Init(); +}