A couple of changes.

Added a higher quality particle config.
Quick hack for crepuscular rays.
added new command, eg: pr_dumpplatform -FFTE -O csplat
used package reporting on servers, auto package downloading on clients, should be fully implemented.
Smoothed out players a little. Added option to menus.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3926 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2011-12-05 15:23:40 +00:00
parent a3257e524f
commit d6d0105d3c
90 changed files with 5301 additions and 1735 deletions

View File

@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "shader.h"
extern cvar_t cl_predict_players;
extern cvar_t cl_lerp_players;
extern cvar_t cl_solid_players;
extern cvar_t cl_item_bobbing;
@ -1672,7 +1673,7 @@ static void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entit
{
lerpents_t *le;
entity_state_t *snew, *sold;
int i, j;
int i;
int oldpnum, newpnum;
vec3_t move;
@ -1748,7 +1749,6 @@ static void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entit
}
else
{
le->isnew = false;
VectorCopy(le->origin, le->lastorigin);
if (snew->dpflags & RENDER_STEP)
@ -1773,16 +1773,13 @@ static void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entit
{
le->origin[i] = le->oldorigin[i] + lfrac*(le->neworigin[i] - le->oldorigin[i]);
for (j = 0; j < 3; j++)
{
a1 = le->oldangle[i];
a2 = le->newangle[i];
if (a1 - a2 > 180)
a1 -= 360;
if (a1 - a2 < -180)
a1 += 360;
le->angles[i] = a1 + lfrac * (a2 - a1);
}
a1 = le->oldangle[i];
a2 = le->newangle[i];
if (a1 - a2 > 180)
a1 -= 360;
if (a1 - a2 < -180)
a1 += 360;
le->angles[i] = a1 + lfrac * (a2 - a1);
}
}
else
@ -1792,16 +1789,13 @@ static void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entit
{
le->origin[i] = sold->origin[i] + frac*(move[i]);
for (j = 0; j < 3; j++)
{
a1 = sold->angles[i];
a2 = snew->angles[i];
if (a1 - a2 > 180)
a1 -= 360;
if (a1 - a2 < -180)
a1 += 360;
le->angles[i] = a1 + frac * (a2 - a1);
}
a1 = sold->angles[i];
a2 = snew->angles[i];
if (a1 - a2 > 180)
a1 -= 360;
if (a1 - a2 < -180)
a1 += 360;
le->angles[i] = a1 + frac * (a2 - a1);
}
le->orglerpdeltatime = 0.1;
le->orglerpstarttime = oldpack->servertime;
@ -1872,30 +1866,6 @@ static qboolean CL_ChooseInterpolationFrames(int *newf, int *oldf, float servert
return true;
}
/*obtains the current entity frame, and invokes CL_TransitionPacketEntities to process the interpolation details
*/
static packet_entities_t *CL_ProcessPacketEntities(float *servertime, qboolean nolerp)
{
packet_entities_t *packnew, *packold;
int newf, oldf;
if (nolerp)
{ //force our emulated time to as late as we can.
//this will disable all position interpolation
*servertime = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.servertime;
}
if (!CL_ChooseInterpolationFrames(&newf, &oldf, *servertime))
return NULL;
packnew = &cl.frames[newf&UPDATE_MASK].packet_entities;
packold = &cl.frames[oldf&UPDATE_MASK].packet_entities;
CL_TransitionPacketEntities(packnew, packold, *servertime);
return packnew;
}
qboolean CL_MayLerp(void)
{
//force lerping when playing low-framerate demos.
@ -1913,6 +1883,83 @@ qboolean CL_MayLerp(void)
return !cl_nolerp.ival;
}
/*fills in cl.lerpents and cl.currentpackentities*/
void CL_TransitionEntities (void)
{
packet_entities_t *packnew, *packold;
int newf, oldf;
qboolean nolerp;
float servertime;
if (cls.protocol == CP_QUAKEWORLD && (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV))
{
nolerp = false;
}
else
{
nolerp = !CL_MayLerp() && cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV;
}
//force our emulated time to as late as we can, if we're not using interpolation, which has the effect of disabling all interpolation
if (nolerp)
servertime = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.servertime;
else
servertime = cl.servertime;
// servertime -= 0.1;
/*make sure we have some info for it, on failure keep the info from the last frame (its possible that the frame data can be changed by a network packet, but mneh, but chances are if there's no info then there are NO packets at all)*/
if (!CL_ChooseInterpolationFrames(&newf, &oldf, servertime))
return;
newf&=UPDATE_MASK;
oldf&=UPDATE_MASK;
/*transition the ents and stuff*/
packnew = &cl.frames[newf].packet_entities;
packold = &cl.frames[oldf].packet_entities;
CL_TransitionPacketEntities(packnew, packold, servertime);
cl.currentpacktime = servertime;
cl.currentpackentities = packnew;
/*and transition players too*/
{
float frac, a1, a2;
int i,j, p;
vec3_t move;
lerpents_t *le;
player_state_t *pnew, *pold;
if (packnew->servertime == packold->servertime)
frac = 1; //lerp totally into the new
else
frac = (servertime-packold->servertime)/(packnew->servertime-packold->servertime);
pnew = &cl.frames[newf].playerstate[0];
pold = &cl.frames[oldf].playerstate[0];
for (p = 0; p < MAX_CLIENTS; p++, pnew++, pold++)
{
le = &cl.lerpplayers[p];
VectorSubtract(pnew->origin, pold->origin, move);
//lerp based purely on the packet times,
for (i = 0; i < 3; i++)
{
le->origin[i] = pold->origin[i] + frac*(move[i]);
a1 = SHORT2ANGLE(pold->command.angles[i]);
a2 = SHORT2ANGLE(pnew->command.angles[i]);
if (a1 - a2 > 180)
a1 -= 360;
if (a1 - a2 < -180)
a1 += 360;
le->angles[i] = a1 + frac * (a2 - a1);
}
le->orglerpdeltatime = 0.1;
le->orglerpstarttime = packold->servertime;
}
}
}
void CL_LinkPacketEntities (void)
{
entity_t *ent;
@ -1927,43 +1974,24 @@ void CL_LinkPacketEntities (void)
//, spnum;
dlight_t *dl;
vec3_t angles;
qboolean nolerp;
static int flickertime;
static int flicker;
float servertime;
if (cls.protocol == CP_QUAKEWORLD && (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV))
{
servertime = cl.servertime;
nolerp = false;
}
else
{
servertime = cl.servertime;
nolerp = !CL_MayLerp() && cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV;
}
pack = CL_ProcessPacketEntities(&servertime, nolerp);
pack = cl.currentpackentities;
if (!pack)
return;
/*
if ((cls.fteprotocolextensions & PEXT_ACCURATETIMINGS) || cls.protocol != CP_QUAKEWORLD)
servertime = cl.servertime;
else
servertime = realtime;
*/
i = servertime*20;
i = cl.currentpacktime*20;
if (flickertime != i)
{
flickertime = i;
flicker = rand();
}
autorotate = anglemod(100*servertime);
autorotate = anglemod(100*cl.currentpacktime);
#ifdef CSQC_DAT
CSQC_DeltaStart(servertime);
CSQC_DeltaStart(cl.currentpacktime);
#endif
for (newpnum=0 ; newpnum<pack->num_entities ; newpnum++)
@ -2205,6 +2233,7 @@ void CL_LinkPacketEntities (void)
if (le->isnew)
{
le->isnew = false;
pe->DelinkTrailstate(&(cl.lerpents[state->number].trailstate));
pe->DelinkTrailstate(&(cl.lerpents[state->number].emitstate));
continue; // not in last message
@ -2738,6 +2767,23 @@ guess_pm_type:
}
TP_ParsePlayerInfo(oldstate, state, info);
if (cl.worldmodel && cl_lerp_players.ival)
{
player_state_t exact;
msec = 1000*((realtime - cls.latency + 0.02) - state->state_time);
// predict players movement
if (msec > 255)
msec = 255;
state->command.msec = msec;
CL_SetSolidEntities();
CL_SetSolidPlayers (num);
CL_PredictUsercmd (0, state, &exact, &state->command); //uses player 0's maxspeed/grav...
VectorCopy (exact.origin, state->predorigin);
}
else
VectorCopy (state->origin, state->predorigin);
}
void CL_ParseClientPersist(void)
@ -3082,6 +3128,16 @@ void CL_LinkPlayers (void)
if (pnum < cl.splitclients)
{ //this is a local player
}
else if (cl_lerp_players.ival)
{
lerpents_t *le = &cl.lerpplayers[j];
VectorCopy (le->origin, ent->origin);
VectorCopy(le->angles, ent->angles);
ent->angles[0] /= 3;
AngleVectors(ent->angles, ent->axis[0], ent->axis[1], ent->axis[2]);
VectorInverse(ent->axis[1]);
}
else if (msec <= 0 || (!predictplayers))
{
VectorCopy (state->origin, ent->origin);
@ -3287,13 +3343,14 @@ void CL_SetSolidEntities (void)
if (!cl.model_precache[state->modelindex])
continue;
if (*cl.model_precache[state->modelindex]->name == '*' || cl.model_precache[state->modelindex]->numsubmodels)
if ( cl.model_precache[state->modelindex]->hulls[1].firstclipnode
|| cl.model_precache[state->modelindex]->clipbox )
if ( cl.model_precache[state->modelindex]->hulls[1].firstclipnode)
{
memset(&pmove.physents[pmove.numphysent], 0, sizeof(physent_t));
pmove.physents[pmove.numphysent].model = cl.model_precache[state->modelindex];
VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin);
VectorCopy (state->angles, pmove.physents[pmove.numphysent].angles);
// VectorCopy (cl.lerpents[state->number].origin, pmove.physents[pmove.numphysent].origin);
// VectorCopy (cl.lerpents[state->number].angles, pmove.physents[pmove.numphysent].angles);
pmove.physents[pmove.numphysent].angles[0]*=-1;
if (++pmove.numphysent == MAX_PHYSENTS)
break;
@ -3386,8 +3443,8 @@ void CL_SetUpPlayerPrediction(qboolean dopred)
if (cl.spectator)
{
if (!Cam_DrawPlayer(0, j))
VectorCopy(pplayer->origin, cl.simorg[0]);
// if (!Cam_DrawPlayer(0, j))
// VectorCopy(pplayer->origin, cl.simorg[0]);
}
}

View File

