From ceb32ec494ae925343b65a195bf9d6757185d194 Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 25 Jun 2014 03:53:11 +0000 Subject: [PATCH] reworked penalties flags. now a single bitfield instead of separate booleans. added 'blind' penalty. tweaked portals again. no longer wrongly impacting against the portal's front/back planes, even with speed. reworked PEXT_LIGHTSTYLECOL, now uses a vector instead of a channel mask. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4699 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_demo.c | 7 +- engine/client/cl_main.c | 2 +- engine/client/cl_parse.c | 36 +++--- engine/client/cl_screen.c | 6 +- engine/client/client.h | 3 +- engine/client/pr_csqc.c | 9 +- engine/client/r_surf.c | 46 ++++--- engine/client/render.h | 1 + engine/common/pmove.c | 2 +- engine/common/pmovetst.c | 52 +++++--- engine/common/pr_common.h | 2 +- engine/common/q1bsp.c | 1 - engine/gl/gl_model.h | 2 +- engine/gl/gl_rlight.c | 62 ++++----- engine/gl/gl_shadow.c | 15 +-- engine/server/pr_cmds.c | 77 +++++++----- engine/server/pr_lua.c | 4 +- engine/server/pr_q1qvm.c | 5 +- engine/server/server.h | 11 +- engine/server/sv_ccmds.c | 258 +++++++++++++------------------------- engine/server/sv_ents.c | 13 +- engine/server/sv_main.c | 38 +++--- engine/server/sv_mvd.c | 7 +- engine/server/sv_phys.c | 5 +- engine/server/sv_send.c | 5 + engine/server/sv_user.c | 41 +++--- engine/server/world.c | 38 ++++-- 27 files changed, 378 insertions(+), 370 deletions(-) diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 527c26719..ec7854267 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1402,11 +1402,14 @@ void CL_Record_f (void) continue; #ifdef PEXT_LIGHTSTYLECOL - if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && cl_lightstyle[i].colour!=7 && *cl_lightstyle[i].map) + if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (cl_lightstyle[i].colours[0]!=1||cl_lightstyle[i].colours[1]!=1||cl_lightstyle[i].colours[2]!=1) && *cl_lightstyle[i].map) { MSG_WriteByte (&buf, svcfte_lightstylecol); MSG_WriteByte (&buf, (unsigned char)i); - MSG_WriteByte (&buf, cl_lightstyle[i].colour); + MSG_WriteByte (&buf, 0x87); + MSG_WriteShort (&buf, cl_lightstyle[i].colours[0]*1024); + MSG_WriteShort (&buf, cl_lightstyle[i].colours[1]*1024); + MSG_WriteShort (&buf, cl_lightstyle[i].colours[2]*1024); MSG_WriteString (&buf, cl_lightstyle[i].map); } else diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 2480db291..19f0cc67e 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1336,7 +1336,7 @@ void CL_ClearState (void) // memset (cl_dlights, 0, sizeof(cl_dlights)); memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); for (i = 0; i < MAX_LIGHTSTYLES; i++) - cl_lightstyle[i].colour = 7; + R_UpdateLightStyle(i, NULL, 1, 1, 1); rtlights_first = rtlights_max = RTL_FIRST; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index c1c6ff9b6..df7754417 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -3765,15 +3765,12 @@ void CLQ2_ParseConfigString (void) } else if (i >= Q2CS_LIGHTS && i < Q2CS_LIGHTS+Q2MAX_LIGHTSTYLES) { - cl_lightstyle[i - Q2CS_LIGHTS].colour = 7; //white - Q_strncpyz (cl_lightstyle[i - Q2CS_LIGHTS].map, s, sizeof(cl_lightstyle[i-Q2CS_LIGHTS].map)); - cl_lightstyle[i - Q2CS_LIGHTS].length = Q_strlen(cl_lightstyle[i - Q2CS_LIGHTS].map); - + R_UpdateLightStyle(i, s, 1, 1, 1); } else if (i == Q2CS_CDTRACK) { // if (cl.refresh_prepped) - Media_NumberedTrack (atoi(s), atoi(s)); + Media_BackgroundTrack (s, NULL); } else if (i >= Q2CS_MODELS && i < Q2CS_MODELS+Q2MAX_MODELS) { @@ -5928,9 +5925,7 @@ void CLQW_ParseServerMessage (void) i = MSG_ReadByte (); if (i >= MAX_LIGHTSTYLES) Host_EndGame ("svc_lightstyle > MAX_LIGHTSTYLES"); - cl_lightstyle[i].colour = 7; //white - Q_strncpyz (cl_lightstyle[i].map, MSG_ReadString(), sizeof(cl_lightstyle[i].map)); - cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); + R_UpdateLightStyle(i, MSG_ReadString(), 1, 1, 1); break; #ifdef PEXT_LIGHTSTYLECOL case svcfte_lightstylecol: @@ -5939,9 +5934,24 @@ void CLQW_ParseServerMessage (void) i = MSG_ReadByte (); if (i >= MAX_LIGHTSTYLES) Host_EndGame ("svc_lightstyle > MAX_LIGHTSTYLES"); - cl_lightstyle[i].colour = MSG_ReadByte(); - Q_strncpyz (cl_lightstyle[i].map, MSG_ReadString(), sizeof(cl_lightstyle[i].map)); - cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); + { + int bits; + vec3_t rgb; + bits = MSG_ReadByte(); + if (bits & 0x80) + { + rgb[0] = MSG_ReadShort()/1024.0; + rgb[1] = MSG_ReadShort()/1024.0; + rgb[1] = MSG_ReadShort()/1024.0; + } + else + { + rgb[0] = (bits&1)?1:0; + rgb[1] = (bits&2)?1:0; + rgb[2] = (bits&4)?1:0; + } + R_UpdateLightStyle(i, MSG_ReadString(), rgb[0], rgb[1], rgb[2]); + } break; #endif @@ -6915,9 +6925,7 @@ void CLNQ_ParseServerMessage (void) MSG_ReadString(); break; } - cl_lightstyle[i].colour = 7; //white - Q_strncpyz (cl_lightstyle[i].map, MSG_ReadString(), sizeof(cl_lightstyle[i].map)); - cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); + R_UpdateLightStyle(i, MSG_ReadString(), 1, 1, 1); break; case svcnq_updatestatlong: diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 6ed660b91..1bae0555c 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -404,7 +404,11 @@ void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode) void SCR_CPrint_f(void) { - SCR_CenterPrint(0, Cmd_Args(), true); + char *s = Cmd_Args(); + if (Cmd_Argc() == 2) + SCR_CenterPrint(0, Cmd_Argv(1), true); + else + SCR_CenterPrint(0, Cmd_Args(), true); } void SCR_EraseCenterString (void) diff --git a/engine/client/client.h b/engine/client/client.h index 479ab8064..ffd1bd136 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -296,7 +296,8 @@ typedef struct { int length; char map[MAX_STYLESTRING]; - int colour; + vec3_t colours; + int colourkey; } lightstyle_t; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index ff58faf5f..7a57f9ce2 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -3010,16 +3010,17 @@ static void QCBUILTIN PF_cs_lightstyle (pubprogfuncs_t *prinst, struct globalvar { int stnum = G_FLOAT(OFS_PARM0); const char *str = PR_GetStringOfs(prinst, OFS_PARM1); - int colourflags = 7; + vec3_t rgb = {1,1,1}; + + if (prinst->callargc >= 3) //fte is a quakeworld engine + VectorCopy(G_VECTOR(OFS_PARM2), rgb); if ((unsigned)stnum >= MAX_LIGHTSTYLES) { Con_Printf ("PF_cs_lightstyle: stnum > MAX_LIGHTSTYLES"); return; } - cl_lightstyle[stnum].colour = colourflags; - Q_strncpyz (cl_lightstyle[stnum].map, str, sizeof(cl_lightstyle[stnum].map)); - cl_lightstyle[stnum].length = Q_strlen(cl_lightstyle[stnum].map); + R_UpdateLightStyle(stnum, str, rgb[0],rgb[1],rgb[2]); } //entity(string field, float match) findchainflags = #450 diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 6cd01c226..85b6d1031 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -982,11 +982,11 @@ static void Surf_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest, { scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_light[maps] = scale; // 8.8 fraction - surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; + surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; if (scale) { - if (cl_lightstyle[surf->styles[maps]].colour == 7) //hopefully a faster alternative. + if (cl_lightstyle[surf->styles[maps]].colours[0] == 1 && cl_lightstyle[surf->styles[maps]].colours[1] == 1 && cl_lightstyle[surf->styles[maps]].colours[2] == 1) //hopefully a faster alternative. { bl = blocklights; for (i=0 ; istyles[maps]].colour & 1) + if (cl_lightstyle[surf->styles[maps]].colours[0]) + { + scale = d_lightstylevalue[surf->styles[maps]] * cl_lightstyle[surf->styles[maps]].colours[0]; for (i=0 ; istyles[maps]].colour & 2) + } + if (cl_lightstyle[surf->styles[maps]].colours[1]) + { + scale = d_lightstylevalue[surf->styles[maps]] * cl_lightstyle[surf->styles[maps]].colours[1]; for (i=0 ; istyles[maps]].colour & 4) + } + if (cl_lightstyle[surf->styles[maps]].colours[2]) + { + scale = d_lightstylevalue[surf->styles[maps]] * cl_lightstyle[surf->styles[maps]].colours[2]; for (i=0 ; istyles[maps]]; surf->cached_light[maps] = scale; // 8.8 fraction - surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; + surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; - if (cl_lightstyle[surf->styles[maps]].colour == 7) //hopefully a faster alternative. + if (cl_lightstyle[surf->styles[maps]].colours[0] == 1 && cl_lightstyle[surf->styles[maps]].colours[1] == 1 && cl_lightstyle[surf->styles[maps]].colours[2] == 1) //hopefully a faster alternative. { bl = blocklights; for (i=0 ; istyles[maps]].colour & 1) + if (cl_lightstyle[surf->styles[maps]].colours[0]) + { + scale = d_lightstylevalue[surf->styles[maps]] * cl_lightstyle[surf->styles[maps]].colours[0]; for (i=0, bl = blocklights; istyles[maps]].colour & 2) + } + if (cl_lightstyle[surf->styles[maps]].colours[1]) + { + scale = d_lightstylevalue[surf->styles[maps]] * cl_lightstyle[surf->styles[maps]].colours[1]; for (i=0, bl = blocklights+1; istyles[maps]].colour & 4) + } + if (cl_lightstyle[surf->styles[maps]].colours[2]) + { + scale = d_lightstylevalue[surf->styles[maps]] * cl_lightstyle[surf->styles[maps]].colours[2]; for (i=0, bl = blocklights+2; icached_light[0] = d_lightstylevalue[0]; - surf->cached_colour[0] = cl_lightstyle[0].colour; + surf->cached_colour[0] = cl_lightstyle[0].colourkey; } else if (r_fullbright.ival) { @@ -1120,7 +1138,7 @@ static void Surf_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest, { scale = d_lightstylevalue[surf->styles[maps]]/3; surf->cached_light[maps] = scale; // 8.8 fraction - surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; + surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; for (i=0 ; istyles[maps]]; surf->cached_light[maps] = scale; // 8.8 fraction - surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colour; + surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; for (i=0 ; istyles[maps] != 255 ; maps++) if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps] - || cl_lightstyle[fa->styles[maps]].colour != fa->cached_colour[maps]) + || cl_lightstyle[fa->styles[maps]].colourkey != fa->cached_colour[maps]) goto dynamic; } diff --git a/engine/client/render.h b/engine/client/render.h index a2f861026..82129dd61 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -467,6 +467,7 @@ qbyte *R_MarkLeaves_Q3 (void); void R_SetFrustum (float projmat[16], float viewmat[16]); void R_SetRenderer(rendererinfo_t *ri); void R_AnimateLight (void); +void R_UpdateLightStyle(unsigned int style, const char *stylestring, float r, float g, float b); struct texture_s *R_TextureAnimation (int frame, struct texture_s *base); //mostly deprecated, only lingers for rtlights so world only. struct texture_s *R_TextureAnimation_Q2 (struct texture_s *base); //mostly deprecated, only lingers for rtlights so world only. void RQ_Init(void); diff --git a/engine/common/pmove.c b/engine/common/pmove.c index c426326e9..127d15510 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -150,7 +150,7 @@ static trace_t PM_PlayerTracePortals(vec3_t start, vec3_t end, unsigned int soli if (tookportal) *tookportal = trace.fraction; - trace = PM_PlayerTrace (from, end, MASK_PLAYERSOLID); + return PM_PlayerTrace (from, end, MASK_PLAYERSOLID); } } } diff --git a/engine/common/pmovetst.c b/engine/common/pmovetst.c index cec891223..79f76a95b 100644 --- a/engine/common/pmovetst.c +++ b/engine/common/pmovetst.c @@ -263,12 +263,14 @@ static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t en //a portal is flush with a world surface behind it. //this causes problems. namely that we can't pass through the portal plane if the bsp behind it prevents out origin from getting through. //so if the trace was clipped and ended infront of the portal, continue the trace to the edges of the portal cutout instead. -void PM_PortalCSG(physent_t *portal, float *trmin, float *trmax, vec3_t start, vec3_t end, trace_t *trace) +static void PM_PortalCSG(physent_t *portal, int entnum, float *trmin, float *trmax, vec3_t start, vec3_t end, trace_t *trace) { vec4_t planes[6]; //far, near, right, left, up, down int plane; vec3_t worldpos; float portalradius = 128; + int hitplane = -1; + float bestfrac; //only run this code if we impacted on the portal's parent. if (trace->fraction == 1 && !trace->startsolid) return; @@ -287,8 +289,8 @@ void PM_PortalCSG(physent_t *portal, float *trmin, float *trmax, vec3_t start, v VectorNegate(planes[5], planes[4]); portalradius/=2; - planes[0][3] = DotProduct(portal->origin, planes[0]) - (1.1/32); - planes[1][3] = DotProduct(portal->origin, planes[1]) - (1.1/32); //an epsilon beyond the portal + planes[0][3] = DotProduct(portal->origin, planes[0]) - (4.0/32); + planes[1][3] = DotProduct(portal->origin, planes[1]) - (4.0/32); //an epsilon beyond the portal. this needs to cover funny angle differences planes[2][3] = DotProduct(portal->origin, planes[2]) - portalradius; planes[3][3] = DotProduct(portal->origin, planes[3]) - portalradius; planes[4][3] = DotProduct(portal->origin, planes[4]) - portalradius; @@ -305,16 +307,15 @@ void PM_PortalCSG(physent_t *portal, float *trmin, float *trmax, vec3_t start, v if (!plane) //front plane gets further away with side planes[plane][3] -= DotProduct(nearest, planes[plane]); else if (plane>1) //side planes get nearer with size - planes[plane][3] += DotProduct(nearest, planes[plane]); + planes[plane][3] += 24;//+= DotProduct(nearest, planes[plane]); if (d - planes[plane][3] >= 0) continue; //endpos is inside else return; //end is already outside } //yup, we're inside, the trace shouldn't end where it actually did - trace->fraction = 1; - trace->startsolid = trace->allsolid = false; - VectorInterpolate(start, 1, end, trace->endpos); + bestfrac = 1; + hitplane = -1; for (plane = 0; plane < 6; plane++) { float ds = DotProduct(start, planes[plane]) - planes[plane][3]; @@ -322,18 +323,32 @@ void PM_PortalCSG(physent_t *portal, float *trmin, float *trmax, vec3_t start, v float frac; if (ds >= 0 && de < 0) { - frac = (ds-(1.0/32)) / (ds - de); - if (frac < trace->fraction) + frac = (ds - (1/32.0)) / (ds - de); + if (frac < bestfrac) { if (frac < 0) frac = 0; - trace->fraction = frac; + hitplane = plane; + bestfrac = frac; VectorInterpolate(start, frac, end, trace->endpos); - VectorCopy(planes[plane], trace->plane.normal); - trace->plane.dist = planes[plane][3]; } } } + trace->startsolid = trace->allsolid = false; + //if we cross the front of the portal, don't shorten the trace, that will artificially clip us + if (hitplane == 0 && trace->fraction > bestfrac) + return; + //okay, elongate to clip to the portal hole properly. + trace->fraction = bestfrac; + VectorInterpolate(start, bestfrac, end, trace->endpos); + + if (hitplane >= 0) + { + VectorCopy(planes[hitplane], trace->plane.normal); + trace->plane.dist = planes[hitplane][3]; + if (hitplane == 1) + trace->entnum = entnum; + } } /* @@ -377,7 +392,7 @@ qboolean PM_TestPlayerPosition (vec3_t pos) { pe = &pmove.physents[j]; if (pe->isportal) - PM_PortalCSG(pe, pmove.player_mins, pmove.player_maxs, pos, pos, &trace); + PM_PortalCSG(pe, j, pmove.player_mins, pmove.player_maxs, pos, pos, &trace); } if (trace.allsolid) return false; @@ -441,7 +456,7 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask) else if (pe->isportal) { //make sure we don't hit the world if we're inside the portal - PM_PortalCSG(pe, pmove.player_mins, pmove.player_maxs, start, end, &total); + PM_PortalCSG(pe, i, pmove.player_mins, pmove.player_maxs, start, end, &total); // trace a line through the apropriate clipping hull if (!PM_TransformedHullCheck (pe->model, start, end, vec3_origin, vec3_origin, &trace, pe->origin, pe->angles)) @@ -459,7 +474,7 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask) { pe = &pmove.physents[j]; if (pe->isportal) - PM_PortalCSG(pe, pmove.player_mins, pmove.player_maxs, start, end, &trace); + PM_PortalCSG(pe, j, pmove.player_mins, pmove.player_maxs, start, end, &trace); } pe = &pmove.physents[i]; } @@ -469,13 +484,10 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask) trace.startsolid = true; if (trace.startsolid && pe->isportal) - continue; - - if (trace.startsolid) - trace.fraction = 0; + trace.startsolid = false; // did we clip the move? - if (trace.fraction < total.fraction) + if (trace.fraction < total.fraction || (trace.startsolid && !total.startsolid)) { // fix trace up by the offset total = trace; diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 3ff1506a1..82c7d48a8 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -448,7 +448,7 @@ void QCBUILTIN PF_WriteEntity (pubprogfuncs_t *prinst, struct globalvars_s *pr_g void QCBUILTIN PF_multicast (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_svtraceline (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_changelevel (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); -void QCBUILTIN PF_applylightstyle(int style, const char *val, int col); +void QCBUILTIN PF_applylightstyle(int style, const char *val, vec3_t rgb); void PF_ambientsound_Internal (float *pos, const char *samp, float vol, float attenuation); void QCBUILTIN PF_makestatic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_logfrag (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 9ab932241..0ffdc0ec4 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -843,7 +843,6 @@ hull_t *Q1BSP_ChooseHull(model_t *model, int forcehullnum, vec3_t mins, vec3_t m qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int hitcontentsmask, trace_t *trace) { hull_t *hull; - vec3_t size; vec3_t start_l, end_l; vec3_t offset; diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 5d41120a1..27812a661 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -384,8 +384,8 @@ typedef struct msurface_s qbyte styles[MAXQ1LIGHTMAPS]; qbyte vlstyles[MAXRLIGHTMAPS]; int cached_light[MAXQ1LIGHTMAPS]; // values currently used in lightmap + int cached_colour[MAXQ1LIGHTMAPS]; qboolean cached_dlight; // true if dynamic light in cache - qbyte cached_colour[MAXQ1LIGHTMAPS]; #ifndef NOSTAINS qboolean stained; #endif diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 162302274..4000bd37e 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -30,6 +30,26 @@ extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps; int r_dlightframecount; int d_lightstylevalue[256]; // 8.8 fraction of base light value +void R_UpdateLightStyle(unsigned int style, const char *stylestring, float r, float g, float b) +{ + if (style >= MAX_LIGHTSTYLES) + return; + + if (!stylestring) + stylestring = ""; + + Q_strncpyz (cl_lightstyle[style].map, stylestring, sizeof(cl_lightstyle[style].map)); + cl_lightstyle[style].length = Q_strlen(cl_lightstyle[style].map); + if (!cl_lightstyle[style].length) + { + d_lightstylevalue[style] = 256; + VectorSet(cl_lightstyle[style].colours, 1,1,1); + } + else + VectorSet(cl_lightstyle[style].colours, r,g,b); + cl_lightstyle[style].colourkey = (int)(cl_lightstyle[style].colours[0]*0x400) ^ (int)(cl_lightstyle[style].colours[1]*0x100000) ^ (int)(cl_lightstyle[style].colours[2]*0x40000000); +} + /* ================== R_AnimateLight @@ -52,13 +72,9 @@ void R_AnimateLight (void) for (j=0 ; jstyles[maps]]*overbright; - if (cl_lightstyle[surf->styles[maps]].colour & 1) - l[0] += lightmap[0] * scale; - if (cl_lightstyle[surf->styles[maps]].colour & 2) - l[1] += lightmap[1] * scale; - if (cl_lightstyle[surf->styles[maps]].colour & 4) - l[2] += lightmap[2] * scale; + l[0] += lightmap[0] * scale * cl_lightstyle[surf->styles[maps]].colours[0]; + l[1] += lightmap[1] * scale * cl_lightstyle[surf->styles[maps]].colours[1]; + l[2] += lightmap[2] * scale * cl_lightstyle[surf->styles[maps]].colours[2]; l[3] += (deluxmap[0]-127)*scale; l[4] += (deluxmap[1]-127)*scale; @@ -1359,12 +1372,9 @@ float *GLRecursiveLightPoint3C (mnode_t *node, vec3_t start, vec3_t end) { scale = d_lightstylevalue[surf->styles[maps]]*overbright; - if (cl_lightstyle[surf->styles[maps]].colour & 1) - l[0] += *lightmap * scale; - if (cl_lightstyle[surf->styles[maps]].colour & 2) - l[1] += *lightmap * scale; - if (cl_lightstyle[surf->styles[maps]].colour & 4) - l[2] += *lightmap * scale; + l[0] += *lightmap * scale * cl_lightstyle[surf->styles[maps]].colours[0]; + l[1] += *lightmap * scale * cl_lightstyle[surf->styles[maps]].colours[1]; + l[2] += *lightmap * scale * cl_lightstyle[surf->styles[maps]].colours[2]; l[3] += deluxmap[0]*scale; l[4] += deluxmap[1]*scale; @@ -1388,12 +1398,9 @@ float *GLRecursiveLightPoint3C (mnode_t *node, vec3_t start, vec3_t end) { scale = d_lightstylevalue[surf->styles[maps]]*overbright; - if (cl_lightstyle[surf->styles[maps]].colour & 1) - l[0] += lightmap[0] * scale; - if (cl_lightstyle[surf->styles[maps]].colour & 2) - l[1] += lightmap[1] * scale; - if (cl_lightstyle[surf->styles[maps]].colour & 4) - l[2] += lightmap[2] * scale; + l[0] += lightmap[0] * scale * cl_lightstyle[surf->styles[maps]].colours[0]; + l[1] += lightmap[1] * scale * cl_lightstyle[surf->styles[maps]].colours[1]; + l[2] += lightmap[2] * scale * cl_lightstyle[surf->styles[maps]].colours[2]; lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1) * 3; @@ -1408,12 +1415,9 @@ float *GLRecursiveLightPoint3C (mnode_t *node, vec3_t start, vec3_t end) { scale = d_lightstylevalue[surf->styles[maps]]*overbright; - if (cl_lightstyle[surf->styles[maps]].colour & 1) - l[0] += *lightmap * scale; - if (cl_lightstyle[surf->styles[maps]].colour & 2) - l[1] += *lightmap * scale; - if (cl_lightstyle[surf->styles[maps]].colour & 4) - l[2] += *lightmap * scale; + l[0] += *lightmap * scale * cl_lightstyle[surf->styles[maps]].colours[0]; + l[1] += *lightmap * scale * cl_lightstyle[surf->styles[maps]].colours[1]; + l[2] += *lightmap * scale * cl_lightstyle[surf->styles[maps]].colours[2]; lightmap += ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1); diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index f57075b39..89182021f 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -3406,18 +3406,9 @@ void Sh_DrawLights(qbyte *vis) colour[2] = dl->color[2]; if (dl->style) { - if (cl_lightstyle[dl->style-1].colour & 1) - colour[0] *= d_lightstylevalue[dl->style-1]/255.0f; - else - colour[0] = 0; - if (cl_lightstyle[dl->style-1].colour & 2) - colour[1] *= d_lightstylevalue[dl->style-1]/255.0f; - else - colour[1] = 0; - if (cl_lightstyle[dl->style-1].colour & 4) - colour[2] *= d_lightstylevalue[dl->style-1]/255.0f; - else - colour[2] = 0; + colour[0] *= cl_lightstyle[dl->style-1].colours[0] * d_lightstylevalue[dl->style-1]/255.0f; + colour[1] *= cl_lightstyle[dl->style-1].colours[1] * d_lightstylevalue[dl->style-1]/255.0f; + colour[2] *= cl_lightstyle[dl->style-1].colours[2] * d_lightstylevalue[dl->style-1]/255.0f; } if (colour[0] < 0.001 && colour[1] < 0.001 && colour[2] < 0.001) diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index e505de1dd..92e9b3947 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -3970,7 +3970,7 @@ static void QCBUILTIN PF_walkmove (pubprogfuncs_t *prinst, struct globalvars_s * pr_global_struct->self = oldself; } -void QCBUILTIN PF_applylightstyle(int style, const char *val, int col) +void QCBUILTIN PF_applylightstyle(int style, const char *val, vec3_t rgb) { client_t *client; int j; @@ -3990,7 +3990,7 @@ void QCBUILTIN PF_applylightstyle(int style, const char *val, int col) sv.strings.lightstyles[style] = Z_StrDup(val); #ifdef PEXT_LIGHTSTYLECOL - sv.strings.lightstylecolours[style] = col; + VectorCopy(rgb, sv.strings.lightstylecolours[style]); #endif // send message to all clients on this server @@ -4007,11 +4007,14 @@ void QCBUILTIN PF_applylightstyle(int style, const char *val, int col) if (!*val) continue; #ifdef PEXT_LIGHTSTYLECOL - if ((client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && col!=7) + if ((client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (rgb[0] != 1 || rgb[1] != 1 || rgb[2] != 1)) { ClientReliableWrite_Begin (client, svcfte_lightstylecol, strlen(val)+4); ClientReliableWrite_Byte (client, style); - ClientReliableWrite_Char (client, col); + ClientReliableWrite_Char (client, 0x87); + ClientReliableWrite_Short (client, rgb[0]*1024); + ClientReliableWrite_Short (client, rgb[1]*1024); + ClientReliableWrite_Short (client, rgb[2]*1024); ClientReliableWrite_String (client, val); } else @@ -4038,22 +4041,17 @@ static void QCBUILTIN PF_lightstyle (pubprogfuncs_t *prinst, struct globalvars_s { int style; const char *val; + vec3_t rgb = {1,1,1}; #ifdef PEXT_LIGHTSTYLECOL - int col; if (svprogfuncs->callargc >= 3) - { - col = G_FLOAT(OFS_PARM2); - if (IS_NAN(col) || !col || col > 0x111) - col = 7; - } - else col = 7; + VectorCopy(G_VECTOR(OFS_PARM2), rgb); #endif style = G_FLOAT(OFS_PARM0); val = PR_GetStringOfs(prinst, OFS_PARM1); - PF_applylightstyle(style, val, col); + PF_applylightstyle(style, val, rgb); } static void QCBUILTIN PF_lightstylevalue (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -4081,16 +4079,11 @@ static void QCBUILTIN PF_lightstylestatic (pubprogfuncs_t *prinst, struct global "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" }; + vec3_t rgb = {1,1,1}; #ifdef PEXT_LIGHTSTYLECOL - int col; if (svprogfuncs->callargc >= 3) - { - col = G_FLOAT(OFS_PARM2); - if (IS_NAN(col) || !col || col > 0x111) - col = 7; - } - else col = 7; + VectorCopy(G_VECTOR(OFS_PARM2), rgb); #endif style = G_FLOAT(OFS_PARM0); @@ -4101,7 +4094,7 @@ static void QCBUILTIN PF_lightstylestatic (pubprogfuncs_t *prinst, struct global num = 'z'-'a'-1; val = styleDefs[num]; - PF_applylightstyle(style, val, col); + PF_applylightstyle(style, val, rgb); } /* @@ -4357,7 +4350,7 @@ extern sizebuf_t csqcmsgbuffer; void QCBUILTIN PF_WriteByte (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int dest = G_FLOAT(OFS_PARM0); - qbyte val = (qbyte)G_FLOAT(OFS_PARM1); + qbyte val = 0xff & (int)G_FLOAT(OFS_PARM1); if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteByte(&csqcmsgbuffer, val); @@ -4400,7 +4393,7 @@ void QCBUILTIN PF_WriteByte (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo void QCBUILTIN PF_WriteChar (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int dest = G_FLOAT(OFS_PARM0); - char val = (char)G_FLOAT(OFS_PARM1); + char val = 0xff & (int)G_FLOAT(OFS_PARM1); if (dest == MSG_CSQC) { //csqc buffers are always written. MSG_WriteChar(&csqcmsgbuffer, val); @@ -5236,17 +5229,17 @@ char *PF_infokey_Internal (int entnum, const char *key) value = ""; } else if (!strcmp(key, "*VIP")) - value = svs.clients[entnum-1].isvip?"1":""; + value = (svs.clients[entnum-1].penalties & BAN_VIP)?"1":""; else if (!strcmp(key, "*ismuted")) - value = svs.clients[entnum-1].ismuted?"1":""; + value = (svs.clients[entnum-1].penalties & BAN_MUTE)?"1":""; else if (!strcmp(key, "*isdeaf")) - value = svs.clients[entnum-1].isdeaf?"1":""; + value = (svs.clients[entnum-1].penalties & BAN_DEAF)?"1":""; else if (!strcmp(key, "*iscrippled")) - value = svs.clients[entnum-1].iscrippled?"1":""; + value = (svs.clients[entnum-1].penalties & BAN_CRIPPLED)?"1":""; else if (!strcmp(key, "*iscuffed")) - value = svs.clients[entnum-1].iscuffed?"1":""; + value = (svs.clients[entnum-1].penalties & BAN_CUFF)?"1":""; else if (!strcmp(key, "*islagged")) - value = svs.clients[entnum-1].islagged?"1":""; + value = (svs.clients[entnum-1].penalties & BAN_LAGGED)?"1":""; else value = Info_ValueForKey (svs.clients[entnum-1].userinfo, key); } else @@ -8614,6 +8607,7 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars VectorCopy(ent->v->maxs, pmove.player_maxs); VectorCopy(ent->v->mins, pmove.player_mins); + pmove.world = &sv.world; pmove.skipent = -1; pmove.numphysent = 1; pmove.physents[0].model = sv.world.worldmodel; @@ -8645,6 +8639,8 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars VectorCopy(pmove.velocity, ent->v->velocity); + VectorCopy(pmove.angles, sv_player->v->v_angle); + ent->v->waterlevel = pmove.waterlevel; @@ -8694,6 +8690,7 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) { if (gfuncs.RunClientCommand) { + vec3_t startangle; #ifdef SVCHAT if (SV_ChatMove(ucmd->impulse)) { @@ -8709,6 +8706,7 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) sv_player->v->v_angle[1] = SHORT2ANGLE(ucmd->angles[1]); sv_player->v->v_angle[2] = SHORT2ANGLE(ucmd->angles[2]); } + VectorCopy(sv_player->v->v_angle, startangle); if (progstype == PROG_H2) sv_player->xv->light_level = 128; //hmm... HACK!!! @@ -8725,7 +8723,7 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) if (ucmd->impulse && SV_FilterImpulse(ucmd->impulse, host_client->trustlevel)) sv_player->v->impulse = ucmd->impulse; - if (host_client->iscuffed) + if (host_client->penalties & BAN_CUFF) { sv_player->v->impulse = 0; sv_player->v->button0 = 0; @@ -8792,6 +8790,23 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, client->edict); PR_ExecuteProgram(svprogfuncs, gfuncs.RunClientCommand); + + + if (!sv_player->v->fixangle) + { + int i; + vec3_t delta; + VectorSubtract (sv_player->v->v_angle, startangle, delta); + + if (delta[0] || delta[1] || delta[2]) + { + //eular angle changes suck + client_t *cl = ClientReliableWrite_BeginSplit(client, svcfte_setangledelta, 7); + for (i=0 ; i < 3 ; i++) + ClientReliableWrite_Angle16 (cl, delta[i]); + } + + } return true; } return false; @@ -8960,7 +8975,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"setmodel", PF_setmodel, 3, 3, 3, 0, D("void(entity e, string m)","Looks up m in the model precache list, and sets both e.model and e.modelindex to match. BSP models will set e.mins and e.maxs accordingly, other models depend upon the value of sv_gameplayfix_setmodelrealbox - for compatibility you should always call setsize after all pickups or non-bsp models. Also relinks collision state.")}, {"setsize", PF_setsize, 4, 4, 4, 0, D("void(entity e, vector min, vector max)", "Sets the e's mins and maxs fields. Also relinks collision state, which sets absmin and absmax too.")}, {"qtest_setabssize",PF_setsize, 5, 0, 0, 0, D("void(entity e, vector min, vector max)", "qtest"), true}, - {"lightstylestatic",PF_lightstylestatic,0, 0, 5, 5, D("void(float style, float val)", "Sets the lightstyle to an explicit numerical level. From Hexen2.")}, + {"lightstylestatic",PF_lightstylestatic,0, 0, 5, 5, D("void(float style, float val, optional vector rgb)", "Sets the lightstyle to an explicit numerical level. From Hexen2.")}, {"breakpoint", PF_break, 6, 6, 6, 0, D("void()", "Trigger a debugging event. FTE will break into the qc debugger. Other engines may crash with a debug execption.")}, {"random", PF_random, 7, 7, 7, 0, D("float()", "Returns a random value between 0 and 1. Be warned, this builtin can return 1 in most engines, which can break arrays.")}, {"sound", PF_sound, 8, 8, 8, 0, D("void(entity e, float chan, string samp, float vol, float atten, optional float speedpct, optional float flags)", "Starts a sound centered upon the given entity.\nchan is the entity sound channel to use, channel 0 will allow you to mix many samples at once, others will replace the old sample\n'samp' must have been precached first\nif specified, 'speedpct' should normally be around 100 (or =0), 200 for double speed or 50 for half speed.\nflags&1 means the sound should be sent reliably.")}, @@ -8997,7 +9012,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs // {"qtest_flymove", NULL, 33}, // float(vector dir) flymove = #33; //qbism super8's 'private'sound #33 {"droptofloor", PF_droptofloor, 34, 34, 34, 0, D("float()", "Instantly moves the entity downwards until it hits the ground. If the entity would need to drop more than 'pr_droptofloorunits' quake units, its position will be considered invalid and the builtin will abort.")}, - {"lightstyle", PF_lightstyle, 35, 35, 35, 0, D("void(float lightstyle, string stylestring, optional float channels)", "Specifies an auto-animating string that specifies the light intensity for entities using that lightstyle.\na is off, z is fully lit. Should be lower case only.\nchannels&1 enables red light.\nchannels&2 enables green light.\nchannels&4 enables blue light.\n")}, + {"lightstyle", PF_lightstyle, 35, 35, 35, 0, D("void(float lightstyle, string stylestring, optional vector rgb)", "Specifies an auto-animating string that specifies the light intensity for entities using that lightstyle.\na is off, z is fully lit. Should be lower case only.\nrgb will recolour all lights using that lightstyle.\n")}, {"rint", PF_rint, 36, 36, 36, 0, D("float(float)", "Rounds the given float up or down to the closest integeral value. X.5 rounds away from 0")}, {"floor", PF_floor, 37, 37, 37, 0, D("float(float)", "Rounds the given float downwards, even when negative.")}, {"ceil", PF_ceil, 38, 38, 38, 0, D("float(float)", "Rounds the given float upwards, even when negative.")}, diff --git a/engine/server/pr_lua.c b/engine/server/pr_lua.c index 6b6915318..720b695e4 100644 --- a/engine/server/pr_lua.c +++ b/engine/server/pr_lua.c @@ -658,7 +658,9 @@ static int bi_lua_precache_sound(lua_State *L) } static int bi_lua_lightstyle(lua_State *L) { - PF_applylightstyle(lua.tointegerx(L, 1, NULL), lua.tolstring(L, 2, NULL), 7); + vec3_t rgb; + lua_readvector(L, 3, rgb); + PF_applylightstyle(lua.tointegerx(L, 1, NULL), lua.tolstring(L, 2, NULL), rgb); return 0; } static int bi_lua_spawn(lua_State *L) diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index f2d58fd71..7f7960a41 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -597,7 +597,10 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con break; case G_LIGHTSTYLE: - PF_applylightstyle(VM_LONG(arg[0]), VM_POINTER(arg[1]), 7); + { + vec3_t rgb = {1,1,1}; + PF_applylightstyle(VM_LONG(arg[0]), VM_POINTER(arg[1]), rgb); + } break; case G_SETORIGIN: diff --git a/engine/server/server.h b/engine/server/server.h index ede9b778a..0cb68571c 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -138,7 +138,7 @@ typedef struct char particle_precache[MAX_SSPARTICLESPRE][MAX_QPATH]; // NULL terminated char sound_precache[MAX_SOUNDS][MAX_QPATH]; // NULL terminated const char *lightstyles[MAX_LIGHTSTYLES]; - qbyte lightstylecolours[MAX_LIGHTSTYLES]; + vec3_t lightstylecolours[MAX_LIGHTSTYLES]; }; } strings; char h2miditrack[MAX_QPATH]; @@ -481,13 +481,14 @@ typedef struct client_s #endif //true/false/persist - qbyte ismuted; + unsigned int penalties; +/* qbyte ismuted; qbyte iscuffed; qbyte iscrippled; qbyte isdeaf; qbyte islagged; qbyte isvip; - +*/ qbyte istobeloaded; //loadgame creates place holders for clients to connect to. Effectivly loading a game reconnects all clients, but has precreated ents. double floodprotmessage; @@ -745,7 +746,9 @@ typedef struct #define BAN_CRIPPLED (1u<<4) //can't move #define BAN_DEAF (1u<<5) //can't see say/say_team #define BAN_LAGGED (1u<<6) //given an extra 200ms -#define BAN_VIP (1u<<7) //mods might give the user special rights +#define BAN_VIP (1u<<7) //mods might give the user special rights, via the *VIP infokey. the engine itself currently does not do anything but track it. +#define BAN_BLIND (1u<<8) //player's pvs is wiped. +#define BAN_SPECONLY (1u<<9) //player is forced to spectate typedef struct bannedips_s { unsigned int banflags; diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 28e7a99a0..f11f04a2a 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -316,7 +316,7 @@ static void SV_Give_f (void) return; } - if (developer.value) +/* if (developer.value) { int oldself; oldself = pr_global_struct->self; @@ -324,7 +324,7 @@ static void SV_Give_f (void) Con_Printf("Result: %s\n", svprogfuncs->EvaluateDebugString(svprogfuncs, Cmd_Args())); pr_global_struct->self = oldself; } - +*/ if (!SV_SetPlayer ()) { return; @@ -363,7 +363,7 @@ static void SV_Give_f (void) case 'c': sv_player->v->ammo_cells = v; break; - default: +/* default: { int oldself; oldself = pr_global_struct->self; @@ -372,6 +372,7 @@ static void SV_Give_f (void) Con_TPrintf("Result: %s\n", svprogfuncs->EvaluateDebugString(svprogfuncs, Cmd_Args())); pr_global_struct->self = oldself; } +*/ } } @@ -765,18 +766,14 @@ void SV_KickSlot_f (void) void SV_EvaluatePenalties(client_t *cl) { bannedips_t *banip; - bannedips_t *cuff = NULL; - bannedips_t *mute = NULL; - bannedips_t *cripple = NULL; - bannedips_t *deaf = NULL; - bannedips_t *lagged = NULL; - bannedips_t *vip = NULL; - bannedips_t *safe = NULL; - bannedips_t *banned = NULL; - char *penalties[8]; - char *reasons[8]; + unsigned int penalties = 0, delta, p; + char *penaltyreason[10]; + char *activepenalties[10]; + char *reasons[10] = {NULL}; + char *penaltynames[10] = {"ban", "safe", "cuff", "mute", "crippled", "deaf", "lag", "vip", "blind", "spec"}; int numpenalties = 0; int numreasons = 0; + int i; if (cl->realip.type != NA_INVALID) { @@ -784,22 +781,16 @@ void SV_EvaluatePenalties(client_t *cl) { if (NET_CompareAdrMasked(&cl->realip, &banip->adr, &banip->adrmask)) { - if ((banip->banflags & BAN_CUFF) && !cuff) - cuff = banip; - if ((banip->banflags & BAN_MUTE) && !mute) - mute = banip; - if ((banip->banflags & BAN_CRIPPLED) && !cripple) - cripple = banip; - if ((banip->banflags & BAN_DEAF) && !deaf) - deaf = banip; - if ((banip->banflags & BAN_LAGGED) && !lagged) - lagged = banip; - if ((banip->banflags & BAN_BAN) && !banned) - banned = banip; - if ((banip->banflags & BAN_PERMIT) && !safe) - safe = banip; - if ((banip->banflags & BAN_VIP) && !vip) - vip = banip; + for (i = 0; i < sizeof(penaltyreason)/sizeof(penaltyreason[0]); i++) + { + p = 1u<banflags & p) + { + if (!penaltyreason[i]) + penaltyreason[i] = banip->reason; + penalties |= p; + } + } } } } @@ -807,164 +798,80 @@ void SV_EvaluatePenalties(client_t *cl) { if (NET_CompareAdrMasked(&cl->netchan.remote_address, &banip->adr, &banip->adrmask)) { - if ((banip->banflags & BAN_CUFF) && !cuff) - cuff = banip; - if ((banip->banflags & BAN_MUTE) && !mute) - mute = banip; - if ((banip->banflags & BAN_CRIPPLED) && !cripple) - cripple = banip; - if ((banip->banflags & BAN_DEAF) && !deaf) - deaf = banip; - if ((banip->banflags & BAN_LAGGED) && !lagged) - lagged = banip; - if ((banip->banflags & BAN_BAN) && !banned) - banned = banip; - if ((banip->banflags & BAN_PERMIT) && !safe) - safe = banip; - if ((banip->banflags & BAN_VIP) && !vip) - vip = banip; + for (i = 0; i < sizeof(penaltyreason)/sizeof(penaltyreason[0]); i++) + { + p = 1u<banflags & p) + { + if (!penaltyreason[i]) + penaltyreason[i] = banip->reason; + penalties |= p; + } + } } } - if (banned && !safe) + delta = cl->penalties ^ penalties; + cl->penalties = penalties; + + if ((penalties & (BAN_BAN | BAN_PERMIT)) == BAN_BAN) { - if (*banned->reason) - SV_BroadcastPrintf(PRINT_HIGH, va("%s was banned: %s\n", cl->name, banned->reason)); + //we should only reach here by a player getting banned mid-game. + if (penaltyreason[0]) + SV_BroadcastPrintf(PRINT_HIGH, va("%s was banned: %s\n", cl->name, penaltyreason[0])); else SV_BroadcastPrintf(PRINT_HIGH, va("%s was banned\n", cl->name)); cl->drop = true; } - if (cuff) - { - if (!cl->iscuffed) - { - cl->iscuffed = true; - penalties[numpenalties++] = "cuffed"; - reasons[numreasons++] = cuff->reason; - } - } - else - { - if (cl->iscuffed == true) - { - cl->iscuffed = false; - SV_PrintToClient(cl, PRINT_HIGH, "Cuff expired\n"); - } - } + //don't announce these now. + delta &= ~(BAN_BAN | BAN_PERMIT); - if (cripple) - { - if (!cl->iscrippled) - { - cl->iscrippled = true; - penalties[numpenalties++] = "crippled"; - reasons[numreasons++] = cripple->reason; - } - } - else - { - if (cl->iscrippled == true) - { - cl->iscrippled = false; - SV_PrintToClient(cl, PRINT_HIGH, "Cripple expired\n"); - } - } - - if (mute) - { - if (!cl->ismuted) - { - cl->ismuted = true; - if (!deaf) - { - penalties[numpenalties++] = "muted"; - reasons[numreasons++] = mute->reason; - } - } - } - else - { - if (cl->ismuted == true) - { - cl->ismuted = false; - - if (!cl->isdeaf) - SV_PrintToClient(cl, PRINT_HIGH, "Mute expired\n"); - if (!deaf && cl->isdeaf == true) - cl->isdeaf = false; //don't let them know that they were ever mute+deaf. - } - } - if (deaf) - { - if (!cl->isdeaf) - { - cl->isdeaf = true; - if (!mute) - { - penalties[numpenalties++] = "deaf"; - reasons[numreasons++] = deaf->reason; - } - } - } - else - { - if (cl->isdeaf == true) - { - cl->isdeaf = false; - SV_PrintToClient(cl, PRINT_HIGH, "Deafness expired\n"); - } - } - if (lagged) - { - if (!cl->islagged) - { - cl->islagged = true; - penalties[numpenalties++] = "lagged"; - reasons[numreasons++] = lagged->reason; - } - } - else - { - if (cl->islagged == true) - { - cl->islagged = false; - SV_PrintToClient(cl, PRINT_HIGH, "Lag penalty expired\n"); - } - } - if (vip) - { - if (!cl->isvip) - { - cl->isvip = true; - penalties[numpenalties++] = "vip"; - reasons[numreasons++] = deaf->reason; - } - } - else - { - if (cl->isvip == true) - { - cl->isvip = false; - SV_PrintToClient(cl, PRINT_HIGH, "VIP expired\n"); - } - } + //deaf+mute sees no (other) penalty messages + if (((penalties|delta) & (BAN_MUTE|BAN_DEAF)) == (BAN_MUTE|BAN_DEAF)) + delta = 0; if (cl->controller) - return; //don't spam it for every player in a splitscreen client. + delta = 0; //don't spam it for every player in a splitscreen client. + + if (delta & BAN_VIP) + { + delta &= ~BAN_VIP; //don't refer to this as a penalty + if (penalties & p) + SV_PrintToClient(cl, PRINT_HIGH, "You are a VIP, apparently\n"); + else + SV_PrintToClient(cl, PRINT_HIGH, "VIP expired\n"); + } + + for (i = 0; i < sizeof(penaltyreason)/sizeof(penaltyreason[0]); i++) + { + p = 1u<state == cs_free) continue; - if (client->isdeaf) + if (client->penalties & BAN_DEAF) continue; SV_ClientPrintf(client, PRINT_CHAT, "%s\n", text); } @@ -2245,17 +2161,17 @@ void SV_User_f (void) if (cl->download) Con_Printf ("download: \"%s\" %ik/%ik (%i%%)", cl->downloadfn, cl->downloadcount/1024, cl->downloadsize/1024, (cl->downloadcount*100)/cl->downloadsize); - if (cl->iscrippled) + if (cl->penalties & BAN_CRIPPLED) Con_Printf("crippled\n"); - if (cl->iscuffed) + if (cl->penalties & BAN_CUFF) Con_Printf("cuffed\n"); - if (cl->isdeaf) + if (cl->penalties & BAN_DEAF) Con_Printf("deaf\n"); - if (cl->islagged) + if (cl->penalties & BAN_LAGGED) Con_Printf("lagged\n"); - if (cl->ismuted) + if (cl->penalties & BAN_MUTE) Con_Printf("muted\n"); - if (cl->isvip) + if (cl->penalties & BAN_VIP) Con_Printf("vip\n"); SV_CalcNetRates(cl, &ftime, &frames, &minf, &maxf); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 48d0942f3..b4e9805f7 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -2290,6 +2290,10 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * if (cl->state != cs_spawned && !(cl->state == cs_free && cl->name[0])) //this includes bots, and nq bots continue; + if ((client->penalties & BAN_BLIND) && client != cl) + continue; + + isbot = (!cl->name[0] || cl->protocol == SCP_BAD); ent = cl->edict; if (cl->viewent && ent == clent) @@ -3139,6 +3143,12 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, pvscamera_t limit = min(client->max_net_ents, sv.world.num_edicts); + if (client->penalties & BAN_BLIND) + { + e = client->edict->entnum; + limit = e+1; + } + for ( ; eentities) - { - Con_Printf("DON'T PANIC!\n"); return; - } // put other visible entities into either a packet_entities or a nails message diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index c0853bfba..b084238b5 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -469,12 +469,12 @@ void SV_DropClient (client_t *drop) rs.deaths += drop->deaths; rs.flags1 &= ~(RANK_CUFFED|RANK_MUTED|RANK_CRIPPLED); - if (drop->iscuffed==2) - rs.flags1 |= RANK_CUFFED; - if (drop->ismuted==2) - rs.flags1 |= RANK_MUTED; - if (drop->iscrippled==2) - rs.flags1 |= RANK_CRIPPLED; +// if (drop->iscuffed==2) +// rs.flags1 |= RANK_CUFFED; +// if (drop->ismuted==2) +// rs.flags1 |= RANK_MUTED; +// if (drop->iscrippled==2) +// rs.flags1 |= RANK_CRIPPLED; drop->kills=0; drop->deaths=0; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, drop->edict); @@ -5659,12 +5659,12 @@ qboolean ReloadRanking(client_t *cl, const char *newname) rs.deaths += cl->deaths; rs.flags1 &= ~(RANK_CUFFED|RANK_MUTED|RANK_CRIPPLED); - if (cl->iscuffed==2) - rs.flags1 |= RANK_CUFFED; - if (cl->ismuted==2) - rs.flags1 |= RANK_MUTED; - if (cl->iscrippled==2) - rs.flags1 |= RANK_CRIPPLED; +// if (cl->iscuffed==2) +// rs.flags1 |= RANK_CUFFED; +// if (cl->ismuted==2) +// rs.flags1 |= RANK_MUTED; +// if (cl->iscrippled==2) +// rs.flags1 |= RANK_CRIPPLED; cl->kills=0; cl->deaths=0; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); @@ -5680,17 +5680,11 @@ qboolean ReloadRanking(client_t *cl, const char *newname) return false; cl->rankid = newid; if (rs.flags1 & RANK_CUFFED) - cl->iscuffed=2; - else if (cl->iscuffed) //continue being cuffed, but don't inflict the new user with persistant cuffing. - cl->iscuffed=1; + cl->penalties |= BAN_CUFF; if (rs.flags1 & RANK_MUTED) - cl->ismuted=2; - else if (cl->ismuted) - cl->ismuted=1; + cl->penalties |= BAN_MUTE; if (rs.flags1 & RANK_CRIPPLED) - cl->iscrippled=2; - else if (cl->iscrippled) - cl->iscrippled=1; + cl->penalties |= BAN_CRIPPLED; cl->trustlevel = rs.trustlevel; return true; @@ -5768,7 +5762,7 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose) if (strncmp(newname, cl->name, sizeof(cl->namebuf)-1)) { - if (cl->ismuted && *cl->name && verbose) //!verbose is a gamecode-forced update, where the gamecode is expected to know what its doing. + if ((cl->penalties & BAN_MUTE) && *cl->name && verbose) //!verbose is a gamecode-forced update, where the gamecode is expected to know what its doing. SV_ClientTPrintf (cl, PRINT_HIGH, "Muted players may not change their names\n"); else { diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 902cd00ac..3fafe553b 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -1956,11 +1956,14 @@ void SV_MVD_SendInitialGamestate(mvddest_t *dest) if (!sv.strings.lightstyles[i]) continue; #ifdef PEXT_LIGHTSTYLECOL - if ((demo.recorder.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && sv.strings.lightstylecolours[i]!=7 && sv.strings.lightstyles[i]) + if ((demo.recorder.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (sv.strings.lightstylecolours[i][0]!=1||sv.strings.lightstylecolours[i][1]!=1||sv.strings.lightstylecolours[i][2]!=1) && sv.strings.lightstyles[i]) { MSG_WriteByte (&buf, svcfte_lightstylecol); MSG_WriteByte (&buf, (unsigned char)i); - MSG_WriteByte (&buf, sv.strings.lightstylecolours[i]); + MSG_WriteByte (&buf, 0x87); + MSG_WriteShort(&buf, sv.strings.lightstylecolours[i][0]*1024); + MSG_WriteShort(&buf, sv.strings.lightstylecolours[i][1]*1024); + MSG_WriteShort(&buf, sv.strings.lightstylecolours[i][2]*1024); MSG_WriteString (&buf, sv.strings.lightstyles[i]); } else diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 9657ab232..279d94047 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -403,14 +403,15 @@ static int WPhys_FlyMove (world_t *w, wedict_t *ent, const vec3_t gravitydir, fl VectorSubtract(end, trace.endpos, move); WPhys_PortalTransform(w, ent, impact, from, move); VectorAdd(from, move, end); - + //if we follow the portal, then we basically need to restart from the other side. time_left -= time_left * trace.fraction; VectorCopy (ent->v->velocity, primal_velocity); VectorCopy (ent->v->velocity, original_velocity); numplanes = 0; - + trace = World_Move (w, from, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, (wedict_t*)ent); + impact = trace.ent; } if (trace.startsolid) diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 1c21209f7..d14e73510 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -669,6 +669,8 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int } else if (mask) { + if (client->penalties & BAN_BLIND) + continue; #ifdef Q2SERVER if (ge) leafnum = CM_PointLeafnum (sv.world.worldmodel, client->q2edict->s.origin); @@ -829,6 +831,9 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int if (!mask) //no pvs? broadcast. goto inrange; + if (client->penalties & BAN_BLIND) + continue; + if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) { vec3_t delta; diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 2a4f8cb01..abf53f061 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1531,12 +1531,15 @@ void SVQW_Spawn_f (void) if (!sv.strings.lightstyles[i]) continue; #ifdef PEXT_LIGHTSTYLECOL - if ((host_client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && sv.strings.lightstylecolours[i]!=7 && sv.strings.lightstyles[i]) + if ((host_client->fteprotocolextensions & PEXT_LIGHTSTYLECOL) && (sv.strings.lightstylecolours[i][0]!=1||sv.strings.lightstylecolours[i][1]!=1||sv.strings.lightstylecolours[i][2]!=1) && sv.strings.lightstyles[i]) { ClientReliableWrite_Begin (host_client, svcfte_lightstylecol, - 3 + (sv.strings.lightstyles[i] ? strlen(sv.strings.lightstyles[i]) : 1)); + 10 + (sv.strings.lightstyles[i] ? strlen(sv.strings.lightstyles[i]) : 1)); ClientReliableWrite_Byte (host_client, (char)i); - ClientReliableWrite_Char (host_client, sv.strings.lightstylecolours[i]); + ClientReliableWrite_Char (host_client, 0x87); + ClientReliableWrite_Short (host_client, sv.strings.lightstylecolours[i][0]*1024); + ClientReliableWrite_Short (host_client, sv.strings.lightstylecolours[i][1]*1024); + ClientReliableWrite_Short (host_client, sv.strings.lightstylecolours[i][2]*1024); ClientReliableWrite_String (host_client, sv.strings.lightstyles[i]); } else @@ -2317,7 +2320,7 @@ void SV_VoiceReadPacket(void) bytes = MSG_ReadShort(); ring = &voice.ring[voice.write & (VOICE_RING_SIZE-1)]; //voice data does not get echoed to the sender unless sv_voip_echo is on too, which is rarely the case, so no worries about leaking the mute+deaf talking-to-yourself thing - if (bytes > sizeof(ring->data) || host_client->ismuted || !sv_voip.ival) + if (bytes > sizeof(ring->data) || (host_client->penalties & BAN_MUTE) || !sv_voip.ival) { MSG_ReadSkip(bytes); return; @@ -2349,7 +2352,7 @@ void SV_VoiceReadPacket(void) if (!cl->spectator) continue; - if (cl->isdeaf) + if (cl->penalties & BAN_DEAF) continue; if (vt == VT_TEAM) @@ -3112,7 +3115,7 @@ void SV_SayOne_f (void) if (Cmd_Argc () < 3) return; - if (host_client->ismuted && !host_client->isdeaf) + if ((host_client->penalties & BAN_MUTE) && !(host_client->penalties & BAN_DEAF)) { SV_ClientTPrintf(host_client, PRINT_CHAT, "You are muted\n"); return; @@ -3120,7 +3123,7 @@ void SV_SayOne_f (void) while((to = SV_GetClientForString(Cmd_Argv(1), &clnum))) { - if (host_client->ismuted) + if ((host_client->penalties & BAN_MUTE)) continue; if (host_client->spectator) { @@ -3132,7 +3135,7 @@ void SV_SayOne_f (void) else Q_snprintfz (text, sizeof(text), "{%s}:", host_client->name); - if (to->isdeaf) + if (to->penalties & BAN_DEAF) continue; for (i = 2; ; i++) @@ -3246,7 +3249,7 @@ void SV_Say (qboolean team) if (Cmd_Argc () < 2) return; - if (!host_client->ismuted) + if (!(host_client->penalties & BAN_MUTE)) Sys_ServerActivity(); memset(sent, 0, sizeof(sent)); @@ -3263,7 +3266,7 @@ void SV_Say (qboolean team) else Q_snprintfz (text, sizeof(text), "%s: ", host_client->name); - if (host_client->ismuted && !host_client->isdeaf) + if ((host_client->penalties & BAN_MUTE) && !(host_client->penalties & BAN_DEAF)) { SV_ClientTPrintf(host_client, PRINT_CHAT, "You cannot chat while muted\n"); return; @@ -3321,7 +3324,7 @@ void SV_Say (qboolean team) Q_strcat(text, "\n"); - if (!host_client->ismuted) + if (!(host_client->penalties & BAN_MUTE)) Sys_Printf ("%s", text); mvdrecording = sv.mvdrecording; @@ -3347,12 +3350,12 @@ void SV_Say (qboolean team) } } - if (host_client->ismuted) + if (host_client->penalties & BAN_MUTE) { if (client != host_client) continue; } - else if (client->isdeaf) + else if (client->penalties & BAN_DEAF) continue; cls |= 1 << j; @@ -3970,12 +3973,12 @@ void SV_Vote_f (void) int totalusers = 0; qboolean passes; - if (!votelevel.value || (host_client->ismuted && host_client->isdeaf)) + if (!votelevel.value || ((host_client->penalties & (BAN_MUTE|BAN_DEAF)) == (BAN_MUTE|BAN_DEAF))) { SV_ClientTPrintf(host_client, PRINT_HIGH, "Voting was dissallowed\n"); return; } - if (host_client->ismuted) + if (host_client->penalties & BAN_MUTE) { SV_ClientTPrintf(host_client, PRINT_HIGH, "Sorry, you cannot vote when muted as it may allow you to send a message.\n"); return; @@ -5924,7 +5927,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) if (ucmd->impulse && SV_FilterImpulse(ucmd->impulse, host_client->trustlevel)) sv_player->v->impulse = ucmd->impulse; - if (host_client->iscuffed) + if (host_client->penalties & BAN_CUFF) { sv_player->v->impulse = 0; sv_player->v->button0 = 0; @@ -6488,7 +6491,7 @@ void SV_ExecuteClientMessage (client_t *cl) cl->delay = bound(0, cl->delay, 1); //but make sure things don't go crazy } } - if (cl->islagged) + if (cl->penalties & BAN_LAGGED) if (cl->delay < 0.2) cl->delay = 0.2; } @@ -6623,7 +6626,7 @@ void SV_ExecuteClientMessage (client_t *cl) } } - if (split->iscrippled) + if (split->penalties & BAN_CRIPPLED) { split->lastcmd.forwardmove = 0; //hmmm.... does this work well enough? oldest.forwardmove = 0; @@ -6891,7 +6894,7 @@ void SVQ2_ExecuteClientMessage (client_t *cl) return; } - if (cl->iscrippled) + if (cl->penalties & BAN_CRIPPLED) { cl->lastcmd.forwardmove = 0; //hmmm.... does this work well enough? oldest.forwardmove = 0; diff --git a/engine/server/world.c b/engine/server/world.c index 44d4d161d..2c4fa8f8b 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -1373,6 +1373,8 @@ void World_PortalCSG(wedict_t *portal, float *trmin, float *trmax, vec3_t start, vec4_t planes[6]; //far, near, right, left, up, down int plane; vec3_t worldpos; + float bestfrac; + int hitplane; float portalradius = portal->v->impulse; //only run this code if we impacted on the portal's parent. if (trace->fraction == 1 && !trace->startsolid) @@ -1392,8 +1394,8 @@ void World_PortalCSG(wedict_t *portal, float *trmin, float *trmax, vec3_t start, VectorNegate(planes[5], planes[4]); portalradius/=2; - planes[0][3] = DotProduct(portal->v->origin, planes[0]) - (1.0/32); - planes[1][3] = DotProduct(portal->v->origin, planes[1]) - (1.0/32); //an epsilon beyond the portal + planes[0][3] = DotProduct(portal->v->origin, planes[0]) - (4.0/32); + planes[1][3] = DotProduct(portal->v->origin, planes[1]) - (4.0/32); //an epsilon beyond the portal planes[2][3] = DotProduct(portal->v->origin, planes[2]) - portalradius; planes[3][3] = DotProduct(portal->v->origin, planes[3]) - portalradius; planes[4][3] = DotProduct(portal->v->origin, planes[4]) - portalradius; @@ -1410,16 +1412,15 @@ void World_PortalCSG(wedict_t *portal, float *trmin, float *trmax, vec3_t start, if (!plane) //front plane gets further away with side planes[plane][3] -= DotProduct(nearest, planes[plane]); else if (plane>1) //side planes get nearer with size - planes[plane][3] += DotProduct(nearest, planes[plane]); + planes[plane][3] += 24;//DotProduct(nearest, planes[plane]); if (d - planes[plane][3] >= 0) continue; //endpos is inside else return; //end is already outside } //yup, we're inside, the trace shouldn't end where it actually did - trace->fraction = 1; - trace->startsolid = trace->allsolid = false; - VectorInterpolate(start, 1, end, trace->endpos); + bestfrac = 1; + hitplane = -1; for (plane = 0; plane < 6; plane++) { float ds = DotProduct(start, planes[plane]) - planes[plane][3]; @@ -1427,18 +1428,31 @@ void World_PortalCSG(wedict_t *portal, float *trmin, float *trmax, vec3_t start, float frac; if (ds >= 0 && de < 0) { - frac = (ds-(1.0/32)) / (ds - de); - if (frac < trace->fraction) + frac = (ds) / (ds - de); + if (frac < bestfrac) { if (frac < 0) frac = 0; - trace->fraction = frac; - VectorInterpolate(start, frac, end, trace->endpos); - VectorCopy(planes[plane], trace->plane.normal); - trace->plane.dist = planes[plane][3]; + bestfrac = frac; + hitplane = plane; } } } + trace->startsolid = trace->allsolid = false; + //if we cross the front of the portal, don't shorten the trace, that will artificially clip us + if (hitplane == 0 && trace->fraction > bestfrac) + return; + //okay, elongate to clip to the portal hole properly. + trace->fraction = bestfrac; + VectorInterpolate(start, bestfrac, end, trace->endpos); + + if (hitplane >= 0) + { + VectorCopy(planes[hitplane], trace->plane.normal); + trace->plane.dist = planes[hitplane][3]; + if (hitplane == 1) + trace->ent = portal; + } } /*