Lots of small changes. q3 player models are working and things, though csqc. md5mesh is supported (md5anim through an alternate 'format' to specify model name and a list of md5anims).

Lots of cool stuff.

r_shadows is still broken due to depth sorting of model (and thier depth value being written too late).


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1196 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2005-08-03 23:14:59 +00:00
parent 0378f937bb
commit 7903310326
60 changed files with 3820 additions and 863 deletions

View File

@ -1362,6 +1362,20 @@ void CL_RotateAroundTag(entity_t *ent, int num, int tagent, int tagnum)
}
}
void V_AddAxisEntity(entity_t *in)
{
entity_t *ent;
if (cl_numvisedicts == MAX_VISEDICTS)
{
Con_Printf("Visedict list is full!\n");
return; // object list is full
}
ent = &cl_visedicts[cl_numvisedicts];
cl_numvisedicts++;
*ent = *in;
}
void V_AddEntity(entity_t *in)
{
entity_t *ent;

View File

@ -36,6 +36,8 @@ cvar_t cl_netfps = {"cl_netfps", "0"};
cvar_t cl_smartjump = {"cl_smartjump", "1"};
cvar_t cl_prydoncursor = {"cl_prydoncursor", "0"}; //for dp protocol
usercmd_t independantphysics[MAX_SPLITS];
@ -551,7 +553,10 @@ void CL_FinishMove (usercmd_t *cmd, int msecs, int pnum)
// from the last level
//
if (++cl.movemessages <= 2)
{
cmd->buttons = 0;
return;
}
//
// figure button bits
//
@ -584,21 +589,50 @@ void CL_FinishMove (usercmd_t *cmd, int msecs, int pnum)
cmd->impulse = 0;
}
cvar_t cl_prydoncursor = {"cl_prydoncursor", "0"};
float cursor_screen[2];
void CL_DrawPrydonCursor(void)
{
if (cls.protocol == CP_NETQUAKE)
if (nq_dp_protocol >= 6)
if (cl_prydoncursor.value)
{
mpic_t *pic = Draw_SafeCachePic(va("gfx/prydoncursor%03i.lmp", (int)cl_prydoncursor.value));
if (pic)
Draw_Pic((cursor_screen[0] + 1) * 0.5 * vid.width, (cursor_screen[1] + 1) * 0.5 * vid.height, pic);
else
Draw_Character((cursor_screen[0] + 1) * 0.5 * vid.width, (cursor_screen[1] + 1) * 0.5 * vid.height, '+');
}
}
void ML_UnProject(vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float wdivh, float fovy);
void CL_UpdatePrydonCursor(float cursor_screen[2], vec3_t cursor_start, vec3_t cursor_impact, int *entnum)
void CL_UpdatePrydonCursor(usercmd_t *from, float cursor_screen[2], vec3_t cursor_start, vec3_t cursor_impact, int *entnum)
{
float modelview[16];
vec3_t cursor_end;
trace_t tr;
vec3_t temp, scale;
vec3_t temp;
vec3_t cursor_impact_normal;
if (!cl_prydoncursor.value)
{ //center the cursor
cursor_screen[0] = 0;
cursor_screen[1] = 0;
}
else
{
cursor_screen[0] += from->sidemove/10000.0f;
cursor_screen[1] -= from->forwardmove/10000.0f;
if (cursor_screen[0] < -1)
cursor_screen[0] = -1;
if (cursor_screen[1] < -1)
cursor_screen[1] = -1;
if (cursor_screen[0] > 1)
cursor_screen[0] = 1;
if (cursor_screen[1] > 1)
cursor_screen[1] = 1;
}
/*
if (cl.cmd.cursor_screen[0] < -1)
@ -625,32 +659,28 @@ void CL_UpdatePrydonCursor(float cursor_screen[2], vec3_t cursor_start, vec3_t c
// cursor_screen[0] = bound(-1, cursor_screen[0], 1);
// cursor_screen[1] = bound(-1, cursor_screen[1], 1);
scale[0] = -tan(r_refdef.fov_x * M_PI / 360.0);
scale[1] = -tan(r_refdef.fov_y * M_PI / 360.0);
scale[2] = 1;
// trace distance
VectorScale(scale, 1000000, scale);
VectorCopy(cl.simorg[0], cursor_start);
temp[0] = cursor_screen[0];
temp[1] = cursor_screen[1];
VectorCopy(vec3_origin, cursor_start);
temp[0] = (cursor_screen[0]+1)/2;
temp[1] = (-cursor_screen[1]+1)/2;
temp[2] = 1;
// ML_UnProject(temp, cursor_end, cl.viewangles[0], cl.simorg[0], vid.width/vid.height, 90);
ML_ModelViewMatrix(modelview, cl.viewangles[0], cl.simorg[0]);
Matrix4_Transform3(modelview, temp, cursor_end);
ML_UnProject(temp, cursor_end, cl.viewangles[0], vec3_origin, (float)vid.width/vid.height, scr_fov.value );
VectorScale(cursor_end, 100000, cursor_end);
VectorAdd(cursor_start, cl.simorg[0], cursor_start);
VectorAdd(cursor_end, cl.simorg[0], cursor_end);
cursor_start[2]+=cl.viewheight[0];
cursor_end[2]+=cl.viewheight[0];
CL_SetSolidEntities();
//don't bother with players, they don't exist in NQ...
tr = PM_PlayerTrace(cursor_start, cursor_end);
VectorCopy(tr.endpos, cursor_impact);
TraceLineN(cursor_start, cursor_end, cursor_impact, cursor_impact_normal);
// CL_SelectTraceLine(cursor_start, cursor_end, cursor_impact, entnum);
// makes sparks where cursor is
//CL_SparkShower(cl.cmd.cursor_impact, cl.cmd.cursor_normal, 5, 0);
// P_RunParticleEffectType(cursor_impact, vec3_origin, 1, 0);
// P_RunParticleEffectType(cursor_impact, vec3_origin, 1, pt_gunshot);
//P_ParticleTrail(cursor_start, cursor_impact, 0, NULL);
}
@ -660,7 +690,6 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf)
int bits;
int i;
float cursor_screen[2];
vec3_t cursor_start, cursor_impact;
int cursor_entitynumber=0;//I hate warnings as errors
@ -704,7 +733,7 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf)
if (nq_dp_protocol >= 6)
{
CL_UpdatePrydonCursor(cursor_screen, cursor_start, cursor_impact, &cursor_entitynumber);
CL_UpdatePrydonCursor(cmd, cursor_screen, cursor_start, cursor_impact, &cursor_entitynumber);
MSG_WriteLong (buf, bits);
}
else
@ -1021,6 +1050,9 @@ void CL_SendCmd (float frametime)
extern cvar_t cl_maxfps;
vec3_t cursor_start, cursor_impact;
int cursor_entitynumber=0;//I hate warnings as errors
if (cls.demoplayback != DPB_NONE)
{
if (cls.demoplayback == DPB_MVD)
@ -1512,6 +1544,8 @@ void CL_InitInput (void)
Cvar_Register (&cl_netfps, inputnetworkcvargroup);
Cvar_Register (&cl_smartjump, inputnetworkcvargroup);
Cvar_Register (&cl_prydoncursor, inputnetworkcvargroup);
}
/*

View File

@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cl_main.c -- client main loop
#include <ctype.h>
#include "quakedef.h"
#include "winquake.h"
#include <sys/types.h>
@ -32,8 +33,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define WINAVI
#endif
#include <ctype.h>
// we need to declare some mouse variables here, because the menu system
// references them even when on a unix system.
@ -1670,6 +1669,16 @@ void CL_ConnectionlessPacket (void)
MSG_BeginReading ();
MSG_ReadLong (); // skip the -1
Cmd_TokenizeString(net_message.data+4, false, false);
if (net_message.cursize == sizeof(net_message_buffer))
net_message.data[sizeof(net_message_buffer)-1] = '\0';
else
net_message.data[net_message.cursize] = '\0';
if (Plug_ConnectionlessClientPacket(net_message.data+4, net_message.cursize-4))
return;
c = MSG_ReadByte ();
if (cls.demoplayback == DPB_NONE)
@ -1994,6 +2003,10 @@ void CLNQ_ConnectionlessPacket(void)
cls.state = ca_connected;
Con_TPrintf (TLC_CONNECTED);
allowremotecmd = false; // localid required now for remote cmds
//send a dummy packet.
//this makes our local nat think we initialised the conversation.
NET_SendPacket(NS_CLIENT, 9, "\xff\xff\xff\xff""dummy", net_from);
return;
case CCREP_REJECT:

View File

@ -2208,7 +2208,10 @@ void CL_ParseStartSoundPacket(void)
if (ent > MAX_EDICTS)
Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent);
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
#ifdef PEXT_CSQC
if (!CSQC_StartSound(ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation))
#endif
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
if (ent == cl.playernum[0]+1)

View File

@ -760,6 +760,9 @@ void SCR_CalcRefdef (void)
}
r_refdef.fov_x = scr_fov.value;
if (cl.stats[0][STAT_VIEWZOOM])
r_refdef.fov_x *= cl.stats[0][STAT_VIEWZOOM]/255.0f;
if (r_refdef.fov_x < 10)
r_refdef.fov_x = 10;
else if (r_refdef.fov_x > 170)
@ -1893,6 +1896,8 @@ void SCR_DrawTwoDimensional(int uimenu, qboolean nohud)
Plug_SBar ();
#endif
SCR_ShowPics_Draw();
CL_DrawPrydonCursor();
}
else
SCR_DrawFPS ();

View File

@ -110,7 +110,7 @@ typedef enum
#define TE_STREAM_FAMINE 32
#define MAX_BEAMS 32
#define MAX_BEAMS 64
typedef struct
{
int entity;
@ -305,8 +305,9 @@ beam_t *CL_NewBeam (int entity, int tag)
{
beam_t *b;
int i;
// override any beam with the same entity
if (entity) // allow multiple world beams
// override any beam with the same entity (unless they used world)
if (entity)
{
for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
if (b->entity == entity && b->tag == tag)
@ -327,25 +328,13 @@ beam_t *CL_NewBeam (int entity, int tag)
}
#define STREAM_ATTACHED 16
#define STREAM_TRANSLUCENT 32
void CL_ParseBeam (int tent)
void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ numbers instead of 0 - 5
{
int ent;
vec3_t start, end;
beam_t *b;
model_t *m;
int btype, etype;
ent = MSG_ReadShort ();
start[0] = MSG_ReadCoord ();
start[1] = MSG_ReadCoord ();
start[2] = MSG_ReadCoord ();
end[0] = MSG_ReadCoord ();
end[1] = MSG_ReadCoord ();
end[2] = MSG_ReadCoord ();
switch(tent)
{
case 0:
@ -362,6 +351,7 @@ void CL_ParseBeam (int tent)
case 1:
if (ent < 0 && ent >= -MAX_CLIENTS) //based on the railgun concept - this adds a rogue style TE_BEAM effect.
{
case 5:
m = Mod_ForName("progs/beam.mdl", false); //remember to precache!
btype = P_FindParticleType("te_beam");
etype = P_FindParticleType("te_beam_end");
@ -424,6 +414,23 @@ void CL_ParseBeam (int tent)
VectorCopy (start, b->start);
VectorCopy (end, b->end);
}
void CL_ParseBeam (int tent)
{
int ent;
vec3_t start, end;
ent = MSG_ReadShort ();
start[0] = MSG_ReadCoord ();
start[1] = MSG_ReadCoord ();
start[2] = MSG_ReadCoord ();
end[0] = MSG_ReadCoord ();
end[1] = MSG_ReadCoord ();
end[2] = MSG_ReadCoord ();
CL_AddBeam(tent, ent, start, end);
}
void CL_ParseStream (int type)
{
int ent;
@ -580,7 +587,7 @@ void CL_ParseTEnt (void)
dlight_t *dl;
int rnd;
// explosion_t *ex;
int cnt;
int cnt, colour;
type = MSG_ReadByte ();
switch (type)
@ -1129,8 +1136,7 @@ void CL_ParseTEnt (void)
// stain (Hopefully this is close to how DP does it)
R_AddStain(pos, -10, -10, -10, 30);
// TODO: DP also has a decal, should this be simulated or should we just
// use a particle effect and let the user decide what to do with it?
P_ParticleTrail(pos, pos2, P_FindParticleType("te_plasmaburn"), NULL);
break;
case DPTE_TEI_G3: //nexuiz's nex beam
@ -1187,13 +1193,86 @@ void CL_ParseTEnt (void)
break;
case DPTE_PARTICLECUBE:
#pragma message("CL_ParseTEnt: effect DPTE_PARTICLECUBE not implemented")
case DPTE_PARTICLERAIN:
#pragma message("CL_ParseTEnt: effect DPTE_PARTICLERAIN not implemented")
case DPTE_PARTICLESNOW:
#pragma message("CL_ParseTEnt: effect DPTE_PARTICLESNOW not implemented")
{
vec3_t dir;
int jitter;
int gravity;
default:
//min
pos[0] = MSG_ReadCoord();
pos[1] = MSG_ReadCoord();
pos[2] = MSG_ReadCoord();
//max
pos2[0] = MSG_ReadCoord();
pos2[1] = MSG_ReadCoord();
pos2[2] = MSG_ReadCoord();
//dir
dir[0] = MSG_ReadCoord();
dir[1] = MSG_ReadCoord();
dir[2] = MSG_ReadCoord();
cnt = MSG_ReadShort(); //count
colour = MSG_ReadByte (); //colour
gravity = MSG_ReadByte (); //gravity flag
jitter = MSG_ReadCoord(); //jitter
P_RunParticleCube(pos, pos2, dir, cnt, colour, gravity, jitter);
}
break;
case DPTE_PARTICLERAIN:
{
vec3_t dir;
//min
pos[0] = MSG_ReadCoord();
pos[1] = MSG_ReadCoord();
pos[2] = MSG_ReadCoord();
//max
pos2[0] = MSG_ReadCoord();
pos2[1] = MSG_ReadCoord();
pos2[2] = MSG_ReadCoord();
//dir
dir[0] = MSG_ReadCoord();
dir[1] = MSG_ReadCoord();
dir[2] = MSG_ReadCoord();
cnt = MSG_ReadShort(); //count
colour = MSG_ReadByte (); //colour
P_RunParticleWeather(pos, pos2, dir, cnt, colour, "rain");
}
break;
case DPTE_PARTICLESNOW:
{
vec3_t dir;
//min
pos[0] = MSG_ReadCoord();
pos[1] = MSG_ReadCoord();
pos[2] = MSG_ReadCoord();
//max
pos2[0] = MSG_ReadCoord();
pos2[1] = MSG_ReadCoord();
pos2[2] = MSG_ReadCoord();
//dir
dir[0] = MSG_ReadCoord();
dir[1] = MSG_ReadCoord();
dir[2] = MSG_ReadCoord();
cnt = MSG_ReadShort(); //count
colour = MSG_ReadByte (); //colour
P_RunParticleWeather(pos, pos2, dir, cnt, colour, "snow");
}
break;
default:
Host_EndGame ("CL_ParseTEnt: bad type - %i", type);
}
}
@ -2168,32 +2247,37 @@ void CL_UpdateBeams (void)
}
// if coming from the player, update the start position
if (b->flags & 1 && b->entity == (autocam[0]?spec_track[0]:(cl.playernum[0]+1))) // entity 0 is the world
if (b->flags & 1 && b->entity == (autocam[0]?spec_track[0]:(cl.playernum[0]+1)) && b->entity>0 && b->entity<= MAX_CLIENTS) // entity 0 is the world
{
player_state_t *pl;
// VectorSubtract(cl.simorg, b->start, org);
// VectorAdd(b->end, org, b->end); //move the end point by simorg-start
VectorCopy (cl.simorg[0], b->start); //move the start point to view origin
b->start[2] += cl.crouch[0];
if (v_viewheight.value)
pl = &cl.frames[cl.parsecount&UPDATE_MASK].playerstate[b->entity-1];
if (pl->messagenum == cl.parsecount)
{
if (v_viewheight.value <= -7)
b->start[2] += -7;
else if (v_viewheight.value >= 4)
b->start[2] += 4;
else
b->start[2] += v_viewheight.value;
}
VectorCopy (cl.simorg[0], b->start); //move the start point to view origin
b->start[2] += cl.crouch[0];
if (v_viewheight.value)
{
if (v_viewheight.value <= -7)
b->start[2] += -7;
else if (v_viewheight.value >= 4)
b->start[2] += 4;
else
b->start[2] += v_viewheight.value;
}
//rotate the end point to face in the view direction. This gives a smoother shafting. turning looks great.
if (cl_truelightning.value)
{
VectorSubtract (b->end, b->start, dist);
d = VectorNormalize(dist);
AngleVectors (cl.simangles[0], b->end, dist, org);
VectorMA(b->start, d, b->end, b->end);
b->end[2] += cl.viewheight[0];
//rotate the end point to face in the view direction. This gives a smoother shafting. turning looks great.
if (cl_truelightning.value)
{
VectorSubtract (b->end, b->start, dist);
d = VectorNormalize(dist);
AngleVectors (cl.simangles[0], b->end, dist, org);
VectorMA(b->start, d, b->end, b->end);
b->end[2] += cl.viewheight[0];
}
}
}
else if (b->flags & STREAM_ATTACHED)

View File

@ -290,7 +290,8 @@ typedef struct
CP_QUAKEWORLD,
CP_NETQUAKE,
CP_QUAKE2,
CP_QUAKE3
CP_QUAKE3,
CP_PLUGIN
} protocol;
qboolean resendinfo;
@ -660,6 +661,7 @@ void CL_ParseTEnt (qboolean nqprot);
void CL_ParseTEnt (void);
#endif
void CL_UpdateTEnts (void);
void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end);
void CL_ClearState (void);
@ -786,6 +788,8 @@ qboolean CSQC_StuffCmd(char *cmd);
qboolean CSQC_CenterPrint(char *cmd);
qboolean CSQC_ConsoleCommand(char *cmd);
qboolean CSQC_KeyPress(int key, qboolean down);
int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation);
void CSQC_ParseEntities(void);
#endif
//

View File

@ -1687,8 +1687,6 @@ qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height)
return NULL;
}
int GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, qboolean mipmap);
int image_width, image_height;
qbyte *COM_LoadFile (char *path, int usehunk);
int Mod_LoadHiResTexture(char *name, char *subpath, qboolean mipmap, qboolean alpha, qboolean colouradjust)
@ -1790,6 +1788,7 @@ int Mod_LoadReplacementTexture(char *name, char *subpath, qboolean mipmap, qbool
return Mod_LoadHiResTexture(name, subpath, mipmap, alpha, gammaadjust);
}
extern cvar_t r_shadow_bumpscale_bumpmap;
int Mod_LoadBumpmapTexture(char *name, char *subpath)
{
char *buf, *data;
@ -1852,7 +1851,7 @@ int Mod_LoadBumpmapTexture(char *name, char *subpath)
if ((data = ReadTargaFile(buf, com_filesize, &image_width, &image_height, 2))) //Only load a greyscale image.
{
TRACE(("dbg: Mod_LoadBumpmapTexture: tga %s loaded\n", name));
len = GL_LoadTexture8Bump(name, image_width, image_height, data, true);
len = GL_LoadTexture8Bump(name, image_width, image_height, data, true, r_shadow_bumpscale_bumpmap.value);
BZ_Free(data);
}
else

View File

@ -1,5 +1,9 @@
// Raw input includes
#ifndef WINUSERAPI
#define WINUSERAPI
#endif
#ifndef RIM_TYPEMOUSE
#define WM_INPUT 255
@ -116,4 +120,4 @@ WINUSERAPI UINT WINAPI GetRawInputDeviceInfoW(HANDLE,UINT,LPVOID,PUINT);
WINUSERAPI UINT WINAPI GetRawInputDeviceList(PRAWINPUTDEVICELIST,PUINT,UINT);
WINUSERAPI UINT WINAPI GetRegisteredRawInputDevices(PRAWINPUTDEVICE,PUINT,UINT);
WINUSERAPI BOOL WINAPI RegisterRawInputDevices(PCRAWINPUTDEVICE,UINT,UINT);
#endif
#endif

View File

@ -241,10 +241,10 @@ static JOYINFOEX ji;
#define RI_INVALID_POS 0x80000000
// raw input dynamic functions
typedef WINUSERAPI INT (WINAPI *pGetRawInputDeviceList)(OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PINT puiNumDevices, IN UINT cbSize);
typedef WINUSERAPI INT(WINAPI *pGetRawInputData)(IN HRAWINPUT hRawInput, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize, IN UINT cbSizeHeader);
typedef WINUSERAPI INT(WINAPI *pGetRawInputDeviceInfoA)(IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize);
typedef WINUSERAPI BOOL (WINAPI *pRegisterRawInputDevices)(IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize);
typedef INT (WINAPI *pGetRawInputDeviceList)(OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PINT puiNumDevices, IN UINT cbSize);
typedef INT(WINAPI *pGetRawInputData)(IN HRAWINPUT hRawInput, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize, IN UINT cbSizeHeader);
typedef INT(WINAPI *pGetRawInputDeviceInfoA)(IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PINT pcbSize);
typedef BOOL (WINAPI *pRegisterRawInputDevices)(IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize);
pGetRawInputDeviceList _GRIDL;
pGetRawInputData _GRID;
@ -1395,6 +1395,13 @@ static void ProcessMouse(mouse_t *mouse, usercmd_t *cmd, int pnum)
mouse_x *= sensitivity.value*in_sensitivityscale;
mouse_y *= sensitivity.value*in_sensitivityscale;
if (cl.stats[pnum][STAT_VIEWZOOM])
{
mouse_x *= cl.stats[pnum][STAT_VIEWZOOM]/255.0f;
mouse_y *= cl.stats[pnum][STAT_VIEWZOOM]/255.0f;
}
if (!cmd)
{
if (mx || my)

View File

@ -828,6 +828,7 @@ float filmstarttime;
int soundpos;
#pragma comment( lib, "vfw32.lib" )
#endif
static qbyte *framedata; //this buffer holds the image data temporarily..
#define MFT_CAPTURE 5 //fixme
@ -908,6 +909,12 @@ qboolean Media_PlayFilm(char *name)
media_filmtype = MFT_NONE;
if (framedata)
{
BZ_Free(framedata);
framedata = NULL;
}
if (!name || !*name) //clear only.
return false;
@ -963,6 +970,8 @@ qboolean Media_PlayFilm(char *name)
if (key_dest != key_console)
scr_con_current=0;
media_filmtype = MFT_ROQ;
framedata = BZ_Malloc(roqfilm->width*roqfilm->height*4);
return true;
}
#ifdef WINAVI
@ -1011,6 +1020,7 @@ qboolean Media_PlayFilm(char *name)
AVIStreamInfo(pavivideo, &psi, sizeof(psi));
filmwidth=psi.rcFrame.right-psi.rcFrame.left; // Width Is Right Side Of Frame Minus Left
filmheight=psi.rcFrame.bottom-psi.rcFrame.top; // Height Is Bottom Of Frame Minus Top
framedata = BZ_Malloc(filmwidth*filmheight*4);
num_frames=AVIStreamLength(pavivideo); // The Last Frame Of The Stream
filmfps=1000.0f*(float)num_frames/(float)AVIStreamSampleToTime(pavivideo,num_frames); // Calculate Rough Milliseconds Per Frame
@ -1088,7 +1098,6 @@ soundpos=0;
qboolean Media_ShowFilm(void)
{
// sfx_t *s;
static qbyte framedata[1024*1024*4];
static float lastframe=0;
// soundcardinfo_t *sc;

View File

@ -103,7 +103,8 @@ extern void FNC(Mod_NowLoadExternal) (void);
extern void FNC(Mod_Think) (void);
extern qboolean FNC(Mod_GetTag) (struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *transforms);
extern int FNC(Mod_TagNumForName) (struct model_s *model, char *name);
extern int FNC(Mod_TagNumForName) (struct model_s *model, char *name);
extern int FNC(Mod_SkinForName) (struct model_s *model, char *name);
#undef FNC
@ -183,6 +184,7 @@ typedef struct {
void (*Mod_Think) (void);
qboolean(*Mod_GetTag) (struct model_s *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result);
int (*Mod_TagNumForName) (struct model_s *model, char *name);
int (*Mod_SkinForName) (struct model_s *model, char *name);
qboolean (*VID_Init) (rendererstate_t *info, unsigned char *palette);

View File

@ -21,6 +21,8 @@ static unsigned int csqcchecksum;
static qboolean csqcwantskeys;
static csqctreadstate_t *csqcthreads;
qboolean csqc_resortfrags;
qboolean csqc_drawsbar;
qboolean csqc_addcrosshair;
cvar_t pr_csmaxedicts = {"pr_csmaxedicts", "3072"};
cvar_t cl_csqcdebug = {"cl_csqcdebug", "0"}; //prints entity numbers which arrive (so I can tell people not to apply it to players...)
@ -38,6 +40,8 @@ cvar_t cl_csqcdebug = {"cl_csqcdebug", "0"}; //prints entity numbers which arriv
globalfunction(ent_update, "CSQC_Ent_Update"); \
globalfunction(ent_remove, "CSQC_Ent_Remove"); \
\
globalfunction(serversound, "CSQC_ServerSound"); \
\
/*These are pointers to the csqc's globals.*/ \
globalfloat(time, "time"); /*float Written before entering most qc functions*/ \
globalentity(self, "self"); /*entity Written before entering most qc functions*/ \
@ -68,6 +72,8 @@ cvar_t cl_csqcdebug = {"cl_csqcdebug", "0"}; //prints entity numbers which arriv
globalvector(pmove_vel, "pmove_vel"); \
globalvector(pmove_mins, "pmove_mins"); \
globalvector(pmove_maxs, "pmove_maxs"); \
globalfloat(pmove_jump_held, "pmove_jump_held"); \
globalfloat(pmove_waterjumptime, "pmove_waterjumptime"); \
globalfloat(input_timelength, "input_timelength"); \
globalvector(input_angles, "input_angles"); \
globalvector(input_movevalues, "input_movevalues"); \
@ -146,11 +152,14 @@ static void CSQC_FindGlobals(void)
fieldfloat(fatness); /*expand models X units along thier normals.*/ \
fieldfloat(skin); \
fieldfloat(colormap); \
fieldfloat(frame); \
fieldfloat(flags); \
fieldfloat(oldframe); \
fieldfloat(frame); \
fieldfloat(frame2); \
fieldfloat(frame1time); \
fieldfloat(frame2time); \
fieldfloat(lerpfrac); \
fieldfloat(renderflags);\
fieldfloat(forceshader);\
\
fieldfloat(drawmask); /*So that the qc can specify all rockets at once or all bannanas at once*/ \
fieldfunction(predraw); /*If present, is called just before it's drawn.*/ \
@ -164,7 +173,7 @@ static void CSQC_FindGlobals(void)
fieldentity(chain); \
fieldentity(groundentity); \
\
fieldvector(solid); \
fieldfloat(solid); \
fieldvector(mins); \
fieldvector(maxs); \
fieldvector(absmins); \
@ -196,6 +205,7 @@ typedef struct csqcedict_s
csqcentvars_t *v;
//add whatever you wish here
trailstate_t *trailstate;
} csqcedict_t;
static csqcedict_t *csqc_edicts; //consider this 'world'
@ -216,7 +226,8 @@ csqcfields //any *64->int32 casts are erroneous, it's biased off NULL.
#undef fieldfunction
}
static csqcedict_t *csqcent[MAX_EDICTS];
static csqcedict_t **csqcent;
static int maxcsqcentities;
#define RETURN_SSTRING(s) (((string_t *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //static - exe will not change it.
char *PF_TempStr(progfuncs_t *prinst);
@ -299,6 +310,7 @@ void PF_infoget (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_strncmp (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_strcasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_strncasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals);
void PF_strpad (progfuncs_t *prinst, struct globalvars_s *pr_globals);
//these functions are from pr_menu.dat
void PF_CL_is_cached_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals);
@ -328,14 +340,14 @@ void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals
void PF_fclose_progs (progfuncs_t *prinst);
char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals);
int QCEditor (progfuncs_t *prinst, char *filename, int line, int nump, char **parms);
void CL_CS_LinkEdict(csqcedict_t *ent)
void CL_CS_LinkEdict(csqcedict_t *ent, qboolean touchtriggers)
{
//FIXME: use some sort of area grid ?
VectorAdd(ent->v->origin, ent->v->mins, ent->v->absmins);
@ -354,7 +366,7 @@ trace_t CL_Move(vec3_t v1, vec3_t mins, vec3_t maxs, vec3_t v2, float nomonsters
memset(&trace, 0, sizeof(trace));
trace.fraction = 1;
cl.worldmodel->funcs.Trace(cl.worldmodel, 0, 0, v1, v2, vec3_origin, vec3_origin, &trace);
cl.worldmodel->funcs.Trace(cl.worldmodel, 0, 0, v1, v2, mins, maxs, &trace);
//why use trace.endpos instead?
//so that if we hit a wall early, we don't have a box covering the whole world because of a shotgun trace.
@ -407,6 +419,8 @@ static void PF_cs_remove (progfuncs_t *prinst, struct globalvars_s *pr_globals)
return;
}
P_DelinkTrailstate(&ed->trailstate);
ED_Free (prinst, (void*)ed);
}
@ -517,15 +531,129 @@ void EularToQuaternian(vec3_t angles, float *quat)
#define CSQCRF_VIEWMODEL 1 //Not drawn in mirrors
#define CSQCRF_EXTERNALMODEL 2 //drawn ONLY in mirrors
#define CSQCRF_DEPTHHACK 4 //fun depthhack
#define CSQCRF_ADDATIVE 8 //add instead of blend
#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)
void PF_R_AddEntity(progfuncs_t *prinst, struct globalvars_s *pr_globals)
static model_t *CSQC_GetModelForIndex(int index)
{
if (index == 0)
return NULL;
else if (index > 0 && index < MAX_MODELS)
return cl.model_precache[index];
else if (index < 0 && index > -MAX_CSQCMODELS)
return cl.model_csqcprecache[-index];
else
return NULL;
}
static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out)
{
int i;
model_t *model;
i = in->v->modelindex;
if (i == 0)
return false;
else if (i > 0 && i < MAX_MODELS)
model = cl.model_precache[i];
else if (i < 0 && i > -MAX_CSQCMODELS)
model = cl.model_csqcprecache[-i];
else
return false; //there might be other ent types later as an extension that stop this.
if (!model)
{
Con_Printf("CopyCSQCEdictToEntity: model wasn't precached!\n");
return false;
}
memset(out, 0, sizeof(*out));
out->model = model;
if (in->v->renderflags)
{
i = in->v->renderflags;
if (i & CSQCRF_VIEWMODEL)
out->flags |= Q2RF_DEPTHHACK;
if (i & CSQCRF_EXTERNALMODEL)
out->flags |= Q2RF_EXTERNALMODEL;
if (i & CSQCRF_DEPTHHACK)
out->flags |= Q2RF_DEPTHHACK;
if (i & CSQCRF_ADDITIVE)
out->flags |= Q2RF_ADDATIVE;
//CSQCRF_USEAXIS is below
if (i & CSQCRF_NOSHADOW)
out->flags |= RF_NOSHADOW;
}
out->frame = in->v->frame;
out->oldframe = in->v->frame2;
out->lerpfrac = in->v->lerpfrac;
VectorCopy(in->v->origin, out->origin);
if ((int)in->v->renderflags & CSQCRF_USEAXIS)
{
VectorCopy(csqcg.forward, out->axis[0]);
VectorNegate(csqcg.right, out->axis[1]);
VectorCopy(csqcg.up, out->axis[2]);
}
else
{
VectorCopy(in->v->angles, out->angles);
out->angles[0]*=-1;
AngleVectors(out->angles, out->axis[0], out->axis[1], out->axis[2]);
VectorInverse(out->axis[1]);
}
out->frame1time = in->v->frame1time;
out->frame2time = in->v->frame2time;
if (!in->v->alpha)
out->alpha = 1;
else
out->alpha = in->v->alpha;
if (!in->v->scale)
out->scale = 1;
else
out->scale = in->v->scale;
out->skinnum = in->v->skin;
out->fatness = in->v->fatness;
#ifdef Q3SHADERS
out->forcedshader = *(int*)&in->v->forceshader;
#endif
out->keynum = -1;
return true;
}
static void PF_cs_makestatic (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{ //still does a remove.
csqcedict_t *in = (void*)G_EDICT(prinst, OFS_PARM0);
entity_t *ent;
if (cl.num_statics >= MAX_STATIC_ENTITIES)
{
Con_Printf ("Too many static entities");
PF_cs_remove(prinst, pr_globals);
return;
}
ent = &cl_static_entities[cl.num_statics];
if (CopyCSQCEdictToEntity(in, ent))
{
cl.num_statics++;
R_AddEfrags(ent);
}
PF_cs_remove(prinst, pr_globals);
}
static void PF_R_AddEntity(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqcedict_t *in = (void*)G_EDICT(prinst, OFS_PARM0);
entity_t ent;
int i;
model_t *model;
if (in->v->predraw)
{
@ -533,68 +661,13 @@ void PF_R_AddEntity(progfuncs_t *prinst, struct globalvars_s *pr_globals)
*csqcg.self = EDICT_TO_PROG(prinst, (void*)in);
PR_ExecuteProgram(prinst, in->v->predraw);
*csqcg.self = oldself;
if (in->isfree)
return; //bummer...
}
i = in->v->modelindex;
if (i == 0)
return;
else if (i > 0 && i < MAX_MODELS)
model = cl.model_precache[i];
else if (i < 0 && i > -MAX_CSQCMODELS)
model = cl.model_csqcprecache[-i];
else
return; //there might be other ent types later as an extension that stop this.
memset(&ent, 0, sizeof(ent));
ent.model = model;
if (!ent.model)
{
Con_Printf("PF_R_AddEntity: model wasn't precached!\n");
return;
}
if (in->v->renderflags)
{
i = in->v->renderflags;
if (i & CSQCRF_VIEWMODEL)
ent.flags |= Q2RF_WEAPONMODEL;
if (i & CSQCRF_EXTERNALMODEL)
ent.flags |= Q2RF_EXTERNALMODEL;
if (i & CSQCRF_DEPTHHACK)
ent.flags |= Q2RF_DEPTHHACK;
if (i & CSQCRF_ADDATIVE)
ent.flags |= Q2RF_ADDATIVE;
//CSQCRF_USEAXIS is below
}
ent.frame = in->v->frame;
ent.oldframe = in->v->oldframe;
ent.lerpfrac = in->v->lerpfrac;
ent.angles[0] = in->v->angles[0];
ent.angles[1] = in->v->angles[1];
ent.angles[2] = in->v->angles[2];
VectorCopy(in->v->origin, ent.origin);
if ((int)in->v->renderflags & CSQCRF_USEAXIS)
{
VectorCopy(csqcg.forward, ent.axis[0]);
VectorNegate(csqcg.right, ent.axis[1]);
VectorCopy(csqcg.up, ent.axis[2]);
}
else
{
AngleVectors(ent.angles, ent.axis[0], ent.axis[1], ent.axis[2]);
VectorInverse(ent.axis[1]);
}
ent.alpha = in->v->alpha;
ent.scale = in->v->scale;
ent.skinnum = in->v->skin;
ent.fatness = in->v->fatness;
V_AddEntity(&ent);
if (CopyCSQCEdictToEntity(in, &ent))
V_AddAxisEntity(&ent);
/*
{
@ -697,6 +770,9 @@ static void PF_R_ClearScene (progfuncs_t *prinst, struct globalvars_s *pr_global
r_refdef.fov_x = scr_fov.value;
r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
*/
csqc_addcrosshair = false;
csqc_drawsbar = false;
}
typedef enum
@ -705,8 +781,8 @@ typedef enum
VF_MIN_X = 2,
VF_MIN_Y = 3,
VF_SIZE = 4,
VF_SIZE_Y = 5,
VF_SIZE_X = 6,
VF_SIZE_X = 5,
VF_SIZE_Y = 6,
VF_VIEWPORT = 7,
VF_FOV = 8,
VF_FOVX = 9,
@ -719,6 +795,9 @@ typedef enum
VF_ANGLES_X = 16,
VF_ANGLES_Y = 17,
VF_ANGLES_Z = 18,
VF_DRAWWORLD = 19,
VF_NOENGINESBAR = 20,
VF_DRAWCROSSHAIR = 21,
VF_PERSPECTIVE = 200
} viewflags;
@ -792,6 +871,16 @@ static void PF_R_SetViewFlag(progfuncs_t *prinst, struct globalvars_s *pr_global
r_refdef.vrect.y = p[1];
break;
case VF_DRAWWORLD:
r_refdef.flags = r_refdef.flags&~Q2RDF_NOWORLDMODEL | (*p?0:Q2RDF_NOWORLDMODEL);
break;
case VF_NOENGINESBAR:
csqc_drawsbar = !*p;
break;
case VF_DRAWCROSSHAIR:
csqc_addcrosshair = *p;
break;
case VF_PERSPECTIVE:
r_refdef.useperspective = *p;
break;
@ -841,6 +930,11 @@ static void PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s *pr_global
#endif
vid.recalc_refdef = 1;
if (csqc_drawsbar)
Sbar_Draw();
if (csqc_addcrosshair)
Draw_Crosshair();
}
static void PF_cs_getstatf(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -889,19 +983,19 @@ static void PF_cs_SetOrigin(progfuncs_t *prinst, struct globalvars_s *pr_globals
VectorCopy(org, ent->v->origin);
CL_CS_LinkEdict(ent);
CL_CS_LinkEdict(ent, false);
}
static void PF_cs_SetSize(progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqcedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0);
float *mins = G_VECTOR(OFS_PARM1);
float *maxs = G_VECTOR(OFS_PARM1);
float *maxs = G_VECTOR(OFS_PARM2);
VectorCopy(mins, ent->v->mins);
VectorCopy(maxs, ent->v->maxs);
CL_CS_LinkEdict(ent);
CL_CS_LinkEdict(ent, false);
}
static void PF_cs_traceline(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -1199,6 +1293,19 @@ static void PF_cs_pointparticles (progfuncs_t *prinst, struct globalvars_s *pr_g
P_RunParticleEffectType(org, vel, count, effectnum);
}
static void PF_cs_trailparticles (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int efnum = G_FLOAT(OFS_PARM0)-1;
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM1);
float *start = G_VECTOR(OFS_PARM2);
float *end = G_VECTOR(OFS_PARM3);
if (!ent->entnum) //world trails are non-state-based.
P_ParticleTrail(start, end, efnum, NULL);
else
P_ParticleTrail(start, end, efnum, &ent->trailstate);
}
static void PF_cs_particlesloaded (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *effectname = PR_GetStringOfs(prinst, OFS_PARM0);
@ -1252,6 +1359,9 @@ static void PF_cs_runplayerphysics (progfuncs_t *prinst, struct globalvars_s *pr
int msecs;
extern vec3_t player_mins;
extern vec3_t player_maxs;
if (!cl.worldmodel)
return; //urm..
/*
int sequence; // just for debugging prints
@ -1307,12 +1417,18 @@ typedef struct {
pmove.sequence = *csqcg.clientcommandframe;
pmove.pm_type = PM_NORMAL;
pmove.jump_msec = 0;//(cls.z_ext & Z_EXT_PM_TYPE) ? 0 : from->jump_msec;
if (csqcg.pmove_jump_held)
pmove.jump_held = *csqcg.pmove_jump_held;
if (csqcg.pmove_waterjumptime)
pmove.waterjumptime = *csqcg.pmove_waterjumptime;
//set up the movement command
msecs = *csqcg.input_timelength*1000 + 0.5f;
//precision inaccuracies. :(
pmove.angles[0] = ANGLE2SHORT(csqcg.input_angles[0]);
pmove.angles[1] = ANGLE2SHORT(csqcg.input_angles[1]);
pmove.angles[2] = ANGLE2SHORT(csqcg.input_angles[2]);
pmove.cmd.angles[0] = ANGLE2SHORT(csqcg.input_angles[0]);
pmove.cmd.angles[1] = ANGLE2SHORT(csqcg.input_angles[1]);
pmove.cmd.angles[2] = ANGLE2SHORT(csqcg.input_angles[2]);
pmove.cmd.forwardmove = csqcg.input_movevalues[0];
pmove.cmd.sidemove = csqcg.input_movevalues[1];
pmove.cmd.upmove = csqcg.input_movevalues[2];
@ -1333,7 +1449,10 @@ typedef struct {
PM_PlayerMove(1);
}
if (csqcg.pmove_jump_held)
*csqcg.pmove_jump_held = pmove.jump_held;
if (csqcg.pmove_waterjumptime)
*csqcg.pmove_waterjumptime = pmove.waterjumptime;
VectorCopy(pmove.origin, csqcg.pmove_org);
VectorCopy(pmove.velocity, csqcg.pmove_vel);
}
@ -1442,7 +1561,7 @@ void PF_cs_sound(progfuncs_t *prinst, struct globalvars_s *pr_globals)
entity = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
channel = G_FLOAT(OFS_PARM1);
sample = PR_GetStringOfs(prinst, OFS_PARM2);
volume = G_FLOAT(OFS_PARM3) * 255;
volume = G_FLOAT(OFS_PARM3);
attenuation = G_FLOAT(OFS_PARM4);
sfx = S_PrecacheSound(sample);
@ -1801,6 +1920,116 @@ static void PF_cl_te_customflash (progfuncs_t *prinst, struct globalvars_s *pr_g
dl->color[2] = colour[2]*0.5f;
}
static void PF_cl_te_bloodshower (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
}
static void PF_cl_te_particlecube (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *minb = G_VECTOR(OFS_PARM0);
float *maxb = G_VECTOR(OFS_PARM1);
float *vel = G_VECTOR(OFS_PARM2);
float howmany = G_FLOAT(OFS_PARM3);
float color = G_FLOAT(OFS_PARM4);
float gravity = G_FLOAT(OFS_PARM5);
float jitter = G_FLOAT(OFS_PARM6);
P_RunParticleCube(minb, maxb, vel, howmany, color, gravity, jitter);
}
static void PF_cl_te_spark (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
}
static void PF_cl_te_smallflash (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
}
static void PF_cl_te_explosion2 (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
}
static void PF_cl_te_lightning1 (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
float *start = G_VECTOR(OFS_PARM1);
float *end = G_VECTOR(OFS_PARM1);
CL_AddBeam(0, ent->entnum+MAX_EDICTS, start, end);
}
static void PF_cl_te_lightning2 (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
float *start = G_VECTOR(OFS_PARM1);
float *end = G_VECTOR(OFS_PARM1);
CL_AddBeam(1, ent->entnum+MAX_EDICTS, start, end);
}
static void PF_cl_te_lightning3 (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
float *start = G_VECTOR(OFS_PARM1);
float *end = G_VECTOR(OFS_PARM1);
CL_AddBeam(2, ent->entnum+MAX_EDICTS, start, end);
}
static void PF_cl_te_beam (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
float *start = G_VECTOR(OFS_PARM1);
float *end = G_VECTOR(OFS_PARM1);
CL_AddBeam(5, ent->entnum+MAX_EDICTS, start, end);
}
static void PF_cl_te_plasmaburn (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
}
static void PF_cl_te_explosionrgb (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *org = G_VECTOR(OFS_PARM0);
float *colour = G_VECTOR(OFS_PARM1);
dlight_t *dl;
extern cvar_t r_explosionlight;
extern sfx_t *cl_sfx_r_exp3;
P_ParticleExplosion (org);
// light
if (r_explosionlight.value)
{
dl = CL_AllocDlight (0);
VectorCopy (org, dl->origin);
dl->radius = 150 + bound(0, r_explosionlight.value, 1)*200;
dl->die = cl.time + 0.5;
dl->decay = 300;
dl->color[0] = 0.4f*colour[0];
dl->color[1] = 0.4f*colour[1];
dl->color[2] = 0.4f*colour[2];
dl->channelfade[0] = 0;
dl->channelfade[1] = 0;
dl->channelfade[2] = 0;
}
S_StartSound (-2, 0, cl_sfx_r_exp3, org, 1, 1);
}
static void PF_cl_te_particlerain (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *min = G_VECTOR(OFS_PARM0);
float *max = G_VECTOR(OFS_PARM1);
float *vel = G_VECTOR(OFS_PARM2);
float howmany = G_FLOAT(OFS_PARM3);
float colour = G_FLOAT(OFS_PARM4);
P_RunParticleWeather(min, max, vel, howmany, colour, "rain");
}
static void PF_cl_te_particlesnow (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *min = G_VECTOR(OFS_PARM0);
float *max = G_VECTOR(OFS_PARM1);
float *vel = G_VECTOR(OFS_PARM2);
float howmany = G_FLOAT(OFS_PARM3);
float colour = G_FLOAT(OFS_PARM4);
P_RunParticleWeather(min, max, vel, howmany, colour, "snow");
}
void CSQC_RunThreads(void)
{
csqctreadstate_t *state = csqcthreads, *next;
@ -1866,7 +2095,7 @@ void PF_cs_droptofloor (progfuncs_t *prinst, struct globalvars_s *pr_globals)
else
{
VectorCopy (trace.endpos, ent->v->origin);
SV_LinkEdict (ent, false);
CL_CS_LinkEdict (ent, false);
ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
ent->v->groundentity = EDICT_TO_PROG(prinst, trace.ent);
G_FLOAT(OFS_RETURN) = 1;
@ -1881,25 +2110,12 @@ static void PF_cs_copyentity (progfuncs_t *prinst, struct globalvars_s *pr_globa
out = (csqcedict_t*)G_EDICT(prinst, OFS_PARM1);
memcpy(out->v, in->v, csqcentsize);
CL_CS_LinkEdict (out, false);
}
//these are the builtins that still need to be added.
#define PF_cs_tracetoss PF_Fixme
#define PF_cs_makestatic PF_Fixme
#define PF_cl_te_bloodshower PF_Fixme
#define PF_cl_te_particlecube PF_Fixme
#define PF_cl_te_spark PF_Fixme
#define PF_cl_te_smallflash PF_Fixme
#define PF_cl_te_explosion2 PF_Fixme
#define PF_cl_te_lightning1 PF_Fixme
#define PF_cl_te_lightning2 PF_Fixme
#define PF_cl_te_lightning3 PF_Fixme
#define PF_cl_te_beam PF_Fixme
#define PF_cl_te_plasmaburn PF_Fixme
#define PF_cl_te_explosionrgb PF_Fixme
#define PF_cl_te_particlerain PF_Fixme
#define PF_cl_te_particlesnow PF_Fixme
#define PF_cs_gettagindex PF_Fixme
#define PF_cs_gettaginfo PF_Fixme
#define PS_cs_setattachment PF_Fixme
#define PF_cs_break PF_Fixme
@ -1928,6 +2144,127 @@ static void PF_Stub (progfuncs_t *prinst, struct globalvars_s *pr_globals)
Con_Printf("Obsolete csqc builtin (%i) executed\n", prinst->lastcalledbuiltinnumber);
}
void PF_rotatevectorsbytag (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
int tagnum = G_FLOAT(OFS_PARM1);
float *srcorg = ent->v->origin;
int modelindex = ent->v->modelindex;
int frame1 = ent->v->frame;
int frame2 = ent->v->frame2;
float lerp = ent->v->lerpfrac;
float frame1time = ent->v->frame1time;
float frame2time = ent->v->frame2time;
float *retorg = G_VECTOR(OFS_RETURN);
model_t *mod = CSQC_GetModelForIndex(modelindex);
float transforms[12];
float src[12];
float dest[12];
int i;
if (Mod_GetTag)
if (Mod_GetTag(mod, tagnum, frame1, frame2, lerp, frame1time, frame2time, transforms))
{
// VectorNegate(transforms+0, transforms+0);
// VectorNegate(transforms+4, transforms+4);
// VectorNegate(transforms+8, transforms+8);
VectorCopy(csqcg.forward, src+0);
VectorNegate(csqcg.right, src+4);
VectorCopy(csqcg.up, src+8);
R_ConcatRotationsPad((void*)src, (void*)transforms, (void*)dest);
VectorCopy(dest+0, csqcg.forward);
VectorNegate(dest+4, csqcg.right);
VectorCopy(dest+8, csqcg.up);
VectorCopy(srcorg, retorg);
for (i = 0 ; i < 3 ; i++)
{
retorg[0] += transforms[i*4+3]*src[4*i+0];
retorg[1] += transforms[i*4+3]*src[4*i+1];
retorg[2] += transforms[i*4+3]*src[4*i+2];
}
return;
}
VectorCopy(srcorg, retorg);
}
static void PF_cs_gettagindex (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
char *tagname = PR_GetStringOfs(prinst, OFS_PARM1);
model_t *mod = CSQC_GetModelForIndex(ent->v->modelindex);
if (Mod_TagNumForName)
G_FLOAT(OFS_RETURN) = Mod_TagNumForName(mod, tagname);
else
G_FLOAT(OFS_RETURN) = 0;
}
static void PF_rotatevectorsbyangles (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *ang = G_VECTOR(OFS_PARM0);
vec3_t src[3], trans[3], res[3];
ang[0]*=-1;
AngleVectors(ang, trans[0], trans[1], trans[2]);
ang[0]*=-1;
VectorInverse(trans[1]);
VectorCopy(csqcg.forward, src[0]);
VectorNegate(csqcg.right, src[1]);
VectorCopy(csqcg.up, src[2]);
R_ConcatRotations(trans, src, res);
VectorCopy(res[0], csqcg.forward);
VectorNegate(res[1], csqcg.right);
VectorCopy(res[2], csqcg.up);
}
static void PF_rotatevectorsbymatrix (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
vec3_t src[3], trans[3], res[3];
VectorCopy(G_VECTOR(OFS_PARM0), src[0]);
VectorNegate(G_VECTOR(OFS_PARM1), src[1]);
VectorCopy(G_VECTOR(OFS_PARM2), src[2]);
VectorCopy(csqcg.forward, src[0]);
VectorNegate(csqcg.right, src[1]);
VectorCopy(csqcg.up, src[2]);
R_ConcatRotations(src, trans, res);
VectorCopy(res[0], csqcg.forward);
VectorNegate(res[1], csqcg.right);
VectorCopy(res[2], csqcg.up);
}
static void PF_skinforname (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int modelindex = G_FLOAT(OFS_PARM0);
char *str = PF_VarString(prinst, 1, pr_globals);
model_t *mod = CSQC_GetModelForIndex(modelindex);
if (Mod_SkinForName)
G_FLOAT(OFS_RETURN) = Mod_SkinForName(mod, str);
else
G_FLOAT(OFS_RETURN) = -1;
}
static void PF_shaderforname (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *str = PF_VarString(prinst, 0, pr_globals);
#ifdef Q3SHADERS
G_INT(OFS_RETURN) = R_RegisterSkin(str);
#else
G_INT(OFS_RETURN) = 0;
#endif
}
#define PF_FixTen PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme,PF_Fixme
//prefixes:
@ -2158,7 +2495,7 @@ PF_ReadAngle, // #??? float() readangle (EXT_CSQC)
PF_ReadString, // #??? string() readstring (EXT_CSQC)
PF_ReadFloat, // #??? string() readfloat (EXT_CSQC)
PF_WasFreed, // #??? float(entity) wasfreed (EXT_CSQC) (should be availabe on server too)
PF_Fixme,
PF_cs_trailparticles, // #??? void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC),
//180
PF_FixTen,
@ -2201,14 +2538,24 @@ PF_str2chr, // #222 float(string str, float index) str2chr (FTE_STRINGS)
PF_chr2str, // #223 string(float chr, ...) chr2str (FTE_STRINGS)
PF_strconv, // #224 string(float ccase, float redalpha, float redchars, string str, ...) strconv (FTE_STRINGS)
PF_infoadd, // #225 string(string old, string key, string value) infoadd
PF_infoget, // #226 string(string info, string key) infoget
PF_strncmp, // #227 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
PF_strcasecmp, // #228 float(string s1, string s2) strcasecmp (FTE_STRINGS)
PF_strncasecmp, // #229 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
PF_strpad, // #225 string(float ccase, float redalpha, float redchars, string str, ...) strconv (FTE_STRINGS)
PF_infoadd, // #226 string(string old, string key, string value) infoadd
PF_infoget, // #227 string(string info, string key) infoget
PF_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS)
PF_strcasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS)
//230
PF_FixTen,
PF_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS)
PF_Fixme, // #231 clientstat
PF_Fixme, // #232 runclientphys
PF_Fixme, // #233 float(entity ent) isbackbuffered
PF_rotatevectorsbytag, // #234
PF_rotatevectorsbyangles, // #235
PF_rotatevectorsbymatrix, // #236
PF_skinforname, // #237
PF_shaderforname, // #238
PF_Fixme, // #239
//240
PF_FixTen,
@ -2333,6 +2680,15 @@ PF_Fixme, // #459
//460
PF_FixTen,
//470
PF_FixTen,
//480
PF_FixTen,
//490
PF_FixTen,
//500
PF_FixTen,
};
static int csqc_numbuiltins = sizeof(csqc_builtins)/sizeof(csqc_builtins[0]);
@ -2411,10 +2767,12 @@ qbyte *CSQC_PRLoadFile (char *path, void *buffer, int bufsize)
//pretend it doesn't
file = COM_LoadStackFile(path, buffer, bufsize);
#ifndef _DEBUG
if (!cls.demoplayback) //allow any csqc when playing a demo
if (!strcmp(path, "csprogs.dat")) //Fail to load any csprogs who's checksum doesn't match.
if (Com_BlockChecksum(buffer, com_filesize) != csqcchecksum)
return NULL;
#endif
return file;
}
@ -2468,14 +2826,14 @@ qboolean CSQC_Init (unsigned int checksum)
csqcprogparms.sv_edicts = (edict_t **)&csqc_edicts;
csqcprogparms.sv_num_edicts = &num_csqc_edicts;
csqcprogparms.useeditor = NULL;//sorry... QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
csqcprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms);
csqctime = Sys_DoubleTime();
if (!csqcprogs)
{
in_sensitivityscale = 1;
csqcprogs = InitProgs(&csqcprogparms);
PR_Configure(csqcprogs, -1, 1);
PR_Configure(csqcprogs, -1, 16);
CSQC_InitFields(); //let the qclib know the field order that the engine needs.
@ -2493,7 +2851,7 @@ qboolean CSQC_Init (unsigned int checksum)
PF_InitTempStrings(csqcprogs);
memset(csqcent, 0, sizeof(csqcent));
memset(csqcent, 0, sizeof(*csqcent)*maxcsqcentities);
csqcentsize = PR_InitEnts(csqcprogs, pr_csmaxedicts.value);
@ -2616,6 +2974,41 @@ qboolean CSQC_CenterPrint(char *cmd)
//this protocol allows up to 32767 edicts.
#ifdef PEXT_CSQC
int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation)
{
void *pr_globals;
char *str;
csqcedict_t *ent;
if (!csqcprogs || !csqcg.serversound)
return false;
if (entnum >= maxcsqcentities)
{
maxcsqcentities = entnum+64;
csqcent = BZ_Realloc(csqcent, sizeof(*csqcent)*maxcsqcentities);
}
ent = csqcent[entnum];
if (!ent)
return false;
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
str = PF_TempStr(csqcprogs);
Q_strncpyz(str, soundname, MAXTEMPBUFFERLEN);
*csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent);
G_FLOAT(OFS_PARM0) = channel;
G_INT(OFS_PARM1) = PR_SetString(csqcprogs, str);
VectorCopy(pos, G_VECTOR(OFS_PARM2));
G_FLOAT(OFS_PARM3) = vol;
G_FLOAT(OFS_PARM4) = attenuation;
PR_ExecuteProgram(csqcprogs, csqcg.serversound);
return G_FLOAT(OFS_RETURN);
}
void CSQC_ParseEntities(void)
{
csqcedict_t *ent;
@ -2640,7 +3033,7 @@ void CSQC_ParseEntities(void)
for(;;)
{
entnum = MSG_ReadShort();
if (!entnum)
if (!entnum || msg_badread)
break;
if (entnum & 0x8000)
{ //remove
@ -2649,8 +3042,11 @@ void CSQC_ParseEntities(void)
if (!entnum)
Host_EndGame("CSQC cannot remove world!\n");
if (entnum >= MAX_EDICTS)
Host_EndGame("CSQC recieved too many edicts!\n");
if (entnum >= maxcsqcentities)
{
maxcsqcentities = entnum+64;
csqcent = BZ_Realloc(csqcent, sizeof(*csqcent)*maxcsqcentities);
}
if (cl_csqcdebug.value)
Con_Printf("Remove %i\n", entnum);
@ -2666,8 +3062,11 @@ void CSQC_ParseEntities(void)
}
else
{
if (entnum >= MAX_EDICTS)
Host_EndGame("CSQC recieved too many edicts!\n");
if (entnum >= maxcsqcentities)
{
maxcsqcentities = entnum+64;
csqcent = BZ_Realloc(csqcent, sizeof(*csqcent)*maxcsqcentities);
}
if (cl.csqcdebug)
{

View File

@ -4,6 +4,9 @@
#ifdef RGLQUAKE
#include "glquake.h"
#ifdef Q3SHADERS
#include "shader.h"
#endif
#endif
int MP_TranslateFTEtoDPCodes(int code);
@ -384,20 +387,35 @@ void PF_CL_drawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals)
pos[0] += size[0];
}
}
#ifdef Q3SHADERS
void GLDraw_ShaderPic (int x, int y, int width, int height, shader_t *pic, float r, float g, float b, float a);
#endif
//float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456;
void PF_CL_drawpic (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *pos = G_VECTOR(OFS_PARM0);
char *picname = PR_GetStringOfs(prinst, OFS_PARM1);
mpic_t *p = Draw_SafeCachePic(picname);
float *size = G_VECTOR(OFS_PARM2);
float *rgb = G_VECTOR(OFS_PARM3);
float alpha = G_FLOAT(OFS_PARM4);
float flag = G_FLOAT(OFS_PARM5);
mpic_t *p;
#ifdef RGLQUAKE
if (qrenderer == QR_OPENGL)
{
#ifdef Q3SHADERS
shader_t *s;
s = R_RegisterCustom(picname, NULL);
if (s)
{
GLDraw_ShaderPic(pos[0], pos[1], size[0], size[1], s, rgb[0], rgb[1], rgb[2], alpha);
return;
}
#endif
if (flag == 1) //add
qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
else if(flag == 2) //modulate
@ -409,6 +427,8 @@ void PF_CL_drawpic (progfuncs_t *prinst, struct globalvars_s *pr_globals)
}
#endif
p = Draw_SafeCachePic(picname);
if (Draw_ImageColours)
Draw_ImageColours(rgb[0], rgb[1], rgb[2], alpha);
if (Draw_Image)

View File

@ -867,11 +867,44 @@ char *particle_set_spikeset =
" blend add\n"
" areaspread 0\n"
" areaspreadvert 0\n"
"}\n"
//the default svc_particle effect.
"r_part pe_default\n"
"{\n"
" texture \"particles/quake\"\n"
" count 1\n"
" scale 4\n"
" veladd 15\n"
" alpha 1\n"
" die 0.4\n"
" alphachange 0\n"
" diesubrand 0.4\n"
" gravity 40\n"
" areaspread 8\n"
" areaspreadvert 8\n"
" spawnmode box\n"
"}\n";
///////////////////////////////////////////////////////////////
char *particle_set_highfps = //submitted by 'ShadowWalker'
//fixme: replace with something more effective
"r_part t_gib\n"
"{\n"
" texture \"particles/bloodtrail\"\n"
@ -1122,7 +1155,25 @@ char *particle_set_highfps = //submitted by 'ShadowWalker'
" areaspreadvert 0\n"
"}\n";
char *particle_set_faithful =
/////////////////////////////////////////////////////////////////////
char *particle_set_faithful = //Created from origional quake by TimeServ.
//The aim being to clone the old effects exactly.
"r_part t_gib\n"
"{\n"
" texture \"particles/quake\"\n"

View File

@ -255,6 +255,8 @@ void R_SetVrect (vrect_t *pvrect, vrect_t *pvrectin, int lineadj);
void GLMod_Init (void);
qboolean GLMod_GetTag(struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *result);
int GLMod_TagNumForName(struct model_s *model, char *name);
int GLMod_SkinNumForName(struct model_s *model, char *name);
void GLMod_ClearAll (void);
struct model_s *GLMod_ForName (char *name, qboolean crash);
struct model_s *GLMod_FindName (char *name);

View File

@ -102,7 +102,8 @@ cvar_t r_fullbrightSkins = {"r_fullbrightSkins", "1", NULL, CVAR_SEMICHEAT};
cvar_t r_fb_models = {"gl_fb_models", "1", NULL, CVAR_SEMICHEAT|CVAR_RENDERERLATCH}; //as it can highlight the gun a little... ooo nooo....
cvar_t r_fb_bmodels = {"gl_fb_bmodels", "1", NULL, CVAR_SEMICHEAT|CVAR_RENDERERLATCH}; //as it can highlight the gun a little... ooo nooo....
cvar_t r_shadow_bumpscale_basetexture = {"r_shadow_bumpscale_basetexture", "4"};
cvar_t r_shadow_bumpscale_bumpmap = {"r_shadow_bumpscale_bumpmap", "10"};
cvar_t gl_nocolors = {"gl_nocolors","0"};
cvar_t gl_load24bit = {"gl_load24bit", "1"};
cvar_t vid_conwidth = {"vid_conwidth", "640", NULL, CVAR_ARCHIVE};
@ -117,17 +118,21 @@ cvar_t gl_savecompressedtex = {"gl_savecompressedtex", "0"};
extern cvar_t gl_dither;
extern cvar_t gl_maxdist;
#ifdef SPECULAR
cvar_t gl_specular = {"gl_specular", "0"};
#endif
cvar_t gl_detail = {"gl_detail", "0", NULL, CVAR_ARCHIVE};
cvar_t gl_detailscale = {"gl_detailscale", "5"};
cvar_t gl_overbright = {"gl_overbright", "0", NULL, CVAR_ARCHIVE};
cvar_t r_shadows = {"r_shadows", "0", NULL, CVAR_ARCHIVE|CVAR_RENDERERLATCH};
cvar_t r_shadow_realtime_world = {"r_shadow_realtime_world", "0", NULL, CVAR_CHEAT};
cvar_t r_shadow_realtime_world_lightmaps = {"r_shadow_realtime_world_lightmaps", "0.8", NULL, CVAR_CHEAT};
cvar_t r_noaliasshadows = {"r_noaliasshadows", "0", NULL, CVAR_ARCHIVE};
cvar_t gl_maxshadowlights = {"gl_maxshadowlights", "2", NULL, CVAR_ARCHIVE};
cvar_t gl_bump = {"gl_bump", "0", NULL, CVAR_ARCHIVE|CVAR_RENDERERLATCH};
cvar_t r_shadow_glsl_offsetmapping = {"r_shadow_glsl_offsetmapping", "0"};
cvar_t r_shadow_glsl_offsetmapping_scale = {"r_shadow_glsl_offsetmapping_scale", "-0.04"};
cvar_t r_shadow_glsl_offsetmapping_bias = {"r_shadow_glsl_offsetmapping_bias", "0.04"};
#ifdef SPECULAR
cvar_t gl_specular = {"gl_specular", "0"};
#endif
cvar_t gl_lightmapmode = {"gl_lightmapmode", "", NULL, CVAR_ARCHIVE};
cvar_t gl_ati_truform = {"gl_ati_truform", "0"};
@ -254,6 +259,8 @@ void GLRenderer_Init(void)
Cvar_Register (&r_shadows, GLRENDEREROPTIONS);
Cvar_Register (&r_noaliasshadows, GLRENDEREROPTIONS);
Cvar_Register (&gl_maxshadowlights, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_bumpscale_basetexture, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_bumpscale_bumpmap, GLRENDEREROPTIONS);
Cvar_Register (&gl_part_flame, GRAPHICALNICETIES);
Cvar_Register (&gl_part_torch, GRAPHICALNICETIES);
@ -276,6 +283,10 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_smoothfont, GRAPHICALNICETIES);
Cvar_Register (&gl_bump, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_glsl_offsetmapping, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_glsl_offsetmapping_scale, GRAPHICALNICETIES);
Cvar_Register (&r_shadow_glsl_offsetmapping_bias, GRAPHICALNICETIES);
Cvar_Register (&gl_contrast, GLRENDEREROPTIONS);
#ifdef R_XFLIP
Cvar_Register (&r_xflip, GLRENDEREROPTIONS);
@ -584,6 +595,7 @@ void (*Mod_NowLoadExternal) (void);
void (*Mod_Think) (void);
qboolean (*Mod_GetTag) (struct model_s *model, int tagnum, int frame, int frame2, float f2ness, float f1time, float f2time, float *transforms);
int (*Mod_TagNumForName) (struct model_s *model, char *name);
int (*Mod_SkinForName) (struct model_s *model, char *name);
@ -698,6 +710,7 @@ rendererinfo_t dedicatedrendererinfo = {
NULL, //Mod_GetTag
NULL, //fixme: server will need this one at some point.
NULL,
NULL, //VID_Init,
NULL, //VID_DeInit,
@ -890,6 +903,7 @@ rendererinfo_t openglrendererinfo = {
GLMod_GetTag,
GLMod_TagNumForName,
GLMod_SkinNumForName,
GLVID_Init,
GLVID_DeInit,
@ -1268,6 +1282,7 @@ void R_SetRenderer(int wanted)
Mod_GetTag = ri->Mod_GetTag;
Mod_TagNumForName = ri->Mod_TagNumForName;
Mod_SkinForName = ri->Mod_SkinForName;
SCR_UpdateScreen = ri->SCR_UpdateScreen;
}
@ -1582,7 +1597,7 @@ TRACE(("dbg: R_ApplyRenderer: reloading ALL models\n"));
if (!cl.model_precache[i])
{
Con_Printf ("\nThe required model file '%s' could not be found or downloaded.\n\n"
Con_Printf ("\nThe required model file '%s' could not be found.\n\n"
, cl.model_name[i]);
Con_Printf ("You may need to download or purchase a client "
"pack in order to play on this server.\n\n");
@ -1591,6 +1606,28 @@ TRACE(("dbg: R_ApplyRenderer: reloading ALL models\n"));
return false;
}
}
#ifdef CSQC_DAT
for (i=1 ; i<MAX_CSQCMODELS ; i++)
{
if (!cl.model_csqcname[i][0])
break;
cl.model_csqcprecache[i] = NULL;
TRACE(("dbg: R_ApplyRenderer: reloading csqc model %s\n", cl.model_csqcname[i]));
cl.model_csqcprecache[i] = Mod_ForName (cl.model_csqcname[i], false);
if (!cl.model_csqcprecache[i])
{
Con_Printf ("\nThe required model file '%s' could not be found.\n\n"
, cl.model_csqcname[i]);
Con_Printf ("You may need to download or purchase a client "
"pack in order to play on this server.\n\n");
CL_Disconnect ();
UI_Reset();
return false;
}
}
#endif
loadmodel = cl.worldmodel = cl.model_precache[1];
TRACE(("dbg: R_ApplyRenderer: done the models\n"));

View File

@ -123,10 +123,6 @@ static void ALSA_SetUnderWater(soundcardinfo_t *sc, qboolean underwater)
{
}
void S_UpdateCapture(void)
{
}
static qboolean Alsa_InitAlsa(void)
{
static qboolean tried;

View File

@ -949,7 +949,7 @@ int SNDDMA_InitCapture (void)
}
void SNDVC_Submit(qbyte *buffer, int samples, int freq, int width);
void S_UpdateCapture(void)
void DSOUND_UpdateCapture(void)
{
HRESULT hr;
LPBYTE lpbuf1 = NULL;
@ -1032,8 +1032,5 @@ void S_UpdateCapture(void)
SNDVC_MicInput(pBuffer, filled, wfxFormat.nSamplesPerSec, inputwidth);
BZ_Free(pBuffer);
}
#else
void S_UpdateCapture(void)
{
}
void (*pDSOUND_UpdateCapture) (void) = &DSOUND_UpdateCapture;
#endif

View File

@ -139,6 +139,17 @@ void S_SoundInfo_f(void)
}
}
void (*pDSOUND_UpdateCapture) (void);
void S_RunCapture(void)
{
//add new drivers in order or desirability.
if (pDSOUND_UpdateCapture)
{
pDSOUND_UpdateCapture();
return;
}
}
sounddriver pDSOUND_InitCard;
sounddriver pALSA_InitCard;
@ -1191,7 +1202,7 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
VectorCopy(right, listener_right);
VectorCopy(up, listener_up);
S_UpdateCapture();
S_RunCapture();
for (sc = sndcardinfo; sc; sc = sc->next)
S_UpdateCard(sc);
@ -1340,7 +1351,7 @@ void S_ExtraUpdate (void)
if (snd_noextraupdate.value)
return; // don't pollute timings
S_UpdateCapture();
S_RunCapture();
for (sc = sndcardinfo; sc; sc = sc->next)
S_Update_(sc);

View File

@ -272,8 +272,3 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
int (*pOSS_InitCard) (soundcardinfo_t *sc, int cardnum) = &OSS_InitCard;
void S_UpdateCapture(void)
{
}

View File

@ -145,8 +145,6 @@ void S_DoRestart (void);
//plays streaming audio
void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels, int width);
//tells the audio capture routines to grab a bit more and send it to voice chat server.
void S_UpdateCapture(void);
void CLVC_Poll (void);
void SNDVC_MicInput(qbyte *buffer, int samples, int freq, int width);

View File

@ -307,10 +307,22 @@ void EditorOpenFile(char *name)
firstblock->datalength = len;
memcpy(firstblock->data, line, len);
if (svprogfuncs)
if (svprogfuncs->ToggleBreak(svprogfuncs, OpenEditorFile+strlen(com_gamedir)+1, i, 3))
if (editprogfuncs)
{
firstblock->flags |= FB_BREAK;
if (editprogfuncs->ToggleBreak(editprogfuncs, OpenEditorFile+strlen(com_gamedir)+1, i, 3))
{
firstblock->flags |= FB_BREAK;
}
}
else
{
if (svprogfuncs)
{
if (svprogfuncs->ToggleBreak(svprogfuncs, OpenEditorFile+strlen(com_gamedir)+1, i, 3))
{
firstblock->flags |= FB_BREAK;
}
}
}
i++;
@ -505,7 +517,6 @@ void Editor_Key(int key)
case K_F9:
{
int f = 0;
#ifndef CLIENTONLY
if (editprogfuncs)
{
if (editprogfuncs->ToggleBreak(editprogfuncs, OpenEditorFile+4, cursorlinenum, 2))
@ -513,6 +524,14 @@ void Editor_Key(int key)
else
f |= 2;
}
#ifndef CLIENTONLY
else if (svprogfuncs)
{
if (svprogfuncs->ToggleBreak(svprogfuncs, OpenEditorFile+4, cursorlinenum, 2))
f |= 1;
else
f |= 2;
}
#endif
if (f & 1)
@ -926,7 +945,7 @@ void Editor_Draw(void)
*/
}
int QCLibEditor(char *filename, int line, int nump, char **parms)
int QCLibEditor(progfuncs_t *prfncs, char *filename, int line, int nump, char **parms)
{
if (editormodal || !developer.value)
return line; //whoops
@ -958,6 +977,8 @@ int QCLibEditor(char *filename, int line, int nump, char **parms)
return line;
}
editprogfuncs = prfncs;
if (!strncmp(OpenEditorFile, "src/", 4))
{
if (!editoractive || strcmp(OpenEditorFile+4, filename))
@ -980,8 +1001,6 @@ int QCLibEditor(char *filename, int line, int nump, char **parms)
}
}
editprogfuncs = svprogfuncs;
for (cursorlinenum = 1, cursorblock = firstblock; cursorlinenum < line && cursorblock->next; cursorlinenum++)
cursorblock=cursorblock->next;
@ -993,7 +1012,7 @@ int QCLibEditor(char *filename, int line, int nump, char **parms)
while(editormodal && editoractive && editprogfuncs)
{
key_dest = key_editor;
// key_dest = key_editor;
scr_disabled_for_loading=false;
SCR_UpdateScreen();
Sys_SendKeyEvents();

View File

@ -1,4 +1,422 @@
#include "quakedef.h"
#include <ctype.h>
typedef struct f_query_s
{
char *query;
char *serverinfo;
char *c_userinfo[MAX_CLIENTS];
qboolean c_exist[MAX_CLIENTS];
unsigned short crc;
double timestamp;
}
f_query_t;
#define F_QUERIES_REMEMBERED 5
f_query_t f_last_queries[F_QUERIES_REMEMBERED];
int f_last_query_pos = 0;
typedef struct f_modified_s {
char name[MAX_QPATH];
qboolean ismodified;
struct f_modified_s *next;
} f_modified_t;
f_modified_t *f_modified_list;
qboolean care_f_modified;
qboolean f_modified_particles;
cvar_t allow_f_version = {"allow_f_version", "1"};
cvar_t allow_f_server = {"allow_f_server", "1"};
cvar_t allow_f_modified = {"allow_f_modified", "1"};
cvar_t allow_f_skins = {"allow_f_skins", "1"};
cvar_t auth_validateclients = {"auth_validateclients", "1"};
void CRC_AddBlock (unsigned short *crcvalue, qbyte *start, int count)
{
while (count--)
CRC_ProcessByte(crcvalue, *start++);
}
unsigned short SCRC_GetQueryStateCrc(char *f_query_string)
{
unsigned short crc;
int i;
char *tmp;
CRC_Init(&crc);
// add query
CRC_AddBlock(&crc, f_query_string, strlen(f_query_string));
// add snapshot of serverinfo
tmp = Info_ValueForKey(cl.serverinfo, "deathmatch");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "teamplay");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "hostname");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "*progs");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "map");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "spawn");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "watervis");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "fraglimit");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "*gamedir");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "timelimit");
CRC_AddBlock(&crc, tmp, strlen(tmp));
// add snapshot of userinfo for every connected client
for (i=0; i < MAX_CLIENTS; i++)
if (cl.players[i].name[0])
{
tmp = Info_ValueForKey(cl.players[i].userinfo, "name");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.players[i].userinfo, "team");
CRC_AddBlock(&crc, tmp, strlen(tmp));
}
// done
return crc;
}
#if 1
#define SECURITY_INIT_BAD_CHECKSUM 1
#define SECURITY_INIT_BAD_VERSION 2
#define SECURITY_INIT_ERROR 3
#define SECURITY_INIT_NOPROC 4
typedef struct signed_buffer_s {
qbyte *buf;
unsigned long size;
} signed_buffer_t;
typedef signed_buffer_t *(*Security_Verify_Response_t) (int, unsigned char *);
typedef int (*Security_Init_t) (char *);
typedef signed_buffer_t *(*Security_Generate_Crc_t) (int);
typedef signed_buffer_t *(*Security_IsModelModified_t) (char *, int, qbyte *, int);
typedef void (*Security_Supported_Binaries_t) (void *);
typedef void (*Security_Shutdown_t) (void);
Security_Verify_Response_t Security_Verify_Response;
Security_Init_t Security_Init;
Security_Generate_Crc_t Security_Generate_Crc;
Security_IsModelModified_t Security_IsModelModified;
Security_Supported_Binaries_t Security_Supported_Binaries;
Security_Shutdown_t Security_Shutdown;
void *secmodule;
void ValidationPrintVersion(char *f_query_string)
{
f_query_t *this_query;
unsigned short query_crc;
unsigned long crc;
char answer;
char name[128];
char sr[256];
int i;
switch(qrenderer)
{
#ifdef RGLQUAKE
case QR_OPENGL:
*sr = *"";
break;
#endif
#ifdef SWQUAKE
case QR_SOFTWARE:
strcpy(sr, (r_pixbytes==4?"32bpp":"8bpp"));
break;
#endif
default:
*sr = *"";
break;
}
if (Security_Generate_Crc && allow_f_version.value)
{
signed_buffer_t *resp;
query_crc = SCRC_GetQueryStateCrc(f_query_string);
//
// remember this f_version
//
this_query = &f_last_queries[f_last_query_pos++ % F_QUERIES_REMEMBERED];
this_query->timestamp = realtime;
this_query->crc = query_crc;
if (this_query->query)
BZ_Free(this_query->query);
this_query->query = BZ_Malloc(strlen(f_query_string)+1);
strcpy(this_query->query, f_query_string);
if (this_query->serverinfo)
BZ_Free(this_query->serverinfo);
this_query->serverinfo = BZ_Malloc(strlen(cl.serverinfo)+1);
strcpy(this_query->serverinfo, cl.serverinfo);
for (i=0; i < MAX_CLIENTS; i++)
{
if (this_query->c_userinfo[i])
{
BZ_Free(this_query->c_userinfo[i]);
this_query->c_userinfo[i] = NULL;
}
this_query->c_exist[i] = false;
if (cl.players[i].name[0])
{
this_query->c_exist[i] = true;
this_query->c_userinfo[i] = BZ_Malloc(strlen(cl.players[i].userinfo)+1);
strcpy(this_query->c_userinfo[i], cl.players[i].userinfo);
}
}
resp = Security_Generate_Crc(cl.playernum[0]);
//now send the data.
// SPipe_WriteChar(f_write, SECURE_CMD_GETVERSION);
// SPipe_WriteString(f_write, f_query_string);
// SPipe_WriteString(f_write, cl.serverinfo);
// SPipe_WriteString(f_write, cl.players[cl.playernum[0]].userinfo);
// get answer
// SPipe_ReadChar(f_read, &answer);
// SPipe_ReadString(f_read, name, 64);
// SPipe_ReadUlong(f_read, &crc);
/*
if (answer == SECURE_ANSWER_OK)
{
// reply
Cbuf_AddText("say ", RESTRICT_LOCAL);
Cbuf_AddText(name, RESTRICT_LOCAL);
if (*sr)
Cbuf_AddText(va("/%s/%s", q_renderername, sr), RESTRICT_LOCAL);//extra info
else
Cbuf_AddText(va("/%s", q_renderername), RESTRICT_LOCAL);//extra info
Cbuf_AddText(" ", RESTRICT_LOCAL);
Cbuf_AddText(va("%04x", query_crc), RESTRICT_LOCAL);
Cbuf_AddText(va("%08x", crc), RESTRICT_LOCAL);
Cbuf_AddText("\n", RESTRICT_LOCAL);
return;
}
*/
}
if (*sr)
Cbuf_AddText (va("say "DISTRIBUTION"Quake v%4.3f-%i "PLATFORM"/%s/%s\n", VERSION, build_number(), q_renderername, sr), RESTRICT_RCON);
else
Cbuf_AddText (va("say "DISTRIBUTION"Quake v%4.3f-%i "PLATFORM"/%s\n", VERSION, build_number(), q_renderername), RESTRICT_RCON);
}
void Validation_FilesModified (void)
{
}
void Validation_CheckIfResponse(char *text)
{
//client name, version type(os-renderer where it matters, os/renderer where renderer doesn't), 12 char hex crc
int f_query_client;
int i;
char *crc;
char *versionstring;
if (!Security_Verify_Response)
return; //valid or not, we can't check it.
if (!auth_validateclients.value)
return;
//do the parsing.
{
char *comp;
int namelen;
for (crc = text + strlen(text) - 1; crc > text; crc--)
if ((unsigned)*crc > ' ')
break;
//find the crc.
for (i = 0; i < 29; i++)
{
if (crc <= text)
return; //not enough chars.
if ((unsigned)crc[-1] <= ' ')
break;
crc--;
}
//we now want 3 string seperated tokens, so the first starts at the fourth found ' ' + 1
i = 7;
for (comp = crc-1; ; comp--)
{
if (comp < text)
return;
if (*comp == ' ')
{
i--;
if (!i)
break;
}
}
versionstring = comp+1;
if (comp <= text)
return; //not enough space for the 'name:'
if (*(comp-1) != ':')
return; //whoops. not a say.
namelen = comp - text-1;
for (f_query_client = 0; f_query_client < MAX_CLIENTS; f_query_client++)
{
if (strlen(cl.players[f_query_client].name) == namelen)
if (!strncmp(cl.players[f_query_client].name, text, namelen))
break;
}
if (f_query_client == MAX_CLIENTS)
return; //looks like a validation, but it's not from a known client.
}
//now do the validation
{
f_query_t *query = NULL;
int itemp;
char buffer[10];
unsigned short query_crc = 0;
unsigned long user_crc = 0;
unsigned long auth_crc = 0;
char auth_answer;
int slot;
signed_buffer_t *resp;
//easy lame way to get the crc from hex.
Q_strncpyS(buffer, crc, 4);
buffer[4] = '\0';
itemp = 0;
sscanf(buffer, "%x", &itemp);
query_crc = (unsigned long) itemp;
Q_strncpyS(buffer, crc+4, 8);
buffer[8] = '\0';
itemp = 0;
sscanf(buffer, "%x", &itemp);
user_crc = (unsigned long) itemp;
//
// find that query
//
/* for (i=f_last_query_pos; i > f_last_query_pos-F_QUERIES_REMEMBERED; i--)
{
if (query_crc == f_last_queries[i % F_QUERIES_REMEMBERED].crc &&
realtime - 5 < f_last_queries[i % F_QUERIES_REMEMBERED].timestamp)
{
query = &f_last_queries[i % F_QUERIES_REMEMBERED];
}
}
if (query == NULL)
return; // reply to unknown query
if (!query->c_exist[f_query_client])
return; // should never happen
*/
resp = Security_Verify_Response(f_query_client, crc);
if (resp && resp->size && *resp->buf)
Con_Printf("Authentication Successful.\n");
else// if (!resp)
Con_Printf("^1^bAUTHENTICATION FAILED.\n");
/*
typedef signed_buffer_t *(*Security_Verify_Response_t) (int, unsigned char *);
// write request
SPipe_WriteChar(f_write, SECURE_CMD_CHECKVERSION2);
SPipe_WriteString(f_write, query->query);
SPipe_WriteString(f_write, query->serverinfo);
SPipe_WriteString(f_write, query->c_userinfo[f_query_client]);
SPipe_WriteString(f_write, versionstring);
// get answer
SPipe_ReadChar(f_read, &auth_answer);
SPipe_ReadUlong(f_read, &auth_crc);
if (auth_answer == SECURE_ANSWER_YES && auth_crc == user_crc)
{
Con_Printf("Authentication Successful.\n");
}
else
Con_Printf("^1^bAUTHENTICATION FAILED.\n");
*/
}
}
void InitValidation(void)
{
Cvar_Register(&allow_f_version, "Authentication");
Cvar_Register(&allow_f_server, "Authentication");
Cvar_Register(&allow_f_modified, "Authentication");
Cvar_Register(&allow_f_skins, "Authentication");
secmodule = LoadLibrary("fteqw-security.dll");
if (secmodule)
{
Security_Verify_Response = (void*)GetProcAddress(secmodule, "Security_Verify_Response");
Security_Init = (void*)GetProcAddress(secmodule, "Security_Init");
Security_Generate_Crc = (void*)GetProcAddress(secmodule, "Security_Generate_Crc");
Security_IsModelModified = (void*)GetProcAddress(secmodule, "Security_IsModelModified");
Security_Supported_Binaries = (void*)GetProcAddress(secmodule, "Security_Supported_Binaries");
Security_Shutdown = (void*)GetProcAddress(secmodule, "Security_Shutdown");
}
if (Security_Init)
{
switch(Security_Init(va("%s %.2f %i", DISTRIBUTION, VERSION, build_number())))
{
case SECURITY_INIT_BAD_CHECKSUM:
Con_Printf("Checksum failed. Security module does not support this build. Go upgrade it.\n");
break;
case SECURITY_INIT_BAD_VERSION:
Con_Printf("Version failed. Security module does not support this version. Go upgrade.\n");
break;
case SECURITY_INIT_ERROR:
Con_Printf("'Generic' security error. Stop hacking.\n");
break;
case SECURITY_INIT_NOPROC:
Con_Printf("/proc/* does not exist. You will need to upgrade your kernel.\n");
break;
case 0:
Cvar_Register(&auth_validateclients, "Authentication");
return;
}
Security_Verify_Response = NULL;
Security_Init = NULL;
Security_Generate_Crc = NULL;
Security_IsModelModified = NULL;
Security_Supported_Binaries = NULL;
Security_Shutdown = NULL;
FreeLibrary(secmodule);
}
}
void Validation_IncludeFile(char *filename, char *file, int filelen)
{
}
qboolean f_modified_particles;
qboolean care_f_modified;
#else
#ifdef RGLQUAKE
#include "glquake.h" //overkill
@ -223,59 +641,6 @@ int SPipe_WriteString(qpipe write_pipe, char *string)
return true;
}
void CRC_AddBlock (unsigned short *crcvalue, qbyte *start, int count)
{
while (count--)
CRC_ProcessByte(crcvalue, *start++);
}
unsigned short SCRC_GetQueryStateCrc(char *f_query_string)
{
unsigned short crc;
int i;
char *tmp;
CRC_Init(&crc);
// add query
CRC_AddBlock(&crc, f_query_string, strlen(f_query_string));
// add snapshot of serverinfo
tmp = Info_ValueForKey(cl.serverinfo, "deathmatch");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "teamplay");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "hostname");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "*progs");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "map");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "spawn");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "watervis");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "fraglimit");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "*gamedir");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.serverinfo, "timelimit");
CRC_AddBlock(&crc, tmp, strlen(tmp));
// add snapshot of userinfo for every connected client
for (i=0; i < MAX_CLIENTS; i++)
if (cl.players[i].name[0])
{
tmp = Info_ValueForKey(cl.players[i].userinfo, "name");
CRC_AddBlock(&crc, tmp, strlen(tmp));
tmp = Info_ValueForKey(cl.players[i].userinfo, "team");
CRC_AddBlock(&crc, tmp, strlen(tmp));
}
// done
return crc;
}
void InitValidation(void)
{
char *read, *write;
@ -397,18 +762,6 @@ void Validation_IncludeFile(char *filename, char *file, int filelen)
}
}
void Validation_FlushFileList(void)
{
f_modified_t *fm;
while(f_modified_list)
{
fm = f_modified_list->next;
Z_Free(f_modified_list);
f_modified_list = fm;
}
}
void ValidationPrintVersion(char *f_query_string)
{
f_query_t *this_query;
@ -505,27 +858,6 @@ void ValidationPrintVersion(char *f_query_string)
Cbuf_AddText (va("say "DISTRIBUTION"Quake v%4.3f-%i "PLATFORM"/%s\n", VERSION, build_number(), q_renderername), RESTRICT_RCON);
}
void Validation_Skins(void)
{
extern cvar_t r_fullbrightSkins, r_fb_models;
int percent = r_fullbrightSkins.value*100;
if (percent < 0)
percent = 0;
if (percent > cls.allow_fbskins*100)
percent = cls.allow_fbskins*100;
if (percent)
Cbuf_AddText(va("say all player skins %i%% fullbright%s\n", percent, r_fb_models.value?" (plus luma)":""), RESTRICT_LOCAL);
else if (r_fb_models.value)
Cbuf_AddText("say luma textures only\n", RESTRICT_LOCAL);
else
Cbuf_AddText("say Only cheaters use full bright skins\n", RESTRICT_LOCAL);
}
void Validation_Server(void)
{
Cbuf_AddText(va("say server is %s\n", NET_AdrToString(cls.netchan.remote_address)), RESTRICT_LOCAL);
}
void Validation_CheckIfResponse(char *text)
{
//client name, version type(os-renderer where it matters, os/renderer where renderer doesn't), 12 char hex crc
@ -654,3 +986,39 @@ void Validation_CheckIfResponse(char *text)
Con_Printf("^1^bAUTHENTICATION FAILED.\n");
}
}
#endif
void Validation_FlushFileList(void)
{
f_modified_t *fm;
while(f_modified_list)
{
fm = f_modified_list->next;
Z_Free(f_modified_list);
f_modified_list = fm;
}
}
void Validation_Server(void)
{
Cbuf_AddText(va("say server is %s\n", NET_AdrToString(cls.netchan.remote_address)), RESTRICT_LOCAL);
}
void Validation_Skins(void)
{
extern cvar_t r_fullbrightSkins, r_fb_models;
int percent = r_fullbrightSkins.value*100;
if (percent < 0)
percent = 0;
if (percent > cls.allow_fbskins*100)
percent = cls.allow_fbskins*100;
if (percent)
Cbuf_AddText(va("say all player skins %i%% fullbright%s\n", percent, r_fb_models.value?" (plus luma)":""), RESTRICT_LOCAL);
else if (r_fb_models.value)
Cbuf_AddText("say luma textures only\n", RESTRICT_LOCAL);
else
Cbuf_AddText("say Only cheaters use full bright skins\n", RESTRICT_LOCAL);
}