@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "netinc.h"
#include "cl_master.h"
#include "cl_ignore.h"
#include "shader.h"
// callbacks
void CL_Sbar_Callback(struct cvar_s *var, char *oldvalue);
@ -45,6 +46,7 @@ cvar_t cl_timeout = SCVAR("cl_timeout", "60");
cvar_t cl_shownet = SCVAR("cl_shownet","0"); // can be 0, 1, or 2
cvar_t cl_pure = CVARD("cl_pure", "0", "If enabled, the filesystem will be restricted to allow only the content of the current server.");
cvar_t cl_sbar = CVARFC("cl_sbar", "0", CVAR_ARCHIVE, CL_Sbar_Callback);
cvar_t cl_hudswap = CVARF("cl_hudswap", "0", CVAR_ARCHIVE);
cvar_t cl_maxfps = CVARF("cl_maxfps", "500", CVAR_ARCHIVE);
@ -52,15 +54,14 @@ cvar_t cl_idlefps = CVARF("cl_idlefps", "0", CVAR_ARCHIVE);
cvar_t cl_yieldcpu = CVARF("cl_yieldcpu", "0", CVAR_ARCHIVE);
cvar_t cl_nopext = CVARF("cl_nopext", "0", CVAR_ARCHIVE);
cvar_t cl_pext_mask = CVAR("cl_pext_mask", "0xffffffff");
cvar_t cl_nolerp = CVAR("cl_nolerp", "2");
cvar_t cl_nolerp_netquake = CVAR("cl_nolerp_netquake", "0");
cvar_t cl_nolerp = CVARD("cl_nolerp", "0", "Disables interpolation. If set, missiles/monsters will be smoother, but they may be more laggy. Does not affect players. A value of 2 means 'interpolate only in single-player/coop'.");
cvar_t cl_nolerp_netquake = CVARD("cl_nolerp_netquake", "0", "Disables interpolation when connected to an NQ server. Does affect players, even the local player. You probably don't want to set this.");
cvar_t hud_tracking_show = CVAR("hud_tracking_show", "1");
cvar_t cl_defaultport = CVARAF("cl_defaultport", STRINGIFY(PORT_QWSERVER), "port", 0);
cvar_t cfg_save_name = CVARF("cfg_save_name", "fte", CVAR_ARCHIVE);
cvar_t cl_packagedownloads = CVAR("cl_packagedownloads", "1");
cvar_t cl_splitscreen = CVAR("cl_splitscreen", "0");
cvar_t lookspring = CVARF("lookspring","0", CVAR_ARCHIVE);
@ -74,9 +75,10 @@ cvar_t m_yaw = CVARF("m_yaw","0.022", CVAR_ARCHIVE);
cvar_t m_forward = CVARF("m_forward","1", CVAR_ARCHIVE);
cvar_t m_side = CVARF("m_side","0.8", CVAR_ARCHIVE);
cvar_t cl_predict_players = CVAR("cl_predict_players", "1");
cvar_t cl_lerp_players = CVARD("cl_lerp_players", "1", "Set this to make other players smoother, though it may increase effective latency. Affects only QuakeWorld.");
cvar_t cl_predict_players = CVARD("cl_predict_players", "1", "Clear this cvar to see ents exactly how they are on the server.");
cvar_t cl_solid_players = CVAR("cl_solid_players", "1");
cvar_t cl_noblink = CVAR("cl_noblink", "0");
cvar_t cl_noblink = CVARD("cl_noblink", "0", "Disable the ^^b text blinking feature.");
cvar_t cl_servername = CVAR("cl_servername", "none");
cvar_t cl_serveraddress = CVAR("cl_serveraddress", "none");
cvar_t qtvcl_forceversion1 = CVAR("qtvcl_forceversion1", "0");
@ -139,7 +141,7 @@ cvar_t cl_gunanglez = SCVAR("cl_gunanglez", "0");
cvar_t cl_download_csprogs = CVARFD("cl_download_csprogs", "1", CVAR_NOTFROMSERVER, "Download updated client gamecode if available.");
cvar_t cl_download_redirection = CVARFD("cl_download_redirection", "0", CVAR_NOTFROMSERVER, "Follow download redirection to download packages instead of individual files.");
cvar_t cl_download_mapsrc = CVARD("cl_download_mapsrc", "", "Specifies an http location prefix for map downloads. EG: \"http://bigfoot.morphos-team.net/misc/quakemaps/\"");
cvar_t cl_download_packages = CVARFD("cl_download_packages", "1", CVAR_NOTFROMSERVER, "0=Do not download packages simply because the server is using them. 1=Do download, but don't use them by default. 2=Do download and install permanently (use with caution!)");
cvar_t cl_download_packages = CVARFD("cl_download_packages", "1", CVAR_NOTFROMSERVER, "0=Do not download packages simply because the server is using them. 1=Download and load packages as needed (does not affect games which do not use this package). 2=Do download and install permanently (use with caution!)");
cvar_t requiredownloads = CVARFD("requiredownloads","1", CVAR_ARCHIVE, "0=join the game before downloads have even finished (might be laggy). 1=wait for all downloads to complete before joining.");
cvar_t cl_muzzleflash = SCVAR("cl_muzzleflash", "1");
@ -712,6 +714,11 @@ void CL_CheckForResend (void)
}
NET_AdrToString(data, sizeof(data), adr);
/*eat up the server's packets, to clear any lingering loopback packets*/
while(NET_GetPacket (NS_SERVER, 0) >= 0)
{
}
if (cls.protocol_nq == CPNQ_ID)
{
net_from = adr;
@ -1306,6 +1313,8 @@ void CL_Disconnect (void)
#endif
CL_StopUpload();
CL_FlushClientCommands();
#ifndef CLIENTONLY
if (!isDedicated)
#endif
@ -1505,6 +1514,12 @@ void CL_PakDownloads(int mode)
s = COM_Parse(s);
pname = Cmd_Argv(i);
//'*' prefix means 'referenced'. so if the server isn't using any files from it, don't bother downloading it.
if (*pname == '*')
pname++;
else
continue;
if (mode != 2)
{
/*if we already have such a file, this is a no-op*/
@ -1518,6 +1533,33 @@ void CL_PakDownloads(int mode)
}
}
void CL_CheckServerPacks(void)
{
static qboolean oldpure;
qboolean pure = cl_pure.ival || atoi(Info_ValueForKey(cl.serverinfo, "sv_pure"));
if (pure != oldpure || cl.serverpakschanged)
{
if (pure)
{
CL_PakDownloads((!cl_download_packages.ival)?1:cl_download_packages.ival);
FS_ForceToPure(cl.serverpaknames, cl.serverpakcrcs, cls.challenge);
/*when enabling pure, kill cached models/sounds/etc*/
Cache_Flush();
/*make sure cheating lamas can't use old shaders from a different srver*/
Shader_NeedReload(true);
}
else
{
CL_PakDownloads(cl_download_packages.ival);
FS_ImpurePacks(cl.serverpaknames, cl.serverpakcrcs);
}
}
oldpure = pure;
cl.serverpakschanged = false;
}
void CL_CheckServerInfo(void)
{
char *s;
@ -1661,16 +1703,7 @@ void CL_CheckServerInfo(void)
if (oldstate != cl.matchstate)
cl.matchgametime = 0;
if (atoi(Info_ValueForKey(cl.serverinfo, "sv_pure")))
{
CL_PakDownloads((!cl_packagedownloads.ival)?1:cl_packagedownloads.ival);
FS_ForceToPure(cl.serverpaknames, cl.serverpakcrcs, cls.challenge);
}
else
{
CL_PakDownloads(cl_packagedownloads.ival);
FS_ImpurePacks(cl.serverpaknames, cl.serverpakcrcs);
}
CL_CheckServerPacks();
Cvar_ForceCheatVars(cls.allow_semicheats, cls.allow_cheats);
Validation_Apply_Ruleset();
@ -2593,8 +2626,8 @@ void CLNQ_ConnectionlessPacket(void)
int ver = MSG_ReadByte();
Con_Printf("ProQuake server %i.%i\n", ver/10, ver%10);
if (ver >= 34)
cls.protocol_nq = CPNQ_PROQUAKE3_4;
// if (ver >= 34)
cls.protocol_nq = CPNQ_PROQUAKE3_4;
if (MSG_ReadByte() == 1)
{
//its a 'pure' server.
@ -3100,6 +3133,7 @@ void CL_Init (void)
Cvar_Register (&rcon_password, cl_controlgroup);
Cvar_Register (&rcon_address, cl_controlgroup);
Cvar_Register (&cl_lerp_players, cl_controlgroup);
Cvar_Register (&cl_predict_players, cl_predictiongroup);
Cvar_Register (&cl_solid_players, cl_predictiongroup);
@ -3132,6 +3166,7 @@ void CL_Init (void)
Cvar_Register (&cl_download_csprogs, cl_controlgroup);
Cvar_Register (&cl_download_redirection, cl_controlgroup);
Cvar_Register (&cl_download_packages, cl_controlgroup);
//
// info mirrors
@ -3168,7 +3203,6 @@ void CL_Init (void)
Cvar_Register (&host_mapname, "Scripting");
Cvar_Register (&cl_packagedownloads, cl_controlgroup);
#ifndef SERVERONLY
Cvar_Register (&cl_loopbackprotocol, cl_controlgroup);
#endif
@ -3943,7 +3977,7 @@ Con_TPrintf (TL_NL);
realtime+=1;
Cbuf_Execute (); //server may have been waiting for the renderer
if (!cls.demoinfile && !*cls.servername)
if (!cls.demoinfile && !*cls.servername && !Media_Playing())
{
#ifndef CLIENTONLY
if (!sv.state)

View File

@ -1145,7 +1145,8 @@ int CL_LoadModels(int stage, qboolean dontactuallyload)
}
else
{
CL_SendClientCommand(true, "disablecsqc");
if (cls.fteprotocolextensions & PEXT_CSQC)
CL_SendClientCommand(true, "disablecsqc");
}
endstage();
}
@ -1410,7 +1411,7 @@ void CL_SendDownloadReq(sizebuf_t *msg)
lasttime = fabs(realtime - lasttime);
if (lasttime > 1)
lasttime = 1;
p = lasttime * drate.ival;
p = lasttime * drate.ival / 1000;
if (p > 90)
p = 90;
}
@ -3952,9 +3953,6 @@ static void CL_SetStat_Internal (int pnum, int stat, int value)
cl.item_gettime[pnum][j] = cl.time;
}
if (stat == STAT_VIEWHEIGHT && cls.z_ext & Z_EXT_VIEWHEIGHT)
cl.viewheight[pnum] = value;
if (stat == STAT_WEAPON)
{
if (cl.stats[pnum][stat] != value)
@ -4016,6 +4014,9 @@ void CL_SetStatFloat (int pnum, int stat, float value)
}
else
cl.statsf[pnum][stat] = value;
if (stat == STAT_VIEWHEIGHT && cls.z_ext & Z_EXT_VIEWHEIGHT)
cl.viewheight[pnum] = value;
}
void CL_SetStatString (int pnum, int stat, char *value)
{
@ -4801,14 +4802,14 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n
}
else if (!strncmp(stufftext, "//paknames ", 11))
{
Q_strncpyz(cl.serverpaknames, stufftext+11, sizeof(cl.serverpaknames));
Q_strncatz(cl.serverpaknames, stufftext+11, sizeof(cl.serverpaknames));
cl.serverpakschanged = true;
}
else if (!strncmp(stufftext, "//paks ", 7))
{
Q_strncpyz(cl.serverpakcrcs, stufftext+7, sizeof(cl.serverpakcrcs));
Q_strncatz(cl.serverpakcrcs, stufftext+7, sizeof(cl.serverpakcrcs));
cl.serverpakschanged = true;
CL_CheckServerInfo();
CL_CheckServerPacks();
}
else if (!strncmp(stufftext, "//vwep ", 7))
{
@ -5305,7 +5306,7 @@ void CLQW_ParseServerMessage (void)
if (!cl.intermission)
TP_ExecTrigger ("f_mapend");
cl.intermission = 1;
cl.completed_time = cl.servertime;
cl.completed_time = cl.gametime;
vid.recalc_refdef = true; // go to full screen
for (i=0 ; i<3 ; i++)
cl.simorg[0][i] = MSG_ReadCoord ();
@ -5320,7 +5321,7 @@ void CLQW_ParseServerMessage (void)
case svc_finale:
cl.intermission = 2;
cl.completed_time = cl.servertime;
cl.completed_time = cl.gametime;
vid.recalc_refdef = true; // go to full screen
SCR_CenterPrint (destsplit, MSG_ReadString (), false);
break;
@ -5712,6 +5713,7 @@ void CLNQ_ParseProQuakeMessage (char *s)
break;
case pqc_ping_times:
cl.last_ping_request = realtime;
while ((ping = MSG_ReadShortPQ(&s)))
{
if ((ping / 4096) >= MAX_CLIENTS)
@ -6112,20 +6114,20 @@ void CLNQ_ParseServerMessage (void)
if (!cl.intermission)
TP_ExecTrigger ("f_mapend");
cl.intermission = 1;
cl.completed_time = cl.servertime;
cl.completed_time = cl.gametime;
vid.recalc_refdef = true; // go to full screen
break;
case svc_finale:
cl.intermission = 2;
cl.completed_time = cl.servertime;
cl.completed_time = cl.gametime;
vid.recalc_refdef = true; // go to full screen
SCR_CenterPrint (0, MSG_ReadString (), false);
break;
case svc_cutscene:
cl.intermission = 3;
cl.completed_time = cl.servertime;
cl.completed_time = cl.gametime;
vid.recalc_refdef = true; // go to full screen
SCR_CenterPrint (0, MSG_ReadString (), false);
break;

View File

@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "winquake.h"
cvar_t cl_nopred = SCVAR("cl_nopred","0");
extern cvar_t cl_lerp_players;
cvar_t cl_pushlatency = SCVAR("pushlatency","-999");
extern frame_t *view_frame;
@ -652,7 +653,6 @@ short LerpAngles16(short to, short from, float frac)
void CL_CalcClientTime(void)
{
{
float want;
float oldst = realtime;
if (cls.protocol == CP_QUAKEWORLD && cls.demoplayback == DPB_MVD)
@ -665,30 +665,42 @@ void CL_CalcClientTime(void)
}
else
{
float min, max;
oldst = cl.servertime;
max = cl.gametime;// - 5;
min = cl.oldgametime;// - 5;
cl.servertime += host_frametime;
if (cl.servertime > cl.gametime)
if (cl.servertime > max)
{
cl.servertime = cl.gametime;
// Con_Printf("clamped to new time\n");
}
if (cl.servertime < cl.oldgametime)
{
if (cl.servertime < cl.oldgametime-0.5)
if (cl.servertime > cl.gametime)
{
cl.servertime = cl.oldgametime-0.5;
cl.servertime = cl.gametime;
// Con_Printf("clamped to new time\n");
}
else
{
cl.servertime -= 0.02*(cl.gametime - cl.servertime);
}
}
if (cl.servertime < min)
{
if (cl.servertime < min-0.5)
{
cl.servertime = min-0.5;
// Con_Printf("clamped to old time\n");
}
else if (cl.servertime < cl.oldgametime-0.3)
else if (cl.servertime < min-0.3)
{
cl.servertime += 0.02*(cl.oldgametime - cl.servertime);
cl.servertime += 0.02*(min - cl.servertime);
// Con_Printf("running really slow\n");
}
else
{
cl.servertime += 0.01*(cl.oldgametime - cl.servertime);
cl.servertime += 0.01*(min - cl.servertime);
// Con_Printf("running slow\n");
}
}
@ -862,6 +874,14 @@ fixedorg:
if (Cam_TrackNum(pnum)>=0 && CL_MayLerp())
{
float f;
if (cl_lerp_players.ival)
{
lerpents_t *le = &cl.lerpplayers[spec_track[pnum]];
org = le->origin;
vel = vec3_origin;
VectorCopy(le->angles, cl.simangles[pnum]);
goto fixedorg;
}
to = &cl.frames[cl.ackedinputsequence & UPDATE_MASK];
from = &cl.frames[cl.oldvalidsequence & UPDATE_MASK];
@ -878,7 +898,7 @@ fixedorg:
// f = 1-f;
// calculate origin
// calculate origin
for (i=0 ; i<3 ; i++)
{
lrp[i] = to->playerstate[cl.playernum[pnum]].origin[i] +

View File

@ -47,6 +47,7 @@ typedef struct
usercmd_t command; // last command for prediction
vec3_t origin;
vec3_t predorigin; // pre-predicted pos
vec3_t viewangles; // only for demos, not from server
vec3_t velocity;
int weaponframe;
@ -247,6 +248,7 @@ typedef struct
#define LFLAG_NOSHADOWS (1<<8)
#define LFLAG_SHADOWMAP (1<<9)
#define LFLAG_CREPUSCULAR (1<<10)
#define LFLAG_DYNAMIC (LFLAG_LIGHTMAP | LFLAG_FLASHBLEND | LFLAG_NORMALMODE | LFLAG_REALTIMEMODE)
@ -643,6 +645,9 @@ typedef struct
float predicted_step_time;
float predicted_step;
packet_entities_t *currentpackentities;
float currentpacktime;
// localized movement vars
float entgravity[MAX_SPLITS];
float maxspeed[MAX_SPLITS];
@ -773,6 +778,7 @@ void CL_ParseDelta (struct entity_state_s *from, struct entity_state_s *to, int
void CL_Init (void);
void Host_WriteConfiguration (void);
void CL_CheckServerInfo(void);
void CL_CheckServerPacks(void);
void CL_EstablishConnection (char *host);
@ -997,6 +1003,7 @@ void CL_SpawnSpriteEffect(vec3_t org, vec3_t dir, struct model_s *model, int sta
void CL_SetSolidPlayers (int playernum);
void CL_SetUpPlayerPrediction(qboolean dopred);
void CL_LinkStaticEntities(void *pvs);
void CL_TransitionEntities (void); /*call at the start of the frame*/
void CL_EmitEntities (void);
void CL_ClearProjectiles (void);
void CL_ParseProjectiles (int modelindex, qboolean nails2);
@ -1237,15 +1244,20 @@ void CIN_StopCinematic (struct cinematics_s *cin);
struct cinematics_s *CIN_PlayCinematic (char *arg);
int CIN_RunCinematic (struct cinematics_s *cin, qbyte **outdata, int *outwidth, int *outheight, qbyte **outpalette);
#ifdef NOMEDIA
#define Media_Playing false
#else
/*media playing system*/
qboolean Media_PlayingFullScreen(void);
void Media_Init(void);
qboolean Media_PlayFilm(char *name);
qboolean Media_Playing(void);
typedef struct cin_s cin_t;
struct cin_s *Media_StartCin(char *name);
texid_tf Media_UpdateForShader(cin_t *cin);
void Media_ShutdownCin(cin_t *cin);
qboolean Media_FakeTrack(int i, qboolean loop);
#endif
//these accept NULL for cin to mean the current fullscreen video
void Media_Send_Command(cin_t *cin, char *command);

View File

@ -2179,6 +2179,7 @@ texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize)
int intfmt;
int pad;
unsigned int w, h;
int divsize, blocksize;
ddsheader fmtheader;
if (*(int*)buffer != *(int*)"DDS ")
@ -2199,16 +2200,22 @@ texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize)
{
intfmt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; //alpha or not? Assume yes, and let the drivers decide.
pad = 8;
divsize = 4;
blocksize = 8;
}
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT3")
{
intfmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
pad = 8;
divsize = 4;
blocksize = 16;
}
else if (*(int*)&fmtheader.ddpfPixelFormat.dwFourCC == *(int*)"DXT5")
{
intfmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
pad = 8;
divsize = 4;
blocksize = 16;
}
else
return r_nulltex;
@ -2220,22 +2227,20 @@ texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize)
GL_MTBind(0, GL_TEXTURE_2D, texnum);
datasize = fmtheader.dwPitchOrLinearSize;
w = fmtheader.dwWidth;
h = fmtheader.dwHeight;
for (mipnum = 0; mipnum < nummips; mipnum++)
{
// (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
if (datasize < pad)
datasize = pad;
w = fmtheader.dwWidth>>mipnum;
if (w < 1)
w = 1;
h = fmtheader.dwHeight>>mipnum;
if (h < 1)
h = 1;
datasize = max(divsize, w)/divsize * max(divsize, h)/divsize * blocksize;
qglCompressedTexImage2DARB(GL_TEXTURE_2D, mipnum, intfmt, w, h, 0, datasize, buffer);
if (qglGetError())
Con_Printf("Incompatible dds file %s (mip %i)\n", iname, mipnum);
buffer += datasize;
datasize/=4;
w = (w+1)>>1;
h = (h+1)>>1;
}
if (qglGetError())
Con_Printf("Incompatible dds file %s\n", iname);

View File

@ -1674,6 +1674,13 @@ qboolean Media_DecodeFrame(cin_t *cin, qboolean nosound)
return cin->decodeframe(cin, nosound);
}
qboolean Media_Playing(void)
{
if (videoshader)
return true;
return false;
}
qboolean Media_PlayFilm(char *name)
{
cin_t *cin;

View File

@ -345,6 +345,7 @@ void M_Menu_Particles_f (void)
"High FPS",
"Fancy",
"Fancy+LG",
"Snazzy",
"Bare bones",
NULL
};
@ -354,6 +355,7 @@ void M_Menu_Particles_f (void)
"highfps",
"spikeset",
"spikeset tsshaft",
"spikeset high tsshaft",
"minimal",
NULL
};
@ -545,6 +547,19 @@ void M_Menu_FPS_f (void)
NULL
};
static const char *fpsvalues[] = {"0", "1", "2", "3", "4", "-1", "-2", "-3", "-4", NULL};
static const char *entlerpopts[] =
{
"Enabled (always)",
"Disabled",
"Enabled (SP only)",
NULL
};
static const char *playerlerpopts[] =
{
"Disabled",
"Enabled",
NULL
};
static const char *bodyopts[] =
{
"Disabled",
@ -552,17 +567,20 @@ void M_Menu_FPS_f (void)
"All",
NULL
};
static const char *bodyvalues[] = {"0", "1", "2", NULL};
static const char *values_0_1_2[] = {"0", "1", "2", NULL};
static const char *values_0_1[] = {"0", "1", NULL};
menu_t *menu;
fpsmenuinfo_t *info;
extern cvar_t v_contentblend, show_fps, cl_r2g, cl_gibfilter, cl_expsprite, cl_deadbodyfilter;
extern cvar_t v_contentblend, show_fps, cl_r2g, cl_gibfilter, cl_expsprite, cl_deadbodyfilter, cl_lerp_players, cl_nolerp;
int y;
menu = M_Options_Title(&y, sizeof(fpsmenuinfo_t));
info = (fpsmenuinfo_t *)menu->data;
/*lerping is here because I'm not sure where else to put it. if they care about framerate that much then they'll want to disable interpolation to get as up-to-date stuff as possible*/
{
menubulk_t bulk[] =
{
@ -572,9 +590,11 @@ void M_Menu_FPS_f (void)
MB_CMD("Apply", M_PresetApply, "Applies selected preset."),
MB_SPACING(4),
MB_COMBOCVAR("Show FPS", show_fps, fpsopts, fpsvalues, "Display FPS or frame millisecond values on screen. Settings except immediate are for values across 1 second."),
MB_COMBOCVAR("Player lerping", cl_lerp_players, playerlerpopts, values_0_1, "Smooth movement of other players, but will increase effective latency. Does not affect all network protocols."),
MB_COMBOCVAR("Entity lerping", cl_nolerp, entlerpopts, values_0_1_2, "Smooth movement of entities, but will increase effective latency."),
MB_CHECKBOXCVAR("Content Blend", v_contentblend, 0),
MB_CHECKBOXCVAR("Gib Filter", cl_gibfilter, 0),
MB_COMBOCVAR("Dead Body Filter", cl_deadbodyfilter, bodyopts, bodyvalues, "Selects which dead player frames to filter out in rendering. Ground frames are those of the player lying on the ground, and all frames include all used in the player dying animation."),
MB_COMBOCVAR("Dead Body Filter", cl_deadbodyfilter, bodyopts, values_0_1_2, "Selects which dead player frames to filter out in rendering. Ground frames are those of the player lying on the ground, and all frames include all used in the player dying animation."),
MB_CHECKBOXCVAR("Explosion Sprite", cl_expsprite, 0),
MB_CHECKBOXCVAR("Rockets to Grenades", cl_r2g, 0),
MB_EDITCVAR("Skybox", "r_skybox"),
@ -928,8 +948,9 @@ void M_Menu_Lighting_f (void)
MB_COMBOCVAR("Powerup Glow", r_powerupglow, powerupopts, powerupvalues, "Disables or enables the dynamic light effect for powerups. Non-self will disable the light only for the current player."),
MB_CHECKBOXCVAR("Powerup Shell", v_powerupshell, 0),
MB_SPACING(4),
MB_SLIDER("Stains", r_stains, 0, 1, 0.05, NULL),
MB_CHECKBOXCVAR("No Light Direction", r_nolightdir, 0),
MB_SLIDER("Blob Shadows", r_shadows, 0, 1, 0.05, "Small blobs underneath monsters and players, to add depth to the scene without excessive rendering."),
MB_SLIDER("Stains", r_stains, 0, 1, 0.05, "Allows discolouration of world surfaces, commonly used for blood trails."),
MB_CHECKBOXCVARTIP("No Light Direction", r_nolightdir, 0, "Disables shading calculations for uniform light levels on models from all directions."),
MB_END()
};
MC_AddBulk(menu, bulk, 16, 216, y);

View File

@ -320,7 +320,7 @@ void M_MenuS_Combos_f (void)
line = Cmd_Argv(5);
if (!*line)
{
line = Cbuf_GetNext(Cmd_ExecLevel);
line = Cbuf_GetNext(Cmd_ExecLevel, true);
if (*line != '{')
Cbuf_InsertText(line, Cmd_ExecLevel, true); //whoops. Stick the trimmed string back in to the cbuf.
else
@ -332,7 +332,7 @@ void M_MenuS_Combos_f (void)
Hunk_TempAlloc(4);
for (opt = 0; opt < sizeof(opts)/sizeof(opts[0])-2; opt++)
{
line = Cbuf_GetNext(Cmd_ExecLevel);
line = Cbuf_GetNext(Cmd_ExecLevel, true);
line = COM_Parse(line);
if (!strcmp(com_token, "}"))
break;

View File

@ -8,6 +8,7 @@ struct mesh_s;
struct batch_s;
struct entity_s;
struct dlight_s;
struct galiasbone_s;
@ -33,6 +34,7 @@ typedef struct {
float *bonestate;
int bonecount;
qboolean boneabs;
#ifdef HALFLIFEMODELS
float bonecontrols[MAX_BONE_CONTROLLERS]; //hl special bone controllers
@ -142,6 +144,7 @@ extern int Mod_TagNumForName (struct model_s *model, char *name);
int Mod_GetNumBones(struct model_s *model, qboolean allowtags);
int Mod_GetBoneRelations(struct model_s *model, int firstbone, int lastbone, framestate_t *fstate, float *result);
int Mod_GetBoneParent(struct model_s *model, int bonenum);
struct galiasbone_s *Mod_GetBoneInfo(struct model_s *model);
char *Mod_GetBoneName(struct model_s *model, int bonenum);
void Draw_FunString(int x, int y, const void *str);
@ -213,6 +216,7 @@ typedef enum backendmode_e
BEM_DEPTHONLY, //just a quick depth pass. textures used only for alpha test (shadowmaps).
BEM_STENCIL, //used for drawing shadow volumes to the stencil buffer.
BEM_DEPTHDARK, //a quick depth pass. textures used only for alpha test. additive textures still shown as normal.
BEM_CREPUSCULAR, //sky is special, everything else completely black
BEM_DEPTHNORM, //all opaque stuff drawn using 'depthnorm' shader
BEM_LIGHT, //we have a valid light
BEM_SMAPLIGHTSPOT, //we have a spot light using a shadowmap
@ -324,5 +328,5 @@ typedef struct rendererinfo_s {
#define BE_SubmitBatch rf->BE_SubmitBatch
#define BE_DrawMesh_List rf->BE_DrawMesh_List
#define BE_DrawMesh_Single rf->BE_DrawMesh_Single
#define BE_SubimtMeshes rf->BE_SubimtMeshes
#define BE_SubmitMeshes rf->BE_SubmitMeshes
#define BE_DrawWorld rf->BE_DrawWorld

View File

@ -305,6 +305,7 @@ static void PClassic_DrawParticles(void)
if (!active_particles)
{
oldtime = cl.time;
return;
}

View File

@ -670,7 +670,7 @@ static void P_ParticleEffect_f(void)
return;
}
buf = Cbuf_GetNext(Cmd_ExecLevel);
buf = Cbuf_GetNext(Cmd_ExecLevel, false);
while (*buf && *buf <= ' ')
buf++; //no whitespace please.
if (*buf != '{')
@ -798,7 +798,7 @@ static void P_ParticleEffect_f(void)
while(1)
{
buf = Cbuf_GetNext(Cmd_ExecLevel);
buf = Cbuf_GetNext(Cmd_ExecLevel, false);
if (!*buf)
{
Con_Printf("Unexpected end of buffer with effect %s\n", ptype->name);
@ -816,7 +816,47 @@ static void P_ParticleEffect_f(void)
// TODO: switch this mess to some sort of binary tree to increase
// parse speed
if (!strcmp(var, "texture"))
if (!strcmp(var, "shader"))
{
Q_strncpyz(ptype->texname, ptype->name, sizeof(ptype->texname));
buf = Cbuf_GetNext(Cmd_ExecLevel, true);
while (*buf && *buf <= ' ')
buf++; //no leading whitespace please.
if (*buf == '{')
{
int nest = 1;
char *str = BZ_Malloc(2);
int slen = 2;
str[0] = '{';
str[1] = '\n';
str[2] = 0;
while(nest)
{
buf = Cbuf_GetNext(Cmd_ExecLevel, true);
if (!*buf)
{
Con_Printf("Unexpected end of buffer with effect %s\n", ptype->name);
break;
}
while (*buf && *buf <= ' ')
buf++; //no leading whitespace please.
if (*buf == '}')
--nest;
if (*buf == '{')
nest++;
str = BZ_Realloc(str, slen + strlen(buf) + 2);
strcpy(str + slen, buf);
slen += strlen(str + slen);
str[slen++] = '\n';
}
str[slen] = 0;
R_RegisterShader(ptype->texname, str);
BZ_Free(str);
}
else
Cbuf_InsertText(buf, Cmd_ExecLevel, true);
}
else if (!strcmp(var, "texture"))
Q_strncpyz(ptype->texname, value, sizeof(ptype->texname));
else if (!strcmp(var, "tcoords"))
{

View File

@ -83,10 +83,6 @@ extern cvar_t dpcompat_stats;
cvar_t dpcompat_corruptglobals = CVAR("dpcompat_corruptglobals", "0");
#define MASK_DELTA 1
#define MASK_STDVIEWMODEL 2
// standard effect cvars/sounds
extern cvar_t r_explosionlight;
extern sfx_t *cl_sfx_wizhit;
@ -98,59 +94,6 @@ extern sfx_t *cl_sfx_ric3;
extern sfx_t *cl_sfx_r_exp3;
//shared constants
typedef enum
{
VF_MIN = 1,
VF_MIN_X = 2,
VF_MIN_Y = 3,
VF_SIZE = 4,
VF_SIZE_X = 5,
VF_SIZE_Y = 6,
VF_VIEWPORT = 7,
VF_FOV = 8,
VF_FOVX = 9,
VF_FOVY = 10,
VF_ORIGIN = 11,
VF_ORIGIN_X = 12,
VF_ORIGIN_Y = 13,
VF_ORIGIN_Z = 14,
VF_ANGLES = 15,
VF_ANGLES_X = 16,
VF_ANGLES_Y = 17,
VF_ANGLES_Z = 18,
VF_DRAWWORLD = 19,
VF_ENGINESBAR = 20,
VF_DRAWCROSSHAIR = 21,
VF_CARTESIAN_ANGLES = 22,
//this is a DP-compatibility hack.
VF_CL_VIEWANGLES_V = 33,
VF_CL_VIEWANGLES_X = 34,
VF_CL_VIEWANGLES_Y = 35,
VF_CL_VIEWANGLES_Z = 36,
//33-36 used by DP...
VF_PERSPECTIVE = 200,
//201 used by DP... WTF? CLEARSCREEN
VF_LPLAYER = 202,
VF_AFOV = 203, //aproximate fov (match what the engine would normally use for the fov cvar). p0=fov, p1=zoom
} viewflags;
/*FIXME: this should be changed*/
#define CSQC_API_VERSION 1.0f
#define CSQCRF_VIEWMODEL 1 //Not drawn in mirrors
#define CSQCRF_EXTERNALMODEL 2 //drawn ONLY in mirrors
#define CSQCRF_DEPTHHACK 4 //fun depthhack
#define CSQCRF_ADDITIVE 8 //add instead of blend
#define CSQCRF_USEAXIS 16 //use v_forward/v_right/v_up as an axis/matrix - predraw is needed to use this properly
#define CSQCRF_NOSHADOW 32 //don't cast shadows upon other entities (can still be self shadowing, if the engine wishes, and not additive)
#define CSQCRF_FRAMETIMESARESTARTTIMES 64 //EXT_CSQC_1: frame times should be read as (time-frametime).
#define CSQCRF_NOAUTOADD 128 //EXT_CSQC_1: don't automatically add after predraw was called
//If I do it like this, I'll never forget to register something...
#define csqcglobals \
globalfunction(init_function, "CSQC_Init"); \
@ -202,8 +145,7 @@ typedef enum
globalfloat(clientcommandframe, "clientcommandframe"); /*float the next frame that will be sent*/ \
globalfloat(servercommandframe, "servercommandframe"); /*float the most recent frame received from the server*/ \
\
globalfloat(player_tracknum, "player_trackentnum"); /*float the player number of the player being tracked*/ \
globalfloat(player_localentnum, "player_localentnum"); /*float the entity number of the local player*/ \
globalfloat(player_localentnum, "player_localentnum"); /*float the entity number the local player is looking out from*/ \
globalfloat(player_localnum, "player_localnum"); /*float the player number of the local player*/ \
globalfloat(intermission, "intermission"); /*float set when the client receives svc_intermission*/ \
globalvector(view_angles, "view_angles"); /*float set to the view angles at the start of each new frame (EXT_CSQC_1)*/ \
@ -247,10 +189,6 @@ static csqcglobals_t csqcg;
static void CSQC_ChangeLocalPlayer(int lplayernum)
{
csqc_lplayernum = lplayernum;
if (csqcg.player_tracknum)
{
*csqcg.player_tracknum = Cam_TrackNum(csqc_lplayernum);
}
if (csqcg.player_localentnum)
{
if (cl.viewentity[lplayernum])
@ -334,57 +272,29 @@ static void QCBUILTIN PF_cs_gettime (progfuncs_t *prinst, struct globalvars_s *p
switch(timer)
{
default:
case 0:
G_FLOAT(OFS_RETURN) = realtime;
break;
case 1:
G_FLOAT(OFS_RETURN) = Sys_DoubleTime();
break;
case 5:
G_FLOAT(OFS_RETURN) = cl.time;
break;
}
}
//this is the list for all the csqc fields.
//(the #define is so the list always matches the ones pulled out)
#define csqcextfields \
comfieldfloat(entnum); \
comfieldfloat(frame2); /*EXT_CSQC_1*/\
comfieldfloat(frame1time); /*EXT_CSQC_1*/\
comfieldfloat(frame2time); /*EXT_CSQC_1*/\
comfieldfloat(lerpfrac); /*EXT_CSQC_1*/\
comfieldfloat(renderflags);\
comfieldfloat(forceshader);/*FTE_CSQC_SHADERS*/\
\
comfieldfloat(baseframe); /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(baseframe2); /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(baseframe1time); /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(baseframe2time); /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(baselerpfrac); /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(basebone); /*FTE_CSQC_BASEFRAME*/\
\
comfieldfloat(bonecontrol1); /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(bonecontrol2); /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(bonecontrol3); /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(bonecontrol4); /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(bonecontrol5); /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(subblendfrac); /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(basesubblendfrac); /*FTE_CSQC_HALFLIFE_MODELS+FTE_CSQC_BASEFRAME*/\
\
comfieldfloat(skeletonindex); /*FTE_CSQC_SKELETONOBJECTS*/\
\
comfieldfloat(drawmask); /*So that the qc can specify all rockets at once or all bannanas at once*/ \
comfieldfunction(predraw); /*If present, is called just before it's drawn.*/ \
comfieldvector(glowmod); \
\
comfieldfloat(ideal_pitch);\
comfieldfloat(pitch_speed);\
//note: doesn't even have to match the clprogs.dat :)
typedef struct {
#define comfieldfloat(ssqcname,sharedname,csqcname) float csqcname
#define comfieldvector(ssqcname,sharedname,csqcname) vec3_t csqcname
#define comfieldentity(ssqcname,sharedname,csqcname) int csqcname
#define comfieldstring(ssqcname,sharedname,csqcname) string_t csqcname
#define comfieldfunction(ssqcname,sharedname,csqcname) func_t csqcname
#define comfieldfloat(csqcname) float csqcname;
#define comfieldvector(csqcname) vec3_t csqcname;
#define comfieldentity(csqcname) int csqcname;
#define comfieldstring(csqcname) string_t csqcname;
#define comfieldfunction(csqcname, typestr) func_t csqcname;
comqcfields
#undef comfieldfloat
#undef comfieldvector
@ -397,11 +307,11 @@ comqcfields
typedef struct {
#endif
#define comfieldfloat(name) float name
#define comfieldvector(name) vec3_t name
#define comfieldentity(name) int name
#define comfieldstring(name) string_t name
#define comfieldfunction(name) func_t name
#define comfieldfloat(name) float name;
#define comfieldvector(name) vec3_t name;
#define comfieldentity(name) int name;
#define comfieldstring(name) string_t name;
#define comfieldfunction(name, typestr) func_t name;
comextqcfields
csqcextfields
#undef comfieldfloat
@ -447,11 +357,11 @@ typedef struct csqcedict_s
static void CSQC_InitFields(void)
{ //CHANGING THIS FUNCTION REQUIRES CHANGES TO csqcentvars_t
#define comfieldfloat(ssqcname,wname,name) PR_RegisterFieldVar(csqcprogs, ev_float, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldvector(ssqcname,wname,name) PR_RegisterFieldVar(csqcprogs, ev_vector, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldentity(ssqcname,wname,name) PR_RegisterFieldVar(csqcprogs, ev_entity, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldstring(ssqcname,wname,name) PR_RegisterFieldVar(csqcprogs, ev_string, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldfunction(ssqcname,wname,name) PR_RegisterFieldVar(csqcprogs, ev_function, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldfloat(name) PR_RegisterFieldVar(csqcprogs, ev_float, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
#define comfieldvector(name) PR_RegisterFieldVar(csqcprogs, ev_vector, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
#define comfieldentity(name) PR_RegisterFieldVar(csqcprogs, ev_entity, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
#define comfieldstring(name) PR_RegisterFieldVar(csqcprogs, ev_string, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
#define comfieldfunction(name, typestr) PR_RegisterFieldVar(csqcprogs, ev_function, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
comqcfields
#undef comfieldfloat
#undef comfieldvector
@ -460,17 +370,17 @@ comqcfields
#undef comfieldfunction
#ifdef VM_Q1
#define comfieldfloat(name) PR_RegisterFieldVar(csqcprogs, ev_float, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1)
#define comfieldvector(name) PR_RegisterFieldVar(csqcprogs, ev_vector, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1)
#define comfieldentity(name) PR_RegisterFieldVar(csqcprogs, ev_entity, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1)
#define comfieldstring(name) PR_RegisterFieldVar(csqcprogs, ev_string, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1)
#define comfieldfunction(name) PR_RegisterFieldVar(csqcprogs, ev_function, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1)
#define comfieldfloat(name) PR_RegisterFieldVar(csqcprogs, ev_float, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1);
#define comfieldvector(name) PR_RegisterFieldVar(csqcprogs, ev_vector, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1);
#define comfieldentity(name) PR_RegisterFieldVar(csqcprogs, ev_entity, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1);
#define comfieldstring(name) PR_RegisterFieldVar(csqcprogs, ev_string, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1);
#define comfieldfunction(name, typestr) PR_RegisterFieldVar(csqcprogs, ev_function, #name, sizeof(csqcentvars_t) + (size_t)&((csqcextentvars_t*)0)->name, -1);
#else
#define comfieldfloat(name) PR_RegisterFieldVar(csqcprogs, ev_float, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldvector(name) PR_RegisterFieldVar(csqcprogs, ev_vector, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldentity(name) PR_RegisterFieldVar(csqcprogs, ev_entity, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldstring(name) PR_RegisterFieldVar(csqcprogs, ev_string, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldfunction(name) PR_RegisterFieldVar(csqcprogs, ev_function, #name, (size_t)&((csqcentvars_t*)0)->name, -1)
#define comfieldfloat(name) PR_RegisterFieldVar(csqcprogs, ev_float, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
#define comfieldvector(name) PR_RegisterFieldVar(csqcprogs, ev_vector, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
#define comfieldentity(name) PR_RegisterFieldVar(csqcprogs, ev_entity, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
#define comfieldstring(name) PR_RegisterFieldVar(csqcprogs, ev_string, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
#define comfieldfunction(name, typestr) PR_RegisterFieldVar(csqcprogs, ev_function, #name, (size_t)&((csqcentvars_t*)0)->name, -1);
#endif
comextqcfields
csqcextfields
@ -811,30 +721,30 @@ static void QCBUILTIN PF_R_DynamicLight_Set(progfuncs_t *prinst, struct globalva
l = cl_dlights+lno;
switch (field)
{
case 0:
case lfield_origin:
VectorCopy(G_VECTOR(OFS_PARM2), l->origin);
l->rebuildcache = true;
break;
case 1:
case lfield_colour:
VectorCopy(G_VECTOR(OFS_PARM2), l->color);
break;
case 2:
case lfield_radius:
l->radius = G_FLOAT(OFS_PARM2);
l->rebuildcache = true;
if (lno >= rtlights_max)
rtlights_max = lno+1;
break;
case 3:
case lfield_flags:
l->flags = G_FLOAT(OFS_PARM2);
l->rebuildcache = true;
break;
case 4:
case lfield_style:
l->style = G_FLOAT(OFS_PARM2);
break;
case 5:
case lfield_angles:
AngleVectors(G_VECTOR(OFS_PARM2), l->axis[0], l->axis[1], l->axis[2]);
break;
case 6:
case lfield_fov:
l->fov = G_FLOAT(OFS_PARM2);
break;
default:
@ -845,7 +755,7 @@ static void QCBUILTIN PF_R_DynamicLight_Get(progfuncs_t *prinst, struct globalva
{
dlight_t *l;
unsigned int lno = G_FLOAT(OFS_PARM0);
int field = G_FLOAT(OFS_PARM1);
enum lightfield_e field = G_FLOAT(OFS_PARM1);
if (lno >= rtlights_max)
{
if (field == -1)
@ -857,25 +767,25 @@ static void QCBUILTIN PF_R_DynamicLight_Get(progfuncs_t *prinst, struct globalva
l = cl_dlights+lno;
switch (field)
{
case 0:
case lfield_origin:
VectorCopy(l->origin, G_VECTOR(OFS_RETURN));
break;
case 1:
case lfield_colour:
VectorCopy(l->color, G_VECTOR(OFS_RETURN));
break;
case 2:
case lfield_radius:
G_FLOAT(OFS_RETURN) = l->radius;
break;
case 3:
case lfield_flags:
G_FLOAT(OFS_RETURN) = l->flags;
break;
case 4:
case lfield_style:
G_FLOAT(OFS_RETURN) = l->style;
break;
case 5:
case lfield_angles:
VectorAngles(l->axis[0], l->axis[2], G_VECTOR(OFS_RETURN));
break;
case 6:
case lfield_fov:
G_FLOAT(OFS_RETURN) = l->fov;
break;
default:
@ -952,8 +862,11 @@ static void QCBUILTIN PF_R_AddEntityMask(progfuncs_t *prinst, struct globalvars_
{
CL_LinkViewModel ();
}
CL_LinkProjectiles ();
CL_UpdateTEnts ();
if (mask & MASK_DELTA)
{
CL_LinkProjectiles ();
CL_UpdateTEnts ();
}
}
}
@ -1128,6 +1041,7 @@ static void QCBUILTIN PF_R_ClearScene (progfuncs_t *prinst, struct globalvars_s
csqc_rebuildmatricies = true;
CL_DecayLights ();
CL_TransitionEntities();
if (cl.worldmodel)
{
@ -3054,13 +2968,12 @@ static void QCBUILTIN PF_cl_te_particlesnow (progfuncs_t *prinst, struct globalv
void CSQC_RunThreads(void)
{
csqctreadstate_t *state = csqcthreads, *next;
float ctime = Sys_DoubleTime();
csqcthreads = NULL;
while(state)
{
next = state->next;
if (state->resumetime > ctime)
if (state->resumetime > cl.servertime)
{ //not time yet, reform original list.
state->next = csqcthreads;
csqcthreads = state;
@ -3450,10 +3363,15 @@ static void QCBUILTIN PF_skinforname (progfuncs_t *prinst, struct globalvars_s *
}
static void QCBUILTIN PF_shaderforname (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *str = PF_VarString(prinst, 0, pr_globals);
char *str = PR_GetStringOfs(prinst, OFS_PARM0);
char *defaultbody = PF_VarString(prinst, 1, pr_globals);
shader_t *shad;
shad = R_RegisterSkin(str, NULL);
if (*defaultbody)
shad = R_RegisterShader(str, defaultbody);
else
shad = R_RegisterSkin(str, NULL);
if (shad)
G_FLOAT(OFS_RETURN) = shad-r_shaders + 1;
else
@ -4119,7 +4037,7 @@ static struct {
{"remove", PF_cs_remove, 15}, // #15 void(entity e) remove (QUAKE)
{"traceline", PF_cs_traceline, 16}, // #16 void(vector v1, vector v2, float nomonst, entity forent) traceline (QUAKE)
{"checkclient", PF_NoCSQC, 17}, // #17 entity() checkclient (QUAKE) (don't support)
{"findstring", PF_FindString, 18}, // #18 entity(entity start, .string fld, string match) findstring (QUAKE)
{"find", PF_FindString, 18}, // #18 entity(entity start, .string fld, string match) findstring (QUAKE)
{"precache_sound", PF_cs_PrecacheSound, 19}, // #19 void(string str) precache_sound (QUAKE)
//20
{"precache_model", PF_cs_PrecacheModel, 20}, // #20 void(string str) precache_model (QUAKE)
@ -4186,7 +4104,7 @@ static struct {
{"centerprint", PF_NoCSQC, 73}, // #73 void(entity ent, string text) centerprint (QUAKE) (don't support - cprint is supported instead)
{"ambientsound", PF_cl_ambientsound, 74}, // #74 void (vector pos, string samp, float vol, float atten) ambientsound (QUAKE)
{"precache_model2", PF_cs_PrecacheModel, 80}, // #75 void(string str) precache_model2 (QUAKE)
{"precache_model2", PF_cs_PrecacheModel, 75}, // #75 void(string str) precache_model2 (QUAKE)
{"precache_sound2", PF_cs_PrecacheSound, 76}, // #76 void(string str) precache_sound2 (QUAKE)
{"precache_file2", PF_NoCSQC, 77}, // #77 void(string str) precache_file2 (QUAKE)
{"setspawnparms", PF_NoCSQC, 78}, // #78 void() setspawnparms (QUAKE) (don't support)
@ -4225,8 +4143,8 @@ static struct {
{"strunzone", PF_forgetstring, 119}, // #119 void(string str) freestring (FRIK_FILE)
//200
{"precachemodel", PF_cs_PrecacheModel, 200},
{"eterncall", PF_externcall, 201},
{"getmodelindex", PF_cs_PrecacheModel, 200},
{"externcall", PF_externcall, 201},
{"addprogs", PF_cs_addprogs, 202},
{"externvalue", PF_externvalue, 203},
{"externset", PF_externset, 204},
@ -4266,13 +4184,15 @@ static struct {
//230
{"strncasecmp", PF_strncasecmp, 230}, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
{"clientstat", PF_NoCSQC, 231}, // #231 clientstat
{"runclientphys", PF_NoCSQC, 232}, // #232 runclientphys
{"isbackbuffered", PF_NoCSQC, 233}, // #233 float(entity ent) isbackbuffered
{"calltimeofday", PF_calltimeofday, 231},
{"clientstat", PF_NoCSQC, 232}, // #231 clientstat
{"runclientphys", PF_NoCSQC, 233}, // #232 runclientphys
// {"isbackbuffered", PF_NoCSQC, 234}, // #233 float(entity ent) isbackbuffered
//I messed up, 234 is meant to be isbackbuffered. luckily that's not present in csqc, but still, this is messy. Don't document this.
{"rotatevectorsbytag", PF_rotatevectorsbytag, 234}, // #234
{"rotatevectorsbyangle", PF_rotatevectorsbyangles, 235}, // #235
{"rotatevectorsbymatrix", PF_rotatevectorsbymatrix, 236}, // #236
{"rotatevectorsbyvectors", PF_rotatevectorsbymatrix, 236}, // #236
{"skinforname", PF_skinforname, 237}, // #237
{"shaderforname", PF_shaderforname, 238}, // #238
{"te_bloodqw", PF_cl_te_bloodqw, 239}, // #239 void te_bloodqw(vector org[, float count]) (FTE_TE_STANDARDEFFECTBUILTINS)
@ -4282,6 +4202,7 @@ static struct {
{"sendpacket", PF_NoCSQC, 242}, //void(string dest, string content) sendpacket = #242; (FTE_QC_SENDPACKET)
// {"bulleten", PF_bulleten, 243}, (removed builtin)
{"rotatevectorsbytag", PF_rotatevectorsbytag, 244},
#ifdef SQL
{"sqlconnect", PF_NoCSQC, 250}, // #250 float([string host], [string user], [string pass], [string defaultdb], [string driver]) sqlconnect (FTE_SQL)
@ -4318,6 +4239,8 @@ static struct {
{"terrain_edit", PF_cs_terrain_edit, 278},//void(float action, vector pos, float radius, float quant) terrain_edit = #278 (??FTE_TERRAIN_EDIT??)
{"touchtriggers", PF_cs_touchtriggers, 279},//void() touchtriggers = #279;
{"skel_ragupdate", PF_skel_ragedit, 281},// (FTE_QC_RAGDOLL)
{"skel_mmap", PF_skel_mmap, 282},// (FTE_QC_RAGDOLL)
//300
{"clearscene", PF_R_ClearScene, 300}, // #300 void() clearscene (EXT_CSQC)
{"addentities", PF_R_AddEntityMask, 301}, // #301 void(float mask) addentities (EXT_CSQC)
@ -4418,7 +4341,7 @@ static struct {
{"readfloat", PF_ReadFloat, 367}, // #367 string() readfloat (EXT_CSQC)
{"readentitynum", PF_ReadEntityNum, 368}, // #368 float() readentitynum (EXT_CSQC)
{"readserverentitystate", PF_ReadServerEntityState, 369}, // #369 void(float flags, float simtime) readserverentitystate (EXT_CSQC_1)
// {"readserverentitystate", PF_ReadServerEntityState, 369}, // #369 void(float flags, float simtime) readserverentitystate (EXT_CSQC_1)
// {"readsingleentitystate", PF_ReadSingleEntityState, 370},
{"deltalisten", PF_DeltaListen, 371}, // #371 float(string modelname, float flags) deltalisten (EXT_CSQC_1)
@ -4483,7 +4406,7 @@ static struct {
{"search_end", PF_search_end, 445}, // #445 void search_end(float handle) (DP_QC_FS_SEARCH)
{"search_getsize", PF_search_getsize, 446}, // #446 float search_getsize(float handle) (DP_QC_FS_SEARCH)
{"search_getfilename", PF_search_getfilename,447}, // #447 string search_getfilename(float handle, float num) (DP_QC_FS_SEARCH)
{"dp_cvar_string", PF_cvar_string, 448}, // #448 string(float n) cvar_string (DP_QC_CVAR_STRING)
{"cvar_string", PF_cvar_string, 448}, // #448 string(float n) cvar_string (DP_QC_CVAR_STRING)
{"findflags", PF_FindFlags, 449}, // #449 entity(entity start, .entity fld, float match) findflags (DP_QC_FINDFLAGS)
{"findchainflags", PF_cs_findchainflags, 450}, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS)
@ -4613,6 +4536,25 @@ static struct {
{NULL}
};
int PR_CSQC_BuiltinValid(char *name, int num)
{
int i;
for (i = 0; BuiltinList[i].name; i++)
{
if (BuiltinList[i].ebfsnum == num)
{
if (!strcmp(BuiltinList[i].name, name))
{
if (BuiltinList[i].bifunc == PF_NoCSQC || BuiltinList[i].bifunc == PF_Fixme)
return false;
else
return true;
}
}
}
return false;
}
static builtin_t csqc_builtin[800];
@ -5009,13 +4951,24 @@ qboolean CSQC_Init (unsigned int checksum)
PF_InitTempStrings(csqcprogs);
CSQC_FindGlobals();
csqc_world.physicstime = 0;
csqc_fakereadbyte = -1;
memset(csqcent, 0, sizeof(*csqcent)*maxcsqcentities); //clear the server->csqc entity translations.
for (i = 0; i < csqcprogs->numprogs; i++)
{
func_t f = PR_FindFunction (csqcprogs, "init", i);
if (f)
{
void *pr_globals = PR_globals(csqcprogs, PR_CURRENT);
G_PROG(OFS_PARM0) = i-1;
PR_ExecuteProgram(csqcprogs, f);
}
}
CSQC_FindGlobals();
csqcentsize = PR_InitEnts(csqcprogs, pr_csqc_maxedicts.value);
ED_Alloc(csqcprogs); //we need a world entity.
@ -5274,8 +5227,6 @@ qboolean CSQC_DrawView(void)
r_secondaryview = 0;
CL_CalcClientTime();
if (csqcg.frametime)
*csqcg.frametime = host_frametime;
@ -5571,7 +5522,6 @@ void CSQC_Input_Frame(int lplayernum, usercmd_t *cmd)
CSQC_ChangeLocalPlayer(lplayernum);
CL_CalcClientTime();
if (csqcg.svtime)
*csqcg.svtime = cl.servertime;
if (csqcg.cltime)

View File

@ -24,27 +24,33 @@ this file deals with qc builtins to apply custom skeletal blending (skeletal obj
#include "quakedef.h"
#ifdef CSQC_DAT
#define RAGDOLL
#include "pr_common.h"
#include "com_mesh.h"
#define MAX_SKEL_OBJECTS 1024
#ifdef RAGDOLL
/*this is the description of the ragdoll, it is how the doll flops around*/
typedef struct doll_s
{
char *name;
model_t *model;
struct doll_s *next;
int numbodies;
int numjoints;
struct
{
int joint;
int bone;
char *name;
} body[32];
// struct
// {
// };
struct
{
int type;
int body[2];
} joint[32];
} doll_t;
enum
@ -52,94 +58,266 @@ enum
BF_ACTIVE, /*used to avoid traces if doll is stationary*/
BF_INSOLID
};
typedef struct {
typedef struct
{
int jointo; /*multiple of 12*/
int flags;
vec3_t vel;
} body_t;
#endif
/*this is the skeletal object*/
typedef struct {
typedef struct skelobject_s
{
int inuse;
model_t *model;
world_t *world; /*be it ssqc or csqc*/
enum
{
SKOT_HBLEND,
SKOT_ABLEND,
SKOT_ARAG
SKOT_RELATIVE,
SKOT_ABSOLUTE
} type;
unsigned int numbones;
float *bonematrix;
/*
#ifdef RAGDOLL
struct skelobject_s *animsource;
unsigned int numbodies;
body_t *body;
doll_t *doll;
*/
#endif
} skelobject_t;
static doll_t *dolllist;
static skelobject_t skelobjects[MAX_SKEL_OBJECTS];
static int numskelobjectsused;
static void bonemat_fromqcvectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3])
{
out[0] = vx[0];
out[1] = -vy[0];
out[2] = vz[0];
out[3] = t[0];
out[4] = vx[1];
out[5] = -vy[1];
out[6] = vz[1];
out[7] = t[1];
out[8] = vx[2];
out[9] = -vy[2];
out[10] = vz[2];
out[11] = t[2];
}
static void bonemat_toqcvectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3])
{
vx[0] = in[0];
vx[1] = in[4];
vx[2] = in[8];
vy[0] = -in[1];
vy[1] = -in[5];
vy[2] = -in[9];
vz[0] = in[2];
vz[1] = in[6];
vz[2] = in[10];
t [0] = in[3];
t [1] = in[7];
t [2] = in[11];
}
static void bonematident_toqcvectors(float vx[3], float vy[3], float vz[3], float t[3])
{
vx[0] = 1;
vx[1] = 0;
vx[2] = 0;
vy[0] = -0;
vy[1] = -1;
vy[2] = -0;
vz[0] = 0;
vz[1] = 0;
vz[2] = 1;
t [0] = 0;
t [1] = 0;
t [2] = 0;
}
static qboolean pendingkill; /*states that there is a skel waiting to be killed*/
#if 0
doll_t *rag_loaddoll(char *fname)
#ifdef RAGDOLL
doll_t *rag_loaddoll(model_t *mod, char *fname)
{
doll_t *d;
void *fptr = NULL;
char *file;
int fsize;
int i, j;
for (d = dolllist; d; d = d->next)
{
if (!strcmp(d->name, fname))
return d;
if (d->model == mod)
if (!strcmp(d->name, fname))
return d;
}
fsize = FS_LoadFile(fname, &fptr);
if (!fptr)
return NULL;
d = malloc(sizeof(*d));
d->next = dolllist;
dolllist = d;
d->name = strdup(fname);
d->model = mod;
d->numbodies = 0;
d->numjoints = 0;
file = fptr;
while(file)
{
file = COM_Parse(file);
if (!strcmp(com_token, "body"))
{
file = COM_Parse(file);
d->body[d->numbodies].name = strdup(com_token);
file = COM_Parse(file);
d->body[d->numbodies].bone = Mod_TagNumForName(d->model, com_token);
d->numbodies++;
}
else if (!strcmp(com_token, "joint"))
{
for (i = 0; i < 2; i++)
{
file = COM_Parse(file);
d->joint[d->numjoints].body[i] = 0;
for (j = 0; j < d->numbodies; j++)
{
if (!strcmp(d->body[j].name, com_token))
{
d->joint[d->numjoints].body[i] = j;
break;
}
}
}
d->numjoints++;
}
}
FS_FreeFile(fptr);
return d;
}
void skel_integrate(progfuncs_t *prinst, skelobject_t *sko, float ft)
void skel_integrate(progfuncs_t *prinst, skelobject_t *sko, skelobject_t *skelobjsrc, float ft, float mmat[12])
{
unsigned int p;
trace_t t;
vec3_t npos, opos;
vec3_t npos, opos, wnpos, wopos;
vec3_t move;
float wantmat[12];
world_t *w = prinst->parms->user;
body_t *b;
float gravity = 800;
int bone, bno;
int boffs;
galiasbone_t *boneinfo = Mod_GetBoneInfo(sko->model);
if (!boneinfo)
return;
for (p = 0, b = sko->body; p < sko->numbodies; p++, b++)
for (bone = 0, bno = 0, b = sko->body; bone < sko->numbones; bone++)
{
/*handle gravity*/
b->vel[2] = b->vel[2] - gravity * ft / 2;
boffs = bone*12;
/*if this bone is positioned using a physical body...*/
if (bno < sko->numbodies && b->jointo == boffs)
{
if (skelobjsrc)
{
/*attempt to move to target*/
if (boneinfo[bone].parent >= 0)
{
Matrix3x4_Multiply(skelobjsrc->bonematrix+boffs, sko->bonematrix+12*boneinfo[bone].parent, wantmat);
}
else
{
Vector4Copy(skelobjsrc->bonematrix+boffs+0, wantmat+0);
Vector4Copy(skelobjsrc->bonematrix+boffs+4, wantmat+4);
Vector4Copy(skelobjsrc->bonematrix+boffs+8, wantmat+8);
}
b->vel[0] = (wantmat[3 ] - sko->bonematrix[b->jointo + 3 ])/ft;
b->vel[1] = (wantmat[7 ] - sko->bonematrix[b->jointo + 7 ])/ft;
b->vel[2] = (wantmat[11] - sko->bonematrix[b->jointo + 11])/ft;
}
else
{
/*handle gravity*/
b->vel[2] = b->vel[2] - gravity * ft / 2;
}
opos[0] = sko->bonematrix[b->jointo + 3 ];
opos[1] = sko->bonematrix[b->jointo + 7 ];
opos[2] = sko->bonematrix[b->jointo + 11];
npos[0] = opos[0] + b->vel[0]*ft;
npos[1] = opos[1] + b->vel[1]*ft;
npos[2] = opos[2] + b->vel[2]*ft;
t = World_Move(w, opos, vec3_origin, vec3_origin, npos, MOVE_NOMONSTERS, w->edicts);
sko->bonematrix[b->jointo + 3 ] = t.endpos[0];
sko->bonematrix[b->jointo + 7 ] = t.endpos[1];
sko->bonematrix[b->jointo + 11] = t.endpos[2];
VectorScale(b->vel, ft, move);
/*handle gravity again to compensate for framerate*/
b->vel[2] = b->vel[2] - gravity * ft / 2;
opos[0] = sko->bonematrix[b->jointo + 3 ];
opos[1] = sko->bonematrix[b->jointo + 7 ];
opos[2] = sko->bonematrix[b->jointo + 11];
npos[0] = opos[0] + move[0];
npos[1] = opos[1] + move[1];
npos[2] = opos[2] + move[2];
Matrix3x4_RM_Transform3(mmat, opos, wopos);
Matrix3x4_RM_Transform3(mmat, npos, wnpos);
t = World_Move(w, wopos, vec3_origin, vec3_origin, wnpos, MOVE_NOMONSTERS, w->edicts);
if (t.startsolid)
t.fraction = 1;
else if (t.fraction < 1)
{
/*clip the velocity*/
float backoff = -DotProduct (b->vel, t.plane.normal) * 1.9; /*teehee, bouncy corpses*/
VectorMA(b->vel, backoff, t.plane.normal, b->vel);
}
if (skelobjsrc)
{
VectorCopy(wantmat+0, sko->bonematrix+b->jointo+0);
VectorCopy(wantmat+4, sko->bonematrix+b->jointo+4);
VectorCopy(wantmat+8, sko->bonematrix+b->jointo+8);
}
sko->bonematrix[b->jointo + 3 ] += move[0] * t.fraction;
sko->bonematrix[b->jointo + 7 ] += move[1] * t.fraction;
sko->bonematrix[b->jointo + 11] += move[2] * t.fraction;
if (!skelobjsrc)
b->vel[2] = b->vel[2] - gravity * ft / 2;
b++;
bno++;
}
else if (skelobjsrc)
{
/*directly copy animation skeleton*/
if (boneinfo[bone].parent >= 0)
{
Matrix3x4_Multiply(skelobjsrc->bonematrix+boffs, sko->bonematrix+12*boneinfo[bone].parent, sko->bonematrix+boffs);
}
else
{
Vector4Copy(skelobjsrc->bonematrix+boffs+0, sko->bonematrix+boffs+0);
Vector4Copy(skelobjsrc->bonematrix+boffs+4, sko->bonematrix+boffs+4);
Vector4Copy(skelobjsrc->bonematrix+boffs+8, sko->bonematrix+boffs+8);
}
}
else
{
/*retain the old relation*/
/*FIXME*/
}
}
/*debugging*/
#if 0
/*draw points*/
for (p = 0, b = sko->body; p < sko->numbodies; p++, b++)
for (bone = 0; p < sko->numbones; bone++)
{
opos[0] = sko->bonematrix[b->jointo + 3 ];
opos[1] = sko->bonematrix[b->jointo + 7 ];
opos[2] = sko->bonematrix[b->jointo + 11];
P_RunParticleEffectTypeString(opos, b->vel, 1, "ragdolltest");
opos[0] = sko->bonematrix[bone*12 + 3 ];
opos[1] = sko->bonematrix[bone*12 + 7 ];
opos[2] = sko->bonematrix[bone*12 + 11];
Matrix3x4_RM_Transform3(mmat, opos, wopos);
P_RunParticleEffectTypeString(wopos, vec3_origin, 1, "ragdolltest");
}
#endif
}
#endif
@ -193,6 +371,7 @@ skelobject_t *skel_get(progfuncs_t *prinst, int skelidx, int bonecount)
skelobjects[skelidx].numbones = bonecount;
/*so bone matrix list can be mmapped some day*/
skelobjects[skelidx].bonematrix = (float*)PR_AddString(prinst, "", sizeof(float)*12*bonecount);
skelobjects[skelidx].world = prinst->parms->user;
if (skelidx <= numskelobjectsused)
{
numskelobjectsused = skelidx + 1;
@ -223,11 +402,77 @@ void skel_lookup(progfuncs_t *prinst, int skelidx, framestate_t *out)
skelobject_t *sko = skel_get(prinst, skelidx, 0);
if (sko && sko->inuse)
{
out->boneabs = sko->type;
out->bonecount = sko->numbones;
out->bonestate = sko->bonematrix;
}
}
void QCBUILTIN PF_skel_mmap(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int skelidx = G_FLOAT(OFS_PARM0);
skelobject_t *sko = skel_get(prinst, skelidx, 0);
if (!sko || sko->world != prinst->parms->user)
G_INT(OFS_RETURN) = 0;
else
G_INT(OFS_RETURN) = PR_SetString(prinst, (void*)sko->bonematrix);
}
void QCBUILTIN PF_skel_ragedit(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
#ifdef RAGDOLL
int skelidx = G_FLOAT(OFS_PARM0);
char *skelname = PR_GetStringOfs(prinst, OFS_PARM1);
int parentskel = G_FLOAT(OFS_PARM2);
float *entorg = G_VECTOR(OFS_PARM3);
float *forward = G_VECTOR(OFS_PARM4);
float *right = G_VECTOR(OFS_PARM5);
float *up = G_VECTOR(OFS_PARM6);
skelobject_t *sko, *psko;
doll_t *doll;
int i;
float emat[12];
bonemat_fromqcvectors(emat, forward, right, up, entorg);
G_FLOAT(OFS_RETURN) = 0;
sko = skel_get(prinst, skelidx, 0);
if (!sko)
return;
if (*skelname)
{
doll = rag_loaddoll(sko->model, skelname);
if (!doll)
return;
}
else
{
/*no doll name makes it revert to a normal skeleton*/
sko->doll = NULL;
G_FLOAT(OFS_RETURN) = 1;
return;
}
if (sko->doll != doll)
{
sko->doll = doll;
free(sko->body);
sko->numbodies = doll->numbodies;
sko->body = malloc(sko->numbodies * sizeof(*sko->body));
memset(sko->body, 0, sko->numbodies * sizeof(*sko->body));
for (i = 0; i < sko->numbodies; i++)
sko->body[i].jointo = doll->body[i].bone * 12;
}
psko = skel_get(prinst, parentskel, 0);
skel_integrate(prinst, sko, psko, host_frametime, emat);
G_FLOAT(OFS_RETURN) = 1;
#endif
}
//float(float modelindex) skel_create (FTE_CSQC_SKELETONOBJECTS)
void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -238,14 +483,9 @@ void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_glob
model_t *model;
int midx;
int type;
char *afname;
midx = G_FLOAT(OFS_PARM0);
if (*prinst->callargc > 1)
afname = PR_GetStringOfs(prinst, OFS_PARM1);
else
afname = "";
type = (*prinst->callargc > 1)?G_FLOAT(OFS_PARM1):SKOT_RELATIVE;
//default to failure
G_FLOAT(OFS_RETURN) = 0;
@ -254,8 +494,7 @@ void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_glob
if (!model)
return; //no model set, can't get a skeleton
type = SKOT_HBLEND;
numbones = Mod_GetNumBones(model, type != SKOT_HBLEND);
numbones = Mod_GetNumBones(model, type != SKOT_RELATIVE);
if (!numbones)
{
// isabs = true;
@ -437,53 +676,6 @@ void QCBUILTIN PF_skel_find_bone (progfuncs_t *prinst, struct globalvars_s *pr_g
G_FLOAT(OFS_RETURN) = Mod_TagNumForName(skelobj->model, bname);
}
static void bonemat_fromqcvectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3])
{
out[0] = vx[0];
out[1] = -vy[0];
out[2] = vz[0];
out[3] = t[0];
out[4] = vx[1];
out[5] = -vy[1];
out[6] = vz[1];
out[7] = t[1];
out[8] = vx[2];
out[9] = -vy[2];
out[10] = vz[2];
out[11] = t[2];
}
static void bonemat_toqcvectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3])
{
vx[0] = in[0];
vx[1] = in[4];
vx[2] = in[8];
vy[0] = -in[1];
vy[1] = -in[5];
vy[2] = -in[9];
vz[0] = in[2];
vz[1] = in[6];
vz[2] = in[10];
t [0] = in[3];
t [1] = in[7];
t [2] = in[11];
}
static void bonematident_toqcvectors(float vx[3], float vy[3], float vz[3], float t[3])
{
vx[0] = 1;
vx[1] = 0;
vx[2] = 0;
vy[0] = -0;
vy[1] = -1;
vy[2] = -0;
vz[0] = 0;
vz[1] = 0;
vz[2] = 1;
t [0] = 0;
t [1] = 0;
t [2] = 0;
}
//vector(float skel, float bonenum) skel_get_bonerel (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc)
void QCBUILTIN PF_skel_get_bonerel (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -493,10 +685,16 @@ void QCBUILTIN PF_skel_get_bonerel (progfuncs_t *prinst, struct globalvars_s *pr
skelobject_t *skelobj = skel_get(prinst, skelidx, 0);
if (!skelobj || (unsigned int)boneidx >= skelobj->numbones)
bonematident_toqcvectors(w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN));
else if (skelobj->type!=SKOT_HBLEND)
else if (skelobj->type!=SKOT_RELATIVE)
{
//FIXME
bonematident_toqcvectors(w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN));
float tmp[12];
float invparent[12];
int parent;
/*invert the parent, multiply that against the child, we now know the transform required to go from parent to child. woo.*/
parent = Mod_GetBoneParent(skelobj->model, boneidx+1)-1;
Matrix3x4_Invert(skelobj->bonematrix+12*parent, invparent);
Matrix3x4_Multiply(invparent, skelobj->bonematrix+12*boneidx, tmp);
bonemat_toqcvectors(tmp, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN));
}
else
bonemat_toqcvectors(skelobj->bonematrix+12*boneidx, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN));
@ -514,7 +712,7 @@ void QCBUILTIN PF_skel_get_boneabs (progfuncs_t *prinst, struct globalvars_s *pr
if (!skelobj || (unsigned int)boneidx >= skelobj->numbones)
bonematident_toqcvectors(w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN));
else if (skelobj->type != SKOT_HBLEND)
else if (skelobj->type != SKOT_RELATIVE)
{
//can just copy it out
bonemat_toqcvectors(skelobj->bonematrix + boneidx*12, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN));
@ -620,13 +818,19 @@ void QCBUILTIN PF_skel_mul_bones (progfuncs_t *prinst, struct globalvars_s *pr_g
if (startbone == -1)
startbone = 0;
//testme
while(startbone < endbone && startbone < skelobj->numbones)
if (endbone == -1)
endbone = skelobj->numbones;
else if (endbone > skelobj->numbones)
endbone = skelobj->numbones;
while(startbone < endbone)
{
Vector4Copy(skelobj->bonematrix+12*startbone+0, temp[0]);
Vector4Copy(skelobj->bonematrix+12*startbone+4, temp[1]);
Vector4Copy(skelobj->bonematrix+12*startbone+8, temp[2]);
R_ConcatTransforms(mult, temp, (float(*)[4])(skelobj->bonematrix+12*startbone));
startbone++;
}
}
@ -645,17 +849,48 @@ void QCBUILTIN PF_skel_copybones (progfuncs_t *prinst, struct globalvars_s *pr_g
skelobjsrc = skel_get(prinst, skelsrc, 0);
if (!skelobjdst || !skelobjsrc)
return;
if (skelobjsrc->type != skelobjdst->type)
return;
if (startbone == -1)
startbone = 0;
//testme
while(startbone < endbone && startbone < skelobjdst->numbones && startbone < skelobjsrc->numbones)
if (endbone == -1)
endbone = skelobjdst->numbones;
if (endbone > skelobjdst->numbones)
endbone = skelobjdst->numbones;
if (endbone > skelobjsrc->numbones)
endbone = skelobjsrc->numbones;
if (skelobjsrc->type == skelobjdst->type)
{
Vector4Copy(skelobjsrc->bonematrix+12*startbone+0, skelobjdst->bonematrix+12*startbone+0);
Vector4Copy(skelobjsrc->bonematrix+12*startbone+4, skelobjdst->bonematrix+12*startbone+4);
Vector4Copy(skelobjsrc->bonematrix+12*startbone+8, skelobjdst->bonematrix+12*startbone+8);
while(startbone < endbone)
{
Vector4Copy(skelobjsrc->bonematrix+12*startbone+0, skelobjdst->bonematrix+12*startbone+0);
Vector4Copy(skelobjsrc->bonematrix+12*startbone+4, skelobjdst->bonematrix+12*startbone+4);
Vector4Copy(skelobjsrc->bonematrix+12*startbone+8, skelobjdst->bonematrix+12*startbone+8);
startbone++;
}
}
else if (skelobjsrc->type == SKOT_RELATIVE && skelobjdst->type == SKOT_ABSOLUTE)
{
/*copy from relative to absolute*/
galiasbone_t *boneinfo = Mod_GetBoneInfo(skelobjsrc->model);
if (!boneinfo)
return;
while(startbone < endbone)
{
if (boneinfo[startbone].parent >= 0)
{
Matrix3x4_Multiply(skelobjsrc->bonematrix+12*startbone, skelobjdst->bonematrix+12*boneinfo[startbone].parent, skelobjdst->bonematrix+12*startbone);
}
else
{
Vector4Copy(skelobjsrc->bonematrix+12*startbone+0, skelobjdst->bonematrix+12*startbone+0);
Vector4Copy(skelobjsrc->bonematrix+12*startbone+4, skelobjdst->bonematrix+12*startbone+4);
Vector4Copy(skelobjsrc->bonematrix+12*startbone+8, skelobjdst->bonematrix+12*startbone+8);
}
startbone++;
}
}
}
@ -669,6 +904,7 @@ void QCBUILTIN PF_skel_delete (progfuncs_t *prinst, struct globalvars_s *pr_glob
if (skelobj)
{
skelobj->inuse = 2; //2 means don't reuse yet.
skelobj->model = NULL;
pendingkill = true;
}
}

View File

@ -338,40 +338,6 @@ qboolean Mod_LoadMap_Proc(model_t *model, char *data)
return true;
}
static qboolean D3_PolyBounds(vec_t result[4], int count, vec4_t *vlist)
{
qboolean ret = false;
int i;
vec4_t tempv, v;
/*inverted*/
result[0] = 10000;
result[1] = -10000;
result[2] = 10000;
result[3] = -10000;
for (i = 0; i < count; i++)
{
Matrix4x4_CM_Transform4(r_refdef.m_view, vlist[i], tempv);
Matrix4x4_CM_Transform4(r_refdef.m_projection, tempv, v);
v[0] /= v[3];
v[1] /= v[3];
// if (v[2] < 0)
// continue;
if (result[0] > v[0])
result[0] = v[0];
if (result[1] < v[0])
result[1] = v[0];
if (result[2] > v[1])
result[2] = v[1];
if (result[3] < v[1])
result[3] = v[1];
ret = true;
}
return ret;
}
qboolean R_CullBox (vec3_t mins, vec3_t maxs);
static int walkno;
@ -523,11 +489,11 @@ void D3_LightPointValues (struct model_s *model, vec3_t point, vec3_t res_diffus
qboolean D3_EdictInFatPVS (struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer)
{
// int i;
// for (i = 0; i < edict->num_leafs; i++)
// if (pvsbuffer[edict->leafnums[i]>>3] & (1u<<(edict->leafnums[i]&7)))
int i;
for (i = 0; i < edict->num_leafs; i++)
if (pvsbuffer[edict->leafnums[i]>>3] & (1u<<(edict->leafnums[i]&7)))
return true;
// return false;
return false;
}
@ -548,6 +514,7 @@ typedef struct cm_surface_s
typedef struct cm_brush_s
{
vec3_t mins, maxs;
int numplanes;
vec4_t *plane;
unsigned int contents;
@ -562,15 +529,10 @@ typedef struct cm_node_s
struct cm_node_s *parent;
struct cm_node_s *child[2];
cm_brush_t **brushlist;
cm_brush_t *brushlist;
cm_surface_t *surfacelist;
} cm_node_t;
typedef struct
{
cm_node_t *nodes; /*first is root*/
} cm_model_t;
static struct
{
float truefraction;
@ -701,7 +663,7 @@ static void D3_TraceToLeaf (cm_node_t *leaf)
pdist = surf->edge[i][3];
}
if (DotProduct(impactpoint, surf->edge[i]) > pdist+DIST_EPSILON)
if (DotProduct(impactpoint, surf->edge[i]) > pdist)
{
break;
}
@ -722,11 +684,10 @@ static void D3_TraceToLeaf (cm_node_t *leaf)
static cm_node_t *D3_ChildNodeForBox(cm_node_t *node, vec3_t mins, vec3_t maxs)
{
float t1, t2;
/*
for(;;)
{
t1 = p1[node->axis] - node->dist;
t2 = p2[node->axis] - node->dist;
t1 = mins[node->axis] - node->dist;
t2 = maxs[node->axis] - node->dist;
//if its completely to one side, walk down that side
if (t1 > maxs[node->axis] && t2 > maxs[node->axis])
@ -749,7 +710,7 @@ static cm_node_t *D3_ChildNodeForBox(cm_node_t *node, vec3_t mins, vec3_t maxs)
//the box crosses this node
break;
}
*/
return node;
}
@ -757,10 +718,16 @@ static void D3_InsertClipSurface(cm_node_t *node, cm_surface_t *surf)
{
node = D3_ChildNodeForBox(node, surf->mins, surf->maxs);
/*FIXME: walk the nodes to find one the one that holds us*/
surf->next = node->surfacelist;
node->surfacelist = surf;
}
static void D3_InsertClipBrush(cm_node_t *node, cm_brush_t *brush)
{
node = D3_ChildNodeForBox(node, brush->mins, brush->maxs);
brush->next = node->brushlist;
node->brushlist = brush;
}
static void D3_RecursiveSurfCheck (cm_node_t *node, float p1f, float p2f, vec3_t p1, vec3_t p2)
{
@ -888,7 +855,7 @@ qboolean D3_Trace (struct model_s *model, int hulloverride, int frame, vec3_t ax
}
else
{
float diststart, distend, frac;
float frac;
/*we now know which surface it hit. recalc the impact point, but with an epsilon this time, so we can never get too close to the surface*/
VectorCopy(traceinfo.surf->plane, trace->plane.normal);
@ -940,11 +907,84 @@ qboolean D3_Trace (struct model_s *model, int hulloverride, int frame, vec3_t ax
unsigned int D3_PointContents (struct model_s *model, vec3_t axis[3], vec3_t p)
{
return FTECONTENTS_SOLID;
cm_node_t *node = model->cnodes;
cm_brush_t *brush;
float t1;
unsigned int contents = 0;
int i;
if (axis)
{
vec3_t tmp;
VectorCopy(p, tmp);
p[0] = DotProduct(tmp, axis[0]);
p[1] = DotProduct(tmp, axis[1]);
p[2] = DotProduct(tmp, axis[2]);
}
while(node)
{
for (brush = node->brushlist; brush; brush = brush->next)
{
if (brush->mins[0] > p[0] || p[0] > brush->maxs[0] ||
brush->mins[1] > p[1] || p[1] > brush->maxs[1] ||
brush->mins[2] > p[2] || p[2] > brush->maxs[2])
continue;
for (i = 0; i < brush->numplanes; i++)
{
if (DotProduct(p, brush->plane[i]) > brush->plane[i][3])
break;
}
if (i == brush->numplanes)
contents |= brush->contents;
}
t1 = p[node->axis] - node->dist;
// see which side we need to go down
if (t1 >= 0)
{
node = node->child[0];
}
else
{
node = node->child[1];
}
}
return contents;
}
#define ensurenewtoken(t) buf = COM_ParseOut(buf, token, sizeof(token)); if (strcmp(token, t)) break;
int D3_ParseContents(char *str)
{
char *e, *n;
unsigned int contents = 0;
while(str)
{
e = strchr(str, ',');
if (e)
{
*e = 0;
n = e+1;
}
else
n = NULL;
if (!strcmp(str, "solid") || !strcmp(str, "opaque"))
contents |= FTECONTENTS_SOLID;
else if (!strcmp(str, "playerclip"))
contents |= FTECONTENTS_PLAYERCLIP;
else if (!strcmp(str, "monsterclip"))
contents |= FTECONTENTS_PLAYERCLIP;
else
Con_Printf("Unknown contents type \"%s\"\n", str);
str = n;
}
return contents;
}
typedef struct
{
int v[2];
@ -954,9 +994,11 @@ qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf)
{
int pedges[64];
cm_surface_t *surf;
cm_brush_t *brush;
vec3_t *verts;
d3edge_t *edges;
int i, j;
int filever = 0;
int numverts, numedges, numpedges;
model_t *cmod;
char token[256];
@ -965,7 +1007,8 @@ qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf)
return false;
buf = COM_ParseOut(buf, token, sizeof(token));
if (atof(token) != 1.0 && atof(token) != 3)
filever = atof(token);
if (filever != 1 && filever != 3)
return false;
buf = COM_ParseOut(buf, token, sizeof(token));
@ -982,6 +1025,13 @@ qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf)
else
cmod = Mod_FindName(token);
if (filever == 3)
{
buf = COM_ParseOut(buf, token, sizeof(token));
/*don't know*/
}
ClearBounds(cmod->mins, cmod->maxs);
ensurenewtoken("{");
ensurenewtoken("vertices");
ensurenewtoken("{");
@ -1037,8 +1087,18 @@ qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf)
break;
ensurenewtoken("polygons");
buf = COM_ParseOut(buf, token, sizeof(token));
/*'polygonMemory', which is unusable for us*/
if (filever == 1)
{
buf = COM_ParseOut(buf, token, sizeof(token));
/*'polygonMemory', which is unusable for us*/
}
else
{
buf = COM_ParseOut(buf, token, sizeof(token));
/*numPolygons*/
buf = COM_ParseOut(buf, token, sizeof(token));
/*numPolygonEdges*/
}
ensurenewtoken("{");
for (;;)
{
@ -1088,7 +1148,29 @@ qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf)
ensurenewtoken(")");
buf = COM_ParseOut(buf, token, sizeof(token));
#ifndef SERVERONLY
surf->shader = R_RegisterShader_Vertex(token);
#endif
if (filever == 3)
{
ensurenewtoken("(");
buf = COM_ParseOut(buf, token, sizeof(token));
buf = COM_ParseOut(buf, token, sizeof(token));
ensurenewtoken(")");
ensurenewtoken("(");
buf = COM_ParseOut(buf, token, sizeof(token));
buf = COM_ParseOut(buf, token, sizeof(token));
ensurenewtoken(")");
ensurenewtoken("(");
buf = COM_ParseOut(buf, token, sizeof(token));
buf = COM_ParseOut(buf, token, sizeof(token));
ensurenewtoken(")");
buf = COM_ParseOut(buf, token, sizeof(token));
}
for (j = 0; j < numpedges; j++)
{
@ -1108,16 +1190,31 @@ qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf)
VectorNormalize(dir);
CrossProduct(surf->plane, dir, surf->edge[j]);
surf->edge[j][3] = DotProduct(v1, surf->edge[j]);
surf->edge[j][3] += DIST_EPSILON;
}
D3_InsertClipSurface(cmod->cnodes, surf);
AddPointToBounds(surf->mins, cmod->mins, cmod->maxs);
AddPointToBounds(surf->maxs, cmod->mins, cmod->maxs);
}
free(verts);
free(edges);
ensurenewtoken("brushes");
buf = COM_ParseOut(buf, token, sizeof(token));
/*'polygonMemory', which is unusable for us*/
if (filever == 1)
{
buf = COM_ParseOut(buf, token, sizeof(token));
/*'brushMemory', which is unusable for us*/
}
else
{
buf = COM_ParseOut(buf, token, sizeof(token));
/*numBrushes */
buf = COM_ParseOut(buf, token, sizeof(token));
/*numBrushPlanes*/
}
ensurenewtoken("{");
for (;;)
{
@ -1125,31 +1222,53 @@ qboolean D3_LoadMap_CollisionMap(model_t *mod, char *buf)
if (!strcmp(token, "}"))
break;
j = atoi(token);
brush = Hunk_Alloc(j*sizeof(vec4_t) + sizeof(*brush));
brush->numplanes = j;
brush->plane = (vec4_t*)(brush+1);
ensurenewtoken("{");
for (i = 0; i < j; i++)
for (i = 0; i < brush->numplanes; i++)
{
ensurenewtoken("(");
buf = COM_ParseOut(buf, token, sizeof(token));
brush->plane[i][0] = atof(token);
buf = COM_ParseOut(buf, token, sizeof(token));
brush->plane[i][1] = atof(token);
buf = COM_ParseOut(buf, token, sizeof(token));
brush->plane[i][2] = atof(token);
ensurenewtoken(")");
buf = COM_ParseOut(buf, token, sizeof(token));
brush->plane[i][3] = atof(token);
}
ensurenewtoken("}");
ensurenewtoken("(");
buf = COM_ParseOut(buf, token, sizeof(token));
brush->mins[0] = atof(token);
buf = COM_ParseOut(buf, token, sizeof(token));
brush->mins[1] = atof(token);
buf = COM_ParseOut(buf, token, sizeof(token));
brush->mins[2] = atof(token);
ensurenewtoken(")");
ensurenewtoken("(");
buf = COM_ParseOut(buf, token, sizeof(token));
brush->maxs[0] = atof(token);
buf = COM_ParseOut(buf, token, sizeof(token));
brush->maxs[1] = atof(token);
buf = COM_ParseOut(buf, token, sizeof(token));
brush->maxs[2] = atof(token);
ensurenewtoken(")");
buf = COM_ParseOut(buf, token, sizeof(token));
brush->contents = D3_ParseContents(token);
if (filever == 3)
buf = COM_ParseOut(buf, token, sizeof(token));
D3_InsertClipBrush(cmod->cnodes, brush);
AddPointToBounds(brush->mins, cmod->mins, cmod->maxs);
AddPointToBounds(brush->maxs, cmod->mins, cmod->maxs);
}
}
else

View File

@ -47,7 +47,7 @@ char *particle_set_spikeset =
"spawnvel 10\n"
"}\n"
"r_part tr_rocket\n"
"r_part t_rocket\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 97 97 191 191 256\n"
@ -78,7 +78,7 @@ char *particle_set_spikeset =
"cliptype rockettail\n"
"}\n"
"r_part tr_altrocket\n"
"r_part t_altrocket\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 97 97 191 191 256\n"
@ -188,7 +188,7 @@ char *particle_set_spikeset =
"rgb 150 150 150\n"
"}\n"
"r_part tr_grenade\n"
"r_part t_grenade\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 97 97 191 191 256\n"
@ -207,7 +207,7 @@ char *particle_set_spikeset =
"}\n"
//cool's blood trails (cos they're cooler)
"r_part tr_gib\n"
"r_part t_gib\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 1 63 63 256 2 64\n"
@ -226,7 +226,7 @@ char *particle_set_spikeset =
"stains 5\n"
"}\n"
"r_part tr_slightblood\n"
"r_part t_zomgib\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 1 63 63 256 2 64\n"
@ -245,7 +245,7 @@ char *particle_set_spikeset =
"stains 5\n"
"}\n"
"r_part tr_wizspike\n"
"r_part t_tracer\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
@ -260,7 +260,7 @@ char *particle_set_spikeset =
"scalefactor 0.825\n"
"}\n"
"r_part tr_knightspike\n"
"r_part t_tracer2\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
@ -275,7 +275,7 @@ char *particle_set_spikeset =
"scalefactor 0.825\n"
"}\n"
"r_part tr_vorespike\n"
"r_part t_tracer3\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
@ -727,7 +727,7 @@ char *particle_set_spikeset =
char *particle_set_faithful =
// faithful, by TimeServ
"r_part tr_gib\n"
"r_part t_gib\n"
"{\n"
"texture \"particles/quake\"\n"
"step 3\n"
@ -742,7 +742,7 @@ char *particle_set_faithful =
"stains 1\n"
"}\n"
"r_part tr_slightblood\n"
"r_part t_zomgib\n"
"{\n"
"texture \"particles/quake\"\n"
"step 6\n"
@ -757,7 +757,7 @@ char *particle_set_faithful =
"stains 1\n"
"}\n"
"r_part tr_vorespike\n"
"r_part t_tracer3\n"
"{\n"
"texture \"particles/quake\"\n"
"step 3\n"
@ -768,7 +768,7 @@ char *particle_set_faithful =
"spawnorg 8\n"
"}\n"
"r_part tr_wizspike\n"
"r_part t_tracer\n"
"{\n"
"texture \"particles/quake\"\n"
"step 3\n"
@ -781,7 +781,7 @@ char *particle_set_faithful =
"spawnmode tracer\n"
"}\n"
"r_part tr_knightspike\n"
"r_part t_tracer2\n"
"{\n"
"texture \"particles/quake\"\n"
"step 3\n"
@ -794,7 +794,7 @@ char *particle_set_faithful =
"spawnmode tracer\n"
"}\n"
"r_part tr_rocket\n"
"r_part t_rocket\n"
"{\n"
"texture \"particles/quake\"\n"
"step 3\n"
@ -812,7 +812,7 @@ char *particle_set_faithful =
"gravity -40\n"
"}\n"
"r_part tr_altrocket\n"
"r_part t_altrocket\n"
"{\n"
"texture \"particles/quake\"\n"
"step 3\n"
@ -825,7 +825,7 @@ char *particle_set_faithful =
"gravity -40\n"
"}\n"
"r_part tr_grenade\n"
"r_part t_grenade\n"
"{\n"
"texture \"particles/quake\"\n"
"step 3\n"
@ -1031,7 +1031,7 @@ char *particle_set_faithful =
char *particle_set_highfps =
// highfps, originally submitted by 'ShadowWalker'
// rehashed by TimeServ
"r_part tr_gib\n"
"r_part t_gib\n"
"{\n"
"texture \"particles/bloodtrail\"\n"
"step 12\n"
@ -1042,7 +1042,7 @@ char *particle_set_highfps =
"rgb 64 0 0\n"
"rgbdelta -128 0 0\n"
"}\n"
"r_part tr_slightblood\n"
"r_part t_zomgib\n"
"{\n"
"texture \"particles/bloodtrail\"\n"
"step 16\n"
@ -1054,7 +1054,7 @@ char *particle_set_highfps =
"rgbdelta -128 0 0\n"
"}\n"
"r_part tr_wizspike\n"
"r_part t_tracer\n"
"{\n"
"texture \"particles/tracer\"\n"
"scale 23\n"
@ -1063,7 +1063,7 @@ char *particle_set_highfps =
"die 0.5\n"
"}\n"
"r_part tr_knightspike\n"
"r_part t_tracer2\n"
"{\n"
"texture \"particles/tracer\"\n"
"scale 23\n"
@ -1072,7 +1072,7 @@ char *particle_set_highfps =
"rgb 192 96 0\n"
"}\n"
"r_part tr_vorespike\n"
"r_part t_tracer3\n"
"{\n"
"texture \"particles/tracer\"\n"
"scale 23\n"
@ -1148,13 +1148,14 @@ char *particle_set_highfps =
"r_part te_railtrail\n"
"{\n"
"step 64\n"
"step 1000000\n"
"scale 5\n"
"die 1.2\n"
"alpha 0.7\n"
"rgb 16 16 255\n"
"blend add\n"
"type beam\n"
"averageout\n"
"}\n"
//the blob tempent is used quite a bit with teamfortress emp grenades.
@ -1211,7 +1212,7 @@ char *particle_set_highfps =
"spawnvel 25 4\n"
"}\n"
"r_part tr_grenade\n"
"r_part t_grenade\n"
"{\n"
"texture \"particles/smoke\"\n"
"step 20\n"
@ -1221,7 +1222,7 @@ char *particle_set_highfps =
"rgb 128 128 128\n"
"}\n"
"r_part tr_rocket\n"
"r_part t_rocket\n"
"{\n"
"texture \"particles/rocket\"\n"
"step 15\n"
@ -1232,7 +1233,7 @@ char *particle_set_highfps =
"assoc t_grenade\n"
"}\n"
"r_part tr_altrocket\n"
"r_part t_altrocket\n"
"{\n"
"texture \"particles/rocket\"\n"
"step 15\n"
@ -1286,6 +1287,474 @@ char *particle_set_highfps =
"rgb 255 255 0\n"
"}\n"
;
//////////////////////////////////////////////////////
char *particle_set_high =
///////////////////////////////
//rocket trail
// flame trail
"r_part tr_rocket\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 97 97 191 191 256\n"
"step 1\n"
"scale 12\n"
"alpha 0.4\n"
"die 0.5\n"
"rgb 255 127 100\n"
"rgbdelta -14 -300 -300\n"
"blend add\n"
"scalefactor 1\n"
"scaledelta -15\n"
"}\n"
// smoke puffs
"r_part +tr_rocket\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 97 97 191 191 256\n"
"step 5\n"
"scale 30\n"
"alpha 0.2\n"
"die 1.5\n"
//diesubrand 10.25
"randomvel 0.2\n"
"rgb 5 5 5\n"
//rgbdelta -230 -45 -9
"gravity -15\n"
"scalefactor 1\n"
"scaledelta 20\n"
"spawnvel 5\n"
"}\n"
// burst sparks
"r_part +tr_rocket\n"
"{\n"
"type texturedspark\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 65 31 95 256 8 32\n"
"count 1\n"
"scale 2\n"
"scalefactor 1\n"
"scaledelta -15\n"
"alpha 0.2\n"
"die 0.25\n"
"rgb 255 128 0\n"
"blend add\n"
"spawnmode ball\n"
"spawnorg 1\n"
"spawnvel 50\n"
"veladd 500\n"
"friction 0.01\n"
"gravity 100\n"
"}\n"
///////////////////////////////////////////
//alternate rocket trail, which is used by a handful of qw players.
//r_part tr_altrocket
//{
//}
///////////////////////////////////////////
//grenade trail
"r_part tr_grenade\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 97 97 191 191 256\n"
"step 6\n"
"scale 32\n"
"scaledelta 12\n"
"alpha 0.3\n"
"die 1.25\n"
"randomvel 2\n"
"veladd 15\n"
"rgb 75 75 75\n"
//rgb 255 50 50
//rgbdelta -255 -75 -75
"gravity -25\n"
"scalefactor 1\n"
"blend modulate\n"
"}\n"
"r_part +tr_grenade\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 97 97 191 191 256\n"
"scale 1\n"
"scaledelta 0.25\n"
"alpha 0.2\n"
"step 4\n"
"die 0.8\n"
"randomvel 0\n"
"rgb 255 150 150\n"
"rgbdelta 0 -150 -150\n"
"type beam\n"
"blend add\n"
"}\n"
//////////////////////////////////
//shotgun impacts
"r_part gunshotsmoke\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 65 31 95 256 8 32\n"
"count 3\n"
"scale 25\n"
"scalefactor 1\n"
"die 0.8\n"
"alpha 0.12\n"
"rgb 32 32 32\n"
"blend add\n"
"spawnmode ball\n"
"spawnorg 2\n"
"spawnvel 20\n"
"veladd -20\n"
"}\n"
"r_part te_gunshot\n"
"{\n"
"type texturedspark\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 65 31 95 256 8 32\n"
"count 3\n"
"scale 2\n"
"scalefactor 1\n"
"alpha 0.5\n"
"die 0.8\n"
"rgb 255 128 0\n"
"blend add\n"
"spawnmode ball\n"
"spawnorg 1\n"
"spawnvel 100\n"
"veladd -80\n"
"friction 0.3\n"
"gravity 400\n"
"assoc gunshotsmoke\n"
"}\n"
//////////////////////////////////
//nail impacts
"r_part te_spike\n"
"{\n"
"type sparkfan\n"
"count 10\n"
"scale 1\n"
"scalefactor 1\n"
"alpha 0.5\n"
"die 0.2\n"
"rgb 255 128 0\n"
"blend add\n"
"spawnmode ball\n"
"spawnorg 12\n"
"spawnvel 300\n"
"}\n"
"r_part +te_spike\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
"count 1\n"
"scale 1\n"
"scalefactor 1\n"
"scaledelta 190\n"
"die 0.1\n"
"alpha 0.6\n"
"rgb 255 128 0\n"
"blend add\n"
"assoc gunshotsmoke\n"
"}\n"
////////////////////////////////////////////////
//explosion
//red bit
"r_part te_explosion\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 97 97 191 191 256\n"
"count 1\n"
"scale 500\n"
"alpha 0.4\n"
"die 0.2\n"
"rgb 255 127 100\n"
"rgbdelta -14 -300 -300\n"
"blend add\n"
"scalefactor 1\n"
"scaledelta -15\n"
"randomvel 0\n"
"lightradius 350\n"
"lightrgb 0.4 0.2 0.05\n"
"lighttime 0.5\n"
"lightradiusfade 350\n"
"lightrgbfade 2 2 2 \n"
"}\n"
//smoke
"r_part +te_explosion\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 97 97 191 191 256\n"
"count 7\n"
"scale 300\n"
"alpha 0.2\n"
"die 0.8\n"
//diesubrand 10.25
"randomvel 100\n"
"rgb 5 5 5\n"
//rgbdelta -230 -45 -9
"gravity -15\n"
"scalefactor 1\n"
"scaledelta 40\n"
"spawnvel 5\n"
"}\n"
// burst sparks
"r_part +te_explosion\n"
"{\n"
"type texturedspark\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 65 31 95 256 8 32\n"
"count 100\n"
"scale 5\n"
"scalefactor 1\n"
"scaledelta -15\n"
"alpha 0.2\n"
"die 0.5\n"
"rgb 255 128 0\n"
"blend add\n"
"spawnmode ball\n"
"spawnorg 1\n"
"randomvel 1000\n"
"friction 0.01\n"
"gravity 100\n"
"stretchfactor 5\n"
"}\n"
//hide lights in explosions.
"r_explosionlight 0\n"
//hide the explosion sprite in nq+qw - WARNING: some mods use this sprite as a flame thrower.
"cl_expsprite 0\n"
"r_effect \"progs/s_explod.spr\" hidden 1\n"
//////////////////////////////////////////
//r_part te_tarexplosion
//{
//}
//////////////////////////////////////////
//r_part te_lavasplash
//{
//}
//////////////////////////////////////////
"r_part te_teleport\n"
"{\n"
"scale 250\n"
"count 1\n"
"alpha 0.3\n"
"die 0.5\n"
"scalefactor 1\n"
"rotationstart 45\n"
"rotationspeed 0\n"
"shader\n"
"{\n"
"glslprogram\n"
"{\n"
"varying vec2 tcoord;\n"
"varying vec4 scoord;\n"
"varying float alph;\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"attribute vec4 v_colour;\n"
"void main(void)\n"
"{\n"
"scoord = ftetransform();\n"
"tcoord = (v_texcoord.st - 0.5)*2.0;\n"
"alph = v_colour.a;\n"
"gl_Position = scoord;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform sampler2D s_t0;\n"
"void main(void)\n"
"{\n"
"vec2 nst;\n"
"float f;\n"
"nst = scoord.xy / scoord.w;\n"
"nst = (1.0 + nst)/2.0;\n"
"f = 1 - length(tcoord);\n"
// f = 1 - tcoord*tcoord;
"if (f < 0) discard;\n"
"f *= alph;\n"
"gl_FragColor = texture2D(s_t0, nst - tcoord*f);\n"
"}\n"
"#endif\n"
"}\n"
"{\n"
"map $currentrender\n"
"blendfunc blend\n"
"}\n"
"}\n"
"}\n"
//////////////////////////////////////////
//hellknight
"r_part tr_knightspike\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
"scale 15\n"
"step 1\n"
"alpha 0.6\n"
"die 0.2\n"
"rgb 192 96 48\n"
"veladd 0\n"
"randomvel 2\n"
"friction 4\n"
"scalefactor 0.825\n"
"blend add\n"
"}\n"
/////////////////////////////////////////
//vore missiles
"r_part tr_vorespike\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
"scale 15\n"
"step 1\n"
"alpha 0.6\n"
"die 0.5\n"
"rgb 192 96 192\n"
"veladd 15\n"
"spawnmode spiral\n"
"spawnvel 50\n"
"randomvel 0\n"
"friction 0\n"
"scalefactor 1\n"
"blend add\n"
"lightradius 150\n"
"lightrgb 0.75 0.37 0.75\n"
"}\n"
//rygel's pack sucks
"r_trail \"progs/v_spike.mdl\" tr_vorespike\n"
/////////////////////////////////////////
//scrag missiles. just use the default trail cos we're lazy
//r_part tr_wizspike
//{
//}
/////////////////////////////////////////
//zombie body-part blood trails
"r_part tr_slightblood\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 1 63 63 256 2 64\n"
"step 16\n"
"scale 64\n"
"alpha 0.6\n"
"die 1\n"
"randomvel 32\n"
"veladd 10\n"
"rotationspeed 90\n"
"rotationstart 0 360\n"
"rgb 32 0 0\n"
"gravity 200\n"
"scalefactor 0.8\n"
"scaledelta -10\n"
"stains 5\n"
"}\n"
//////////////////////////////////////////
//regular ol' blood trails
"r_part tr_blood\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 1 63 63 256 2 64\n"
"step 4\n"
"scale 64\n"
"alpha 0.3\n"
"die 1\n"
"randomvel 32\n"
"veladd 10\n"
"rotationspeed 90\n"
"rotationstart 0 360\n"
"rgb 64 0 0\n"
"gravity 200\n"
"scalefactor 0.8\n"
"scaledelta -10\n"
"stains 5\n"
"}\n"
//////////////////////////////////
//fallbacks
"r_part pe_default\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
"count 1\n"
"scale 4\n"
"veladd 15\n"
"die 0.4\n"
"alphadelta 0\n"
"diesubrand 0.4\n"
"gravity 40\n"
"spawnorg 8\n"
"}\n"
"r_part pe_defaulttrail\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
"scale 15\n"
"step 1\n"
"alpha 0.6\n"
"die 0.2\n"
"rgb 192 96 48\n"
"veladd 0\n"
"randomvel 2\n"
"friction 4\n"
"scalefactor 0.825\n"
"blend add\n"
"}\n"
//////////////////////////////////
//map debugging
"r_part pe_pointfile\n"
"{\n"
"texture \"particles/fteparticlefont.tga\"\n"
"tcoords 1 97 95 191 256\n"
"count 1\n"
"scale 50\n"
"die 30\n"
"alphadelta 0\n"
"rgb 255 255 0\n"
"}\n"
;

View File

@ -1,7 +1,8 @@
extern char *particle_set_spikeset;
extern char *particle_set_faithful;
extern char *particle_set_highfps;
extern char *particle_set_high;
extern char *particle_set_minimal;
extern char *particle_set_h2part;
extern char *particle_set_tsshaft;
#define R_PARTSET_BUILTINS {"spikeset", &particle_set_spikeset},{"faithful", &particle_set_faithful},{"highfps", &particle_set_highfps},{"minimal", &particle_set_minimal},{"h2part", &particle_set_h2part},{"tsshaft", &particle_set_tsshaft},
#define R_PARTSET_BUILTINS {"spikeset", &particle_set_spikeset},{"faithful", &particle_set_faithful},{"highfps", &particle_set_highfps},{"high", &particle_set_high},{"minimal", &particle_set_minimal},{"h2part", &particle_set_h2part},{"tsshaft", &particle_set_tsshaft},

View File

@ -2092,7 +2092,8 @@ void Surf_DrawWorld (void)
else
{
vis = R_MarkLeaves_Q1 ();
VectorCopy (r_refdef.vieworg, modelorg);
if (!(r_novis.ival & 2))
VectorCopy (r_refdef.vieworg, modelorg);
Surf_RecursiveWorldNode (cl.worldmodel->nodes, 0xf);
}
@ -2165,6 +2166,10 @@ static int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader)
}
}
/*not required, but using one lightmap per texture can result in better texture unit switching*/
if (lightmap[texnum]->shader != shader)
continue;
if (lightmap[texnum]->external)
{
TEXASSIGN(lightmap_textures[texnum], R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT));
@ -2172,17 +2177,13 @@ static int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader)
lightmap[texnum]->external = false;
}
/*not required, but using one lightmap per texture can result in better texture unit switching*/
if (lightmap[texnum]->shader != shader)
continue;
best = LMBLOCK_HEIGHT;
for (i=0 ; i<LMBLOCK_WIDTH-w ; i++)
for (i = 0; i <= LMBLOCK_WIDTH - w; i++)
{
best2 = 0;
for (j=0 ; j<w ; j++)
for (j=0; j < w; j++)
{
if (lightmap[texnum]->allocated[i+j] >= best)
break;
@ -2199,7 +2200,7 @@ static int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader)
if (best + h > LMBLOCK_HEIGHT)
continue;
for (i=0 ; i<w ; i++)
for (i=0; i < w; i++)
lightmap[texnum]->allocated[*x + i] = best + h;
return texnum;

View File

@ -204,8 +204,8 @@ void Surf_RenderDynamicLightmaps (struct msurface_s *fa);
void Surf_RenderAmbientLightmaps (struct msurface_s *fa, int ambient);
int Surf_LightmapShift (struct model_s *model);
#ifndef LMBLOCK_WIDTH
#define LMBLOCK_WIDTH 128
#define LMBLOCK_HEIGHT 128
#define LMBLOCK_WIDTH 256
#define LMBLOCK_HEIGHT 256
typedef struct glRect_s {
unsigned char l,t,w,h;
} glRect_t;

View File

@ -703,7 +703,7 @@ int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum)
dsbuf.lpwfxFormat = NULL;
#ifdef DSBCAPS_GLOBALFOCUS
if (snd_inactive.ival)
if (snd_inactive.ival || sys_parentwindow) /*always inactive if we have a parent window, because we can't tell properly otherwise*/
{
dsbuf.dwFlags |= DSBCAPS_GLOBALFOCUS;
sc->inactive_sound = true;

View File

@ -147,9 +147,11 @@ void S_StopSoundCard (soundcardinfo_t *sc, int entnum, int entchannel);
void S_DefaultSpeakerConfiguration(soundcardinfo_t *sc);
void S_ResetFailedLoad(void);
#ifdef PEXT2_VOICECHAT
void S_Voip_Parse(void);
#endif
#ifdef VOICECHAT
extern cvar_t cl_voip_showmeter;
void S_Voip_Parse(void);
void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf);
void S_Voip_MapChange(void);
int S_Voip_Loudness(qboolean ignorevad); //-1 for not capturing, otherwise between 0 and 100

View File

@ -812,7 +812,7 @@ HRESULT WINAPI DllRegisterServer(void)
HKEY h;
bool allusers = false;
int i;
char *ls;
const char *ls;
for (i = 0; regkeys[i].key; i++)
{
@ -841,7 +841,7 @@ HRESULT WINAPI DllUnregisterServer(void)
{
int i;
bool allusers = false;
char *ls;
const char *ls;
char tmp[1024];
HKEY h;

View File

@ -125,6 +125,8 @@ LRESULT CALLBACK MyPluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPar
*/
return TRUE;
case WM_ERASEBKGND:
return FALSE;
case WM_PAINT:
if (pub->downloading)
{

View File

@ -509,9 +509,6 @@ qboolean Plug_ChangeWindow(struct context *ctx, void *whnd, int left, int top, i
ctx->resetvideo = true;
Plug_LockPlugin(ctx, false);
while(ctx->pub.running && ctx->resetvideo)
Sleep(10);
return result;
}

View File

@ -378,7 +378,11 @@ DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exception
if (pIsDebuggerPresent ())
{
/*if we have a current window, minimize it to bring us out of fullscreen*/
extern qboolean vid_initializing;
qboolean oldval = vid_initializing;
vid_initializing = true;
ShowWindow(mainwindow, SW_MINIMIZE);
vid_initializing = oldval;
return EXCEPTION_CONTINUE_SEARCH;
}

View File

@ -883,15 +883,20 @@ void Editor_Draw(void)
useeval = false;
else
{
char *eq;
char *eq, *term;
Draw_FunString(0, 8, evalstring);
eq = strchr(evalstring, '=');
if (eq)
{
if (strchr(eq, ';'))
term = strchr(eq, ';');
if (!term)
term = strchr(eq, '\n');
if (!term)
term = strchr(eq, '\r');
if (term)
{
*strchr(eq, ';') = '\0';
*term = '\0';
eq = NULL;
}
else

View File

@ -380,6 +380,7 @@ typedef struct {
rulesetrule_t rulesetrules_strict[] = {
{"ruleset_allow_shaders", "0"},
{"r_vertexlight", "0"},
{"ruleset_allow_playercount", "0"},
{"ruleset_allow_frj", "0"},
{"ruleset_allow_packet", "0"},
@ -406,6 +407,7 @@ rulesetrule_t rulesetrules_nqr[] = {
{"ruleset_allow_sensative_texture_replacements", "0"},
{"ruleset_allow_localvolume", "0"},
{"ruleset_allow_shaders", "0"},
{"r_vertexlight", "0"},
{"v_projectionmode", "0"},
{NULL}
};
@ -424,8 +426,8 @@ void RulesetLatch(cvar_t *cvar)
void Validation_DelatchRulesets(void)
{ //game has come to an end, allow the ruleset to be changed
Cvar_ApplyLatches(CVAR_RULESETLATCH);
Con_DPrintf("Ruleset deactivated\n");
if (Cvar_ApplyLatches(CVAR_RULESETLATCH))
Con_DPrintf("Ruleset deactivated\n");
}
qboolean Validation_GetCurrentRulesetName(char *rsnames, int resultbuflen, qboolean enforcechosenrulesets)

View File

@ -1463,6 +1463,8 @@ void V_RenderView (void)
CL_AllowIndependantSendCmd(false);
CL_TransitionEntities();
//work out which packet entities are solid
CL_SetSolidEntities ();

View File

@ -152,14 +152,15 @@ typedef struct
#define Q1CONTENTS_LAVA -5
#define Q1CONTENTS_SKY -6
#define FTECONTENTS_EMPTY 0
#define FTECONTENTS_SOLID 1
#define FTECONTENTS_WATER 2
#define FTECONTENTS_SLIME 4
#define FTECONTENTS_LAVA 8
#define FTECONTENTS_SKY 16
#define FTECONTENTS_LADDER 32
#define FTECONTENTS_FLUID (FTECONTENTS_WATER|FTECONTENTS_SLIME|FTECONTENTS_LAVA|FTECONTENTS_SKY) //sky is a fluid for q1 code.
#define FTECONTENTS_EMPTY 0
#define FTECONTENTS_SOLID 1
#define FTECONTENTS_WATER 2
#define FTECONTENTS_SLIME 4
#define FTECONTENTS_LAVA 8
#define FTECONTENTS_SKY 16
#define FTECONTENTS_LADDER 32
#define FTECONTENTS_FLUID (FTECONTENTS_WATER|FTECONTENTS_SLIME|FTECONTENTS_LAVA|FTECONTENTS_SKY) //sky is a fluid for q1 code.
#define FTECONTENTS_PLAYERCLIP 64
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct
@ -214,7 +215,7 @@ typedef struct
} dsedge_t;
typedef struct
{
unsigned short v[2]; // vertex numbers
unsigned int v[2]; // vertex numbers
} dledge_t;
#define MAXLIGHTMAPS 4

View File

@ -269,7 +269,7 @@ void Cbuf_InsertText (const char *text, int level, qboolean addnl)
}
}
char *Cbuf_GetNext(int level)
char *Cbuf_GetNext(int level, qboolean ignoresemicolon)
{
int i;
char *text;
@ -285,7 +285,7 @@ start:
{
if (text[i] == '"')
quotes++;
if ( !(quotes&1) && text[i] == ';')
if ( !(quotes&1) && text[i] == ';' && !ignoresemicolon)
break; // don't break if inside a quoted string
if (text[i] == '\n')
break;
@ -707,7 +707,7 @@ void Cmd_Alias_f (void)
if (Cmd_Argc() == 2) //check the next statement for being '{'
{
char *line, *end;
line = Cbuf_GetNext(Cmd_ExecLevel);
line = Cbuf_GetNext(Cmd_ExecLevel, false);
while(*line <= ' ' && *line) //skip leading whitespace.
line++;
@ -730,7 +730,7 @@ void Cmd_Alias_f (void)
a->value = NULL;
for(;;)
{
s = Cbuf_GetNext(Cmd_ExecLevel);
s = Cbuf_GetNext(Cmd_ExecLevel, false);
if (!*s)
{
Con_Printf(CON_WARNING "WARNING: Multiline alias was not terminated\n");
@ -2350,7 +2350,7 @@ void Cbuf_ExecBlock(int level)
char *remainingcbuf;
char *exectext = NULL;
char *line, *end;
line = Cbuf_GetNext(level);
line = Cbuf_GetNext(level, false);
while(*line <= ' ' && *line) //skip leading whitespace.
line++;
@ -2364,7 +2364,7 @@ void Cbuf_ExecBlock(int level)
for(;;)
{
line = Cbuf_GetNext(level);
line = Cbuf_GetNext(level, false);
while(*line <= ' ' && *line) //skip leading whitespace.
line++;
@ -2415,7 +2415,7 @@ void Cbuf_ExecBlock(int level)
void Cbuf_SkipBlock(int level)
{
char *line, *end;
line = Cbuf_GetNext(level);
line = Cbuf_GetNext(level, false);
while(*line <= ' ' && *line) //skip leading whitespace.
line++;
@ -2429,7 +2429,7 @@ void Cbuf_SkipBlock(int level)
for(;;)
{
line = Cbuf_GetNext(level);
line = Cbuf_GetNext(level, false);
while(*line <= ' ' && *line) //skip leading whitespace.
line++;
@ -2511,7 +2511,7 @@ skipws:
skipblock:
Cbuf_SkipBlock(level);
}
end = Cbuf_GetNext(level);
end = Cbuf_GetNext(level, false);
while(*end <= ' ' && *end)
end++;
if (!strncmp(end, "else", 4))

View File

@ -47,7 +47,7 @@ void Cbuf_InsertText (const char *text, int level, qboolean addnl);
// inserted at the beginning of the buffer, before any remaining unexecuted
// commands.
char *Cbuf_GetNext(int level);
char *Cbuf_GetNext(int level, qboolean ignoresemicolon);
void Cbuf_Execute (void);
// Pulls off \n terminated lines of text from the command buffer and sends

View File

@ -893,7 +893,7 @@ int Alias_GetBoneRelations(galiasinfo_t *inf, framestate_t *fstate, float *resul
return 0;
}
//_may_ write into bonepose, return value is the real result
//_may_ write into bonepose, return value is the real result. obtains absolute values
float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *buffer, int buffersize)
{
#ifdef SKELETALMODELS
@ -908,6 +908,8 @@ float *Alias_GetBonePositions(galiasinfo_t *inf, framestate_t *fstate, float *bu
{
relations = fstate->bonestate;
numbones = inf->numbones;
if (fstate->boneabs)
return relations;
}
else
{
@ -3317,6 +3319,25 @@ int Mod_GetBoneRelations(model_t *model, int firstbone, int lastbone, framestate
return 0;
}
galiasbone_t *Mod_GetBoneInfo(model_t *model)
{
#ifdef SKELETALMODELS
galiasbone_t *bone;
galiasinfo_t *inf;
if (!model || model->type != mod_alias)
return NULL;
inf = Mod_Extradata(model);
bone = (galiasbone_t*)((char*)inf + inf->ofsbones);
return bone;
#else
return NULL;
#endif
}
int Mod_GetBoneParent(model_t *model, int bonenum)
{
#ifdef SKELETALMODELS
@ -4584,7 +4605,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
boneinfo[i].basepose.size[2] = LittleFloat(boneinfo[i].basepose.size[2]);
/*not sure if this is needed, but mimic DP*/
if (i >= 0)
if (i)
{
boneinfo[i].basepose.quat[0] *= -1;
boneinfo[i].basepose.quat[2] *= -1;
@ -4672,24 +4693,6 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
}
}
}
/*
for (i = 0; i < num_boneinfo; i++)
{
animbones[i].parent = LittleLong(animbones[i].parent);
if (strcmp(boneinfo[i].name, animbones[i].name))
{
fail = true;
Con_Printf("PSK/PSA bone names do not match %s vs %s\n", boneinfo[i].name, animbones[i].name);
break;
}
else if (boneinfo[i].parent != animbones[i].parent)
{
fail = true;
Con_Printf("PSK/PSA bone parents do not match for bone %s\n", boneinfo[i].name);
break;
}
}*/
}
}
else if (!strcmp("ANIMINFO", chunk->id) && chunk->recordsize == sizeof(pskaniminfo_t))

View File

@ -82,7 +82,7 @@ typedef struct {
} galiaspose_t;
#ifdef SKELETALMODELS
typedef struct {
typedef struct galiasbone_s {
char name[32];
int parent;
} galiasbone_t;

View File

@ -1728,7 +1728,11 @@ static qboolean GenerateCollisionMesh(world_t *world, model_t *mod, wedict_t *ed
ed->ode.ode_numtriangles = numindexes/3;
return true;
}
/*
static void World_ODE_BodyFromSkel(world_t *world)
{
}
*/
static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed)
{
dBodyID body = (dBodyID)ed->ode.ode_body;

View File

@ -320,8 +320,10 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation
struct vfsfile_s *FS_OpenReadLocation(flocation_t *location);
char *FS_WhichPackForLocation(flocation_t *loc);
qboolean FS_GetPackageDownloadable(char *package);
char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly);
char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly, qboolean ext);
char *FS_GetPackNames(char *buffer, int buffersize, int referencedonly, qboolean ext);
void FS_ReferenceControl(unsigned int refflag, unsigned int resetflags);
int COM_FOpenFile (const char *filename, FILE **file);
int COM_FOpenWriteFile (const char *filename, FILE **file);

View File

@ -673,7 +673,7 @@ cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
{
if (var->string && value)
if (strcmp(var->string, value))
Shader_NeedReload();
Shader_NeedReload(false);
}
if (var->flags & CVAR_USERINFO)
{
@ -833,8 +833,9 @@ void Cvar_ForceCheatVars(qboolean semicheats, qboolean absolutecheats)
}
}
void Cvar_ApplyLatches(int latchflag)
int Cvar_ApplyLatches(int latchflag)
{
int result = 0;
cvar_group_t *grp;
cvar_t *var;
int mask = ~0;
@ -854,10 +855,14 @@ void Cvar_ApplyLatches(int latchflag)
var->flags &= ~latchflag;
Cvar_Set(var, var->latched_string);
var->flags = of;
result++;
}
var->flags &= mask;
}
}
return result;
}
cvar_t *Cvar_Set (cvar_t *var, const char *value)

View File

@ -156,7 +156,7 @@ void Cvar_SetValue (cvar_t *var, float value);
qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag);
void Cvar_ApplyLatches(int latchflag);
int Cvar_ApplyLatches(int latchflag);
//sets vars to their latched values
void Cvar_Hook(cvar_t *cvar, void (*callback) (struct cvar_s *var, char *oldvalue));

View File

@ -19,6 +19,7 @@ qboolean com_fschanged = true;
static unsigned int fs_restarts;
extern cvar_t com_fs_cache;
int active_fs_cachetype;
static int fs_referencetype;
struct
{
@ -156,6 +157,7 @@ typedef struct searchpath_s
qboolean copyprotected; //don't allow downloads from here.
qboolean istemporary;
qboolean isexplicit; //explicitly loaded (ie: id1|qw|$gamedir|fte)
qboolean referenced;
void *handle;
char purepath[256]; //server tracks the path used to load them so it can tell the client
@ -507,6 +509,7 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation
{
if (loc)
{
search->referenced |= fs_referencetype;
loc->search = search;
len = loc->len;
}
@ -528,6 +531,7 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation
{
if (loc)
{
search->referenced |= fs_referencetype;
loc->search = search;
len = loc->len;
}
@ -578,6 +582,19 @@ char *FS_WhichPackForLocation(flocation_t *loc)
return ret;
}
/*requires extension*/
qboolean FS_GetPackageDownloadable(char *package)
{
searchpath_t *search;
for (search = com_purepaths ; search ; search = search->nextpure)
{
if (!strcmp(package, search->purepath))
return !search->copyprotected;
}
return false;
}
char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly)
{
@ -607,7 +624,14 @@ char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly)
return buffer;
}
}
char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly, qboolean ext)
/*
referencedonly=0: show all paks
referencedonly=1: show only paks that are referenced (q3-compat)
referencedonly=2: show all paks, but paks that are referenced are prefixed with a star
ext=0: hide extensions (q3-compat)
ext=1: show extensions.
*/
char *FS_GetPackNames(char *buffer, int buffersize, int referencedonly, qboolean ext)
{
char temp[MAX_OSPATH];
searchpath_t *search;
@ -618,6 +642,11 @@ char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly, qbo
{
for (search = com_purepaths ; search ; search = search->nextpure)
{
if (referencedonly == 0 && !search->referenced)
continue;
if (referencedonly == 2 && search->referenced)
Q_strncatz(buffer, "*", buffersize);
if (!ext)
{
COM_StripExtension(search->purepath, temp, sizeof(temp));
@ -638,6 +667,11 @@ char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly, qbo
search->crc_check = search->funcs->GeneratePureCRC(search->handle, 0, 0);
if (search->crc_check)
{
if (referencedonly == 0 && !search->referenced)
continue;
if (referencedonly == 2 && search->referenced)
Q_strncatz(buffer, "*", sizeof(buffer));
if (!ext)
{
COM_StripExtension(search->purepath, temp, sizeof(temp));
@ -653,6 +687,20 @@ char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly, qbo
}
}
void FS_ReferenceControl(unsigned int refflag, unsigned int resetflags)
{
searchpath_t *s;
if (resetflags)
{
for (s=com_searchpaths ; s ; s=s->next)
{
s->referenced &= ~resetflags;
}
}
fs_referencetype = refflag;
}
#if 0
int COM_FOpenLocationFILE(flocation_t *loc, FILE **file)

View File

@ -29,7 +29,7 @@ extern cvar_t r_shadow_bumpscale_basetexture;
//these are in model.c (or gl_model.c)
qboolean RMod_LoadVertexes (lump_t *l);
qboolean RMod_LoadEdges (lump_t *l, qboolean lm);
qboolean RMod_LoadMarksurfaces (lump_t *l);
qboolean RMod_LoadMarksurfaces (lump_t *l, qboolean lm);
qboolean RMod_LoadSurfedges (lump_t *l);
void RMod_LoadLighting (lump_t *l);
@ -98,8 +98,8 @@ void CalcSurfaceExtents (msurface_t *s)
s->texturemins[i] = bmins[i] * 16;
s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
// if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 ) //q2 uses 512. probably for skys.
// Sys_Error ("Bad surface extents");
// if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 8176 ) //q2 uses 512. probably for skys.
// Con_Printf ("Bad surface extents (texture %s)\n", s->texinfo->texture->name);
}
}
@ -203,23 +203,11 @@ typedef struct q2mapsurface_s // used internally due to name len probs //ZOID
typedef struct cmodel_s
{
vec3_t mins, maxs;
vec3_t origin; // for sounds or lights
int headnode;
int numsurfaces;
int firstsurface;
int firstbrush; //q3 submodels are considered small enough that you will never need to walk any sort of tree.
int num_brushes;//the brushes are checked instead.
} q2cmodel_t;
typedef struct {
char shader[MAX_QPATH];
int brushNum;
int visibleSide; // the brush side that ray tests need to clip against (-1 == none)
} dfog_t;
typedef struct
{
@ -272,61 +260,76 @@ typedef struct
int patch_cp[2];
} q3cface_t;
typedef struct cmodel_s
{
vec3_t mins, maxs;
vec3_t origin; // for sounds or lights
int headnode;
int numsurfaces;
int firstsurface;
int firstbrush; //q3 submodels are considered small enough that you will never need to walk any sort of tree.
int num_brushes;//the brushes are checked instead.
} cmodel_t;
/*used to trace*/
int checkcount;
static int checkcount;
int numbrushsides;
q2cbrushside_t map_brushsides[MAX_Q2MAP_BRUSHSIDES];
static mfog_t *map_fogs;
static int map_numfogs;
int numtexinfo;
q2mapsurface_t *map_surfaces;
static int numbrushsides;
static q2cbrushside_t map_brushsides[MAX_Q2MAP_BRUSHSIDES];
int numplanes;
mplane_t map_planes[MAX_Q2MAP_PLANES+6]; // extra for box hull
static int numtexinfo;
static q2mapsurface_t *map_surfaces;
int numleafs = 1; // allow leaf funcs to be called without a map
mleaf_t map_leafs[MAX_MAP_LEAFS];
int emptyleaf;
static int numplanes;
static mplane_t map_planes[MAX_Q2MAP_PLANES+6]; // extra for box hull
int numleafbrushes;
int map_leafbrushes[MAX_Q2MAP_LEAFBRUSHES];
static int numleafs = 1; // allow leaf funcs to be called without a map
static mleaf_t map_leafs[MAX_MAP_LEAFS];
static int emptyleaf;
int numcmodels;
q2cmodel_t map_cmodels[MAX_Q2MAP_MODELS];
static int numleafbrushes;
static int map_leafbrushes[MAX_Q2MAP_LEAFBRUSHES];
int numbrushes;
q2cbrush_t map_brushes[MAX_Q2MAP_BRUSHES];
static int numcmodels;
static cmodel_t map_cmodels[MAX_Q2MAP_MODELS];
int numvisibility;
qbyte map_visibility[MAX_Q2MAP_VISIBILITY];
q2dvis_t *map_q2vis = (q2dvis_t *)map_visibility;
q3dvis_t *map_q3pvs = (q3dvis_t *)map_visibility;
qbyte map_hearability[MAX_Q2MAP_VISIBILITY];
q3dvis_t *map_q3phs = (q3dvis_t *)map_hearability;
static int numbrushes;
static q2cbrush_t map_brushes[MAX_Q2MAP_BRUSHES];
int numentitychars;
char *map_entitystring;
static int numvisibility;
static qbyte map_visibility[MAX_Q2MAP_VISIBILITY];
static q2dvis_t *map_q2vis = (q2dvis_t *)map_visibility;
static q3dvis_t *map_q3pvs = (q3dvis_t *)map_visibility;
static qbyte map_hearability[MAX_Q2MAP_VISIBILITY];
static q3dvis_t *map_q3phs = (q3dvis_t *)map_hearability;
int numareas = 1;
q2carea_t map_q2areas[MAX_Q2MAP_AREAS];
q3carea_t map_q3areas[MAX_CM_AREAS];
static int numentitychars;
static char *map_entitystring;
int numareaportals;
q2dareaportal_t map_areaportals[MAX_Q2MAP_AREAPORTALS];
static int numareas = 1;
static q2carea_t map_q2areas[MAX_Q2MAP_AREAS];
static q3carea_t map_q3areas[MAX_CM_AREAS];
q3cpatch_t map_patches[MAX_CM_PATCHES];
int numpatches;
static int numareaportals;
static q2dareaportal_t map_areaportals[MAX_Q2MAP_AREAPORTALS];
int map_leafpatches[MAX_CM_LEAFFACES];
int numleafpatches;
static q3cpatch_t map_patches[MAX_CM_PATCHES];
static int numpatches;
int numclusters = 1;
static int map_leafpatches[MAX_CM_LEAFFACES];
static int numleafpatches;
q2mapsurface_t nullsurface;
static int numclusters = 1;
int floodvalid;
static q2mapsurface_t nullsurface;
qbyte portalopen[MAX_Q2MAP_AREAPORTALS]; //memset will work if it's a qbyte, really it should be a qboolean
static int floodvalid;
static qbyte portalopen[MAX_Q2MAP_AREAPORTALS]; //memset will work if it's a qbyte, really it should be a qboolean
static int mapisq3;
@ -336,42 +339,33 @@ cvar_t map_autoopenportals = SCVAR("map_autoopenportals", "1"); //1 for lack of
cvar_t r_subdivisions = SCVAR("r_subdivisions", "2");
int CM_NumInlineModels (model_t *model);
q2cmodel_t *CM_InlineModel (char *name);
cmodel_t *CM_InlineModel (char *name);
void CM_InitBoxHull (void);
void FloodAreaConnections (void);
int c_pointcontents;
int c_traces, c_brush_traces;
static int c_pointcontents;
static int c_traces, c_brush_traces;
vecV_t *map_verts; //3points
int numvertexes;
static vecV_t *map_verts; //3points
static int numvertexes;
vec2_t *map_vertstmexcoords;
vec2_t *map_vertlstmexcoords;
vec4_t *map_colors4f_array;
vec3_t *map_normals_array;
vec3_t *map_svector_array;
vec3_t *map_tvector_array;
typedef struct {
char shader[MAX_QPATH];
int brushNum;
int visibleSide; // the brush side that ray tests need to clip against (-1 == none)
} dfog_t;
mfog_t *map_fogs;
int map_numfogs;
static vec2_t *map_vertstmexcoords;
static vec2_t *map_vertlstmexcoords;
static vec4_t *map_colors4f_array;
static vec3_t *map_normals_array;
static vec3_t *map_svector_array;
static vec3_t *map_tvector_array;
q3cface_t *map_faces;
int numfaces;
static int numfaces;
index_t *map_surfindexes;
int map_numsurfindexes;
static index_t *map_surfindexes;
static int map_numsurfindexes;
int *map_leaffaces;
int numleaffaces;
static int *map_leaffaces;
static int numleaffaces;
@ -1016,7 +1010,7 @@ CMod_LoadSubmodels
qboolean CMod_LoadSubmodels (lump_t *l)
{
q2dmodel_t *in;
q2cmodel_t *out;
cmodel_t *out;
int i, j, count;
in = (void *)(cmod_base + l->fileofs);
@ -1924,7 +1918,7 @@ qboolean CModQ3_LoadMarksurfaces (lump_t *l)
qboolean CModQ3_LoadSubmodels (lump_t *l)
{
q3dmodel_t *in;
q2cmodel_t *out;
cmodel_t *out;
int i, j, count;
int *leafbrush;
mleaf_t *bleaf;
@ -3567,7 +3561,7 @@ CM_LoadMap
Loads in the map and all submodels
==================
*/
q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *checksum)
cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *checksum)
{
unsigned *buf;
int i,j;
@ -3874,7 +3868,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned
#ifndef SERVERONLY
noerrors = noerrors && CMod_LoadTexInfo (&header.lumps[Q2LUMP_TEXINFO]);
noerrors = noerrors && CMod_LoadFaces (&header.lumps[Q2LUMP_FACES]);
noerrors = noerrors && RMod_LoadMarksurfaces (&header.lumps[Q2LUMP_LEAFFACES]);
noerrors = noerrors && RMod_LoadMarksurfaces (&header.lumps[Q2LUMP_LEAFFACES], false);
#endif
noerrors = noerrors && CMod_LoadVisibility (&header.lumps[Q2LUMP_VISIBILITY]);
noerrors = noerrors && CMod_LoadBrushes (&header.lumps[Q2LUMP_BRUSHES]);
@ -3945,7 +3939,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned
for (i=1 ; i< loadmodel->numsubmodels ; i++)
{
q2cmodel_t *bm;
cmodel_t *bm;
char name[10];
@ -3988,7 +3982,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned
CM_InlineModel
==================
*/
q2cmodel_t *CM_InlineModel (char *name)
cmodel_t *CM_InlineModel (char *name)
{
int num;

View File

@ -915,6 +915,13 @@ void Matrix4_Multiply(const float *a, const float *b, float *out)
out[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
}
void Matrix3x4_RM_Transform3(const float *matrix, const float *vector, float *product)
{
product[0] = matrix[0]*vector[0] + matrix[1]*vector[1] + matrix[2]*vector[2] + matrix[3];
product[1] = matrix[4]*vector[0] + matrix[5]*vector[1] + matrix[6]*vector[2] + matrix[7];
product[2] = matrix[8]*vector[0] + matrix[9]*vector[1] + matrix[10]*vector[2] + matrix[11];
}
//transform 4d vector by a 4d matrix.
void Matrix4x4_CM_Transform4(const float *matrix, const float *vector, float *product)
{

View File

@ -161,6 +161,7 @@ void Matrix4x4_CM_UnProject (const vec3_t in, vec3_t out, const vec3_t viewangl
void Matrix3x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]);
void Matrix4x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]);
void Matrix3x4_RM_ToVectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]);
void Matrix3x4_RM_Transform3(const float *matrix, const float *vector, float *product);
float *Matrix4x4_CM_NewRotation(float a, float x, float y, float z);
float *Matrix4x4_CM_NewTranslation(float x, float y, float z);

View File

@ -74,6 +74,7 @@ extern cvar_t sv_port_ipx;
extern cvar_t sv_port_tcp;
extern cvar_t sv_port_tcp6;
#endif
cvar_t net_hybriddualstack = CVAR("net_hybriddualstack", "1");
extern cvar_t sv_public, sv_listen_qw, sv_listen_nq, sv_listen_dp, sv_listen_q3;
@ -387,6 +388,27 @@ char *NET_AdrToString (char *s, int len, netadr_t a)
#ifdef IPPROTO_IPV6
case NA_BROADCAST_IP6:
case NA_IPV6:
if (!*(int*)&a.address.ip6[0] &&
!*(int*)&a.address.ip6[4] &&
!*(short*)&a.address.ip6[8] &&
*(short*)&a.address.ip6[10] == (short)0xffff)
{
if (a.port)
snprintf (s, len, "%i.%i.%i.%i:%i",
a.address.ip6[12],
a.address.ip6[13],
a.address.ip6[14],
a.address.ip6[15],
ntohs(a.port));
else
snprintf (s, len, "%i.%i.%i.%i",
a.address.ip6[12],
a.address.ip6[13],
a.address.ip6[14],
a.address.ip6[15]);
break;
}
*s = 0;
doneblank = false;
p = s;
@ -450,7 +472,7 @@ char *NET_AdrToString (char *s, int len, netadr_t a)
break;
#endif
case NA_LOOPBACK:
snprintf (s, len, "LocalHost");
snprintf (s, len, "QLoopBack");
break;
#ifdef IRCCONNECT
@ -488,6 +510,18 @@ char *NET_BaseAdrToString (char *s, int len, netadr_t a)
#ifdef IPPROTO_IPV6
case NA_BROADCAST_IP6:
case NA_IPV6:
if (!*(int*)&a.address.ip6[0] &&
!*(int*)&a.address.ip6[4] &&
!*(short*)&a.address.ip6[8] &&
*(short*)&a.address.ip6[10] == (short)0xffff)
{
snprintf (s, len, "%i.%i.%i.%i",
a.address.ip6[12],
a.address.ip6[13],
a.address.ip6[14],
a.address.ip6[15]);
break;
}
*s = 0;
doneblank = false;
p = s;
@ -1478,41 +1512,95 @@ int FTENET_Generic_GetLocalAddress(ftenet_generic_connection_t *con, netadr_t *o
memset(&adr, 0, sizeof(adr));
SockadrToNetadr(&from, &adr);
for (b = 0; b < sizeof(adr.address); b++)
if (((unsigned char*)&adr.address)[b] != 0)
break;
if (adr.type == NA_IPV6 &&
!*(int*)&adr.address.ip6[0] &&
!*(int*)&adr.address.ip6[4] &&
!*(short*)&adr.address.ip6[8] &&
*(short*)&adr.address.ip6[10]==(short)0xffff &&
!*(int*)&adr.address.ip6[12])
{
/*ipv4-mapped address ANY, pretend we read blank*/
b = sizeof(adr.address);
}
else
{
for (b = 0; b < sizeof(adr.address); b++)
if (((unsigned char*)&adr.address)[b] != 0)
break;
}
if (b == sizeof(adr.address))
{
gethostname(adrs, sizeof(adrs));
h = gethostbyname(adrs);
b = 0;
if(h && h->h_addrtype == AF_INET)
{
for (b = 0; h->h_addr_list[b]; b++)
{
memcpy(&((struct sockaddr_in*)&from)->sin_addr, h->h_addr_list[b], sizeof(((struct sockaddr_in*)&from)->sin_addr));
SockadrToNetadr(&from, &adr);
if (idx++ == count)
*out = adr;
}
}
#ifdef IPPROTO_IPV6
else if(h && h->h_addrtype == AF_INET6)
if (pgetaddrinfo)
{
for (b = 0; h->h_addr_list[b]; b++)
struct addrinfo hints, *result, *itr;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = ((struct sockaddr_in*)&from)->sin_family; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
if (pgetaddrinfo(adrs, NULL, &hints, &result) != 0)
{
memcpy(&((struct sockaddr_in6*)&from)->sin6_addr, h->h_addr_list[b], sizeof(((struct sockaddr_in6*)&from)->sin6_addr));
SockadrToNetadr(&from, &adr);
if (idx++ == count)
*out = adr;
}
}
#endif
else
{
for (itr = result; itr; itr = itr->ai_next)
{
if (idx++ == count)
{
SockadrToNetadr((struct sockaddr_qstorage*)itr->ai_addr, out);
out->port = ((struct sockaddr_in*)&from)->sin_port;
}
}
pfreeaddrinfo(result);
if (b == 0)
/*if none found, fill in the 0.0.0.0 or whatever*/
if (!idx)
{
idx++;
*out = adr;
}
}
}
else
#endif
{
if (idx++ == count)
*out = adr;
h = gethostbyname(adrs);
b = 0;
if(h && h->h_addrtype == AF_INET)
{
for (b = 0; h->h_addr_list[b]; b++)
{
((struct sockaddr_in*)&from)->sin_family = AF_INET;
memcpy(&((struct sockaddr_in*)&from)->sin_addr, h->h_addr_list[b], sizeof(((struct sockaddr_in*)&from)->sin_addr));
SockadrToNetadr(&from, &adr);
if (idx++ == count)
*out = adr;
}
}
#ifdef IPPROTO_IPV6
else if(h && h->h_addrtype == AF_INET6)
{
for (b = 0; h->h_addr_list[b]; b++)
{
((struct sockaddr_in*)&from)->sin_family = AF_INET6;
memcpy(&((struct sockaddr_in6*)&from)->sin6_addr, h->h_addr_list[b], sizeof(((struct sockaddr_in6*)&from)->sin6_addr));
SockadrToNetadr(&from, &adr);
if (idx++ == count)
*out = adr;
}
}
#endif
if (b == 0)
{
if (idx++ == count)
*out = adr;
}
}
}
else
@ -1598,48 +1686,63 @@ qboolean FTENET_Generic_SendPacket(ftenet_generic_connection_t *con, int length,
if (size == FTENET_ADDRTYPES)
return false;
NetadrToSockadr (&to, &addr);
switch(to.type)
{
default:
Con_Printf("Bad address type\n");
break;
#ifdef USEIPX //who uses ipx nowadays anyway?
case NA_BROADCAST_IPX:
case NA_IPX:
size = sizeof(struct sockaddr_ipx);
break;
#endif
case NA_BROADCAST_IP:
case NA_IP:
size = sizeof(struct sockaddr_in);
break;
#ifdef IPPROTO_IPV6
case NA_BROADCAST_IP6:
case NA_IPV6:
/*special code to handle sending to hybrid sockets*/
if (con->addrtype[1] == NA_IPV6 && to.type == NA_IP)
{
memset(&addr, 0, sizeof(struct sockaddr_in6));
((struct sockaddr_in6*)&addr)->sin6_family = AF_INET6;
*(short*)&((struct sockaddr_in6*)&addr)->sin6_addr.s6_addr[10] = 0xffff;
*(int*)&((struct sockaddr_in6*)&addr)->sin6_addr.s6_addr[12] = *(int*)&to.address.ip;
((struct sockaddr_in6*)&addr)->sin6_port = to.port;
size = sizeof(struct sockaddr_in6);
break;
}
else
#endif
{
NetadrToSockadr (&to, &addr);
switch(to.type)
{
default:
Con_Printf("Bad address type\n");
break;
#ifdef USEIPX //who uses ipx nowadays anyway?
case NA_BROADCAST_IPX:
case NA_IPX:
size = sizeof(struct sockaddr_ipx);
break;
#endif
case NA_BROADCAST_IP:
case NA_IP:
size = sizeof(struct sockaddr_in);
break;
#ifdef IPPROTO_IPV6
case NA_BROADCAST_IP6:
case NA_IPV6:
size = sizeof(struct sockaddr_in6);
break;
#endif
}
}
ret = sendto (con->thesocket, data, length, 0, (struct sockaddr*)&addr, size );
if (ret == -1)
{
int ecode = qerrno;
// wouldblock is silent
if (qerrno == EWOULDBLOCK)
if (ecode == EWOULDBLOCK)
return true;
if (qerrno == ECONNREFUSED)
if (ecode == ECONNREFUSED)
return true;
#ifndef SERVERONLY
if (qerrno == EADDRNOTAVAIL)
Con_DPrintf("NET_SendPacket Warning: %i\n", qerrno);
if (ecode == EADDRNOTAVAIL)
Con_DPrintf("NET_SendPacket Warning: %i\n", ecode);
else
#endif
Con_TPrintf (TL_NETSENDERROR, qerrno);
Con_TPrintf (TL_NETSENDERROR, ecode);
}
return true;
}
@ -1682,7 +1785,7 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
ftenet_generic_connection_t *newcon;
unsigned long _true = true;
int newsocket;
int newsocket = INVALID_SOCKET;
int temp;
netadr_t adr;
struct sockaddr_qstorage qs;
@ -1690,6 +1793,7 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
int port;
int bindtries;
int bufsz;
qboolean hybrid = false;
if (!NET_PortToAdr(adrfamily, address, &adr))
@ -1698,12 +1802,54 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
return NULL; //couldn't resolve the name
}
temp = NetadrToSockadr(&adr, &qs);
family = ((struct sockaddr_in*)&qs)->sin_family;
family = ((struct sockaddr*)&qs)->sa_family;
if ((newsocket = socket (family, SOCK_DGRAM, protocol)) == INVALID_SOCKET)
#ifdef IPV6_V6ONLY
if (isserver && family == AF_INET && net_hybriddualstack.ival && !((struct sockaddr_in*)&qs)->sin_addr.s_addr)
{
return NULL;
unsigned long _false = false;
if ((newsocket = socket (AF_INET6, SOCK_DGRAM, protocol)) != INVALID_SOCKET)
{
if (0 == setsockopt(newsocket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&_false, sizeof(_false)))
{
int ip = ((struct sockaddr_in*)&qs)->sin_addr.s_addr;
int port = ((struct sockaddr_in*)&qs)->sin_port;
ip = ((struct sockaddr_in*)&qs)->sin_addr.s_addr;
memset(&qs, 0, sizeof(struct sockaddr_in6));
((struct sockaddr_in6*)&qs)->sin6_family = AF_INET6;
/*
if (((struct sockaddr_in*)&qs)->sin_addr.s_addr)
{
((struct sockaddr_in6*)&qs)->sin6_addr.s6_addr[10] = 0xff;
((struct sockaddr_in6*)&qs)->sin6_addr.s6_addr[11] = 0xff;
((struct sockaddr_in6*)&qs)->sin6_addr.s6_addr[12] = ((qbyte*)&ip)[0];
((struct sockaddr_in6*)&qs)->sin6_addr.s6_addr[13] = ((qbyte*)&ip)[1];
((struct sockaddr_in6*)&qs)->sin6_addr.s6_addr[14] = ((qbyte*)&ip)[2];
((struct sockaddr_in6*)&qs)->sin6_addr.s6_addr[15] = ((qbyte*)&ip)[3];
}
*/
((struct sockaddr_in6*)&qs)->sin6_port = port;
temp = sizeof(struct sockaddr_in6);
hybrid = true;
}
else
{
/*v6only failed... if the option doesn't exist, chances are this is a hybrid system which doesn't support both simultaneously anyway*/
closesocket(newsocket);
newsocket = INVALID_SOCKET;
}
}
}
#endif
if (newsocket == INVALID_SOCKET)
if ((newsocket = socket (family, SOCK_DGRAM, protocol)) == INVALID_SOCKET)
{
return NULL;
}
if (family == AF_INET6 && !net_hybriddualstack.ival)
setsockopt(newsocket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&_true, sizeof(_true));
bufsz = 1<<18;
setsockopt(newsocket, SOL_SOCKET, SO_RCVBUF, (void*)&bufsz, sizeof(bufsz));
@ -1749,8 +1895,16 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i
newcon->Close = FTENET_Generic_Close;
newcon->islisten = isserver;
newcon->addrtype[0] = adr.type;
newcon->addrtype[1] = NA_INVALID;
if (hybrid)
{
newcon->addrtype[0] = NA_IP;
newcon->addrtype[1] = NA_IPV6;
}
else
{
newcon->addrtype[0] = adr.type;
newcon->addrtype[1] = NA_INVALID;
}
newcon->thesocket = newsocket;
@ -3003,6 +3157,10 @@ int maxport = port + 100;
// }
}
#ifdef IPV6_V6ONLY
setsockopt(newsocket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&_true, sizeof(_true));
#endif
address.sin6_family = AF_INET6;
//ZOID -- check for interface binding option
// if ((i = COM_CheckParm("-ip6")) != 0 && i < com_argc) {
@ -3281,6 +3439,8 @@ void NET_Init (void)
if (r)
Sys_Error ("Winsock initialization failed.");
#endif
Cvar_Register(&net_hybriddualstack, "networking");
}
#ifndef SERVERONLY
void NET_InitClient(void)

View File

@ -62,6 +62,9 @@
};
#endif
#endif
#ifndef IPV6_V6ONLY
#define IPV6_V6ONLY 27
#endif
#if (_MSC_VER >= 1600)
#undef EADDRNOTAVAIL

View File

@ -218,7 +218,16 @@ static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t en
model->funcs.Trace(model, 0, 0, axis, start_l, end_l, player_mins, player_maxs, trace);
}
else
{
for (i = 0; i < 3; i++)
{
if (start_l[i]+player_mins[i] > model->maxs[i] && end_l[i] + player_mins[i] > model->maxs[i])
return false;
if (start_l[i]+player_maxs[i] < model->mins[i] && end_l[i] + player_maxs[i] < model->mins[i])
return false;
}
model->funcs.Trace(model, 0, 0, NULL, start_l, end_l, player_mins, player_maxs, trace);
}
}
else
{

View File

@ -496,15 +496,6 @@ typedef struct {
} pf_fopen_files_t;
pf_fopen_files_t pf_fopen_files[MAX_QC_FILES];
/*only read+append+write are standard frik_file*/
#define FRIK_FILE_READ 0 /*read-only*/
#define FRIK_FILE_APPEND 1 /*append (write-only, but offset begins at end of previous file)*/
#define FRIK_FILE_WRITE 2 /*write-only*/
#define FRIK_FILE_INVALID 3 /*no idea what this is for, presume placeholder*/
#define FRIK_FILE_READNL 4 /*fgets ignores newline chars, returning the entire thing in one lump*/
#define FRIK_FILE_MMAP_READ 5 /*fgets returns a pointer. memory is not guarenteed to be released.*/
#define FRIK_FILE_MMAP_RW 6 /*fgets returns a pointer. file is written upon close. memory is not guarenteed to be released.*/
void QCBUILTIN PF_fopen (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *name = PR_GetStringOfs(prinst, OFS_PARM0);
@ -2012,6 +2003,7 @@ void QCBUILTIN PF_uri_unescape (progfuncs_t *prinst, struct globalvars_s *pr_gl
// uri_get() gets content from an URL and calls a callback "uri_get_callback" with it set as string; an unique ID of the transfer is returned
// returns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string
//float(string uril, float id) uri_get = #513;
void QCBUILTIN PF_uri_get (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
Con_Printf("PF_uri_get: stub\n");
@ -2448,9 +2440,13 @@ void QCBUILTIN PF_externrefcall (progfuncs_t *prinst, struct globalvars_s *pr_gl
{
int progsnum;
func_t f;
int i;
progsnum = G_PROG(OFS_PARM0);
f = G_INT(OFS_PARM1);
for (i = OFS_PARM0; i < OFS_PARM5; i+=3)
VectorCopy(G_VECTOR(i+(2*3)), G_VECTOR(i));
(*prinst->pr_trace)++; //continue debugging.
PR_ExecuteProgram(prinst, f);
}
@ -2483,7 +2479,10 @@ void QCBUILTIN PF_externvalue (progfuncs_t *prinst, struct globalvars_s *pr_glob
G_INT(OFS_RETURN+2) = ((int*)&var->_int)[2];
}
else
G_INT(OFS_RETURN) = 0;
{
n = prinst->FindFunction(prinst, varname, n);
G_INT(OFS_RETURN) = n;
}
}
void QCBUILTIN PF_externcall (progfuncs_t *prinst, struct globalvars_s *pr_globals) //this func calls a function in annother progs (by name)
@ -2628,15 +2627,345 @@ void QCBUILTIN PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals
Cbuf_AddText (str, RESTRICT_INSECURE);
}
void QCBUILTIN PF_calltimeofday (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
date_t date;
func_t f;
f = PR_FindFunction(prinst, "timeofday", PR_ANY);
if (f)
{
SV_TimeOfDay(&date);
G_FLOAT(OFS_PARM0) = (float)date.sec;
G_FLOAT(OFS_PARM1) = (float)date.min;
G_FLOAT(OFS_PARM2) = (float)date.hour;
G_FLOAT(OFS_PARM3) = (float)date.day;
G_FLOAT(OFS_PARM4) = (float)date.mon;
G_FLOAT(OFS_PARM5) = (float)date.year;
G_INT(OFS_PARM6) = (int)PR_TempString(prinst, date.str);
PR_ExecuteProgram(prinst, f);
}
}
void QCBUILTIN PF_sprintf (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char result[1024];
char *fmt = PR_GetStringOfs(prinst, OFS_PARM0);
const char *s, *s0;
char outbuf[4096];
char *o = outbuf, *end = outbuf + sizeof(outbuf), *err;
int argpos = 1;
int width, precision, thisarg, flags;
char formatbuf[16];
char *f;
int isfloat;
static int dummyivec[3] = {0, 0, 0};
static float dummyvec[3] = {0, 0, 0};
char vabuf[1024];
Con_Printf("PF_sprintf: stub\n");
Q_strncpyz(result, fmt, sizeof(result));
#define PRINTF_ALTERNATE 1
#define PRINTF_ZEROPAD 2
#define PRINTF_LEFT 4
#define PRINTF_SPACEPOSITIVE 8
#define PRINTF_SIGNPOSITIVE 16
RETURN_TSTRING(result);
formatbuf[0] = '%';
s = PR_GetStringOfs(prinst, OFS_PARM0);
#define GETARG_FLOAT(a) (((a)>=1 && (a)<*prinst->callargc) ? (G_FLOAT(OFS_PARM0 + 3 * (a))) : 0)
#define GETARG_VECTOR(a) (((a)>=1 && (a)<*prinst->callargc) ? (G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyvec)
#define GETARG_INT(a) (((a)>=1 && (a)<*prinst->callargc) ? (G_INT(OFS_PARM0 + 3 * (a))) : 0)
#define GETARG_INTVECTOR(a) (((a)>=1 && (a)<*prinst->callargc) ? ((int*) G_VECTOR(OFS_PARM0 + 3 * (a))) : dummyivec)
#define GETARG_STRING(a) (((a)>=1 && (a)<*prinst->callargc) ? (PR_GetStringOfs(prinst, OFS_PARM0 + 3 * (a))) : "")
for(;;)
{
s0 = s;
switch(*s)
{
case 0:
goto finished;
case '%':
++s;
if(*s == '%')
goto verbatim;
// complete directive format:
// %3$*1$.*2$ld
width = -1;
precision = -1;
thisarg = -1;
flags = 0;
isfloat = -1;
// is number following?
if(*s >= '0' && *s <= '9')
{
width = strtol(s, &err, 10);
if(!err)
{
Con_Printf("PF_sprintf: bad format string: %s\n", s0);
goto finished;
}
if(*err == '$')
{
thisarg = width;
width = -1;
s = err + 1;
}
else
{
if(*s == '0')
{
flags |= PRINTF_ZEROPAD;
if(width == 0)
width = -1; // it was just a flag
}
s = err;
}
}
if(width < 0)
{
for(;;)
{
switch(*s)
{
case '#': flags |= PRINTF_ALTERNATE; break;
case '0': flags |= PRINTF_ZEROPAD; break;
case '-': flags |= PRINTF_LEFT; break;
case ' ': flags |= PRINTF_SPACEPOSITIVE; break;
case '+': flags |= PRINTF_SIGNPOSITIVE; break;
default:
goto noflags;
}
++s;
}
noflags:
if(*s == '*')
{
++s;
if(*s >= '0' && *s <= '9')
{
width = strtol(s, &err, 10);
if(!err || *err != '$')
{
Con_Printf("PF_sprintf: invalid format string: %s\n", s0);
goto finished;
}
s = err + 1;
}
else
width = argpos++;
width = GETARG_FLOAT(width);
if(width < 0)
{
flags |= PRINTF_LEFT;
width = -width;
}
}
else if(*s >= '0' && *s <= '9')
{
width = strtol(s, &err, 10);
if(!err)
{
Con_Printf("PF_sprintf: invalid format string: %s\n", s0);
goto finished;
}
s = err;
if(width < 0)
{
flags |= PRINTF_LEFT;
width = -width;
}
}
// otherwise width stays -1
}
if(*s == '.')
{
++s;
if(*s == '*')
{
++s;
if(*s >= '0' && *s <= '9')
{
precision = strtol(s, &err, 10);
if(!err || *err != '$')
{
Con_Printf("PF_sprintf: invalid format string: %s\n", s0);
goto finished;
}
s = err + 1;
}
else
precision = argpos++;
precision = GETARG_FLOAT(precision);
}
else if(*s >= '0' && *s <= '9')
{
precision = strtol(s, &err, 10);
if(!err)
{
Con_Printf("PF_sprintf: invalid format string: %s\n", s0);
goto finished;
}
s = err;
}
else
{
Con_Printf("PF_sprintf: invalid format string: %s\n", s0);
goto finished;
}
}
for(;;)
{
switch(*s)
{
case 'h': isfloat = 1; break;
case 'l': isfloat = 0; break;
case 'L': isfloat = 0; break;
case 'j': break;
case 'z': break;
case 't': break;
default:
goto nolength;
}
++s;
}
nolength:
// now s points to the final directive char and is no longer changed
if(isfloat < 0)
{
if(*s == 'i')
isfloat = 0;
else
isfloat = 1;
}
if(thisarg < 0)
thisarg = argpos++;
if(o < end - 1)
{
f = &formatbuf[1];
if(*s != 's' && *s != 'c')
if(flags & PRINTF_ALTERNATE) *f++ = '#';
if(flags & PRINTF_ZEROPAD) *f++ = '0';
if(flags & PRINTF_LEFT) *f++ = '-';
if(flags & PRINTF_SPACEPOSITIVE) *f++ = ' ';
if(flags & PRINTF_SIGNPOSITIVE) *f++ = '+';
*f++ = '*';
if(precision >= 0)
{
*f++ = '.';
*f++ = '*';
}
*f++ = *s;
*f++ = 0;
if(width < 0) // not set
width = 0;
switch(*s)
{
case 'd': case 'i':
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
else
Q_snprintfz(o, end - o, formatbuf, width, precision, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
o += strlen(o);
break;
case 'o': case 'u': case 'x': case 'X':
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
else
Q_snprintfz(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
o += strlen(o);
break;
case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (double) GETARG_FLOAT(thisarg) : (double) GETARG_INT(thisarg)));
else
Q_snprintfz(o, end - o, formatbuf, width, precision, (isfloat ? (double) GETARG_FLOAT(thisarg) : (double) GETARG_INT(thisarg)));
o += strlen(o);
break;
case 'v': case 'V':
f[-2] += 'g' - 'v';
if(precision < 0) // not set
Q_snprintfz(o, end - o, va(vabuf, sizeof(vabuf), "%s %s %s", /* NESTED SPRINTF IS NESTED */ formatbuf, formatbuf, formatbuf),
width, (isfloat ? (double) GETARG_VECTOR(thisarg)[0] : (double) GETARG_INTVECTOR(thisarg)[0]),
width, (isfloat ? (double) GETARG_VECTOR(thisarg)[1] : (double) GETARG_INTVECTOR(thisarg)[1]),
width, (isfloat ? (double) GETARG_VECTOR(thisarg)[2] : (double) GETARG_INTVECTOR(thisarg)[2])
);
else
Q_snprintfz(o, end - o, va(vabuf, sizeof(vabuf), "%s %s %s", /* NESTED SPRINTF IS NESTED */ formatbuf, formatbuf, formatbuf),
width, precision, (isfloat ? (double) GETARG_VECTOR(thisarg)[0] : (double) GETARG_INTVECTOR(thisarg)[0]),
width, precision, (isfloat ? (double) GETARG_VECTOR(thisarg)[1] : (double) GETARG_INTVECTOR(thisarg)[1]),
width, precision, (isfloat ? (double) GETARG_VECTOR(thisarg)[2] : (double) GETARG_INTVECTOR(thisarg)[2])
);
o += strlen(o);
break;
case 'c':
if(flags & PRINTF_ALTERNATE)
{
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
else
Q_snprintfz(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
o += strlen(o);
}
else
{
unsigned int c = (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg));
// char charbuf16[16];
// const char *buf = u8_encodech(c, NULL, charbuf16);
// if(!buf)
// buf = "";
if(precision < 0) // not set
precision = end - o - 1;
// o += u8_strpad(o, end - o, buf, (flags & PRINTF_LEFT) != 0, width, precision);
}
break;
case 's':
if(flags & PRINTF_ALTERNATE)
{
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, GETARG_STRING(thisarg));
else
Q_snprintfz(o, end - o, formatbuf, width, precision, GETARG_STRING(thisarg));
o += strlen(o);
}
else
{
if(precision < 0) // not set
precision = end - o - 1;
// o += u8_strpad(o, end - o, GETARG_STRING(thisarg), (flags & PRINTF_LEFT) != 0, width, precision);
}
break;
default:
Con_Printf("PF_sprintf: invalid format string: %s\n", s0);
goto finished;
}
}
++s;
break;
default:
verbatim:
if(o < end - 1)
*o++ = *s++;
break;
}
}
finished:
*o = 0;
RETURN_TSTRING(outbuf);
}
#define DEF_SAVEGLOBAL (1u<<15)
@ -2812,7 +3141,7 @@ lh_extension_t QSG_Extensions[] = {
{"DP_QC_COPYENTITY", 1, NULL, {"copyentity"}},
{"DP_QC_CRC16", 1, NULL, {"crc16"}},
{"DP_QC_CVAR_DEFSTRING", 1, NULL, {"cvar_defstring"}},
{"DP_QC_CVAR_STRING", 1, NULL, {"dp_cvar_string"}}, //448 builtin.
{"DP_QC_CVAR_STRING", 1, NULL, {"cvar_string"}}, //448 builtin.
{"DP_QC_CVAR_TYPE", 1, NULL, {"cvar_type"}},
{"DP_QC_EDICT_NUM", 1, NULL, {"edict_num"}},
{"DP_QC_ENTITYDATA", 5, NULL, {"numentityfields", "entityfieldname", "entityfieldtype", "getentityfieldstring", "putentityfieldstring"}},

View File

@ -34,7 +34,6 @@ struct wedict_s
#ifdef USEODE
entityode_t ode;
#endif
qbyte solidtype;
/*the above is shared with ssqc*/
};
@ -175,7 +174,8 @@ void PR_AutoCvarSetup(progfuncs_t *prinst);
void PR_AutoCvar(progfuncs_t *prinst, cvar_t *var);
void QCBUILTIN PF_skel_mmap(progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_ragedit(progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_build (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_get_numbones (progfuncs_t *prinst, struct globalvars_s *pr_globals);
@ -279,6 +279,8 @@ void QCBUILTIN PF_bufstr_add (progfuncs_t *prinst, struct globalvars_s *pr_glob
void QCBUILTIN PF_bufstr_free (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_buf_cvarlist (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_calltimeofday (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_whichpack (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_fclose_progs (progfuncs_t *prinst);
@ -314,7 +316,7 @@ void QCBUILTIN PF_ForceInfoKey(progfuncs_t *prinst, struct globalvars_s *pr_glob
void QCBUILTIN PF_precache_vwep_model(progfuncs_t *prinst, struct globalvars_s *pr_globals);
int PF_checkclient_Internal (progfuncs_t *prinst);
void PF_precache_sound_Internal (progfuncs_t *prinst, char *s);
int PF_precache_model_Internal (progfuncs_t *prinst, char *s);
int PF_precache_model_Internal (progfuncs_t *prinst, char *s, qboolean queryonly);
void PF_setmodel_Internal (progfuncs_t *prinst, edict_t *e, char *m);
char *PF_infokey_Internal (int entnum, char *value);
void PF_centerprint_Internal (int entnum, qboolean plaque, char *s);
@ -391,6 +393,77 @@ pbool ED_CanFree (edict_t *ed);
//shared constants
typedef enum
{
VF_MIN = 1,
VF_MIN_X = 2,
VF_MIN_Y = 3,
VF_SIZE = 4,
VF_SIZE_X = 5,
VF_SIZE_Y = 6,
VF_VIEWPORT = 7,
VF_FOV = 8,
VF_FOVX = 9,
VF_FOVY = 10,
VF_ORIGIN = 11,
VF_ORIGIN_X = 12,
VF_ORIGIN_Y = 13,
VF_ORIGIN_Z = 14,
VF_ANGLES = 15,
VF_ANGLES_X = 16,
VF_ANGLES_Y = 17,
VF_ANGLES_Z = 18,
VF_DRAWWORLD = 19,
VF_ENGINESBAR = 20,
VF_DRAWCROSSHAIR = 21,
VF_CARTESIAN_ANGLES = 22,
//this is a DP-compatibility hack.
VF_CL_VIEWANGLES_V = 33,
VF_CL_VIEWANGLES_X = 34,
VF_CL_VIEWANGLES_Y = 35,
VF_CL_VIEWANGLES_Z = 36,
//33-36 used by DP...
VF_PERSPECTIVE = 200,
//201 used by DP... WTF? CLEARSCREEN
VF_LPLAYER = 202,
VF_AFOV = 203, //aproximate fov (match what the engine would normally use for the fov cvar). p0=fov, p1=zoom
} viewflags;
/*FIXME: this should be changed*/
#define CSQC_API_VERSION 1.0f
#define CSQCRF_VIEWMODEL 1 //Not drawn in mirrors
#define CSQCRF_EXTERNALMODEL 2 //drawn ONLY in mirrors
#define CSQCRF_DEPTHHACK 4 //fun depthhack
#define CSQCRF_ADDITIVE 8 //add instead of blend
#define CSQCRF_USEAXIS 16 //use v_forward/v_right/v_up as an axis/matrix - predraw is needed to use this properly
#define CSQCRF_NOSHADOW 32 //don't cast shadows upon other entities (can still be self shadowing, if the engine wishes, and not additive)
#define CSQCRF_FRAMETIMESARESTARTTIMES 64 //EXT_CSQC_1: frame times should be read as (time-frametime).
#define CSQCRF_NOAUTOADD 128 //EXT_CSQC_1: don't automatically add after predraw was called
/*only read+append+write are standard frik_file*/
#define FRIK_FILE_READ 0 /*read-only*/
#define FRIK_FILE_APPEND 1 /*append (write-only, but offset begins at end of previous file)*/
#define FRIK_FILE_WRITE 2 /*write-only*/
#define FRIK_FILE_INVALID 3 /*no idea what this is for, presume placeholder*/
#define FRIK_FILE_READNL 4 /*fgets ignores newline chars, returning the entire thing in one lump*/
#define FRIK_FILE_MMAP_READ 5 /*fgets returns a pointer. memory is not guarenteed to be released.*/
#define FRIK_FILE_MMAP_RW 6 /*fgets returns a pointer. file is written upon close. memory is not guarenteed to be released.*/
#define MASK_DELTA 1
#define MASK_STDVIEWMODEL 2
enum lightfield_e
{
lfield_origin=0,
lfield_colour=1,
lfield_radius=2,
lfield_flags=3,
lfield_style=4,
lfield_angles=5,
lfield_fov=6
};

View File

@ -112,6 +112,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PORT_Q2CLIENT 27901
#define PORT_Q2SERVER 27910
//hexen2: 26900
//=========================================
// out of band message id bytes

View File

@ -64,7 +64,7 @@ typedef struct trace_s
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
cplane_t plane; // surface normal at impact
q2csurface_t *surface; // surface hit
q2csurface_t *surface; // q2-compat surface hit
int contents; // contents on other side of surface hit
void *ent; // not set by CM_*() functions
//AND THIS LINE

View File

@ -5,7 +5,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj
{0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake_SDL", "ftequake_SDL.vcproj", "{F384725A-62D4-4063-9941-6D8D2D6C2A47}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake_SDL.vcproj", "{F384725A-62D4-4063-9941-6D8D2D6C2A47}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npfte", "npfte.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}"
ProjectSection(ProjectDependencies) = postProject
@ -18,8 +18,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "botlib", "botlib.vcproj", "
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fteqcc", "..\qclib\dotnet2005\qcc.vcproj", "{2866F783-6B44-4655-A38D-D53874037454}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "axfte", "axfte.vcproj", "{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtvprox", "..\..\fteqtv\dotnet2005\qtvprox.vcproj", "{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}"
EndProject
Global
@ -101,10 +99,12 @@ Global
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.D3DDebug|x64.ActiveCfg = D3DDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.D3DRelease|Win32.ActiveCfg = D3DDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.D3DRelease|x64.ActiveCfg = D3DDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug Dedicated Server|Win32.ActiveCfg = Debug Dedicated Server SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug Dedicated Server|x64.ActiveCfg = Debug Dedicated Server SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug|Win32.ActiveCfg = Debug Dedicated Server SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug|x64.ActiveCfg = Debug Dedicated Server SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug Dedicated Server|Win32.ActiveCfg = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug Dedicated Server|x64.ActiveCfg = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug Dedicated Server|x64.Build.0 = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug|Win32.ActiveCfg = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug|x64.ActiveCfg = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug|x64.Build.0 = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.GLDebug|Win32.ActiveCfg = GLDebug_SDL|Win32
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.GLDebug|Win32.Build.0 = GLDebug_SDL|Win32
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.GLDebug|x64.ActiveCfg = GLDebug_SDL|x64
@ -118,10 +118,12 @@ Global
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MinGLRelease|x64.ActiveCfg = MinGLRelease_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MRelease|Win32.ActiveCfg = MRelease_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MRelease|x64.ActiveCfg = MRelease_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release Dedicated Server|Win32.ActiveCfg = Release Dedicated Server SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release Dedicated Server|x64.ActiveCfg = Release Dedicated Server SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release|Win32.ActiveCfg = Release Dedicated Server SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release|x64.ActiveCfg = Release Dedicated Server SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release Dedicated Server|Win32.ActiveCfg = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release Dedicated Server|x64.ActiveCfg = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release Dedicated Server|x64.Build.0 = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release|Win32.ActiveCfg = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release|x64.ActiveCfg = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release|x64.Build.0 = Release Dedicated Server_SDL|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|Win32.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|x64.Build.0 = GLRelease|x64
@ -258,52 +260,6 @@ Global
{2866F783-6B44-4655-A38D-D53874037454}.Release|Win32.ActiveCfg = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.Release|Win32.Build.0 = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.Release|x64.ActiveCfg = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.D3DDebug|Win32.Build.0 = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.D3DDebug|x64.ActiveCfg = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.D3DDebug|x64.Build.0 = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.D3DRelease|Win32.ActiveCfg = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.D3DRelease|Win32.Build.0 = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.D3DRelease|x64.ActiveCfg = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.D3DRelease|x64.Build.0 = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Debug Dedicated Server|x64.ActiveCfg = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Debug Dedicated Server|x64.Build.0 = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Debug|Win32.ActiveCfg = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Debug|Win32.Build.0 = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Debug|x64.ActiveCfg = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Debug|x64.Build.0 = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.GLDebug|Win32.ActiveCfg = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.GLDebug|Win32.Build.0 = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.GLDebug|x64.ActiveCfg = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.GLDebug|x64.Build.0 = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.GLRelease|Win32.ActiveCfg = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.GLRelease|Win32.Build.0 = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.GLRelease|x64.ActiveCfg = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.GLRelease|x64.Build.0 = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MDebug|Win32.ActiveCfg = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MDebug|Win32.Build.0 = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MDebug|x64.ActiveCfg = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MDebug|x64.Build.0 = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MinGLDebug|Win32.ActiveCfg = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MinGLDebug|Win32.Build.0 = Debug|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MinGLDebug|x64.ActiveCfg = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MinGLDebug|x64.Build.0 = Debug|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MinGLRelease|Win32.ActiveCfg = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MinGLRelease|Win32.Build.0 = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MinGLRelease|x64.ActiveCfg = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MinGLRelease|x64.Build.0 = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MRelease|Win32.ActiveCfg = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MRelease|Win32.Build.0 = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MRelease|x64.ActiveCfg = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.MRelease|x64.Build.0 = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Release Dedicated Server|x64.ActiveCfg = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Release Dedicated Server|x64.Build.0 = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Release|Win32.ActiveCfg = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Release|Win32.Build.0 = Release|Win32
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Release|x64.ActiveCfg = Release|x64
{E27271B3-4E6F-4F53-86FF-2BCBB6BA4D01}.Release|x64.Build.0 = Release|x64
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DDebug|Win32.Build.0 = Debug|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DDebug|x64.ActiveCfg = Debug|Win32

View File

@ -495,6 +495,7 @@
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../libs/dxsdk7/lib"
GenerateManifest="false"
IgnoreDefaultLibraryNames="libc.lib;msvcrt.lib"
SubSystem="2"
OptimizeReferences="2"

View File

@ -82,7 +82,6 @@
AdditionalDependencies="comctl32.lib wsock32.lib winmm.lib odbc32.lib odbccp32.lib"
OutputFile="../../npfte_dbg.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../libs/dxsdk7/lib"
GenerateManifest="false"
IgnoreDefaultLibraryNames="libc.lib;msvcrt.lib"
@ -90,7 +89,6 @@
GenerateDebugInformation="true"
GenerateMapFile="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"

View File

@ -1,5 +1,3 @@
LIBRARY npfte.dll
EXPORTS
;npapi
NP_GetEntryPoints

View File

@ -324,6 +324,9 @@ struct {
qboolean initedspotpasses;
const shader_t *spotpassshader;
const shader_t *crepskyshader;
const shader_t *crepopaqueshader;
qboolean initeddepthnorm;
const shader_t *depthnormshader;
texid_t tex_normals;
@ -901,6 +904,8 @@ static void T_Gen_CurrentRender(int tmu)
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolean useclientarray)
@ -2417,13 +2422,13 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned
case SP_ATTR_COLOUR:
if (shaderstate.sourcevbo->colours4f)
{
GL_SelectVBO(shaderstate.curvertexvbo);
GL_SelectVBO(shaderstate.sourcevbo->vbocolours);
qglVertexAttribPointer(p->handle[perm], 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->colours4f);
return 1u<<p->handle[perm];
}
else if (shaderstate.sourcevbo->colours4ub)
{
GL_SelectVBO(shaderstate.curvertexvbo);
GL_SelectVBO(shaderstate.sourcevbo->vbocolours);
qglVertexAttribPointer(p->handle[perm], 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(byte_vec4_t), shaderstate.sourcevbo->colours4ub);
return 1u<<p->handle[perm];
}
@ -2555,6 +2560,27 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned
qglUniform3fvARB(p->handle[perm], 1, param3);
break;
case SP_LIGHTSCREEN:
{
float v[4], tempv[4];
float out[3];
v[0] = shaderstate.lightorg[0];
v[1] = shaderstate.lightorg[1];
v[2] = shaderstate.lightorg[2];
v[3] = 1;
Matrix4x4_CM_Transform4(shaderstate.modelviewmatrix, v, tempv);
Matrix4x4_CM_Transform4(r_refdef.m_projection, tempv, v);
v[3] *= 2;
v[0] = (v[0]/v[3]) + 0.5;
v[1] = (v[1]/v[3]) + 0.5;
v[2] = (v[2]/v[3]) + 0.5;
qglUniform3fvARB(p->handle[perm], 1, v);
}
break;
case SP_LIGHTRADIUS:
qglUniform1fARB(p->handle[perm], shaderstate.lightradius);
break;
@ -2793,6 +2819,7 @@ void GLBE_SelectMode(backendmode_t mode)
//we don't write or blend anything (maybe alpha test... but mneh)
BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHCLOSERONLY | SBITS_MASK_BITS);
GL_CullFace(0);
//don't change cull stuff, and
//don't actually change stencil stuff - caller needs to be
@ -2822,6 +2849,31 @@ void GLBE_SelectMode(backendmode_t mode)
shaderstate.lightpassshader = R_RegisterCustom("lightpass", Shader_LightPass_Std, NULL);
}
break;
case BEM_CREPUSCULAR:
if (!shaderstate.crepopaqueshader)
{
shaderstate.crepopaqueshader = R_RegisterShader("crepuscular_opaque",
"{\n"
"program crepuscular_opaque\n"
"}\n"
);
}
if (!shaderstate.crepskyshader)
{
shaderstate.crepskyshader = R_RegisterShader("crepuscular_sky",
"{\n"
"program crepuscular_sky\n"
"{\n"
"map $diffuse\n"
"}\n"
"{\n"
"map $fullbright\n"
"}\n"
"}\n"
);
}
break;
#endif
case BEM_FOG:
while(shaderstate.lastpasstmus>0)
@ -2989,6 +3041,12 @@ static void DrawMeshes(void)
BE_RenderMeshProgram(shaderstate.depthnormshader, shaderstate.depthnormshader->passes);
break;
#endif
case BEM_CREPUSCULAR:
if (shaderstate.curshader->flags & SHADER_SKY)
BE_RenderMeshProgram(shaderstate.crepskyshader, shaderstate.crepskyshader->passes);
else
BE_RenderMeshProgram(shaderstate.crepopaqueshader, shaderstate.crepopaqueshader->passes);
break;
case BEM_DEPTHONLY:
GL_DeSelectProgram();
#ifdef warningmsg
@ -3265,7 +3323,7 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist)
continue;
}
}
else if (shaderstate.mode != BEM_FOG)
else if (shaderstate.mode != BEM_FOG && shaderstate.mode != BEM_CREPUSCULAR)
continue;
}
@ -3273,7 +3331,7 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist)
}
}
static void GLBE_SubmitMeshes (qboolean drawworld, batch_t **blist, int start, int stop)
void GLBE_SubmitMeshes (qboolean drawworld, batch_t **blist, int start, int stop)
{
model_t *model = cl.worldmodel;
int i;
@ -3489,7 +3547,7 @@ void GLBE_DrawLightPrePass(qbyte *vis, batch_t **batches)
#ifdef RTLIGHTS
/*regular lighting now*/
BE_SelectEntity(&r_worldentity);
Sh_DrawLights(vis);
Sh_DrawLights(vis, batches);
#endif
shaderstate.tex_sourcecol = r_nulltex;
@ -3571,7 +3629,7 @@ void GLBE_DrawWorld (qbyte *vis)
#ifdef RTLIGHTS
RSpeedRemark();
BE_SelectEntity(&r_worldentity);
Sh_DrawLights(vis);
Sh_DrawLights(vis, batches);
RSpeedEnd(RSPEED_STENCILSHADOWS);
#endif

View File

@ -1683,7 +1683,7 @@ void GL_UploadBump(qbyte *data, int width, int height, qboolean mipmap, float bu
miplevel = 0;
while (scaled_width > 1 || scaled_height > 1)
{
GL_MipMapNormal(nmap,scaled_width,scaled_height);
GL_MipMap(nmap,scaled_width,scaled_height);
//GL_MipMapGray((qbyte *)scaled, scaled_width, scaled_height);
scaled_width >>= 1;
scaled_height >>= 1;

View File

@ -59,7 +59,6 @@ void GL_DrawHeightmapModel (batch_t **batches, entity_t *e)
heightmap_t *hm = m->terrain;
mesh_t *mesh;
batch_t *b;
vbo_t *vbo;
if (e->model == cl.worldmodel)
{

View File

@ -713,6 +713,7 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash)
case 30: //hl
case 29: //q1
case 28: //prerel
case BSPVERSION_LONG:
if (!RMod_LoadBrushModel (mod, buf))
continue;
break;
@ -2206,7 +2207,7 @@ qboolean RMod_LoadNodes (lump_t *l, qboolean lm)
for (j=0 ; j<2 ; j++)
{
p = LittleShort (in->children[j]);
p = LittleLong (in->children[j]);
if (p >= 0)
out->children[j] = loadmodel->nodes + p;
else
@ -2470,7 +2471,7 @@ Mod_LoadClipnodes
qboolean RMod_LoadClipnodes (lump_t *l, qboolean lm)
{
dsclipnode_t *ins;
dsclipnode_t *inl;
dlclipnode_t *inl;
mclipnode_t *out;
int i, count;
hull_t *hull;
@ -2753,33 +2754,62 @@ void RMod_MakeHull0 (void)
Mod_LoadMarksurfaces
=================
*/
qboolean RMod_LoadMarksurfaces (lump_t *l)
qboolean RMod_LoadMarksurfaces (lump_t *l, qboolean lm)
{
int i, j, count;
short *in;
msurface_t **out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->marksurfaces = out;
loadmodel->nummarksurfaces = count;
for ( i=0 ; i<count ; i++)
if (lm)
{
j = (unsigned short)LittleShort(in[i]);
if (j >= loadmodel->numsurfaces)
int *inl;
inl = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*inl))
{
Con_Printf (CON_ERROR "Mod_ParseMarksurfaces: bad surface number\n");
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
out[i] = loadmodel->surfaces + j;
count = l->filelen / sizeof(*inl);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->marksurfaces = out;
loadmodel->nummarksurfaces = count;
for ( i=0 ; i<count ; i++)
{
j = (unsigned int)LittleLong(inl[i]);
if (j >= loadmodel->numsurfaces)
{
Con_Printf (CON_ERROR "Mod_ParseMarksurfaces: bad surface number\n");
return false;
}
out[i] = loadmodel->surfaces + j;
}
}
else
{
short *ins;
ins = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*ins))
{
Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name);
return false;
}
count = l->filelen / sizeof(*ins);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->marksurfaces = out;
loadmodel->nummarksurfaces = count;
for ( i=0 ; i<count ; i++)
{
j = (unsigned short)LittleShort(ins[i]);
if (j >= loadmodel->numsurfaces)
{
Con_Printf (CON_ERROR "Mod_ParseMarksurfaces: bad surface number\n");
return false;
}
out[i] = loadmodel->surfaces + j;
}
}
return true;
@ -3186,7 +3216,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
noerrors = noerrors && RMod_LoadFaces (&header->lumps[LUMP_FACES], longm);
}
if (!isDedicated)
noerrors = noerrors && RMod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
noerrors = noerrors && RMod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES], longm);
if (noerrors)
RMod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
noerrors = noerrors && RMod_LoadLeafs (&header->lumps[LUMP_LEAFS], longm);

View File

@ -324,8 +324,7 @@ typedef struct
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
unsigned short v[2];
unsigned int cachededgeoffset;
unsigned int v[2];
} medge_t;
typedef struct mtexinfo_s
@ -426,8 +425,8 @@ typedef struct mnode_s
int childnum[2];
#endif
unsigned short firstsurface;
unsigned short numsurfaces;
unsigned int firstsurface;
unsigned int numsurfaces;
} mnode_t;

View File

@ -393,6 +393,8 @@ void R_PushDlights (void)
return;
currentmodel = cl.worldmodel;
if (!currentmodel->funcs.MarkLights)
return;
l = cl_dlights+rtlights_first;
for (i=rtlights_first ; i <= DL_LAST ; i++, l++)

View File

@ -32,7 +32,7 @@ void R_RenderBrushPoly (msurface_t *fa);
#define PROJECTION_DISTANCE 200
#define MAX_STENCIL_ENTS 128
extern int gl_canstencil;
extern int gl_stencilbits;
FTEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB;
FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB;
@ -298,7 +298,7 @@ void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const mod
VectorScale((m+4), 2, (m+4));
VectorScale((m+8), 2, (m+8));
}
if (mod && !ruleset_allow_larger_models.ival && mod->clampscale != 1)
if (mod && !ruleset_allow_larger_models.ival && mod->clampscale != 1 && mod->type == mod_alias)
{ //possibly this should be on a per-frame basis, but that's a real pain to do
Con_DPrintf("Rescaling %s by %f\n", mod->name, mod->clampscale);
VectorScale((m+0), mod->clampscale, (m+0));
@ -389,7 +389,7 @@ void R_SetupGL (void)
stencilshadows |= r_shadow_realtime_world.ival && r_shadow_realtime_world_shadows.ival;
#endif
if ((!stencilshadows || !gl_canstencil) && gl_maxdist.value>=100)//gl_nv_range_clamp)
if ((!stencilshadows || !gl_stencilbits) && gl_maxdist.value>=100)//gl_nv_range_clamp)
{
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
// yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect;
@ -397,10 +397,16 @@ void R_SetupGL (void)
// MYgluPerspective (yfov, screenaspect, 4, 4096);
Matrix4x4_CM_Projection_Far(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value, gl_maxdist.value);
if (gl_config.arb_depth_clamp)
qglEnable(GL_DEPTH_CLAMP_ARB);
}
else
{
Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value);
if (gl_config.arb_depth_clamp)
qglDisable(GL_DEPTH_CLAMP_ARB);
}
}
else

View File

@ -501,6 +501,14 @@ static void R_ImportRTLights(char *entlump)
lighttype_t type;
float origin[3], angles[3], radius, color[3], light[4], fadescale, lightscale, originhack[3], overridecolor[3], vec[4];
char key[256], value[8192];
int nest;
COM_Parse(entlump);
if (!strcmp(com_token, "Version"))
{
entlump = COM_Parse(entlump);
entlump = COM_Parse(entlump);
}
for (entnum = 0; ;entnum++)
{
@ -522,13 +530,26 @@ static void R_ImportRTLights(char *entlump)
pflags = 0;
effects = 0;
islight = false;
nest = 1;
while (1)
{
entlump = COM_Parse(entlump);
if (!entlump)
break; // error
if (com_token[0] == '{')
{
nest++;
continue;
}
if (com_token[0] == '}')
break; // end of entity
{
nest--;
if (!nest)
break; // end of entity
continue;
}
if (nest!=1)
continue;
if (com_token[0] == '_')
Q_strncpyz(key, com_token + 1, sizeof(key));
else
@ -656,6 +677,14 @@ static void R_ImportRTLights(char *entlump)
lightscale = atof(value);
else if (!strcmp("fade", key))
fadescale = atof(value);
else if (!strcmp("light_radius", key))
{
light[0] = 1;
light[1] = 1;
light[2] = 1;
light[3] = atof(value);
}
}
if (!islight)
continue;
@ -877,7 +906,7 @@ static void R_SaveRTLights_f(void)
light->style-1,
"", light->corona,
ang[0], ang[1], ang[2],
light->coronascale, light->ambientscale, light->diffusescale, light->specularscale, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE)
light->coronascale, light->ambientscale, light->diffusescale, light->specularscale, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE|LFLAG_CREPUSCULAR)
));
}
VFS_CLOSE(f);

View File

@ -42,7 +42,7 @@ static qboolean shader_reload_needed;
static qboolean shader_rescan_needed;
//cvars that affect shader generation
cvar_t r_vertexlight = SCVAR("r_vertexlight", "0");
cvar_t r_vertexlight = CVARFD("r_vertexlight", "0", CVAR_SHADERSYSTEM, "Hack loaded shaders to remove detail pass and lightmap sampling for faster rendering.");
extern cvar_t r_deluxemapping;
extern cvar_t r_fastturb, r_fastsky, r_skyboxname;
extern cvar_t r_drawflat;
@ -192,6 +192,11 @@ static shadercache_t **shader_hash;
static char shaderbuf[MAX_QPATH * 256];
int shaderbuflen;
static enum {
SPM_DEFAULT, /*quake3/fte internal*/
SPM_DOOM3,
} shaderparsemode;
shader_t *r_shaders;
static hashtable_t shader_active_hash;
void *shader_active_hash_mem;
@ -205,7 +210,7 @@ static qboolean Shader_Parsetok( shader_t *shader, shaderpass_t *pass, shaderkey
static void Shader_ParseFunc( char **args, shaderfunc_t *func );
static void Shader_MakeCache( char *path );
static void Shader_GetPathAndOffset( char *name, char **path, unsigned int *offset );
static void Shader_ReadShader(shader_t *s, char *shadersource);
static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode);
//===========================================================================
@ -548,10 +553,24 @@ static int Shader_SetImageFlags ( shader_t *shader )
static texid_t Shader_FindImage ( char *name, int flags )
{
if (!Q_stricmp (name, "$whiteimage"))
return r_whiteimage;
if (shaderparsemode == SPM_DOOM3)
{
if (!Q_stricmp (name, "_default"))
return r_whiteimage; /*fixme*/
if (!Q_stricmp (name, "_white"))
return r_whiteimage;
if (!Q_stricmp (name, "_black"))
{
int wibuf[16] = {0};
return R_LoadTexture("$blackimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA);;
}
}
else
return R_LoadHiResTexture(name, NULL, flags);
{
if (!Q_stricmp (name, "$whiteimage"))
return r_whiteimage;
}
return R_LoadHiResTexture(name, NULL, flags);
}
@ -1550,7 +1569,102 @@ struct sbuiltin_s
"#endif\n"
},
{QR_OPENGL, 110, "crepuscular_rays",
/*yoinked from http://fabiensanglard.net/lightScattering/index.php*/
"!!cvarf crep_decay\n"
"!!cvarf crep_density\n"
"!!cvarf crep_weight\n"
"varying vec2 tc;\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
"void main ()\n"
"{\n"
"tc = v_texcoord;\n"
"gl_Position = v_position;\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform float cvar_crep_decay;\n"
"uniform float cvar_crep_density;\n"
"uniform float cvar_crep_weight;\n"
"uniform float l_lightcolour;\n"
"uniform vec3 l_lightscreen;\n"
"uniform sampler2D s_t0;\n"
"const int NUM_SAMPLES = 100;\n"
"void main()\n"
"{\n"
// "gl_FragColor = texture2D(s_t0, tc.st);\n"
"vec2 deltaTextCoord = vec2( tc.st - l_lightscreen.xy );\n"
"vec2 textCoo = tc.st;\n"
"deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * cvar_crep_density;\n"
"float illuminationDecay = 1.0;\n"
"for(int i=0; i < NUM_SAMPLES ; i++)\n"
"{\n"
"textCoo -= deltaTextCoord;\n"
"vec4 sample = texture2D(s_t0, textCoo);\n"
"sample *= illuminationDecay * cvar_crep_weight;\n"
"gl_FragColor += sample;\n"
"illuminationDecay *= cvar_crep_decay;\n"
"}\n"
"gl_FragColor *= l_lightcolour;\n"
"}\n"
"#endif\n"
},
{QR_OPENGL, 110, "crepuscular_opaque",
"#ifdef VERTEX_SHADER\n"
"void main ()\n"
"{\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"void main()\n"
"{\n"
"gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
"}\n"
"#endif\n"
},
{QR_OPENGL, 110, "crepuscular_sky",
"#ifdef VERTEX_SHADER\n"
"varying vec3 pos;\n"
"void main ()\n"
"{\n"
" pos = v_position.xyz;\n"
" gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform float e_time;\n"
"uniform vec3 e_eyepos;\n"
"varying vec3 pos;\n"
"uniform sampler2D s_t0;\n"
"uniform sampler2D s_t1;\n"
"void main ()\n"
"{\n"
" vec2 tccoord;\n"
" vec3 dir = pos - e_eyepos;\n"
" dir.z *= 3.0;\n"
" dir.xy /= 0.5*length(dir);\n"
" tccoord = (dir.xy + e_time*0.03125);\n"
" vec3 solid = vec3(texture2D(s_t0, tccoord));\n"
" tccoord = (dir.xy + e_time*0.0625);\n"
" vec4 clouds = texture2D(s_t1, tccoord);\n"
" gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef D3DQUAKE
@ -1839,6 +1953,7 @@ struct shader_field_names_s shader_field_names[] =
{"e_light_ambient", SP_E_L_AMBIENT},
/*rtlight properties, use with caution*/
{"l_lightscreen", SP_LIGHTSCREEN},
{"l_lightradius", SP_LIGHTRADIUS},
{"l_lightcolour", SP_LIGHTCOLOUR},
{"l_lightposition", SP_LIGHTPOSITION},
@ -1868,7 +1983,7 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames)
for (p = 0; cvarfnames[i][p] && (unsigned char)cvarfnames[i][p] > 32 && p < sizeof(tmpname)-1; p++)
tmpname[p] = cvarfnames[i][p];
tmpname[p] = 0;
cvar = Cvar_FindVar(tmpname);
cvar = Cvar_Get(tmpname, "0", CVAR_SHADERSYSTEM, "glsl cvars");
if (!cvar)
continue;
cvar->flags |= CVAR_SHADERSYSTEM;
@ -2911,6 +3026,26 @@ static void Shaderpass_NoLightMap ( shader_t *shader, shaderpass_t *pass, char *
pass->rgbgen = RGB_GEN_IDENTITY;
}
static void Shaderpass_Red(shader_t *shader, shaderpass_t *pass, char **ptr)
{
pass->rgbgen = RGB_GEN_CONST;
pass->rgbgen_func.args[0] = Shader_ParseFloat(ptr);
}
static void Shaderpass_Green(shader_t *shader, shaderpass_t *pass, char **ptr)
{
pass->rgbgen = RGB_GEN_CONST;
pass->rgbgen_func.args[1] = Shader_ParseFloat(ptr);
}
static void Shaderpass_Blue(shader_t *shader, shaderpass_t *pass, char **ptr)
{
pass->rgbgen = RGB_GEN_CONST;
pass->rgbgen_func.args[2] = Shader_ParseFloat(ptr);
}
static void Shaderpass_Alpha(shader_t *shader, shaderpass_t *pass, char **ptr)
{
pass->alphagen = ALPHA_GEN_CONST;
pass->alphagen_func.args[0] = Shader_ParseFloat(ptr);
}
static void Shaderpass_MaskColor(shader_t *shader, shaderpass_t *pass, char **ptr)
{
pass->shaderbits |= SBITS_MASK_RED|SBITS_MASK_GREEN|SBITS_MASK_BLUE;
@ -3007,6 +3142,10 @@ static shaderkey_t shaderpasskeys[] =
{"alphatest", Shaderpass_AlphaTest},
{"texgen", Shaderpass_TexGen},
{"cameracubemap",Shaderpass_CubeMap},
{"red", Shaderpass_Red},
{"green", Shaderpass_Green},
{"blue", Shaderpass_Blue},
{"alpha", Shaderpass_Alpha},
{NULL, NULL}
};
@ -3048,6 +3187,13 @@ void Shader_Free (shader_t *shader)
Shader_FreePass (pass);
}
shader->numpasses = 0;
if (shader->genargs)
{
free(shader->genargs);
shader->genargs = NULL;
}
shader->uses = 0;
}
@ -3080,8 +3226,7 @@ qboolean Shader_Init (void)
Shader_FlushGenerics();
}
shader_rescan_needed = true;
Shader_NeedReload();
Shader_NeedReload(true);
Shader_DoReload();
memset(wibuf, 0xff, sizeof(wibuf));
@ -3205,9 +3350,10 @@ void Shader_Reset(shader_t *s)
char name[MAX_QPATH];
int uses = s->uses;
shader_gen_t *defaultgen = s->generator;
const char *genargs = s->genargs;
char *genargs = s->genargs;
texnums_t dt = s->defaulttextures;
Q_strncpyz(name, s->name, sizeof(name));
s->genargs = NULL;
Shader_Free(s);
memset(s, 0, sizeof(*s));
@ -3987,7 +4133,7 @@ void Shader_DefaultScript(char *shortname, shader_t *s, const void *args)
if (*f == '{')
{
f++;
Shader_ReadShader(s, (void*)f);
Shader_ReadShader(s, (void*)f, SPM_DEFAULT);
}
};
@ -4406,19 +4552,29 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args)
void Shader_DefaultBSPVertex(char *shortname, shader_t *s, const void *args)
{
shaderpass_t *pass;
s->defaulttextures.base = R_LoadHiResTexture(va("%s_d.tga", shortname), NULL, 0);
pass = &s->passes[0];
pass->tcgen = TC_GEN_BASE;
pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0);
pass->shaderbits |= SBITS_MISC_DEPTHWRITE;
pass->rgbgen = RGB_GEN_VERTEX_LIGHTING;
pass->alphagen = ALPHA_GEN_IDENTITY;
pass->numMergedPasses = 1;
Shader_SetBlendmode(pass);
if (!TEXVALID(pass->anim_frames[0]))
if (TEXVALID(s->defaulttextures.base))
{
Con_DPrintf (CON_WARNING "Shader %s has a stage with no image: %s.\n", s->name, shortname );
pass->anim_frames[0] = missing_texture;
pass->texgen = T_GEN_DIFFUSE;
}
else
{
pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0);
if (!TEXVALID(pass->anim_frames[0]))
{
Con_DPrintf (CON_WARNING "Shader %s has a stage with no image: %s.\n", s->name, shortname );
pass->anim_frames[0] = missing_texture;
}
}
s->numpasses = 1;
@ -4541,10 +4697,12 @@ void Shader_Default2D(char *shortname, shader_t *s, const void *genargs)
}
//loads a shader string into an existing shader object, and finalises it and stuff
static void Shader_ReadShader(shader_t *s, char *shadersource)
static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode)
{
char *token;
shaderparsemode = parsemode;
// set defaults
s->flags = SHADER_CULL_FRONT;
s->uses = 1;
@ -4603,11 +4761,15 @@ static qboolean Shader_ParseShader(char *shortname, char *usename, shader_t *s)
unsigned int offset = 0, length;
char path[MAX_QPATH];
char *buf = NULL, *ts = NULL;
int parsemode = SPM_DEFAULT;
Shader_GetPathAndOffset( shortname, &ts, &offset );
if ( ts )
{
if (!strcmp(COM_FileExtension(ts), "mtr"))
parsemode = SPM_DOOM3;
Com_sprintf ( path, sizeof(path), "%s", ts );
length = FS_LoadFile ( path, (void **)&buf );
}
@ -4630,7 +4792,7 @@ static qboolean Shader_ParseShader(char *shortname, char *usename, shader_t *s)
Shader_Reset(s);
Shader_ReadShader(s, file);
Shader_ReadShader(s, file, parsemode);
FS_FreeFile(buf);
return true;
@ -4692,7 +4854,10 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
Q_strncpyz(s->name, shortname, sizeof(s->name));
s->generator = defaultgen;
s->genargs = genargs;
if (genargs)
s->genargs = strdup(genargs);
else
s->genargs = NULL;
if (ruleset_allow_shaders.ival)
{
@ -4757,7 +4922,7 @@ static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *gena
}
else
{
r_shaders[i].uses = 0;
Shader_Free(s);
}
return -1;
}
@ -4815,8 +4980,10 @@ void Shader_DoReload(void)
}
}
void Shader_NeedReload(void)
void Shader_NeedReload(qboolean rescanfs)
{
if (rescanfs)
shader_rescan_needed = true;
shader_reload_needed = true;
}

View File

@ -8,9 +8,14 @@
#define SHADOWMAP_SIZE 512
#define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff
#define nearplane (16)
static int shadow_fbo_id;
static int crepuscular_fbo_id;
texid_t crepuscular_texture_id;
shader_t *crepuscular_shader;
static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour);
@ -37,6 +42,7 @@ typedef struct {
mesh_t **s;
} shadowmeshsurfs_t;
typedef struct shadowmesh_s {
qboolean surfonly;
unsigned int numindicies;
unsigned int maxindicies;
index_t *indicies;
@ -51,6 +57,8 @@ typedef struct shadowmesh_s {
unsigned int leafbytes;
unsigned char *litleaves;
GLuint vebo[2];
} shadowmesh_t;
/*state of the current shadow mesh*/
@ -204,10 +212,15 @@ static void SH_FreeShadowMesh(shadowmesh_t *sm)
Z_Free(sm->litsurfs);
Z_Free(sm->indicies);
Z_Free(sm->verts);
qglDeleteBuffersARB(2, sm->vebo);
sm->vebo[0] = 0;
sm->vebo[1] = 0;
Z_Free(sm);
}
static void SHM_BeginShadowMesh(dlight_t *dl)
static void SHM_BeginShadowMesh(dlight_t *dl, qboolean surfonly)
{
unsigned int i;
unsigned int lb;
@ -249,6 +262,7 @@ static void SHM_BeginShadowMesh(dlight_t *dl)
sh_shmesh->numverts = 0;
sh_shmesh->maxindicies = 0;
sh_shmesh->numindicies = 0;
sh_shmesh->surfonly = surfonly;
if (sh_shmesh->numsurftextures != cl.worldmodel->numtextures)
{
@ -269,6 +283,20 @@ static void SHM_BeginShadowMesh(dlight_t *dl)
}
static struct shadowmesh_s *SHM_FinishShadowMesh(dlight_t *dl)
{
if (sh_shmesh != &sh_tempshmesh)
{
qglGenBuffersARB(2, sh_shmesh->vebo);
GL_SelectVBO(sh_shmesh->vebo[0]);
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(*sh_shmesh->verts) * sh_shmesh->numverts, sh_shmesh->verts, GL_STATIC_DRAW_ARB);
Z_Free(sh_shmesh->verts);
sh_shmesh->verts = NULL;
GL_SelectEBO(sh_shmesh->vebo[1]);
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(*sh_shmesh->indicies) * sh_shmesh->numindicies, sh_shmesh->indicies, GL_STATIC_DRAW_ARB);
Z_Free(sh_shmesh->indicies);
sh_shmesh->indicies = NULL;
}
return sh_shmesh;
}
@ -413,8 +441,8 @@ static void SHM_RecursiveWorldNodeQ1_r (dlight_t *dl, mnode_t *node)
if ((s*s+t*t+dot*dot) < maxdist)
{
SHM_Shadow_Cache_Surface(surf);
#define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff
if (sh_shmesh->surfonly)
continue;
//build a list of the edges that are to be drawn.
for (v = 0; v < surf->numedges; v++)
@ -600,10 +628,8 @@ static void SHM_RecursiveWorldNodeQ2_r (dlight_t *dl, mnode_t *node)
if ((s*s+t*t+dot*dot) < maxdist)
{
SHM_Shadow_Cache_Surface(surf);
#define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff
if (sh_shmesh->surfonly)
continue;
//build a list of the edges that are to be drawn.
for (v = 0; v < surf->numedges; v++)
@ -786,78 +812,278 @@ static void SHM_RecursiveWorldNodeQ3_r (dlight_t *dl, mnode_t *node)
}
#endif
static struct {
unsigned int numtris;
unsigned int maxtris;
struct {
signed int edge[3];
} *tris; /*negative for reverse edge*/
unsigned int numedges;
unsigned int maxedges;
struct {
unsigned int vert[2];
} *edges;
unsigned int numpoints;
unsigned int maxpoints;
vec3_t *points;
unsigned int maxedgeuses;
int *edgeuses; /*negative for back sides, so 0 means unused or used equally on both sides*/
} cv;
#define VERT_POS_EPSILON (1.0f/32)
static int SHM_ComposeVolume_FindVert(float *vert)
{
int i;
for (i = 0; i < cv.numpoints; i++)
{
#if 1
if (cv.points[i][0] == vert[0] &&
cv.points[i][1] == vert[1] &&
cv.points[i][2] == vert[2])
#else
vec3_t d;
d[0] = cv.points[i][0]-vert[0];
d[1] = cv.points[i][1]-vert[1];
d[2] = cv.points[i][2]-vert[2];
if (d[0]*d[0] < VERT_POS_EPSILON &&
d[1]*d[1] < VERT_POS_EPSILON &&
d[2]*d[2] < VERT_POS_EPSILON)
#endif
return i;
}
VectorCopy(vert, cv.points[i]);
cv.numpoints++;
return i;
}
static int SHM_ComposeVolume_FindEdge(int v1, int v2)
{
int i;
for (i = 0; i < cv.numedges; i++)
{
if (cv.edges[i].vert[0] == v1 && cv.edges[i].vert[1] == v2)
return i;
if (cv.edges[i].vert[0] == v2 && cv.edges[i].vert[1] == v1)
return -(i+1);
}
cv.edges[i].vert[0] = v1;
cv.edges[i].vert[1] = v2;
cv.numedges++;
return i;
}
/*each triangle is coplanar, and all face the light, and its a triangle fan. this is a special case that provides a slight speedup*/
static void SHM_ComposeVolume_Fan(vecV_t *points, int numpoints)
{
int newmax;
int lastedge;
int i;
#define MAX_ARRAY_VERTS 65535
static int pointidx[MAX_ARRAY_VERTS];
/*make sure there's space*/
newmax = (cv.numpoints+numpoints + inc)&~(inc-1);
if (cv.maxpoints < newmax)
{
cv.maxpoints = newmax;
cv.points = BZ_Realloc(cv.points, newmax * sizeof(*cv.points));
}
newmax = (cv.numedges+(numpoints-2)*3 + inc)&~(inc-1);
if (cv.maxedges < newmax)
{
cv.maxedges = newmax;
cv.edges = BZ_Realloc(cv.edges, newmax * sizeof(*cv.edges));
}
newmax = (cv.numtris+(numpoints-2) + inc)&~(inc-1);
if (cv.maxtris < newmax)
{
cv.maxtris = newmax;
cv.tris = BZ_Realloc(cv.tris, newmax * sizeof(*cv.tris));
}
for (i = 0; i < numpoints; i++)
{
pointidx[i] = SHM_ComposeVolume_FindVert(points[i]);
}
lastedge = SHM_ComposeVolume_FindEdge(pointidx[0], pointidx[1]);
for (i = 2; i < numpoints; i++)
{
cv.tris[cv.numtris].edge[0] = lastedge;
cv.tris[cv.numtris].edge[1] = SHM_ComposeVolume_FindEdge(pointidx[i-1], pointidx[i]);
lastedge = SHM_ComposeVolume_FindEdge(pointidx[i], pointidx[i-2]);
cv.tris[cv.numtris].edge[2] = lastedge;
lastedge = -(lastedge+1);
cv.numtris++;
}
}
static void SHM_ComposeVolume_Soup(vecV_t *points, int numpoints, int *idx, int numidx)
{
int newmax;
int i;
#define MAX_ARRAY_VERTS 65535
static int pointidx[MAX_ARRAY_VERTS];
/*make sure there's space*/
newmax = (cv.numpoints+numpoints + inc)&~(inc-1);
if (cv.maxpoints < newmax)
{
cv.maxpoints = newmax;
cv.points = BZ_Realloc(cv.points, newmax * sizeof(*cv.points));
}
newmax = (cv.numedges+numidx + inc)&~(inc-1);
if (cv.maxedges < newmax)
{
cv.maxedges = newmax;
cv.edges = BZ_Realloc(cv.edges, newmax * sizeof(*cv.edges));
}
newmax = (cv.numtris+numidx/3 + inc)&~(inc-1);
if (cv.maxtris < newmax)
{
cv.maxtris = newmax;
cv.tris = BZ_Realloc(cv.tris, newmax * sizeof(*cv.tris));
}
for (i = 0; i < numpoints; i++)
{
pointidx[i] = SHM_ComposeVolume_FindVert(points[i]);
}
for (i = 0; i < numidx; i+=3, idx+=3)
{
cv.tris[cv.numtris].edge[0] = SHM_ComposeVolume_FindEdge(pointidx[idx[0]], pointidx[idx[1]]);
cv.tris[cv.numtris].edge[1] = SHM_ComposeVolume_FindEdge(pointidx[idx[1]], pointidx[idx[2]]);
cv.tris[cv.numtris].edge[2] = SHM_ComposeVolume_FindEdge(pointidx[idx[2]], pointidx[idx[0]]);
cv.numtris++;
}
}
/*call this function after generating litsurfs meshes*/
static void SHM_ComposeVolume_BruteForce(dlight_t *dl)
{
/*FIXME: This function is not complete*/
shadowmeshsurfs_t *sms;
unsigned int tno;
unsigned int sno;
unsigned int vno, vno2;
unsigned int fvert, lvert;
int i, e;
mesh_t *sm;
vec3_t ext;
cv.numedges = 0;
cv.numpoints = 0;
cv.numtris = 0;
for (tno = 0; tno < sh_shmesh->numsurftextures; tno++)
{
sms = &sh_shmesh->litsurfs[tno];
if (!sms->count)
continue;
if ((cl.worldmodel->textures[tno]->shader->flags & (SHADER_BLEND|SHADER_NODRAW)))
continue;
for (sno = 0; sno < sms->count; sno++)
{
sm = sms->s[sno];
if (sm->istrifan)
{
//planer poly
//if ((rand()&63)!=63)
//continue;
fvert = sh_shmesh->numverts;
SHM_TriangleFan(sm->numvertexes, sm->xyz_array, dl->origin, PROJECTION_DISTANCE);
vno = (sh_shmesh->numindicies+sm->numvertexes*6); //and a bit of padding
if (sh_shmesh->maxindicies < vno)
{
sh_shmesh->maxindicies = vno;
sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, vno * sizeof(*sh_shmesh->indicies));
}
lvert = fvert + sm->numvertexes*2-1;
for (vno = 0; vno < sm->numvertexes; vno++)
{
if (vno == sm->numvertexes-1)
vno2 = 0;
else
vno2 = vno+1;
sh_shmesh->indicies[sh_shmesh->numindicies++] = fvert+vno;
sh_shmesh->indicies[sh_shmesh->numindicies++] = lvert-vno;
sh_shmesh->indicies[sh_shmesh->numindicies++] = fvert+vno2;
sh_shmesh->indicies[sh_shmesh->numindicies++] = lvert-vno;
sh_shmesh->indicies[sh_shmesh->numindicies++] = lvert-vno2;
sh_shmesh->indicies[sh_shmesh->numindicies++] = fvert+vno2;
}
}
SHM_ComposeVolume_Fan(sm->xyz_array, sm->numvertexes);
else
{
/*each triangle may or may not face the light*/
}
SHM_ComposeVolume_Soup(sm->xyz_array, sm->numvertexes, sm->indexes, sm->numindexes);
}
}
/*FIXME: clip away overlapping triangles*/
/* unsigned int numindicies;
unsigned int maxindicies;
index_t *indicies;
if (cv.maxedgeuses < cv.numedges)
{
BZ_Free(cv.edgeuses);
cv.maxedgeuses = cv.numedges;
cv.edgeuses = Z_Malloc(cv.maxedgeuses * sizeof(*cv.edgeuses));
}
else
memset(cv.edgeuses, 0, cv.numedges * sizeof(*cv.edgeuses));
i = (sh_shmesh->numverts+cv.numpoints*6+inc+5)&~(inc-1); //and a bit of padding
if (sh_shmesh->maxverts < i)
{
sh_shmesh->maxverts = i;
sh_shmesh->verts = BZ_Realloc(sh_shmesh->verts, i * sizeof(*sh_shmesh->verts));
}
unsigned int numverts;
unsigned int maxverts;
vec3_t *verts;
for (i = 0; i < cv.numpoints; i++)
{
/*front face*/
sh_shmesh->verts[(i * 2) + 0][0] = cv.points[i][0];
sh_shmesh->verts[(i * 2) + 0][1] = cv.points[i][1];
sh_shmesh->verts[(i * 2) + 0][2] = cv.points[i][2];
//we also have a list of all the surfaces that this light lights.
unsigned int numsurftextures;
shadowmeshsurfs_t *litsurfs;
/*shadow direction*/
ext[0] = cv.points[i][0]-dl->origin[0];
ext[1] = cv.points[i][1]-dl->origin[1];
ext[2] = cv.points[i][2]-dl->origin[2];
VectorNormalize(ext);
unsigned int leafbytes;
unsigned char *litleaves;
*/
/*back face*/
sh_shmesh->verts[(i * 2) + 1][0] = cv.points[i][0] + ext[0] * dl->radius*2;
sh_shmesh->verts[(i * 2) + 1][1] = cv.points[i][1] + ext[1] * dl->radius*2;
sh_shmesh->verts[(i * 2) + 1][2] = cv.points[i][2] + ext[2] * dl->radius*2;
}
sh_shmesh->numverts = i*2;
i = (sh_shmesh->numindicies+cv.numtris*6+cv.numedges*6+inc+5)&~(inc-1); //and a bit of padding
if (sh_shmesh->maxindicies < i)
{
sh_shmesh->maxindicies = i;
sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, i * sizeof(*sh_shmesh->indicies));
}
for (tno = 0; tno < cv.numtris; tno++)
{
for (i = 0; i < 3; i++)
{
e = cv.tris[tno].edge[i];
if (e < 0)
{
e = -(e+1);
cv.edgeuses[e]--;
e = cv.edges[e].vert[1];
}
else
{
cv.edgeuses[e]++;
e = cv.edges[e].vert[0];
}
sh_shmesh->indicies[sh_shmesh->numindicies+i] = e*2;
sh_shmesh->indicies[sh_shmesh->numindicies+5-i] = e*2 + 1;
}
sh_shmesh->numindicies += 6;
}
for (i = 0; i < cv.numedges; i++)
{
if (cv.edgeuses[i] > 0)
{
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[1]*2 + 0;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[0]*2 + 0;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[0]*2 + 1;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[0]*2 + 1;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[1]*2 + 1;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[1]*2 + 0;
}
else if (cv.edgeuses[i] < 0)
{
//generally should not happen...
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[1]*2 + 0;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[0]*2 + 1;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[0]*2 + 0;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[0]*2 + 1;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[1]*2 + 0;
sh_shmesh->indicies[sh_shmesh->numindicies++] = cv.edges[i].vert[1]*2 + 1;
}
}
}
static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvis, unsigned char *vvis, qboolean surfonly)
@ -868,41 +1094,38 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi
if (dl->worldshadowmesh && !dl->rebuildcache)
return dl->worldshadowmesh;
if (cl.worldmodel->fromgame == fg_quake || cl.worldmodel->fromgame == fg_halflife)
firstedge=0;
switch(cl.worldmodel->fromgame)
{
SHM_BeginShadowMesh(dl);
case fg_quake:
case fg_halflife:
SHM_BeginShadowMesh(dl, surfonly);
SHM_MarkLeavesQ1(dl, lvis);
SHM_RecursiveWorldNodeQ1_r(dl, cl.worldmodel->nodes);
}
break;
#ifdef Q2BSPS
case fg_quake2:
SHM_BeginShadowMesh(dl, surfonly);
SHM_MarkLeavesQ2(dl, lvis, vvis);
SHM_RecursiveWorldNodeQ2_r(dl, cl.worldmodel->nodes);
break;
#endif
#ifdef Q3BSPS
else if (cl.worldmodel->fromgame == fg_quake3)
{
SHM_BeginShadowMesh(dl);
case fg_quake3:
/*q3 doesn't have edge info*/
SHM_BeginShadowMesh(dl, true);
sh_shadowframe++;
SHM_RecursiveWorldNodeQ3_r(dl, cl.worldmodel->nodes);
if (!surfonly)
SHM_ComposeVolume_BruteForce(dl);
return SHM_FinishShadowMesh(dl);
// SHM_RecursiveWorldNodeQ3_r(cl.worldmodel->nodes);
//if generating shadow volumes too:
// decompose the shadow-casting faces into triangles
// find neighbours
// emit front faces (clip back faces to the light's cube?)
// emit edges where there were no neighbours
}
break;
#endif
#ifdef Q2BSPS
else if (cl.worldmodel->fromgame == fg_quake2)
{
SHM_BeginShadowMesh(dl);
SHM_MarkLeavesQ2(dl, lvis, vvis);
SHM_RecursiveWorldNodeQ2_r(dl, cl.worldmodel->nodes);
}
#endif
else
default:
return NULL;
}
/*generate edge polys for map types that need it (q1/q2)*/
if (!surfonly)
{
SHM_BeginQuads();
@ -942,8 +1165,6 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi
SHM_End();
}
firstedge=0;
return SHM_FinishShadowMesh(dl);
}
@ -1046,6 +1267,7 @@ static void Sh_Scissor (srect_t r)
qglPopMatrix();
}
#endif
qglScissor(r.x, r.y, r.width, r.height);
if (qglDepthBoundsEXT)
@ -1135,7 +1357,7 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, srect_t *r)
r->height = vid.pixelheight;
r->dmin = 0;
r->dmax = 1;
if (0)//!r_shadow_scissor.integer)
if (1)//!r_shadow_scissor.integer)
{
return false;
}
@ -1212,8 +1434,14 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, srect_t *r)
y1 = 0;
if (x2 < 0)
x2 = 0;
if (y2 < 0)
y2 = 0;
if (x1 > r_refdef.vrect.width)
x1 = r_refdef.vrect.width;
if (y1 > r_refdef.vrect.height * vid.pixelheight / vid.height)
y1 = r_refdef.vrect.height * vid.pixelheight / vid.height;
if (x2 > r_refdef.vrect.width)
x2 = r_refdef.vrect.width;
if (y2 > r_refdef.vrect.height * vid.pixelheight / vid.height)
y2 = r_refdef.vrect.height * vid.pixelheight / vid.height;
r->x = floor(x1);
@ -1559,6 +1787,11 @@ void Sh_Shutdown(void)
qglDeleteRenderbuffersEXT(1, &shadow_fbo_id);
shadow_fbo_id = 0;
}
if (crepuscular_fbo_id)
{
qglDeleteRenderbuffersEXT(1, &crepuscular_fbo_id);
crepuscular_fbo_id = 0;
}
}
void Sh_GenShadowMap (dlight_t *l, qbyte *lvis)
@ -1814,8 +2047,6 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour)
}
}
#define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff
/*Fixme: this is brute forced*/
#ifdef warningmsg
#pragma warningmsg("brush shadows are bruteforced")
@ -1937,14 +2168,15 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q
//qglEnable(GL_POLYGON_OFFSET_FILL);
//qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
GL_SelectVBO(0);
GL_SelectEBO(0);
GL_SelectVBO(sm->vebo[0]);
GL_SelectEBO(sm->vebo[1]);
qglEnableClientState(GL_VERTEX_ARRAY);
//draw cached world shadow mesh
qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), sm->verts);
qglDrawRangeElements(GL_TRIANGLES, 0, sm->numverts, sm->numindicies, GL_INDEX_TYPE, sm->indicies);
RQuantAdd(RQUANT_SHADOWFACES, sm->numindicies);
GL_SelectVBO(0);
GL_SelectEBO(0);
//qglEnable(GL_POLYGON_OFFSET_FILL);
//qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit);
}
@ -1996,8 +2228,9 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q
//redraws world geometry up to 3 times per light...
static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
{
int sdecrw;
int sincrw;
int sref;
int sfrontfail;
int sbackfail;
int leaf;
qbyte *lvis;
srect_t rect;
@ -2063,76 +2296,90 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
//FIXME: is it practical to test to see if scissors allow not clearing the stencil buffer?
/*we don't need all that much stencil buffer depth, and if we don't get enough or have dodgy volumes, wrap if we can*/
sincrw = GL_INCR;
sdecrw = GL_DECR;
#ifdef I_LIVE_IN_A_FREE_COUNTRY
sref = 0;
sbackfail = GL_INCR;
sfrontfail = GL_DECR;
if (gl_config.ext_stencil_wrap)
{ //minimise damage...
sincrw = GL_INCR_WRAP_EXT;
sbackfail = GL_INCR_WRAP_EXT;
sdecrw = GL_DECR_WRAP_EXT;
}
#else
sref = (1<<gl_stencilbits)-1; /*this is halved for two-sided stencil support, just in case there's no wrap support*/
sbackfail = GL_DECR;
sfrontfail = GL_INCR;
if (gl_config.ext_stencil_wrap)
{ //minimise damage...
sbackfail = GL_DECR_WRAP_EXT;
sfrontfail = GL_INCR_WRAP_EXT;
}
#endif
//our stencil writes.
#ifdef _DEBUG
/* if (r_shadows.value == 666) //testing (visible shadow volumes)
#if 0 //def _DEBUG
// if (r_shadows.value == 666) //testing (visible shadow volumes)
{
checkerror();
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
checkglerror();
qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
qglColor3f(dl->color[0], dl->color[1], dl->color[2]);
qglDisable(GL_STENCIL_TEST);
qglEnable(GL_POLYGON_OFFSET_FILL);
qglPolygonOffset(-1, -1);
// qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Sh_DrawStencilLightShadows(dl, lvis, false);
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
qglDisable(GL_POLYGON_OFFSET_FILL);
checkerror();
checkglerror();
qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}*/
}
#endif
if (qglStencilOpSeparateATI)
{
qglClearStencil(0);
sref/=2;
qglClearStencil(sref);
qglClear(GL_STENCIL_BUFFER_BIT);
GL_CullFace(0);
qglStencilFunc( GL_ALWAYS, 1, ~0 );
qglStencilFunc(GL_ALWAYS, 0, ~0);
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, sincrw, GL_KEEP);
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, sdecrw, GL_KEEP);
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, sbackfail, GL_KEEP);
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, sfrontfail, GL_KEEP);
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
qglStencilOpSeparateATI(GL_FRONT_AND_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
GL_CullFace(SHADER_CULL_FRONT);
qglStencilFunc( GL_EQUAL, 0, ~0 );
qglStencilFunc(GL_EQUAL, sref, ~0);
}
else if (qglActiveStencilFaceEXT)
{
sref/=2;
/*personally I prefer the ATI way (nvidia method)*/
qglClearStencil(0);
qglClearStencil(sref);
qglClear(GL_STENCIL_BUFFER_BIT);
GL_CullFace(0);
qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
qglActiveStencilFaceEXT(GL_BACK);
qglStencilOp(GL_KEEP, sincrw, GL_KEEP);
qglStencilFunc( GL_ALWAYS, 1, ~0 );
qglActiveStencilFaceEXT(GL_BACK);
qglStencilOp(GL_KEEP, sbackfail, GL_KEEP);
qglStencilFunc(GL_ALWAYS, 0, ~0 );
qglActiveStencilFaceEXT(GL_FRONT);
qglStencilOp(GL_KEEP, sdecrw, GL_KEEP);
qglStencilFunc( GL_ALWAYS, 1, ~0 );
qglStencilOp(GL_KEEP, sfrontfail, GL_KEEP);
qglStencilFunc(GL_ALWAYS, 0, ~0 );
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
qglActiveStencilFaceEXT(GL_BACK);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc( GL_ALWAYS, 0, ~0 );
qglStencilFunc(GL_ALWAYS, 0, ~0 );
qglActiveStencilFaceEXT(GL_FRONT);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc( GL_EQUAL, 0, ~0 );
qglStencilFunc(GL_EQUAL, sref, ~0 );
qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
@ -2140,21 +2387,21 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
}
else //your graphics card sucks and lacks efficient stencil shadow techniques.
{ //centered around 0. Will only be increased then decreased less.
qglClearStencil(0);
qglClearStencil(sref);
qglClear(GL_STENCIL_BUFFER_BIT);
qglStencilFunc(GL_ALWAYS, 0, ~0);
GL_CullFace(SHADER_CULL_BACK);
qglStencilOp(GL_KEEP, sincrw, GL_KEEP);
qglStencilOp(GL_KEEP, sbackfail, GL_KEEP);
Sh_DrawStencilLightShadows(dl, lvis, vvis, false);
GL_CullFace(SHADER_CULL_FRONT);
qglStencilOp(GL_KEEP, sdecrw, GL_KEEP);
qglStencilOp(GL_KEEP, sfrontfail, GL_KEEP);
Sh_DrawStencilLightShadows(dl, lvis, vvis, true);
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
qglStencilFunc(GL_EQUAL, 0, ~0);
qglStencilFunc(GL_EQUAL, sref, ~0);
}
//end stencil writing.
@ -2167,15 +2414,15 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
{
qglColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
qglStencilFunc(GL_GREATER, 1, ~0);
qglStencilFunc(GL_GREATER, sref, ~0);
R2D_ConsoleBackground(vid.height);
qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
qglStencilFunc(GL_LESS, 1, ~0);
qglStencilFunc(GL_LESS, sref, ~0);
R2D_ConsoleBackground(vid.height);
qglColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
qglStencilFunc(GL_NEVER, 1, ~0);
qglStencilFunc(GL_EQUAL, sref, ~0);
R2D_ConsoleBackground(vid.height);
}
@ -2260,7 +2507,95 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
Sh_DrawEntLighting(dl, colour);
}
void Sh_DrawLights(qbyte *vis)
void GLBE_SubmitMeshes (qboolean drawworld, batch_t **blist, int start, int stop);
void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches)
{
static mesh_t mesh;
static vecV_t xyz[4] =
{
{-1,-1,-1},
{-1,1,-1},
{1,1,-1},
{1,-1,-1}
};
static vec2_t tc[4] =
{
{0,0},
{0,1},
{1,1},
{1,0}
};
static index_t idx[6] =
{
0,1,2,
0,2,3
};
mesh.numindexes = 6;
mesh.numvertexes = 4;
mesh.xyz_array = xyz;
mesh.st_array = tc;
mesh.indexes = idx;
#if 1
/*
a crepuscular light (seriously, that's the correct spelling) is one that gives 'god rays', rather than regular light.
our implementation doesn't cast shadows. this allows it to actually be outside the map, and to shine through cloud layers in the sky.
we could cast shadows if the light was actually inside, I suppose.
Anyway, its done using an FBO, where everything but the sky is black (stuff that occludes the sky is black too).
which is then blitted onto the screen in 2d-space.
*/
/*requires an FBO, as stated above*/
if (!gl_config.ext_framebuffer_objects)
return;
//checkglerror();
if (!crepuscular_fbo_id)
{
qglGenFramebuffersEXT(1, &crepuscular_fbo_id);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, crepuscular_fbo_id);
qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
qglReadBuffer(GL_NONE);
crepuscular_texture_id = GL_AllocNewTexture("***crepusculartexture***", vid.pixelwidth, vid.pixelheight);
/*FIXME: requires npot*/
crepuscular_shader = R_RegisterShader("crepuscular_screen",
"{\n"
"program crepuscular_rays\n"
"{\n"
"map \"***crepusculartexture***\"\n"
"blend add\n"
"}\n"
"}\n"
);
GL_MTBind(0, GL_TEXTURE_2D, crepuscular_texture_id);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, crepuscular_texture_id.num, 0);
}
else
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, crepuscular_fbo_id);
//checkglerror();
BE_SelectMode(BEM_CREPUSCULAR);
BE_SelectDLight(dl, colours);
//checkglerror();
GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_BLEND);
//checkglerror();
//fixme: check regular post-proc
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
checkglerror();
BE_SelectMode(BEM_STANDARD);
GLBE_DrawMesh_Single(crepuscular_shader, &mesh, NULL, &crepuscular_shader->defaulttextures, 0);
checkglerror();
#endif
}
void Sh_DrawLights(qbyte *vis, batch_t **mbatches)
{
vec3_t colour;
dlight_t *dl;
@ -2332,7 +2667,9 @@ void Sh_DrawLights(qbyte *vis)
if (colour[0] < 0.001 && colour[1] < 0.001 && colour[2] < 0.001)
continue; //just switch these off.
if (((!dl->die)?!r_shadow_realtime_world_shadows.ival:!r_shadow_realtime_dlight_shadows.ival) || dl->flags & LFLAG_NOSHADOWS)
if (dl->flags & LFLAG_CREPUSCULAR)
Sh_DrawCrepuscularLight(dl, colour, mbatches);
else if (((!dl->die)?!r_shadow_realtime_world_shadows.ival:!r_shadow_realtime_dlight_shadows.ival) || dl->flags & LFLAG_NOSHADOWS)
{
Sh_DrawShadowlessLight(dl, colour, vis);
}

View File

@ -284,7 +284,7 @@ qboolean gammaworks; //if the gl drivers can set proper gamma.
gl_config_t gl_config;
int gl_canstencil;
int gl_stencilbits;
float gldepthmin, gldepthmax;
const char *gl_vendor;
@ -495,6 +495,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
if (GL_CheckExtension("GL_EXT_stencil_two_side"))
qglActiveStencilFaceEXT = (void *) getglext("glActiveStencilFaceEXT");
if (GL_CheckExtension("GL_ARB_depth_clamp") || GL_CheckExtension("GL_NV_depth_clamp"))
gl_config.arb_depth_clamp = true;
if (GL_CheckExtension("GL_ARB_texture_compression"))
{
qglCompressedTexImage2DARB = (void *)getglext("glCompressedTexImage2DARB");
@ -559,7 +562,17 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
// glslang
//the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects.
//but our code kinda requires both for clean workings.
if (gl_config.glversion >= 2)// && (gl_config.gles || 0))
if (strstr(gl_renderer, " Mesa ") && Cvar_Get("gl_blacklist_mesa_glsl", "1", CVAR_RENDERERLATCH, "gl blacklists")->ival && (gl_config.glversion < 3 || gl_config.gles))
{
//(9:12:33 PM) bigfoot: Spike, can you please blacklist your menu shader on Mesa? My machine just hard locked up again because I forgot that pressing escape in FTE is verboten
//(11:51:42 PM) bigfoot: OpenGL vendor string: Tungsten Graphics, Inc
//(11:51:50 PM) bigfoot: OpenGL version string: 2.1 Mesa 7.7.1
//blacklist all glsl, it can't handle #define macros properly either.
//if the menu shader is hardlocking, I don't know what else will do it too.
Con_Printf(CON_NOTICE "Mesa detected, ignoring any GLSL support. Use '+set gl_blacklist_mesa_glsl 0' on the commandline to reenable it.\n");
}
else if (gl_config.glversion >= 2)// && (gl_config.gles || 0))
{
/*core names are different from extension names (more functions too)*/
gl_config.arb_shader_objects = true;

View File

@ -109,8 +109,6 @@ qboolean isPermedia = false;
qboolean mouseactive = false;
qboolean ActiveApp = false;
int gl_canstencil;
/*-----------------------------------------------------------------------*/
@ -1005,7 +1003,7 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
GLVID_SetPalette(palette);
GLVID_ShiftPalette(palette);
qglGetIntegerv(GL_STENCIL_BITS, &gl_canstencil);
qglGetIntegerv(GL_STENCIL_BITS, &gl_stencilbits);
InitSig(); // trap evil signals

View File

@ -1483,14 +1483,14 @@ BOOL bSetupPixelFormat(HDC hDC)
TRACE(("dbg: bSetupPixelFormat: we can use the stencil buffer. woot\n"));
qDescribePixelFormat(hDC, pixelformat, sizeof(pfd), &pfd);
FixPaletteInDescriptor(hDC, &pfd);
gl_canstencil = pfd.cStencilBits;
gl_stencilbits = pfd.cStencilBits;
return TRUE;
}
}
TRACE(("dbg: ChoosePixelFormat 1: no stencil buffer for us\n"));
pfd.cStencilBits = 0;
gl_canstencil = false;
gl_stencilbits = 0;
if ( (pixelformat = qChoosePixelFormat(hDC, &pfd)) == 0 )
{

View File

@ -171,6 +171,7 @@ typedef struct {
qboolean arb_shader_objects;
qboolean ext_framebuffer_objects;
qboolean ext_stencil_wrap;
qboolean arb_depth_clamp;
int ext_texture_filter_anisotropic;
int maxtmus; //max texture units
} gl_config_t;
@ -291,7 +292,7 @@ typedef void (APIENTRY *lpSelTexFUNC) (GLenum en);
extern lpMTexFUNC qglMTexCoord2fSGIS;
extern lpSelTexFUNC qglSelectTextureSGIS;
extern int gl_canstencil;
extern int gl_stencilbits;
extern FTEPFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
extern lpMTexFUNC qglMTexCoord2fSGIS;

View File

@ -698,6 +698,9 @@ typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
#define GL_NUM_EXTENSIONS 0x821D
#endif
#ifndef GL_ARB_depth_clamp
#define GL_DEPTH_CLAMP_ARB 0x864F
#endif
#endif

View File

@ -306,6 +306,7 @@ typedef struct {
SP_LIGHTRADIUS, /*these light values are realtime lighting*/
SP_LIGHTCOLOUR,
SP_LIGHTPOSITION,
SP_LIGHTSCREEN,
//things that are set immediatly
SP_FIRSTIMMEDIATE, //never set
@ -402,7 +403,7 @@ struct shader_s
skydome_t *skydome;
shader_gen_t *generator;
const char *genargs;
char *genargs;
meshfeatures_t features;
bucket_t bucket;
@ -438,7 +439,7 @@ void Shader_DoReload(void);
void R_BackendInit (void);
void Shader_Shutdown (void);
qboolean Shader_Init (void);
void Shader_NeedReload(void);
void Shader_NeedReload(qboolean rescanfs);
void Shader_WriteOutGenerics_f(void);
mfog_t *CM_FogForOrigin(vec3_t org);
@ -502,7 +503,7 @@ void BE_SetupForShadowMap(void);
//Called from shadowmapping code into backend
void BE_BaseEntTextures(void);
//Draws lights, called from the backend
void Sh_DrawLights(qbyte *vis);
void Sh_DrawLights(qbyte *vis, batch_t **mbatches);
void Sh_Shutdown(void);
//Draws the depth of ents in the world near the current light
void BE_BaseEntShadowDepth(void);

View File

@ -1,15 +1,16 @@
#include <stdio.h>
#include <string.h>
char *effects[] =
char effects[][64] =
{
"spikeset.cfg",
"faithful.cfg",
"highfps.cfg",
"high.cfg",
"minimal.cfg",
"h2part.cfg",
"tsshaft.cfg",
NULL
""
};
int main(void)
@ -20,15 +21,25 @@ int main(void)
c = fopen("../client/r_partset.c", "wt");
h = fopen("../client/r_partset.h", "wt");
if (!c || !h)
{
printf("unable to open a file\n");
return;
}
fprintf(c, "/*\nWARNING: THIS FILE IS GENERATED BY '"__FILE__"'.\nYOU SHOULD NOT EDIT THIS FILE BY HAND\n*/\n\n");
fprintf(c, "#include \"r_partset.h\"\n\n\n");
for (i = 0; effects[i]; i++)
for (i = 0; *effects[i]; i++)
{
s = fopen(effects[i], "rt");
if (!s)
{
printf("unable to open %s\n", effects[i]);
return;
}
*strchr(effects[i], '.') = 0;
fprintf(h, "extern char *particle_set_%s;\n", effects[i]);
if (i)
fprintf(c, "\n\n\n//////////////////////////////////////////////////////\n\n\n");
fprintf(c, "char *particle_set_%s =\n", effects[i]);
@ -66,7 +77,7 @@ int main(void)
}
fputs("#define R_PARTSET_BUILTINS ", h);
for (i = 0; effects[i]; i++)
for (i = 0; *effects[i]; i++)
{
fprintf(h, "{\"%s\", &particle_set_%s},", effects[i], effects[i]);
}

460
engine/partcfgs/high.cfg Normal file
View File

@ -0,0 +1,460 @@
///////////////////////////////
//rocket trail
// flame trail
r_part tr_rocket
{
texture "particles/fteparticlefont.tga"
tcoords 97 97 191 191 256
step 1
scale 12
alpha 0.4
die 0.5
rgb 255 127 100
rgbdelta -14 -300 -300
blend add
scalefactor 1
scaledelta -15
}
// smoke puffs
r_part +tr_rocket
{
texture "particles/fteparticlefont.tga"
tcoords 97 97 191 191 256
step 5
scale 30
alpha 0.2
die 1.5
//diesubrand 10.25
randomvel 0.2
rgb 5 5 5
//rgbdelta -230 -45 -9
gravity -15
scalefactor 1
scaledelta 20
spawnvel 5
}
// burst sparks
r_part +tr_rocket
{
type texturedspark
texture "particles/fteparticlefont.tga"
tcoords 1 65 31 95 256 8 32
count 1
scale 2
scalefactor 1
scaledelta -15
alpha 0.2
die 0.25
rgb 255 128 0
blend add
spawnmode ball
spawnorg 1
spawnvel 50
veladd 500
friction 0.01
gravity 100
}
///////////////////////////////////////////
//alternate rocket trail, which is used by a handful of qw players.
//r_part tr_altrocket
//{
//}
///////////////////////////////////////////
//grenade trail
r_part tr_grenade
{
texture "particles/fteparticlefont.tga"
tcoords 97 97 191 191 256
step 6
scale 32
scaledelta 12
alpha 0.3
die 1.25
randomvel 2
veladd 15
rgb 75 75 75
//rgb 255 50 50
//rgbdelta -255 -75 -75
gravity -25
scalefactor 1
blend modulate
}
r_part +tr_grenade
{
texture "particles/fteparticlefont.tga"
tcoords 97 97 191 191 256
scale 1
scaledelta 0.25
alpha 0.2
step 4
die 0.8
randomvel 0
rgb 255 150 150
rgbdelta 0 -150 -150
type beam
blend add
}
//////////////////////////////////
//shotgun impacts
r_part gunshotsmoke
{
texture "particles/fteparticlefont.tga"
tcoords 1 65 31 95 256 8 32
count 3
scale 25
scalefactor 1
die 0.8
alpha 0.12
rgb 32 32 32
blend add
spawnmode ball
spawnorg 2
spawnvel 20
veladd -20
}
r_part te_gunshot
{
type texturedspark
texture "particles/fteparticlefont.tga"
tcoords 1 65 31 95 256 8 32
count 3
scale 2
scalefactor 1
alpha 0.5
die 0.8
rgb 255 128 0
blend add
spawnmode ball
spawnorg 1
spawnvel 100
veladd -80
friction 0.3
gravity 400
assoc gunshotsmoke
}
//////////////////////////////////
//nail impacts
r_part te_spike
{
type sparkfan
count 10
scale 1
scalefactor 1
alpha 0.5
die 0.2
rgb 255 128 0
blend add
spawnmode ball
spawnorg 12
spawnvel 300
}
r_part +te_spike
{
texture "particles/fteparticlefont.tga"
tcoords 1 97 95 191 256
count 1
scale 1
scalefactor 1
scaledelta 190
die 0.1
alpha 0.6
rgb 255 128 0
blend add
assoc gunshotsmoke
}
////////////////////////////////////////////////
//explosion
//red bit
r_part te_explosion
{
texture "particles/fteparticlefont.tga"
tcoords 97 97 191 191 256
count 1
scale 500
alpha 0.4
die 0.2
rgb 255 127 100
rgbdelta -14 -300 -300
blend add
scalefactor 1
scaledelta -15
randomvel 0
lightradius 350
lightrgb 0.4 0.2 0.05
lighttime 0.5
lightradiusfade 350
lightrgbfade 2 2 2
}
//smoke
r_part +te_explosion
{
texture "particles/fteparticlefont.tga"
tcoords 97 97 191 191 256
count 7
scale 300
alpha 0.2
die 0.8
//diesubrand 10.25
randomvel 100
rgb 5 5 5
//rgbdelta -230 -45 -9
gravity -15
scalefactor 1
scaledelta 40
spawnvel 5
}
// burst sparks
r_part +te_explosion
{
type texturedspark
texture "particles/fteparticlefont.tga"
tcoords 1 65 31 95 256 8 32
count 100
scale 5
scalefactor 1
scaledelta -15
alpha 0.2
die 0.5
rgb 255 128 0
blend add
spawnmode ball
spawnorg 1
randomvel 1000
friction 0.01
gravity 100
stretchfactor 5
}
//hide lights in explosions.
r_explosionlight 0
//hide the explosion sprite in nq+qw - WARNING: some mods use this sprite as a flame thrower.
cl_expsprite 0
r_effect "progs/s_explod.spr" hidden 1
//////////////////////////////////////////
//r_part te_tarexplosion
//{
//}
//////////////////////////////////////////
//r_part te_lavasplash
//{
//}
//////////////////////////////////////////
r_part te_teleport
{
scale 250
count 1
alpha 0.3
die 0.5
scalefactor 1
rotationstart 45
rotationspeed 0
shader
{
glslprogram
{
varying vec2 tcoord;
varying vec4 scoord;
varying float alph;
#ifdef VERTEX_SHADER
attribute vec2 v_texcoord;
attribute vec4 v_colour;
void main(void)
{
scoord = ftetransform();
tcoord = (v_texcoord.st - 0.5)*2.0;
alph = v_colour.a;
gl_Position = scoord;
}
#endif
#ifdef FRAGMENT_SHADER
uniform sampler2D s_t0;
void main(void)
{
vec2 nst;
float f;
nst = scoord.xy / scoord.w;
nst = (1.0 + nst)/2.0;
f = 1 - length(tcoord);
// f = 1 - tcoord*tcoord;
if (f < 0) discard;
f *= alph;
gl_FragColor = texture2D(s_t0, nst - tcoord*f);
}
#endif
}
{
map $currentrender
blendfunc blend
}
}
}
//////////////////////////////////////////
//hellknight
r_part tr_knightspike
{
texture "particles/fteparticlefont.tga"
tcoords 1 97 95 191 256
scale 15
step 1
alpha 0.6
die 0.2
rgb 192 96 48
veladd 0
randomvel 2
friction 4
scalefactor 0.825
blend add
}
/////////////////////////////////////////
//vore missiles
r_part tr_vorespike
{
texture "particles/fteparticlefont.tga"
tcoords 1 97 95 191 256
scale 15
step 1
alpha 0.6
die 0.5
rgb 192 96 192
veladd 15
spawnmode spiral
spawnvel 50
randomvel 0
friction 0
scalefactor 1
blend add
lightradius 150
lightrgb 0.75 0.37 0.75
}
//rygel's pack sucks
r_trail "progs/v_spike.mdl" tr_vorespike
/////////////////////////////////////////
//scrag missiles. just use the default trail cos we're lazy
//r_part tr_wizspike
//{
//}
/////////////////////////////////////////
//zombie body-part blood trails
r_part tr_slightblood
{
texture "particles/fteparticlefont.tga"
tcoords 1 1 63 63 256 2 64
step 16
scale 64
alpha 0.6
die 1
randomvel 32
veladd 10
rotationspeed 90
rotationstart 0 360
rgb 32 0 0
gravity 200
scalefactor 0.8
scaledelta -10
stains 5
}
//////////////////////////////////////////
//regular ol' blood trails
r_part tr_blood
{
texture "particles/fteparticlefont.tga"
tcoords 1 1 63 63 256 2 64
step 4
scale 64
alpha 0.3
die 1
randomvel 32
veladd 10
rotationspeed 90
rotationstart 0 360
rgb 64 0 0
gravity 200
scalefactor 0.8
scaledelta -10
stains 5
}
//////////////////////////////////
//fallbacks
r_part pe_default
{
texture "particles/fteparticlefont.tga"
tcoords 1 97 95 191 256
count 1
scale 4
veladd 15
die 0.4
alphadelta 0
diesubrand 0.4
gravity 40
spawnorg 8
}
r_part pe_defaulttrail
{
texture "particles/fteparticlefont.tga"
tcoords 1 97 95 191 256
scale 15
step 1
alpha 0.6
die 0.2
rgb 192 96 48
veladd 0
randomvel 2
friction 4
scalefactor 0.825
blend add
}
//////////////////////////////////
//map debugging
r_part pe_pointfile
{
texture "particles/fteparticlefont.tga"
tcoords 1 97 95 191 256
count 1
scale 50
die 30
alphadelta 0
rgb 255 255 0
}

View File

@ -373,6 +373,11 @@ reeval:
OPC->_float = (ptr->_float *= OPA->_float);
break;
case OP_MULSTOREP_V: // e.v *= f
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
OPC->_vector[0] = (ptr->_vector[0] *= OPA->_float);
OPC->_vector[0] = (ptr->_vector[1] *= OPA->_float);
@ -383,6 +388,11 @@ reeval:
OPB->_float /= OPA->_float;
break;
case OP_DIVSTOREP_F: // e.f /= f
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float /= OPA->_float);
break;
@ -396,10 +406,20 @@ reeval:
OPB->_vector[2] += OPA->_vector[2];
break;
case OP_ADDSTOREP_F: // e.f += f
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float += OPA->_float);
break;
case OP_ADDSTOREP_V: // e.v += v
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
OPC->_vector[0] = (ptr->_vector[0] += OPA->_vector[0]);
OPC->_vector[1] = (ptr->_vector[1] += OPA->_vector[1]);
@ -415,10 +435,20 @@ reeval:
OPB->_vector[2] -= OPA->_vector[2];
break;
case OP_SUBSTOREP_F: // e.f -= f
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
OPC->_float = (ptr->_float -= OPA->_float);
break;
case OP_SUBSTOREP_V: // e.v -= v
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
OPC->_vector[0] = (ptr->_vector[0] -= OPA->_vector[0]);
OPC->_vector[1] = (ptr->_vector[1] -= OPA->_vector[1]);
@ -780,7 +810,13 @@ reeval:
OPC->_int = OPA->_int - OPB->_int;
break;
case OP_LOADP_C: //load character from a string
ptr = QCPOINTERM(OPA->_int + (int)OPB->_float);
i = (unsigned int)OPA->_int + (unsigned int)OPB->_float;
if ((unsigned int)i >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer read in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTERM(i);
OPC->_float = *(unsigned char *)ptr;
break;
case OP_LOADP_I:
@ -789,12 +825,24 @@ reeval:
case OP_LOADP_ENT:
case OP_LOADP_S:
case OP_LOADP_FNC:
i = OPA->_int + OPB->_int*4;
if ((unsigned int)i >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer read in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTERM(OPA->_int + OPB->_int*4);
OPC->_int = ptr->_int;
break;
case OP_LOADP_V:
ptr = QCPOINTERM(OPA->_int + OPB->_int);
i = OPA->_int + OPB->_int*4;
if ((unsigned int)i >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer read in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTERM(i);
OPC->_vector[0] = ptr->_vector[0];
OPC->_vector[1] = ptr->_vector[1];
OPC->_vector[2] = ptr->_vector[2];
@ -852,6 +900,11 @@ reeval:
OPB->_float = (float)((int)OPB->_float | (int)OPA->_float);
break;
case OP_BITSETP: // .b (+) a
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
ptr->_float = (float)((int)ptr->_float | (int)OPA->_float);
break;
@ -859,6 +912,11 @@ reeval:
OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float));
break;
case OP_BITCLRP: // .b (-) a
if ((unsigned int)OPB->_int >= addressableused)
{
pr_xstatement = st-pr_statements;
PR_RunError (progfuncs, "bad pointer write in %s", PR_StringToNative(progfuncs, pr_xfunction->s_name));
}
ptr = QCPOINTER(OPB);
ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float));
break;

