From 750bb413e98213326e277da2ed0b3ea01f5a8640 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Tue, 22 Mar 2022 16:38:31 -0700 Subject: [PATCH] prop_rope: Now a shared (client/server) entity instead of just client. Will now respect parenting so you can have very dynamic rope attachments in the world. --- src/client/entities.qc | 3 + src/client/entry.qc | 5 + src/gs-entbase/client.src | 1 - src/gs-entbase/client/env_cubemap.qc | 7 +- src/gs-entbase/client/env_sun.qc | 12 +- src/gs-entbase/shared.src | 1 + .../{client => shared}/prop_rope.qc | 204 ++++++++++++++---- src/shared/entities.h | 1 + 8 files changed, 180 insertions(+), 54 deletions(-) rename src/gs-entbase/{client => shared}/prop_rope.qc (60%) diff --git a/src/client/entities.qc b/src/client/entities.qc index 44b011e5..8fe6ad65 100644 --- a/src/client/entities.qc +++ b/src/client/entities.qc @@ -124,6 +124,9 @@ Entity_EntityUpdate(float type, float new) } ips.ReceiveEntity(new, readfloat()); break; + case ENT_PROPROPE: + prop_rope_readentity(new); + break; default: //error(sprintf("Unknown entity type update received. (%d)\n", t)); } diff --git a/src/client/entry.qc b/src/client/entry.qc index f5f09287..7460e8f0 100644 --- a/src/client/entry.qc +++ b/src/client/entry.qc @@ -391,6 +391,11 @@ CSQC_UpdateView(float w, float h, float focus) CSQC_RenderScene(); RenderTarget_Monitor_Update(); + if (g_iCubeProcess == TRUE) { + cl.PostFrame(); + continue; + } + /* all 2D operations happen after this point */ for (entity b = world; (b = findfloat(b, ::isCSQC, 1));) { NSEntity pf = (NSEntity) b; diff --git a/src/gs-entbase/client.src b/src/gs-entbase/client.src index 22736ec5..df6eb810 100644 --- a/src/gs-entbase/client.src +++ b/src/gs-entbase/client.src @@ -22,6 +22,5 @@ client/infodecal.qc client/sky_camera.qc client/info_notnull.qc client/point_message.qc -client/prop_rope.qc client/prop_static.qc #endlist diff --git a/src/gs-entbase/client/env_cubemap.qc b/src/gs-entbase/client/env_cubemap.qc index 017c2adc..1fc46536 100644 --- a/src/gs-entbase/client/env_cubemap.qc +++ b/src/gs-entbase/client/env_cubemap.qc @@ -88,6 +88,10 @@ CMap_Shoot(void) print("^3Cubemap processing...\n"); g_vecCubePos = tmp.origin; g_dCubeSize = (float)tmp.m_iSize; + + setproperty(VF_CL_VIEWANGLES, [0,0,0]); + setproperty(VF_ANGLES, [0,0,0]); + strReflectcube = sprintf( "env/%s_%d_%d_%d", mapname, @@ -133,8 +137,9 @@ CMap_Build void CMap_Build(void) { + /* prevent command spam */ if (g_iCubeProcess == TRUE) { - return; + return; } localcmd("r_speeds 0\n"); diff --git a/src/gs-entbase/client/env_sun.qc b/src/gs-entbase/client/env_sun.qc index b149eee6..b6fd03f4 100644 --- a/src/gs-entbase/client/env_sun.qc +++ b/src/gs-entbase/client/env_sun.qc @@ -174,7 +174,7 @@ env_sun_lensflare(vector m_vecLensPos, float m_flLensAlpha, vector vecColor) vector player_pos = getproperty(VF_ORIGIN); vector player_angle = getproperty(VF_CL_VIEWANGLES); - m_flLensAlpha *= 0.15f; + m_flLensAlpha *= 0.5f; if (m_flLensAlpha <= 0.0f) { return; @@ -201,12 +201,12 @@ env_sun_lensflare(vector m_vecLensPos, float m_flLensAlpha, vector vecColor) player_angle[0] *= -1; vector test1, test2; - makevectors(vectoangles(m_vecLensPos - player_pos)); - test1 = v_forward; - makevectors(player_angle); - test2 = v_forward; + test1 = project(m_vecLensPos); + test2 = video_res / 2; + + vector c = (test2 - test1) * 1.25f; + m_flLensAlpha = bound(0.0, 1.0 - (vlen(c) / 350), 1.0f) * m_flLensAlpha; - vector c = (test1 - test2) * 512; 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); drawpic(lens_1 + c * 0.2, "textures/sfx/flare3", FLARE_SIZE, vecColor * m_flLensAlpha, 1.0f, DRAWFLAG_ADDITIVE); diff --git a/src/gs-entbase/shared.src b/src/gs-entbase/shared.src index 4981472e..c61f20cb 100644 --- a/src/gs-entbase/shared.src +++ b/src/gs-entbase/shared.src @@ -28,5 +28,6 @@ shared/trigger_camera.qc shared/trigger_gravity.qc shared/info_particle_system.qc shared/prop_vehicle_driveable.qc +shared/prop_rope.qc shared/worldspawn.qc #endlist diff --git a/src/gs-entbase/client/prop_rope.qc b/src/gs-entbase/shared/prop_rope.qc similarity index 60% rename from src/gs-entbase/client/prop_rope.qc rename to src/gs-entbase/shared/prop_rope.qc index 6d7c38d9..1d54faf6 100644 --- a/src/gs-entbase/client/prop_rope.qc +++ b/src/gs-entbase/shared/prop_rope.qc @@ -32,6 +32,16 @@ ROPE_HALF : Only draw the first half of the rope, useful for vertical setups. This entity was introduced in The Wastes (2018). */ +typedef enumflags +{ + PROPROPE_CHANGED_MAT, + PROPROPE_CHANGED_SAG, + PROPROPE_CHANGED_SWING, + PROPROPE_CHANGED_SEGMENTS, + PROPROPE_CHANGED_ORIGIN, + PROPROPE_CHANGED_TARGET +}; + #define ROPE_RIBBON void(float radius, vector texcoordbias) R_EndPolygonRibbon = #0; @@ -41,20 +51,26 @@ var int autocvar_rope_debug = FALSE; class prop_rope:NSEntity { string m_strShader; - float m_flSag; - float m_flSwingFactor; - int m_iSegments; + PREDICTED_FLOAT(m_flSag); + PREDICTED_FLOAT(m_flSwingFactor); + PREDICTED_INT(m_iSegments); + PREDICTED_VECTOR(m_vecTarget); void(void) prop_rope; - virtual float() predraw; - virtual void(string, string) SpawnKey; - virtual void(void) RendererRestarted; -#ifndef ROPE_RIBBON - virtual void(vector, vector, int) draw_segment; +#ifdef CLIENT + virtual float() predraw; + virtual void(float,float) ReadEntity; +#else + virtual void(void) Respawn; + virtual void(void) EvaluateEntity; + virtual float(entity, float) SendEntity; + virtual void(string, string) SpawnKey; #endif }; +#ifdef CLIENT + #ifndef ROPE_RIBBON void prop_rope::draw_segment(vector start, vector end, int flip) @@ -118,8 +134,6 @@ prop_rope::predraw(void) float sc; vector vecPlayer; - entity x = find(world, ::targetname, target); - int s = (float)getproperty(VF_ACTIVESEAT); pSeat = &g_seats[s]; vecPlayer = pSeat->m_vecPredictedOrigin; @@ -127,26 +141,17 @@ prop_rope::predraw(void) if (checkpvs(vecPlayer, this) == FALSE) return (PREDRAW_NEXT); - if (!x) { -#ifdef GS_DEVELOPER - print(sprintf("%s::predraw: Unknown target '%s'\n", - this.classname, target)); -#endif - remove(this); - return (PREDRAW_NEXT); - } - /* draw the start/end without segments */ if (autocvar_rope_debug == TRUE) { R_BeginPolygon("", 0, 0); R_PolygonVertex(origin, [0,1], [0,1,0], 1.0f); - R_PolygonVertex(x.origin, [1,1], [0,1,0], 1.0f); + R_PolygonVertex(m_vecTarget, [1,1], [0,1,0], 1.0f); R_EndPolygon(); } segments = m_iSegments; - travel = vlen(origin - x.origin) / segments; + travel = vlen(origin - m_vecTarget) / segments; sc = 0; pos1 = origin; @@ -154,7 +159,7 @@ prop_rope::predraw(void) float sag = cos(sc) * m_flSag; /* get the direction */ - makevectors(vectoangles(x.origin - origin)); + makevectors(vectoangles(m_vecTarget - origin)); /* travel further and sag */ pos2 = pos1 + (v_forward * travel) + (v_up * -sag) + ((v_right * sin(time)) * m_flSwingFactor); @@ -183,12 +188,12 @@ prop_rope::predraw(void) } sc = 0; - pos1 = x.origin; + pos1 = m_vecTarget; for (float i = 0; i < segments / 2; i++) { float sag = cos(sc) * m_flSag; /* get the direction */ - makevectors(vectoangles(origin - x.origin)); + makevectors(vectoangles(origin - m_vecTarget)); /* travel further and sag */ pos2 = pos1 + (v_forward * travel) + (v_up * -sag) - ((v_right * sin(time)) * m_flSwingFactor); @@ -215,42 +220,149 @@ prop_rope::predraw(void) } void -prop_rope::SpawnKey(string strField, string strKey) +prop_rope::ReadEntity(float flSendFlags, float new) { - switch (strField) { - case "sag": - m_flSag = stof(strKey); - break; - case "segments": - m_iSegments = stoi(strKey); - break; - case "shader": - m_strShader = strKey; - break; - case "swingfactor": - m_flSwingFactor = stof(strKey); - break; - default: - super::SpawnKey(strField, strKey); + if (flSendFlags & PROPROPE_CHANGED_MAT) + m_strShader = readstring(); + if (flSendFlags & PROPROPE_CHANGED_SAG) + m_flSag = readfloat(); + if (flSendFlags & PROPROPE_CHANGED_SWING) + m_flSwingFactor = readfloat(); + if (flSendFlags & PROPROPE_CHANGED_SEGMENTS) + m_iSegments = readint(); + if (flSendFlags & PROPROPE_CHANGED_ORIGIN) { + origin[0] = readcoord(); + origin[1] = readcoord(); + origin[2] = readcoord(); + setsize(this, [0,0,0], [0,0,0]); + setorigin(this, origin); } + if (flSendFlags & PROPROPE_CHANGED_TARGET) { + m_vecTarget[0] = readcoord(); + m_vecTarget[1] = readcoord(); + m_vecTarget[2] = readcoord(); + } +} +#else +void +prop_rope::Respawn(void) +{ + SetOrigin(GetSpawnOrigin()); + SetSize([0,0,0], [0,0,0]); +} +void +prop_rope::EvaluateEntity(void) +{ + entity eFind = find(world, ::targetname, target); + + if (!eFind) { + print(sprintf("prop_rope: Unable to find target %S\n", target)); + return; + } + + m_vecTarget = eFind.origin; + + if (ATTR_CHANGED(m_flSag)) { + SetSendFlags(PROPROPE_CHANGED_SAG); + } + if (ATTR_CHANGED(m_flSwingFactor)) { + SetSendFlags(PROPROPE_CHANGED_SWING); + } + if (ATTR_CHANGED(m_iSegments)) { + SetSendFlags(PROPROPE_CHANGED_SEGMENTS); + } + + if (ATTR_CHANGED(origin)) { + SetSendFlags(PROPROPE_CHANGED_ORIGIN); + } + if (ATTR_CHANGED(m_vecTarget)) { + SetSendFlags(PROPROPE_CHANGED_TARGET); + } + + SAVE_STATE(m_flSag); + SAVE_STATE(m_flSwingFactor); + SAVE_STATE(m_iSegments); + SAVE_STATE(origin); + SAVE_STATE(m_vecTarget); +} + +float +prop_rope::SendEntity(entity ePVEnt, float flSendFlags) +{ + WriteByte(MSG_ENTITY, ENT_PROPROPE); + WriteFloat(MSG_ENTITY, flSendFlags); + + if (flSendFlags & PROPROPE_CHANGED_MAT) + WriteString(MSG_ENTITY, m_strShader); + if (flSendFlags & PROPROPE_CHANGED_SAG) + WriteFloat(MSG_ENTITY, m_flSag); + if (flSendFlags & PROPROPE_CHANGED_SWING) + WriteFloat(MSG_ENTITY, m_flSwingFactor); + if (flSendFlags & PROPROPE_CHANGED_SEGMENTS) + WriteInt(MSG_ENTITY, m_iSegments); + if (flSendFlags & PROPROPE_CHANGED_ORIGIN) { + WriteCoord(MSG_ENTITY, origin[0]); + WriteCoord(MSG_ENTITY, origin[1]); + WriteCoord(MSG_ENTITY, origin[2]); + } + if (flSendFlags & PROPROPE_CHANGED_TARGET) { + WriteCoord(MSG_ENTITY, m_vecTarget[0]); + WriteCoord(MSG_ENTITY, m_vecTarget[1]); + WriteCoord(MSG_ENTITY, m_vecTarget[2]); + } + + return 1; } void -prop_rope::RendererRestarted(void) +prop_rope::SpawnKey(string strKey, string strValue) { - precache_pic(m_strShader); + switch (strKey) { + case "sag": + m_flSag = stof(strValue); + break; + case "segments": + m_iSegments = stoi(strValue); + break; + case "shader": + m_strShader = strValue; + break; + case "swingfactor": + m_flSwingFactor = stof(strValue); + break; + default: + super::SpawnKey(strKey, strValue); + } } +#endif void prop_rope::prop_rope(void) { +#ifdef SERVER m_flSwingFactor = random(); m_flSag = 15.0f; m_iSegments = 16; m_strShader = "textures/props/wire_default"; + + super::NSEntity(); +#else + /* this is empty for a good reason */ drawmask = MASK_ENGINE; - Init(); - RendererRestarted(); - setsize(this, [0,0,0], [0,0,0]); - setorigin(this, origin); +#endif } + + +#ifdef CLIENT +void +prop_rope_readentity(float isnew) +{ + prop_rope rope = (prop_rope)self; + float flags = readfloat(); + + if (isnew) + spawnfunc_prop_rope(); + + rope.ReadEntity(flags, isnew); +} +#endif diff --git a/src/shared/entities.h b/src/shared/entities.h index 3e03d679..e9badc76 100644 --- a/src/shared/entities.h +++ b/src/shared/entities.h @@ -37,5 +37,6 @@ enum ENT_VEHICLE, ENT_VEH_TANKMORTAR, ENT_VEH_4WHEEL, + ENT_PROPROPE, ENT_SEPARATOR, };