View File

@ -99,6 +99,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define SP2MODELS //quake2 sprite models
#define MD2MODELS //quake2 alias models
#define MD3MODELS //quake3 alias models
#define MD5MODELS //doom3 models
#define ZYMOTICMODELS //zymotic skeletal models.
#define HUFFNETWORK //huffman network compression
#define HALFLIFEMODELS //halflife model support (experimental)

View File

@ -1156,7 +1156,7 @@ void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize)
while (1)
{
// skip whitespace up to a /n
while (*text && *text <= ' ' && *text != '\n')
while (*text && (unsigned)*text <= ' ' && *text != '\n')
{
text++;
}

View File

@ -1389,7 +1389,10 @@ void COM_StripExtension (char *in, char *out)
while(*s != '/' && s != out)
{
if (*s == '.')
{
*s = 0;
break;
}
s--;
}
@ -1688,7 +1691,7 @@ char *COM_StringParse (char *data, qboolean expandmacros, qboolean qctokenize)
// skip whitespace
skipwhite:
while ( (c = *data), c <= ' ' && c != '\n')
while ( (c = *data), (unsigned)c <= ' ' && c != '\n')
{
if (c == 0)
return NULL; // end of file;
@ -1824,7 +1827,7 @@ skipwhite:
data++;
len++;
c = *data;
} while (c>32 && !(qctokenize && (c == '\n' || c == '{' || c == '}' || c == ')' || c == '(' || c == ']' || c == '[' || c == '\'' || c == ':' || c == ',' || c == ';')));
} while ((unsigned)c>32 && !(qctokenize && (c == '\n' || c == '{' || c == '}' || c == ')' || c == '(' || c == ']' || c == '[' || c == '\'' || c == ':' || c == ',' || c == ';')));
com_token[len] = 0;