View File

@ -235,7 +235,10 @@ struct globalvars_s *PR_globals (progfuncs_t *progfuncs, progsnum_t pnum)
if (pnum < 0)
{
if (!current_progstate)
return NULL; //err.. you've not loaded one yet.
{
static float fallback[RESERVED_OFS];
return (struct globalvars_s *)fallback; //err.. you've not loaded one yet.
}
return (struct globalvars_s *)current_progstate->globals;
}
return (struct globalvars_s *)pr_progstate[pnum].globals;

View File

@ -14,7 +14,7 @@ struct edict_s;
vec3_t vec3_origin;
fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs);
pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, ddefXX_t *key, char *s, int bits);
pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, unsigned int fldofs, int fldtype, char *s);
/*
=================
@ -460,7 +460,7 @@ char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val)
type &= ~DEF_SAVEGLOBAL;
#endif
if (pr_types)
if (current_progstate && pr_types)
type = pr_types[type].type;
switch (type)
@ -573,8 +573,8 @@ char *PR_UglyValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val)
type &= ~DEF_SAVEGLOBAL;
#endif
if (pr_types)
type = pr_types[type].type;
// if (pr_types)
// type = pr_types[type].type;
switch (type)
{
@ -1025,7 +1025,7 @@ Can parse either fields or globals
returns false if error
=============
*/
pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, ddefXX_t *key, char *s, int structtype)
pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, unsigned int fldofs, int fldtype, char *s)
{
int i;
char string[128];
@ -1033,31 +1033,8 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, ddefXX_t *key, char *s,
char *v, *w;
string_t st;
dfunction_t *func;
int type;
switch(structtype)
{
case PST_DEFAULT:
qcptr += ((ddef16_t*)key)->ofs*sizeof(int);
if (pr_types)
type = pr_types[((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL].type;
else
type = ((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL;
break;
case PST_FTE32:
qcptr += ((ddef32_t*)key)->ofs*sizeof(int);
if (pr_types)
type = pr_types[((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL].type;
else
type = ((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL;
break;
default:
Sys_Error("Bad struct type in ED_ParseEpair");
return false;
}
int type = fldtype & ~DEF_SAVEGLOBAL;
qcptr += fldofs*sizeof(int);
switch (type)
{
@ -1231,7 +1208,7 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent)
}
cont:
if (!ED_ParseEpair (progfuncs, (char*)ent->fields - progfuncs->stringtable, (ddefXX_t*)key, qcc_token, PST_FTE32))
if (!ED_ParseEpair (progfuncs, (char*)ent->fields - progfuncs->stringtable, key->ofs, key->type, qcc_token))
{
continue;
// Sys_Error ("ED_ParseEdict: parse error on entities");
@ -1662,6 +1639,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
eval_t *fulldata; //this is part of FTE_FULLSPAWNDATA
char *datastart;
eval_t *selfvar = NULL;
eval_t *var;
char filename[128];
@ -1691,14 +1669,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
{
isloadgame = false;
if (pr_typecurrent>=0)
num = ED_FindGlobalOfs(progfuncs, "__fullspawndata");
else
num = 0;
if (num)
fulldata = (eval_t *)((int *)pr_globals + num);
else
fulldata = NULL;
fulldata = PR_FindGlobal(progfuncs, "__fullspawndata", PR_ANY, NULL);
}
while(1)
@ -1877,7 +1848,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
else
{
file = QCC_COM_Parse(file);
ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d16, qcc_token, PST_DEFAULT);
ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, d16->ofs, d16->type, qcc_token);
}
break;
case PST_QTEST:
@ -1890,7 +1861,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
else
{
file = QCC_COM_Parse(file);
ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d32, qcc_token, PST_FTE32);
ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, d32->ofs, d32->type, qcc_token);
}
break;
default:
@ -1976,7 +1947,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
else
{
file = QCC_COM_Parse(file);
ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d16, qcc_token, PST_DEFAULT);
ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, d16->ofs, d16->type, qcc_token);
}
break;
case PST_QTEST:
@ -1989,7 +1960,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
else
{
file = QCC_COM_Parse(file);
ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d32, qcc_token, PST_FTE32);
ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, d32->ofs, d32->type, qcc_token);
}
break;
default:
@ -2069,8 +2040,6 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
}
else
{
eval_t *selfvar;
//added by request of Mercury.
if (fulldata) //this is a vital part of HL map support!!!
{ //essentually, it passes the ent's spawn info to the ent.
@ -2085,8 +2054,10 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags)
fulldata->string = PR_StringToProgs(progfuncs, spawndata);
}
selfvar = (eval_t *)((int *)pr_globals + ED_FindGlobalOfs(progfuncs, "self"));
selfvar->edict = EDICT_TO_PROG(progfuncs, ed);
if (!selfvar)
selfvar = PR_FindGlobal(progfuncs, "self", PR_ANY, NULL);
if (selfvar)
selfvar->edict = EDICT_TO_PROG(progfuncs, ed);
//DP_SV_SPAWNFUNC_PREFIX support
eclassname = PR_StringToNative(progfuncs, var->string);

