From 4366f644e58544e2d774094b7c7692d3150232a5 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sat, 1 Oct 2005 03:09:17 +0000 Subject: [PATCH] A few tweeks here and there. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1407 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_cg.c | 2 +- engine/client/cl_ents.c | 106 ++++++++++--- engine/client/cl_main.c | 54 ++++++- engine/client/cl_parse.c | 40 ++++- engine/client/cl_pred.c | 301 ++++++++++++++++++++++++++++--------- engine/client/client.h | 5 + engine/client/clq3_parse.c | 2 +- engine/client/m_download.c | 1 - engine/client/pr_menu.c | 101 +++++++++++-- engine/client/sys_win.c | 9 +- engine/client/textedit.c | 2 +- engine/client/view.c | 3 +- engine/common/common.c | 51 ++++++- engine/common/fs.c | 2 +- engine/common/gl_q2bsp.c | 2 +- engine/common/net_chan.c | 4 + engine/common/net_wins.c | 4 +- engine/common/protocol.h | 29 ++-- engine/common/world.h | 3 + engine/common/zone.c | 6 +- engine/gl/gl_shader.c | 8 +- engine/qclib/qcc_pr_comp.c | 21 ++- engine/server/pr_cmds.c | 176 +++++++++++++++++++--- engine/server/server.h | 1 + engine/server/sv_ccmds.c | 27 ++++ engine/server/sv_ents.c | 20 ++- engine/server/sv_master.c | 18 ++- engine/server/sv_send.c | 6 +- engine/server/sv_user.c | 35 +++-- engine/server/svq2_ents.c | 2 +- engine/server/svq3_game.c | 48 +++++- engine/server/world.c | 151 ++++++++++++++++++- 32 files changed, 1019 insertions(+), 221 deletions(-) diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 226482e5e..9f9e063a7 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -499,7 +499,7 @@ static long CG_SystemCallsEx(void *offset, unsigned int mask, int fn, const long cvar_t *var; var = Cvar_FindVar(VM_POINTER(arg[0])); if (var) - Cvar_Set(var, VM_POINTER(arg[1])); //set it + Cvar_Set(var, VM_POINTER(arg[1])?VM_POINTER(arg[1]):""); //set it else Cvar_Get(VM_POINTER(arg[0]), VM_POINTER(arg[1]), 0, "Q3CG created"); //create one } diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 8e0ac4ee0..783555476 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -396,13 +396,13 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean if (to->frame != from->frame) { cl.lerpents[to->number].oldframechange = cl.lerpents[to->number].framechange; //marked for hl models - cl.lerpents[to->number].framechange = cl.time; //marked for hl models + cl.lerpents[to->number].framechange = cl.servertime; //marked for hl models } if (to->modelindex != from->modelindex || to->number != from->number || VectorLength(move)>500) //model changed... or entity changed... { cl.lerpents[to->number].oldframechange = cl.lerpents[to->number].framechange; //marked for hl models - cl.lerpents[to->number].framechange = cl.time; //marked for hl models + cl.lerpents[to->number].framechange = cl.servertime; //marked for hl models cl.lerpents[to->number].lerptime = -10; cl.lerpents[to->number].lerprate = 0; @@ -438,10 +438,10 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean //2: physics. Objects moving acording to gravity. //3: both. This is really awkward. And I'm really lazy. //the real solution would be to seperate the two. - cl.lerpents[to->number].lerprate = cl.time-cl.lerpents[to->number].lerptime; //time per update + cl.lerpents[to->number].lerprate = cl.servertime-cl.lerpents[to->number].lerptime; //time per update // Con_Printf("%f=%f-%f\n", cl.lerpents[to->number].lerprate, cl.time, cl.lerpents[to->number].lerptime); cl.lerpents[to->number].frame = from->frame; - cl.lerpents[to->number].lerptime = cl.time; + cl.lerpents[to->number].lerptime = cl.servertime; if (cl.lerpents[to->number].lerprate>0.2) cl.lerpents[to->number].lerprate=0.2; @@ -505,7 +505,12 @@ void CL_ParsePacketEntities (qboolean delta) int word, newnum, oldnum; qboolean full; int from; - +/* + cl.oldgametime = cl.gametime; + cl.oldgametimemark = cl.gametimemark; + cl.gametime = realtime; + cl.gametimemark = realtime; +*/ newpacket = cls.netchan.incoming_sequence&UPDATE_MASK; newp = &cl.frames[newpacket].packet_entities; cl.frames[newpacket].invalid = false; @@ -991,16 +996,38 @@ void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o( to->flags &= ~0x80000000; if (!from || to->modelindex != from->modelindex || to->number != from->number) //model changed... or entity changed... + { cl.lerpents[to->number].lerptime = -10; + cl.lerpents[to->number].origin[0] = to->origin[0]; + cl.lerpents[to->number].origin[1] = to->origin[1]; + cl.lerpents[to->number].origin[2] = to->origin[2]; + + cl.lerpents[to->number].angles[0] = to->angles[0]; + cl.lerpents[to->number].angles[1] = to->angles[1]; + cl.lerpents[to->number].angles[2] = to->angles[2]; + } else if (to->frame != from->frame || to->origin[0] != from->origin[0] || to->origin[1] != from->origin[1] || to->origin[2] != from->origin[2]) { - cl.lerpents[to->number].origin[0] = from->origin[0]; - cl.lerpents[to->number].origin[1] = from->origin[1]; - cl.lerpents[to->number].origin[2] = from->origin[2]; + if (from == &defaultstate) //lerp from the new position instead of old, so no lerp + { + cl.lerpents[to->number].origin[0] = to->origin[0]; + cl.lerpents[to->number].origin[1] = to->origin[1]; + cl.lerpents[to->number].origin[2] = to->origin[2]; - cl.lerpents[to->number].angles[0] = from->angles[0]; - cl.lerpents[to->number].angles[1] = from->angles[1]; - cl.lerpents[to->number].angles[2] = from->angles[2]; + cl.lerpents[to->number].angles[0] = to->angles[0]; + cl.lerpents[to->number].angles[1] = to->angles[1]; + cl.lerpents[to->number].angles[2] = to->angles[2]; + } + else + { + cl.lerpents[to->number].origin[0] = from->origin[0]; + cl.lerpents[to->number].origin[1] = from->origin[1]; + cl.lerpents[to->number].origin[2] = from->origin[2]; + + cl.lerpents[to->number].angles[0] = from->angles[0]; + cl.lerpents[to->number].angles[1] = from->angles[1]; + cl.lerpents[to->number].angles[2] = from->angles[2]; + } //we have three sorts of movement. //1: stepping monsters. These have frames and tick at 10fps. //2: physics. Objects moving acording to gravity. @@ -1234,9 +1261,9 @@ void CLNQ_ParseEntity(unsigned int bits) //1: stepping monsters. These have frames and tick at 10fps. //2: physics. Objects moving acording to gravity. //3: both. This is really awkward. And I'm really lazy. - cl.lerpents[state->number].lerprate = cl.time-cl.lerpents[state->number].lerptime; //time per update + cl.lerpents[state->number].lerprate = cl.gametime-cl.lerpents[state->number].lerptime; //time per update cl.lerpents[state->number].frame = from->frame; - cl.lerpents[state->number].lerptime = cl.time; + cl.lerpents[state->number].lerptime = cl.gametime; if (cl.lerpents[state->number].lerprate>0.2) cl.lerpents[state->number].lerprate=0.2; @@ -1511,19 +1538,29 @@ void CL_LinkPacketEntities (void) ent->forcedshader = NULL; #endif - //figure out the lerp factor - if (cl.lerpents[s1->number].lerprate<=0) - ent->lerpfrac = 0; + if (cl_nolerp.value) + f = 1; else - ent->lerpfrac = 1-(cl.time-cl.lerpents[s1->number].lerptime)/cl.lerpents[s1->number].lerprate; + { + //figure out the lerp factor + if (cl.lerpents[s1->number].lerprate<=0) + f = 0; + else + f = (cl.servertime-cl.lerpents[s1->number].lerptime)/cl.lerpents[s1->number].lerprate;//(cl.gametime-cl.oldgametime);//1-(cl.time-cl.lerpents[s1->number].lerptime)/cl.lerpents[s1->number].lerprate; + if (f<0) + f=0; + if (f>1) + f=1; + } + + ent->lerpfrac = 1-(cl.servertime-cl.lerpents[s1->number].lerptime)/cl.lerpents[s1->number].lerprate; if (ent->lerpfrac<0) ent->lerpfrac=0; if (ent->lerpfrac>1) ent->lerpfrac=1; - f = 1-ent->lerpfrac; - if (cl_nolerp.value) - f = 1; +// if (s1->modelindex == 87 && !cl.paused) +// Con_Printf("%f %f\n", f, cl.lerpents[s1->number].lerptime-cl.servertime); // calculate origin for (i=0 ; i<3 ; i++) @@ -1609,8 +1646,8 @@ void CL_LinkPacketEntities (void) ent->frame = s1->frame; ent->oldframe = cl.lerpents[s1->number].frame; - ent->frame1time = cl.time - cl.lerpents[s1->number].framechange; - ent->frame2time = cl.time - cl.lerpents[s1->number].oldframechange; + ent->frame1time = cl.servertime - cl.lerpents[s1->number].framechange; + ent->frame2time = cl.servertime - cl.lerpents[s1->number].oldframechange; // f = (sin(realtime)+1)/2; @@ -2314,6 +2351,7 @@ void CL_LinkPlayers (void) entity_t *ent; int msec; frame_t *frame; + frame_t *fromf; int oldphysent; vec3_t angles; @@ -2321,12 +2359,13 @@ void CL_LinkPlayers (void) if (playertime > realtime) playertime = realtime; - frame = &cl.frames[cl.parsecount&UPDATE_MASK]; + frame = &cl.frames[cl.validsequence&UPDATE_MASK]; + fromf = &cl.frames[cl.oldvalidsequence&UPDATE_MASK]; for (j=0, info=cl.players, state=frame->playerstate ; j < MAX_CLIENTS ; j++, info++, state++) { - if (state->messagenum != cl.parsecount) + if (state->messagenum != cl.validsequence) continue; // not present this frame // spawn light flashes, even ones coming from invisible objects @@ -2429,8 +2468,25 @@ void CL_LinkPlayers (void) // only predict half the move to minimize overruns msec = 500*(playertime - state->state_time); - if (pnum < cl.splitclients) + if (1) { + float f; + int i; + f = (cl.gametime-cl.servertime)/(cl.gametime-cl.oldgametime); + if (f<0) + f=0; + if (f>1) + f=1; + + for (i=0 ; i<3 ; i++) + { + ent->origin[i] = state->origin[i] + + f * (fromf->playerstate[j].origin[i] - state->origin[i]); + } + + } + else if (pnum < cl.splitclients) + { //this is a local player } else if (msec <= 0 || (!cl_predict_players.value && !cl_predict_players2.value)) { diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 4a825d336..3966abcad 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -81,6 +81,8 @@ cvar_t cl_indepphysics = {"cl_indepphysics", "0"}; cvar_t localid = {"localid", ""}; +cvar_t cl_antibunch = {"cl_antibunch", "0.013"}; + static qboolean allowremotecmd = true; // @@ -845,6 +847,12 @@ void CL_ClearState (void) Media_PlayFilm(""); } + for (i = 0; i < UPDATE_BACKUP; i++) + { + if (cl.frames[i].packet_entities.entities) + Z_Free(cl.frames[i].packet_entities.entities); + } + if (cl.lerpents) BZ_Free(cl.lerpents); @@ -2038,14 +2046,52 @@ CL_ReadPackets void CL_ReadPackets (void) { // while (NET_GetPacket ()) - while (CL_GetMessage()) + for(;;) { + if (cl.oldgametime && cl_antibunch.value) + { + float want; + static float clamp; + + want = cl.oldgametime + realtime - cl.gametimemark - clamp; + if (want>cl.time) //don't decrease + { + clamp = 0; + cl.time = want; + } + + if (cl.time > cl.gametime) + { + clamp += cl.time - cl.gametime; + cl.time = cl.gametime; + } + if (cl.time < cl.oldgametime) + { + clamp -= cl.time - cl.gametime; + cl.time = cl.oldgametime; + } + + if (cl.time < cl.gametime-(1/cl_antibunch.value)) + { +// if (cl.gametime - 2 > cl.time) +// cl.gametime = 0; + break; + } + + } + + if (!CL_GetMessage()) + break; + #ifdef NQPROT if (cls.demoplayback == DPB_NETQUAKE) { MSG_BeginReading (); cls.netchan.last_received = realtime; CLNQ_ParseServerMessage (); + + if (!cls.demoplayback) + CL_NextDemo(); continue; } #endif @@ -2105,9 +2151,10 @@ void CL_ReadPackets (void) { case 0: break; - case 1: + case 1://datagram +// if (cls.n cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence - 3; - case 2: + case 2://reliable CLNQ_ParseServerMessage (); break; } @@ -2425,6 +2472,7 @@ void CL_Init (void) Cvar_Register (&host_mapname, "Scripting"); Cvar_Register (&cl_indepphysics, cl_controlgroup); + Cvar_Register (&cl_antibunch, "evil hacks"); #ifdef IRCCLIENT Cmd_AddCommand ("irc", CL_IRC_f); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 7b76b3c86..99b970783 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -691,6 +691,11 @@ void Sound_NextDownload (void) unsigned int chksum = strtoul(s, NULL, 0); if (CSQC_Init(chksum)) CL_SendClientCommand(true, "enablecsqc"); + else + Sbar_Start(); //try and start this before we're actually on the server, + //this'll stop the mod from sending so much stuffed data at us, whilst we're frozen while trying to load. + //hopefully this'll make it more robust. + //csqc is expected to use it's own huds, or to run on decent servers. :p } } #endif @@ -1519,6 +1524,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. Con_TPrintf (TLC_GOTSVDATAPACKET); CL_ClearState (); Stats_NewMap(); + P_NewServer(); protover = MSG_ReadLong (); @@ -1653,7 +1659,6 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. cl.worldmodel = cl.model_precache[1]; - R_NewMap (); if (cls.demoplayback) @@ -1669,6 +1674,9 @@ void CLNQ_SignonReply (void) { extern cvar_t topcolor; extern cvar_t bottomcolor; + extern cvar_t rate; + extern cvar_t model; + extern cvar_t skin; Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); @@ -1685,6 +1693,14 @@ Con_DPrintf ("CL_SignonReply: %i\n", cls.signon); CL_SendClientCommand(true, "color %i %i\n", (int)topcolor.value, (int)bottomcolor.value); CL_SendClientCommand(true, "spawn %s", ""); + + if (nq_dp_protocol) //dp needs a couple of extras to work properly. + { + CL_SendClientCommand(true, "rate %s", rate.string); + + CL_SendClientCommand(true, "playermodel %s", model.string); + CL_SendClientCommand(true, "playerskin %s", skin.string); + } break; case 3: @@ -2433,7 +2449,7 @@ void CL_ParseClientdata (void) frame->senttime = realtime - host_frametime; parsecounttime = cl.frames[i].senttime; - frame->receivedtime = realtime; + frame->receivedtime = (cl.gametimemark - cl.oldgametimemark)*20; // calculate latency latency = frame->receivedtime - frame->senttime; @@ -2690,6 +2706,9 @@ void CL_SetStat (int pnum, int stat, int value) if (stat == STAT_TIME && cls.z_ext & Z_EXT_SERVERTIME) { + cl.oldgametime = cl.gametime; + cl.oldgametimemark = cl.gametimemark; + // cl.servertime_works = true; cl.gametime = value * 0.001; cl.gametimemark = realtime; @@ -4188,20 +4207,25 @@ void CLNQ_ParseServerMessage (void) break; case svc_time: + + cls.netchan.outgoing_sequence++; + cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence-1; + cl.validsequence = cls.netchan.incoming_sequence-1; + received_framecount = host_framecount; cl.last_servermessage = realtime; + cl.oldgametime = cl.gametime; cl.oldgametimemark = cl.gametimemark; cl.gametime = MSG_ReadFloat(); + cl.gametimemark = realtime; + if (nq_dp_protocol<5) { // cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities; cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.num_entities=0; } - cls.netchan.outgoing_sequence++; - cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence-1; - cl.validsequence = cls.netchan.incoming_sequence-1; break; case svc_updatename: @@ -4242,7 +4266,11 @@ void CLNQ_ParseServerMessage (void) case svc_lightstyle: i = MSG_ReadByte (); if (i >= MAX_LIGHTSTYLES) - Host_EndGame ("svc_lightstyle > MAX_LIGHTSTYLES"); + { + Con_Printf("svc_lightstyle: %i >= MAX_LIGHTSTYLES\n", i); + MSG_ReadString(); + break; + } #ifdef PEXT_LIGHTSTYLECOL cl_lightstyle[i].colour = 7; //white #endif diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index a1345f595..06c11969c 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -517,6 +517,173 @@ void CL_CalcCrouch (int pnum) } } +float LerpAngles360(float to, float from, float frac) +{ + int delta; + delta = (from-to); + + if (delta > 180) + delta -= 360; + if (delta < -180) + delta += 360; + + return to + frac*delta; +} + +//shamelessly ripped from zquake +extern cvar_t cl_nolerp; +static void CL_LerpMove (int pnum, float msgtime) +{ + static int lastsequence = 0; + static vec3_t lerp_angles[3]; + static vec3_t lerp_origin[3]; + static float lerp_times[3]; + static qboolean nolerp[2]; + static float demo_latency = 0.01; + float frac; + float simtime; + int i; + int from, to; + + if (cl_nolerp.value) + return; + + if (cls.netchan.outgoing_sequence < lastsequence) { + // reset + lastsequence = -1; + lerp_times[0] = -1; + demo_latency = 0.01; + } + + if (cls.netchan.outgoing_sequence > lastsequence) { + lastsequence = cls.netchan.outgoing_sequence; + // move along + lerp_times[2] = lerp_times[1]; + lerp_times[1] = lerp_times[0]; + lerp_times[0] = msgtime; + + VectorCopy (lerp_origin[1], lerp_origin[2]); + VectorCopy (lerp_origin[0], lerp_origin[1]); + VectorCopy (cl.simorg[pnum], lerp_origin[0]); + + VectorCopy (lerp_angles[1], lerp_angles[2]); + VectorCopy (lerp_angles[0], lerp_angles[1]); + VectorCopy (cl.simangles[pnum], lerp_angles[0]); + + nolerp[1] = nolerp[0]; + nolerp[0] = false; + for (i = 0; i < 3; i++) + if (fabs(lerp_origin[0][i] - lerp_origin[1][i]) > 40) + break; + if (i < 3) + nolerp[0] = true; // a teleport or something + } + + simtime = realtime - demo_latency; + + // adjust latency + if (simtime > lerp_times[0]) { + // Com_DPrintf ("HIGH clamp\n"); + demo_latency = realtime - lerp_times[0]; + } + else if (simtime < lerp_times[2]) { + // Com_DPrintf (" low clamp\n"); + demo_latency = realtime - lerp_times[2]; + } else { + // drift towards ideal latency + float ideal_latency = (lerp_times[0] - lerp_times[2]) * 0.6; + if (demo_latency > ideal_latency) + demo_latency = max(demo_latency - host_frametime * 0.1, ideal_latency); + } + + // decide where to lerp from + if (simtime > lerp_times[1]) { + from = 1; + to = 0; + } else { + from = 2; + to = 1; + } + + if (nolerp[to]) + return; + + frac = (simtime - lerp_times[from]) / (lerp_times[to] - lerp_times[from]); + frac = bound (0, frac, 1); + + for (i=0 ; i<3 ; i++) + { + cl.simorg[pnum][i] = lerp_origin[from][i] + + frac * (lerp_origin[to][i] - lerp_origin[from][i]); + cl.simangles[pnum][i] = LerpAngles360(lerp_angles[from][i], lerp_angles[to][i], frac); + } + +// LerpVector (lerp_origin[from], lerp_origin[to], frac, cl.simorg); +// LerpAngles (lerp_angles[from], lerp_angles[to], frac, cl.simangles); +} + +short LerpAngles16(short to, short from, float frac) +{ + int delta; + delta = (from-to); + + if (delta > 32767) + delta -= 65535; + if (delta < -32767) + delta += 65535; + + return to + frac*delta; +} + +void CL_CalcClientTime(void) +{ + + { + float want; + + want = cl.oldgametime + realtime - cl.gametimemark; + if (want>cl.servertime) + cl.servertime = want; + + if (cl.servertime > cl.gametime) + cl.servertime = cl.gametime; + if (cl.servertime < cl.oldgametime) + cl.servertime = cl.oldgametime; + } + + if (cls.protocol == CP_NETQUAKE || cls.demoplayback) + { + float want; +// float off; + + want = cl.oldgametime + realtime - cl.gametimemark; +// off = (want - cl.time); + if (want>cl.time) //don't decrease + cl.time = want; + +// Con_Printf("Drifted to %f off by %f\n", cl.time, off); + +// Con_Printf("\n"); + if (cl.time > cl.gametime) + { + cl.time = cl.gametime; +// Con_Printf("max TimeClamp\n"); + } + if (cl.time < cl.oldgametime) + { + cl.time = cl.oldgametime; +// Con_Printf("old TimeClamp\n"); + } + + } + else + { + cl.time = realtime - cls.latency - cl_pushlatency.value*0.001; + if (cl.time > realtime) + cl.time = realtime; + } +} + /* ============== CL_PredictMove @@ -549,37 +716,8 @@ void CL_PredictMovePNum (int pnum) if (cl.paused && !cls.demoplayback!=DPB_MVD && (!cl.spectator || !autocam[pnum])) return; - if (cl.oldgametime) - { - float want; - float off; + CL_CalcClientTime(); - want = cl.oldgametime + realtime - cl.gametimemark; - off = (want - cl.time); - if (want>cl.time) - cl.time = want; - -// Con_Printf("Drifted to %f off by %f\n", cl.time, off); - - if (cl.time > cl.gametime) - cl.time = cl.gametime; - if (cl.time < cl.oldgametime) - cl.time = cl.oldgametime; - } - else - { - cl.time = realtime - cls.latency - cl_pushlatency.value*0.001; - if (cl.time > realtime) - cl.time = realtime; - } -/* else - { - entitystate_t - cl.crouch = 0; - VectorCopy(cl - return; - } -*/ if (cl.intermission && cl.intermission != 3) { cl.crouch[pnum] = 0; @@ -623,13 +761,15 @@ void CL_PredictMovePNum (int pnum) //figure out the lerp factor if (cl.lerpents[state->number].lerprate<=0) - f = 1; + f = 0; else - f = (cl.time-cl.lerpents[state->number].lerptime)/cl.lerpents[state->number].lerprate; + f = (cl.gametime-cl.servertime)/(cl.gametime-cl.oldgametime);//f = (cl.time-cl.lerpents[state->number].lerptime)/cl.lerpents[state->number].lerprate; if (f<0) f=0; if (f>1) f=1; + f = 1-f; +// Con_Printf("%f\n", f); // if (cl_nolerp.value) // f = 1; @@ -642,29 +782,6 @@ void CL_PredictMovePNum (int pnum) org = lrp; -/* - if (old) - { - float f = (cl.time-cl.lerpents[cl.viewentity[pnum]].lerptime)/cl.lerpents[cl.viewentity[pnum]].lerprate; - f=1-f; - if (f<0)f=0; - if (f>1)f=1; - - vel = vec3_origin; - - for (i=0 ; i<3 ; i++) - lrp[i] = state->origin[i] + - f * (old->origin[i] - state->origin[i]); - - org = lrp; - } - else - { - org = state->origin; - Con_Printf("No old\n"); - } -*/ - goto fixedorg; } } @@ -689,32 +806,64 @@ fixedorg: to = &cl.frames[cl.validsequence & UPDATE_MASK]; - for (i=1 ; i=0 && !cl_nolerp.value) { - to = &cl.frames[(cl.validsequence+i) & UPDATE_MASK]; - if (cl.intermission) - to->playerstate->pm_type = PM_FLY; - CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]] - , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); + float f; - cl.onground[pnum] = pmove.onground; + to = &cl.frames[cl.validsequence & UPDATE_MASK]; + from = &cl.frames[cl.oldvalidsequence & UPDATE_MASK]; - if (to->senttime >= cl.time) - break; - from = to; + //figure out the lerp factor + f = (cl.gametime-cl.servertime)/(cl.gametime-cl.oldgametime);//f = (cl.time-cl.lerpents[state->number].lerptime)/cl.lerpents[state->number].lerprate; + if (f<0) + f=0; + if (f>1) + f=1; +// f = 1-f; + + + // calculate origin + for (i=0 ; i<3 ; i++) + { + lrp[i] = to->playerstate[cl.playernum[pnum]].origin[i] + + f * (from->playerstate[cl.playernum[pnum]].origin[i] - to->playerstate[cl.playernum[pnum]].origin[i]); + + cl.simangles[pnum][i] = LerpAngles16(to->playerstate[spec_track[pnum]].command.angles[i], from->playerstate[spec_track[pnum]].command.angles[i], f)*360.0f/65535; + } + + org = lrp; + + goto fixedorg; } - - if (independantphysics[pnum].msec) + else { - from = to; - to = &ind; - to->cmd[pnum] = independantphysics[pnum]; - to->senttime = cl.time; + for (i=1 ; iplayerstate->pm_type = PM_FLY; CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]] - , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); + , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); - cl.onground[pnum] = pmove.onground; + cl.onground[pnum] = pmove.onground; + + if (to->senttime >= cl.time) + break; + from = to; + } + + if (independantphysics[pnum].msec) + { + from = to; + to = &ind; + to->cmd[pnum] = independantphysics[pnum]; + to->senttime = cl.time; + CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]] + , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); + + cl.onground[pnum] = pmove.onground; + } } pmove.numphysent = oldphysent; @@ -757,6 +906,10 @@ fixedorg: CL_CatagorizePosition(pnum); } + + if (cls.demoplayback) + CL_LerpMove (pnum, to->senttime); + out: CL_CalcCrouch (pnum); cl.waterlevel[pnum] = pmove.waterlevel; diff --git a/engine/client/client.h b/engine/client/client.h index e2ba9301e..f7bc03fa9 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -459,6 +459,11 @@ typedef struct // the client simulates or interpolates movement to get these values double time; // this is the time value that the client // is rendering at. always <= realtime + + float servertime; //current server time, bound between gametime and gametimemark + float mtime; //server time as on the server when we last received a packet. not allowed to decrease. + float oldmtime; //server time as on the server for the previously received packet. + float gametime; float gametimemark; float oldgametime; //used as the old time to lerp cl.time from. diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index e7f10d9d9..c5228e42c 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -513,7 +513,7 @@ void CLQ3_ParseGameState(void) // // wipe the client_state_t struct // - memset(&cl, 0, sizeof(cl)); + CL_ClearState(); cl.minpitch = -90; cl.maxpitch = 90; diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 66dabb599..c28de390d 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -204,7 +204,6 @@ void M_Download_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m) if (!cls.downloadmethod && (info->parsedsourcenum==-1 || downloadablelist[info->parsedsourcenum])) { //done downloading char basename[64]; - char *absolutename; info->parsedsourcenum++; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 81a39df06..df034bfd2 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -33,8 +33,6 @@ cvar_t pr_menuqc_coreonerror = {"pr_menuqc_coreonerror", "1"}; //pr_cmds.c builtins that need to be moved to a common. void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...); -void PF_cvar_string (progfuncs_t *prinst, struct globalvars_s *pr_globals); -void PF_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_print (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_dprint (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_error (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -190,7 +188,30 @@ void PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = (float)(((int)G_FLOAT(OFS_PARM0))%((int)G_FLOAT(OFS_PARM1))); } +char *RemapCvarNameFromDPToFTE(char *name) +{ + if (!stricmp(name, "vid_bitsperpixel")) + return "vid_bpp"; + if (!stricmp(name, "_cl_playermodel")) + return "model"; + if (!stricmp(name, "_cl_playerskin")) + return "skin"; + if (!stricmp(name, "_cl_color")) + return "topcolor"; + if (!stricmp(name, "_cl_name")) + return "name"; + if (!stricmp(name, "v_contrast")) + return "v_contrast"; + if (!stricmp(name, "v_hwgamma")) + return "vid_hardwaregamma"; + if (!stricmp(name, "showfps")) + return "show_fps"; + if (!stricmp(name, "sv_progs")) + return "progs"; + + return name; +} static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -198,6 +219,7 @@ static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) char *str; str = PR_GetStringOfs(prinst, OFS_PARM0); + str = RemapCvarNameFromDPToFTE(str); { var = Cvar_Get(str, "", 0, "menu cvars"); if (var) @@ -210,23 +232,39 @@ static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = 0; } } +static void PF_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *var_name, *val; + cvar_t *var; + + var_name = PR_GetStringOfs(prinst, OFS_PARM0); + var_name = RemapCvarNameFromDPToFTE(var_name); + val = PR_GetStringOfs(prinst, OFS_PARM1); + + var = Cvar_Get(var_name, val, 0, "QC variables"); + Cvar_Set (var, val); +} +static void PF_cvar_string (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str = PR_GetStringOfs(prinst, OFS_PARM0); + cvar_t *cv = Cvar_Get(RemapCvarNameFromDPToFTE(str), "", 0, "QC variables"); + G_INT( OFS_RETURN ) = (int)PR_SetString( prinst, cv->string ); +} + +qboolean M_Vid_GetMove(int num, int *w, int *h); +//a bit pointless really void PF_cl_getresolution (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float mode = G_FLOAT(OFS_PARM0); float *ret = G_VECTOR(OFS_RETURN); -#pragma message("fixme: PF_getresolution should return other modes") - if (mode > 0) - { - ret[0] = 0; - ret[1] = 0; - ret[2] = 0; - } - else - { - ret[0] = vid.width; - ret[1] = vid.height; - ret[2] = 0; - } + int w, h; + + w=h=0; + M_Vid_GetMove(mode, &w, &h); + + ret[0] = w; + ret[1] = h; + ret[2] = 0; } @@ -475,12 +513,45 @@ void PF_CL_drawfill (progfuncs_t *prinst, struct globalvars_s *pr_globals) //void drawsetcliparea(float x, float y, float width, float height) = #458; void PF_CL_drawsetcliparea (progfuncs_t *prinst, struct globalvars_s *pr_globals) { + float x = G_FLOAT(OFS_PARM0), y = G_FLOAT(OFS_PARM1), w = G_FLOAT(OFS_PARM2), h = G_FLOAT(OFS_PARM3); + +#ifdef RGLQUAKE + if (qrenderer == QR_OPENGL && qglScissor) + { + + x *= (float)glwidth/vid.width; + y *= (float)glheight/vid.height; + + w *= (float)glwidth/vid.width; + h *= (float)glheight/vid.height; + + //add a pixel because this makes DP's menus come out right. + x-=1; + y-=1; + w+=2; + h+=2; + + + qglScissor (x, glheight-(y+h), w, h); + qglEnable(GL_SCISSOR_TEST); G_FLOAT(OFS_RETURN) = 1; + return; + } +#endif + G_FLOAT(OFS_RETURN) = 0; } //void drawresetcliparea(void) = #459; void PF_CL_drawresetcliparea (progfuncs_t *prinst, struct globalvars_s *pr_globals) { +#ifdef RGLQUAKE + if (qrenderer == QR_OPENGL) + { + qglDisable(GL_SCISSOR_TEST); G_FLOAT(OFS_RETURN) = 1; + return; + } +#endif + G_FLOAT(OFS_RETURN) = 0; } //void (float width, vector rgb, float alpha, float flags, vector pos1, ...) drawline; diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index a93c0ae92..e3ff9260c 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -956,16 +956,17 @@ HWND hwnd_dialog; #ifndef CLIENTONLY qboolean isDedicated = false; #endif - +/* #ifdef _MSC_VER #include void VARGS Signal_Error_Handler(int i) { int *basepointer; __asm {mov basepointer,ebp}; - Sys_Error("Receieved signal, offset was 0x%8x", basepointer[73]); + Sys_Error("Received signal, offset was 0x%8x", basepointer[73]); } #endif +*/ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { @@ -980,7 +981,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin /* previous instances do not exist in Win32 */ if (hPrevInstance) return 0; - +/* #ifndef _DEBUG #ifdef _MSC_VER signal (SIGFPE, Signal_Error_Handler); @@ -988,7 +989,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin signal (SIGSEGV, Signal_Error_Handler); #endif #endif - +*/ global_hInstance = hInstance; global_nCmdShow = nCmdShow; diff --git a/engine/client/textedit.c b/engine/client/textedit.c index 608c362c9..7ec3c38aa 100644 --- a/engine/client/textedit.c +++ b/engine/client/textedit.c @@ -730,7 +730,7 @@ void Draw_CursorLine(int ox, int y, fileblock_t *b) int cx; int a = 0, i; - int colour=COLOR_WHITE; + int colour=COLOR_BLUE; int ts = edittabspacing.value; if (ts < 1) diff --git a/engine/client/view.c b/engine/client/view.c index c8dcafd6f..c6a0856f6 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1103,8 +1103,6 @@ void V_CalcRefdef (int pnum) return; #endif - V_DriftPitch (pnum); - // view is the weapon model (only visible from inside body) view = &cl.viewent[pnum]; @@ -1341,6 +1339,7 @@ void V_RenderPlayerViews(int plnum) } else { + V_DriftPitch (plnum); V_CalcRefdef (plnum); } diff --git a/engine/common/common.c b/engine/common/common.c index fd0d01dd3..a20097dec 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -1927,7 +1927,7 @@ skipwhite: // parse a regular word do { - if (len >= sizeof(com_token)-1) + if (len >= TOKENSIZE-1) break; com_token[len] = c; data++; @@ -2400,6 +2400,55 @@ char *Info_ValueForKey (char *s, const char *key) } } +char *Info_KeyForNumber (char *s, int num) +{ + static char pkey[1024]; + char *o; + + if (*s == '\\') + s++; + while (1) + { + o = pkey; + while (*s != '\\') + { + if (!*s) + { + *pkey='\0'; + return pkey; + } + *o++ = *s++; + if (o+2 >= pkey+sizeof(pkey)) //hrm. hackers at work.. + { + *pkey='\0'; + return pkey; + } + } + *o = 0; + s++; + + while (*s != '\\' && *s) + { + if (!*s) + { + *pkey='\0'; + return pkey; + } + s++; + } + + if (!num--) + return pkey; //found the right one + + if (!*s) + { + *pkey='\0'; + return pkey; + } + s++; + } +} + void Info_RemoveKey (char *s, const char *key) { char *start; diff --git a/engine/common/fs.c b/engine/common/fs.c index 8d86e5d2f..34729c4a1 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1887,7 +1887,7 @@ gamemode_info_t gamemode_info[] = { {"Darkplaces-Quake", "darkplaces", "-quake", "id1/pak0.pak", "id1", "qw", "fte"}, {"Darkplaces-Hipnotic", "hipnotic", "-hipnotic", NULL/*"hipnotic/pak0.pak"*/,"id1", "qw", "hipnotic", "fte"}, {"Darkplaces-Rogue", "rogue", "-rogue", NULL/*"rogue/pak0.pak", "id1"*/, "qw", "rogue", "fte"}, - {"Nexuiz", "nexuiz", "-nexuiz", "data/data20050531.pk3", "id1", "qw", "data", "fte"}, + {"Nexuiz", "nexuiz", "-nexuiz", "data/cvars.txt", "id1", "qw", "data", "fte"}, //supported commercial mods (some are currently only partially supported) {"FTE-Hexen2", "hexen", "-hexen2", "data1/pak0.pak", "data1", "fte"}, diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 478dc6b77..9231a01dd 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -3310,7 +3310,7 @@ void Q2BSP_MarkLights (dlight_t *light, int bit, mnode_t *node) } surf->dlightbits |= bit; } - return; + return; } splitplane = node->plane; diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 61882a00b..7866fa437 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -279,12 +279,16 @@ qboolean NQNetChan_Process(netchan_t *chan) } drop = sequence - chan->incoming_unreliable - 1; if (drop > 0) + { Con_DPrintf("Dropped %i datagrams\n", drop); + chan->drop_count += drop; + } chan->incoming_unreliable = sequence; chan->last_received = realtime; chan->incoming_acknowledged++; + chan->good_count++; return 1; } if (header & NETFLAG_DATA) diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 3e5eb2fe3..c2a6dd01a 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -836,8 +836,8 @@ int UDP_OpenSocket (int port, qboolean bcast) int i; int maxport = port + 100; - if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) - Sys_Error ("UDP_OpenSocket: socket: %s", strerror(qerrno)); + if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) + return INVALID_SOCKET; if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 99eb86c0b..bf9948c35 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -683,34 +683,41 @@ typedef struct entity_state_s int bitmask; // for dp ents, so lost state can be repeated in replacement packets. int flags; // nolerp, etc + + int effects; + vec3_t origin; - vec3_t old_origin; //q2 vec3_t angles; - unsigned short modelindex2; //q2 +#if defined(Q2CLIENT) || defined(Q2SERVER) + int renderfx; //q2 + vec3_t old_origin; //q2/q3 qbyte modelindex3; //q2 qbyte modelindex4; //q2 - unsigned short frame; - unsigned short colormap; - unsigned short skinnum; - int effects; - int renderfx; //q2 qbyte sound; //q2 qbyte event; //q2 + unsigned short modelindex2; //q2 +#endif + unsigned short frame; + unsigned short colormap; + unsigned short skinnum; + qbyte glowsize; qbyte glowcolour; - qbyte scale; qbyte trans; + char fatness; qbyte hexen2flags; qbyte abslight; qbyte dpflags; - qbyte solid; - unsigned short light[4]; + qbyte solid; + qbyte colormod[3]; + qbyte lightstyle; qbyte lightpflags; + unsigned short light[4]; unsigned short tagentity; unsigned short tagindex; @@ -736,6 +743,8 @@ typedef struct usercmd_s short forwardmove, sidemove, upmove; qbyte impulse; qbyte lightlevel; + + //freestyle qbyte weapon; int servertime; } usercmd_t; diff --git a/engine/common/world.h b/engine/common/world.h index 630f5265b..dcdf379b7 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -91,6 +91,9 @@ typedef struct q2trace_s #define MOVE_NOMONSTERS 1 #define MOVE_MISSILE 2 #define MOVE_HITMODEL 4 +#define MOVE_RESERVED 8 //so we are less likly to get into tricky situations when we want to steal annother future DP extension. +#define MOVE_TRIGGERS 16 //triggers must be marked with FINDABLE_NONSOLID (an alternative to solid-corpse) +#define MOVE_EVERYTHING 32 //doesn't use the area grid stuff, and can return triggers and non-solid items if they're marked with FINDABLE_NONSOLID typedef struct areanode_s { diff --git a/engine/common/zone.c b/engine/common/zone.c index 95797de8a..71ec88968 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -197,6 +197,8 @@ void VARGS Z_Free (void *c) if (nz == zone_head) zone_head = nz->next; +// Con_Printf("Free of %i bytes\n", nz->size); + free(nz); } @@ -279,7 +281,9 @@ void *Z_BaseTagMalloc (int size, int tag, qboolean clear) zone_t *nt; // Z_CheckSentinals(); - +//Con_Printf("Malloc of %i bytes\n", size); +//if (size>20) +//Con_Printf("Big malloc\n"); if (size <= 0) Sys_Error ("Z_Malloc: size %i", size); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index a00301d37..f95923087 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -1668,6 +1668,7 @@ void Shader_UpdateRegistration (void) } } */ +/* void Shader_UploadCinematic (shader_t *shader) { int j; @@ -1677,7 +1678,7 @@ void Shader_UploadCinematic (shader_t *shader) pass = shader->passes; for ( j = 0; j < shader->numpasses; j++, pass++ ) { if ( pass->flags & SHADER_PASS_VIDEOMAP ) { -// pass->anim_frames[0] = GL_ResampleCinematicFrame ( pass ); + pass->anim_frames[0] = GL_ResampleCinematicFrame ( pass ); } } } @@ -1700,9 +1701,8 @@ void Shader_RunCinematic (void) if ( !(pass->flags & SHADER_PASS_VIDEOMAP) ) continue; -//FIXME: videomaps // reinitialize -/* if ( pass->cin->frame == -1 ) { + if ( pass->cin->frame == -1 ) { GL_StopCinematic ( pass->cin ); GL_PlayCinematic( pass->cin ); @@ -1715,10 +1715,10 @@ void Shader_RunCinematic (void) } GL_RunCinematic ( pass->cin ); -*/ } } } +*/ void Shader_DefaultBSP(char *shortname, shader_t *s) { diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index a854ba4af..616731451 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -4992,13 +4992,21 @@ void QCC_PR_ParseStatement (void) if (e == &def_ret) { //copy it out, so our hack just below doesn't crash us - if (e->type->type == ev_vector) +/* if (e->type->type == ev_vector) e = QCC_PR_Statement(pr_opcodes+OP_STORE_V, e, QCC_GetTemp(type_vector), NULL); else e = QCC_PR_Statement(pr_opcodes+OP_STORE_F, e, QCC_GetTemp(type_float), NULL); + + if (e == &def_ret) //this shouldn't be happening + QCC_Error(ERR_INTERNAL, "internal error: switch: e == &def_ret"); +*/ + et = NULL; + } + else + { + et = e->temp; + e->temp = NULL; //so noone frees it until we finish this loop } - et = e->temp; - e->temp = NULL; //so noone frees it until we finish this loop //expands @@ -5216,8 +5224,11 @@ void QCC_PR_ParseStatement (void) num_breaks = breaks; } - e->temp = et; - QCC_FreeTemp(e); + if (et) + { + e->temp = et; + QCC_FreeTemp(e); + } return; } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 49dc8feb1..e8a08598f 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -59,6 +59,9 @@ cvar_t pr_compatabilitytest = {"pr_compatabilitytest", "0", NULL, CVAR_LATCH}; cvar_t pr_ssqc_coreonerror = {"pr_coreonerror", "1"}; +cvar_t pr_tempstringcount = {"pr_tempstringcount", "16"}; +cvar_t pr_tempstringsize = {"pr_tempstringsize", "4096"}; + cvar_t sv_addon[MAXADDONS]; char cvargroup_progs[] = "Progs variables"; @@ -886,6 +889,9 @@ void PR_Init(void) Cvar_Register (&pr_overridebuiltins, cvargroup_progs); Cvar_Register (&pr_ssqc_coreonerror, cvargroup_progs); + + Cvar_Register (&pr_tempstringcount, cvargroup_progs); + Cvar_Register (&pr_tempstringsize, cvargroup_progs); } void Q_InitProgs(void) @@ -1463,12 +1469,11 @@ char *PF_VarString (progfuncs_t *prinst, int first, globalvars_t *pr_globals) s = PR_GetStringOfs(prinst, OFS_PARM0+i*3); if (s) { - strcat (out, Translate(s)); + s = Translate(s); + if (strlen(out)+strlen(s)+1 >= sizeof(buffer[0])) + SV_Error("VarString (builtin call ending with strings) exceeded maximum string length of %i chars", sizeof(buffer[0])); -//#ifdef PARANOID - if (strlen(out)+1 >= sizeof(buffer[0])) - Sys_Error("VarString (builtin call ending with strings) exceeded maximum string length of %i chars", sizeof(buffer[0])); -//#endif + strcat (out, s); } } return out; @@ -3268,7 +3273,7 @@ void PF_findradius (progfuncs_t *prinst, struct globalvars_s *pr_globals) ent = EDICT_NUM(svprogfuncs, i); if (ent->isfree) continue; - if (ent->v->solid == SOLID_NOT) + if (ent->v->solid == SOLID_NOT && (progstype != PROG_QW || !((int)ent->v->flags & FL_FINDABLE_NONSOLID))) continue; for (j=0 ; j<3 ; j++) eorg[j] = org[j] - (ent->v->origin[j] + (ent->v->mins[j] + ent->v->maxs[j])*0.5); @@ -3338,8 +3343,8 @@ void PF_printv (progfuncs_t *prinst, struct globalvars_s *pr_globals) Con_Printf (PR_GetStringOfs(prinst, OFS_PARM0),temp); } -#define MAX_TEMPSTRS 16 -#define MAXTEMPBUFFERLEN 4096 +#define MAX_TEMPSTRS ((int)pr_tempstringcount.value) +#define MAXTEMPBUFFERLEN ((int)pr_tempstringsize.value) char *PF_TempStr(progfuncs_t *prinst) { if (prinst->tempstringnum == MAX_TEMPSTRS) @@ -3356,6 +3361,13 @@ string_t PR_TempString(progfuncs_t *prinst, char *str) void PF_InitTempStrings(progfuncs_t *prinst) { + if (pr_tempstringcount.value < 2) + pr_tempstringcount.value = 2; + if (pr_tempstringsize.value < 256) + pr_tempstringsize.value = 256; + pr_tempstringcount.flags |= CVAR_NOSET; + pr_tempstringsize.flags |= CVAR_NOSET; + prinst->tempstringbase = prinst->AddString(prinst, "", MAXTEMPBUFFERLEN*MAX_TEMPSTRS); prinst->tempstringnum = 0; } @@ -3827,11 +3839,14 @@ void PF_lightstyle (progfuncs_t *prinst, struct globalvars_s *pr_globals) continue; if ( client->state == cs_spawned ) { + if (style >= MAX_STANDARDLIGHTSTYLES) + if (!*val) + continue; #ifdef PEXT_LIGHTSTYLECOL if (client->fteprotocolextensions & PEXT_LIGHTSTYLECOL && col!=7) { ClientReliableWrite_Begin (client, svc_lightstylecol, strlen(val)+4); - ClientReliableWrite_Char (client, style); + ClientReliableWrite_Byte (client, style); ClientReliableWrite_Char (client, col); ClientReliableWrite_String (client, val); } @@ -3839,7 +3854,7 @@ void PF_lightstyle (progfuncs_t *prinst, struct globalvars_s *pr_globals) { #endif ClientReliableWrite_Begin (client, svc_lightstyle, strlen(val)+3); - ClientReliableWrite_Char (client, style); + ClientReliableWrite_Byte (client, style); ClientReliableWrite_String (client, val); #ifdef PEXT_LIGHTSTYLECOL } @@ -5475,6 +5490,8 @@ static int chrconv_number(int i, int base, int conv) switch (conv) { default: + case 5: + case 6: case 0: break; case 1: @@ -5509,7 +5526,7 @@ static int chrconv_punct(int i, int base, int conv) } return i + base; } -static int chrchar_alpha(int i, int basec, int baset, int convc, int convt) +static int chrchar_alpha(int i, int basec, int baset, int convc, int convt, int charnum) { //convert case and colour seperatly... @@ -5525,6 +5542,11 @@ static int chrchar_alpha(int i, int basec, int baset, int convc, int convt) case 2: baset = 128; break; + + case 5: + case 6: + baset = 128*((charnum&1) == (convt-5)); + break; } switch (convc) @@ -5570,13 +5592,13 @@ void PF_strconv (progfuncs_t *prinst, struct globalvars_s *pr_globals) *result = chrconv_number(*string, '0'-30, redchars); else if (*string >= 'a' && *string <= 'z') //normal numbers... - *result = chrchar_alpha(*string, 0, 'a', ccase, redchars); + *result = chrchar_alpha(*string, 'a', 0, ccase, redchars, i); else if (*string >= 'A' && *string <= 'Z') //normal numbers... - *result = chrchar_alpha(*string, 0, 'A', ccase, redchars); + *result = chrchar_alpha(*string, 'A', 0, ccase, redchars, i); else if (*string >= 'a'+128 && *string <= 'z'+128) //normal numbers... - *result = chrchar_alpha(*string, 128, 'a', ccase, redchars); + *result = chrchar_alpha(*string, 'a', 128, ccase, redchars, i); else if (*string >= 'A'+128 && *string <= 'Z'+128) //normal numbers... - *result = chrchar_alpha(*string, 128, 'A', ccase, redchars); + *result = chrchar_alpha(*string, 'A', 128, ccase, redchars, i); else if ((*string & 127) < 16 || !redalpha) //special chars.. *result = *string; @@ -6169,6 +6191,7 @@ lh_extension_t QSG_Extensions[] = { #ifdef SVCHAT {"FTE_NPCCHAT", 1, NULL, {"chat"}}, //server looks at chat files. It automagically branches through calling qc functions as requested. #endif + {"FTE_QC_CHECKPVS", 1, NULL, {"checkpvs"}}, {"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclient"}}, {"FTE_SOLID_LADDER"}, //part of a worthy hl implementation. Allows a simple trigger to remove effects of gravity (solid 20) @@ -6530,7 +6553,7 @@ void PF_strpad (progfuncs_t *prinst, struct globalvars_s *pr_globals) Q_strncpyz(dest, src, MAXTEMPBUFFERLEN); dest+=strlen(dest); - while(pad) + while(pad-->0) *dest++ = ' '; *dest = '\0'; } @@ -8821,6 +8844,120 @@ void PF_runclientphys(progfuncs_t *prinst, struct globalvars_s *pr_globals) PM_PlayerMove(sv.gamespeed); } +//DP_QC_GETSURFACE +// #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) +void PF_getsurfacenumpoints(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int surfnum; + model_t *model; + int modelindex; + edict_t *ent; + + ent = G_EDICT(prinst, OFS_PARM0); + surfnum = G_FLOAT(OFS_PARM1); + + modelindex = ent->v->modelindex; + if (modelindex > 0 && modelindex < MAX_MODELS) + model = sv.models[(int)ent->v->modelindex]; + else + model = NULL; + + if (!model || surfnum >= model->numsurfaces) + G_FLOAT(OFS_RETURN) = 0; + else + G_FLOAT(OFS_RETURN) = model->surfaces[surfnum].mesh->numvertexes; +} +// #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) +void PF_getsurfacepoint(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int surfnum, pointnum; + model_t *model; + int modelindex; + edict_t *ent; + + ent = G_EDICT(prinst, OFS_PARM0); + surfnum = G_FLOAT(OFS_PARM1); + pointnum = G_FLOAT(OFS_PARM2); + + modelindex = ent->v->modelindex; + if (modelindex > 0 && modelindex < MAX_MODELS) + model = sv.models[(int)ent->v->modelindex]; + else + model = NULL; + + if (!model || surfnum >= model->numsurfaces) + { + G_FLOAT(OFS_RETURN+0) = 0; + G_FLOAT(OFS_RETURN+1) = 0; + G_FLOAT(OFS_RETURN+2) = 0; + } + else + { + G_FLOAT(OFS_RETURN+0) = model->surfaces[surfnum].mesh->xyz_array[pointnum][2]; + G_FLOAT(OFS_RETURN+1) = model->surfaces[surfnum].mesh->xyz_array[pointnum][2]; + G_FLOAT(OFS_RETURN+2) = model->surfaces[surfnum].mesh->xyz_array[pointnum][2]; + } +} +// #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) +void PF_getsurfacenormal(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int surfnum, pointnum; + model_t *model; + int modelindex; + edict_t *ent; + + ent = G_EDICT(prinst, OFS_PARM0); + surfnum = G_FLOAT(OFS_PARM1); + pointnum = G_FLOAT(OFS_PARM2); + + modelindex = ent->v->modelindex; + if (modelindex > 0 && modelindex < MAX_MODELS) + model = sv.models[(int)ent->v->modelindex]; + else + model = NULL; + + if (!model || surfnum >= model->numsurfaces) + { + G_FLOAT(OFS_RETURN+0) = 0; + G_FLOAT(OFS_RETURN+1) = 0; + G_FLOAT(OFS_RETURN+2) = 0; + } + else + { + G_FLOAT(OFS_RETURN+0) = model->surfaces[surfnum].plane->normal[0]; + G_FLOAT(OFS_RETURN+1) = model->surfaces[surfnum].plane->normal[1]; + G_FLOAT(OFS_RETURN+2) = model->surfaces[surfnum].plane->normal[2]; + if (model->surfaces[surfnum].flags & SURF_PLANEBACK) + VectorInverse(G_VECTOR(OFS_RETURN)); + } +} +// #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) +void PF_getsurfacetexture(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +} +// #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) +void PF_getsurfacenearpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +} +// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) +void PF_getsurfaceclippedpoint(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +} + +//#240 float(vector viewpos, entity viewee) checkpvs (FTE_QC_CHECKPVS) +//note: this requires a correctly setorigined entity. +void PF_checkpvs(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *viewpos = G_VECTOR(OFS_PARM0); + edict_t *ent = G_EDICT(prinst, OFS_PARM1); + + //FIXME: Make all alternatives of FatPVS not recalulate the pvs. + //and yeah, this is overkill what with the whole fat thing and all. + sv.worldmodel->funcs.FatPVS(sv.worldmodel, viewpos, false); + + G_FLOAT(OFS_RETURN) = sv.worldmodel->funcs.EdictInFatPVS(sv.worldmodel, ent); +} + //entity(string match [, float matchnum]) matchclient = #241; void PF_matchclient(progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -9155,6 +9292,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"isbackbuffered", PF_isbackbuffered, 0, 0, 0, 234}, {"te_bloodqw", PF_te_bloodqw, 0, 0, 0, 239}, + {"checkpvs", PF_checkpvs, 0, 0, 0, 240}, {"matchclientname", PF_matchclient, 0, 0, 0, 241}, //end fte extras @@ -9213,14 +9351,14 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"vectorvectors", PF_vectorvectors, 0, 0, 0, 432},// #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) {"te_plasmaburn", PF_te_plasmaburn, 0, 0, 0, 433},// #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) -/* + {"getsurfacenumpoints",PF_getsurfacenumpoints,0,0, 0, 434},// #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) {"getsurfacepoint",PF_getsurfacepoint, 0, 0, 0, 435},// #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) {"getsurfacenormal",PF_getsurfacenormal,0, 0, 0, 436},// #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) - {"getsurfacetexture",PF_getsurfacetexture,0, 0, 0, 437},// #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) +// {"getsurfacetexture",PF_getsurfacetexture,0, 0, 0, 437},// #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) {"getsurfacenearpoint",PF_getsurfacenearpoint,0,0, 0, 438},// #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) {"getsurfaceclippedpoint",PF_getsurfaceclippedpoint,0,0,0, 439},// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) -*/ + //KRIMZON_SV_PARSECLIENTCOMMAND {"clientcommand", PF_clientcommand, 0, 0, 0, 440},// #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) {"tokenize", PF_Tokenize, 0, 0, 0, 441},// #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) diff --git a/engine/server/server.h b/engine/server/server.h index 462b98f81..7d7c0d682 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -784,6 +784,7 @@ typedef struct #define FL_PARTIALGROUND 1024 // not all corners are valid #define FL_WATERJUMP 2048 // player jumping out of water +#define FL_FINDABLE_NONSOLID 16384 //a cpqwsv feature #define FL_MOVECHAIN_ANGLE 32768 // when in a move chain, will update the angle #define FL_CLASS_DEPENDENT 2097152 diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 826ceb338..99da79384 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -1179,6 +1179,25 @@ void SV_Serverinfo_f (void) if (Cmd_Argv(1)[0] == '*') { + if (!strcmp(Cmd_Argv(1), "*")) + if (!strcmp(Cmd_Argv(2), "")) + { //clear it out + char *k; + for(i=0;;) + { + k = Info_KeyForNumber(svs.info, i); + if (!*k) + break; //no more. + else if (*k == '*') + i++; //can't remove * keys + else if ((var = Cvar_FindVar(k)) && var->flags&CVAR_SERVERINFO) + i++; //this one is a cvar. + else + Info_RemoveKey(svs.info, k); //we can remove this one though, so yay. + } + + return; + } Con_TPrintf (TL_STARKEYPROTECTED); return; } @@ -1233,6 +1252,12 @@ void SV_Localinfo_f (void) if (Cmd_Argv(1)[0] == '*') { + if (!strcmp(Cmd_Argv(1), "*")) + if (!strcmp(Cmd_Argv(2), "")) + { //clear it out + Info_RemoveNonStarKeys(localinfo); + return; + } Con_TPrintf (TL_STARKEYPROTECTED); return; } @@ -1272,8 +1297,10 @@ void SV_SaveInfo(FILE *f, char *info, char *commandname) void SV_SaveInfos(FILE *f) { fwrite("\n", 1, 1, f); + fwrite("serverinfo * \"\"\n", 16, 1, f); SV_SaveInfo(f, svs.info, "serverinfo"); fwrite("\n", 1, 1, f); + fwrite("localinfo * \"\"\n", 15, 1, f); SV_SaveInfo(f, localinfo, "localinfo"); } diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 414946d73..8b2774a4f 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -782,7 +782,7 @@ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t * // flag #define E5_FRAME16 (1<<21) // unused -#define E5_UNUSED22 (1<<22) +#define E5_COLORMOD (1<<22) // bits >= (1<<24) #define E5_EXTEND3 (1<<23) @@ -803,8 +803,6 @@ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t * // bits2 > 0 #define E5_EXTEND4 (1<<31) - - void SVDP_EmitEntity(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean isnew) { int bits; @@ -847,8 +845,8 @@ void SVDP_EmitEntity(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, q bits |= E5_LIGHT; if (from->glowsize != to->glowsize || from->glowcolour != to->glowcolour) bits |= E5_GLOW; -// if (from->colormod[0] != to->colormod[0] || o->colormod[1] != to->colormod[1] || o->colormod[2] != to->colormod[2]) -// bits |= E5_COLORMOD; + if (from->colormod[0] != to->colormod[0] || from->colormod[1] != to->colormod[1] || from->colormod[2] != to->colormod[2]) + bits |= E5_COLORMOD; if ((bits & E5_ORIGIN) && (/*!(to->flags & RENDER_LOWPRECISION) ||*/ to->origin[0] < -4096 || to->origin[0] >= 4096 || to->origin[1] < -4096 || to->origin[1] >= 4096 || to->origin[2] < -4096 || to->origin[2] >= 4096)) bits |= E5_ORIGIN32; @@ -968,12 +966,12 @@ void SVDP_EmitEntity(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, q MSG_WriteByte(msg, to->glowsize); MSG_WriteByte(msg, to->glowcolour); } -// if (bits & E5_COLORMOD) -// { -// MSG_WriteByte(msg, to->colormod[0]); -// MSG_WriteByte(msg, to->colormod[1]); -// MSG_WriteByte(msg, to->colormod[2]); -// } + if (bits & E5_COLORMOD) + { + MSG_WriteByte(msg, to->colormod[0]); + MSG_WriteByte(msg, to->colormod[1]); + MSG_WriteByte(msg, to->colormod[2]); + } } entity_state_t defaultstate; diff --git a/engine/server/sv_master.c b/engine/server/sv_master.c index 80d93a50d..144f1e29d 100644 --- a/engine/server/sv_master.c +++ b/engine/server/sv_master.c @@ -71,15 +71,15 @@ typedef struct svm_server_s { } svm_server_t; typedef struct { + int socketudp; float time; int port; - int socketudp; svm_server_t *firstserver; int numservers; } masterserver_t; -masterserver_t svm; +masterserver_t svm = {INVALID_SOCKET}; void SVM_RemoveOldServers(void) { @@ -155,14 +155,17 @@ void SVM_Heartbeat(netadr_t *adr, int numclients, float validuntil) void SVM_Init(int port) { - if (!svm.socketudp) + if (svm.socketudp == INVALID_SOCKET) svm.socketudp = UDP_OpenSocket(port, false); } void SVM_ShutDown (void) { - if (svm.socketudp) + if (svm.socketudp != INVALID_SOCKET) + { UDP_CloseSocket(svm.socketudp); + svm.socketudp = INVALID_SOCKET; + } } void SVM_Think(int port) @@ -187,11 +190,14 @@ void SVM_Think(int port) addrlen = sizeof(addr); net_message.cursize = recvfrom(svm.socketudp, net_message_buffer, sizeof(net_message_buffer)-1, 0, (struct sockaddr *)&addr, &addrlen); - net_message.data[net_message.cursize] = '\0'; //null term all strings. - if (net_message.cursize < 0) + if (net_message.cursize <= 0) { + addrlen = WSAGetLastError(); + + return; } + net_message.data[net_message.cursize] = '\0'; //null term all strings. SockadrToNetadr(&addr, &netaddr); svm.time = Sys_DoubleTime(); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 4a8db9d74..eb5d2a22c 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -989,13 +989,13 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) // every now and then, send an update so that extrapolation // on client side doesn't stray too far off if (ISQWCLIENT(client)) - if (client->zquake_extensions & Z_EXT_SERVERTIME && sv.time - client->nextservertimeupdate > 0) + if (client->zquake_extensions & Z_EXT_SERVERTIME && sv.physicstime - client->nextservertimeupdate > 0) { MSG_WriteByte (msg, svc_updatestatlong); MSG_WriteByte (msg, STAT_TIME); - MSG_WriteLong (msg, (int)(sv.time * 1000)); + MSG_WriteLong (msg, (int)(sv.physicstime * 1000)); - client->nextservertimeupdate = sv.time+10; + client->nextservertimeupdate = sv.physicstime;//+10; } #ifdef NQPROT diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index ae4fe0e3d..f7f7842c2 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1101,28 +1101,35 @@ void SV_Spawn_f (void) { if (sv.democausesreconnect) { + if (i >= MAX_STANDARDLIGHTSTYLES) + continue; ClientReliableWrite_Begin (host_client, svc_lightstyle, 3 + (sv.demolightstyles[i] ? strlen(sv.demolightstyles[i]) : 1)); ClientReliableWrite_Byte (host_client, (char)i); ClientReliableWrite_String (host_client, sv.demolightstyles[i]); } else + { + if (i >= MAX_STANDARDLIGHTSTYLES) + if (!sv.lightstyles[i]) + continue; #ifdef PEXT_LIGHTSTYLECOL - if (host_client->fteprotocolextensions & PEXT_LIGHTSTYLECOL && sv.lightstylecolours[i]!=7) - { - ClientReliableWrite_Begin (host_client, svc_lightstylecol, - 3 + (sv.lightstyles[i] ? strlen(sv.lightstyles[i]) : 1)); - ClientReliableWrite_Byte (host_client, (char)i); - ClientReliableWrite_Char (host_client, sv.lightstylecolours[i]); - ClientReliableWrite_String (host_client, sv.lightstyles[i]); - } - else + if (host_client->fteprotocolextensions & PEXT_LIGHTSTYLECOL && sv.lightstylecolours[i]!=7) + { + ClientReliableWrite_Begin (host_client, svc_lightstylecol, + 3 + (sv.lightstyles[i] ? strlen(sv.lightstyles[i]) : 1)); + ClientReliableWrite_Byte (host_client, (char)i); + ClientReliableWrite_Char (host_client, sv.lightstylecolours[i]); + ClientReliableWrite_String (host_client, sv.lightstyles[i]); + } + else #endif - { - ClientReliableWrite_Begin (host_client, svc_lightstyle, - 3 + (sv.lightstyles[i] ? strlen(sv.lightstyles[i]) : 1)); - ClientReliableWrite_Byte (host_client, (char)i); - ClientReliableWrite_String (host_client, sv.lightstyles[i]); + { + ClientReliableWrite_Begin (host_client, svc_lightstyle, + 3 + (sv.lightstyles[i] ? strlen(sv.lightstyles[i]) : 1)); + ClientReliableWrite_Byte (host_client, (char)i); + ClientReliableWrite_String (host_client, sv.lightstyles[i]); + } } } diff --git a/engine/server/svq2_ents.c b/engine/server/svq2_ents.c index 6a52ad7cb..eeff029e0 100644 --- a/engine/server/svq2_ents.c +++ b/engine/server/svq2_ents.c @@ -588,7 +588,7 @@ Build a client frame structure ============================================================================= */ -qbyte fatpvs[(MAX_MAP_LEAFS+1)/4]; +extern qbyte fatpvs[(MAX_MAP_LEAFS+1)/4]; /* ============= diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 7af348a20..8f9eefb15 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -6,7 +6,7 @@ #ifdef Q3SERVER -//#define USEBOTLIB +#define USEBOTLIB #ifdef USEBOTLIB @@ -24,8 +24,43 @@ #define Z_TAG_BOTLIB 221726 +#ifdef _WIN32 + #if 0 + #pragma comment (lib, "botlib.lib") + #define FTE_GetBotLibAPI GetBotLibAPI + #else + botlib_export_t *FTE_GetBotLibAPI( int apiVersion, botlib_import_t *import ) + { + botlib_export_t *(*QDECL pGetBotLibAPI)( int apiVersion, botlib_import_t *import ); -#pragma comment (lib, "H:/quake/quake3/quake3-1.32b/code/botlib/botlib_vc6/Debug/botlib_vc6.lib") + static HINSTANCE hmod; + if (!hmod) + hmod = LoadLibrary("botlib.dll"); + if (!hmod) + return NULL; + + pGetBotLibAPI = (void*)GetProcAddress(hmod, "GetBotLibAPI"); + + if (!pGetBotLibAPI) + return NULL; + return pGetBotLibAPI(apiVersion, import); + } + #endif + +#elif defined(__linux__) + + #include "dlopen.h" + botlib_export_t *FTE_GetBotLibAPI( int apiVersion, botlib_import_t *import ) + { + void *handle; + dlopen(); + } +#else + botlib_export_t *FTE_GetBotLibAPI(int version, int apiVersion, botlib_import_t *import) + { //a stub that will prevent botlib from loading. + return NULL; + } +#endif botlib_export_t *botlib; @@ -1751,7 +1786,7 @@ void SV_InitBotLib() // Z_FreeTags(Z_TAG_BOTLIB); botlibmemoryavailable = 1024*1024*16; - botlib = GetBotLibAPI(BOTLIB_API_VERSION, &import); + botlib = FTE_GetBotLibAPI(BOTLIB_API_VERSION, &import); if (!botlib) { bot_enable->flags |= CVAR_LATCH; @@ -1773,10 +1808,14 @@ void SV_InitBotLib() qboolean SVQ3_InitGame(void) { char buffer[8192]; + extern cvar_t progs; if (sv.worldmodel->fromgame == fg_quake) return false; //always fail on q1bsp + if (*progs.string) //don't load q3 gamecode if we're explicitally told to load a progs. + return false; + SVQ3_ShutdownGame(); @@ -1826,7 +1865,8 @@ void SVQ3_RunFrame(void) { VM_Call(q3gamevm, GAME_RUN_FRAME, (int)(sv.time*1000)); #ifdef USEBOTLIB - VM_Call(q3gamevm, BOTAI_START_FRAME, (int)(sv.time*1000)); + if (botlib) + VM_Call(q3gamevm, BOTAI_START_FRAME, (int)(sv.time*1000)); #endif } diff --git a/engine/server/world.c b/engine/server/world.c index 99b0f2d00..9da3d60a6 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -1498,6 +1498,85 @@ void SVQ2_ClipMoveToEntities ( moveclip_t *clip, int contentsmask ) #endif //=========================================================================== + +/* +==================== +SV_ClipToEverything + +like SV_ClipToLinks, but doesn't use the links part. This can be used for checking triggers, solid entities, not-solid entities. +Sounds pointless, I know. +==================== +*/ +void SV_ClipToEverything (moveclip_t *clip) +{ + int e; + trace_t trace; + edict_t *touch; + for (e=1 ; eisfree) + continue; + if (touch->v->solid == SOLID_NOT && !((int)touch->v->flags & FL_FINDABLE_NONSOLID)) + continue; + if (touch->v->solid == SOLID_TRIGGER && !((int)touch->v->flags & FL_FINDABLE_NONSOLID)) + continue; + + if (touch == clip->passedict) + continue; + + if (clip->type & MOVE_NOMONSTERS && touch->v->solid != SOLID_BSP) + continue; + + if (clip->passedict) + { + // don't clip corpse against character + if (clip->passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE)) + continue; + // don't clip character against corpse + if (clip->passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE) + continue; + + if (!((int)clip->passedict->v->dimension_hit & (int)touch->v->dimension_solid)) + continue; + } + + if (clip->boxmins[0] > touch->v->absmax[0] + || clip->boxmins[1] > touch->v->absmax[1] + || clip->boxmins[2] > touch->v->absmax[2] + || clip->boxmaxs[0] < touch->v->absmin[0] + || clip->boxmaxs[1] < touch->v->absmin[1] + || clip->boxmaxs[2] < touch->v->absmin[2] ) + continue; + + if (clip->passedict && clip->passedict->v->size[0] && !touch->v->size[0]) + continue; // points never interact + + // might intersect, so do an exact clip + if (clip->trace.allsolid) + return; + if (clip->passedict) + { + if (PROG_TO_EDICT(svprogfuncs, touch->v->owner) == clip->passedict) + continue; // don't clip against own missiles + if (PROG_TO_EDICT(svprogfuncs, clip->passedict->v->owner) == touch) + continue; // don't clip against owner + } + + if ((int)touch->v->flags & FL_MONSTER) + trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + else + trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + if (trace.allsolid || trace.startsolid || + trace.fraction < clip->trace.fraction) + { + trace.ent = touch; + clip->trace = trace; + } + } +} + /* ==================== SV_ClipToLinks @@ -1511,6 +1590,71 @@ void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip ) edict_t *touch; trace_t trace; + if (clip->type & MOVE_TRIGGERS) + { + for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next) + { + next = l->next; + touch = EDICT_FROM_AREA(l); + if (!((int)touch->v->flags & FL_FINDABLE_NONSOLID)) + continue; + if (touch->v->solid != SOLID_TRIGGER) + continue; + if (touch == clip->passedict) + continue; + + if (clip->type & MOVE_NOMONSTERS && touch->v->solid != SOLID_BSP) + continue; + + if (clip->passedict) + { + /* These can never happen, touch is a SOLID_TRIGGER + // don't clip corpse against character + if (clip->passedict->v->solid == SOLID_CORPSE && (touch->v->solid == SOLID_SLIDEBOX || touch->v->solid == SOLID_CORPSE)) + continue; + // don't clip character against corpse + if (clip->passedict->v->solid == SOLID_SLIDEBOX && touch->v->solid == SOLID_CORPSE) + continue; + */ + if (!((int)clip->passedict->v->dimension_hit & (int)touch->v->dimension_solid)) + continue; + } + + if (clip->boxmins[0] > touch->v->absmax[0] + || clip->boxmins[1] > touch->v->absmax[1] + || clip->boxmins[2] > touch->v->absmax[2] + || clip->boxmaxs[0] < touch->v->absmin[0] + || clip->boxmaxs[1] < touch->v->absmin[1] + || clip->boxmaxs[2] < touch->v->absmin[2] ) + continue; + + if (clip->passedict && clip->passedict->v->size[0] && !touch->v->size[0]) + continue; // points never interact + + // might intersect, so do an exact clip + if (clip->trace.allsolid) + return; + if (clip->passedict) + { + if (PROG_TO_EDICT(svprogfuncs, touch->v->owner) == clip->passedict) + continue; // don't clip against own missiles + if (PROG_TO_EDICT(svprogfuncs, clip->passedict->v->owner) == touch) + continue; // don't clip against owner + } + + if ((int)touch->v->flags & FL_MONSTER) + trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + else + trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + if (trace.allsolid || trace.startsolid || + trace.fraction < clip->trace.fraction) + { + trace.ent = touch; + clip->trace = trace; + } + } + } + // touch linked edicts for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) { @@ -1754,12 +1898,9 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs ); // clip to entities -/*#ifdef Q2BSPS - if (sv.worldmodel->fromgame == fg_quake2 || sv.worldmodel->fromgame == fg_quake3) - SV_ClipMoveToEntities(&clip); + if (clip.type & MOVE_EVERYTHING) + SV_ClipToEverything (&clip); else -#endif -*/ SV_ClipToLinks ( sv_areanodes, &clip ); if (clip.trace.startsolid)