View File

@ -27,6 +27,7 @@
extern qboolean r_usinglits;
#endif
extern cvar_t r_shadow_bumpscale_basetexture;
//these are in model.c (or gl_model.c)
void GLMod_LoadVertexes (lump_t *l);
@ -1115,7 +1116,7 @@ void *Mod_LoadWall(char *name)
oin = (qbyte *)wal+wal->offsets[0];
for (j = 0; j < wal->width*wal->height; j++)
in[j] = (d_q28to24table[oin[j]*3+0] + d_q28to24table[oin[j]*3+1] + d_q28to24table[oin[j]*3+2])/3;
tex->gl_texturenumbumpmap = GL_LoadTexture8Bump (va("%s_bump", wal->name), tex->width, tex->height, in, true);
tex->gl_texturenumbumpmap = GL_LoadTexture8Bump (va("%s_bump", wal->name), tex->width, tex->height, in, true, r_shadow_bumpscale_basetexture.value);
texture_mode = GL_LINEAR;
}
else

View File

@ -513,6 +513,29 @@ void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
in1[2][2] * in2[2][3] + in1[2][3];
}
void R_ConcatRotationsPad (float in1[3][4], float in2[3][4], float out[3][4])
{
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
in1[0][2] * in2[2][0];
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
in1[0][2] * in2[2][1];
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
in1[0][2] * in2[2][2];
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
in1[1][2] * in2[2][0];
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
in1[1][2] * in2[2][1];
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
in1[1][2] * in2[2][2];
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
in1[2][2] * in2[2][0];
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
in1[2][2] * in2[2][1];
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
in1[2][2] * in2[2][2];
}
/*
===================
@ -804,9 +827,9 @@ void Matrix4_Transform4(float *matrix, float *vector, float *product)
void Matrix4_Transform3(float *matrix, float *vector, float *product)
{
product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12]*vector[3];
product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13]*vector[3];
product[2] = matrix[2]*vector[0] + matrix[6]*vector[1] + matrix[10]*vector[2] + matrix[14]*vector[3];
product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12];
product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13];
product[2] = matrix[2]*vector[0] + matrix[6]*vector[1] + matrix[10]*vector[2] + matrix[14];
}
void ML_ModelViewMatrix(float *modelview, vec3_t viewangles, vec3_t vieworg)
@ -896,33 +919,76 @@ void ML_ProjectionMatrix(float *proj, float wdivh, float fovy)
proj[15] = 0;
}
typedef struct {
float m[4][4];
} matrix4x4_t;
void Matrix4x4_Invert_Simple (matrix4x4_t *out, const matrix4x4_t *in1)
{
// we only support uniform scaling, so assume the first row is enough
// (note the lack of sqrt here, because we're trying to undo the scaling,
// this means multiplying by the inverse scale twice - squaring it, which
// makes the sqrt a waste of time)
#if 1
double scale = 1.0 / (in1->m[0][0] * in1->m[0][0] + in1->m[0][1] * in1->m[0][1] + in1->m[0][2] * in1->m[0][2]);
#else
double scale = 3.0 / sqrt
(in1->m[0][0] * in1->m[0][0] + in1->m[0][1] * in1->m[0][1] + in1->m[0][2] * in1->m[0][2]
+ in1->m[1][0] * in1->m[1][0] + in1->m[1][1] * in1->m[1][1] + in1->m[1][2] * in1->m[1][2]
+ in1->m[2][0] * in1->m[2][0] + in1->m[2][1] * in1->m[2][1] + in1->m[2][2] * in1->m[2][2]);
scale *= scale;
#endif
// invert the rotation by transposing and multiplying by the squared
// recipricol of the input matrix scale as described above
out->m[0][0] = (float)(in1->m[0][0] * scale);
out->m[0][1] = (float)(in1->m[1][0] * scale);
out->m[0][2] = (float)(in1->m[2][0] * scale);
out->m[1][0] = (float)(in1->m[0][1] * scale);
out->m[1][1] = (float)(in1->m[1][1] * scale);
out->m[1][2] = (float)(in1->m[2][1] * scale);
out->m[2][0] = (float)(in1->m[0][2] * scale);
out->m[2][1] = (float)(in1->m[1][2] * scale);
out->m[2][2] = (float)(in1->m[2][2] * scale);
// invert the translate
out->m[0][3] = -(in1->m[0][3] * out->m[0][0] + in1->m[1][3] * out->m[0][1] + in1->m[2][3] * out->m[0][2]);
out->m[1][3] = -(in1->m[0][3] * out->m[1][0] + in1->m[1][3] * out->m[1][1] + in1->m[2][3] * out->m[1][2]);
out->m[2][3] = -(in1->m[0][3] * out->m[2][0] + in1->m[1][3] * out->m[2][1] + in1->m[2][3] * out->m[2][2]);
// don't know if there's anything worth doing here
out->m[3][0] = 0;
out->m[3][1] = 0;
out->m[3][2] = 0;
out->m[3][3] = 1;
}
//screen->3d
void ML_UnProject(vec3_t in, vec3_t out, vec3_t viewangles, vec3_t vieworg, float wdivh, float fovy)
{
float modelview[16];
float proj[16];
float tempm[16];
ML_ModelViewMatrix(modelview, viewangles, vieworg);
ML_ProjectionMatrix(proj, wdivh, fovy);
Matrix4_Multiply(proj, modelview, tempm);
Matrix4x4_Invert_Simple(proj, tempm);
{
float v[4], tempv[4];
v[0] = in[0];
v[1] = in[1];
v[2] = in[2];
v[0] = in[0]*2-1;
v[1] = in[1]*2-1;
v[2] = in[2]*2-1;
v[3] = 1;
Matrix4_Multiply(modelview, v, tempv);
Matrix4_Multiply(proj, tempv, v);
Matrix4_Transform4(proj, v, tempv);
v[0] /= v[3];
v[1] /= v[3];
v[2] /= v[3];
out[0] = (1+v[0])/2;
out[1] = (1+v[1])/2;
out[2] = (1+v[2])/2;
out[0] = tempv[0];
out[1] = tempv[1];
out[2] = tempv[2];
}
}

View File

@ -47,9 +47,9 @@ extern int nanmask;
#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}
#define VectorClear(a) (a[0]=a[1]=a[2]=0)
#define VectorNegate(a,b) (b[0]=-a[0],b[1]=-a[1],b[2]=-a[2])
#define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
#define VectorLength(a) Length(a)
void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc);

View File

@ -30,9 +30,9 @@ typedef struct
netadrtype_t type;
union {
qbyte ip[4];
qbyte ip6[16];
qbyte ipx[10];
qbyte ip[4];
qbyte ip6[16];
qbyte ipx[10];
};
unsigned short port;

View File

@ -160,6 +160,8 @@ void P_TorchEffect (vec3_t pos, int type); //particles centered around a model,
void P_BlobExplosion (vec3_t org); //tarbaby explosion or TF emp.
void P_ParticleExplosion (vec3_t org); //rocket explosion (sprite is allocated seperatly :( )
void P_LavaSplash (vec3_t org); //cthon dying, or a gas grenade.
void P_RunParticleCube(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter);
void P_RunParticleWeather(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname);
//the core spawn function for trails. (trailstate can be null)
int P_ParticleTrail (vec3_t start, vec3_t end, int type, trailstate_t **trailstate);

View File

@ -23,6 +23,9 @@ typedef struct plugin_s {
int sbarlevel[3]; //0 - main sbar, 1 - supplementry sbar sections (make sure these can be switched off), 2 - overlays (scoreboard). menus kill all.
int reschange;
//protocol-in-a-plugin
int connectionlessclientpacket;
struct plugin_s *next;
} plugin_t;
@ -37,6 +40,7 @@ void Plug_RegisterBuiltin(char *name, Plug_Builtin_t bi, int flags);
#define PLUG_BIF_QVMONLY 2
void Plug_Init(void);
void Plug_Close(plugin_t *plug);
void Plug_Tick(void);
qboolean Plugin_ExecuteString(void);
@ -45,6 +49,7 @@ void Plug_Shutdown(void);
static plugin_t *plugs;
static plugin_t *menuplug; //plugin that has the current menu
static plugin_t *protocolclientplugin;
typedef struct {
@ -165,7 +170,7 @@ plugin_t *Plug_Load(char *file)
for (newplug = plugs; newplug; newplug = newplug->next)
{
if (!stricmp(newplug->name, file))
return NULL;
return newplug;
}
newplug = Z_Malloc(sizeof(plugin_t)+strlen(file)+1);
@ -176,11 +181,17 @@ plugin_t *Plug_Load(char *file)
currentplug = newplug;
if (newplug->vm)
{
Con_Printf("Created plugin %s\n", file);
newplug->next = plugs;
plugs = newplug;
argarray = 4;
VM_Call(newplug->vm, 0, Plug_FindBuiltin("Plug_GetEngineFunction"-4, ~0, &argarray));
if (!VM_Call(newplug->vm, 0, Plug_FindBuiltin("Plug_GetEngineFunction"-4, ~0, &argarray)))
{
Plug_Close(newplug);
return NULL;
}
if (newplug->reschange)
VM_Call(newplug->vm, newplug->reschange, vid.width, vid.height);
@ -238,6 +249,8 @@ int Plug_ExportToEngine(void *offset, unsigned int mask, const long *arg)
currentplug->sbarlevel[1] = arg[1];
else if (!strcmp(name, "SbarOverlay")) //overlay - scoreboard type stuff.
currentplug->sbarlevel[2] = arg[1];
else if (!strcmp(name, "ConnectionlessClientPacket"))
currentplug->connectionlessclientpacket = arg[1];
else
return 0;
return 1;
@ -1072,6 +1085,45 @@ int Plug_Net_Send(void *offset, unsigned int mask, const long *arg)
return -2;
}
}
int Plug_Net_SendTo(void *offset, unsigned int mask, const long *arg)
{
int written;
int handle = VM_LONG(arg[0]);
void *src = VM_POINTER(arg[1]);
int srclen = VM_LONG(arg[2]);
netadr_t *address = VM_POINTER(arg[3]);
struct sockaddr_qstorage sockaddr;
if (handle == -1)
{
NET_SendPacket(NS_CLIENT, srclen, src, *address);
return srclen;
}
NetadrToSockadr(address, &sockaddr);
if (handle < 0 || handle >= pluginstreamarraylen || pluginstreamarray[handle].plugin != currentplug)
return -2;
switch(pluginstreamarray[handle].type)
{
case STREAM_SOCKET:
written = sendto(pluginstreamarray[handle].socket, src, srclen, 0, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
if (written < 0)
{
if (qerrno == EWOULDBLOCK)
return -1;
else
return -2;
}
else if (written == 0)
return -2; //closed by remote connection.
return written;
default:
return -2;
}
}
int Plug_Net_Close(void *offset, unsigned int mask, const long *arg)
{
int handle = VM_LONG(arg[0]);
@ -1096,7 +1148,8 @@ void Plug_Load_f(void)
{
Con_Printf("Loads a plugin\n");
Con_Printf("plug_load [pluginpath]\n");
Con_Printf("example pluginpath: plugins/blahx86.so\n");
Con_Printf("example pluginpath: plugins/blah\n");
Con_Printf("will load blahx86.dll or blah.so\n");
return;
}
if (!Plug_Load(plugin))
@ -1156,16 +1209,20 @@ void Plug_Init(void)
Plug_RegisterBuiltin("Net_TCPConnect", Plug_Net_TCPConnect, 0);
Plug_RegisterBuiltin("Net_Recv", Plug_Net_Recv, 0);
Plug_RegisterBuiltin("Net_Send", Plug_Net_Send, 0);
Plug_RegisterBuiltin("Net_SendTo", Plug_Net_SendTo, 0);
Plug_RegisterBuiltin("Net_Close", Plug_Net_Close, 0);
Plug_RegisterBuiltin("Media_ShowFrameRGBA_32", Plug_Media_ShowFrameRGBA_32, 0);
if (plug_loaddefault.value)
{
#ifdef _WIN32
COM_EnumerateFiles("plugins/*x86.dll", Plug_Emumerated, "x86.dll");
COM_EnumerateFiles("plugins/*x86.dll", Plug_Emumerated, "x86.dll");
#elif defined(__linux__)
COM_EnumerateFiles("plugins/*x86.so", Plug_Emumerated, "x86.so");
COM_EnumerateFiles("plugins/*x86.so", Plug_Emumerated, "x86.so");
#endif
COM_EnumerateFiles("plugins/*.qvm", Plug_Emumerated, ".qvm");
COM_EnumerateFiles("plugins/*.qvm", Plug_Emumerated, ".qvm");
}
}
void Plug_Tick(void)
@ -1240,6 +1297,32 @@ qboolean Plug_Menu_Event(int eventtype, int param) //eventtype = draw/keydown/ke
return ret;
}
int Plug_ConnectionlessClientPacket(char *buffer, int size)
{
for (currentplug = plugs; currentplug; currentplug = currentplug->next)
{
if (currentplug->connectionlessclientpacket)
{
switch (VM_Call(currentplug->vm, currentplug->connectionlessclientpacket, buffer, size, &net_from))
{
case 0:
continue; //wasn't handled
case 1:
currentplug = NULL; //was handled with no apparent result
return true;
case 2:
#ifndef SERVERONLY
cls.protocol = CP_PLUGIN; //woo, the plugin wants to connect to them!
protocolclientplugin = currentplug;
#endif
currentplug = NULL;
return true;
}
}
}
return false;
}
void Plug_SBar(void)
{
plugin_t *oc=currentplug;
@ -1329,6 +1412,12 @@ void Plug_Close(plugin_t *plug)
menuplug = NULL;
key_dest = key_game;
}
if (protocolclientplugin == plug)
{
protocolclientplugin = NULL;
if (cls.protocol == CP_PLUGIN)
cls.protocol = CP_UNKNOWN;
}
}
void Plug_Close_f(void)

View File

@ -268,10 +268,8 @@ PM_PlayerTrace
trace_t PM_PlayerTrace (vec3_t start, vec3_t end)
{
trace_t trace, total;
hull_t *hull;
int i;
physent_t *pe;
vec3_t mins, maxs;
// fill in a default trace
memset (&total, 0, sizeof(trace_t));
@ -282,7 +280,6 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end)
for (i=0 ; i< pmove.numphysent ; i++)
{
pe = &pmove.physents[i];
// get the clipping hull
// trace a line through the apropriate clipping hull
PM_TransformedHullCheck (pe->model, start, end, &trace, pe->origin, pe->angles);

View File

@ -848,6 +848,7 @@ typedef struct q1usercmd_s
//ROGUE
#define Q2RF_ADDATIVE 0x00080000
#define RF_NOSHADOW 0x00100000
// player_state_t->refdef flags
#define Q2RDF_UNDERWATER 1 // warp the screen as apropriate

File diff suppressed because it is too large Load Diff

View File

@ -106,7 +106,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /G5 /ML /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /Yu"quakedef.h" /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c
# ADD CPP /nologo /G5 /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /Yu"quakedef.h" /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c
# SUBTRACT CPP /X
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
@ -117,7 +117,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 comctl32.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib winmm.lib /nologo /subsystem:windows /debug /machine:I386 /out:"../../fteglqw_dbg.exe" /libpath:"../libs/dxsdk7/lib"
# ADD LINK32 comctl32.lib wsock32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /out:"../../fteglqw_dbg.exe" /libpath:"../libs/dxsdk7/lib"
# SUBTRACT LINK32 /pdb:none
!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease"
@ -2638,8 +2638,6 @@ SOURCE=..\gl\gl_alias.c
!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server"
# PROP Exclude_From_Build 1
!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server"
# PROP BASE Exclude_From_Build 1

File diff suppressed because it is too large Load Diff

View File

@ -1442,6 +1442,60 @@ void GLDraw_Pic (int x, int y, mpic_t *pic)
GL_DrawMesh(&draw_mesh, gl->texnum);
}
#ifdef Q3SHADERS
void GLDraw_ShaderPic (int x, int y, int width, int height, shader_t *pic, float r, float g, float b, float a)
{
meshbuffer_t mb;
if (!pic)
return;
R_IBrokeTheArrays();
mb.entity = &r_worldentity;
mb.shader = pic;
mb.fog = NULL;
mb.mesh = &draw_mesh;
mb.infokey = 0;
mb.dlightbits = 0;
draw_mesh_xyz[0][0] = x;
draw_mesh_xyz[0][1] = y;
draw_mesh_st[0][0] = 0;
draw_mesh_st[0][1] = 0;
draw_mesh_xyz[1][0] = x+width;
draw_mesh_xyz[1][1] = y;
draw_mesh_st[1][0] = 1;
draw_mesh_st[1][1] = 0;
draw_mesh_xyz[2][0] = x+width;
draw_mesh_xyz[2][1] = y+height;
draw_mesh_st[2][0] = 1;
draw_mesh_st[2][1] = 1;
draw_mesh_xyz[3][0] = x;
draw_mesh_xyz[3][1] = y+height;
draw_mesh_st[3][0] = 0;
draw_mesh_st[3][1] = 1;
draw_mesh_colors[0][0] = r*255;
draw_mesh_colors[0][1] = g*255;
draw_mesh_colors[0][2] = b*255;
draw_mesh_colors[0][3] = a*255;
((int*)draw_mesh_colors)[1] = ((int*)draw_mesh_colors)[0];
((int*)draw_mesh_colors)[2] = ((int*)draw_mesh_colors)[0];
((int*)draw_mesh_colors)[3] = ((int*)draw_mesh_colors)[0];
draw_mesh.colors_array = draw_mesh_colors;
R_PushMesh(&draw_mesh, mb.shader->features | MF_COLORS | MF_NONBATCHED);
R_RenderMeshBuffer ( &mb, false );
draw_mesh.colors_array = NULL;
}
#endif
void GLDraw_ScalePic (int x, int y, int width, int height, mpic_t *pic)
{
glpic_t *gl;
@ -2903,7 +2957,7 @@ unsigned int * genNormalMap(qbyte *pixels, int w, int h, float scale)
/* The highest resolution mipmap level always has a
unit length magnitude. */
nmap[i*w+j] = LittleLong ((255 << 24)|(b << 16)|(g << 8)|(r)); // <AWE> Added support for big endian.
nmap[i*w+j] = LittleLong ((pixels[i*wr + j] << 24)|(b << 16)|(g << 8)|(r)); // <AWE> Added support for big endian.
}
}
@ -2911,7 +2965,7 @@ unsigned int * genNormalMap(qbyte *pixels, int w, int h, float scale)
}
//PENTA
void GL_UploadBump(qbyte *data, int width, int height, qboolean mipmap)
void GL_UploadBump(qbyte *data, int width, int height, qboolean mipmap, float bumpscale)
{
unsigned char *scaled = uploadmemorybuffer;
int scaled_width, scaled_height;
@ -2938,10 +2992,7 @@ void GL_UploadBump(qbyte *data, int width, int height, qboolean mipmap)
GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
}
// if (is_overriden)
// nmap = (qbyte *)genNormalMap(scaled,scaled_width,scaled_height,10.0f);
// else
nmap = (qbyte *)genNormalMap(scaled,scaled_width,scaled_height,4.0f);
nmap = (qbyte *)genNormalMap(scaled,scaled_width,scaled_height,bumpscale);
qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA
, scaled_width, scaled_height, 0,
@ -3563,7 +3614,7 @@ int GL_LoadTexture8Grey (char *identifier, int width, int height, unsigned char
return texture_extension_number-1;
}
int GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, qboolean mipmap)
int GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, qboolean mipmap, float bumpscale)
{
// qboolean noalpha;
// int p, s;
@ -3599,7 +3650,7 @@ int GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char
{
GL_Bind(texture_extension_number );
GL_UploadBump (data, width, height, mipmap);
GL_UploadBump (data, width, height, mipmap, bumpscale);
}
texture_extension_number++;

View File

@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "shader.h"
#endif
extern cvar_t r_shadow_bumpscale_basetexture;
extern int gl_bumpmappingpossible;
qboolean isnotmap = true; //used to not warp ammo models.
@ -57,6 +58,9 @@ void Mod_LoadGroupModel (model_t *mod, void *buffer);
#ifdef ZYMOTICMODELS
void GLMod_LoadZymoticModel(model_t *mod, void *buffer);
#endif
#ifdef MD5MODELS
void GLMod_LoadMD5MeshModel(model_t *mod, void *buffer);
#endif
model_t *GLMod_LoadModel (model_t *mod, qboolean crash);
#ifdef DOOMWADS
@ -678,8 +682,23 @@ couldntload:
break;
#endif
default:
Con_Printf("Unrecognised model format %i\n", LittleLong(*(unsigned *)buf));
goto couldntload;
//check for text based headers
COM_Parse((char*)buf);
if (!strcmp(com_token, "MD5Version"))
{
GLMod_LoadMD5MeshModel (mod, buf);
break;
}
else if (!strcmp(com_token, "EXTERNALANIM"))
{
GLMod_LoadCompositeAnim (mod, buf);
break;
}
else
{
Con_Printf("Unrecognised model format %i\n", LittleLong(*(unsigned *)buf));
goto couldntload;
}
}
P_DefaultTrail(mod);
@ -1060,7 +1079,7 @@ TRACE(("dbg: GLMod_LoadTextures: inittexturedescs\n"));
for (j = 0; j < pixels; j++)
base[j] = (host_basepal[base[j]*3] + host_basepal[base[j]*3+1] + host_basepal[base[j]*3+2]) / 3;
tx->gl_texturenumbumpmap = GL_LoadTexture8Bump(altname, tx->width, tx->height, base, true); //normalise it and then bump it.
tx->gl_texturenumbumpmap = GL_LoadTexture8Bump(altname, tx->width, tx->height, base, true, r_shadow_bumpscale_basetexture.value); //normalise it and then bump it.
}
//don't do any complex quake 8bit -> glossmap. It would likly look a little ugly...
@ -1187,7 +1206,6 @@ TRACE(("dbg: GLMod_LoadTextures: inittexturedescs\n"));
}
}
int GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, qboolean mipmap);
void GLMod_NowLoadExternal(void)
{
extern int gl_bumpmappingpossible;
@ -1247,7 +1265,7 @@ void GLMod_NowLoadExternal(void)
*heightmap++ = (data[j*4+0] + data[j*4+1] + data[j*4+2])/3;
}
tx->gl_texturenumbumpmap = GL_LoadTexture8Bump (va("%s_bump", tx->name), width, height, heightmap-j, true);
tx->gl_texturenumbumpmap = GL_LoadTexture8Bump (va("%s_bump", tx->name), width, height, heightmap-j, true, r_shadow_bumpscale_basetexture.value);
}
}
}