View File

@ -346,6 +346,9 @@ ddef32_t *ED_FindLocalOrGlobal(progfuncs_t *progfuncs, char *name, eval_t **val)
ddef16_t *def16;
int i;
if (pr_typecurrent < 0)
return NULL;
switch (pr_progstate[pr_typecurrent].structtype)
{
case PST_DEFAULT:
@ -470,7 +473,7 @@ char *EvaluateDebugString(progfuncs_t *progfuncs, char *key)
c2 = c+1;
c = strchr(c2, '.');
type = type &~DEF_SAVEGLOBAL;
if (current_progstate->types)
if (current_progstate && current_progstate->types)
type = current_progstate->types[type].type;
if (type != ev_entity)
return "'.' without entity";

View File

@ -19,8 +19,16 @@ int maxshares;
pbool PR_SwitchProgs(progfuncs_t *progfuncs, progsnum_t type)
{
if ((unsigned)type >= maxprogs)
{
if (type == -1)
{
pr_typecurrent = -1;
current_progstate = NULL;
return true;
}
PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", type);
// Sys_Error("Bad prog type - %i", type);
}
if (pr_progstate[(unsigned)type].progs == NULL) //we havn't loaded it yet, for some reason
return false;
@ -32,38 +40,38 @@ pbool PR_SwitchProgs(progfuncs_t *progfuncs, progsnum_t type)
return true;
}
void PR_MoveParms(progfuncs_t *progfuncs, progsnum_t progs1, progsnum_t progs2) //from 2 to 1
void PR_MoveParms(progfuncs_t *progfuncs, progsnum_t newpr, progsnum_t oldpr) //from 2 to 1
{
unsigned int a;
progstate_t *p1;
progstate_t *p2;
progstate_t *np;
progstate_t *op;
if (progs1 == progs2)
if (newpr == oldpr)
return; //don't bother coping variables to themselves...
p1 = &pr_progstate[(int)progs1];
p2 = &pr_progstate[(int)progs2];
np = &pr_progstate[(int)newpr];
op = &pr_progstate[(int)oldpr];
if ((unsigned)progs1 >= maxprogs || !p1->globals)
PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", progs1);
if ((unsigned)progs2 >= maxprogs || !p2->globals)
PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", progs2);
if ((unsigned)newpr >= maxprogs || !np->globals)
PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", newpr);
if ((unsigned)oldpr >= maxprogs || !op->globals)
return;
//copy parms.
for (a = 0; a < MAX_PARMS;a++)
{
*(int *)&p1->globals[OFS_PARM0+3*a ] = *(int *)&p2->globals[OFS_PARM0+3*a ];
*(int *)&p1->globals[OFS_PARM0+3*a+1] = *(int *)&p2->globals[OFS_PARM0+3*a+1];
*(int *)&p1->globals[OFS_PARM0+3*a+2] = *(int *)&p2->globals[OFS_PARM0+3*a+2];
*(int *)&np->globals[OFS_PARM0+3*a ] = *(int *)&op->globals[OFS_PARM0+3*a ];
*(int *)&np->globals[OFS_PARM0+3*a+1] = *(int *)&op->globals[OFS_PARM0+3*a+1];
*(int *)&np->globals[OFS_PARM0+3*a+2] = *(int *)&op->globals[OFS_PARM0+3*a+2];
}
p1->globals[OFS_RETURN] = p2->globals[OFS_RETURN];
p1->globals[OFS_RETURN+1] = p2->globals[OFS_RETURN+1];
p1->globals[OFS_RETURN+2] = p2->globals[OFS_RETURN+2];
np->globals[OFS_RETURN] = op->globals[OFS_RETURN];
np->globals[OFS_RETURN+1] = op->globals[OFS_RETURN+1];
np->globals[OFS_RETURN+2] = op->globals[OFS_RETURN+2];
//move the vars defined as shared.
for (a = 0; a < numshares; a++)//fixme: make offset per progs
{
memmove(&((int *)p1->globals)[shares[a].varofs], &((int *)p2->globals)[shares[a].varofs], shares[a].size*4);
memmove(&((int *)np->globals)[shares[a].varofs], &((int *)op->globals)[shares[a].varofs], shares[a].size*4);
/* ((int *)p1->globals)[shares[a].varofs] = ((int *)p2->globals)[shares[a].varofs];
if (shares[a].size > 1)
{
@ -96,12 +104,11 @@ progsnum_t PR_LoadProgs(progfuncs_t *progfuncs, char *s, int headercrc, builtin_
#ifdef QCJIT
current_progstate->jit = PR_GenerateJit(progfuncs);
#endif
if (oldtype>=0)
if (oldtype != -1)
PR_SwitchProgs(progfuncs, oldtype);
return a; //we could load it. Yay!
}
if (oldtype!=-1)
PR_SwitchProgs(progfuncs, oldtype);
PR_SwitchProgs(progfuncs, oldtype);
return -1; // loading failed.
}
}

View File

@ -3682,7 +3682,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could
{ //you're allowed to use int 0 to pass a null function pointer
//this is basically because __NULL__ is defined as ~0 (int 0)
}
else if (p->type != ev_variant) //can cast to variant whatever happens
else if (p->type != ev_variant && e->type->type != ev_variant) //can cast to variant whatever happens
{
if (flag_laxcasts || (p->type == ev_function && e->type->type == ev_function))
{
@ -4808,7 +4808,10 @@ QCC_def_t *QCC_PR_Term (void)
//pointers
((newtype->type == ev_pointer || newtype->type == ev_string || newtype->type == ev_integer) && (e->type->type == ev_pointer || e->type->type == ev_string || e->type->type == ev_integer))
//ents/classs
|| (newtype->type == ev_entity && e->type->type == ev_entity))
|| (newtype->type == ev_entity && e->type->type == ev_entity)
//variants are fine too
|| (newtype->type == ev_variant || e->type->type == ev_variant)
)
{
//direct cast
e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t));

View File

@ -1875,6 +1875,7 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
QCC_def_t *d;
int f;
unsigned short crc;
QCC_def_t *ld;
// int c;
file[0] = '\0';
@ -1909,6 +1910,7 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
ADD3(qcva("\tint\tpad[%i];\n", RESERVED_OFS));
for (d=pr.def_head.next ; d ; d=d->next)
{
ld = d;
if (!strcmp (d->name, "end_sys_globals"))
break;
if (d->ofs<RESERVED_OFS)
@ -1921,7 +1923,8 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
break;
case ev_vector:
ADD(qcva("\tvec3_t\t%s;\n",d->name));
d=d->next->next->next; // skip the elements
if (d->deftail)
d=d->deftail; // skip the elements
break;
case ev_string:
ADD(qcva("\tstring_t\t%s;\n",d->name));
@ -1961,7 +1964,8 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
break;
case ev_vector:
ADD(qcva("\tvec3_t\t%s;\n",d->name));
d=d->next->next->next; // skip the elements
if (d->deftail)
d=d->deftail; // skip the elements
break;
case ev_string:
ADD(qcva("\tstring_t\t%s;\n",d->name));

File diff suppressed because it is too large Load Diff

View File

@ -457,7 +457,7 @@ static eval_t *Q1QVMPF_GetEdictFieldValue(progfuncs_t *pf, edict_t *e, char *fie
{
if (!strcmp(fieldname, "message"))
{
return (eval_t*)&e->v->_message;
return (eval_t*)&e->v->message;
}
return NULL;
}
@ -567,7 +567,7 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con
break;
case G_PRECACHE_MODEL:
PF_precache_model_Internal(svprogfuncs, VM_POINTER(arg[0]));
PF_precache_model_Internal(svprogfuncs, VM_POINTER(arg[0]), false);
break;
case G_LIGHTSTYLE:
@ -1417,7 +1417,7 @@ qboolean PR_LoadQ1QVM(void)
#define globalint(required, name) pr_global_ptrs->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) //the logic of this is somewhat crazy
#define globalfloat(required, name) pr_global_ptrs->name = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
#define globalstring(required, name) pr_global_ptrs->name = (string_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
#define globalvec(required, name) pr_global_ptrs->V_##name = (vec3_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
#define globalvec(required, name) pr_global_ptrs->name = (vec3_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
#define globalfunc(required, name) pr_global_ptrs->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name)
#define globalfloatnull(required, name) pr_global_ptrs->name = NULL
globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about.

View File

@ -54,16 +54,16 @@ typedef struct nqglobalvars_s
float *total_monsters;
float *found_secrets;
float *killed_monsters;
vec3_t *V_v_forward;
vec3_t *V_v_up;
vec3_t *V_v_right;
vec3_t *v_forward;
vec3_t *v_up;
vec3_t *v_right;
float *trace_allsolid;
float *trace_startsolid;
float *trace_fraction;
float *trace_surfaceflags;
float *trace_endcontents;
vec3_t *V_trace_endpos;
vec3_t *V_trace_plane_normal;
vec3_t *trace_endpos;
vec3_t *trace_plane_normal;
float *trace_plane_dist;
int *trace_ent;
float *trace_inopen;
@ -91,7 +91,7 @@ typedef struct nqglobalvars_s
float *spawnparamglobals[NUM_SPAWN_PARMS];
} globalptrs_t;
#define P_VEC(v) (pr_global_struct->V_##v)
#define P_VEC(v) (pr_global_struct->v)
/*my hands are tied when it comes to the layout of this structure
@ -102,163 +102,192 @@ But if we include all, that's a waste for csqc...
But we can overlap useful csqc-only ones with ssqc ones that are not going to be used on the client, so long as the types match.
This list isn't shared with the menu.
If the left has an underscore, it means we don't use in for ssqc at all, its dead, purely for the ssqc mod
If the middle has an underscore, then we don't use it in shared code.
If the right has an underscore, then we don't use it in csqc (yet)
if the middle has a valid name, both left+right must have valid names too.
so the base fields are a fixed size
and the extension fields are added on the end and can have extra vm-specific stuff added on the end
*/
/*DO NOT ADD TO THIS STRUCTURE (base-qw-compat for q1qvm)*/
#define comqcfields \
comfieldfloat(modelindex,modelindex,modelindex);\
comfieldvector(absmin,absmin,absmin);\
comfieldvector(absmax,absmax,absmax);\
comfieldfloat(ltime,ltime,_ltime);\
comfieldfloat(_lastruntime,lastruntime,_lastruntime); /*type doesn't match the qc, we use a hidden double instead. this is dead.*/ \
comfieldfloat(movetype,movetype,movetype);\
comfieldfloat(solid,solid,solid);\
comfieldvector(origin,origin,origin);\
comfieldvector(oldorigin,oldorigin,_oldorigin);\
comfieldvector(velocity,velocity,velocity);\
comfieldvector(angles,angles,angles);\
comfieldvector(avelocity,avelocity,avelocity);\
comfieldstring(classname,classname,classname);\
comfieldstring(model,model,model);\
comfieldfloat(frame,frame,frame);\
comfieldfloat(skin,skin,skin);\
comfieldfloat(effects,effects,effects);\
comfieldvector(mins,mins,mins);\
comfieldvector(maxs,maxs,maxs);\
comfieldvector(size,size,size);\
comfieldfunction(touch,touch,touch);\
comfieldfunction(_use,_use,_use);\
comfieldfunction(think,think,think);\
comfieldfunction(blocked,blocked,_blocked);\
comfieldfloat(nextthink,nextthink,nextthink);\
comfieldentity(groundentity,groundentity,groundentity);\
comfieldfloat(health,_health,_health);\
comfieldfloat(frags,_frags,_frags);\
comfieldfloat(weapon,_weapon,_weapon);\
comfieldstring(weaponmodel,_weaponmodel,_weaponmodel);\
comfieldfloat(weaponframe,_weaponframe,_weaponframe);\
comfieldfloat(currentammo,_currentammo,_currentammo);\
comfieldfloat(ammo_shells,_ammo_shells,_ammo_shells);\
comfieldfloat(ammo_nails,_ammo_nails,_ammo_nails);\
comfieldfloat(ammo_rockets,_ammo_rockets,_ammo_rockets);\
comfieldfloat(ammo_cells,_ammo_cells,_ammo_cells);\
comfieldfloat(items,_items,_items);\
comfieldfloat(takedamage,_takedamage,_takedamage);\
comfieldentity(chain,chain,chain);\
comfieldfloat(_deadflag,_deadflag,_deadflag);\
comfieldvector(view_ofs,view_ofs,_view_ofs);\
comfieldfloat(button0,_button0,_button0);\
comfieldfloat(button1,_button1,_button1); /*dead field in nq mode*/ \
comfieldfloat(button2,_button2,_button2);\
comfieldfloat(impulse,_impulse,_impulse);\
comfieldfloat(fixangle,_fixangle,_fixangle);\
comfieldvector(v_angle,v_angle,_v_angle);\
comfieldstring(netname,_netname,_netname);\
comfieldentity(enemy,enemy,enemy);\
comfieldfloat(flags,flags,flags);\
comfieldfloat(colormap,colormap,colormap);\
comfieldfloat(team,_team,_team);\
comfieldfloat(_max_health,_max_health,_max_health);\
comfieldfloat(teleport_time,_teleport_time,_teleport_time);\
comfieldfloat(_armortype,_armortype,_armortype);\
comfieldfloat(armorvalue,_armorvalue,_armorvalue);\
comfieldfloat(waterlevel,waterlevel,_waterlevel);\
comfieldfloat(watertype,watertype,_watertype);\
comfieldfloat(ideal_yaw,ideal_yaw,ideal_yaw);\
comfieldfloat(yaw_speed,yaw_speed,yaw_speed);\
comfieldentity(aiment,aiment,aiment);\
comfieldentity(goalentity,goalentity,goalentity);\
comfieldfloat(_spawnflags,_spawnflags,_spawnflags);\
comfieldstring(_target,_target,_target);\
comfieldstring(targetname,_targetname,_targetname);\
comfieldfloat(dmg_take,_dmg_take,_dmg_take);\
comfieldfloat(dmg_save,_dmg_save,_dmg_save);\
comfieldentity(dmg_inflictor,_dmg_inflictor,_dmg_inflictor);\
comfieldentity(owner,owner,owner);\
comfieldvector(movedir,movedir,movedir);\
comfieldstring(_message,_message,_message); /*not used directly, hexen2 uses floats, so we go via qclib for message*/\
comfieldfloat(sounds,_sounds,_sounds);\
comfieldstring(_noise,_noise,_noise);\
comfieldstring(_noise1,_noise1,_noise1);\
comfieldstring(_noise2,_noise2,_noise2);\
comfieldstring(_noise3,_noise3,_noise3);
comfieldfloat(modelindex)\
comfieldvector(absmin)\
comfieldvector(absmax)\
comfieldfloat(ltime)\
comfieldfloat(lastruntime) /*type doesn't match the qc, we use a hidden double instead. this is dead.*/ \
comfieldfloat(movetype)\
comfieldfloat(solid)\
comfieldvector(origin)\
comfieldvector(oldorigin)\
comfieldvector(velocity)\
comfieldvector(angles)\
comfieldvector(avelocity)\
comfieldstring(classname)\
comfieldstring(model)\
comfieldfloat(frame)\
comfieldfloat(skin)\
comfieldfloat(effects)\
comfieldvector(mins)\
comfieldvector(maxs)\
comfieldvector(size)\
comfieldfunction(touch, ".void()")\
comfieldfunction(use, ".void()")\
comfieldfunction(think, ".void()")\
comfieldfunction(blocked, ".void()")\
comfieldfloat(nextthink)\
comfieldentity(groundentity)\
comfieldfloat(health)\
comfieldfloat(frags)\
comfieldfloat(weapon)\
comfieldstring(weaponmodel)\
comfieldfloat(weaponframe)\
comfieldfloat(currentammo)\
comfieldfloat(ammo_shells)\
comfieldfloat(ammo_nails)\
comfieldfloat(ammo_rockets)\
comfieldfloat(ammo_cells)\
comfieldfloat(items)\
comfieldfloat(takedamage)\
comfieldentity(chain)\
comfieldfloat(deadflag)\
comfieldvector(view_ofs)\
comfieldfloat(button0)\
comfieldfloat(button1) /*dead field in nq mode*/ \
comfieldfloat(button2)\
comfieldfloat(impulse)\
comfieldfloat(fixangle)\
comfieldvector(v_angle)\
comfieldstring(netname)\
comfieldentity(enemy)\
comfieldfloat(flags)\
comfieldfloat(colormap)\
comfieldfloat(team)\
comfieldfloat(max_health)\
comfieldfloat(teleport_time)\
comfieldfloat(armortype)\
comfieldfloat(armorvalue)\
comfieldfloat(waterlevel)\
comfieldfloat(watertype)\
comfieldfloat(ideal_yaw)\
comfieldfloat(yaw_speed)\
comfieldentity(aiment)\
comfieldentity(goalentity)\
comfieldfloat(spawnflags)\
comfieldstring(target)\
comfieldstring(targetname)\
comfieldfloat(dmg_take)\
comfieldfloat(dmg_save)\
comfieldentity(dmg_inflictor)\
comfieldentity(owner)\
comfieldvector(movedir)\
comfieldstring(message) /*not used directly, hexen2 uses floats, so we go via qclib for message*/\
comfieldfloat(sounds)\
comfieldstring(noise)\
comfieldstring(noise1)\
comfieldstring(noise2)\
comfieldstring(noise3)
/*DO NOT ADD TO THE ABOVE STRUCTURE*/
#define comextqcfields \
comfieldvector(punchangle); /*std in nq*/\
comfieldfloat(gravity); /*added in quake 1.09 (for hipnotic)*/\
comfieldfloat(hull);/*PEXT_HEXEN2*/\
comfieldentity(movechain);/*hexen2*/\
comfieldfunction(chainmoved);/*hexen2*/\
comfieldfloat(dimension_solid);/*EXT_DIMENSION_PHYSICS*/\
comfieldfloat(dimension_hit);/*EXT_DIMENSION_PHYSICS*/\
comfieldfloat(scale);/*DP_ENT_SCALE*/\
comfieldfloat(fatness);/*FTE_PEXT_FATNESS*/\
comfieldfloat(alpha);/*DP_ENT_ALPHA*/\
comfieldvector(colormod);\
comfieldfloat(pmove_flags);/*EXT_CSQC_1*/\
comfieldfloat(jointtype);/*DP_...PHYSICS*/\
comfieldfloat(mass);/*DP_...PHYSICS*/\
comfieldfloat(bouncefactor);/*DP_...PHYSICS*/\
comfieldfloat(bouncestop);/*DP_...PHYSICS*/
comfieldvector(punchangle) /*std in nq*/\
comfieldfloat(gravity) /*added in quake 1.09 (for hipnotic)*/\
comfieldfloat(hull)/*PEXT_HEXEN2*/\
comfieldentity(movechain)/*hexen2*/\
comfieldfunction(chainmoved, ".void()")/*hexen2*/\
comfieldfloat(dimension_solid)/*EXT_DIMENSION_PHYSICS*/\
comfieldfloat(dimension_hit)/*EXT_DIMENSION_PHYSICS*/\
comfieldfloat(scale)/*DP_ENT_SCALE*/\
comfieldfloat(fatness)/*FTE_PEXT_FATNESS*/\
comfieldfloat(alpha)/*DP_ENT_ALPHA*/\
comfieldvector(colormod)\
comfieldfloat(pmove_flags)/*EXT_CSQC_1*/\
comfieldfloat(jointtype)/*DP_...PHYSICS*/\
comfieldfloat(mass)/*DP_...PHYSICS*/\
comfieldfloat(bouncefactor)/*DP_...PHYSICS*/\
comfieldfloat(bouncestop)/*DP_...PHYSICS*/
#define svextqcfields \
comfieldfloat(maxspeed);/*added in quake 1.09*/\
comfieldfloat(items2); /*added in quake 1.09 (for hipnotic)*/\
comfieldentity(view2);/*FTE_PEXT_VIEW2*/\
comfieldvector(movement);\
comfieldfloat(vw_index);\
comfieldentity(nodrawtoclient);\
comfieldentity(drawonlytoclient);\
comfieldentity(viewmodelforclient);/*DP_ENT_VIEWMODEL*/\
comfieldentity(exteriormodeltoclient);\
comfieldfloat(button3); /*DP_INPUTBUTTONS (note in qw, we set 1 to equal 3, to match zquake/fuhquake/mvdsv)*/\
comfieldfloat(button4);\
comfieldfloat(button5);\
comfieldfloat(button6);\
comfieldfloat(button7);\
comfieldfloat(button8);\
comfieldfloat(viewzoom);/*DP_VIEWZOOM*/\
comfieldentity(tag_entity);\
comfieldfloat(tag_index);\
comfieldfloat(glow_size);\
comfieldfloat(glow_color);\
comfieldfloat(glow_trail);\
comfieldvector(color);/*Hexen2 has a .float color, the warnings should be benign*/ \
comfieldfloat(light_lev);\
comfieldfloat(style);\
comfieldfloat(pflags);\
comfieldfloat(clientcolors);\
comfieldfloat(dimension_see);/*EXT_DIMENSION_VISIBLE*/\
comfieldfloat(dimension_seen);/*EXT_DIMENSION_VISIBLE*/\
comfieldfloat(dimension_ghost);/*EXT_DIMENSION_GHOST*/\
comfieldfloat(dimension_ghost_alpha);/*EXT_DIMENSION_GHOST*/\
comfieldfloat(playerclass);/*hexen2 requirements*/\
comfieldfloat(drawflags);/*hexen2*/\
comfieldfloat(hasted);/*hexen2 uses this AS WELL as maxspeed*/\
comfieldfloat(light_level);/*hexen2's grabbing light level from client*/\
comfieldfloat(abslight);/*hexen2's force a lightlevel*/\
comfieldfunction(SendEntity);/*EXT_CSQC*/\
comfieldfloat(SendFlags);/*EXT_CSQC_1 (one of the DP guys came up with it)*/\
comfieldfloat(Version);/*EXT_CSQC (obsolete)*/\
comfieldfloat(pvsflags);/*EXT_CSQC_1*/\
comfieldfloat(uniquespawnid);/*FTE_ENT_UNIQUESPAWNID*/\
comfieldfunction(customizeentityforclient);
comfieldfloat(maxspeed)/*added in quake 1.09*/\
comfieldfloat(items2) /*added in quake 1.09 (for hipnotic)*/\
comfieldentity(view2)/*FTE_PEXT_VIEW2*/\
comfieldvector(movement)\
comfieldfloat(vw_index)\
comfieldentity(nodrawtoclient)\
comfieldentity(drawonlytoclient)\
comfieldentity(viewmodelforclient)/*DP_ENT_VIEWMODEL*/\
comfieldentity(exteriormodeltoclient)\
comfieldfloat(button3) /*DP_INPUTBUTTONS (note in qw, we set 1 to equal 3, to match zquake/fuhquake/mvdsv)*/\
comfieldfloat(button4)\
comfieldfloat(button5)\
comfieldfloat(button6)\
comfieldfloat(button7)\
comfieldfloat(button8)\
comfieldfloat(viewzoom)/*DP_VIEWZOOM*/\
comfieldentity(tag_entity)\
comfieldfloat(tag_index)\
comfieldfloat(glow_size)\
comfieldfloat(glow_color)\
comfieldfloat(glow_trail)\
comfieldvector(color)/*Hexen2 has a .float color, the warnings should be benign*/ \
comfieldfloat(light_lev)\
comfieldfloat(style)\
comfieldfloat(pflags)\
comfieldfloat(clientcolors)\
comfieldfloat(dimension_see)/*EXT_DIMENSION_VISIBLE*/\
comfieldfloat(dimension_seen)/*EXT_DIMENSION_VISIBLE*/\
comfieldfloat(dimension_ghost)/*EXT_DIMENSION_GHOST*/\
comfieldfloat(dimension_ghost_alpha)/*EXT_DIMENSION_GHOST*/\
comfieldfloat(playerclass)/*hexen2 requirements*/\
comfieldfloat(drawflags)/*hexen2*/\
comfieldfloat(hasted)/*hexen2 uses this AS WELL as maxspeed*/\
comfieldfloat(light_level)/*hexen2's grabbing light level from client*/\
comfieldfloat(abslight)/*hexen2's force a lightlevel*/\
comfieldfunction(SendEntity, ".float(entity playerent, float changedflags)")/*EXT_CSQC*/\
comfieldfloat(SendFlags)/*EXT_CSQC_1 (one of the DP guys came up with it)*/\
comfieldfloat(Version)/*EXT_CSQC (obsolete)*/\
comfieldfloat(pvsflags)/*EXT_CSQC_1*/\
comfieldfloat(uniquespawnid)/*FTE_ENT_UNIQUESPAWNID*/\
comfieldfunction(customizeentityforclient, ".float()")
//this is the list for all the csqc fields.
//(the #define is so the list always matches the ones pulled out)
#define csqcextfields \
comfieldfloat(entnum) \
comfieldfloat(frame2) /*EXT_CSQC_1*/\
comfieldfloat(frame1time) /*EXT_CSQC_1*/\
comfieldfloat(frame2time) /*EXT_CSQC_1*/\
comfieldfloat(lerpfrac) /*EXT_CSQC_1*/\
comfieldfloat(renderflags)\
comfieldfloat(forceshader)/*FTE_CSQC_SHADERS*/\
\
comfieldfloat(baseframe) /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(baseframe2) /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(baseframe1time) /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(baseframe2time) /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(baselerpfrac) /*FTE_CSQC_BASEFRAME*/\
comfieldfloat(basebone) /*FTE_CSQC_BASEFRAME*/\
\
comfieldfloat(bonecontrol1) /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(bonecontrol2) /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(bonecontrol3) /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(bonecontrol4) /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(bonecontrol5) /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(subblendfrac) /*FTE_CSQC_HALFLIFE_MODELS*/\
comfieldfloat(basesubblendfrac) /*FTE_CSQC_HALFLIFE_MODELS+FTE_CSQC_BASEFRAME*/\
\
comfieldfloat(skeletonindex) /*FTE_CSQC_SKELETONOBJECTS*/\
\
comfieldfloat(drawmask) /*So that the qc can specify all rockets at once or all bannanas at once*/ \
comfieldfunction(predraw, ".void()") /*If present, is called just before it's drawn.*/ \
comfieldvector(glowmod) \
\
comfieldfloat(ideal_pitch)\
comfieldfloat(pitch_speed)
typedef struct stdentvars_s //standard = standard for qw
{
#define comfieldfloat(ssqcname,sharedname,csqcname) float ssqcname
#define comfieldvector(ssqcname,sharedname,csqcname) vec3_t ssqcname
#define comfieldentity(ssqcname,sharedname,csqcname) int ssqcname
#define comfieldstring(ssqcname,sharedname,csqcname) string_t ssqcname
#define comfieldfunction(ssqcname,sharedname,csqcname) func_t ssqcname
#define comfieldfloat(sharedname) float sharedname;
#define comfieldvector(sharedname) vec3_t sharedname;
#define comfieldentity(sharedname) int sharedname;
#define comfieldstring(sharedname) string_t sharedname;
#define comfieldfunction(sharedname, typestr) func_t sharedname;
comqcfields
#undef comfieldfloat
#undef comfieldvector
@ -271,11 +300,11 @@ comqcfields
typedef struct extentvars_s
{
#endif
#define comfieldfloat(name) float name
#define comfieldvector(name) vec3_t name
#define comfieldentity(name) int name
#define comfieldstring(name) string_t name
#define comfieldfunction(name) func_t name
#define comfieldfloat(name) float name;
#define comfieldvector(name) vec3_t name;
#define comfieldentity(name) int name;
#define comfieldstring(name) string_t name;
#define comfieldfunction(name, typestr) func_t name;
comextqcfields
svextqcfields
#undef comfieldfloat
@ -291,11 +320,11 @@ svextqcfields
#endif
typedef struct {
#define comfieldfloat(ssqcname,sharedname,csqcname) float sharedname
#define comfieldvector(ssqcname,sharedname,csqcname) vec3_t sharedname
#define comfieldentity(ssqcname,sharedname,csqcname) int sharedname
#define comfieldstring(ssqcname,sharedname,csqcname) string_t sharedname
#define comfieldfunction(ssqcname,sharedname,csqcname) func_t sharedname
#define comfieldfloat(sharedname) float sharedname;
#define comfieldvector(sharedname) vec3_t sharedname;
#define comfieldentity(sharedname) int sharedname;
#define comfieldstring(sharedname) string_t sharedname;
#define comfieldfunction(sharedname, typestr) func_t sharedname;
comqcfields
#undef comfieldfloat
#undef comfieldvector
@ -308,11 +337,11 @@ comqcfields
typedef struct {
#endif
#define comfieldfloat(name) float name
#define comfieldvector(name) vec3_t name
#define comfieldentity(name) int name
#define comfieldstring(name) string_t name
#define comfieldfunction(name) func_t name
#define comfieldfloat(name) float name;
#define comfieldvector(name) vec3_t name;
#define comfieldentity(name) int name;
#define comfieldstring(name) string_t name;
#define comfieldfunction(name, typestr) func_t name;
comextqcfields
#undef comfieldfloat
#undef comfieldvector
@ -366,7 +395,16 @@ typedef struct {
vec3_t ode_joint_movedir; // parameters
void *ode_massbuf;
} entityode_t;
/*
typedef struct
{
void *ode_body;
} skelbodyode_t;
typedef struct
{
int dummy;
} skeljointode_t;
*/
typedef struct
{
// for ODE physics engine

View File

@ -183,9 +183,10 @@ typedef struct
qbyte master_buf[MAX_DATAGRAM];
// the signon buffer will be sent to each client as they connect
// includes the entity baselines, the static entities, etc
// traditionally includes the entity baselines, the static entities, etc
// large levels will have >MAX_DATAGRAM sized signons, so
// multiple signon messages are kept
// fte only stores writebyted stuff in here. everything else is regenerated based upon the client's extensions.
sizebuf_t signon;
int num_signon_buffers;
int signon_buffer_size[MAX_SIGNON_BUFFERS];
@ -1002,6 +1003,7 @@ qboolean SVQ3_Command(void);
//
// sv_phys.c
//
void WPhys_Init(void);
void SV_SetMoveVars(void);
void WPhys_RunNewmis (world_t *w);
qboolean SV_Physics (void);
@ -1030,6 +1032,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, char *sample, int volume, float attenuation, int pitchadj);
void SVQ1_StartSound (wedict_t *entity, int channel, char *sample, int volume, float attenuation, int pitchadj);
void SV_PrintToClient(client_t *cl, int level, char *string);
void SV_StuffcmdToClient(client_t *cl, char *string);
void VARGS SV_ClientPrintf (client_t *cl, int level, char *fmt, ...) LIKEPRINTF(3);
void VARGS SV_ClientTPrintf (client_t *cl, int level, translation_t text, ...);
void VARGS SV_BroadcastPrintf (int level, char *fmt, ...) LIKEPRINTF(2);

View File

@ -384,6 +384,8 @@ int ShowMapList (const char *name, int flags, void *parm)
void SV_MapList_f(void)
{
COM_EnumerateFiles("maps/*.bsp", ShowMapList, NULL);
COM_EnumerateFiles("maps/*.cm", ShowMapList, NULL);
COM_EnumerateFiles("maps/*.hmp", ShowMapList, NULL);
}
void gtcallback(struct cvar_s *var, char *oldvalue)
@ -615,7 +617,14 @@ void SV_Map_f (void)
SCR_ImageName(level);
#endif
SV_BroadcastCommand ("changing \"%s\"\n", level);
for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
{
/*pass the new map's name as an extension, so appropriate loading screens can be shown*/
if (ISNQCLIENT(host_client))
SV_StuffcmdToClient(host_client, va("restart \"%s\"\n", level));
else
SV_StuffcmdToClient(host_client, va("changing \"%s\"\n", level));
}
SV_SendMessagesToAll ();
if (newunit || !startspot || !SV_LoadLevelCache(NULL, level, startspot, false))

View File

@ -61,15 +61,31 @@ int SV_ModelIndex (char *name)
return i;
if (i==MAX_MODELS || !sv.strings.model_precache[i])
{
if (i!=MAX_MODELS && sv.state == ss_loading)
if (i!=MAX_MODELS)
{
Q_strncpyz(sv.strings.model_precache[i], name, sizeof(sv.strings.model_precache[i]));
#ifdef VM_Q1
if (svs.gametype == GT_Q1QVM)
sv.strings.model_precache[i] = name;
else
#endif
sv.strings.model_precache[i] = PR_AddString(svprogfuncs, name, 0);
if (!strcmp(name + strlen(name) - 4, ".bsp"))
sv.models[i] = Mod_FindName(sv.strings.model_precache[i]);
Con_Printf("WARNING: SV_ModelIndex: model %s not precached\n", name);
Con_DPrintf("WARNING: SV_ModelIndex: model %s not precached\n", name);
if (sv.state != ss_loading)
{
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i);
MSG_WriteString(&sv.reliable_datagram, sv.strings.model_precache[i]);
#ifdef NQPROT
MSG_WriteByte(&sv.nqreliable_datagram, svcdp_precache);
MSG_WriteShort(&sv.nqreliable_datagram, i);
MSG_WriteString(&sv.nqreliable_datagram, sv.strings.model_precache[i]);
#endif
}
}
else
SV_Error ("SV_ModelIndex: model %s not precached", name);
}
return i;
}
@ -798,6 +814,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
sv.signon.prim = svs.netprim;
sv.num_signon_buffers = 1;
FS_ReferenceControl(1, 1);
strcpy (sv.name, server);
#ifndef SERVERONLY
current_loading_size+=10;
@ -1528,6 +1546,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
}
}
FS_ReferenceControl(0, 0);
SV_MVD_SendInitialGamestate(NULL);
}

View File

@ -130,7 +130,7 @@ cvar_t allow_download_configs = CVAR("allow_download_configs", "0");
cvar_t sv_public = CVAR("sv_public", "0");
cvar_t sv_listen_qw = CVARAF("sv_listen_qw", "1", "sv_listen", 0);
cvar_t sv_listen_nq = CVAR("sv_listen_nq", "0");
cvar_t sv_listen_nq = CVARD("sv_listen_nq", "2", "Allow new (net)quake clients to connect to the server. 0 = don't let them in. 1 = allow them in (WARNING: this allows 'qsmurf' DOS attacks). 2 = accept (net)quake clients by emulating a challenge (as secure as QW/Q2 but does not fully conform to the NQ protocol).");
cvar_t sv_listen_dp = CVAR("sv_listen_dp", "0"); /*kinda fucked right now*/
cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0");
cvar_t sv_reportheartbeats = CVAR("sv_reportheartbeats", "1");
@ -164,10 +164,10 @@ cvar_t sv_port_tcp6 = CVARC("sv_port_tcp6", "", SV_Tcpport6_Callback);
#endif
cvar_t sv_port_ipv4 = CVARC("sv_port", "27500", SV_Port_Callback);
#ifdef IPPROTO_IPV6
cvar_t sv_port_ipv6 = CVARC("sv_port_ipv6", "27500", SV_PortIPv6_Callback);
cvar_t sv_port_ipv6 = CVARC("sv_port_ipv6", "", SV_PortIPv6_Callback);
#endif
#ifdef USEIPX
cvar_t sv_port_ipx = CVARC("sv_port_ipx", "27500", SV_PortIPX_Callback);
cvar_t sv_port_ipx = CVARC("sv_port_ipx", "", SV_PortIPX_Callback);
#endif
cvar_t pausable = CVAR("pausable", "1");
@ -491,7 +491,8 @@ void SV_DropClient (client_t *drop)
// call the prog function for removing a client
// this will set the body to a dead frame, among other things
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, drop->edict);
PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientDisconnect);
if (pr_global_ptrs->ClientDisconnect)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientDisconnect);
}
else if (SpectatorDisconnect)
{
@ -2873,7 +2874,78 @@ void SVNQ_ConnectionlessPacket(void)
MSG_BeginReading(svs.netprim);
header = LongSwap(MSG_ReadLong());
if (!(header & NETFLAG_CTL))
{
if (sv_listen_nq.ival == 2)
if ((header & (NETFLAG_DATA|NETFLAG_EOM)) == (NETFLAG_DATA|NETFLAG_EOM))
{
int sequence;
sequence = LongSwap(MSG_ReadLong());
if (sequence <= 1)
{
int numnops = 0;
int numnonnops = 0;
/*make it at least robust enough to ignore any other stringcmds*/
while(1)
{
switch(MSG_ReadByte())
{
case clc_nop:
numnops++;
continue;
case clc_stringcmd:
numnonnops++;
Cmd_TokenizeString(MSG_ReadString(), false, false);
if (!strcmp("challengeconnect", Cmd_Argv(0)))
{
client_t *newcl;
/*okay, so this is a reliable packet from a client, containing a 'cmd challengeconnect $challenge' response*/
str = va("connect %i %i %s \"\\name\\unconnected\"", NET_PROTOCOL_VERSION, 0, Cmd_Argv(1));
Cmd_TokenizeString (str, false, false);
newcl = SVC_DirectConnect();
if (newcl)
newcl->netchan.incoming_reliable_sequence = sequence;
/*if there is anything else in the packet, we don't actually care. its reliable, so they'll resend*/
return;
}
continue;
case -1:
break;
default:
numnonnops++;
break;
}
break;
}
if (numnops && !numnonnops)
{
sb.maxsize = sizeof(buffer);
sb.data = buffer;
/*ack it, so dumb proquake clones can actually send the proper packet*/
SZ_Clear(&sb);
MSG_WriteLong(&sb, BigLong(NETFLAG_ACK | 8));
MSG_WriteLong(&sb, sequence);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
/*resend the cmd request, cos if they didn't send it then it must have gotten dropped*/
SZ_Clear(&sb);
MSG_WriteLong(&sb, 0);
MSG_WriteLong(&sb, 0);
MSG_WriteByte(&sb, svc_stufftext);
MSG_WriteString(&sb, va("cmd challengeconnect %i\n", SV_NewChallenge()));
*(int*)sb.data = BigLong(NETFLAG_UNRELIABLE|sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
}
}
}
return; //no idea what it is.
}
length = header & NETFLAG_LENGTH_MASK;
if (length != net_message.cursize)
@ -2916,10 +2988,35 @@ void SVNQ_ConnectionlessPacket(void)
}
else
{
str = va("connect %i %i %i \"\\name\\unconnected\"", NET_PROTOCOL_VERSION, 0, SV_NewChallenge());
Cmd_TokenizeString (str, false, false);
if (sv_listen_nq.ival == 2)
{
SZ_Clear(&sb);
MSG_WriteLong(&sb, 0);
MSG_WriteByte(&sb, CCREP_ACCEPT);
NET_LocalAddressForRemote(svs.sockets, &net_from, &localaddr, 0);
MSG_WriteLong(&sb, ShortSwap(localaddr.port));
*(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
SVC_DirectConnect();
SZ_Clear(&sb);
MSG_WriteLong(&sb, 0);
MSG_WriteLong(&sb, 0);
MSG_WriteByte(&sb, svc_stufftext);
MSG_WriteString(&sb, va("cmd challengeconnect %i\n", SV_NewChallenge()));
*(int*)sb.data = BigLong(NETFLAG_UNRELIABLE|sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from);
/*don't worry about repeating, the nop case above will recover it*/
}
else
{
str = va("connect %i %i %i \"\\name\\unconnected\"", NET_PROTOCOL_VERSION, 0, SV_NewChallenge());
Cmd_TokenizeString (str, false, false);
SVC_DirectConnect();
}
}
break;
case CCREQ_SERVER_INFO:
@ -3615,7 +3712,7 @@ float SV_Frame (void)
sv.gamespeed = 1;
#ifndef SERVERONLY
if ((sv.paused & 4) != ((!isDedicated && sv.allocated_client_slots == 1 && key_dest != key_game)?4:0))
if ((sv.paused & 4) != ((!isDedicated && sv.allocated_client_slots == 1 && key_dest != key_game && cls.state == ca_active)?4:0))
sv.paused ^= 4;
#endif
@ -4091,12 +4188,15 @@ void SV_InitLocal (void)
int port = atoi(com_argv[p+1]);
if (!port)
port = PORT_QWSERVER;
Cvar_SetValue(&sv_port_ipv4, port);
if (*sv_port_ipv4.string)
Cvar_SetValue(&sv_port_ipv4, port);
#ifdef IPPROTO_IPV6
Cvar_SetValue(&sv_port_ipv6, port);
if (*sv_port_ipv6.string)
Cvar_SetValue(&sv_port_ipv6, port);
#endif
#ifdef USEIPX
Cvar_SetValue(&sv_port_ipx, port);
if (*sv_port_ipx.string)
Cvar_SetValue(&sv_port_ipx, port);
#endif
}

View File

@ -1245,7 +1245,10 @@ void SV_ProgStartFrame (void)
Q1QVM_StartFrame();
else
#endif
PR_ExecuteProgram (svprogfuncs, pr_global_struct->StartFrame);
{
if (pr_global_ptrs->StartFrame)
PR_ExecuteProgram (svprogfuncs, *pr_global_ptrs->StartFrame);
}
}
#endif
@ -1837,8 +1840,8 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent)
Q1QVM_PlayerPreThink();
else
#endif
if (pr_global_struct->PlayerPreThink)
PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPreThink);
if (pr_global_ptrs->PlayerPreThink)
PR_ExecuteProgram (svprogfuncs, *pr_global_ptrs->PlayerPreThink);
if (readyforjump) //qw progs can't jump for themselves...
{
@ -1936,8 +1939,8 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent)
else
#endif
{
if (pr_global_struct->PlayerPostThink)
PR_ExecuteProgram (w->progs, pr_global_struct->PlayerPostThink);
if (pr_global_ptrs->PlayerPostThink)
PR_ExecuteProgram (w->progs, *pr_global_ptrs->PlayerPostThink);
}
}
#endif
@ -2075,12 +2078,6 @@ void World_Physics_Frame(world_t *w)
WPhys_RunEntity (w, ent);
WPhys_RunNewmis (w);
if (((!ent->solidtype) != (!(qbyte)ent->v->solid)) && !ent->isfree)
{
Con_DPrintf("Entity \"%s\" improperly changed solid type\n", PR_GetString(w->progs, ent->v->classname));
World_LinkEdict (w, ent, true); // a change of solidity should always relink the edict. someone messed up.
}
}
if (retouch)

View File

@ -264,6 +264,31 @@ void SV_PrintToClient(client_t *cl, int level, char *string)
}
}
void SV_StuffcmdToClient(client_t *cl, char *string)
{
switch (cl->protocol)
{
case SCP_BAD: //bot
break;
case SCP_QUAKE2:
#ifdef Q2SERVER
ClientReliableWrite_Begin (cl, svcq2_stufftext, strlen(string)+3);
ClientReliableWrite_String (cl, string);
#endif
break;
case SCP_QUAKE3:
break;
case SCP_QUAKEWORLD:
case SCP_DARKPLACES6:
case SCP_DARKPLACES7:
case SCP_NETQUAKE:
case SCP_FITZ666:
ClientReliableWrite_Begin (cl, svc_stufftext, strlen(string)+3);
ClientReliableWrite_String (cl, string);
break;
}
}
/*
=================
@ -1880,6 +1905,7 @@ void SV_UpdateToReliableMessages (void)
{
if (strcmp(host_client->name, name))
{
Con_DPrintf("Client %s programatically renamed to %s\n", host_client->name, name);
Info_SetValueForKey(host_client->userinfo, "name", name, sizeof(host_client->userinfo));
if (!strcmp(Info_ValueForKey(host_client->userinfo, "name"), name))
{

View File

@ -782,7 +782,7 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
dir = opendir(truepath);
if (!dir)
{
Con_Printf("Failed to open dir %s\n", truepath);
Con_DPrintf("Failed to open dir %s\n", truepath);
return true;
}
do

View File

@ -409,7 +409,7 @@ void SV_New_f (void)
{
char buffer[1024];
FS_GetPackNames(buffer, sizeof(buffer), false, true); /*retain extensions, or we'd have to assume pk3*/
FS_GetPackNames(buffer, sizeof(buffer), 2, true); /*retain extensions, or we'd have to assume pk3*/
ClientReliableWrite_Begin(host_client, svc_stufftext, 1+11+strlen(buffer)+1+1);
ClientReliableWrite_SZ(host_client, "//paknames ", 11);
ClientReliableWrite_SZ(host_client, buffer, strlen(buffer));
@ -1693,13 +1693,26 @@ void SV_Begin_Core(client_t *split)
pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict);
G_FLOAT(OFS_PARM0) = split->csqcactive; //this arg is part of EXT_CSQC_1, but doesn't have to be supported by the mod
PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientConnect);
if (pr_globals)
G_FLOAT(OFS_PARM0) = split->csqcactive; //this arg is part of EXT_CSQC_1, but doesn't have to be supported by the mod
if (pr_global_ptrs->ClientConnect)
PR_ExecuteProgram (svprogfuncs, *pr_global_ptrs->ClientConnect);
// actually spawn the player
pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, split->edict);
PR_ExecuteProgram (svprogfuncs, pr_global_struct->PutClientInServer);
if (pr_global_ptrs->PutClientInServer)
PR_ExecuteProgram (svprogfuncs, *pr_global_ptrs->PutClientInServer);
else
{
split->edict->v->health = 100;
split->edict->v->mins[0] = -16;
split->edict->v->mins[1] = -16;
split->edict->v->mins[2] = -24;
split->edict->v->maxs[0] = 16;
split->edict->v->maxs[1] = 16;
split->edict->v->maxs[2] = 32;
}
}
oh = host_client;
@ -2475,7 +2488,7 @@ qboolean SV_AllowDownload (const char *name)
if (!strcmp("pk4", COM_FileExtension(name)) || !strcmp("pk3", COM_FileExtension(name)) || !strcmp("pak", COM_FileExtension(name)))
{
/*do not permit 'id1/pak1.pak' or 'baseq3/pak0.pk3' or any similarly named packages. such packages would violate copyright, and must be obtained through other means (like buying the damn game)*/
//if (!strstr(name, "/pak"))
if (!strstr(name, "/pak"))
return !!allow_download_packages.value;
}
return false;
@ -2510,7 +2523,7 @@ qboolean SV_AllowDownload (const char *name)
//pak/pk3s.
if (!strcmp("pk4", COM_FileExtension(name)) || !strcmp("pk3", COM_FileExtension(name)) || !strcmp("pak", COM_FileExtension(name)))
if (strnicmp(name, "pak", 3)) //don't give out q3 pk3 files.
if (strnicmp(name, "pak", 3)) //don't give out core pak/pk3 files. This matches q3 logic.
return !!allow_download_packages.value;
if (!strcmp("cfg", COM_FileExtension(name)))
@ -2575,11 +2588,14 @@ static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementnam
if (!strncmp(name, "package/", 8))
{
vfsfile_t *f;
f = FS_OpenVFS(name+8, "rb", FS_ROOT);
if (f)
if (FS_GetPackageDownloadable(name+8))
{
VFS_CLOSE(f);
return -5; //found package
f = FS_OpenVFS(name+8, "rb", FS_ROOT);
if (f)
{
VFS_CLOSE(f);
return -5; //found package
}
}
return -1; //not found
}
@ -4226,34 +4242,34 @@ void Cmd_FPSList_f(void)
if (!cl->state)
continue;
if (cl->protocol != SCP_QUAKEWORLD)
continue;
if (cl->frameunion.frames)
if (ISQWCLIENT(cl) || ISNQCLIENT(cl))
{
for (f = 0; f < UPDATE_BACKUP; f++)
if (cl->frameunion.frames)
{
if (cl->frameunion.frames[f].move_msecs >= 0)
for (f = 0; f < UPDATE_BACKUP; f++)
{
if (!cl->frameunion.frames[f].move_msecs)
if (cl->frameunion.frames[f].move_msecs >= 0)
{
this = 1001;
msecs+=1;
}
else
{
this = 1000.0f/cl->frameunion.frames[f].move_msecs;
msecs += cl->frameunion.frames[f].move_msecs;
}
ftime += this;
if (minf > this)
minf = this;
if (maxf < this)
maxf = this;
frames++;
if (!cl->frameunion.frames[f].move_msecs)
{
this = 1001;
msecs+=1;
}
else
{
this = 1000.0f/cl->frameunion.frames[f].move_msecs;
msecs += cl->frameunion.frames[f].move_msecs;
}
ftime += this;
if (minf > this)
minf = this;
if (maxf < this)
maxf = this;
frames++;
inbytes += cl->frameunion.frames[f].packetsizein;
outbytes += cl->frameunion.frames[f].packetsizeout;
inbytes += cl->frameunion.frames[f].packetsizein;
outbytes += cl->frameunion.frames[f].packetsizeout;
}
}
}
}
@ -4781,19 +4797,20 @@ typedef struct
ucmd_t ucmds[] =
{
/*connection process*/
{"new", SV_New_f, true},
#ifdef PEXT_PK3DOWNLOADS
{"pk3list", SV_PK3List_f, true},
#endif
{"modellist", SV_Modellist_f, true},
{"soundlist", SV_Soundlist_f, true},
{"prespawn", SVQW_PreSpawn_f, true},
{"spawn", SV_Spawn_f, true},
{"begin", SV_Begin_f, true},
/*ezquake warning*/
{"al", SV_STFU_f, true},
{"join", Cmd_Join_f},
{"observe", Cmd_Observe_f},
{"drop", SV_Drop_f},
{"disconnect", SV_Drop_f},
{"pings", SV_Pings_f},
@ -4809,18 +4826,25 @@ ucmd_t ucmds[] =
{"say_team", SV_Say_Team_f},
{"setinfo", SV_SetInfo_f},
{"serverinfo", SV_ShowServerinfo_f},
/*demo/download commands*/
{"stopdownload", SV_StopDownload_f},
{"demolist", SV_UserCmdMVDList_f},
{"demoinfo", SV_MVDInfo_f},
{"dlsize", SV_DownloadSize_f},
{"download", SV_BeginDownload_f},
{"nextdl", SV_NextDownload_f},
/*quakeworld specific things*/
{"join", Cmd_Join_f},
{"observe", Cmd_Observe_f},
{"snap", SV_NoSnap_f},
{"ptrack", SV_PTrack_f}, //ZOID - used with autocam
{"enablecsqc", SV_EnableClientsCSQC},
{"disablecsqc", SV_DisableClientsCSQC},
{"snap", SV_NoSnap_f},
{"vote", SV_Vote_f},
#ifdef SVRANKING
@ -4835,10 +4859,6 @@ ucmd_t ucmds[] =
{"notarget", Cmd_Notarget_f},
{"setpos", Cmd_SetPos_f},
{"stopdownload", SV_StopDownload_f},
{"demolist", SV_UserCmdMVDList_f},
{"demoinfo", SV_MVDInfo_f},
#ifdef VOICECHAT
{"voicetarg", SV_Voice_Target_f},
{"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/
@ -4883,37 +4903,42 @@ ucmd_t ucmdsq2[] = {
ucmd_t nqucmds[] =
{
{"new", SVNQ_New_f, true},
{"spawn", SVNQ_Spawn_f, true},
{"begin", SVNQ_Begin_f, true},
{"prespawn", SVNQ_PreSpawn_f, true},
{"status", NULL},
{"god", Cmd_God_f},
{"give", Cmd_Give_f},
{"notarget", Cmd_Notarget_f},
{"fly", Cmd_Fly_f},
{"noclip", Cmd_Noclip_f},
{"pings", SV_Pings_f},
{"name", SVNQ_NQInfo_f},
{"say", SV_Say_f},
{"say_team", SV_Say_Team_f},
{"tell", SV_SayOne_f},
{"color", SVNQ_NQColour_f},
{"efpslist", Cmd_FPSList_f}, //don't conflict with the ktpro one
{"pings", SV_Pings_f},
{"ping", SVNQ_Ping_f},
{"kill", SV_Kill_f},
{"pause", SV_Pause_f},
{"spawn", SVNQ_Spawn_f, true},
{"begin", SVNQ_Begin_f, true},
{"prespawn", SVNQ_PreSpawn_f, true},
{"kick", NULL},
{"ping", SVNQ_Ping_f},
{"ban", NULL},
{"vote", SV_Vote_f},
/*DP download protocol*/
{"dlsize", SV_DownloadSize_f},
{"download", SV_BeginDownload_f},
{"sv_startdownload", SVDP_StartDownload_f},
/*userinfo stuff*/
{"setinfo", SV_SetInfo_f},
{"name", SVNQ_NQInfo_f},
{"color", SVNQ_NQColour_f},
{"playermodel", NULL},
{"playerskin", NULL},
{"rate", SV_Rate_f},
@ -4922,9 +4947,11 @@ ucmd_t nqucmds[] =
{"topten", Rank_ListTop10_f},
#endif
/*various misc extensions*/
{"pext", SV_Pext_f},
{"enablecsqc", SV_EnableClientsCSQC},
{"disablecsqc", SV_DisableClientsCSQC},
#ifdef VOICECHAT
{"voicetarg", SV_Voice_Target_f},
{"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/
@ -5608,7 +5635,8 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
Q1QVM_PlayerPreThink();
else
#endif
PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPreThink);
if (pr_global_ptrs->PlayerPreThink)
PR_ExecuteProgram (svprogfuncs, *pr_global_ptrs->PlayerPreThink);
if (progstype != PROG_QW)
{
@ -5827,7 +5855,8 @@ void SV_PostRunCmd(void)
pr_global_struct->time = sv.time;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player);
PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPostThink);
if (pr_global_ptrs->PlayerPostThink)
PR_ExecuteProgram (svprogfuncs, *pr_global_ptrs->PlayerPostThink);
WPhys_RunNewmis (&sv.world);
}
@ -5946,7 +5975,7 @@ void SV_ReadQCRequest(void)
G_INT(OFS_PARM0+i*3) = PR_TempString(svprogfuncs, MSG_ReadString());
break;
case ev_entity:
args[i] = 's';
args[i] = 'e';
e = MSG_ReadShort();
if (e < 0 || e >= sv.world.num_edicts)
e = 0;
@ -6535,6 +6564,9 @@ void SVNQ_ReadClientMove (usercmd_t *move)
move->msec=timesincelast*1000;//MSG_ReadFloat;
frame->move_msecs = move->msec;
// read buttons
if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7)
bits = MSG_ReadLong();
@ -6618,6 +6650,9 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
// save time for ping calculations
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].senttime = realtime;
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1;
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].move_msecs = -1;
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].packetsizein = net_message.cursize;
cl->frameunion.frames[cl->netchan.outgoing_sequence & UPDATE_MASK].packetsizeout = 0;
host_client = cl;
sv_player = host_client->edict;
@ -6648,7 +6683,9 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
return;
case clc_disconnect:
SV_DropClient (cl);
host_client = cl;
sv_player = cl->edict;
SV_Drop_f();
break;
case clc_nop:
break;

View File

@ -61,6 +61,7 @@ int QDECL GHL_PrecacheModel(char *name)
if (sv.state != ss_loading)
{
Con_DPrintf("Delayed model precache: %s\n", s);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, i);
MSG_WriteString(&sv.reliable_datagram, name);
@ -105,6 +106,7 @@ int QDECL GHL_PrecacheSound(char *name)
if (sv.state != ss_loading)
{
Con_DPrintf("Delayed sound precache: %s\n", s);
MSG_WriteByte(&sv.reliable_datagram, svcfte_precache);
MSG_WriteShort(&sv.reliable_datagram, -i);
MSG_WriteString(&sv.reliable_datagram, name);

View File

@ -369,9 +369,7 @@ void World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers)
if (ent->area.prev)
World_UnlinkEdict (ent); // unlink from old position
ent->solidtype = ent->v->solid;
if (ent == w->edicts)
return; // don't add the world