View File

@ -1,3 +1,7 @@
//FIXME: Light visibility is decided from weather the light's pvs overlaps the view pvs.
//This doesn't take light radius into account. This means that lights around corners that will never be visible are drawn in full per-pixel goodness.
//This is bad. lights*3, 33% framerate for no worthwhile effect.
#include "quakedef.h"
#ifdef RGLQUAKE
#include "glquake.h"
@ -9,6 +13,13 @@ void GL_SelectTexture (GLenum target);
void R_RenderDynamicLightmaps (msurface_t *fa);
void R_BlendLightmaps (void);
void PPL_BeginShadowMesh(dlight_t *dl);
void PPL_FinishShadowMesh(dlight_t *dl);
void PPL_FlushShadowMesh(dlight_t *dl);
void PPL_Shadow_Cache_Surface(msurface_t *surf); //only caches for lighting
void PPL_Shadow_Cache_Leaf(mleaf_t *leaf);
extern qboolean r_inmirror;
extern int gldepthfunc;
extern int *lightmap_textures;
@ -23,6 +34,10 @@ extern cvar_t gl_part_flame;
extern cvar_t gl_part_flame;
extern cvar_t gl_maxshadowlights;
extern cvar_t r_shadow_realtime_world;
extern cvar_t r_shadow_realtime_world_lightmaps;
extern cvar_t r_shadow_glsl_offsetmapping;
extern cvar_t r_shadow_glsl_offsetmapping_scale;
extern cvar_t r_shadow_glsl_offsetmapping_bias;
extern int detailtexture;
extern cvar_t gl_bump;
extern cvar_t gl_specular;
@ -33,6 +48,8 @@ extern cvar_t r_drawflat;
extern cvar_t r_wallcolour;
extern cvar_t r_floorcolour;
float r_lightmapintensity; //1 or r_shadow_realtime_world_lightmaps
int overbright;
extern lightmapinfo_t **lightmap;
@ -78,11 +95,21 @@ qboolean PPL_ShouldDraw(void)
return true;
}
typedef struct {
int count;
msurface_t **s;
} shadowmeshsurfs_t;
typedef struct shadowmesh_s {
int numindicies;
int numverts;
int *indicies;
vec3_t *verts;
//we also have a list of all the surfaces that this light lights.
int numsurftextures;
shadowmeshsurfs_t *litsurfs;
unsigned char *litleaves;
} shadowmesh_t;
@ -1137,29 +1164,44 @@ static void PPL_BaseChain_Flat(msurface_t *first)
int vi=-10;
glRect_t *theRect;
if (r_wallcolour.modified)
{
char *s;
r_wallcolour.modified = false;
if (!r_lightmapintensity)
{ //these are bad. :(
s = COM_Parse(r_wallcolour.string);
wallcolour[0] = atof(com_token);
s = COM_Parse(s);
wallcolour[1] = atof(com_token);
s = COM_Parse(s);
wallcolour[2] = atof(com_token);
PPL_EnableVertexArrays();
qglColor4f(0,0,0,1);
qglDisable(GL_TEXTURE_2D); //texturing? who wants texturing?!?!
for (s = first; s ; s=s->texturechain)
PPL_GenerateArrays(s);
PPL_FlushArrays();
qglEnable(GL_TEXTURE_2D); //texturing? who wants texturing?!?!
return;
}
if (r_floorcolour.modified)
else
{
char *s;
r_floorcolour.modified = false;
if (r_wallcolour.modified)
{
char *s;
r_wallcolour.modified = false;
s = COM_Parse(r_floorcolour.string);
floorcolour[0] = atof(com_token);
s = COM_Parse(s);
floorcolour[1] = atof(com_token);
s = COM_Parse(s);
floorcolour[2] = atof(com_token);
s = COM_Parse(r_wallcolour.string);
wallcolour[0] = atof(com_token);
s = COM_Parse(s);
wallcolour[1] = atof(com_token);
s = COM_Parse(s);
wallcolour[2] = atof(com_token);
}
if (r_floorcolour.modified)
{
char *s;
r_floorcolour.modified = false;
s = COM_Parse(r_floorcolour.string);
floorcolour[0] = atof(com_token);
s = COM_Parse(s);
floorcolour[1] = atof(com_token);
s = COM_Parse(s);
floorcolour[2] = atof(com_token);
}
}
PPL_EnableVertexArrays();
@ -1349,7 +1391,7 @@ static void PPL_BaseChain_NPR_Sketch(msurface_t *first)
static void PPL_BaseTextureChain(msurface_t *first)
{
texture_t *t;
if (r_drawflat.value)
if (r_drawflat.value||!r_lightmapintensity)
{
if (r_drawflat.value == 2)
{
@ -1831,8 +1873,14 @@ void PPL_BaseEntTextures(void)
switch (currententity->model->type)
{
//FIXME: We want to depth sort with particles, but we also want depth. :(
//Until then, we have broken model lighting.
case mod_alias:
RQ_AddDistReorder(PPL_DrawEnt, currententity, NULL, currententity->origin);
// R_DrawGAliasModel (currententity);
if (currententity->flags & Q2RF_WEAPONMODEL)
RQ_AddDistReorder(PPL_DrawEnt, currententity, NULL, r_refdef.vieworg);
else
RQ_AddDistReorder(PPL_DrawEnt, currententity, NULL, currententity->origin);
break;
case mod_brush:
@ -1893,6 +1941,10 @@ PERMUTATION_GENERIC = 0,
PERMUTATION_BUMPMAP = 1,
PERMUTATION_SPECULAR = 2,
PERMUTATION_BUMP_SPEC = 3,
PERMUTATION_OFFSET = 4,
PERMUTATION_OFFSET_BUMP = 5,
PERMUTATION_OFFSET_SPEC = 6,
PERMUTATION_OFFSET_BUMP_SPEC = 7,
PERMUTATIONS
};
@ -1901,6 +1953,8 @@ int ppl_light_shader_eyeposition[PERMUTATIONS];
int ppl_light_shader_lightposition[PERMUTATIONS];
int ppl_light_shader_lightcolour[PERMUTATIONS];
int ppl_light_shader_lightradius[PERMUTATIONS];
int ppl_light_shader_offset_scale[PERMUTATIONS];
int ppl_light_shader_offset_bias[PERMUTATIONS];
void PPL_CreateLightTexturesProgram(void)
{
@ -1910,7 +1964,11 @@ void PPL_CreateLightTexturesProgram(void)
"",
"#define BUMP\n",
"#define SPECULAR\n",
"#define SPECULAR\n#define BUMP\n"
"#define SPECULAR\n#define BUMP\n",
"#define USEOFFSETMAPPING\n",
"#define USEOFFSETMAPPING\n#define BUMP\n",
"#define USEOFFSETMAPPING\n#define SPECULAR\n",
"#define USEOFFSETMAPPING\n#define SPECULAR\n#define BUMP\n"
};
char *vert =
"varying vec2 tcbase;\n"
@ -1918,7 +1976,7 @@ void PPL_CreateLightTexturesProgram(void)
"varying vec3 LightVector;\n"
"uniform vec3 LightPosition;\n"
"#ifdef SPECULAR\n"
"#if defined(SPECULAR) || defined(USEOFFSETMAPPING)\n"
"uniform vec3 EyePosition;\n"
"varying vec3 EyeVector;\n"
"#endif\n"
@ -1934,7 +1992,7 @@ void PPL_CreateLightTexturesProgram(void)
" LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
" LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
"#ifdef SPECULAR\n"
"#if defined(SPECULAR)||defined(USEOFFSETMAPPING)\n"
" vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;\n"
" EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n"
" EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n"
@ -1945,7 +2003,7 @@ void PPL_CreateLightTexturesProgram(void)
char *frag =
"uniform sampler2D baset;\n"
"#if defined(BUMP) || defined(SPECULAR)\n"
"#if defined(BUMP) || defined(SPECULAR) || defined(USEOFFSETMAPPING)\n"
"uniform sampler2D bumpt;\n"
"#endif\n"
"#ifdef SPECULAR\n"
@ -1958,13 +2016,28 @@ void PPL_CreateLightTexturesProgram(void)
"uniform float lightradius;\n"
"uniform vec3 LightColour;\n"
"#ifdef SPECULAR\n"
"#if defined(SPECULAR) || defined(USEOFFSETMAPPING)\n"
"varying vec3 EyeVector;\n"
"#endif\n"
"#ifdef USEOFFSETMAPPING\n"
"uniform float OffsetMapping_Scale;\n"
"uniform float OffsetMapping_Bias;\n"
"#endif\n"
"void main (void)\n"
"{\n"
"#ifdef USEOFFSETMAPPING\n"
" // this is 3 sample because of ATI Radeon 9500-9800/X300 limits\n"
" vec2 OffsetVector = normalize(EyeVector).xy * vec2(-0.333, 0.333);\n"
" vec2 TexCoordOffset = tcbase + OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(bumpt, tcbase).w);\n"
" TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(bumpt, TexCoordOffset).w);\n"
" TexCoordOffset += OffsetVector * (OffsetMapping_Bias + OffsetMapping_Scale * texture2D(bumpt, TexCoordOffset).w);\n"
"#define tcbase TexCoordOffset\n"
"#endif\n"
"#ifdef BUMP\n"
" vec3 bases = vec3(texture2D(baset, tcbase));\n"
"#else\n"
@ -2009,12 +2082,129 @@ void PPL_CreateLightTexturesProgram(void)
ppl_light_shader_lightposition [i]= qglGetUniformLocationARB(ppl_light_shader[i], "LightPosition");
ppl_light_shader_lightcolour[i] = qglGetUniformLocationARB(ppl_light_shader[i], "LightColour");
ppl_light_shader_lightradius[i] = qglGetUniformLocationARB(ppl_light_shader[i], "lightradius");
ppl_light_shader_offset_scale[i] = qglGetUniformLocationARB(ppl_light_shader[i], "OffsetMapping_Scale");
ppl_light_shader_offset_bias[i] = qglGetUniformLocationARB(ppl_light_shader[i], "OffsetMapping_Bias");
GLSlang_UseProgram(0);
}
}
};
void PPL_LightTexturesFP_Cached(model_t *model, vec3_t modelorigin, dlight_t *light, vec3_t colour)
{
int i, j;
texture_t *t;
msurface_t *s;
int p, lp=-1;
extern cvar_t gl_specular;
shadowmesh_t *shm = light->worldshadowmesh;
vec3_t relativelightorigin;
vec3_t relativeeyeorigin;
if (qglGetError())
Con_Printf("GL Error before lighttextures\n");
VectorSubtract(light->origin, modelorigin, relativelightorigin);
VectorSubtract(r_refdef.vieworg, modelorigin, relativeeyeorigin);
qglEnable(GL_BLEND);
GL_TexEnv(GL_MODULATE);
qglBlendFunc(GL_ONE, GL_ONE);
qglDisableClientState(GL_COLOR_ARRAY);
if (qglGetError())
Con_Printf("GL Error early in lighttextures\n");
for (j=0 ; j<shm->numsurftextures ; j++)
{
if (!shm->litsurfs[j].count)
continue;
s = shm->litsurfs[j].s[0];
t = s->texinfo->texture;
t = GLR_TextureAnimation (t);
for (i=0 ; i<shm->litsurfs[j].count ; i++)
{
s = shm->litsurfs[j].s[i];
if (s->visframe != r_framecount)
continue;
if (s->flags & SURF_PLANEBACK)
{//inverted normal.
if (DotProduct(s->plane->normal, relativelightorigin)-s->plane->dist > lightradius)
continue;
}
else
{
if (-DotProduct(s->plane->normal, relativelightorigin)+s->plane->dist > lightradius)
continue;
}
// if ((s->flags & SURF_DRAWTURB) && r_wateralphaval != 1.0)
// continue; // draw translucent water later
p = 0;
if (t->gl_texturenumbumpmap && ppl_light_shader[p|PERMUTATION_BUMPMAP])
p |= PERMUTATION_BUMPMAP;
if (gl_specular.value && t->gl_texturenumspec && ppl_light_shader[p|PERMUTATION_SPECULAR])
p |= PERMUTATION_SPECULAR;
if (r_shadow_glsl_offsetmapping.value && t->gl_texturenumbumpmap && ppl_light_shader[p|PERMUTATION_OFFSET])
p |= PERMUTATION_OFFSET;
if (p != lp)
{
lp = p;
GLSlang_UseProgram(ppl_light_shader[p]);
if (ppl_light_shader_eyeposition[p] != -1)
qglUniform3fvARB(ppl_light_shader_eyeposition[p], 1, relativeeyeorigin);
qglUniform3fvARB(ppl_light_shader_lightposition[p], 1, relativelightorigin);
qglUniform3fvARB(ppl_light_shader_lightcolour[p], 1, colour);
qglUniform1fARB(ppl_light_shader_lightradius[p], light->radius);
if (ppl_light_shader_offset_scale[p]!=-1)
qglUniform1fARB(ppl_light_shader_offset_scale[p], r_shadow_glsl_offsetmapping_scale.value);
if (ppl_light_shader_offset_bias[p]!=-1)
qglUniform1fARB(ppl_light_shader_offset_bias[p], r_shadow_glsl_offsetmapping_bias.value);
}
if (p & PERMUTATION_BUMPMAP)
GL_MBind(GL_TEXTURE1_ARB, t->gl_texturenumbumpmap);
if (p & PERMUTATION_SPECULAR)
GL_MBind(GL_TEXTURE2_ARB, t->gl_texturenumspec);
GL_MBind(GL_TEXTURE0_ARB, t->gl_texturenum);
qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
qglMultiTexCoord3fARB(GL_TEXTURE1_ARB, s->texinfo->vecs[0][0], s->texinfo->vecs[0][1], s->texinfo->vecs[0][2]);
qglMultiTexCoord3fARB(GL_TEXTURE2_ARB, -s->texinfo->vecs[1][0], -s->texinfo->vecs[1][1], -s->texinfo->vecs[1][2]);
if (s->flags & SURF_PLANEBACK)
qglMultiTexCoord3fARB(GL_TEXTURE3_ARB, -s->plane->normal[0], -s->plane->normal[1], -s->plane->normal[2]);
else
qglMultiTexCoord3fARB(GL_TEXTURE3_ARB, s->plane->normal[0], s->plane->normal[1], s->plane->normal[2]);
qglTexCoordPointer(2, GL_FLOAT, 0, s->mesh->st_array);
qglVertexPointer(3, GL_FLOAT, 0, s->mesh->xyz_array);
qglDrawElements(GL_TRIANGLES, s->mesh->numindexes, GL_UNSIGNED_INT, s->mesh->indexes);
}
}
GLSlang_UseProgram(0);
qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (qglGetError())
Con_Printf("GL Error during lighttextures\n");
}
void PPL_LightTexturesFP(model_t *model, vec3_t modelorigin, dlight_t *light, vec3_t colour)
{
int i;
@ -2128,7 +2318,10 @@ void PPL_LightTextures(model_t *model, vec3_t modelorigin, dlight_t *light, vec3
if (ppl_light_shader[0])
{
PPL_LightTexturesFP(model, modelorigin, light, colour);
if (model == cl.worldmodel && light->worldshadowmesh)
PPL_LightTexturesFP_Cached(model, modelorigin, light, colour);
else
PPL_LightTexturesFP(model, modelorigin, light, colour);
return;
}
@ -2934,6 +3127,27 @@ qboolean PPL_VisOverlaps(qbyte *v1, qbyte *v2)
}
return false;
}
qboolean PPL_LeafInView(qbyte *lightvis)
{
int i;
int m = (cl.worldmodel->numleafs+7)/8;
mleaf_t *wl = cl.worldmodel->leafs;
unsigned char lv;
for (i = 0; i < m; i++)
{
lv = lightvis[i];
if (lv&1 && wl[(i<<3)+0].visframe == r_visframecount) return true;
if (lv&2 && wl[(i<<3)+1].visframe == r_visframecount) return true;
if (lv&4 && wl[(i<<3)+2].visframe == r_visframecount) return true;
if (lv&8 && wl[(i<<3)+3].visframe == r_visframecount) return true;
if (lv&16 && wl[(i<<3)+4].visframe == r_visframecount) return true;
if (lv&32 && wl[(i<<3)+5].visframe == r_visframecount) return true;
if (lv&64 && wl[(i<<3)+6].visframe == r_visframecount) return true;
if (lv&128 && wl[(i<<3)+7].visframe == r_visframecount) return true;
}
return false;
}
void PPL_RecursiveWorldNode_r (mnode_t *node)
{
@ -2967,6 +3181,7 @@ void PPL_RecursiveWorldNode_r (mnode_t *node)
if (node->contents < 0)
{
pleaf = (mleaf_t *)node;
PPL_Shadow_Cache_Leaf(pleaf);
mark = pleaf->firstmarksurface;
c = pleaf->nummarksurfaces;
@ -3051,6 +3266,11 @@ void PPL_RecursiveWorldNode_r (mnode_t *node)
fabs(surf->center[2] - lightorg[2]) > lightradius+surf->radius)
continue;
*/
PPL_Shadow_Cache_Surface(surf);
#define PROJECTION_DISTANCE (float)(lightradius*2)//0x7fffffff
//build a list of the edges that are to be drawn.
@ -3470,14 +3690,6 @@ void PPL_RecursiveWorldNode (dlight_t *dl)
float *v1, *v2;
vec3_t v3, v4;
if (dl->worldshadowmesh)
{
qglEnableClientState(GL_VERTEX_ARRAY);
qglVertexPointer(3, GL_FLOAT, 0, dl->worldshadowmesh->verts);
qglDrawElements(GL_TRIANGLES, dl->worldshadowmesh->numindicies, GL_UNSIGNED_INT, dl->worldshadowmesh->indicies);
return;
}
lightradius = dl->radius;
lightorg[0] = dl->origin[0]+0.5;
@ -3488,6 +3700,17 @@ void PPL_RecursiveWorldNode (dlight_t *dl)
modelorg[1] = lightorg[1];
modelorg[2] = lightorg[2];
if (dl->worldshadowmesh)
{
qglEnableClientState(GL_VERTEX_ARRAY);
qglVertexPointer(3, GL_FLOAT, 0, dl->worldshadowmesh->verts);
qglDrawRangeElements(GL_TRIANGLES, 0, dl->worldshadowmesh->numverts, dl->worldshadowmesh->numindicies, GL_UNSIGNED_INT, dl->worldshadowmesh->indicies);
return;
}
PPL_BeginShadowMesh(dl);
qglEnableClientState(GL_VERTEX_ARRAY);
if (qglGetError())
@ -3579,6 +3802,8 @@ void PPL_RecursiveWorldNode (dlight_t *dl)
varray_vc=0;
firstedge=0;
PPL_FinishShadowMesh(dl);
}
void PPL_DrawBrushModelShadow(dlight_t *dl, entity_t *e)
@ -3591,7 +3816,7 @@ void PPL_DrawBrushModelShadow(dlight_t *dl, entity_t *e)
model_t *model;
msurface_t *surf;
RotateLightVector(e->angles, e->origin, dl->origin, lightorg);
RotateLightVector(e->axis, e->origin, dl->origin, lightorg);
qglPushMatrix();
R_RotateForEntity(e);
@ -3727,6 +3952,9 @@ void PPL_UpdateNodeShadowFrames(qbyte *lvis)
int i;
mnode_t *node;
if (!lvis) //using a cached light, we don't need shadowframes
return;
#ifdef Q3BSPS
@ -4025,7 +4253,7 @@ void CL_NewDlight (int key, float x, float y, float z, float radius, float time,
int type);
//generates stencil shadows of the world geometry.
//redraws world geometry
void PPL_AddLight(dlight_t *dl)
qboolean PPL_AddLight(dlight_t *dl)
{
int i;
int sdecrw;
@ -4069,24 +4297,45 @@ void PPL_AddLight(dlight_t *dl)
}
if (colour[0] < 0.1 && colour[1] < 0.1 && colour[2] < 0.1)
return; //just switch these off.
return false; //just switch these off.
if (PPL_ScissorForBox(mins, maxs))
return; //was culled.
return false; //was culled.
if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
i = cl.worldmodel->funcs.LeafForPoint(r_refdef.vieworg, cl.worldmodel);
if (dl->worldshadowmesh)
{
if (!PPL_LeafInView(dl->worldshadowmesh->litleaves))
return false;
/*
if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
i = cl.worldmodel->funcs.LeafForPoint(r_refdef.vieworg, cl.worldmodel);
else
i = r_viewleaf - cl.worldmodel->leafs;
vvis = cl.worldmodel->funcs.LeafPVS(i, cl.worldmodel, vvisb);
// if (!(lvis[i>>3] & (1<<(i&7)))) //light might not be visible, but it's effects probably should be.
// return;
if (!PPL_VisOverlaps(dl->worldshadowmesh->litleaves, vvis)) //The two viewing areas do not intersect.
return;
*/
lvis = NULL;
}
else
i = r_viewleaf - cl.worldmodel->leafs;
{
if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
i = cl.worldmodel->funcs.LeafForPoint(r_refdef.vieworg, cl.worldmodel);
else
i = r_viewleaf - cl.worldmodel->leafs;
leaf = cl.worldmodel->funcs.LeafForPoint(dl->origin, cl.worldmodel);
lvis = cl.worldmodel->funcs.LeafPVS(leaf, cl.worldmodel, lvisb);
vvis = cl.worldmodel->funcs.LeafPVS(i, cl.worldmodel, vvisb);
leaf = cl.worldmodel->funcs.LeafForPoint(dl->origin, cl.worldmodel);
lvis = cl.worldmodel->funcs.LeafPVS(leaf, cl.worldmodel, lvisb);
vvis = cl.worldmodel->funcs.LeafPVS(i, cl.worldmodel, vvisb);
// if (!(lvis[i>>3] & (1<<(i&7)))) //light might not be visible, but it's effects probably should be.
// return;
if (!PPL_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect.
return;
// if (!(lvis[i>>3] & (1<<(i&7)))) //light might not be visible, but it's effects probably should be.
// return;
if (!PPL_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect.
return false;
}
PPL_EnableVertexArrays();
@ -4147,7 +4396,7 @@ void PPL_AddLight(dlight_t *dl)
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, sincrw, GL_KEEP);
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, sdecrw, GL_KEEP);
PPL_UpdateNodeShadowFrames(lvisb);
PPL_UpdateNodeShadowFrames(lvis);
PPL_RecursiveWorldNode(dl);
PPL_DrawShadowMeshes(dl);
qglStencilOpSeparateATI(GL_FRONT_AND_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
@ -4172,7 +4421,7 @@ void PPL_AddLight(dlight_t *dl)
qglStencilOp(GL_KEEP, sdecrw, GL_KEEP);
qglStencilFunc( GL_ALWAYS, 1, ~0 );
PPL_UpdateNodeShadowFrames(lvisb);
PPL_UpdateNodeShadowFrames(lvis);
PPL_RecursiveWorldNode(dl);
PPL_DrawShadowMeshes(dl);
@ -4218,10 +4467,39 @@ void PPL_AddLight(dlight_t *dl)
qglEnable(GL_DEPTH_TEST);
qglDepthMask(0);
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
qglCullFace(GL_FRONT);
#if 0 //draw the stencil stuff to the red channel
/* {
#pragma comment(lib, "opengl32.lib");
static char buffer[1024*1024*8];
glReadPixels(0, 0, vid.width, vid.height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buffer);
glDrawPixels(vid.width, vid.height, GL_GREEN, GL_UNSIGNED_BYTE, buffer);
}
*/
qglMatrixMode(GL_PROJECTION);
qglPushMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPushMatrix();
GL_Set2D();
qglColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
qglStencilFunc( GL_GREATER, 1, ~0 );
Draw_ConsoleBackground(480);
qglColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
qglStencilFunc( GL_LESS, 1, ~0 );
Draw_ConsoleBackground(480);
qglMatrixMode(GL_PROJECTION);
qglPopMatrix();
qglMatrixMode(GL_MODELVIEW);
qglPopMatrix();
#endif
qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
}
qglColor3f(1,1,1);
@ -4244,6 +4522,8 @@ void PPL_AddLight(dlight_t *dl)
qglStencilFunc( GL_ALWAYS, 0, ~0 );
qglDisable(GL_SCISSOR_TEST);
return true;
}
#endif
@ -4259,10 +4539,17 @@ void PPL_DrawWorld (void)
float furthest;
#endif
int i;
int numlights;
vec3_t mins, maxs;
int maxshadowlights = gl_maxshadowlights.value;
if (!r_shadow_realtime_world.value)
r_lightmapintensity = 1;
else
r_lightmapintensity = r_shadow_realtime_world_lightmaps.value;
/*
if (!lightmap)
{
@ -4298,6 +4585,7 @@ void PPL_DrawWorld (void)
// Con_Printf("GL Error on entities\n");
#ifdef PPL
numlights = 0;
RSpeedRemark();
if (r_shadows.value && qglStencilFunc && gl_canstencil)
{
@ -4325,11 +4613,11 @@ void PPL_DrawWorld (void)
maxs[2] = l->origin[2] + l->radius;
if (R_CullBox(mins, maxs))
continue;
// if (R_CullSphere(l->origin, l->radius*1.1))
// continue;
if (R_CullSphere(l->origin, l->radius))
continue;
#if 1
if (!maxshadowlights--)
if (maxshadowlights-- <= 0)
continue;
#else
VectorSubtract(l->origin, r_refdef.vieworg, mins)
@ -4371,7 +4659,8 @@ void PPL_DrawWorld (void)
l->color[2]*=10;
}
TRACE(("dbg: calling PPL_AddLight\n"));
PPL_AddLight(l);
if (PPL_AddLight(l))
numlights++;
if(!l->isstatic)
{
l->color[0]/=10;
@ -4387,6 +4676,7 @@ void PPL_DrawWorld (void)
}
RSpeedEnd(RSPEED_STENCILSHADOWS);
#endif
// Con_Printf("%i lights\n", numlights);
// if (qglGetError())
// Con_Printf("GL Error on shadow lighting\n");
@ -4428,4 +4718,268 @@ void PPL_CreateShaderObjects(void)
PPL_LoadSpecularFragmentProgram();
}
#endif
void PPL_FlushShadowMesh(dlight_t *dl)
{
int tn;
shadowmesh_t *sm;
sm = dl->worldshadowmesh;
if (sm)
{
dl->worldshadowmesh = NULL;
for (tn = 0; tn < sm->numsurftextures; tn++)
if (sm->litsurfs[tn].count)
BZ_Free(sm->litsurfs);
BZ_Free(sm->indicies);
BZ_Free(sm->verts);
BZ_Free(sm);
}
}
//okay, so this is a bit of a hack...
qboolean buildingmesh;
void (APIENTRY *realBegin) (GLenum);
void (APIENTRY *realEnd) (void);
void (APIENTRY *realVertex3f) (GLfloat x, GLfloat y, GLfloat z);
void (APIENTRY *realVertex3fv) (const GLfloat *v);
void (APIENTRY *realVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void (APIENTRY *realDrawArrays) (GLenum mode, GLint first, GLsizei count);
void (APIENTRY *realDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
#define inc 128
int sh_type;
int sh_index[64*64];
int sh_vertnum; //vertex number (set to 0 at SH_Begin)
int sh_maxverts;
int sh_numverts; //total emitted
int sh_maxindicies;
int sh_numindicies;
float *sh_vertexpointer;
int sh_vpstride;
shadowmesh_t *sh_shmesh;
void APIENTRY SH_Begin (GLenum e)
{
sh_type = e;
}
void APIENTRY SH_End (void)
{
int i;
int v1, v2;
switch(sh_type)
{
case GL_POLYGON:
i = (sh_numindicies+(sh_vertnum-2)*3+inc+5)&~(inc-1); //and a bit of padding
if (sh_maxindicies != i)
{
sh_maxindicies = i;
sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, i * sizeof(*sh_shmesh->indicies));
}
//decompose the poly into a triangle fan.
v1 = sh_index[0];
v2 = sh_index[1];
for (i = 2; i < sh_vertnum; i++)
{
sh_shmesh->indicies[sh_numindicies++] = v1;
sh_shmesh->indicies[sh_numindicies++] = v2;
sh_shmesh->indicies[sh_numindicies++] = v2 = sh_index[i];
}
sh_vertnum = 0;
break;
case GL_TRIANGLES:
i = (sh_numindicies+(sh_vertnum)+inc+5)&~(inc-1); //and a bit of padding
if (sh_maxindicies != i)
{
sh_maxindicies = i;
sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, i * sizeof(*sh_shmesh->indicies));
}
//add the extra triangles
for (i = 0; i < sh_vertnum; i+=3)
{
sh_shmesh->indicies[sh_numindicies++] = sh_index[i+0];
sh_shmesh->indicies[sh_numindicies++] = sh_index[i+1];
sh_shmesh->indicies[sh_numindicies++] = sh_index[i+2];
}
sh_vertnum = 0;
break;
case GL_QUADS:
i = (sh_numindicies+(sh_vertnum/4)*6+inc+5)&~(inc-1); //and a bit of padding
if (sh_maxindicies != i)
{
sh_maxindicies = i;
sh_shmesh->indicies = BZ_Realloc(sh_shmesh->indicies, i * sizeof(*sh_shmesh->indicies));
}
//add the extra triangles
for (i = 0; i < sh_vertnum; i+=4)
{
sh_shmesh->indicies[sh_numindicies++] = sh_index[i+0];
sh_shmesh->indicies[sh_numindicies++] = sh_index[i+1];
sh_shmesh->indicies[sh_numindicies++] = sh_index[i+2];
sh_shmesh->indicies[sh_numindicies++] = sh_index[i+0];
sh_shmesh->indicies[sh_numindicies++] = sh_index[i+2];
sh_shmesh->indicies[sh_numindicies++] = sh_index[i+3];
}
sh_vertnum = 0;
break;
default:
if (sh_vertnum)
Sys_Error("SH_End: verticies were left");
}
}
void APIENTRY SH_Vertex3f (GLfloat x, GLfloat y, GLfloat z)
{
int i;
if (sh_vertnum > sizeof(sh_index)/sizeof(sh_index[0]))
Sys_Error("SH_End: too many verticies");
//add the verts as we go
i = (sh_numverts+inc+5)&~(inc-1); //and a bit of padding
if (sh_maxverts != i)
{
sh_maxverts = i;
sh_shmesh->verts = BZ_Realloc(sh_shmesh->verts, i * sizeof(*sh_shmesh->verts));
}
sh_shmesh->verts[sh_numverts][0] = x;
sh_shmesh->verts[sh_numverts][1] = y;
sh_shmesh->verts[sh_numverts][2] = z;
sh_index[sh_vertnum] = sh_numverts;
sh_vertnum++;
sh_numverts++;
switch(sh_type)
{
case GL_POLYGON:
break;
case GL_TRIANGLES:
if (sh_vertnum == 3)
SH_End();
break;
case GL_QUADS:
if (sh_vertnum == 4)
SH_End();
break;
default:
Sys_Error("SH_Vertex3f: bad type");
}
}
void APIENTRY SH_Vertex3fv (const GLfloat *v)
{
SH_Vertex3f(v[0], v[1], v[2]);
}
void APIENTRY SH_VertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
{
sh_vertexpointer = pointer;
sh_vpstride = stride/4;
if (!sh_vpstride)
sh_vpstride = 3;
}
void APIENTRY SH_DrawArrays (GLenum mode, GLint first, GLsizei count)
{
int i;
SH_Begin(mode);
count+=first;
for (i = first; i < count; i++)
SH_Vertex3fv(sh_vertexpointer + i*sh_vpstride);
SH_End();
}
void APIENTRY SH_DrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
{
int i;
SH_Begin(mode);
for (i = 0; i < count; i++)
SH_Vertex3fv(sh_vertexpointer + (((int*)indices)[i])*sh_vpstride);
SH_End();
}
void PPL_Shadow_Cache_Surface(msurface_t *surf)
{
int i;
if (!buildingmesh)
return;
for (i = 0; i < cl.worldmodel->numtextures; i++)
if (surf->texinfo->texture == cl.worldmodel->textures[i])
break;
sh_shmesh->litsurfs[i].s = BZ_Realloc(sh_shmesh->litsurfs[i].s, sizeof(void*)*(sh_shmesh->litsurfs[i].count+1));
sh_shmesh->litsurfs[i].s[sh_shmesh->litsurfs[i].count] = surf;
sh_shmesh->litsurfs[i].count++;
}
void PPL_Shadow_Cache_Leaf(mleaf_t *leaf)
{
int i;
if (!buildingmesh)
return;
i = leaf - cl.worldmodel->leafs;
sh_shmesh->litleaves[i>>3] = 1<<(i&7);
}
void PPL_BeginShadowMesh(dlight_t *dl)
{
PPL_FlushShadowMesh(dl);
if (buildingmesh)
return;
if (!dl->isstatic)
return;
sh_maxverts = 0;
sh_numverts = 0;
sh_vertnum = 0;
sh_maxindicies = 0;
sh_numindicies = 0;
buildingmesh = true;
realBegin = qglBegin;
realEnd = qglEnd;
realVertex3f = qglVertex3f;
realVertex3fv = qglVertex3fv;
realVertexPointer = qglVertexPointer;
realDrawArrays = qglDrawArrays;
realDrawElements = qglDrawElements;
qglBegin = SH_Begin;
qglEnd = SH_End;
qglVertex3f = SH_Vertex3f;
qglVertex3fv = SH_Vertex3fv;
qglVertexPointer = SH_VertexPointer;
qglDrawArrays = SH_DrawArrays;
qglDrawElements = SH_DrawElements;
sh_shmesh = Z_Malloc(sizeof(*sh_shmesh) + (cl.worldmodel->numleafs+7)/8);
sh_shmesh->litsurfs = Z_Malloc(sizeof(shadowmeshsurfs_t)*cl.worldmodel->numtextures);
sh_shmesh->numsurftextures=cl.worldmodel->numtextures;
sh_shmesh->litleaves = (unsigned char*)(sh_shmesh+1);
}
void PPL_FinishShadowMesh(dlight_t *dl)
{
int i;
if (!buildingmesh)
return;
qglBegin = realBegin;
qglEnd = realEnd;
qglVertex3f = realVertex3f;
qglVertex3fv = realVertex3fv;
qglVertexPointer = realVertexPointer;
qglDrawArrays = realDrawArrays;
qglDrawElements = realDrawElements;
buildingmesh = false;
dl->worldshadowmesh = sh_shmesh;
sh_shmesh->numindicies = sh_numindicies;
sh_shmesh->numverts = sh_numverts;
sh_shmesh = NULL;
}
#endif //ifdef GLQUAKE

View File

@ -222,6 +222,9 @@ void GLSCR_UpdateScreen (void)
Media_RecordFrame();
#endif
GLR_BrightenScreen();
if (key_dest == key_console)
Con_DrawConsole(vid_conheight.value/2, false);
GL_EndRendering ();
GL_DoSwap();
RSpeedEnd(RSPEED_TOTALREFRESH);

View File

@ -1828,7 +1828,7 @@ void Shader_DefaultSkin(char *shortname, shader_t *s)
{
shaderpass_t *pass;
pass = &s->passes[0];
pass->flags = SHADER_PASS_BLEND|SHADER_PASS_DEPTHWRITE;
pass->flags = SHADER_PASS_DEPTHWRITE;
pass->anim_frames[0] = Mod_LoadHiResTexture(shortname, NULL, true, true, true);//GL_FindImage (shortname, 0);
pass->depthfunc = GL_LEQUAL;
pass->rgbgen = RGB_GEN_LIGHTING_DIFFUSE;
@ -1847,7 +1847,7 @@ void Shader_DefaultSkin(char *shortname, shader_t *s)
s->numpasses = 1;
s->numdeforms = 0;
s->flags = SHADER_BLEND|SHADER_DEPTHWRITE|SHADER_CULL_FRONT;
s->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT;
s->features = MF_STCOORDS|MF_NORMALS;
s->sort = SHADER_SORT_OPAQUE;
s->registration_sequence = 1;//fizme: registration_sequence;
@ -2027,7 +2027,11 @@ shader_t *R_RegisterSkin (char *name)
}
shader_t *R_RegisterCustom (char *name, void(*defaultgen)(char *name, shader_t*))
{
return &r_shaders[R_LoadShader (name, defaultgen)];
int i;
i = R_LoadShader (name, defaultgen);
if (i < 0)
return NULL;
return &r_shaders[i];
}
#endif

View File

@ -843,18 +843,25 @@ void GL_DoSwap (void)
// handle the mouse state when windowed if that's changed
if (modestate == MS_WINDOWED)
{
if (!_windowed_mouse.value) {
if (windowed_mouse) {
if (!_windowed_mouse.value)
{
if (windowed_mouse)
{
IN_DeactivateMouse ();
IN_ShowMouse ();
windowed_mouse = false;
}
} else {
}
else
{
windowed_mouse = true;
if ((key_dest == key_game||mouseusedforgui) && !mouseactive && ActiveApp) {
if ((key_dest == key_game||mouseusedforgui) && !mouseactive && ActiveApp)
{
IN_ActivateMouse ();
IN_HideMouse ();
} else if (mouseactive && !(key_dest == key_game || mouseusedforgui)) {
}
else if (mouseactive && key_dest == key_console)
{//!(key_dest == key_game || mouseusedforgui)) {
IN_DeactivateMouse ();
IN_ShowMouse ();
}

View File

@ -114,7 +114,7 @@ void GL_Upload8 (qbyte *data, int width, int height, qboolean mipmap, qboolean
void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qboolean alpha);
#endif
int GL_LoadTexture (char *identifier, int width, int height, qbyte *data, qboolean mipmap, qboolean alpha);
int GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, qboolean mipmap);
int GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, qboolean mipmap, float bumpscale);
int GL_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, qboolean mipmap, qboolean alpha);
int GL_LoadTexture32 (char *identifier, int width, int height, unsigned *data, qboolean mipmap, qboolean alpha);
int GL_LoadCompressed(char *name);
@ -347,7 +347,7 @@ typedef struct {
//gl_ppl.c
void PPL_DrawWorld (void);
void RotateLightVector(vec3_t angles, vec3_t origin, vec3_t lightpoint, vec3_t result);
void RotateLightVector(vec3_t *angles, vec3_t origin, vec3_t lightpoint, vec3_t result);
#endif

View File

@ -82,7 +82,7 @@ pbool CompileParams(progfuncs_t *progfuncs, int doall, int nump, char **parms)
if (!externs->useeditor)
printf("Error in %s on line %i\n", errorfile, errorline);
else
externs->useeditor(errorfile, errorline, nump, parms);
externs->useeditor(progfuncs, errorfile, errorline, nump, parms);
}
return false;
}
@ -108,7 +108,7 @@ int Comp_Begin(progfuncs_t *progfuncs, int nump, char **parms)
{
PostCompile();
if (*errorfile)
externs->useeditor(errorfile, errorline, nump, parms);
externs->useeditor(progfuncs, errorfile, errorline, nump, parms);
return false;
}
@ -125,7 +125,7 @@ int Comp_Continue(progfuncs_t *progfuncs)
{
PostCompile();
if (*errorfile)
externs->useeditor(errorfile, errorline, comp_nump, comp_parms);
externs->useeditor(progfuncs, errorfile, errorline, comp_nump, comp_parms);
return false;
}
@ -136,7 +136,7 @@ int Comp_Continue(progfuncs_t *progfuncs)
PostCompile();
if (*errorfile)
externs->useeditor(errorfile, errorline, comp_nump, comp_parms);
externs->useeditor(progfuncs, errorfile, errorline, comp_nump, comp_parms);
return false;
}

View File

@ -654,12 +654,12 @@ reeval:
//array/structure reading/riting.
case OP_GLOBALADDRESS:
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int/4);
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
break;
case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors)
OPC->_int = OPA->_int + OPB->_int*4;
break;
case OP_LOADA_I:
case OP_LOADA_F:
case OP_LOADA_FLD:

View File

@ -654,12 +654,12 @@ reeval:
//array/structure reading/riting.
case OP_GLOBALADDRESS:
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int/4);
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
break;
case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors)
OPC->_int = OPA->_int + OPB->_int*4;
break;
case OP_LOADA_I:
case OP_LOADA_F:
case OP_LOADA_FLD:

View File

@ -654,12 +654,12 @@ reeval:
//array/structure reading/riting.
case OP_GLOBALADDRESS:
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int/4);
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
break;
case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors)
OPC->_int = OPA->_int + OPB->_int*4;
break;
case OP_LOADA_I:
case OP_LOADA_F:
case OP_LOADA_FLD:

View File

@ -654,12 +654,12 @@ reeval:
//array/structure reading/riting.
case OP_GLOBALADDRESS:
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int/4);
OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int);
break;
case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors)
OPC->_int = OPA->_int + OPB->_int*4;
break;
case OP_LOADA_I:
case OP_LOADA_F:
case OP_LOADA_FLD:

View File

@ -321,6 +321,8 @@ eval_t *GetEdictFieldValue(progfuncs_t *progfuncs, struct edict_s *ed, char *nam
struct edict_s *ProgsToEdict (progfuncs_t *progfuncs, int progs)
{
if ((unsigned)progs >= maxedicts)
progs = 0;
return (struct edict_s *)PROG_TO_EDICT(progfuncs, progs);
}
int EdictToProgs (progfuncs_t *progfuncs, struct edict_s *ed)

View File

@ -730,7 +730,7 @@ static char *lastfile = 0;
lastline = pr_progstate[pn].linenums[statement];
lastfile = f->s_file+progfuncs->stringtable;
lastline = externs->useeditor(lastfile, lastline, 0, NULL);
lastline = externs->useeditor(progfuncs, lastfile, lastline, 0, NULL);
if (pr_progstate[pn].linenums[statement] != lastline)
{
@ -750,7 +750,7 @@ static char *lastfile = 0;
else if (f) //annoying.
{
if (externs->useeditor)
externs->useeditor(f->s_file+progfuncs->stringtable, -1, 0, NULL);
externs->useeditor(progfuncs, f->s_file+progfuncs->stringtable, -1, 0, NULL);
return statement;
}

View File

@ -166,7 +166,7 @@ typedef struct progexterns_s {
struct edict_s **sv_edicts; //pointer to the engine's reference to world.
int *sv_num_edicts; //pointer to the engine's edict count.
int (*useeditor) (char *filename, int line, int nump, char **parms); //called on syntax errors or step-by-step debugging.
int (*useeditor) (progfuncs_t *prinst, char *filename, int line, int nump, char **parms); //called on syntax errors or step-by-step debugging.
} progparms_t, progexterns_t;
void QC_AddSharedVar(progfuncs_t *progfuncs, int start, int size);

View File

@ -44,7 +44,7 @@ cvar_t saved4 = {"saved4", "0", NULL, CVAR_ARCHIVE};
cvar_t temp1 = {"temp1", "0", NULL, CVAR_ARCHIVE};
cvar_t noexit = {"noexit", "0", NULL};
cvar_t pr_maxedicts = {"pr_maxedicts", "2000", NULL, CVAR_LATCH};
cvar_t pr_maxedicts = {"pr_maxedicts", "2048", NULL, CVAR_LATCH};
cvar_t pr_imitatemvdsv = {"pr_imitatemvdsv", "0", NULL, CVAR_LATCH};
cvar_t pr_fixbrokenqccarrays = {"pr_fixbrokenqccarrays", "1", NULL, CVAR_LATCH};
@ -291,13 +291,13 @@ void VARGS PR_CB_Free(void *mem)
BZ_Free(mem);
}
void PF_break (progfuncs_t *prinst, struct globalvars_s *pr_globals);
int QCLibEditor(char *filename, int line, int nump, char **parms);
int QCEditor (char *filename, int line, int nump, char **parms)
int QCLibEditor(progfuncs_t *prinst, char *filename, int line, int nump, char **parms);
int QCEditor (progfuncs_t *prinst, char *filename, int line, int nump, char **parms)
{
#ifdef TEXTEDITOR
static char oldfuncname[64];
if (!parms)
return QCLibEditor(filename, line, nump, parms);
return QCLibEditor(prinst, filename, line, nump, parms);
else
{
if (!nump && !strncmp(oldfuncname, *parms, sizeof(oldfuncname)))
@ -1211,6 +1211,8 @@ void Q_InitProgs(void)
}
sv.max_edicts = pr_maxedicts.value;
if (sv.max_edicts > MAX_EDICTS)
sv.max_edicts = MAX_EDICTS;
pr_edict_size = PR_InitEnts(svprogfuncs, sv.max_edicts);
}
@ -5326,7 +5328,7 @@ void PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_globals)
if (start < 0)
start = strlen(s)-start;
if (length < 0)
length = strlen(s)-start;
length = strlen(s)-start+(length+1);
if (start >= strlen(s) || length<=0 || !*s)
{
@ -9466,9 +9468,6 @@ void PR_RegisterFields(void) //it's just easier to do it this way.
fieldfloat(fatness);
fieldentity(view2);
fieldvector(movement);
PR_RegisterFieldVar(svprogfuncs, ev_float, "buttonforward", (int)&((entvars_t*)0)->movement[0], -1);
PR_RegisterFieldVar(svprogfuncs, ev_float, "buttonright", (int)&((entvars_t*)0)->movement[1], -1);
PR_RegisterFieldVar(svprogfuncs, ev_float, "buttonup", (int)&((entvars_t*)0)->movement[2], -1);
fieldfloat(fteflags);
fieldfloat(vweapmodelindex);
@ -9478,6 +9477,8 @@ void PR_RegisterFields(void) //it's just easier to do it this way.
fieldentity(viewmodelforclient);
fieldentity(exteriormodeltoclient);
fieldfloat(viewzoom);
fieldentity(tag_entity);
fieldfloat(tag_index);

View File

@ -185,6 +185,8 @@ typedef struct entvars_s
int viewmodelforclient;
int exteriormodeltoclient;
float viewzoom;
int tag_entity;
float tag_index;

View File

@ -551,6 +551,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
svs.clients[i].num_backbuf = 0;
svs.clients[i].datagram.cursize = 0;
}
svs.clients[i].csqcactive = false;
}
if (sv_bigcoords.value)

View File

@ -148,7 +148,7 @@ cvar_t watervis = {"watervis", "" , NULL, CVAR_SERVERINFO};
cvar_t rearview = {"rearview", "" , NULL, CVAR_SERVERINFO};
cvar_t allow_luma = {"allow_luma", "1", NULL, CVAR_SERVERINFO};
cvar_t allow_bump = {"allow_bump", "1", NULL, CVAR_SERVERINFO};
cvar_t allow_skybox = {"allow_skybox", "1", NULL, CVAR_SERVERINFO};
cvar_t allow_skybox = {"allow_skybox", "", NULL, CVAR_SERVERINFO};
cvar_t sv_allow_splitscreen = {"allow_splitscreen", "",NULL,CVAR_SERVERINFO};
cvar_t fbskins = {"fbskins", "0", NULL, CVAR_SERVERINFO}; //to get rid of lame fuhquake fbskins
cvar_t mirrors = {"mirrors", "" , NULL, CVAR_SERVERINFO};
@ -1103,7 +1103,7 @@ qboolean SV_ChallengePasses(int challenge)
return false;
}
void SV_RejectMessage(int protocol, char *format, ...)
void VARGS SV_RejectMessage(int protocol, char *format, ...)
{
va_list argptr;
char string[8192];
@ -2047,6 +2047,10 @@ qboolean SV_ConnectionlessPacket (void)
return true;
}
}
else if (!strcmp(c,"\xad\xad\xad\xad""getchallenge"))
{
SVC_GetChallenge ();
}
else if (!strcmp(c,"getchallenge"))
{
SVC_GetChallenge ();

View File

@ -1689,15 +1689,13 @@ void SV_MVD_Record_f (void)
_snprintf (name, MAX_OSPATH+MAX_MVD_NAME, "%s/%s/%s", com_gamedir, sv_demoDir.string, newname);
Sys_mkdir(va("%s/%s", com_gamedir, sv_demoDir.string));
//
// open the demo file
//
COM_StripExtension(name, name);
COM_DefaultExtension(name, ".mvd");
COM_CreatePath(name);
//
// open the demo file and start recording
//
SV_MVD_Record (SV_InitRecordFile(name));
}

View File

@ -547,7 +547,8 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
switch (client->protocol)
{
case SCP_BAD:
break;
continue; //a bot.
#ifdef NQPROT
case SCP_NETQUAKE:
case SCP_DARKPLACES6:
@ -663,23 +664,45 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
}
inrange:
#ifdef NQPROT
if (!ISQWCLIENT(client))
switch (client->protocol)
{
if (reliable) {
case SCP_BAD:
continue; //a bot.
#ifdef NQPROT
case SCP_NETQUAKE:
case SCP_DARKPLACES6:
case SCP_DARKPLACES7: //extra prediction stuff
if (reliable)
{
ClientReliableCheckBlock(client, sv.nqmulticast.cursize);
ClientReliableWrite_SZ(client, sv.nqmulticast.data, sv.nqmulticast.cursize);
} else
}
else
SZ_Write (&client->datagram, sv.nqmulticast.data, sv.nqmulticast.cursize);
}
else
#endif
{
if (reliable) {
break;
#endif
#ifdef Q2SERVER
case SCP_QUAKE2:
if (reliable)
{
ClientReliableCheckBlock(client, sv.q2multicast.cursize);
ClientReliableWrite_SZ(client, sv.q2multicast.data, sv.q2multicast.cursize);
}
else
SZ_Write (&client->datagram, sv.q2multicast.data, sv.q2multicast.cursize);
break;
#endif
case SCP_QUAKEWORLD:
if (reliable)
{
ClientReliableCheckBlock(client, sv.multicast.cursize);
ClientReliableWrite_SZ(client, sv.multicast.data, sv.multicast.cursize);
} else
}
else
SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize);
break;
}
}
}
@ -1220,7 +1243,11 @@ void SV_UpdateClientStats (client_t *client, int pnum)
stats[STAT_ROCKETS] = ent->v->ammo_rockets;
stats[STAT_CELLS] = ent->v->ammo_cells;
if (!client->spectator)
{
stats[STAT_ACTIVEWEAPON] = ent->v->weapon;
if (client->csqcactive)
stats[STAT_WEAPONFRAME] = ent->v->weaponframe;
}
// stuff the sigil bits into the high bits of items for sbar
if (pr_items2)
@ -1236,7 +1263,10 @@ void SV_UpdateClientStats (client_t *client, int pnum)
stats[STAT_VIEW2] = 0;
#endif
stats[STAT_VIEWZOOM] = 255;
if (!ent->v->viewzoom)
stats[STAT_VIEWZOOM] = 255;
else
stats[STAT_VIEWZOOM] = ent->v->viewzoom*255;
SV_UpdateQCStats(ent, stats);

View File

@ -1089,34 +1089,31 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max
trace_t SVQ2_ClipMoveToEntity (q2edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
{
trace_t trace;
/*
vec3_t offset;
vec3_t start_l, end_l;
hull_t *hull;
// fill in a default trace
memset (&trace, 0, sizeof(trace_t));
trace.fraction = 1;
trace.allsolid = true;
VectorCopy (end, trace.endpos);
model_t *model;
// get the clipping hull
hull = SVQ2_HullForEntity (ent, mins, maxs, offset);
VectorSubtract (start, offset, start_l);
VectorSubtract (end, offset, end_l);
if (ent->s.solid == Q2SOLID_BSP)
{
model = sv.models[(int)ent->s.modelindex];
if (!model || model->type != mod_brush)
SV_Error("SOLID_BSP with non bsp model");
}
else
{
vec3_t boxmins, boxmaxs;
VectorSubtract (ent->mins, maxs, boxmins);
VectorSubtract (ent->maxs, mins, boxmaxs);
SV_HullForBox(boxmins, boxmaxs);
model = NULL;
}
// trace a line through the apropriate clipping hull
TransformedTrace(ent->s.modelindex, start_l, end_l, &trace, ent->s.angles);
// fix trace up by the offset
if (trace.fraction != 1)
VectorAdd (trace.endpos, offset, trace.endpos);
TransformedTrace(model, 0, 0, start, end, mins, maxs, &trace, ent->s.origin, ent->s.angles);
// did we clip the move?
if (trace.fraction < 1 || trace.startsolid )
trace.ent = (edict_t *)ent;
*/
return trace;
}
#endif