added con_textsize to resize console separately from everything else.

qcc: added support for variable arguments via the va_arg intrinsic.
qcc: fix up some comment/whitespace issues with the preprocessor.
random hacks to try to improve dp compatibility a little.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4573 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-12-29 22:48:28 +00:00
parent d7cdc39ccd
commit bfe545222e
75 changed files with 2053 additions and 825 deletions

View file

@ -1624,6 +1624,19 @@ void CL_RotateAroundTag(entity_t *ent, int entnum, int parenttagent, int parentt
model = ps->modelindex;
CL_LerpNetFrameState(FS_REG, &fstate, &cl.lerpents[parenttagent]);
/*inherit certain properties from the parent entity*/
if (ps->dpflags & RENDER_VIEWMODEL)
ent->flags |= Q2RF_WEAPONMODEL|Q2RF_MINLIGHT|Q2RF_DEPTHHACK;
if ((ps->dpflags & RENDER_EXTERIORMODEL) || r_refdef.playerview->viewentity == ps->number)
ent->flags |= Q2RF_EXTERNALMODEL;
if (ent->playerindex == -1 && ps->colormap > 0 && ps->colormap <= cl.allocated_client_slots)
{
ent->playerindex = ps->colormap-1;
ent->topcolour = cl.players[ent->playerindex].ttopcolor;
ent->bottomcolour = cl.players[ent->playerindex].tbottomcolor;
}
}
else
{

View file

@ -696,14 +696,17 @@ void CL_ClampPitch (int pnum)
vang[PITCH] *= -1;
/*edit it*/
if (vang[PITCH] < -180)
vang[PITCH] += cl.playerview[pnum].viewanglechange[PITCH];
vang[YAW] += cl.playerview[pnum].viewanglechange[YAW];
if (vang[PITCH] <= -180)
vang[PITCH] += 360;
if (vang[PITCH] > 180)
vang[PITCH] -= 360;
if (vang[ROLL] > 180)
if (vang[ROLL] >= 180)
vang[ROLL] -= 360;
vang[PITCH] += cl.playerview[pnum].viewanglechange[PITCH];
vang[YAW] += cl.playerview[pnum].viewanglechange[YAW];
if (vang[ROLL] < -180)
vang[ROLL] += 360;
/*keep the player looking relative to their ground (smoothlyish)*/
if (!vang[ROLL])
{
@ -715,10 +718,16 @@ void CL_ClampPitch (int pnum)
if (fabs(vang[ROLL]) < host_frametime*180)
vang[ROLL] = 0;
else if (vang[ROLL] > 0)
{
Con_Printf("Roll %f\n", vang[ROLL]);
vang[ROLL] -= host_frametime*180;
}
else
{
Con_Printf("Roll %f\n", vang[ROLL]);
vang[ROLL] += host_frametime*180;
}
}
VectorClear(cl.playerview[pnum].viewanglechange);
/*clamp pitch*/
if (vang[PITCH] > cl.maxpitch)
@ -737,6 +746,10 @@ void CL_ClampPitch (int pnum)
VectorAngles(view[0], view[2], cl.playerview[pnum].viewangles);
cl.playerview[pnum].viewangles[PITCH] *= -1;
if (cl.playerview[pnum].viewangles[ROLL] >= 360)
cl.playerview[pnum].viewangles[ROLL] -= 360;
if (cl.playerview[pnum].viewangles[ROLL] < 0)
cl.playerview[pnum].viewangles[ROLL] += 360;
if (cl.playerview[pnum].viewangles[PITCH] < -180)
cl.playerview[pnum].viewangles[PITCH] += 360;
return;

View file

@ -5877,13 +5877,13 @@ void CLQW_ParseServerMessage (void)
case svcfte_cgamepacket:
csqcpacket = true;
#ifdef HLCLIENT
if (CLHL_ParseGamePacket())
break;
#endif
#ifdef CSQC_DAT
if (CSQC_ParseGamePacket())
break;
#endif
#ifdef HLCLIENT
if (CLHL_ParseGamePacket())
break;
#endif
Con_Printf("Unable to parse gamecode packet\n");
break;

View file

@ -261,9 +261,9 @@ qintptr_t VARGS Plug_Draw_Character(void *offset, quintptr_t mask, const qintptr
int x, y;
if (qrenderer == QR_NONE)
return 0;
Font_BeginString(font_conchar, arg[0], arg[1], &x, &y);
Font_BeginString(font_default, arg[0], arg[1], &x, &y);
Font_DrawChar(x, y, CON_WHITEMASK | 0xe000 | (unsigned int)arg[2]);
Font_EndString(font_conchar);
Font_EndString(font_default);
return 0;
}
qintptr_t VARGS Plug_Draw_String(void *offset, quintptr_t mask, const qintptr_t *arg)
@ -274,7 +274,7 @@ qintptr_t VARGS Plug_Draw_String(void *offset, quintptr_t mask, const qintptr_t
return 0;
COM_ParseFunString(CON_WHITEMASK, VM_POINTER(arg[2]), buffer, sizeof(buffer), false);
str = buffer;
Font_BeginString(font_conchar, VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), &px, &py);
Font_BeginString(font_default, VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), &px, &py);
ipx = px;
while(*str)
{
@ -286,7 +286,7 @@ qintptr_t VARGS Plug_Draw_String(void *offset, quintptr_t mask, const qintptr_t
px = Font_DrawChar(px, py, *str);
str++;
}
Font_EndString(font_conchar);
Font_EndString(font_default);
return 0;
}

View file

@ -580,7 +580,7 @@ void SCR_CheckDrawCenterString (void)
continue;
SCR_VRectForPlayer(&rect, pnum);
SCR_DrawCenterString(&rect, p, font_conchar);
SCR_DrawCenterString(&rect, p, font_default);
}
}
@ -599,13 +599,26 @@ void R_DrawTextField(int x, int y, int w, int h, char *text, unsigned int defaul
p.time_off = scr_centertime.value;
p.time_start = cl.time;
SCR_DrawCenterString(&r, &p, font_conchar);
SCR_DrawCenterString(&r, &p, font_default);
}
void SCR_DrawCursor(int prydoncursornum)
{
extern cvar_t cl_cursor, cl_cursorbias, cl_cursorsize;
mpic_t *p;
if (key_dest_absolutemouse & kdm_game)
{
//if the game is meant to be drawing a cursor, don't draw one over the top.
key_dest_absolutemouse &= ~kdm_game;
if (!Key_MouseShouldBeFree())
{ //unless something else wants a cursor too.
key_dest_absolutemouse |= kdm_game;
return;
}
key_dest_absolutemouse |= kdm_game;
}
if (!*cl_cursor.string || prydoncursornum>1)
p = R2D_SafeCachePic(va("gfx/prydoncursor%03i.lmp", prydoncursornum));
else
@ -620,11 +633,11 @@ void SCR_DrawCursor(int prydoncursornum)
else
{
float x, y;
Font_BeginScaledString(font_conchar, mousecursor_x, mousecursor_y, 8, 8, &x, &y);
Font_BeginScaledString(font_default, mousecursor_x, mousecursor_y, 8, 8, &x, &y);
x -= Font_CharWidth('+' | 0xe000 | CON_WHITEMASK)/2;
y -= Font_CharHeight()/2;
Font_DrawScaleChar(x, y, '+' | 0xe000 | CON_WHITEMASK);
Font_EndString(font_conchar);
Font_EndString(font_default);
}
}
static void SCR_DrawSimMTouchCursor(void)
@ -635,11 +648,11 @@ static void SCR_DrawSimMTouchCursor(void)
{
if (multicursor_active[i])
{
Font_BeginScaledString(font_conchar, multicursor_x[i], multicursor_y[i], 8, 8, &x, &y);
Font_BeginScaledString(font_default, multicursor_x[i], multicursor_y[i], 8, 8, &x, &y);
x -= Font_CharWidth('+' | 0xe000 | CON_WHITEMASK)/2;
y -= Font_CharHeight()/2;
Font_DrawScaleChar(x, y, '+' | 0xe000 | CON_WHITEMASK);
Font_EndString(font_conchar);
Font_EndString(font_default);
}
}
}
@ -1090,7 +1103,7 @@ void SCR_StringXY(char *str, float x, float y)
char *s2;
int px, py;
Font_BeginString(font_conchar, ((x<0)?vid.width:x), ((y<0)?vid.height - sb_lines:y), &px, &py);
Font_BeginString(font_default, ((x<0)?vid.width:x), ((y<0)?vid.height - sb_lines:y), &px, &py);
if (x < 0)
{
@ -1103,7 +1116,7 @@ void SCR_StringXY(char *str, float x, float y)
while (*str)
px = Font_DrawChar(px, py, CON_WHITEMASK|*str++);
Font_EndString(font_conchar);
Font_EndString(font_default);
}
void SCR_DrawFPS (void)

View file

@ -1603,7 +1603,7 @@ void CL_ParseTEnt (void)
gravity = MSG_ReadByte (); //gravity flag
jitter = MSG_ReadCoord(); //jitter
P_RunParticleCube(pos, pos2, dir, cnt, colour, gravity, jitter);
P_RunParticleCube(P_INVALID, pos, pos2, dir, dir, cnt, colour, gravity, jitter);
}
break;
case TEDP_PARTICLERAIN:

View file

@ -21,9 +21,14 @@ struct hlcvar_s *QDECL GHL_CVarGetPointer(char *varname);
//I hope you're c99 and have a __func__
#endif
extern cvar_t temp1;
#define ignore(s) Con_Printf("Fixme: " s "\n")
#define notimpl(l) Con_Printf("halflife cl builtin not implemented on line %i\n", l)
#define notimpf(f) Con_Printf("halflife cl builtin %s not implemented\n", f)
#define notimp() Con_Printf("halflife cl builtin %s not implemented\n", __func__)
#define bi_begin() if (temp1.ival)Con_Printf("enter %s\n", __func__)
#define bi_end() if (temp1.ival)Con_Printf("leave %s\n", __func__)
#define bi_trace() bi_begin(); bi_end()
#if HLCLIENT >= 1
#define HLCL_API_VERSION HLCLIENT
@ -34,21 +39,28 @@ struct hlcvar_s *QDECL GHL_CVarGetPointer(char *varname);
void *vgui_panel;
void *(QDECL *vgui_init)(void);
void (QDECL *vgui_frame)(void);
void (QDECL *vgui_key)(int down, int scan);
void (QDECL *vgui_mouse)(int x, int y);
qboolean VGui_Setup(void)
{
void *vguidll;
int (QDECL *init)(void);
dllfunction_t funcs[] =
{
{(void*)&init, "init"},
{(void*)&vgui_init, "init"},
{(void*)&vgui_frame, "frame"},
{(void*)&vgui_key, "key"},
{(void*)&vgui_mouse, "mouse"},
{NULL}
};
vguidll = Sys_LoadLibrary("vguiwrap", funcs);
if (vguidll)
vgui_panel = init();
vgui_panel = vgui_init();
return !!vgui_panel;
}
@ -89,17 +101,17 @@ typedef struct
{
short lerpmsecs;
qbyte msec;
//pad1
vec3_t viewangles;
float forwardmove;
float sidemove;
float upmove;
qbyte lightlevel;
//pad1
unsigned short buttons;
qbyte impulse;
qbyte weaponselect;
//pad2
int impact_index;
vec3_t impact_position;
} hlusercmd_t;
@ -120,6 +132,7 @@ typedef struct
qbyte isus;
qbyte isspec;
qbyte pl;
//pad3
char *model;
short tcolour;
short bcolour;
@ -372,11 +385,16 @@ int hl_viewmodelsequencebody;
HLPIC QDECL CLGHL_pic_load (char *picname)
{
return Mod_ForName(picname, false);
void *ret;
bi_begin();
ret = Mod_ForName(picname, false);
bi_end();
return ret;
// return R2D_SafeCachePic(picname);
}
int QDECL CLGHL_pic_getnumframes (HLPIC pic)
{
bi_trace();
if (pic)
return pic->numframes;
else
@ -387,9 +405,10 @@ static mspriteframe_t *getspriteframe(HLPIC pic, int frame)
{
msprite_t *psprite;
mspritegroup_t *pgroup;
bi_trace();
if (!pic)
return NULL;
psprite = pic->cache.data;
psprite = pic->meshinfo;
if (!psprite)
return NULL;
@ -404,6 +423,7 @@ static mspriteframe_t *getspriteframe(HLPIC pic, int frame)
static mpic_t *getspritepic(HLPIC pic, int frame)
{
mspriteframe_t *f;
bi_trace();
f = getspriteframe(pic, frame);
if (f)
return f->shader;
@ -413,6 +433,7 @@ static mpic_t *getspritepic(HLPIC pic, int frame)
int QDECL CLGHL_pic_getheight (HLPIC pic, int frame)
{
mspriteframe_t *pframe;
bi_trace();
pframe = getspriteframe(pic, frame);
if (!pframe)
@ -423,6 +444,7 @@ int QDECL CLGHL_pic_getheight (HLPIC pic, int frame)
int QDECL CLGHL_pic_getwidth (HLPIC pic, int frame)
{
mspriteframe_t *pframe;
bi_trace();
pframe = getspriteframe(pic, frame);
if (!pframe)
@ -432,12 +454,14 @@ int QDECL CLGHL_pic_getwidth (HLPIC pic, int frame)
}
void QDECL CLGHL_pic_select (HLPIC pic, int r, int g, int b)
{
bi_trace();
selectedpic = pic;
R2D_ImageColours(r/255.0f, g/255.0f, b/255.0f, 1);
}
void QDECL CLGHL_pic_drawcuropaque (int frame, int x, int y, hlsubrect_t *loc)
{
mpic_t *pic = getspritepic(selectedpic, frame);
bi_trace();
if (!pic)
return;
@ -453,6 +477,7 @@ void QDECL CLGHL_pic_drawcuropaque (int frame, int x, int y, hlsubrect_t *loc)
void QDECL CLGHL_pic_drawcuralphtest (int frame, int x, int y, hlsubrect_t *loc)
{
mpic_t *pic = getspritepic(selectedpic, frame);
bi_trace();
if (!pic)
return;
//use some kind of alpha
@ -467,6 +492,8 @@ void QDECL CLGHL_pic_drawcuralphtest (int frame, int x, int y, hlsubrect_t *loc)
void QDECL CLGHL_pic_drawcuradditive (int frame, int x, int y, hlsubrect_t *loc)
{
mpic_t *pic = getspritepic(selectedpic, frame);
bi_trace();
if (!pic)
return;
@ -494,9 +521,23 @@ void QDECL CLGHL_pic_drawcuradditive (int frame, int x, int y, hlsubrect_t *loc)
}
void QDECL CLGHL_pic_enablescissor (int x, int y, int width, int height)
{
srect_t srect;
bi_trace();
srect.x = x / vid.width;
srect.y = y / vid.height;
srect.width = width / vid.width;
srect.height = height / vid.height;
srect.dmin = -99999;
srect.dmax = 99999;
srect.y = (1-srect.y) - srect.height;
BE_Scissor(&srect);
}
void QDECL CLGHL_pic_disablescissor (void)
{
bi_trace();
BE_Scissor(NULL);
}
hlspriteinf_t *QDECL CLGHL_pic_parsepiclist (char *filename, int *numparsed)
{
@ -506,6 +547,8 @@ hlspriteinf_t *QDECL CLGHL_pic_parsepiclist (char *filename, int *numparsed)
void *file;
char *pos;
bi_trace();
*numparsed = 0;
FS_LoadFile(filename, &file);
@ -556,10 +599,12 @@ hlspriteinf_t *QDECL CLGHL_pic_parsepiclist (char *filename, int *numparsed)
void QDECL CLGHL_fillrgba (int x, int y, int width, int height, int r, int g, int b, int a)
{
bi_trace();
}
int QDECL CLGHL_getscreeninfo (hlscreeninfo_t *info)
{
int i;
bi_trace();
if (info->size != sizeof(*info))
return false;
@ -574,10 +619,12 @@ int QDECL CLGHL_getscreeninfo (hlscreeninfo_t *info)
}
void QDECL CLGHL_setcrosshair (HLPIC pic, hlsubrect_t rect, int r, int g, int b)
{
bi_trace();
}
struct hlcvar_s *QDECL CLGHL_cvar_register (char *name, char *defvalue, int flags)
{
bi_trace();
if (Cvar_Get(name, defvalue, 0, "Halflife cvars"))
return GHL_CVarGetPointer(name);
else
@ -586,6 +633,7 @@ struct hlcvar_s *QDECL CLGHL_cvar_register (char *name, char *defvalue, int flag
float QDECL CLGHL_cvar_getfloat (char *name)
{
cvar_t *var = Cvar_FindVar(name);
bi_trace();
if (var)
return var->value;
return 0;
@ -593,6 +641,7 @@ float QDECL CLGHL_cvar_getfloat (char *name)
char *QDECL CLGHL_cvar_getstring (char *name)
{
cvar_t *var = Cvar_FindVar(name);
bi_trace();
if (var)
return var->string;
return "";
@ -600,11 +649,13 @@ char *QDECL CLGHL_cvar_getstring (char *name)
void QDECL CLGHL_cmd_register (char *name, xcommand_t func)
{
bi_trace();
Cmd_AddCommand(name, func);
}
void QDECL CLGHL_hooknetmsg (char *msgname, void *func)
{
int i;
bi_trace();
//update the current list now.
for (i = 0; i < sizeof(usermsgs)/sizeof(usermsgs[0]); i++)
{
@ -631,16 +682,19 @@ void QDECL CLGHL_hooknetmsg (char *msgname, void *func)
}
void QDECL CLGHL_forwardcmd (char *command)
{
bi_trace();
CL_SendClientCommand(true, "%s", command);
}
void QDECL CLGHL_localcmd (char *command)
{
bi_trace();
Cbuf_AddText(command, RESTRICT_SERVER);
}
void QDECL CLGHL_getplayerinfo (int entnum, hlplayerinfo_t *result)
{
player_info_t *player;
bi_trace();
entnum--;
if (entnum < 0 || entnum >= MAX_CLIENTS)
return;
@ -662,6 +716,7 @@ void QDECL CLGHL_getplayerinfo (int entnum, hlplayerinfo_t *result)
void QDECL CLGHL_startsound_name (char *name, float vol)
{
sfx_t *sfx = S_PrecacheSound (name);
bi_trace();
if (!sfx)
{
Con_Printf ("CLGHL_startsound_name: can't cache %s\n", name);
@ -672,6 +727,7 @@ void QDECL CLGHL_startsound_name (char *name, float vol)
void QDECL CLGHL_startsound_idx (int idx, float vol)
{
sfx_t *sfx = cl.sound_precache[idx];
bi_trace();
if (!sfx)
{
Con_Printf ("CLGHL_startsound_name: index not precached %s\n", name);
@ -682,68 +738,80 @@ void QDECL CLGHL_startsound_idx (int idx, float vol)
void QDECL CLGHL_anglevectors (float *ina, float *outf, float *outr, float *outu)
{
bi_trace();
AngleVectors(ina, outf, outr, outu);
}
hlmsginfo_t *QDECL CLGHL_get_message_info (char *name)
{
//fixme: add parser
//fixme: add parser for titles.txt
hlmsginfo_t *ret;
bi_trace();
ret = Z_Malloc(sizeof(*ret));
memset(ret, 0, sizeof(*ret));
ret->name = name;
ret->message = name;
ret->x = 0;
ret->y = 0;
ret->x = -1;
ret->y = -1;
*(int*)&ret->c1 = 0xffffffff;
*(int*)&ret->c2 = 0xffffffff;
ret->effect = 0;
ret->fadein = 0;
ret->fadeout = 0;
ret->fadein = 1;
ret->fadeout = 1.5;
ret->fxtime = 0;
ret->holdtime = 1000;
ret->holdtime = 3;
return ret;
}
int QDECL CLGHL_drawchar (int x, int y, int charnum, int r, int g, int b)
{
bi_trace();
return 0;
}
int QDECL CLGHL_drawstring (int x, int y, char *string)
{
bi_trace();
return 0;
}
void QDECL CLGHL_settextcolour(float r, float g, float b)
{
bi_trace();
}
void QDECL CLGHL_drawstring_getlen (char *string, int *outlen, int *outheight)
{
bi_trace();
*outlen = strlen(string)*8;
*outheight = 8;
}
void QDECL CLGHL_consoleprint (char *str)
{
bi_trace();
Con_Printf("%s", str);
}
void QDECL CLGHL_centerprint (char *str)
{
bi_trace();
SCR_CenterPrint(0, str, true);
}
int QDECL CLGHL_getwindowcenterx(void)
{
bi_trace();
return window_center_x;
}
int QDECL CLGHL_getwindowcentery(void)
{
bi_trace();
return window_center_y;
}
void QDECL CLGHL_getviewnangles(float*ang)
{
bi_trace();
VectorCopy(cl.playerview[0].viewangles, ang);
}
void QDECL CLGHL_setviewnangles(float*ang)
{
bi_trace();
VectorCopy(ang, cl.playerview[0].viewangles);
}
void QDECL CLGHL_getmaxclients(float*ang){notimpf(__func__);}
@ -751,25 +819,29 @@ void QDECL CLGHL_cvar_setvalue(char *cvarname, char *value){notimpf(__func__);}
int QDECL CLGHL_cmd_argc(void)
{
bi_trace();
return Cmd_Argc();
}
char *QDECL CLGHL_cmd_argv(int i)
{
bi_trace();
return Cmd_Argv(i);
}
#define CLGHL_con_printf Con_Printf//void CLGHL_con_printf(char *fmt, ...){notimp(__LINE__);}
#define CLGHL_con_dprintf Con_DPrintf//void CLGHL_con_dprintf(char *fmt, ...){notimp(__LINE__);}
#define CLGHL_con_printf Con_Printf
#define CLGHL_con_dprintf Con_DPrintf
void QDECL CLGHL_con_notificationprintf(int pos, char *fmt, ...){notimpf(__func__);}
void QDECL CLGHL_con_notificationprintfex(void *info, char *fmt, ...){notimpf(__func__);}
char *QDECL CLGHL_physkey(char *key){notimpf(__func__);return NULL;}
char *QDECL CLGHL_serverkey(char *key){notimpf(__func__);return NULL;}
float QDECL CLGHL_getclientmaxspeed(void)
{
bi_trace();
return 320;
}
int QDECL CLGHL_checkparm(char *str, const char **next)
{
int i;
bi_trace();
i = COM_CheckParm(str);
if (next)
{
@ -782,6 +854,7 @@ int QDECL CLGHL_checkparm(char *str, const char **next)
}
int QDECL CLGHL_keyevent(int key, int down)
{
bi_trace();
if (key >= 241 && key <= 241+5)
Key_Event(0, K_MOUSE1+key-241, 0, down);
else
@ -789,11 +862,18 @@ int QDECL CLGHL_keyevent(int key, int down)
return true; //fixme: check the return type
}
void QDECL CLGHL_getmousepos(int *outx, int *outy){notimpf(__func__);}
int QDECL CLGHL_movetypeisnoclip(void){notimpf(__func__);return 0;}
int QDECL CLGHL_movetypeisnoclip(void)
{
bi_trace();
if (cl.playerview[0].pmovetype == PM_SPECTATOR)
return true;
return false;
}
struct hlclent_s *QDECL CLGHL_getlocalplayer(void){notimpf(__func__);return NULL;}
struct hlclent_s *QDECL CLGHL_getviewent(void){notimpf(__func__);return NULL;}
struct hlclent_s *QDECL CLGHL_getentidx(int idx)
{
bi_trace();
notimpf(__func__);return NULL;
}
float QDECL CLGHL_getlocaltime(void){return cl.time;}
@ -813,6 +893,7 @@ unsigned short QDECL CLGHL_precacheevent(int evtype, char *name){notimpf(__func_
void QDECL CLGHL_playevent(int flags, struct hledict_s *ent, unsigned short evindex, float delay, float *origin, float *angles, float f1, float f2, int i1, int i2, int b1, int b2){notimpf(__func__);}
void QDECL CLGHL_weaponanimate(int newsequence, int body)
{
bi_trace();
hl_viewmodelsequencetime = cl.time;
hl_viewmodelsequencecur = newsequence;
hl_viewmodelsequencebody = body;
@ -821,28 +902,34 @@ float QDECL CLGHL_randfloat(float minv, float maxv){notimpf(__func__);return min
long QDECL CLGHL_randlong(long minv, long maxv){notimpf(__func__);return minv;}
void QDECL CLGHL_hookevent(char *name, void (*func)(struct hlevent_s *event))
{
bi_trace();
Con_Printf("CLGHL_hookevent: not implemented. %s\n", name);
// notimpf(__func__);
}
int QDECL CLGHL_con_isshown(void)
{
bi_trace();
return scr_con_current > 0;
}
char *QDECL CLGHL_getgamedir(void)
{
extern char gamedirfile[];
bi_trace();
return gamedirfile;
}
struct hlcvar_s *QDECL CLGHL_cvar_find(char *name)
{
bi_trace();
return GHL_CVarGetPointer(name);
}
char *QDECL CLGHL_lookupbinding(char *command)
{
bi_trace();
return NULL;
}
char *QDECL CLGHL_getlevelname(void)
{
bi_trace();
if (!cl.worldmodel)
return "";
return cl.worldmodel->name;
@ -851,10 +938,12 @@ void QDECL CLGHL_getscreenfade(struct hlsfade_s *fade){notimpf(__func__);}
void QDECL CLGHL_setscreenfade(struct hlsfade_s *fade){notimpf(__func__);}
void *QDECL CLGHL_vgui_getpanel(void)
{
bi_trace();
return vgui_panel;
}
void QDECL CLGHL_vgui_paintback(int extents[4])
{
bi_trace();
notimpf(__func__);
}
@ -862,6 +951,7 @@ void *QDECL CLGHL_loadfile(char *path, int alloctype, int *length)
{
void *ptr = NULL;
int flen = -1;
bi_trace();
if (alloctype == 5)
{
flen = FS_LoadFile(path, &ptr);
@ -876,10 +966,12 @@ void *QDECL CLGHL_loadfile(char *path, int alloctype, int *length)
}
char *QDECL CLGHL_parsefile(char *data, char *token)
{
bi_trace();
return COM_ParseOut(data, token, 1024);
}
void QDECL CLGHL_freefile(void *file)
{
bi_trace();
//only valid for alloc type 5
FS_FreeFile(file);
}
@ -887,10 +979,12 @@ void QDECL CLGHL_freefile(void *file)
int QDECL CLGHL_forcedspectator(void)
{
bi_trace();
return cls.demoplayback;
}
model_t *QDECL CLGHL_loadmapsprite(char *name)
{
bi_trace();
notimpf(__func__);return NULL;
}
@ -906,12 +1000,14 @@ int QDECL CLGHL_playerfromtracker(int tracker){notimpf(__func__);return 0;}
int QDECL CLGHL_sendcmd_unreliable(char *cmd){notimpf(__func__);return 0;}
void QDECL CLGHL_getsysmousepos(long *xandy)
{
bi_trace();
#ifdef _WIN32
GetCursorPos((LPPOINT)xandy);
#endif
}
void QDECL CLGHL_setsysmousepos(int x, int y)
{
bi_trace();
#ifdef _WIN32
SetCursorPos(x, y);
#endif
@ -919,6 +1015,7 @@ void QDECL CLGHL_setsysmousepos(int x, int y)
void QDECL CLGHL_setmouseenable(qboolean enable)
{
extern cvar_t _windowed_mouse;
bi_trace();
Cvar_Set(&_windowed_mouse, enable?"1":"0");
}
@ -927,18 +1024,22 @@ void QDECL CLGHL_setmouseenable(qboolean enable)
#if HLCL_API_VERSION >= 7
int QDECL CLGHL_demo_isrecording(void)
{
bi_trace();
return cls.demorecording;
}
int QDECL CLGHL_demo_isplaying(void)
{
bi_trace();
return cls.demoplayback;
}
int QDECL CLGHL_demo_istimedemo(void)
{
bi_trace();
return cls.timedemo;
}
void QDECL CLGHL_demo_writedata(int size, void *data)
{
bi_trace();
notimpf(__func__);
}
@ -1153,7 +1254,8 @@ void CLHL_UnloadClientGame(void)
void CLHL_LoadClientGame(void)
{
char fullname[MAX_OSPATH];
char *path;
char path[MAX_OSPATH];
void *iterator;
int (QDECL *initfunc)(CLHL_enginecgamefuncs_t *funcs, int version);
dllfunction_t funcs[] =
@ -1166,20 +1268,15 @@ void CLHL_LoadClientGame(void)
memset(&CLHL_cgamefuncs, 0, sizeof(CLHL_cgamefuncs));
clg = NULL;//Sys_LoadLibrary("C:/Incoming/d/Half-Life/sdks/hlsdk-2.3-p3/hlsdk-2.3-p3/multiplayer/cl_dll/Debug/client", funcs);
if (!clg)
clg = NULL;
iterator = NULL;
while(COM_IteratePaths(&iterator, path, sizeof(path)))
{
path = NULL;
while((path = COM_NextPath (path)))
{
if (!path)
return; // couldn't find one anywhere
snprintf (fullname, sizeof(fullname), "%s/%s", path, "cl_dlls/client");
snprintf (fullname, sizeof(fullname), "%s%s", path, "cl_dlls/client");
clg = Sys_LoadLibrary(fullname, funcs);
if (clg)
break;
}
}
if (!clg)
return;
@ -1244,6 +1341,7 @@ int CLHL_DrawHud(void)
{
extern kbutton_t in_attack;
hllocalclientdata_t state;
int ret;
if (!clg || !CLHL_cgamefuncs.HUD_Redraw)
return false;
@ -1263,11 +1361,12 @@ int CLHL_DrawHud(void)
state.weapons = cl.playerview[0].stats[STAT_ITEMS];
state.fov = 90;
V_StopPitchDrift(0);
V_StopPitchDrift(&cl.playerview[0]);
CLHL_cgamefuncs.HUD_UpdateClientData(&state, cl.time);
return CLHL_cgamefuncs.HUD_Redraw(cl.time, cl.intermission);
ret = CLHL_cgamefuncs.HUD_Redraw(cl.time, cl.intermission);
return ret;
}
int CLHL_AnimateViewEntity(entity_t *ent)

View file

@ -1144,6 +1144,7 @@ qboolean CSQC_UnconnectedInit(void);
qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checksum);
qboolean CSQC_ConsoleLink(char *text, char *info);
void CSQC_RegisterCvarsAndThings(void);
qboolean CSQC_SetupToRenderPortal(int entnum);
qboolean CSQC_DrawView(void);
void CSQC_Shutdown(void);
qboolean CSQC_StuffCmd(int lplayernum, char *cmd, char *cmdend);

View file

@ -67,6 +67,7 @@ cvar_t con_notifytime_chat = CVAR("con_notifytime_chat", "8");
cvar_t con_separatechat = CVAR("con_separatechat", "0");
cvar_t con_timestamps = CVAR("con_timestamps", "0");
cvar_t con_timeformat = CVAR("con_timeformat", "(%H:%M:%S) ");
cvar_t con_textsize = CVARD("con_textsize", "8", "Resize the console text to be a different height, scaled separately from the hud. The value is the height in (virtual) pixels.");
#define NUM_CON_TIMES 24
@ -588,6 +589,7 @@ void Con_Init (void)
Cvar_Register (&con_separatechat, "Console controls");
Cvar_Register (&con_timestamps, "Console controls");
Cvar_Register (&con_timeformat, "Console controls");
Cvar_Register (&con_textsize, "Console controls");
Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
Cmd_AddCommand ("messagemode", Con_MessageMode_f);
@ -1183,7 +1185,7 @@ void Con_DrawNotifyOne (console_t *con)
int maxlines;
float t;
Font_BeginString(font_conchar, x, y, &x, &y);
Font_BeginString(font_console, x, y, &x, &y);
Font_Transform(con->notif_w, 0, &w, NULL);
if (con->notif_l < 0)
@ -1250,7 +1252,7 @@ void Con_DrawNotifyOne (console_t *con)
lines++;
}
Font_EndString(font_conchar);
Font_EndString(font_console);
}
void Con_DrawNotify (void)
@ -1286,7 +1288,7 @@ void Con_DrawNotify (void)
conchar_t *c, *end;
char *foo = va(chat_team?"say_team: %s":"say: %s", chat_buffer?chat_buffer:"");
int lines, i, pos;
Font_BeginString(font_conchar, 0, 0, &x, &y);
Font_BeginString(font_console, 0, 0, &x, &y);
y = con_main.notif_l * Font_CharHeight();
i = chat_team?10:5;
@ -1315,7 +1317,7 @@ void Con_DrawNotify (void)
Font_LineDraw(x, y, starts[i], ends[i]);
y += Font_CharHeight();
}
Font_EndString(font_conchar);
Font_EndString(font_console);
}
}
@ -1510,8 +1512,8 @@ int Con_DrawAlternateConsoles(int lines)
if (lines == (int)scr_conlines && consshown > 1)
{
int mx, my, h;
Font_BeginString(font_conchar, mousecursor_x, mousecursor_y, &mx, &my);
Font_BeginString(font_conchar, 0, y, &x, &y);
Font_BeginString(font_console, mousecursor_x, mousecursor_y, &mx, &my);
Font_BeginString(font_console, 0, y, &x, &y);
h = Font_CharHeight();
for (x = 0, con = &con_main; con; con = con->next)
{
@ -1525,7 +1527,7 @@ int Con_DrawAlternateConsoles(int lines)
lx = 0;
for (lx = x, start = buffer; start < end; start++)
{
lx = Font_CharEndCoord(font_conchar, lx, *start);
lx = Font_CharEndCoord(font_console, lx, *start);
}
if (lx > Font_ScreenWidth())
{
@ -1535,7 +1537,7 @@ int Con_DrawAlternateConsoles(int lines)
for (lx = x, start = buffer; start < end; start++)
{
Font_DrawChar(lx, y, *start);
lx = Font_CharEndCoord(font_conchar, lx, *start);
lx = Font_CharEndCoord(font_console, lx, *start);
}
lx += 8;
if (mx >= x && mx < lx && my >= y && my < y+h)
@ -1543,7 +1545,7 @@ int Con_DrawAlternateConsoles(int lines)
x = lx;
}
y+= h;
Font_EndString(font_conchar);
Font_EndString(font_console);
y = (y*(int)vid.height) / (float)vid.rotpixelheight;
}
@ -1838,9 +1840,9 @@ void Con_DrawConsole (int lines, qboolean noback)
con_current->selendline = NULL;
selactive = Key_GetConsoleSelectionBox(con_current, &selsx, &selsy, &selex, &seley);
Font_BeginString(font_conchar, x, y, &x, &y);
Font_BeginString(font_conchar, selsx, selsy, &selsx, &selsy);
Font_BeginString(font_conchar, selex, seley, &selex, &seley);
Font_BeginString(font_console, x, y, &x, &y);
Font_BeginString(font_console, selsx, selsy, &selsx, &selsy);
Font_BeginString(font_console, selex, seley, &selex, &seley);
ex = Font_ScreenWidth();
sx = x;
ex -= sx;
@ -1857,7 +1859,7 @@ void Con_DrawConsole (int lines, qboolean noback)
{
char *version = version_string();
int i;
Font_BeginString(font_conchar, vid.width, lines, &x, &y);
Font_BeginString(font_console, vid.width, lines, &x, &y);
y -= Font_CharHeight();
for (i = 0; version[i]; i++)
x -= Font_CharWidth(version[i] | CON_WHITEMASK|CON_HALFALPHA);
@ -1865,7 +1867,7 @@ void Con_DrawConsole (int lines, qboolean noback)
x = Font_DrawChar(x, y, version[i] | CON_WHITEMASK|CON_HALFALPHA);
}
Font_EndString(font_conchar);
Font_EndString(font_console);
if (con_current->selstartline)
{
@ -1904,17 +1906,17 @@ void Con_DrawConsole (int lines, qboolean noback)
//FIXME: support line breaks.
conchar_t buffer[2048], *starts[8], *ends[8];
int lines, i, px, py;
Font_BeginString(font_conchar, x, y, &px, &py);
Font_BeginString(font_console, x, y, &px, &py);
lines = Font_LineBreaks(buffer, COM_ParseFunString(CON_WHITEMASK|CON_NONCLEARBG, key, buffer, sizeof(buffer), false), 256, 8, starts, ends);
ih = max(Font_CharHeight()*lines, ih)/2;
y += ih - (Font_CharHeight()*lines)/2;
Font_BeginString(font_conchar, x, y, &px, &py);
Font_BeginString(font_console, x, y, &px, &py);
for (i = 0; i < lines; i++)
{
Font_LineDraw(px, py, starts[i], ends[i]);
py += Font_CharHeight();
}
Font_EndString(font_conchar);
Font_EndString(font_console);
}
}
}

View file

@ -141,6 +141,7 @@ keyname_t keynames[] =
{"KP_PLUS", K_KP_PLUS},
{"KP_NUMLOCK", K_KP_NUMLOCK},
{"KP_STAR", K_KP_STAR},
{"KP_MULTIPLY", K_KP_STAR},
{"KP_EQUALS", K_KP_EQUALS},
//fuhquake compatible.
@ -1568,6 +1569,7 @@ void Key_Unbind_f (void)
b = Key_StringToKeynum (Cmd_Argv(1), &modifier);
if (b==-1)
{
if (cl_warncmd.ival)
Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
return;
}
@ -1605,6 +1607,7 @@ void Key_Bind_f (void)
b = Key_StringToKeynum (Cmd_Argv(1), &modifier);
if (b==-1)
{
if (cl_warncmd.ival)
Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
return;
}
@ -1652,6 +1655,7 @@ void Key_BindLevel_f (void)
b = Key_StringToKeynum (Cmd_Argv(1), &modifier);
if (b==-1)
{
if (cl_warncmd.ival)
Con_Printf ("\"%s\" isn't a valid key\n", Cmd_Argv(1));
return;
}

View file

@ -198,7 +198,7 @@ extern qboolean chat_team;
void Key_Event (int devid, int key, unsigned int unicode, qboolean down);
void Key_Init (void);
void Key_WriteBindings (vfsfile_t *f);
void Key_WriteBindings (struct vfsfile_s *f);
void Key_SetBinding (int keynum, int modifier, char *binding, int cmdlevel);
void Key_ClearStates (void);
void Key_Unbindall_f (void); //aka: Key_Shutdown

View file

@ -483,14 +483,14 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
range = 1;
option->slider.vx = x;
x -= 8;
Font_BeginString(font_conchar, x, y, &x, &y);
Font_BeginString(font_default, x, y, &x, &y);
x = Font_DrawChar(x, y, 0xe080 | CON_WHITEMASK);
s = x;
for (i=0 ; i<SLIDER_RANGE ; i++)
x = Font_DrawChar(x, y, 0xe081 | CON_WHITEMASK);
Font_DrawChar(x, y, 0xe082 | CON_WHITEMASK);
Font_DrawChar(s + (x-s) * range - Font_CharWidth(0xe083 | CON_WHITEMASK)/2, y, 0xe083 | CON_WHITEMASK);
Font_EndString(font_conchar);
Font_EndString(font_default);
}
break;
case mt_checkbox:

View file

@ -149,6 +149,7 @@ void M_Menu_SinglePlayer_f (void)
MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_game");
//quake2 uses the 'newgame' alias.
menu->selecteditem = (menuoption_t*)
MC_AddConsoleCommand (menu, 64, 40, "Easy", "closemenu; skill 0;deathmatch 0; coop 0;newgame\n");
MC_AddConsoleCommand (menu, 64, 48, "Medium", "closemenu; skill 1;deathmatch 0; coop 0;newgame\n");
@ -264,6 +265,7 @@ void M_Menu_SinglePlayer_f (void)
else
{
MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title1.lmp");
//startmap selection in hexen2 is nasty.
if (havemp)
{
menu->selecteditem = (menuoption_t*)
@ -314,7 +316,7 @@ void M_Menu_SinglePlayer_f (void)
MC_AddCenterPicture(menu, 0, 24, "gfx/p_option.lmp");
menu->selecteditem = (menuoption_t*)
MC_AddConsoleCommandQBigFont (menu, 72, 32, "New Game", "closemenu;disconnect;maxclients 1;deathmatch 0;coop 0;map start\n");
MC_AddConsoleCommandQBigFont (menu, 72, 32, "New Game", "closemenu;disconnect;maxclients 1;deathmatch 0;coop 0;startmap_sp\n");
MC_AddConsoleCommandQBigFont (menu, 72, 52, "Load Game", "menu_load\n");
MC_AddConsoleCommandQBigFont (menu, 72, 72, "Save Game", "menu_save\n");
@ -340,7 +342,7 @@ void M_Menu_SinglePlayer_f (void)
{
MC_AddPicture(menu, 72, 32, 232, 64, "gfx/sp_menu.lmp");
b = MC_AddConsoleCommand (menu, 16, 32, "", "closemenu;disconnect;maxclients 1;deathmatch 0;coop 0;map start\n");
b = MC_AddConsoleCommand (menu, 16, 32, "", "closemenu;disconnect;maxclients 1;deathmatch 0;coop 0;startmap_sp\n");
menu->selecteditem = (menuoption_t *)b;
b->common.width = p->width;
b->common.height = 20;

View file

@ -64,6 +64,7 @@ void R2D_TransPicTranslate (float x, float y, int width, int height, qbyte *pic,
void R2D_TileClear (float x, float y, float w, float h);
void R2D_FadeScreen (void);
void R2D_Font_Changed(void);
void R2D_ConsoleBackground (int firstline, int lastline, qboolean forceopaque);
void R2D_EditorBackground (void);

View file

@ -505,6 +505,9 @@ char *Master_ReadKeyString(serverinfo_t *server, int keynum)
{
static char adr[MAX_ADR_SIZE];
if (!server)
return "";
if (keynum < SLKEY_CUSTOM)
{
switch(keynum)

View file

@ -202,7 +202,7 @@ static void PClassic_RunParticleWeather(vec3_t minb, vec3_t maxb, vec3_t dir, fl
}
//DP extension: add particles within a box.
static void PClassic_RunParticleCube(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter)
static void PClassic_RunParticleCube(int ptype, vec3_t minb, vec3_t maxb, vec3_t dir_min, vec3_t dir_max, float count, int colour, qboolean gravity, float jitter)
{
}

View file

@ -15,7 +15,7 @@ static int PNULL_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float coun
static int PNULL_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlkey, trailstate_t **tsk){return 1;}
static int PNULL_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk){return 1;}
static void PNULL_RunParticleWeather(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname){}
static void PNULL_RunParticleCube(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter){}
static void PNULL_RunParticleCube(int typenum, vec3_t minb, vec3_t maxb, vec3_t dir_min, vec3_t dir_max, float count, int colour, qboolean gravity, float jitter){}
static void PNULL_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count){}
static void PNULL_RunParticleEffect2 (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count){}
static void PNULL_RunParticleEffect3 (vec3_t org, vec3_t box, int color, int effect, int count){}

View file

@ -2214,21 +2214,21 @@ static void P_ImportEffectInfo_f(void)
ptype->flags = (ptype->flags & ~PT_NODLSHADOW) | (!atoi(arg[1])?PT_NODLSHADOW:0);
else if (!strcmp(arg[0], "lightcubemapnum") && args == 2)
ptype->dl_cubemapnum = atoi(arg[1]);
#if 0
else if (!strcmp(arg[0], "staincolor") && args == 2)
;
else if (!strcmp(arg[0], "stainalpha") && args == 2)
;
else if (!strcmp(arg[0], "stainsize") && args == 2)
;
else if (!strcmp(arg[0], "staintex") && args == 2)
;
else if (!strcmp(arg[0], "stainless") && args == 1)
;
else if (!strcmp(arg[0], "rotate") && args == 2)
;
else if (!strcmp(arg[0], "rotate") && args == 4)
;
#if 1
else if (!strcmp(arg[0], "staincolor") && args == 3)
Con_DPrintf("Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
else if (!strcmp(arg[0], "stainalpha") && args == 3)
Con_DPrintf("Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
else if (!strcmp(arg[0], "stainsize") && args == 3)
Con_DPrintf("Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
else if (!strcmp(arg[0], "staintex") && args == 3)
Con_DPrintf("Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
else if (!strcmp(arg[0], "stainless") && args == 2)
Con_DPrintf("Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
else if (!strcmp(arg[0], "rotate") && args == 3)
Con_DPrintf("Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
else if (!strcmp(arg[0], "rotate") && args == 5)
Con_DPrintf("Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
#endif
else
Con_Printf("Particle effect token not recognised, or invalid args: %s %s %s %s %s %s\n", arg[0], args<2?"":arg[1], args<3?"":arg[2], args<4?"":arg[3], args<5?"":arg[4], args<6?"":arg[5]);
@ -3940,14 +3940,15 @@ static void PScript_RunParticleEffect4 (vec3_t org, float radius, int color, int
}
}
static void PScript_RunParticleCube(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter)
static void PScript_RunParticleCube(int ptype, vec3_t minb, vec3_t maxb, vec3_t dir_min, vec3_t dir_max, float count, int colour, qboolean gravity, float jitter)
{
vec3_t org;
int i, j;
float num;
float invcount;
int ptype = P_FindParticleType(va("te_cube%s_%i", gravity?"_g":"", colour));
if (ptype < 0)
ptype = P_FindParticleType(va("te_cube%s_%i", gravity?"_g":"", colour));
if (ptype < 0)
{
ptype = P_FindParticleType(va("te_cube%s", gravity?"_g":""));
@ -3970,7 +3971,7 @@ static void PScript_RunParticleCube(vec3_t minb, vec3_t maxb, vec3_t dir, float
num = rand() / (float)RAND_MAX;
org[j] = minb[j] + num*(maxb[j]-minb[j]);
}
P_RunParticleEffectType(org, dir, invcount, ptype);
P_RunParticleEffectType(org, dir_min, invcount, ptype);
}
}

View file

@ -1167,14 +1167,14 @@ void QCBUILTIN PF_R_PolygonEnd(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
qboolean csqc_rebuildmatricies;
float csqc_proj_matrix[16];
float csqc_proj_matrix_inverse[16];
void V_ApplyAFov(void);
void V_ApplyAFov(playerview_t *pv);
void buildmatricies(void)
{
float modelview[16];
float proj[16];
float ofovx = r_refdef.fov_x,ofovy=r_refdef.fov_y;
if (r_refdef.dirty & RDFD_FOV)
V_ApplyAFov();
V_ApplyAFov(csqc_playerview);
/*build modelview and projection*/
Matrix4x4_CM_ModelViewMatrix(modelview, r_refdef.viewangles, r_refdef.vieworg);
@ -1187,6 +1187,9 @@ void buildmatricies(void)
Matrix4_Invert(csqc_proj_matrix, csqc_proj_matrix_inverse);
csqc_rebuildmatricies = false;
r_refdef.fov_x = ofovx,
r_refdef.fov_y = ofovy;
}
static void QCBUILTIN PF_cs_project (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -2104,6 +2107,31 @@ static void QCBUILTIN PF_cs_setsensativityscaler (pubprogfuncs_t *prinst, struct
in_sensitivityscale = G_FLOAT(OFS_PARM0);
}
static void QCBUILTIN PF_cs_boxparticles(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int effectnum = CL_TranslateParticleFromServer(G_FLOAT(OFS_PARM0));
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM1);
float *org_from = G_VECTOR(OFS_PARM2);
float *org_to = G_VECTOR(OFS_PARM3);
float *vel_from = G_VECTOR(OFS_PARM4);
float *vel_to = G_VECTOR(OFS_PARM5);
float count = G_FLOAT(OFS_PARM6);
int flags = (prinst->callargc < 7)?0:G_FLOAT(OFS_PARM7);
if (flags & 128)
{
flags &= ~128;
P_ParticleTrail(org_from, org_to, effectnum, 0, NULL);
}
else
{
P_RunParticleCube(effectnum, org_from, org_to, vel_from, vel_to, count, 0, true, 0);
}
if (flags)
Con_DPrintf("PF_cs_boxparticles: flags & %x is not supported\n", flags);
}
static void QCBUILTIN PF_cs_pointparticles (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int effectnum = G_FLOAT(OFS_PARM0);
@ -3295,7 +3323,7 @@ static void QCBUILTIN PF_cl_te_particlecube (pubprogfuncs_t *prinst, struct glob
float gravity = G_FLOAT(OFS_PARM5);
float jitter = G_FLOAT(OFS_PARM6);
P_RunParticleCube(minb, maxb, vel, howmany, color, gravity, jitter);
P_RunParticleCube(P_INVALID, minb, maxb, vel, vel, howmany, color, gravity, jitter);
}
static void QCBUILTIN PF_cl_te_spark (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -4111,7 +4139,31 @@ static void QCBUILTIN PF_getentity(pubprogfuncs_t *prinst, struct globalvars_s *
}
}
static void QCBUILTIN PF_V_CalcRefdef(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0);
extern cvar_t cl_forcesplitclient;
Con_DPrintf("Warning: V_CalcRefdef (builtin 640) not implemented.\n");
// if (ent->xv->entnum >= 1 && ent->xv->entnum <= MAX_CLIENTS)
// CSQC_ChangeLocalPlayer(ent->xv->entnum-1);
csqc_rebuildmatricies = true;
CL_DecayLights ();
#if defined(SKELETALOBJECTS) || defined(RAGDOLLS)
skel_dodelete(csqcprogs);
#endif
CL_ClearEntityLists();
V_ClearRefdef(csqc_playerview);
r_refdef.drawsbar = false; //csqc defaults to no sbar.
csqc_addcrosshair = false;
VectorCopy(ent->v->origin, csqc_playerview->simorg);
V_CalcRefdef(csqc_playerview); //set up the defaults
}
#if 1
//static void QCBUILTIN PF_ReadServerEntityState(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -4276,9 +4328,6 @@ static void QCBUILTIN PF_ReadServerEntityState(pubprogfuncs_t *prinst, struct gl
//PF_cs_ - works in csqc only (dependant upon globals or fields)
//PF_cl_ - works in csqc and menu (if needed...)
//these are the builtins that still need to be added.
#define PS_cs_setattachment PF_Fixme
//warning: functions that depend on globals are bad, mkay?
static struct {
char *name;
@ -4466,7 +4515,7 @@ static struct {
{"shaderforname", PF_shaderforname, 238}, // #238
{"te_bloodqw", PF_cl_te_bloodqw, 239}, // #239 void te_bloodqw(vector org[, float count]) (FTE_TE_STANDARDEFFECTBUILTINS)
// {"checkpvs", PF_checkpvs, 240},
{"checkpvs", PF_checkpvs, 240},
// {"matchclientname", PF_matchclient, 241},
{"sendpacket", PF_NoCSQC, 242}, //void(string dest, string content) sendpacket = #242; (FTE_QC_SENDPACKET)
@ -4694,7 +4743,7 @@ static struct {
{"clientcommand", PF_NoCSQC, 440}, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) (don't implement)
{"tokenize", PF_Tokenize, 441}, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND)
{"argv", PF_ArgV, 442}, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND)
{"setattachment", PS_cs_setattachment,443}, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
{"setattachment", PF_setattachment, 443}, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS)
{"search_begin", PF_search_begin, 444}, // #444 float search_begin(string pattern, float caseinsensitive, float quiet) (DP_QC_FS_SEARCH)
{"search_end", PF_search_end, 445}, // #445 void search_end(float handle) (DP_QC_FS_SEARCH)
@ -4799,7 +4848,7 @@ static struct {
//DP_SV_WRITEPICTURE
{"WritePicture", PF_ReadPicture, 501}, // #501 void(float to, string s, float sz) WritePicture
// {"boxparticles", PF_Fixme, 502},
{"boxparticles", PF_cs_boxparticles, 502},
//DP_QC_WHICHPACK
{"whichpack", PF_whichpack, 503}, // #503 string(string filename) whichpack
@ -4873,6 +4922,7 @@ static struct {
{"setbindmaps", PF_cl_SetBindMap, 632},
{"digest_hex", PF_digest_hex, 639},
{"V_CalcRefdef", PF_V_CalcRefdef, 640},
{NULL}
};
@ -5056,7 +5106,7 @@ void CSQC_Shutdown(void)
{
key_dest_absolutemouse &= ~kdm_game;
CSQC_ForgetThreads();
PR_ResetFonts(true);
PR_ResetFonts(kdm_game);
PR_Common_Shutdown(csqcprogs, false);
csqcprogs->CloseProgs(csqcprogs);
}
@ -5695,6 +5745,46 @@ void CSQC_CvarChanged(cvar_t *var)
}
}
//evil evil function. calling qc from inside the renderer is BAD.
qboolean CSQC_SetupToRenderPortal(int entkeynum)
{
#ifdef TEXTEDITOR
extern qboolean editormodal;
if (editormodal)
return false;
#endif
if (csqcprogs && entkeynum < 0)
{
csqcedict_t *e = (void*)EDICT_NUM(csqcprogs, -entkeynum);
if (e->xv->camera_transform)
{
int oself = *csqcg.self;
void *pr_globals = PR_globals(csqcprogs, PR_CURRENT);
*csqcg.self = EDICT_TO_PROG(csqcprogs, e);
VectorCopy(r_refdef.vieworg, G_VECTOR(OFS_PARM0));
VectorAngles(vpn, vup, G_VECTOR(OFS_PARM1));
VectorCopy(vpn, csqcg.forward);
VectorCopy(vright, csqcg.right);
VectorCopy(vup, csqcg.up);
VectorCopy(r_refdef.vieworg/*r_refdef.pvsorigin*/, csqcg.trace_endpos);
PR_ExecuteProgram (csqcprogs, e->xv->camera_transform);
VectorCopy(csqcg.forward, vpn);
VectorCopy(csqcg.right, vright);
VectorCopy(csqcg.up, vup);
VectorCopy(G_VECTOR(OFS_RETURN), r_refdef.vieworg);
VectorCopy(csqcg.trace_endpos, r_refdef.pvsorigin);
*csqcg.self = oself;
return true;
}
}
return false;
}
qboolean CSQC_DrawView(void)
{
int ticlimit = 10;
@ -6304,10 +6394,10 @@ void CSQC_ParseEntities(void)
if (msg_readcount != packetstart+packetsize)
{
if (msg_readcount > packetstart+packetsize)
Con_Printf("CSQC overread entity %i. Size %i, read %i\n", entnum, packetsize, msg_readcount - packetsize);
Con_Printf("CSQC overread entity %i. Size %i, read %i", entnum, packetsize, msg_readcount - packetstart);
else
Con_Printf("CSQC underread entity %i. Size %i, read %i\n", entnum, packetsize, msg_readcount - packetsize);
Con_Printf("First byte is %i\n", net_message.data[msg_readcount]);
Con_Printf("CSQC underread entity %i. Size %i, read %i", entnum, packetsize, msg_readcount - packetstart);
Con_Printf(", first byte is %i(%x)\n", net_message.data[msg_readcount], net_message.data[msg_readcount]);
#ifndef CLIENTONLY
if (sv.state)
{

View file

@ -68,23 +68,24 @@ void QCBUILTIN PF_CL_drawresetcliparea (pubprogfuncs_t *prinst, struct globalvar
}
#define FONT_SLOTS 16
#define FONT_SIZES 4
#define FONT_SIZES 16
struct {
unsigned int owner; //kdm_foo. whoever has an interest in this font. font is purged when this becomes 0.
char slotname[16];
char facename[64];
char facename[MAX_OSPATH];
int sizes;
int size[4];
struct font_s *font[4];
int size[FONT_SIZES];
struct font_s *font[FONT_SIZES];
} fontslot[FONT_SLOTS];
static struct font_s *PR_CL_ChooseFont(world_t *world, float szx, float szy)
struct font_s *PR_CL_ChooseFont(float *fontsel, float szx, float szy)
{
int fontidx = 0; //default by default...
struct font_s *font = font_conchar;
struct font_s *font = font_default;
if (world->g.drawfont)
if (fontsel)
{
fontidx = *world->g.drawfont;
fontidx = *fontsel;
}
if (fontidx >= 0 && fontidx < FONT_SLOTS)
@ -106,7 +107,7 @@ static struct font_s *PR_CL_ChooseFont(world_t *world, float szx, float szy)
void PR_CL_BeginString(pubprogfuncs_t *prinst, float vx, float vy, float szx, float szy, float *px, float *py)
{
world_t *world = prinst->parms->user;
struct font_s *font = PR_CL_ChooseFont(world, szx, szy);
struct font_s *font = PR_CL_ChooseFont(world->g.drawfont, szx, szy);
if (world->g.drawfontscale && (world->g.drawfontscale[0] || world->g.drawfontscale[1]))
{
szx *= world->g.drawfontscale[0];
@ -135,11 +136,18 @@ int PR_findnamedfont(char *name, qboolean isslotname)
}
return -1;
}
void PR_ResetFonts(qboolean purge)
//purgeowner 0 will reload all fonts. other values will purge only fonts which are now unused.
void PR_ResetFonts(unsigned int purgeowner)
{
int i, j;
for (i = 0; i < FONT_SLOTS; i++)
{
fontslot[i].owner &= ~purgeowner;
//don't bother flushing fonts when we don't really need to.
if (fontslot[i].owner && purgeowner)
return;
for (j = 0; j < fontslot[i].sizes; j++)
{
if (fontslot[i].font[j])
@ -147,19 +155,25 @@ void PR_ResetFonts(qboolean purge)
fontslot[i].font[j] = NULL;
}
if (purge)
//if noone is interested in it now, it can be purged fully.
if (!fontslot[i].owner)
{
fontslot[i].sizes = 0;
fontslot[i].slotname[0] = '\0';
fontslot[i].facename[0] = '\0';
}
else
{
{ //otherwise load it.
for (j = 0; j < fontslot[i].sizes; j++)
{
if (qrenderer == QR_NONE)
fontslot[i].font[j] = NULL;
else
fontslot[i].font[j] = Font_LoadFont(fontslot[i].size[j], fontslot[i].facename);
}
}
}
}
void QCBUILTIN PF_CL_findfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
char *slotname = PR_GetStringOfs(prinst, OFS_PARM0);
@ -174,6 +188,7 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
//float fix_scale = G_FLOAT(OFS_PARM4);
//float fix_voffset = G_FLOAT(OFS_PARM5);
int i, sz;
world_t *world = prinst->parms->user;
G_FLOAT(OFS_RETURN) = 0; //return default on failure.
@ -200,7 +215,9 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
Font_Free(fontslot[slotnum].font[i]);
fontslot[slotnum].font[i] = NULL;
}
fontslot[slotnum].owner = 0;
}
fontslot[slotnum].owner |= world->keydestmask;
while(*sizestr)
{
@ -216,6 +233,9 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
if (i >= FONT_SIZES)
break;
fontslot[slotnum].size[i] = sz;
if (qrenderer == QR_NONE)
fontslot[slotnum].font[i] = NULL;
else
fontslot[slotnum].font[i] = Font_LoadFont(fontslot[slotnum].size[i], facename);
fontslot[slotnum].sizes++;
}
@ -223,6 +243,103 @@ void QCBUILTIN PF_CL_loadfont (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
G_FLOAT(OFS_RETURN) = slotnum;
}
void CL_LoadFont_f(void)
{
//console command for compat with dp/debug.
if (Cmd_Argc() == 1)
{
int i, j;
for (i = 0; i < FONT_SLOTS; i++)
{
if (fontslot[i].sizes)
{
Con_Printf("%s: %s (", fontslot[i].slotname, fontslot[i].facename);
for (j = 0; j < fontslot[i].sizes; j++)
{
if (j)
Con_Printf(", ", fontslot[i].size[j]);
Con_Printf("%i", fontslot[i].size[j]);
}
Con_Printf(")\n");
}
}
}
else
{
int i;
int slotnum = 0;
char *slotname = Cmd_Argv(1);
char *facename = Cmd_Argv(2);
int sizenum = 3;
//loadfont slot face size1 size2...
slotnum = PR_findnamedfont(slotname, true);
if (slotnum < 0)
{
char *dpnames[] = {"default", "console", "sbar", "notify", "chat", "centerprint", "infobar", "menu", "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7", NULL};
for (i = 0; dpnames[i]; i++)
{
if (!strcmp(dpnames[i], slotname))
{
//assign it to this slot only if this slot does not already have a face. avoids corrupting already-loaded fonts.
if (!*fontslot[i].facename)
slotnum = i;
break;
}
}
if (slotnum < 0)
slotnum = PR_findnamedfont("", true); //whatever is still free
}
if (slotnum < 0)
{
Con_Printf("out of font slots\n");
return;
}
//if there's a new font in this slot, purge the old and change the name+face strings
if (stricmp(fontslot[slotnum].slotname, slotname) || stricmp(fontslot[slotnum].facename, facename))
{
Q_strncpyz(fontslot[slotnum].slotname, slotname, sizeof(fontslot[slotnum].slotname));
Q_strncpyz(fontslot[slotnum].facename, facename, sizeof(fontslot[slotnum].facename));
for (i = 0; i < fontslot[slotnum].sizes; i++)
{
if (fontslot[slotnum].font[i])
Font_Free(fontslot[slotnum].font[i]);
fontslot[slotnum].font[i] = NULL;
}
fontslot[slotnum].owner = 0;
}
if (!*facename)
return;
fontslot[slotnum].owner |= kdm_console; //fonts owned by the console are never forgotten.
while(sizenum < Cmd_Argc())
{
int sz = atoi(Cmd_Argv(sizenum++));
if (sz <= 0)
sz = 8;
for (i = 0; i < fontslot[slotnum].sizes; i++)
{
if (fontslot[slotnum].size[i] == sz)
break;
}
if (i == fontslot[slotnum].sizes)
{
if (i >= FONT_SIZES)
break;
fontslot[slotnum].size[i] = sz;
if (qrenderer == QR_NONE)
fontslot[slotnum].font[i] = NULL;
else
fontslot[slotnum].font[i] = Font_LoadFont(fontslot[slotnum].size[i], facename);
fontslot[slotnum].sizes++;
}
}
}
}
void QCBUILTIN PF_CL_DrawTextField (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *pos = G_VECTOR(OFS_PARM0);
@ -696,7 +813,7 @@ void QCBUILTIN PF_SubConDraw (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
fontsize *= world->g.drawfontscale[1];
}
Con_DrawOneConsole(con, PR_CL_ChooseFont(world, fontsize, fontsize), pos[0], pos[1], size[0], size[1]);
Con_DrawOneConsole(con, PR_CL_ChooseFont(world->g.drawfont, fontsize, fontsize), pos[0], pos[1], size[0], size[1]);
}
qboolean Key_Console (console_t *con, unsigned int unicode, int key);
void Key_ConsoleRelease (console_t *con, unsigned int unicode, int key);
@ -1715,7 +1832,7 @@ void MP_Shutdown (void)
PR_Common_Shutdown(menu_world.progs, false);
menu_world.progs->CloseProgs(menu_world.progs);
memset(&menu_world, 0, sizeof(menu_world));
PR_ResetFonts(true);
PR_ResetFonts(kdm_menu);
#ifdef CL_MASTER
Master_ClearMasks();
@ -1960,6 +2077,7 @@ void MP_RegisterCvarsAndCmds(void)
Cmd_AddCommand("menu_restart", MP_Reload_f);
Cmd_AddCommand("menu_cmd", MP_GameCommand_f);
Cmd_AddCommand("breakpoint_menu", MP_Breakpoint_f);
Cmd_AddCommand("loadfont", CL_LoadFont_f);
Cvar_Register(&forceqmenu, MENUPROGSGROUP);
Cvar_Register(&pr_menuqc_coreonerror, MENUPROGSGROUP);

View file

@ -41,6 +41,7 @@ extern cvar_t gl_screenangle;
extern cvar_t vid_conautoscale;
extern cvar_t vid_conheight;
extern cvar_t vid_conwidth;
extern cvar_t con_textsize;
void R2D_Font_Callback(struct cvar_s *var, char *oldvalue);
void R2D_Conautoscale_Callback(struct cvar_s *var, char *oldvalue);
void R2D_ScreenAngle_Callback(struct cvar_s *var, char *oldvalue);
@ -115,9 +116,15 @@ void R2D_Shutdown(void)
cl_numstris = 0;
cl_maxstris = 0;
if (font_conchar)
Font_Free(font_conchar);
font_conchar = NULL;
if (font_console == font_default)
font_console = NULL;
if (font_console)
Font_Free(font_console);
font_console = NULL;
if (font_default)
Font_Free(font_default);
font_default = NULL;
if (font_tiny)
Font_Free(font_tiny);
font_tiny = NULL;
@ -659,17 +666,30 @@ void R2D_Font_AddFontLink(char *buffer, int buffersize, char *fontname)
}
}
#endif
void R2D_Font_Callback(struct cvar_s *var, char *oldvalue)
void R2D_Font_Changed(void)
{
if (font_conchar)
Font_Free(font_conchar);
font_conchar = NULL;
if (!con_textsize.modified)
return;
con_textsize.modified = false;
if (font_console == font_default)
font_console = NULL;
if (font_console)
Font_Free(font_console);
font_console = NULL;
if (font_default)
Font_Free(font_default);
font_default = NULL;
#if defined(MENU_DAT) || defined(CSQC_DAT)
PR_ResetFonts(0);
#endif
if (qrenderer == QR_NONE)
return;
#if defined(_WIN32) && !defined(_SDL)
if (!strcmp(var->string, "?"))
if (!strcmp(gl_font.string, "?"))
{
BOOL (APIENTRY *pChooseFontA)(LPCHOOSEFONTA) = NULL;
dllfunction_t funcs[] =
@ -681,7 +701,11 @@ void R2D_Font_Callback(struct cvar_s *var, char *oldvalue)
LOGFONT lf = {0};
CHOOSEFONTA cf = {sizeof(cf)};
extern HWND mainwindow;
font_conchar = Font_LoadFont(8, "");
font_default = Font_LoadFont(8, "");
if (con_textsize.ival != 8 && con_textsize.ival >= 1)
font_console = Font_LoadFont(con_textsize.ival, "");
if (!font_console)
font_console = font_default;
cf.hwndOwner = mainwindow;
cf.iPointSize = (8 * vid.rotpixelheight)/vid.height;
@ -710,15 +734,29 @@ void R2D_Font_Callback(struct cvar_s *var, char *oldvalue)
}
R2D_Font_AddFontLink(fname, sizeof(fname), lf.lfFaceName);
Cvar_Set(var, fname);
Cvar_Set(&gl_font, fname);
}
return;
}
#endif
font_conchar = Font_LoadFont(8, var->string);
if (!font_conchar && *var->string)
font_conchar = Font_LoadFont(8, "");
font_default = Font_LoadFont(8, gl_font.string);
if (!font_default && *gl_font.string)
font_default = Font_LoadFont(8, "");
if (con_textsize.ival != 8 && con_textsize.ival >= 1)
{
font_console = Font_LoadFont(con_textsize.ival, gl_font.string);
if (!font_console)
font_console = Font_LoadFont(con_textsize.ival, "");
}
if (!font_console)
font_console = font_default;
}
void R2D_Font_Callback(struct cvar_s *var, char *oldvalue)
{
con_textsize.modified = true;
}
// console size manipulation callbacks
@ -795,19 +833,8 @@ void R2D_Console_Resize(void)
vid.width = cwidth;
vid.height = cheight;
if (font_tiny)
Font_Free(font_tiny);
font_tiny = NULL;
if (font_conchar)
Font_Free(font_conchar);
font_conchar = NULL;
Cvar_ForceCallback(&gl_font);
#if defined(MENU_DAT) || defined(CSQC_DAT)
PR_ResetFonts(false);
#endif
#ifdef PLUGINS
Plug_ResChanged();
#endif
@ -1201,13 +1228,13 @@ void R2D_DrawCrosshair(void)
for (sc = 0; sc < cl.splitclients; sc++)
{
SCR_CrosshairPosition(&cl.playerview[sc], &sx, &sy);
Font_BeginScaledString(font_conchar, sx, sy, size, size, &sx, &sy);
Font_BeginScaledString(font_default, sx, sy, size, size, &sx, &sy);
sx -= Font_CharScaleWidth('+' | 0xe000 | CON_WHITEMASK)/2;
sy -= Font_CharScaleHeight()/2;
Font_ForceColour(ch_color[0], ch_color[1], ch_color[2], crosshairalpha.value);
Font_DrawScaleChar(sx, sy, '+' | 0xe000 | CON_WHITEMASK);
Font_InvalidateColour();
Font_EndString(font_conchar);
Font_EndString(font_default);
}
return;
}

View file

@ -926,10 +926,10 @@ static void Surf_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest,
}
else if (!currentmodel->lightdata)
{
/*fullbright if map is not lit*/
/*fullbright if map is not lit. but not overbright*/
for (i=0 ; i<size*3 ; i++)
{
blocklights[i] = 255*256;
blocklights[i] = 128*256;
}
}
else if (!surf->samples)
@ -1887,26 +1887,73 @@ start:
}
#endif
static void Surf_CleanChains(void)
static void Surf_PushChains(model_t *model)
{
model_t *model = cl.worldmodel;
batch_t *batch;
int i;
if (r_refdef.recurse)
if (r_refdef.recurse == R_MAX_RECURSE)
Sys_Error("Recursed too deep\n");
if (!r_refdef.recurse)
{
for (i = 0; i < SHADER_SORT_COUNT; i++)
for (batch = model->batches[i]; batch; batch = batch->next)
{
batch->firstmesh = 0;
}
}
#if R_MAX_RECURSE > 2
else if (r_refdef.recurse > 1)
{
for (i = 0; i < SHADER_SORT_COUNT; i++)
for (batch = model->batches[i]; batch; batch = batch->next)
{
batch->recursefirst[r_refdef.recurse] = batch->firstmesh;
batch->firstmesh = batch->meshes;
}
}
#endif
else
{
for (i = 0; i < SHADER_SORT_COUNT; i++)
for (batch = model->batches[i]; batch; batch = batch->next)
{
batch->firstmesh = batch->meshes;
}
}
}
static void Surf_PopChains(model_t *model)
{
batch_t *batch;
int i;
if (!r_refdef.recurse)
{
for (i = 0; i < SHADER_SORT_COUNT; i++)
for (batch = model->batches[i]; batch; batch = batch->next)
{
batch->meshes = 0;
}
}
#if R_MAX_RECURSE > 2
else if (r_refdef.recurse > 1)
{
for (i = 0; i < SHADER_SORT_COUNT; i++)
for (batch = model->batches[i]; batch; batch = batch->next)
{
batch->meshes = batch->firstmesh;
batch->firstmesh = batch->recursefirst[r_refdef.recurse];
}
}
#endif
else
{
for (i = 0; i < SHADER_SORT_COUNT; i++)
for (batch = model->batches[i]; batch; batch = batch->next)
{
batch->meshes = batch->firstmesh;
batch->firstmesh = 0;
}
}
}
@ -2191,6 +2238,9 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent)
if (b->buildmeshes)
b->buildmeshes(b);
if (!b->shader)
b->shader = R_TextureAnimation(ent->framestate.g[FS_REG].frame[0], b->texture)->shader;
if (bef & BEF_FORCEADDITIVE)
{
b->next = batches[SHADER_SORT_ADDITIVE];
@ -2244,6 +2294,8 @@ void Surf_DrawWorld (void)
Surf_LightmapShift(cl.worldmodel);
Surf_PushChains(cl.worldmodel);
#ifdef Q2BSPS
if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)
{
@ -2337,7 +2389,7 @@ void Surf_DrawWorld (void)
if (cl.worldmodel->fromgame == fg_quake || cl.worldmodel->fromgame == fg_halflife)
Surf_LessenStains();
Surf_CleanChains();
Surf_PopChains(cl.worldmodel);
}
}
@ -2589,7 +2641,11 @@ void Surf_BuildModelLightmaps (model_t *m)
shift = Surf_LightmapShift(currentmodel);
if (*m->name == '*' && m->fromgame == fg_quake3) //FIXME: should be all bsp formats
{
if (!cl.model_precache[1] || cl.model_precache[1]->needload)
return;
newfirst = cl.model_precache[1]->lightmaps.first;
}
else
{
if (!m->lightdata && m->lightmaps.count && m->fromgame == fg_quake3)
@ -2758,6 +2814,8 @@ void Surf_BuildLightmaps (void)
m = cl.model_precache[j];
if (!m)
break;
if (m->needload)
continue;
Surf_BuildModelLightmaps(m);
}
for (j=1 ; j<MAX_CSMODELS ; j++)

View file

@ -149,6 +149,7 @@ typedef struct mplane_s
} mplane_t;
#define MAXFRUSTUMPLANES 7 //4 side, 1 near, 1 far (fog), 1 water plane.
#define R_MAX_RECURSE 6
#define RDFD_FOV 1
typedef struct
{
@ -182,7 +183,7 @@ typedef struct
pxrect_t pxrect; /*vrect, but in pixels rather than virtual coords*/
qboolean externalview; /*draw external models and not viewmodels*/
qboolean recurse; /*in a mirror/portal/half way through drawing something else*/
int recurse; /*in a mirror/portal/half way through drawing something else*/
qboolean forcevis; /*if true, vis comes from the forcedvis field instead of recalculated*/
unsigned int flipcull; /*reflected/flipped view, requires inverted culling (should be set to SHADER_CULL_FLIPPED or 0)*/
qboolean useperspective; /*not orthographic*/
@ -275,7 +276,7 @@ void GLR_InitTextures (void);
void GLR_InitEfrags (void);
void GLR_RenderView (void); // must set r_refdef first
// called whenever r_refdef or vid change
void GLR_DrawPortal(struct batch_s *batch, struct batch_s **blist, int portaltype);
void GLR_DrawPortal(struct batch_s *batch, struct batch_s **blist, struct batch_s *depthmasklist[2], int portaltype);
void GLR_PreNewMap(void);
void GLR_NewMap (void);
@ -353,6 +354,8 @@ texid_tf R_LoadReplacementTexture(char *name, char *subpath, unsigned int flags)
texid_tf R_LoadHiResTexture(char *name, char *subpath, unsigned int flags);
texid_tf R_LoadBumpmapTexture(char *name, char *subpath);
qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, qboolean *hasalpha, char *fname);
extern texid_t particletexture;
extern texid_t particlecqtexture;
extern texid_t explosiontexture;

View file

@ -330,7 +330,7 @@ cvar_t gl_texturemode2d = CVARFC("gl_texturemode2d", "GL_LINEAR",
cvar_t vid_triplebuffer = CVARAF ("vid_triplebuffer", "1",
"gl_triplebuffer", CVAR_ARCHIVE);
cvar_t r_noportals = SCVAR ("r_noportals", "0");
cvar_t r_portalrecursion = CVARD ("r_portalrecursion", "1", "The number of portals the camera is allowed to recurse through.");
cvar_t dpcompat_psa_ungroup = SCVAR ("dpcompat_psa_ungroup", "0");
cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0",
CVAR_ARCHIVE);
@ -405,7 +405,7 @@ void GLRenderer_Init(void)
Cvar_Register (&dpcompat_psa_ungroup, GLRENDEREROPTIONS);
Cvar_Register (&r_lerpmuzzlehack, GLRENDEREROPTIONS);
Cvar_Register (&r_noframegrouplerp, GLRENDEREROPTIONS);
Cvar_Register (&r_noportals, GLRENDEREROPTIONS);
Cvar_Register (&r_portalrecursion, GLRENDEREROPTIONS);
Cvar_Register (&r_noaliasshadows, GLRENDEREROPTIONS);
Cvar_Register (&gl_maxshadowlights, GLRENDEREROPTIONS);
Cvar_Register (&r_shadow_bumpscale_basetexture, GLRENDEREROPTIONS);
@ -1970,12 +1970,12 @@ qbyte *R_CalcVis_Q1 (void)
qbyte *R_MarkLeaves_Q1 (void)
{
static qbyte fatvis[2][MAX_MAP_LEAFS/8];
static qbyte *cvis[2];
static qbyte fatvis[R_MAX_RECURSE][MAX_MAP_LEAFS/8];
static qbyte *cvis[R_MAX_RECURSE];
qbyte *vis;
mnode_t *node;
int i;
qboolean portal = r_refdef.recurse;
int portal = r_refdef.recurse;
//for portals to work, we need two sets of any pvs caches
//this means lights can still check pvs at the end of the frame despite recursing in the mean time

View file

@ -150,12 +150,12 @@ int Sbar_BottomColour(player_info_t *p)
void Draw_ExpandedString(float x, float y, conchar_t *str)
{
int px, py;
Font_BeginString(font_conchar, x, y, &px, &py);
Font_BeginString(font_default, x, y, &px, &py);
while(*str)
{
px = Font_DrawChar(px, py, *str++);
}
Font_EndString(font_conchar);
Font_EndString(font_default);
}
//Draws a marked-up string using the regular char set with no width limit. doesn't support new lines
@ -187,7 +187,7 @@ void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean
COM_ParseFunString(highlight?CON_ALTMASK:CON_WHITEMASK, str, buffer, sizeof(buffer), false);
Font_BeginString(font_conchar, x, y, &px, &py);
Font_BeginString(font_default, x, y, &px, &py);
if (rightalign)
{
for (w = buffer; *w; w++)
@ -207,7 +207,7 @@ void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean
return;
px = Font_DrawChar(px, py, *w);
}
Font_EndString(font_conchar);
Font_EndString(font_default);
}
static qboolean largegame = false;
@ -999,9 +999,9 @@ Draws one solid graphics character
void Sbar_DrawCharacter (float x, float y, int num)
{
int px, py;
Font_BeginString(font_conchar, sbar_rect.x + x + 4, sbar_rect.y + y + sbar_rect.height-SBAR_HEIGHT, &px, &py);
Font_BeginString(font_default, sbar_rect.x + x + 4, sbar_rect.y + y + sbar_rect.height-SBAR_HEIGHT, &px, &py);
Font_DrawChar(px, py, num | 0xe000 | CON_WHITEMASK);
Font_EndString(font_conchar);
Font_EndString(font_default);
}
/*
@ -2359,7 +2359,7 @@ static void Sbar_Voice(int y)
int s, i;
float range = loudness/100.0f;
w = 0;
Font_BeginString(font_conchar, sbar_rect.x + sbar_rect.width/2, sbar_rect.y + y + sbar_rect.height-SBAR_HEIGHT, &x, &y);
Font_BeginString(font_default, sbar_rect.x + sbar_rect.width/2, sbar_rect.y + y + sbar_rect.height-SBAR_HEIGHT, &x, &y);
w += Font_CharWidth(0xe080 | CON_WHITEMASK);
w += Font_CharWidth(0xe081 | CON_WHITEMASK)*16;
w += Font_CharWidth(0xe082 | CON_WHITEMASK);
@ -2378,7 +2378,7 @@ static void Sbar_Voice(int y)
x = Font_DrawChar(x, y, 0xe081 | CON_WHITEMASK);
Font_DrawChar(x, y, 0xe082 | CON_WHITEMASK);
Font_DrawChar(s + (x-s) * range - Font_CharWidth(0xe083 | CON_WHITEMASK)/2, y, 0xe083 | CON_WHITEMASK);
Font_EndString(font_conchar);
Font_EndString(font_default);
}
#endif
}
@ -2784,22 +2784,22 @@ ping time frags name
f = s->frags; \
sprintf(num, "%3i",f); \
\
Font_BeginString(font_conchar, x+8, y, &cx, &cy); \
Font_BeginString(font_default, x+8, y, &cx, &cy); \
Font_DrawChar(cx, cy, num[0] | 0xe000 | CON_WHITEMASK); \
Font_BeginString(font_conchar, x+16, y, &cx, &cy); \
Font_BeginString(font_default, x+16, y, &cx, &cy); \
Font_DrawChar(cx, cy, num[1] | 0xe000 | CON_WHITEMASK); \
Font_BeginString(font_conchar, x+24, y, &cx, &cy); \
Font_BeginString(font_default, x+24, y, &cx, &cy); \
Font_DrawChar(cx, cy, num[2] | 0xe000 | CON_WHITEMASK); \
\
if ((cl.spectator && k == Cam_TrackNum(pv)) ||\
(!cl.spectator && k == pv->playernum)) \
{ \
Font_BeginString(font_conchar, x, y, &cx, &cy); \
Font_BeginString(font_default, x, y, &cx, &cy); \
Font_DrawChar(cx, cy, 16 | 0xe000 | CON_WHITEMASK); \
Font_BeginString(font_conchar, x+32, y, &cx, &cy); \
Font_BeginString(font_default, x+32, y, &cx, &cy); \
Font_DrawChar(cx, cy, 17 | 0xe000 | CON_WHITEMASK); \
} \
Font_EndString(font_conchar); \
Font_EndString(font_default); \
} \
})
#define COLUMN_TEAMNAME COLUMN(team, 4*8, \
@ -3226,19 +3226,19 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
f = s->frags;
sprintf (num, "%3i",f);
Font_BeginString(font_conchar, x+8, y, &px, &py);
Font_BeginString(font_default, x+8, y, &px, &py);
Font_DrawChar ( px, py, num[0] | 0xe000 | CON_WHITEMASK);
Font_BeginString(font_conchar, x+16, y, &px, &py);
Font_BeginString(font_default, x+16, y, &px, &py);
Font_DrawChar ( px, py, num[1] | 0xe000 | CON_WHITEMASK);
Font_BeginString(font_conchar, x+24, y, &px, &py);
Font_BeginString(font_default, x+24, y, &px, &py);
Font_DrawChar ( px, py, num[2] | 0xe000 | CON_WHITEMASK);
if ((cl.spectator && k == pv->cam_spec_track) ||
(!cl.spectator && k == pv->playernum))
{
Font_BeginString(font_conchar, x, y, &px, &py);
Font_BeginString(font_default, x, y, &px, &py);
Font_DrawChar ( px, py, 16 | 0xe000 | CON_WHITEMASK);
Font_BeginString(font_conchar, x+32, y, &px, &py);
Font_BeginString(font_default, x+32, y, &px, &py);
Font_DrawChar ( px, py, 17 | 0xe000 | CON_WHITEMASK);
}
@ -3280,11 +3280,11 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
if (!strncmp(cl.players[pv->playernum].team, tm->team, 16))
{
Font_BeginString(font_conchar, x-8, y, &px, &py);
Font_BeginString(font_default, x-8, y, &px, &py);
Font_DrawChar(px, py, 16|0xe000|CON_WHITEMASK);
Font_BeginString(font_conchar, x+32, y, &px, &py);
Font_BeginString(font_default, x+32, y, &px, &py);
Font_DrawChar(px, py, 17|0xe000|CON_WHITEMASK);
Font_EndString(font_conchar);
Font_EndString(font_default);
}
y += 8;

View file

@ -115,9 +115,10 @@ int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int max
int Font_LineWidth(conchar_t *start, conchar_t *end);
float Font_LineScaleWidth(conchar_t *start, conchar_t *end);
void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end);
extern struct font_s *font_conchar;
extern struct font_s *font_default;
extern struct font_s *font_console;
extern struct font_s *font_tiny;
void PR_ResetFonts(qboolean purge); //for menu/csqc
void PR_ResetFonts(unsigned int purgeowner); //for menu/csqc
/*end fonts*/
void R_NetgraphInit(void);

View file

@ -1592,7 +1592,7 @@ static soundcardinfo_t *SNDDMA_Init(char *driver, char *device)
{ //if the sample speeds of multiple soundcards do not match, it'll fail.
if (snd_speed != sc->sn.speed)
{
Con_Printf("S_Startup: Ignoring soundcard %s due to mismatched sample speeds.\n", sc->name);
Con_TPrintf("S_Startup: Ignoring soundcard %s due to mismatched sample speeds.\n", sc->name);
S_ShutdownCard(sc);
continue;
}
@ -1624,7 +1624,7 @@ static soundcardinfo_t *SNDDMA_Init(char *driver, char *device)
{ //if the sample speeds of multiple soundcards do not match, it'll fail.
if (snd_speed != sc->sn.speed)
{
Con_Printf("S_Startup: Ignoring soundcard %s due to mismatched sample speeds.\nTry running Quake with -singlesound to use just the primary soundcard\n", sc->name);
Con_TPrintf("S_Startup: Ignoring soundcard %s due to mismatched sample speeds.\nTry running Quake with -singlesound to use just the primary soundcard\n", sc->name);
S_ShutdownCard(sc);
continue;
}
@ -1640,7 +1640,10 @@ static soundcardinfo_t *SNDDMA_Init(char *driver, char *device)
}
Z_Free(sc);
Con_Printf("Could not start \"%s\" device \"%s\"\n", driver?driver:"audio", device?device:"default");
if (!driver)
Con_TPrintf("Could not start audio device \"%s\"\n", device?device:"default");
else
Con_TPrintf("Could not start \"%s\" device \"%s\"\n", driver, device?device:"default");
return NULL;
}

View file

@ -73,6 +73,7 @@ typedef struct {
int ident;
int version;
int type;
//int rendermode; //present only in halflife sprites.
float boundingradius;
int width;
int height;
@ -81,11 +82,19 @@ typedef struct {
synctype_t synctype;
} dsprite_t;
#define SPR_VP_PARALLEL_UPRIGHT 0
#define SPR_FACING_UPRIGHT 1
#define SPR_VP_PARALLEL 2
#define SPR_ORIENTED 3
#define SPR_VP_PARALLEL_ORIENTED 4
#define SPR_VP_PARALLEL_UPRIGHT 0 //xy faces view. z is always up.
#define SPR_FACING_UPRIGHT 1 //xy faces view. z is always up.
#define SPR_VP_PARALLEL 2 //faces camera (traditional sprite)
#define SPR_ORIENTED 3 //uses axis
#define SPR_VP_PARALLEL_ORIENTED 4 //faces camera *then* rotated
#define SPRDP_LABEL 5
#define SPRDP_LABEL_SCALE 6
#define SPRDP_OVERHEAD 7
#define SPRHL_OPAQUE 0
#define SPRHL_ADDITIVE 1
#define SPRHL_INDEXALPHA 2
#define SPRHL_ALPHATEST 3
typedef struct {
int origin[2];

View file

@ -852,11 +852,8 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
}
if (match[nest] == '/')
{
char utf8[MAX_OSPATH];
wchar_t wroot[MAX_OSPATH];
char submatch[MAX_OSPATH];
char tmproot[MAX_OSPATH];
char file[MAX_OSPATH];
if (!wild)
return Sys_EnumerateFiles2(match, matchstart, nest+1, func, parm, spath);
@ -872,13 +869,18 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
{
wchar_t wroot[MAX_OSPATH];
r = FindFirstFileW(widen(wroot, sizeof(wroot), tmproot), &fd);
}
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
go = true;
do
{
char utf8[MAX_OSPATH];
char file[MAX_OSPATH];
narrowen(utf8, sizeof(utf8), fd.cFileName);
if (*utf8 == '.'); //don't ever find files with a name starting with '.'
else if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //is a directory
@ -902,22 +904,25 @@ static int Sys_EnumerateFiles2 (const char *match, int matchstart, int neststart
{
const char *submatch = match + neststart;
char tmproot[MAX_OSPATH];
wchar_t wroot[MAX_OSPATH];
char utf8[MAX_OSPATH];
char file[MAX_OSPATH];
if (neststart+4 > MAX_OSPATH)
return 1;
memcpy(tmproot, match, neststart);
strcpy(tmproot+neststart, "*.*");
{
wchar_t wroot[MAX_OSPATH];
r = FindFirstFileW(widen(wroot, sizeof(wroot), tmproot), &fd);
}
strcpy(tmproot+neststart, "");
if (r==(HANDLE)-1)
return 1;
go = true;
do
{
char utf8[MAX_OSPATH];
char file[MAX_OSPATH];
narrowen(utf8, sizeof(utf8), fd.cFileName);
if (*utf8 == '.')
; //don't ever find files with a name starting with '.' (includes .. and . directories, and unix hidden files)

View file

@ -909,7 +909,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
else
c = NULL;
Font_BeginString(font_conchar, nx, vy, &nx, &y);
Font_BeginString(font_default, nx, vy, &nx, &y);
if (ts < 1)
ts = 4;
@ -946,7 +946,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
nnx-=(nnx - -viewportx)%ts;
}
else
nnx = Font_CharEndCoord(font_conchar, nx, (int)d[i] | (colour));
nnx = Font_CharEndCoord(font_default, nx, (int)d[i] | (colour));
if (smx >= nx && smx <= nnx)
{
@ -1048,14 +1048,14 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
{
if (*tooltip == '\n')
break;
smx = Font_CharEndCoord(font_conchar, smx, *tooltip);
smx = Font_CharEndCoord(font_default, smx, *tooltip);
}
y = Font_CharHeight();
Font_EndString(font_conchar);
Font_EndString(font_default);
R2D_ImageColours(0, 0, 0, 1);
R2D_FillBlock(((nx)*vid.width) / vid.pixelwidth, ((smy)*vid.height) / vid.pixelheight, ((smx - nx)*vid.width) / vid.pixelwidth, (y*vid.height) / vid.pixelheight);
R2D_ImageColours(1, 1, 1, 1);
Font_BeginString(font_conchar, nx, vy, &y, &y);
Font_BeginString(font_default, nx, vy, &y, &y);
for(smx = nx; t < tooltip; t++)
{
smx = Font_DrawChar(smx, smy, (COLOR_CYAN<<CON_FGSHIFT) | *t);
@ -1065,7 +1065,7 @@ static void Draw_Line(int vy, fileblock_t *b, int cursorx)
smy += Font_CharHeight();
}
}
Font_EndString(font_conchar);
Font_EndString(font_default);
}
static fileblock_t *firstline(void)

View file

@ -139,6 +139,8 @@ V_CalcBob
float V_CalcBob (playerview_t *pv, qboolean queryold)
{
float cycle;
float hspeed, bob;
vec3_t hvel;
if (cl.spectator)
return 0;
@ -163,14 +165,12 @@ float V_CalcBob (playerview_t *pv, qboolean queryold)
// bob is proportional to simulated velocity in the xy plane
// (don't count Z, or jumping messes it up)
//FIXME: gravitydir
pv->bob = sqrt(pv->simvel[0]*pv->simvel[0] + pv->simvel[1]*pv->simvel[1]) * cl_bob.value;
pv->bob = pv->bob*0.3 + pv->bob*0.7*sin(cycle);
if (pv->bob > 4)
pv->bob = 4;
else if (pv->bob < -7)
pv->bob = -7;
hspeed = DotProduct(pv->simvel, pv->gravitydir);
VectorMA(pv->simvel, hspeed, pv->gravitydir, hvel);
hspeed = VectorLength(hvel);
hspeed = bound(0, hspeed, 400);
bob = hspeed * bound(0, cl_bob.value, 0.05);
pv->bob = bob*0.3 + bob*0.7*sin(cycle);
return pv->bob;
}
@ -1028,7 +1028,7 @@ float CalcFov (float fov_x, float width, float height)
return a;
}
void V_ApplyAFov(void)
void V_ApplyAFov(playerview_t *pv)
{
//explicit fov overrides aproximate fov.
//aproximate fov is our regular fov value. explicit is settable by gamecode for weird aspect ratios
@ -1040,8 +1040,8 @@ void V_ApplyAFov(void)
float afov = r_refdef.afov;
if (!afov) //make sure its sensible.
afov = scr_fov.value;
if (r_refdef.playerview->stats[STAT_VIEWZOOM])
afov *= r_refdef.playerview->stats[STAT_VIEWZOOM]/255.0f;
if (pv && pv->stats[STAT_VIEWZOOM])
afov *= pv->stats[STAT_VIEWZOOM]/255.0f;
ws = 1;
if (r_stereo_method.ival == 5 && r_stereo_separation.value)
@ -1152,7 +1152,7 @@ void V_ApplyRefdef (void)
r_refdef.vrect.y += r_refdef.grect.y;
if (r_refdef.dirty & RDFD_FOV)
V_ApplyAFov();
V_ApplyAFov(r_refdef.playerview);
r_refdef.dirty = 0;
}

View file

@ -97,6 +97,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#define AVAIL_OPENAL
#define AVAIL_FREETYPE
#if !defined(NO_DIRECTX) && !defined(NODIRECTX) && defined(_WIN32)
#define AVAIL_DINPUT
@ -132,7 +133,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//#define BOTLIB_STATIC
#endif
#define AVAIL_FREETYPE
#ifdef _WIN32
//needs testing on other platforms
//#define AVAIL_OPENAL
@ -160,8 +160,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#undef AVAIL_FREETYPE
#endif
//#define AVAIL_FREETYPE
//set any additional defines or libs in win32
#define SVRANKING

View file

@ -30,13 +30,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//#define MAX_MAP_ENTITIES 1024
//#define MAX_MAP_ENTSTRING 65536
#define MAX_MAP_PLANES 65636*2 //sanity (used by q2)
#define SANITY_MAX_MAP_NODES 65535 //sanity
#define SANITY_MAX_MAP_CLIPNODES 65535 //sanity
#define MAX_MAP_LEAFS 65535 //pvs buffer size. not sanity.
#define SANITY_MAX_MAP_VERTS 65535 //sanity
#define SANITY_MAX_MAP_FACES 65535 //sanity
//#define MAX_MAP_MARKSURFACES 65535 //sanity
#define MAX_MAP_PLANES 65536*2 //sanity (used by q2)
#define SANITY_MAX_MAP_NODES 65536 //sanity
#define SANITY_MAX_MAP_CLIPNODES 65536 //sanity
#define MAX_MAP_LEAFS 65536 //pvs buffer size. not sanity.
#define SANITY_MAX_MAP_VERTS 65536 //sanity
#define SANITY_MAX_MAP_FACES 65536 //sanity
//#define MAX_MAP_MARKSURFACES 65536 //sanity
//#define MAX_MAP_TEXINFO 4096 //sanity
#define MAX_MAP_EDGES 256000
//#define MAX_MAP_SURFEDGES 512000

View file

@ -2094,7 +2094,7 @@ void Cmd_ExecuteString (char *text, int level)
return;
}
#endif
if (cl_warncmd.value || developer.value)
if ((cl_warncmd.value && level <= RESTRICT_LOCAL) || developer.value)
Con_TPrintf ("Unknown command \"%s\"\n", Cmd_Argv(0));
}

View file

@ -2062,7 +2062,7 @@ unsigned int utf8_decode(int *error, const void *in, char **out)
if (*error == 4)
{
*out = lowend;
uc = (((uc&0x3ffu) << 10) || (lowsur&0x3ffu)) + 0x10000;
uc = (((uc&0x3ffu) << 10) | (lowsur&0x3ffu)) + 0x10000;
*error = false;
}
else
@ -2115,7 +2115,7 @@ unsigned int unicode_decode(int *error, const void *in, char **out)
{ //quake
*error = 0;
charcode = *(unsigned char*)in;
if (charcode != '\n' && charcode != '\t' && charcode != '\r' && (charcode < ' ' || charcode > 127))
if (charcode && charcode != '\n' && charcode != '\t' && charcode != '\r' && (charcode < ' ' || charcode > 127))
charcode |= 0xe000;
*out = (char*)in + 1;
}
@ -2856,6 +2856,27 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
continue;
}
}
else if (str[1] == 'x') //RGB colours
{
if (ishexcode(str[2]) && ishexcode(str[3]) && ishexcode(str[4]))
{
int r, g, b;
r = dehex(str[2]);
g = dehex(str[3]);
b = dehex(str[4]);
ext = (ext & ~CON_RICHFOREMASK) | CON_RICHFORECOLOUR;
ext |= r<<CON_RICHRSHIFT;
ext |= g<<CON_RICHGSHIFT;
ext |= b<<CON_RICHBSHIFT;
if (!keepmarkup)
{
str += 5;
continue;
}
}
}
else if (str[1] == '^')
{
if (keepmarkup)
@ -2887,8 +2908,6 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
if (ishexcode(str[2]) && ishexcode(str[3]) && ishexcode(str[4]))
{
//we don't support the full 12bit colour depth (only 4-bit CGA)
//so find the closest that we do support
int r, g, b;
r = dehex(str[2]);
g = dehex(str[3]);

View file

@ -93,8 +93,6 @@ extern conchar_t q3codemasks[MAXQ3COLOURS];
#define CON_ERROR "^&C0"
#define CON_NOTICE "^&-1"
#define CON_TEXTSIZE 16384
#define isextendedcode(x) ((x >= '0' && x <= '9') || (x >= 'A' && x <= 'F') || x == '-')
#define ishexcode(x) ((x >= '0' && x <= '9') || (x >= 'A' && x <= 'F') || (x >= 'a' && x <= 'f'))

View file

@ -3504,8 +3504,8 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs)
#endif
}
}
blockcache = false;
}
blockcache = false;
COM_Effectinfo_Clear();
#ifndef SERVERONLY

View file

@ -294,7 +294,7 @@ static int numplanes;
static mplane_t map_planes[MAX_Q2MAP_PLANES+6]; // extra for box hull
static int numleafs = 1; // allow leaf funcs to be called without a map
static mleaf_t map_leafs[MAX_MAP_LEAFS];
static mleaf_t map_leafs[(MAX_MAP_LEAFS+7)/8];
static int emptyleaf;
static int numleafbrushes;

View file

@ -130,7 +130,7 @@ typedef struct {
int (*ParticleTrail) (vec3_t startpos, vec3_t end, int type, int dlkey, trailstate_t **tsk);
int (*RunParticleEffectState) (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk);
void (*RunParticleWeather) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname);
void (*RunParticleCube) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter);
void (*RunParticleCube) (int typenum, vec3_t minb, vec3_t maxb, vec3_t dir_min, vec3_t dir_max, float count, int colour, qboolean gravity, float jitter); //typenum may be P_INVALID
void (*RunParticleEffect) (vec3_t org, vec3_t dir, int color, int count);
void (*RunParticleEffect2) (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count);
void (*RunParticleEffect3) (vec3_t org, vec3_t box, int color, int effect, int count);

View file

@ -91,6 +91,9 @@ int PM_TransformedModelPointContents (model_t *mod, vec3_t p, vec3_t origin, vec
vec3_t p_l, axis[3];
VectorSubtract (p, origin, p_l);
if (!mod->funcs.PointContents)
return FTECONTENTS_EMPTY;
// rotate start and end into the models frame of reference
if (angles[0] || angles[1] || angles[2])
{
@ -117,10 +120,12 @@ int PM_PointContents (vec3_t p)
physent_t *pe;
model_t *pm;
//check world.
pm = pmove.physents[0].model;
if (!pm || pm->needload)
return FTECONTENTS_EMPTY;
pc = pm->funcs.PointContents(pm, NULL, p);
//we need this for e2m2 - waterjumping on to plats wouldn't work otherwise.
for (num = 1; num < pmove.numphysent; num++)
{

View file

@ -305,7 +305,7 @@ void QCBUILTIN PF_getsurfacetexture(pubprogfuncs_t *prinst, struct globalvars_s
if (!model || model->type != mod_brush)
return;
if (surfnum < 0 || surfnum > model->nummodelsurfaces)
if (surfnum < 0 || surfnum >= model->nummodelsurfaces)
return;
surfnum += model->firstmodelsurface;
surf = &model->surfaces[surfnum];
@ -598,6 +598,57 @@ void QCBUILTIN PF_getsurfacepointattribute(pubprogfuncs_t *prinst, struct global
}
}
qbyte qcpvs[(MAX_MAP_LEAFS+7)/8];
//#240 float(vector viewpos, entity viewee) checkpvs (FTE_QC_CHECKPVS)
//note: this requires a correctly setorigined entity.
void QCBUILTIN PF_checkpvs(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *world = prinst->parms->user;
float *viewpos = G_VECTOR(OFS_PARM0);
wedict_t *ent = G_WEDICT(prinst, OFS_PARM1);
if (!world->worldmodel || world->worldmodel->needload)
G_FLOAT(OFS_RETURN) = false;
else
{
//FIXME: Make all alternatives of FatPVS not recalulate the pvs.
//and yeah, this is overkill what with the whole fat thing and all.
world->worldmodel->funcs.FatPVS(world->worldmodel, viewpos, qcpvs, sizeof(qcpvs), false);
G_FLOAT(OFS_RETURN) = world->worldmodel->funcs.EdictInFatPVS(world->worldmodel, &ent->pvsinfo, qcpvs);
}
}
void QCBUILTIN PF_setattachment(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
wedict_t *e = G_WEDICT(prinst, OFS_PARM0);
wedict_t *tagentity = G_WEDICT(prinst, OFS_PARM1);
char *tagname = PR_GetStringOfs(prinst, OFS_PARM2);
world_t *world = prinst->parms->user;
model_t *model;
int tagidx;
tagidx = 0;
if (tagentity != world->edicts && tagname && tagname[0])
{
model = world->Get_CModel(world, tagentity->v->modelindex);
if (model)
{
tagidx = Mod_TagNumForName(model, tagname);
if (tagidx == 0)
Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity), model->name);
}
else
Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): Couldn't load model\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname);
}
e->xv->tag_entity = EDICT_TO_PROG(prinst, tagentity);
e->xv->tag_index = tagidx;
}
#ifndef TERRAIN
void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -2241,13 +2292,15 @@ void QCBUILTIN PF_chr2str (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
//returns character at position X
void QCBUILTIN PF_str2chr (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int err;
char *next;
char *instr = PR_GetStringOfs(prinst, OFS_PARM0);
int ofs = (prinst->callargc>1)?G_FLOAT(OFS_PARM1):0;
if (VMUTF8)
{
if (ofs < 0)
ofs = unicode_charcount(instr, ~0)+ofs;
ofs = unicode_charcount(instr, 1<<30)+ofs;
ofs = unicode_byteofsfromcharofs(instr, ofs);
}
else
@ -2259,7 +2312,7 @@ void QCBUILTIN PF_str2chr (pubprogfuncs_t *prinst, struct globalvars_s *pr_globa
if (ofs && (ofs < 0 || ofs > strlen(instr)))
G_FLOAT(OFS_RETURN) = '\0';
else
G_FLOAT(OFS_RETURN) = VMUTF8?unicode_decode(NULL, instr+ofs, NULL):(unsigned char)instr[ofs];
G_FLOAT(OFS_RETURN) = VMUTF8?unicode_decode(&err, instr+ofs, &next):(unsigned char)instr[ofs];
}
//FTE_STRINGS
@ -2466,7 +2519,7 @@ void QCBUILTIN PF_substring (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
//UTF-8-FIXME: start+length are chars not bytes...
if (VMUTF8)
slen = unicode_charcount(s, ~0);
slen = unicode_charcount(s, 1<<30);
else
slen = strlen(s);
@ -2506,7 +2559,7 @@ void QCBUILTIN PF_substring (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
void QCBUILTIN PF_strlen(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (VMUTF8)
G_FLOAT(OFS_RETURN) = unicode_charcount(PR_GetStringOfs(prinst, OFS_PARM0), ~0);
G_FLOAT(OFS_RETURN) = unicode_charcount(PR_GetStringOfs(prinst, OFS_PARM0), 1<<30);
else
G_FLOAT(OFS_RETURN) = strlen(PR_GetStringOfs(prinst, OFS_PARM0));
}

View file

@ -193,6 +193,8 @@ void QCBUILTIN PF_getsurfaceclippedpoint(pubprogfuncs_t *prinst, struct globalva
void QCBUILTIN PF_getsurfacenumtriangles(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_getsurfacetriangle(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_getsurfacepointattribute(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_checkpvs(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_setattachment(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
#ifndef SKELETALOBJECTS
#define PF_gettaginfo PF_Fixme
@ -479,6 +481,7 @@ pbool QDECL ED_CanFree (edict_t *ed);
#define SOLID_PHASEH2 5 // hexen2 flag - these ents can be freely walked through or something
#define SOLID_CORPSE 5 // non-solid to solid_slidebox entities and itself.
#define SOLID_LADDER 20 //dmw. touch on edge, not blocking. Touching players have different physics. Otherwise a SOLID_TRIGGER
#define SOLID_PORTAL 21 //1: traces always use point-size. 2: various movetypes automatically transform entities. 3: traces that impact portal bbox use a union. 4. traces ignore part of the world within the portal's box
#define SOLID_PHYSICS_BOX 32 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity)
#define SOLID_PHYSICS_SPHERE 33 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity)
#define SOLID_PHYSICS_CAPSULE 34 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity)
@ -542,6 +545,8 @@ typedef enum
VF_SCREENVSIZE = 204,
VF_SCREENPSIZE = 205,
VF_VIEWENTITY = 206,
VF_STATSENTITIY = 207, //the player number for the stats.
VF_SCREENVOFFSET = 208,
} viewflags;
/*FIXME: this should be changed*/

View file

@ -268,7 +268,7 @@ static void BE_CreateSamplerStates(void)
if (flags & SHADER_PASS_NEAREST)
sampdesc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
else
sampdesc.Filter = /*D3D11_FILTER_MIN_MAG_MIP_POINT;D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;*/D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampdesc.Filter = /*D3D11_FILTER_MIN_MAG_MIP_POINT;*/D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;/*D3D11_FILTER_MIN_MAG_MIP_LINEAR*/;
sampdesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
}
if (flags & SHADER_PASS_CLAMP)
@ -2053,6 +2053,7 @@ static void BE_DrawMeshChain_Internal(void)
BE_RenderMeshProgram(shaderstate.shader_rtlight[shaderstate.curlmode], vertcount, idxfirst, idxcount);
break;
case BEM_DEPTHONLY:
if (shaderstate.depthonly->prog)
BE_RenderMeshProgram(shaderstate.depthonly, vertcount, idxfirst, idxcount);
#if 0
shaderstate.lastpasscount = 0;

View file

@ -1689,7 +1689,7 @@
PreprocessorDefinitions="NDEBUG;GLQUAKE;WIN32;_WINDOWS;BOTLIB_STATIC;MULTITHREAD"
StringPooling="true"
ExceptionHandling="0"
BufferSecurityCheck="false"
BufferSecurityCheck="true"
EnableEnhancedInstructionSet="2"
FloatingPointModel="2"
RuntimeTypeInfo="false"

View file

@ -58,7 +58,7 @@ static const char LIGHTPASS_SHADER[] = "\
}\n\
}";
extern cvar_t r_glsl_offsetmapping, r_noportals;
extern cvar_t r_glsl_offsetmapping, r_portalrecursion;
static void BE_SendPassBlendDepthMask(unsigned int sbits);
void GLBE_SubmitBatch(batch_t *batch);
@ -3241,6 +3241,7 @@ void GLBE_SelectMode(backendmode_t mode)
{
extern int gldepthfunc;
// shaderstate.lastuniform = 0;
if (mode != shaderstate.mode)
{
shaderstate.mode = mode;
@ -3488,6 +3489,9 @@ void GLBE_Scissor(srect_t *rect)
*/ qglDisable(GL_SCISSOR_TEST);
if (qglDepthBoundsEXT)
qglDisable(GL_DEPTH_BOUNDS_TEST_EXT);
// if (qglDepthBoundsEXT)
// qglDepthBoundsEXT(0, 1);
}
}
@ -4101,7 +4105,7 @@ void GLBE_SubmitBatch(batch_t *batch)
static void GLBE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist)
{
batch_t *batch, *old;
batch_t *batch, *masklists[2];
int i;
/*attempt to draw portal shaders*/
if (shaderstate.mode == BEM_STANDARD)
@ -4116,34 +4120,33 @@ static void GLBE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist)
if (batch->buildmeshes)
batch->buildmeshes(batch);
/*draw already-drawn portals as depth-only, to ensure that their contents are not harmed*/
GLBE_SelectMode(BEM_DEPTHONLY);
for (old = worldlist[SHADER_SORT_PORTAL]; old && old != batch; old = old->next)
{
if (old->meshes == old->firstmesh)
continue;
GLBE_SubmitBatch(old);
}
if (!old)
{
for (old = dynamiclist; old != batch; old = old->next)
{
if (old->meshes == old->firstmesh)
continue;
GLBE_SubmitBatch(old);
}
}
GLBE_SelectMode(BEM_STANDARD);
GLR_DrawPortal(batch, worldlist, 0);
masklists[0] = worldlist[SHADER_SORT_PORTAL];
masklists[1] = dynamiclist;
GLR_DrawPortal(batch, worldlist, masklists, 0);
/*clear depth again*/
GL_ForceDepthWritable();
qglClear(GL_DEPTH_BUFFER_BIT);
currententity = &r_worldentity;
shaderstate.curtime = shaderstate.updatetime - shaderstate.curentity->shaderTime;
}
}
//make sure the current scene doesn't draw over the portal where its not meant to. clamp depth so the near clip plane doesn't cause problems.
if (gl_config.arb_depth_clamp)
qglEnable(GL_DEPTH_CLAMP_ARB);
for (i = 0; i < 2; i++)
{
for (batch = i?dynamiclist:worldlist[SHADER_SORT_PORTAL]; batch; batch = batch->next)
{
if (batch->meshes == batch->firstmesh)
continue;
/*draw depth only, to mask it off*/
GLBE_SelectMode(BEM_DEPTHONLY);
GLBE_SubmitBatch(batch);
GLBE_SelectMode(BEM_STANDARD);
}
}
if (gl_config.arb_depth_clamp)
qglDisable(GL_DEPTH_CLAMP_ARB);
}
}
@ -4173,6 +4176,16 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
TRACE(("GLBE_SubmitMeshesSortList: shader %s\n", batch->shader->name));
//FIXME:!!
if (!batch->shader)
{
Con_Printf("Shader not set...\n");
if (batch->texture)
batch->shader = R_TextureAnimation(0, batch->texture)->shader;
else
continue;
}
if (batch->shader->flags & SHADER_NODRAW)
continue;
if (batch->shader->flags & SHADER_NODLIGHT)
@ -4236,7 +4249,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
GL_ForceDepthWritable();
qglClearColor(0, 0, 0, 0);
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLR_DrawPortal(batch, cl.worldmodel->batches, 1);
GLR_DrawPortal(batch, cl.worldmodel->batches, NULL, 1);
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
r_refdef.vrect = orect;
r_refdef.pxrect = oprect;
@ -4291,7 +4304,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
GL_ForceDepthWritable();
qglClearColor(0, 0, 0, 0);
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLR_DrawPortal(batch, cl.worldmodel->batches, ((batch->shader->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
GLR_DrawPortal(batch, cl.worldmodel->batches, NULL, ((batch->shader->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
r_refdef.vrect = ovrect;
@ -4299,7 +4312,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
GL_ViewportUpdate();
}
else
GLR_DrawPortal(batch, cl.worldmodel->batches, 3);
GLR_DrawPortal(batch, cl.worldmodel->batches, NULL, 3);
}
if ((batch->shader->flags & SHADER_HASRIPPLEMAP) && gl_config.ext_framebuffer_objects)
{
@ -4333,9 +4346,9 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
// r_refdef.waterheight = DotProduct(batch->mesh[0]->xyz_array[0], batch->mesh[0]->normals_array[0]);
r_refdef.recurse = true; //paranoid, should stop potential infinite loops
r_refdef.recurse+=1; //paranoid, should stop potential infinite loops
GLBE_SubmitMeshes(true, SHADER_SORT_RIPPLE, SHADER_SORT_RIPPLE);
r_refdef.recurse = false;
r_refdef.recurse-=1;
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
r_refdef.vrect = orect;
@ -4354,12 +4367,13 @@ void GLBE_SubmitMeshes (qboolean drawworld, int start, int stop)
{
model_t *model = cl.worldmodel;
int i;
int portaldepth = r_portalrecursion.ival;
for (i = start; i <= stop; i++)
{
if (drawworld)
{
if (i == SHADER_SORT_PORTAL && !r_noportals.ival && !r_refdef.recurse)
if (i == SHADER_SORT_PORTAL && r_refdef.recurse < portaldepth)
GLBE_SubmitMeshesPortals(model->batches, shaderstate.mbatches[i]);
GLBE_SubmitMeshesSortList(model->batches[i]);

View file

@ -24,7 +24,8 @@ int Font_DrawChar(int px, int py, unsigned int charcode);
float Font_DrawScaleChar(float px, float py, unsigned int charcode); /*avoid using*/
void Font_EndString(struct font_s *font);
int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends);
struct font_s *font_conchar;
struct font_s *font_default;
struct font_s *font_console;
struct font_s *font_tiny;
extern unsigned int r2d_be_flags;
@ -171,8 +172,8 @@ static const char *imgs[] =
typedef struct ftfontface_s
{
struct ftfontface_s *next;
struct ftfontface_s **link; //like prev, but not.
struct ftfontface_s *fnext;
struct ftfontface_s **flink; //like prev, but not.
char name[MAX_OSPATH];
int refs;
int activeheight; //needs reconfiguring when different sizes are used
@ -703,7 +704,7 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename)
if (f->ftfaces == MAX_FTFACES)
return false;
for (qface = ftfaces; qface; qface = qface->next)
for (qface = ftfaces; qface; qface = qface->fnext)
{
if (!strcmp(qface->name, fontfilename))
{
@ -814,9 +815,11 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, char *fontfilename)
{
/*success!*/
qface = Z_Malloc(sizeof(*qface));
qface->link = &ftfaces;
qface->next = *qface->link;
*qface->link = qface;
qface->flink = &ftfaces;
qface->fnext = *qface->flink;
*qface->flink = qface;
if (qface->fnext)
qface->fnext->flink = &qface->fnext;
qface->face = face;
qface->membuf = fbase;
qface->refs++;
@ -1336,9 +1339,9 @@ void Font_Free(struct font_s *f)
pFT_Done_Face(qface->face);
if (qface->membuf)
BZ_Free(qface->membuf);
*qface->link = qface->next;
if (qface->next)
qface->next->link = qface->link;
*qface->flink = qface->fnext;
if (qface->fnext)
qface->fnext->flink = qface->flink;
Z_Free(qface);
}
}

View file

@ -199,6 +199,11 @@ qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer)
shaders[i]->defaulttextures.base = R_LoadTexture8Pal24("", tex[i].w, tex[i].h, (qbyte *) texheader + tex[i].offset, (qbyte *) texheader + tex[i].w * tex[i].h + tex[i].offset, IF_NOALPHA|IF_NOGAMMA);
}
model->numskins = texheader->numtextures;
model->skins = ZG_Malloc(&mod->memgroup, model->numskins*sizeof(*model->skins));
memcpy(model->skins, (short *) ((qbyte *) texheader + texheader->skins), model->numskins*sizeof(*model->skins));
if (texmem)
Z_Free(texmem);
@ -665,20 +670,17 @@ void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
hlmodelcache_t *modelc = Mod_Extradata(rent->model);
hlmodel_t model;
int body, m;
short *skins;
int batchid = 0;
static mesh_t bmesh, *mptr = &bmesh;
//general model
model.header = (hlmdl_header_t *) ((char *)modelc + modelc->header);
model.texheader = (hlmdl_header_t *) ((char *)modelc + modelc->texheader);
// model.texheader = (hlmdl_header_t *) ((char *)modelc + modelc->texheader);
model.textures = (hlmdl_tex_t *) ((char *)modelc + modelc->textures);
model.bones = (hlmdl_bone_t *) ((char *)modelc + modelc->bones);
model.bonectls = (hlmdl_bonecontroller_t *) ((char *)modelc + modelc->bonectls);
model.shaders = (shader_t **) ((char *)modelc + modelc->shaders);
skins = (short *) ((qbyte *) model.texheader + model.texheader->skins);
for (body = 0; body < model.header->numbodyparts; body++)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
@ -697,6 +699,8 @@ void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
float tex_h;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if (mesh->skinindex >= modelc->numskins)
continue;
if (batches)
{
@ -707,7 +711,7 @@ void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
if (!b)
return;
shader = model.shaders[skins[mesh->skinindex]];
shader = model.shaders[modelc->skins[mesh->skinindex]];
b->buildmeshes = R_HL_BuildMesh;
b->ent = rent;
b->mesh = NULL;
@ -754,8 +758,8 @@ void R_HalfLife_WalkMeshes(entity_t *rent, batch_t *b, batch_t **batches)
{
if (batchid == b->surf_first)
{
tex_w = 1.0f / model.textures[skins[mesh->skinindex]].w;
tex_h = 1.0f / model.textures[skins[mesh->skinindex]].h;
tex_w = 1.0f / model.textures[modelc->skins[mesh->skinindex]].w;
tex_h = 1.0f / model.textures[modelc->skins[mesh->skinindex]].h;
b->mesh = &mptr;
R_HL_BuildFrame(&model, amodel, b->ent, (short *) ((qbyte *) model.header + mesh->index), tex_w, tex_h, b->mesh[0]);

View file

@ -2138,7 +2138,7 @@ qboolean Mod_LoadSubmodels (lump_t *l)
}
for ( ; j<MAX_MAP_HULLSM ; j++)
out->headnode[j] = 0;
for (j=0 ; j<3 ; j++)
for (j=0 ; j<4 ; j++)
out->hullavailable[j] = true;
for ( ; j<MAX_MAP_HULLSM ; j++)
out->hullavailable[j] = false;
@ -3049,7 +3049,7 @@ void Mod_Batches_Build(mesh_t *meshlist, model_t *mod, void (*build)(model_t *mo
/*assign each mesh to a batch, generating as needed*/
Mod_Batches_Generate(mod);
bmeshes = ZG_Malloc(&loadmodel->memgroup, sizeof(*bmeshes)*mod->nummodelsurfaces*2);
bmeshes = ZG_Malloc(&loadmodel->memgroup, sizeof(*bmeshes)*mod->nummodelsurfaces*R_MAX_RECURSE);
//we now know which batch each surface is in, and how many meshes there are in each batch.
//allocate the mesh-pointer-lists for each batch. *2 for recursion.
@ -3057,7 +3057,7 @@ void Mod_Batches_Build(mesh_t *meshlist, model_t *mod, void (*build)(model_t *mo
for (batch = mod->batches[sortid]; batch != NULL; batch = batch->next)
{
batch->mesh = bmeshes + i;
i += batch->maxmeshes*2;
i += batch->maxmeshes*R_MAX_RECURSE;
}
//store the *surface* into the batch's mesh list (yes, this is an evil cast hack, but at least both are pointers)
for (i=0; i<mod->nummodelsurfaces; i++)
@ -3250,6 +3250,11 @@ qboolean Mod_LoadLeafs (lump_t *l, int lm)
return false;
}
count = l->filelen / sizeof(*in);
if (count > MAX_MAP_LEAFS)
{
Con_Printf (CON_ERROR "Mod_LoadLeafs: %s has more than %i leafs\n",loadmodel->name, MAX_MAP_LEAFS);
return false;
}
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->leafs = out;
@ -3307,6 +3312,11 @@ qboolean Mod_LoadLeafs (lump_t *l, int lm)
return false;
}
count = l->filelen / sizeof(*in);
if (count > MAX_MAP_LEAFS)
{
Con_Printf (CON_ERROR "Mod_LoadLeafs: %s has more than %i leafs\n",loadmodel->name, MAX_MAP_LEAFS);
return false;
}
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->leafs = out;
@ -3364,6 +3374,11 @@ qboolean Mod_LoadLeafs (lump_t *l, int lm)
return false;
}
count = l->filelen / sizeof(*in);
if (count > MAX_MAP_LEAFS)
{
Con_Printf (CON_ERROR "Mod_LoadLeafs: %s has more than %i leafs\n",loadmodel->name, MAX_MAP_LEAFS);
return false;
}
out = ZG_Malloc(&loadmodel->memgroup, count*sizeof(*out));
loadmodel->leafs = out;
@ -4561,7 +4576,7 @@ qboolean QDECL Mod_LoadSpriteModel (model_t *mod, void *buffer)
int numframes;
int size;
dspriteframetype_t *pframetype;
// int rendertype=0;
int rendertype=SPRHL_ALPHATEST;
unsigned char pal[256*4];
int sptype;
@ -4582,7 +4597,7 @@ qboolean QDECL Mod_LoadSpriteModel (model_t *mod, void *buffer)
if (LittleLong(pin->version) == SPRITEHL_VERSION)
{
pin = (dsprite_t*)((char*)pin + 4);
/*rendertype =*/ LittleLong (pin->type); //not sure what the values mean.
rendertype = LittleLong (pin->type); //not sure what the values mean.
}
numframes = LittleLong (pin->numframes);
@ -4592,6 +4607,22 @@ qboolean QDECL Mod_LoadSpriteModel (model_t *mod, void *buffer)
psprite = ZG_Malloc(&loadmodel->memgroup, size);
mod->meshinfo = psprite;
switch(sptype)
{
case SPR_VP_PARALLEL_UPRIGHT:
case SPR_FACING_UPRIGHT:
case SPR_VP_PARALLEL:
case SPR_ORIENTED:
// case SPR_VP_PARALLEL_ORIENTED:
// case SPRDP_LABEL:
// case SPRDP_LABEL_SCALE:
// case SPRDP_OVERHEAD:
break;
default:
Con_DPrintf(CON_ERROR "%s has unsupported sprite type %i\n", mod->name, sptype);
sptype = SPR_VP_PARALLEL;
break;
}
psprite->type = sptype;
psprite->maxwidth = LittleLong (pin->width);
@ -4621,13 +4652,28 @@ qboolean QDECL Mod_LoadSpriteModel (model_t *mod, void *buffer)
return false;
}
for (i = 0; i < 256; i++)
if (rendertype == SPRHL_INDEXALPHA)
{
Con_Printf(CON_ERROR "%s: SPRHL_INDEXALPHA sprites are not supported\n", mod->name);
return false;
}
else
{
for (i = 0; i < 256; i++)
{//FIXME: bgr?
pal[i*4+0] = *src++;
pal[i*4+1] = *src++;
pal[i*4+2] = *src++;
pal[i*4+3] = 255;
}
if (rendertype == SPRHL_ALPHATEST)
{
pal[255*4+0] = 0;
pal[255*4+1] = 0;
pal[255*4+2] = 0;
pal[255*4+3] = 0;
}
}
pframetype = (dspriteframetype_t *)(src);
}

View file

@ -107,9 +107,9 @@ once a batch is known to the backend for that frame, its shader, vbo, ent, light
typedef struct batch_s
{
mesh_t **mesh; /*list must be long enough for all surfaces that will form part of this batch times two, for mirrors/portals*/
unsigned int firstmesh;
unsigned int meshes;
struct batch_s *next;
unsigned int meshes;
unsigned int firstmesh;
shader_t *shader;
struct vbo_s *vbo;
@ -126,6 +126,9 @@ typedef struct batch_s
struct texnums_s *skin;
void (*buildmeshes)(struct batch_s *b);
#if R_MAX_RECURSE > 2
unsigned int recursefirst[R_MAX_RECURSE-2]; //fixme: should thih, firstmesh, and meshes be made ushorts?
#endif
/*caller-use, not interpreted by backend*/
union
{
@ -830,7 +833,7 @@ typedef struct model_s
{
char name[MAX_QPATH];
int datasequence;
qboolean needload; // bmodels and sprites don't cache normally
int needload; // if needload is set, the model is not currently valid. 0=false, 1=true, 2 means it was never valid (and please don't spam about it still being invalid). most code should treat this as a simple boolean.
qboolean tainted;
qboolean pushdepth; // bsp submodels have this flag set so you don't get z fighting on co-planar surfaces.

View file

@ -743,7 +743,7 @@ static float sgn(float a)
if (a < 0.0F) return (-1.0F);
return (0.0F);
}
void R_ObliqueNearClip(mplane_t *wplane)
void R_ObliqueNearClip(float *viewmat, mplane_t *wplane)
{
float f;
vec4_t q, c;
@ -751,9 +751,9 @@ void R_ObliqueNearClip(mplane_t *wplane)
vec4_t vplane;
//convert world plane into view space
Matrix4x4_CM_Transform3x3(r_refdef.m_view, wplane->normal, vplane);
Matrix4x4_CM_Transform3x3(viewmat, wplane->normal, vplane);
VectorScale(wplane->normal, wplane->dist, ping);
Matrix4x4_CM_Transform3(r_refdef.m_view, ping, pong);
Matrix4x4_CM_Transform3(viewmat, ping, pong);
vplane[3] = -DotProduct(pong, vplane);
// Calculate the clip-space corner point opposite the clipping plane
@ -776,17 +776,17 @@ void R_ObliqueNearClip(mplane_t *wplane)
r_refdef.m_projection[10] = c[2] + 1.0F;
r_refdef.m_projection[14] = c[3];
}
void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2], int portaltype)
{
entity_t *view;
// GLdouble glplane[4];
plane_t plane;
float vmat[16];
refdef_t oldrefdef;
mesh_t *mesh = batch->mesh[batch->firstmesh];
int sort;
qbyte newvis[(MAX_MAP_LEAFS+7)/8];
if (r_refdef.recurse)
if (r_refdef.recurse >= R_MAX_RECURSE-1)
return;
if (!mesh->normals_array)
@ -806,14 +806,14 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
if (DotProduct(r_refdef.vieworg, plane.normal)-plane.dist > batch->shader->portaldist)
return;
}
//if we're behind it, then also don't draw anything.
if (DotProduct(r_refdef.vieworg, plane.normal)-plane.dist < 0)
//if we're behind it, then also don't draw anything. for our purposes, behind is when the entire near clipplane is behind.
if (DotProduct(r_refdef.vieworg, plane.normal)-plane.dist < -gl_mindist.value)
return;
TRACE(("GLR_DrawPortal: portal type %i\n", portaltype));
oldrefdef = r_refdef;
r_refdef.recurse = true;
r_refdef.recurse+=1;
r_refdef.externalview = true;
@ -823,6 +823,7 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
//fixme: pvs is surely wrong?
r_refdef.flipcull ^= SHADER_CULL_FLIP;
R_MirrorMatrix(&plane);
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
break;
case 2: /*fbo refraction (fucked depth, working clip plane)*/
@ -876,10 +877,30 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
}
// memset(newvis, 0xff, pvsbytes);
}
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
break;
default: /*q3 portal*/
if (batch->ent != &r_worldentity)
case 0: /*q3 portal*/
default:
if (CSQC_SetupToRenderPortal(batch->ent->keynum))
{
plane_t oplane = plane;
float ivmat[16], trmat[16];
//transform the old surface plane into the new view matrix
Matrix4_Invert(r_refdef.m_view, ivmat);
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
Matrix4_Multiply(ivmat, vmat, trmat);
plane.normal[0] = (oplane.normal[0] * trmat[0] + oplane.normal[1] * trmat[4] + oplane.normal[2] * trmat[8]);
plane.normal[1] = (oplane.normal[0] * trmat[1] + oplane.normal[1] * trmat[5] + oplane.normal[2] * trmat[9]);
plane.normal[2] = (oplane.normal[0] * trmat[2] + oplane.normal[1] * trmat[6] + oplane.normal[2] * trmat[10]);
plane.dist = -oplane.dist + trmat[12]*oplane.normal[0] + trmat[13]*oplane.normal[1] + trmat[14]*oplane.normal[2];
VectorNegate(plane.normal, plane.normal);
if (Cvar_Get("temp_useplaneclip", "1", 0, "temp")->ival)
portaltype = 1; //make sure the near clipplane is used.
}
else if (batch->ent != &r_worldentity)
{
float d;
view = batch->ent;
@ -887,11 +908,13 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
d-= 0.1; //nudge it past.
VectorAdd(r_refdef.vieworg, view->oldorigin, r_refdef.vieworg); //trivial offset for the warpzone.
VectorMA(r_refdef.vieworg, -d, plane.normal, r_refdef.pvsorigin); //clip the pvs origin to the plane.
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
}
else if (!(view = R_NearestPortal(&plane)) || VectorCompare(view->origin, view->oldorigin))
{
r_refdef.flipcull ^= SHADER_CULL_FLIP;
R_MirrorMatrix(&plane);
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
}
else
{
@ -922,35 +945,23 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
TransformDir(vpn, paxis, vaxis, vpn);
TransformDir(vright, paxis, vaxis, vright);
TransformDir(vup, paxis, vaxis, vup);
Matrix4x4_CM_ModelViewMatrixFromAxis(vmat, vpn, vright, vup, r_refdef.vieworg);
}
break;
}
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg);
VectorAngles(vpn, vup, r_refdef.viewangles);
VectorCopy(r_refdef.vieworg, r_origin);
/*FIXME: the batch stuff should be done in renderscene*/
/*fixup the first mesh index*/
for (sort = 0; sort < SHADER_SORT_COUNT; sort++)
for (batch = blist[sort]; batch; batch = batch->next)
{
batch->firstmesh = batch->meshes;
}
GL_CullFace(0);
/*FIXME: can we get away with stenciling the screen?*/
/*Add to frustum culling instead of clip planes?*/
// if (qglClipPlane)
// {
// glplane[0] = -plane.normal[0];
// glplane[1] = -plane.normal[1];
// glplane[2] = -plane.normal[2];
// glplane[3] = plane.dist;
// qglClipPlane(GL_CLIP_PLANE0, glplane);
// qglEnable(GL_CLIP_PLANE0);
// }
/* if (qglClipPlane)
{
GLdouble glplane[4];
glplane[0] = -plane.normal[0];
glplane[1] = -plane.normal[1];
glplane[2] = -plane.normal[2];
glplane[3] = plane.dist;
qglClipPlane(GL_CLIP_PLANE0, glplane);
qglEnable(GL_CLIP_PLANE0);
}*/
if (r_refdef.frustum_numplanes < MAXFRUSTUMPLANES)
{
r_refdef.frustum[r_refdef.frustum_numplanes].normal[0] = plane.normal[0];
@ -959,18 +970,56 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
r_refdef.frustum[r_refdef.frustum_numplanes].dist = plane.dist + 0.01;
if (portaltype == 1 || portaltype == 2)
R_ObliqueNearClip(&r_refdef.frustum[r_refdef.frustum_numplanes]);
R_ObliqueNearClip(vmat, &r_refdef.frustum[r_refdef.frustum_numplanes]);
r_refdef.frustum_numplanes++;
}
GL_CullFace(0);
if (depthmasklist)
{
/*draw already-drawn portals as depth-only, to ensure that their contents are not harmed*/
/*we can only do this AFTER the oblique perspective matrix is calculated, to avoid depth inconsistancies, while we still have the old view matrix*/
int i;
batch_t *dmask = NULL;
if (qglLoadMatrixf)
{
qglMatrixMode(GL_PROJECTION);
qglLoadMatrixf(r_refdef.m_projection);
}
currententity = NULL;
if (gl_config.arb_depth_clamp)
qglEnable(GL_DEPTH_CLAMP_ARB);
GL_ForceDepthWritable();
GLBE_SelectMode(BEM_DEPTHONLY);
for (i = 0; i < 2; i++)
{
for (dmask = depthmasklist[i]; dmask; dmask = dmask->next)
{
if (dmask == batch)
continue;
if (dmask->meshes == dmask->firstmesh)
continue;
GLBE_SubmitBatch(dmask);
}
}
GLBE_SelectMode(BEM_STANDARD);
if (gl_config.arb_depth_clamp)
qglDisable(GL_DEPTH_CLAMP_ARB);
currententity = NULL;
}
//now determine the stuff the backend will use.
memcpy(r_refdef.m_view, vmat, sizeof(float)*16);
VectorAngles(vpn, vup, r_refdef.viewangles);
r_refdef.viewangles[0] *= -1;
VectorCopy(r_refdef.vieworg, r_origin);
//FIXME: R_RenderScene is currently overriding r_refdef.frustum_numplanes and discarding our new near plane, resulting in wasted draw calls.
R_RenderScene();
// if (qglClipPlane)
// qglDisable(GL_CLIP_PLANE0);
for (sort = 0; sort < SHADER_SORT_COUNT; sort++)
for (batch = blist[sort]; batch; batch = batch->next)
{
batch->firstmesh = 0;
}
r_refdef = oldrefdef;
/*broken stuff*/
@ -994,6 +1043,7 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
#ifdef warningmsg
#pragma warningmsg("warning: there's a bug with rtlights in portals, culling is broken or something. May also be loading the wrong matrix")
#endif
currententity = NULL;
}

View file

@ -247,7 +247,8 @@ void GLR_ReInit (void)
R_InitBloomTextures();
}
/*
#if 1
typedef struct
{
long offset; // Position of the entry in WAD
@ -266,57 +267,66 @@ typedef struct
} wad2_t;
void R_MakeTexWad_f(void)
{
//this function is written as little endian. nothing will fix that.
miptex_t dummymip = {"", 0, 0, {0, 0, 0, 0}};
wad2_t wad2 = {"WAD2",0,0};
wad2entry_t entry[2048];
int entries = 0, i;
FILE *f;
vfsfile_t *f;
char base[128];
char *texname;
// qbyte b;
float scale;
qboolean hasalpha;
int width, height;
qbyte *buf, *outmip;
qbyte *mip, *stack;
// WIN32_FIND_DATA fd;
// HANDLE h;
char *wadname = Cmd_Argv(1);
char *imagename = Cmd_Argv(2);
float scale = atof(Cmd_Argv(3));
scale = atof(Cmd_Argv(2));
if (!scale)
scale = 2;
// h = FindFirstFile(va("%s/textures/ *.tga", com_gamedir), &fd); //if this is uncommented, clear that space... (gcc warning fix)
if (!shader)
if (!*wadname || !*imagename)
return;
f=FS_OpenVFS(wadname, "w+b", FS_GAMEONLY);
if (!f)
return;
mip = BZ_Malloc(1024*1024);
// initbuf = BZ_Malloc(1024*1024*4);
stack = BZ_Malloc(1024*1024*4+1024);
f=fopen(va("%s/shadrtex.wad", com_gamedir), "wb");
fwrite(&wad2, 1, sizeof(wad2_t), f);
for (shad = shader; shad; shad=shad->next)
VFS_SEEK(f, 0);
VFS_READ(f, &wad2, sizeof(wad2_t));
VFS_SEEK(f, wad2.offset);
VFS_READ(f, entry, sizeof(entry[0]) * wad2.num);
//find the end of the data.
wad2.offset = sizeof(wad2_t);
for (entries = 0; entries < wad2.num; entries++)
if (wad2.offset < entry[entries].offset + entry[entries].dsize)
wad2.offset = entry[entries].offset + entry[entries].dsize;
VFS_SEEK(f, wad2.offset);
{
texname = shad->editorname;
if (!*texname)
continue;
COM_StripExtension(shad->name, base);
COM_StripExtension(imagename, base, sizeof(base));
base[15]=0;
for (i =0; i < entries; i++)
if (!strcmp(entry[entries].name, base))
if (!stricmp(entry[i].name, base))
break;
if (i != entries)
{
Con_Printf("Skipped %s - duplicated shrunken name\n", texname);
continue;
}
entry[entries].offset = ftell(f);
entry[entries].dsize = entry[entries].size = 0;
entry[entries].type = TYP_MIPTEX;
entry[entries].cmprs = 0;
entry[entries].dummy = 0;
strcpy(entry[entries].name, base);
Con_Printf("Replacing %s, you'll want to compact your wad at some point.\n", base); //this will leave a gap. we don't support compacting.
else
entries++;
entry[i].offset = VFS_TELL(f);
entry[i].dsize = entry[i].size = 0;
entry[i].type = TYP_MIPTEX;
entry[i].cmprs = 0;
entry[i].dummy = 0;
strcpy(entry[i].name, base);
strcpy(dummymip.name, base);
@ -330,28 +340,28 @@ void R_MakeTexWad_f(void)
char *path[] ={
"%s",
"override/%s.tga",
"override/%s.pcx",
"textures/%s.png",
"textures/%s.tga",
"%s.png",
"%s.tga",
"progs/%s"};
for (h = 0, buf=NULL; h < sizeof(path)/sizeof(char *); h++)
{
buf = COM_LoadStackFile(va(path[h], texname), stack, 1024*1024*4+1024);
buf = COM_LoadStackFile(va(path[h], imagename), stack, 1024*1024*4+1024);
if (buf)
break;
}
if (!buf)
{
Con_Printf("Failed to find texture \"%s\"\n", texname);
continue;
}
data = ReadTargaFile(buf, com_filesize, &width, &height, false);
if (buf)
data = Read32BitImageFile(buf, com_filesize, &width, &height, &hasalpha, imagename);
else
data = NULL;
if (!data)
{
BZ_Free(data);
Con_Printf("Skipped %s - file type not supported (bad bpp?)\n", texname);
continue;
data = Z_Malloc(16*16*4);
width = 16;
height = 16;
}
dummymip.width = (int)(width/scale) & ~0xf;
@ -360,6 +370,10 @@ if (!data)
dummymip.width=16;
if (dummymip.height<=0)
dummymip.height=16;
if (dummymip.width > 1024)
dummymip.width = 1024;
if (dummymip.height > 1024)
dummymip.height = 1024;
dummymip.offsets[0] = sizeof(dummymip);
dummymip.offsets[1] = dummymip.offsets[0]+dummymip.width*dummymip.height;
@ -371,7 +385,7 @@ if (!data)
yi = (float)height/dummymip.height;
fwrite(&dummymip, 1, sizeof(dummymip), f);
VFS_WRITE(f, &dummymip, sizeof(dummymip));
outmip=mip;
for (outmip=mip, y = 0; y < height; y+=yi)
for (x = 0; x < width; x+=xi)
@ -380,7 +394,7 @@ if (!data)
data[(int)(x+y*width)*4+1],
data[(int)(x+y*width)*4+2]);
}
fwrite(mip, dummymip.width, dummymip.height, f);
VFS_WRITE(f, mip, dummymip.width * dummymip.height);
for (outmip=mip, y = 0; y < height; y+=yi*2)
for (x = 0; x < width; x+=xi*2)
{
@ -388,7 +402,7 @@ if (!data)
data[(int)(x+y*width)*4+1],
data[(int)(x+y*width)*4+2]);
}
fwrite(mip, dummymip.width/2, dummymip.height/2, f);
VFS_WRITE(f, mip, (dummymip.width/2) * (dummymip.height/2));
for (outmip=mip, y = 0; y < height; y+=yi*4)
for (x = 0; x < width; x+=xi*4)
{
@ -396,7 +410,7 @@ if (!data)
data[(int)(x+y*width)*4+1],
data[(int)(x+y*width)*4+2]);
}
fwrite(mip, dummymip.width/4, dummymip.height/4, f);
VFS_WRITE(f, mip, (dummymip.width/4) * (dummymip.height/4));
for (outmip=mip, y = 0; y < height; y+=yi*8)
for (x = 0; x < width; x+=xi*8)
{
@ -404,30 +418,29 @@ if (!data)
data[(int)(x+y*width)*4+1],
data[(int)(x+y*width)*4+2]);
}
fwrite(mip, dummymip.width/8, dummymip.height/8, f);
VFS_WRITE(f, mip, (dummymip.width/8) * (dummymip.height/8));
BZ_Free(data);
}
entries++;
entry[i].dsize = VFS_TELL(f) - entry[i].offset;
Con_Printf("Added %s\n", base);
GLSCR_UpdateScreen();
}
wad2.offset = ftell(f);
wad2.offset = VFS_TELL(f);
wad2.num = entries;
fwrite(entry, entries, sizeof(wad2entry_t), f);
fseek(f, 0, SEEK_SET);
fwrite(&wad2, 1, sizeof(wad2_t), f);
fclose(f);
VFS_WRITE(f, entry, entries*sizeof(wad2entry_t));
VFS_SEEK(f, 0);
VFS_WRITE(f, &wad2, sizeof(wad2_t));
VFS_CLOSE(f);
BZ_Free(mip);
// BZ_Free(initbuf);
BZ_Free(stack);
Con_Printf("Written %i mips to textures.wad\n", entries);
Con_Printf("%s now has %i entries\n", wadname, entries);
}
*/
#endif
void GLR_TimeRefresh_f (void);
extern cvar_t v_contrast, r_drawflat;
@ -467,7 +480,7 @@ void GLR_Init (void)
{
Cmd_AddCommand ("timerefresh", GLR_TimeRefresh_f);
// Cmd_AddCommand ("makewad", R_MakeTexWad_f);
Cmd_AddCommand ("makewad", R_MakeTexWad_f);
// Cvar_Hook(&r_floortexture, GLR_Floortexture_Callback);
// Cvar_Hook(&r_walltexture, GLR_Walltexture_Callback);

View file

@ -71,6 +71,8 @@ void GLSCR_UpdateScreen (void)
vid.numpages = 2 + vid_triplebuffer.value;
R2D_Font_Changed();
if (scr_disabled_for_loading)
{
extern float scr_disabled_time;

View file

@ -489,6 +489,7 @@ static void Shader_ParseVector(shader_t *shader, char **ptr, vec3_t v)
char *scratch;
char *token;
qboolean bracket;
qboolean fromcvar = false;
token = Shader_ParseString(ptr);
if (*token == '$')
@ -507,6 +508,7 @@ static void Shader_ParseVector(shader_t *shader, char **ptr, vec3_t v)
scratch = var->string;
token = Shader_ParseString( ptr);
fromcvar = true;
}
if (!Q_stricmp (token, "("))
{
@ -522,12 +524,22 @@ static void Shader_ParseVector(shader_t *shader, char **ptr, vec3_t v)
bracket = false;
v[0] = atof ( token );
v[1] = Shader_ParseFloat (shader, ptr );
token = Shader_ParseString ( ptr );
if ( !token[0] ) {
v[2] = 0;
} else if ( token[strlen(token)-1] == ')' ) {
v[1] = fromcvar?v[0]:0;
} else if (bracket && token[strlen(token)-1] == ')' ) {
bracket = false;
token[strlen(token)-1] = 0;
v[1] = atof ( token );
} else {
v[1] = atof ( token );
}
token = Shader_ParseString ( ptr );
if ( !token[0] ) {
v[2] = fromcvar?v[1]:0;
} else if (bracket && token[strlen(token)-1] == ')' ) {
token[strlen(token)-1] = 0;
v[2] = atof ( token );
} else {

View file

@ -224,6 +224,8 @@ typedef struct //this is stored as the cache. an hlmodel_t is generated when dra
int bones;
int bonectls;
int shaders;
short *skins;
int numskins;
} hlmodelcache_t;
/* HL mathlib prototypes: */

View file

@ -230,6 +230,7 @@ char *QC_ucase(char *str)
return s;
}
//#define STACKTRACE
void PDECL PR_StackTrace (pubprogfuncs_t *ppf)
{
progfuncs_t *progfuncs = (progfuncs_t *)ppf;
@ -282,18 +283,18 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf)
}
#ifdef STACKTRACE
if (i == pr_depth)
for (arg = 0; arg < f->locals; arg++)
{
ddef16_t *local;
local = ED_GlobalAtOfs16(progfuncs, f->parm_start+arg);
if (!local)
{
printf(" ofs %i: %f : %i\n", f->parm_start+arg, *(float *)(globalbase - f->locals+arg), *(int *)(globalbase - f->locals+arg) );
//printf(" ofs %i: %f : %i\n", f->parm_start+arg, *(float *)(globalbase - f->locals+arg), *(int *)(globalbase - f->locals+arg) );
}
else
{
printf(" %s: %s\n", local->s_name+progfuncs->stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase - f->locals+arg)));
printf(" %s: %s\n", local->s_name+progfuncs->funcs.stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase - f->locals+arg), false));
if (local->type == ev_vector)
arg+=2;
}
@ -427,7 +428,7 @@ int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsn
pr_depth--;
PR_StackTrace (&progfuncs->funcs);
printf ("stack overflow on call to %s\n", progfuncs->funcs.stringtable+f->s_name);
printf ("stack overflow on call to %s (depth %i)\n", progfuncs->funcs.stringtable+f->s_name, pr_depth);
//comment this out if you want the progs to try to continue anyway (could cause infinate loops)
PR_AbortStack(&progfuncs->funcs);

View file

@ -1,7 +1,8 @@
#define PROGSUSED
#include "progsint.h"
#define HunkAlloc BADGDFG sdfhhsf FHS
//#define MAPPING_DEBUG
//#define MAPPING_PARANOID //may actually break unions, so beware.
void PR_SetBuiltins(int type);
/*
@ -243,7 +244,9 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, char *name
if (!name) //engine can use this to offset all progs fields
{ //which fixes constant field offsets (some ktpro arrays)
progfuncs->funcs.fieldadjust = fields_size/4;
// printf("FIELD ADJUST: %i %i %i\n", progfuncs->funcs.fieldadjust, fields_size, (int)fields_size/4);
#ifdef MAPPING_DEBUG
printf("FIELD ADJUST: %i %i %i\n", progfuncs->funcs.fieldadjust, fields_size, (int)fields_size/4);
#endif
return 0;
}
@ -273,7 +276,9 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, char *name
if (prinst.field[i].progsofs == -1)
prinst.field[i].progsofs = progsofs;
// printf("Dupfield %s %i -> %i\n", name, prinst.field[i].progsofs,prinst.field[i].ofs);
#ifdef MAPPING_DEBUG
printf("Dupfield %s %i -> %i\n", name, prinst.field[i].progsofs,prinst.field[i].ofs);
#endif
return prinst.field[i].ofs-progfuncs->funcs.fieldadjust; //got a match
}
}
@ -315,7 +320,8 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, char *name
{ //the engine is setting up a list of required field indexes.
//paranoid checking of the offset.
/* for (i = 0; i < numfields-1; i++)
#if 0//def MAPPING_PARANOID
for (i = 0; i < numfields-1; i++)
{
if (field[i].ofs == ((unsigned)engineofs)/4)
{
@ -327,7 +333,8 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, char *name
else
Sys_Error("Duplicated offset");
}
}*/
}
#endif
if (engineofs&3)
Sys_Error("field %s is %i&3", name, (int)engineofs);
prinst.field[fnum].ofs = ofs = engineofs/4;
@ -343,19 +350,25 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, char *name
{
if (prinst.field[i].progsofs == (unsigned)progsofs)
{
// printf("found union field %s %i -> %i\n", prinst.field[i].name, prinst.field[i].progsofs, prinst.field[i].ofs);
#ifdef MAPPING_DEBUG
printf("found union field %s %i -> %i\n", prinst.field[i].name, prinst.field[i].progsofs, prinst.field[i].ofs);
#endif
prinst.field[fnum].ofs = ofs = prinst.field[i].ofs;
break;
}
if (prinst.field[i].type == ev_vector && prinst.field[i].progsofs+1 == (unsigned)progsofs)
{
// printf("found union field %s %i -> %i\n", prinst.field[i].name, prinst.field[i].progsofs+1, prinst.field[i].ofs+1);
#ifdef MAPPING_DEBUG
printf("found union field %s %i -> %i\n", prinst.field[i].name, prinst.field[i].progsofs+1, prinst.field[i].ofs+1);
#endif
prinst.field[fnum].ofs = ofs = prinst.field[i].ofs+1;
break;
}
if (prinst.field[i].type == ev_vector && prinst.field[i].progsofs+2 == (unsigned)progsofs)
{
// printf("found union field %s %i -> %i\n", prinst.field[i].name, prinst.field[i].progsofs+2, prinst.field[i].ofs+2);
#ifdef MAPPING_DEBUG
printf("found union field %s %i -> %i\n", prinst.field[i].name, prinst.field[i].progsofs+2, prinst.field[i].ofs+2);
#endif
prinst.field[fnum].ofs = ofs = prinst.field[i].ofs+2;
break;
}
@ -372,7 +385,9 @@ int PDECL QC_RegisterFieldVar(pubprogfuncs_t *ppf, unsigned int type, char *name
prinst.field[fnum].progsofs = progsofs;
// printf("Field %s %i -> %i\n", name, prinst.field[fnum].progsofs,prinst.field[fnum].ofs);
#ifdef MAPPING_DEBUG
printf("Field %s %i -> %i\n", name, prinst.field[fnum].progsofs,prinst.field[fnum].ofs);
#endif
//we've finished setting the structure
return ofs - progfuncs->funcs.fieldadjust;
@ -410,9 +425,13 @@ void PDECL QC_AddSharedFieldVar(pubprogfuncs_t *ppf, int num, char *stringtable)
{
if (!strcmp(pr_fielddefs16[i].s_name+stringtable, pr_globaldefs16[num].s_name+stringtable))
{
// int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
#ifdef MAPPING_DEBUG
int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
#endif
*(int *)&pr_globals[pr_globaldefs16[num].ofs] = QC_RegisterFieldVar(&progfuncs->funcs, pr_fielddefs16[i].type, pr_globaldefs16[num].s_name+stringtable, -1, *(int *)&pr_globals[pr_globaldefs16[num].ofs]);
// printf("Field=%s global %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(volatile int *)&pr_globals[pr_globaldefs16[num].ofs]);
#ifdef MAPPING_DEBUG
printf("Field=%s global %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(volatile int *)&pr_globals[pr_globaldefs16[num].ofs]);
#endif
return;
}
}
@ -422,9 +441,13 @@ void PDECL QC_AddSharedFieldVar(pubprogfuncs_t *ppf, int num, char *stringtable)
o = prinst.field[i].progsofs;
if (o == *(unsigned int *)&pr_globals[pr_globaldefs16[num].ofs])
{
// int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
#ifdef MAPPING_DEBUG
int old = *(int *)&pr_globals[pr_globaldefs16[num].ofs];
#endif
*(int *)&pr_globals[pr_globaldefs16[num].ofs] = prinst.field[i].ofs-progfuncs->funcs.fieldadjust;
// printf("Field global=%s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(volatile int *)&pr_globals[pr_globaldefs16[num].ofs]);
#ifdef MAPPING_DEBUG
printf("Field global=%s %i -> %i\n", pr_globaldefs16[num].s_name+stringtable, old, *(volatile int *)&pr_globals[pr_globaldefs16[num].ofs]);
#endif
return;
}
}

View file

@ -111,7 +111,7 @@ int reorganisefields;
//pr_exec.c
#define MAX_STACK_DEPTH 64
#define MAX_STACK_DEPTH 1024 //insanely high value requried for xonotic.
prstack_t pr_stack[MAX_STACK_DEPTH];
#define pr_stack prinst.pr_stack
int pr_depth;

View file

@ -256,7 +256,7 @@ typedef union eval_s
#define PR_SaveEnts(pf, buf, size, maxsize, mode) (*pf->save_ents) (pf, buf, size, maxsize, mode)
#define EDICT_NUM(pf, num) (*pf->EDICT_NUM) (pf, num)
#define NUM_FOR_EDICT(pf, e) (*pf->NUM_FOR_EDICT) (pf, e)
#define NUM_FOR_EDICT(pf, e) (*pf->NUM_FOR_EDICT) (pf, (struct edict_s*)(e))
#define SetGlobalEdict(pf, ed, ofs) (*pf->SetGlobalEdict) (pf, ed, ofs)
#define PR_VarString(pf,first) (*pf->VarString) (pf,first)

View file

@ -318,6 +318,7 @@ typedef struct QCC_type_s
unsigned int size;
pbool typedefed:1;
pbool vargs:1;
pbool vargcount:1;
char *name;
char *aname;
} QCC_type_t;
@ -330,6 +331,7 @@ typedef struct temp_s {
#ifdef WRITEASM
struct QCC_def_s *lastfunc;
#endif
int laststatement;
struct temp_s *next;
int used;
unsigned int size;
@ -347,6 +349,7 @@ typedef struct QCC_def_s
gofs_t ofs;
struct QCC_def_s *scope; // function the var was defined in, or NULL
struct QCC_def_s *deftail; // arrays and structs create multiple globaldef objects providing different types at the different parts of the single object (struct), or alternative names (vectors). this allows us to correctly set the const type based upon how its initialised.
struct QCC_def_s *generatedfor;
int initialized; // 1 when a declaration included "= immediate"
int constant; // 1 says we can use the value over and over again
@ -445,8 +448,10 @@ typedef struct
char *value;
char params[MAXCONSTANTPARAMS][MAXCONSTANTPARAMLENGTH];
int numparams;
pbool used;
pbool inside;
pbool used:1;
pbool inside:1;
pbool evil:1;
pbool varg:1;
int namelen;
} CompilerConstant_t;
@ -629,6 +634,7 @@ enum {
WARN_UNDEFNOTDEFINED,
WARN_PRECOMPILERMESSAGE,
WARN_TOOMANYPARAMETERSFORFUNC,
WARN_TOOMANYPARAMETERSVARARGS,
WARN_STRINGTOOLONG,
WARN_BADTARGET,
WARN_BADPRAGMA,
@ -696,7 +702,6 @@ enum {
ERR_TOOMANYCASES,
ERR_TOOMANYLABELS,
ERR_TOOMANYOPENFILES,
ERR_TOOMANYPARAMETERSVARARGS,
ERR_TOOMANYTOTALPARAMETERS,
//these are probably yours, or qcc being fussy.
@ -835,6 +840,7 @@ void QCC_PR_PrintDefs (void);
void QCC_PR_SkipToSemicolon (void);
extern char *pr_parm_argcount_name;
#define MAX_EXTRA_PARMS 128
#ifdef MAX_EXTRA_PARMS
extern char pr_parm_names[MAX_PARMS+MAX_EXTRA_PARMS][MAX_NAME];
@ -862,8 +868,8 @@ extern QCC_string_t s_file; // filename for function definition
extern QCC_def_t def_ret, def_parms[MAX_PARMS];
void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname);
void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname);
void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *thearray, char *arrayname);
void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *thearray, char *arrayname);
void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype);
void PostCompile(void);

View file

@ -886,11 +886,11 @@ static char *decodeUTF(int type, unsigned char *inputf, unsigned int inbytes, in
{
case UTF16LE:
w = 2;
maxperchar = 3;
maxperchar = 4;
break;
case UTF16BE:
w = 2;
maxperchar = 3;
maxperchar = 4;
break;
case UTF32LE:
w = 4;
@ -910,14 +910,25 @@ static char *decodeUTF(int type, unsigned char *inputf, unsigned int inbytes, in
{
switch(type)
{
default:
case UTF16LE:
inc = *inputf++;
inc|= (*inputf++)<<8;
break;
case UTF16BE:
inc = (*inputf++)<<8;
inc|= *inputf++;
inc = inputf[type==UTF16BE];
inc|= inputf[type==UTF16LE]<<8;
inputf += 2;
//handle surrogates
if (inc >= 0xd800u && inc < 0xdc00u && i+1 < chars)
{
unsigned int l;
l = inputf[type==UTF16BE];
l|= inputf[type==UTF16LE]<<8;
if (l >= 0xdc00u && l < 0xe000u)
{
inputf+=2;
inc = ((inc & 0x3ffu)<<10) | (l & 0x3ffu) + 0x10000;
i++;
}
}
break;
case UTF32LE:
inc = *inputf++;

View file

@ -146,6 +146,7 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign, p
QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *newself, QCC_def_t *func, QCC_def_t *arglist[], QCC_type_t *argtypelist[], int argcount);
void QCC_Marshal_Locals(int firststatement, int laststatement);
QCC_def_t *QCC_PR_ParseArrayPointer (QCC_def_t *d, pbool allowarrayassign, pbool makestructpointers);
QCC_def_t *QCC_LoadFromArray(QCC_def_t *base, QCC_def_t *index, QCC_type_t *t, pbool preserve);
QCC_ref_t *QCC_DefToRef(QCC_ref_t *ref, QCC_def_t *def); //ref is a buffer to write into, to avoid excessive allocs
QCC_def_t *QCC_RefToDef(QCC_ref_t *ref, pbool freetemps);
@ -1301,6 +1302,27 @@ static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted)
/*impossible*/
return -1;
}
QCC_def_t *QCC_SupplyConversionForAssignment(QCC_def_t *to, QCC_def_t *from, etype_t wanted, pbool fatal)
{
extern char *basictypenames[];
int o;
o = QCC_ShouldConvert(from, wanted);
if (o == 0) //type already matches
return from;
if (flag_typeexplicit)
QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, from, "Implicit type mismatch on assignment to %s. Needed %s, got %s.", to->name, basictypenames[wanted], basictypenames[from->type->type]);
if (o < 0)
{
if (fatal && wanted != ev_variant && from->type->type != ev_variant)
QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, from, "Implicit type mismatch on assignment to %s. Needed %s, got %s.", to->name, basictypenames[wanted], basictypenames[from->type->type]);
else
return from;
}
return QCC_PR_Statement(&pr_opcodes[o], from, NULL, NULL); //conversion return value
}
QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted, pbool fatal)
{
extern char *basictypenames[];
@ -1419,6 +1441,8 @@ static QCC_def_t *QCC_GetTemp(QCC_type_t *type)
numtemps+=type->size;
}
t->laststatement = numstatements;
var_c->s_file = s_file;
var_c->s_line = pr_source_line;
@ -1784,6 +1808,42 @@ int QCC_PR_FindSourceForTemp(QCC_def_t *tempdef, int op, pbool *need_lock)
return st;
}
int QCC_PR_FindSourceForAssignedOffset(int ofs, int firstst)
{
int st = -1;
for (st = numstatements-1; st>=firstst; st--)
{
if (statements[st].c == ofs && OpAssignsToC(statements[st].op))
return st;
if (statements[st].b == ofs && OpAssignsToB(statements[st].op))
return st;
}
return -1;
}
pbool QCC_Temp_Describe(QCC_def_t *def, char *buffer, int buffersize)
{
QCC_dstatement_t *s;
int st;
temp_t *t = def->temp;
if (!t)
return false;
if (t->lastfunc != pr_scope)
return false;
st = QCC_PR_FindSourceForAssignedOffset(def->ofs, t->laststatement);
if (st == -1)
return false;
s = &statements[st];
switch(s->op)
{
default:
_snprintf(buffer, buffersize, "%s %s %s", QCC_VarAtOffset(s->a, 1), pr_opcodes[s->op].name, QCC_VarAtOffset(s->b, 1));
break;
}
return true;
}
QCC_dstatement_t *QCC_PR_SimpleStatement( int op, int var_a, int var_b, int var_c, int force);
QCC_def_t *QCC_PR_StatementFlags (QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement, unsigned int flags)
@ -3502,6 +3562,12 @@ QCC_def_t *QCC_PR_GenerateFunctionCall (QCC_def_t *newself, QCC_def_t *func, QCC
}
}
if (func->type->vargcount)
{
QCC_def_t *va_passcount = QCC_PR_GetDef(type_float, "__va_count", NULL, true, 0, 0);
QCC_FreeTemp(QCC_PR_StatementFlags (&pr_opcodes[OP_STORE_F], QCC_MakeFloatConst(argcount), va_passcount, NULL, 0));
}
//if the return value was in use, save it off now, so that it doesn't get clobbered
if (def_ret.temp->used)
{
@ -3729,6 +3795,25 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
QCC_PR_Expect(")");
return d;
}
if (!strcmp(func->name, "va_arg") || !strcmp(func->name, "...")) //second for compat with gmqcc
{
QCC_def_t *va_list;
QCC_def_t *idx;
QCC_type_t *type;
va_list = QCC_PR_GetDef(type_vector, "__va_list", pr_scope, false, 0, 0);
idx = QCC_PR_Expression (TOP_PRIORITY, EXPR_DISALLOW_COMMA);
idx = QCC_PR_Statement(&pr_opcodes[OP_MUL_F], idx, QCC_MakeFloatConst(3), NULL);
QCC_PR_Expect(",");
type = QCC_PR_ParseType(false, false);
QCC_PR_Expect(")");
if (!va_list || !va_list->arraysize)
QCC_PR_ParseError (ERR_TYPEMISMATCHPARM, "va_arg() intrinsic only works inside varadic functions");
if (!func->initialized)
func->initialized = 3;
func->references++;
return QCC_LoadFromArray(va_list, idx, type, false);
}
if (!strcmp(func->name, "random"))
{
QCC_def_t *old = NULL;
@ -4175,7 +4260,7 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
{
char genfunc[2048];
sprintf(genfunc, "spawnfunc_%s", rettype->name);
func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 0, false);
func = QCC_PR_GetDef(type_function, genfunc, NULL, true, 0, GDF_CONST);
func->references++;
QCC_FreeTemp(QCC_PR_GenerateFunctionCall(NULL, func, NULL, NULL, 0));
@ -4267,11 +4352,15 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
else
p = t->params[arg].type;
if (extraparms && arg >= MAX_PARMS)
QCC_PR_ParseErrorPrintDef (ERR_TOOMANYPARAMETERSVARARGS, func, "More than %i parameters on varargs function", MAX_PARMS);
else if (arg >= MAX_PARMS+MAX_EXTRA_PARMS)
if (arg >= MAX_PARMS+MAX_EXTRA_PARMS)
QCC_PR_ParseErrorPrintDef (ERR_TOOMANYTOTALPARAMETERS, func, "More than %i parameters", MAX_PARMS+MAX_EXTRA_PARMS);
if (!extraparms && arg >= t->num_parms && !p)
else if (extraparms && arg >= MAX_PARMS && !t->vargcount)
{
//vararg builtins cannot accept more than 8 args. they can't tell if they got more, and wouldn't know where to read them.
QCC_PR_ParseWarning (WARN_TOOMANYPARAMETERSVARARGS, "More than %i parameters on varargs function", MAX_PARMS);
QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSVARARGS, func);
}
else if (!extraparms && arg >= t->num_parms && !p)
{
QCC_PR_ParseWarning (WARN_TOOMANYPARAMETERSFORFUNC, "too many parameters");
QCC_PR_ParsePrintDef(WARN_TOOMANYPARAMETERSFORFUNC, func);
@ -4359,7 +4448,10 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_ref_t *funcref) //warning, the func cou
QCC_PR_ParsePrintDef(WARN_LAXCAST, func);
}
else
QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHPARM, func, "type mismatch on parm %i: %s should be %s", arg+1, TypeName(e->type, typebuf1, sizeof(typebuf1)), TypeName(p, typebuf2, sizeof(typebuf2)));
{
QCC_PR_ParseWarning (ERR_TYPEMISMATCHPARM, "type mismatch on parm %i: %s should be %s", arg+1, TypeName(e->type, typebuf1, sizeof(typebuf1)), TypeName(p, typebuf2, sizeof(typebuf2)));
QCC_PR_ParsePrintDef(ERR_TYPEMISMATCHPARM, func);
}
}
}
p = e->type;
@ -4983,7 +5075,9 @@ static QCC_ref_t *QCC_PR_ParseField(QCC_ref_t *refbuf, QCC_ref_t *lhs)
if (field->cast->type == ev_field || field->cast->type == ev_variant)
{
//fields are generally always readonly. that refers to the field def itself, rather than products of said field.
lhs = QCC_PR_BuildRef(refbuf, REF_FIELD, QCC_RefToDef(lhs, true), QCC_RefToDef(field, true), (field->cast->type == ev_field)?field->cast->aux_type:type_variant, lhs->readonly);
//entities, like 'world' might also be consts. just ignore that fact. the def itself is not assigned, but the fields of said def.
//the engine may have a problem with this, but the qcc has no way to referenced locations as readonly separately from the def itself.
lhs = QCC_PR_BuildRef(refbuf, REF_FIELD, QCC_RefToDef(lhs, true), QCC_RefToDef(field, true), (field->cast->type == ev_field)?field->cast->aux_type:type_variant, false);
}
else
{
@ -5402,6 +5496,7 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
(!strcmp(name, "randomv")) ||
(!strcmp(name, "sizeof")) ||
(!strcmp(name, "entnum")) ||
(!strcmp(name, "va_arg")) ||
(!strcmp(name, "_"))) //intrinsics, any old function with no args will do.
{
d = QCC_PR_GetDef (type_function, name, NULL, true, 0, false);
@ -5505,7 +5600,10 @@ QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
qcc_usefulstatement=true;
e = QCC_PR_Term (0);
if (e->constant)
{
QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", e->name);
QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANT, e);
}
if (e->temp)
QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Hey! That's a temp! ++ operators cannot work on temps!");
switch (e->type->type)
@ -5527,7 +5625,10 @@ QCC_ref_t *QCC_PR_RefTerm (QCC_ref_t *retbuf, unsigned int exprflags)
qcc_usefulstatement=true;
e = QCC_PR_Term (0);
if (e->constant)
{
QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", e->name);
QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANT, e);
}
if (e->temp)
QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Hey! That's a temp! -- operators cannot work on temps!");
switch (e->type->type)
@ -5957,7 +6058,7 @@ void QCC_StoreToArray(QCC_def_t *base, QCC_def_t *index, QCC_def_t *source, QCC_
else
{
base->references++;
funcretr = QCC_PR_GetDef(NULL, qcva("ArraySet*%s", base->name), NULL, false, 0, false);
funcretr = QCC_PR_GetDef(NULL, qcva("ArraySet*%s", base->name), base->scope, false, 0, GDF_CONST|(base->scope?GDF_STATIC:0));
if (!funcretr)
{
QCC_type_t *arraysetfunc = qccHunkAlloc(sizeof(*arraysetfunc));
@ -5970,7 +6071,8 @@ void QCC_StoreToArray(QCC_def_t *base, QCC_def_t *index, QCC_def_t *source, QCC_
arraysetfunc->name = "ArraySet";
fparms[0].type = type_float;
fparms[1].type = base->type;
funcretr = QCC_PR_GetDef(arraysetfunc, qcva("ArraySet*%s", base->name), NULL, true, 0, false);
funcretr = QCC_PR_GetDef(arraysetfunc, qcva("ArraySet*%s", base->name), base->scope, true, 0, GDF_CONST|(base->scope?GDF_STATIC:0));
funcretr->generatedfor = base;
}
if (source->type->type != t->type)
@ -6061,9 +6163,10 @@ QCC_def_t *QCC_LoadFromArray(QCC_def_t *base, QCC_def_t *index, QCC_type_t *t, p
flags = preserve?STFL_PRESERVEA:0;
index = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], index, NULL, NULL, preserve?STFL_PRESERVEA:0);
}
else if (index->type->type != ev_float)
else
{
flags = preserve?STFL_PRESERVEA|STFL_PRESERVEB:0;
if (index->type->type != ev_float)
QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, base, "array index is not a single numeric value");
}
@ -6083,6 +6186,7 @@ QCC_def_t *QCC_LoadFromArray(QCC_def_t *base, QCC_def_t *index, QCC_type_t *t, p
//hexen2 uses element indicies. we internally use words.
//words means you can pack vectors into structs without the offset needing to be a multiple of 3.
//as its floats, I'm going to try using 0/0.33/0.66 just for the luls
//FIXME: we may very well have a *3 already, dividing by 3 again is crazy.
index = QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_F], index, QCC_MakeFloatConst(3), NULL, flags&STFL_PRESERVEA);
flags &= ~STFL_PRESERVEB;
base = QCC_PR_StatementFlags(&pr_opcodes[OP_FETCH_GBL_V], base, index, NULL, flags); //get pointer to precise def.
@ -6111,7 +6215,7 @@ QCC_def_t *QCC_LoadFromArray(QCC_def_t *base, QCC_def_t *index, QCC_type_t *t, p
base->references++;
funcretr = QCC_PR_GetDef(NULL, qcva("ArrayGet*%s", base->name), NULL, false, 0, false);
funcretr = QCC_PR_GetDef(NULL, qcva("ArrayGet*%s", base->name), base->scope, false, 0, GDF_CONST|(base->scope?GDF_STATIC:0));
if (!funcretr)
{
QCC_type_t *ftype = qccHunkAlloc(sizeof(*ftype));
@ -6123,7 +6227,10 @@ QCC_def_t *QCC_LoadFromArray(QCC_def_t *base, QCC_def_t *index, QCC_type_t *t, p
ftype->num_parms = 1;
ftype->name = "ArrayGet";
fparms[0].type = type_float;
funcretr = QCC_PR_GetDef(ftype, qcva("ArrayGet*%s", base->name), NULL, true, 0, false);
funcretr = QCC_PR_GetDef(ftype, qcva("ArrayGet*%s", base->name), base->scope, true, 0, GDF_CONST|(base->scope?GDF_STATIC:0));
funcretr->generatedfor = base;
if (!funcretr->constant)
printf("not constant?\n");
}
itmp = index->temp;
@ -6134,6 +6241,7 @@ QCC_def_t *QCC_LoadFromArray(QCC_def_t *base, QCC_def_t *index, QCC_type_t *t, p
if (base->type->type == ev_vector)
{
//FIXME: we may very well have a *3 already, dividing by 3 again is crazy.
args[0] = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], QCC_SupplyConversion(index, ev_float, true), QCC_MakeFloatConst(3), NULL);
base = QCC_PR_GenerateFunctionCall(NULL, funcretr, args, &type_float, 1);
base->type = t;
@ -6287,7 +6395,12 @@ QCC_def_t *QCC_StoreToRef(QCC_ref_t *dest, QCC_def_t *source, pbool readable, pb
QCC_ref_t ptrref;
QCC_type_t *t = source->type;
if (dest->readonly)
{
QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to constant %s", dest->base->name);
QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANT, dest->base);
if (dest->index)
QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANT, dest->index);
}
if (source->type->type == ev_integer && source->constant && !G_INT(source->ofs))
{
@ -6576,14 +6689,11 @@ QCC_opcode_t *QCC_PR_ChooseOpcode(QCC_def_t *lhs, QCC_def_t *rhs, QCC_opcode_t *
if (oldop->priority == CONDITION_PRIORITY)
op = oldop;
else
{
if (flag_laxcasts)
{
op = oldop;
QCC_PR_ParseWarning(WARN_LAXCAST, "type mismatch for %s (%s and %s)", oldop->name, lhs->type->name, rhs->type->name);
}
else
QCC_PR_ParseError (ERR_TYPEMISMATCH, "type mismatch for %s (%s and %s)", oldop->name, lhs->type->name, rhs->type->name);
QCC_PR_ParseWarning(flag_laxcasts?WARN_LAXCAST:ERR_TYPEMISMATCH, "type mismatch for %s (%s and %s)", oldop->name, lhs->type->name, rhs->type->name);
QCC_PR_ParsePrintDef(flag_laxcasts?WARN_LAXCAST:ERR_TYPEMISMATCH, lhs);
QCC_PR_ParsePrintDef(flag_laxcasts?WARN_LAXCAST:ERR_TYPEMISMATCH, rhs);
}
}
else
@ -6737,9 +6847,14 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
if (ops)
{
if (lhsr->postinc)
QCC_PR_ParseError(ERR_INTERNAL, "Assignment to lvalue");
QCC_PR_ParseError(ERR_INTERNAL, "Assignment to post-inc result");
if (lhsr->readonly)
{
QCC_PR_ParseWarning(WARN_ASSIGNMENTTOCONSTANT, "Assignment to lvalue");
QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANT, lhsr->base);
if (lhsr->index)
QCC_PR_ParsePrintDef(WARN_ASSIGNMENTTOCONSTANT, lhsr->index);
}
rhsr = QCC_PR_RefExpression (&rhsbuf, priority, exprflags | EXPR_DISALLOW_ARRAYASSIGN);
@ -6785,7 +6900,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
//convert so we don't have issues with: i = (int)(float)(i+f)
//this will also catch things like vec *= vec; which would be trying to store a float into a vector.
rhsd = QCC_SupplyConversion(rhsd, lhsr->cast->type, true);
rhsd = QCC_SupplyConversionForAssignment(lhsr->base, rhsd, lhsr->cast->type, true);
}
else
{
@ -6799,7 +6914,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
}
}
else
rhsd = QCC_SupplyConversion(rhsd, lhsr->cast->type, true);
rhsd = QCC_SupplyConversionForAssignment(lhsr->base, rhsd, lhsr->cast->type, true);
}
rhsd = QCC_StoreToRef(lhsr, rhsd, true, false); //FIXME: this should not always be true, but we don't know if the caller actually needs it
qcc_usefulstatement = true;
@ -8993,8 +9108,8 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
return f;
}
if (type->num_parms < 0)
QCC_PR_ParseError (ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body");
// if (type->vargs)
// QCC_PR_ParseError (ERR_FUNCTIONWITHVARGS, "QC function with variable arguments and function body");
f->builtin = 0;
//
@ -9041,6 +9156,49 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type)
}
}
if (type->vargcount)
{
if (!pr_parm_argcount_name)
QCC_Error(ERR_INTERNAL, "I forgot what the va_count argument is meant to be called");
else
{
QCC_def_t *va_passcount = QCC_PR_GetDef(type_float, "__va_count", NULL, true, 0, 0);
QCC_def_t *va_count = QCC_PR_GetDef(type_float, pr_parm_argcount_name, pr_scope, true, 0, 0);
QCC_PR_SimpleStatement(OP_SUB_F, va_passcount->ofs, QCC_MakeFloatConst(type->num_parms)->ofs, va_count->ofs, false);
}
}
if (type->vargs)
{
int i;
int maxvacount = 24;
QCC_def_t *a;
pbool opcodeextensions = QCC_OPCodeValid(&pr_opcodes[OP_FETCH_GBL_F]) || QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]); //if we have opcode extensions, we can use those instead of via a function. this allows to use proper locals for the vargs.
QCC_def_t *va_list;
va_list = QCC_PR_GetDef(type_vector, "__va_list", pr_scope, true, maxvacount, opcodeextensions?0:GDF_STATIC);
for (i = 0; i < maxvacount; i++)
{
QCC_ref_t varef;
u = i + type->num_parms;
if (u >= MAX_PARMS)
{
if (!extra_parms[u - MAX_PARMS])
{
e2 = (QCC_def_t *) qccHunkAlloc (sizeof(QCC_def_t));
e2->name = "extra parm";
e2->ofs = QCC_GetFreeGlobalOffsetSpace(3);
extra_parms[u - MAX_PARMS] = e2;
}
a = extra_parms[u - MAX_PARMS];
}
else
a = &def_parms[u];
a->type = type_vector;
QCC_StoreToRef(QCC_PR_BuildRef(&varef, REF_ARRAY, va_list, QCC_MakeIntConst(i*3), type_vector, false), a, false, false);
}
}
QCC_RemapLockedTemps(-1, -1);
/*if (pr_classtype)
@ -9317,11 +9475,11 @@ QCC_def_t *QCC_PR_EmitArrayGetVector(QCC_def_t *array)
return func;
}
void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *thearray, char *arrayname)
{
QCC_def_t *vectortrick;
QCC_dfunction_t *df;
QCC_def_t *def, *index;
QCC_def_t *index;
QCC_dstatement_t *st;
QCC_def_t *eq;
@ -9335,15 +9493,14 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
fasttrackpossible = NULL;
s_file = scope->s_file;
def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
if (def->type->type == ev_vector)
numslots = def->arraysize;
if (thearray->type->type == ev_vector)
numslots = thearray->arraysize;
else
numslots = def->arraysize*def->type->size;
numslots = thearray->arraysize*thearray->type->size;
if (numslots >= 15 && def->type->type != ev_vector)
vectortrick = QCC_PR_EmitArrayGetVector(def);
if (numslots >= 15 && thearray->type->type != ev_vector)
vectortrick = QCC_PR_EmitArrayGetVector(thearray);
else
vectortrick = NULL;
@ -9355,7 +9512,8 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
df = &functions[numfunctions];
numfunctions++;
df->s_file = 0;
pr_source_line = thearray->s_line; //thankfully these functions are emitted after compilation.
df->s_file = thearray->s_file;
df->s_name = QCC_CopyString(scope->name);
df->first_statement = numstatements;
df->parm_size[0] = 1;
@ -9371,10 +9529,10 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
//fetch_gbl takes: (float size, variant array[]), float index, variant pos
//note that the array size is coded into the globals, one index before the array.
if (def->type->type == ev_vector)
QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_V], def, index, &def_ret, true);
if (thearray->type->type == ev_vector)
QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_V], thearray, index, &def_ret, true);
else
QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_F], def, index, &def_ret, true);
QCC_PR_Statement3(&pr_opcodes[OP_FETCH_GBL_F], thearray, index, &def_ret, true);
QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_RETURN], &def_ret, NULL, NULL));
@ -9390,8 +9548,8 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
//we need to work out which part, x/y/z that it's stored in.
//0,1,2 = i - ((int)i/3 *) 3;
div3 = QCC_PR_GetDef(type_float, "div3___", def, true, 0, false);
intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", def, true, 0, false);
div3 = QCC_PR_GetDef(type_float, "div3___", thearray, true, 0, false);
intdiv3 = QCC_PR_GetDef(type_float, "intdiv3___", thearray, true, 0, false);
eq = QCC_PR_Statement(pr_opcodes+OP_GE_F, index, QCC_MakeFloatConst((float)numslots), NULL); //escape clause - should call some sort of error function instead.. that'd rule!
QCC_FreeTemp(QCC_PR_Statement(pr_opcodes+OP_IFNOT_I, eq, 0, &st));
@ -9439,7 +9597,7 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, char *arrayname)
else
{
QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
QCC_PR_ArrayRecurseDivideRegular(def, index, 0, numslots);
QCC_PR_ArrayRecurseDivideRegular(thearray, index, 0, numslots);
}
QCC_PR_Statement(pr_opcodes+OP_RETURN, QCC_MakeFloatConst(0), 0, NULL);
@ -9498,10 +9656,10 @@ void QCC_PR_ArraySetRecurseDivide(QCC_def_t *array, QCC_def_t *index, QCC_def_t
}
}
void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *thearray, char *arrayname)
{
QCC_dfunction_t *df;
QCC_def_t *def, *index, *value;
QCC_def_t *index, *value;
QCC_def_t *fasttrackpossible;
int numslots;
@ -9512,13 +9670,12 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
fasttrackpossible = NULL;
s_file = scope->s_file;
def = QCC_PR_GetDef(NULL, arrayname, NULL, false, 0, false);
pr_scope = scope;
if (def->type->type == ev_vector)
numslots = def->arraysize;
if (thearray->type->type == ev_vector)
numslots = thearray->arraysize;
else
numslots = def->arraysize*def->type->size;
numslots = thearray->arraysize*thearray->type->size;
if (numfunctions >= MAX_FUNCTIONS)
QCC_Error(ERR_INTERNAL, "Too many function defs");
@ -9526,15 +9683,16 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
df = &functions[numfunctions];
numfunctions++;
df->s_file = 0;
pr_source_line = thearray->s_line; //thankfully these functions are emitted after compilation.
df->s_file = thearray->s_file;
df->s_name = QCC_CopyString(scope->name);
df->first_statement = numstatements;
df->parm_size[0] = 1;
df->parm_size[1] = def->type->size;
df->parm_size[1] = thearray->type->size;
df->numparms = 2;
locals_start = locals_end = FIRST_LOCAL;
index = QCC_PR_GetDef(type_float, "indexs___", def, true, 0, false);
value = QCC_PR_GetDef(def->type, "value___", def, true, 0, false);
index = QCC_PR_GetDef(type_float, "indexs___", pr_scope, true, 0, false);
value = QCC_PR_GetDef(thearray->type, "value___", pr_scope, true, 0, false);
G_FUNCTION(scope->ofs) = df - functions;
@ -9546,11 +9704,11 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
//note that the array size is coded into the globals, one index before the array.
QCC_PR_Statement3(&pr_opcodes[OP_CONV_FTOI], index, NULL, index, true); //address stuff is integer based, but standard qc (which this accelerates in supported engines) only supports floats
QCC_PR_SimpleStatement (OP_BOUNDCHECK, index->ofs, ((int*)qcc_pr_globals)[def->ofs-1]+1, 0, true);//annoy the programmer. :p
if (def->type->type == ev_vector)//shift it upwards for larger types
QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntConst(def->type->size), index, true);
QCC_PR_Statement3(&pr_opcodes[OP_GLOBALADDRESS], def, index, index, true); //comes with built in add
if (def->type->type == ev_vector)
QCC_PR_SimpleStatement (OP_BOUNDCHECK, index->ofs, ((int*)qcc_pr_globals)[thearray->ofs-1]+1, 0, true);//annoy the programmer. :p
if (thearray->type->type == ev_vector)//shift it upwards for larger types
QCC_PR_Statement3(&pr_opcodes[OP_MUL_I], index, QCC_MakeIntConst(thearray->type->size), index, true);
QCC_PR_Statement3(&pr_opcodes[OP_GLOBALADDRESS], thearray, index, index, true); //comes with built in add
if (thearray->type->type == ev_vector)
QCC_PR_Statement3(&pr_opcodes[OP_STOREP_V], value, index, NULL, true); //*b = a
else
QCC_PR_Statement3(&pr_opcodes[OP_STOREP_F], value, index, NULL, true);
@ -9561,7 +9719,7 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, char *arrayname)
}
QCC_PR_Statement3(pr_opcodes+OP_BITAND_F, index, index, index, false);
QCC_PR_ArraySetRecurseDivide(def, index, value, 0, numslots);
QCC_PR_ArraySetRecurseDivide(thearray, index, value, 0, numslots);
QCC_PR_Statement(pr_opcodes+OP_DONE, 0, 0, NULL);
@ -9730,8 +9888,8 @@ QCC_def_t *QCC_PR_DummyDef(QCC_type_t *type, char *name, QCC_def_t *scope, int a
{
if (!pHash_Get(&globalstable, "end_sys_fields"))
first->references++; //anything above needs to be left in, and so warning about not using it is just going to pee people off.
if (!arraysize && first->type->type != ev_field)
first->constant = false;
// if (!arraysize && first->type->type != ev_field)
// first->constant = false;
if (scope)
pHash_Add(&localstable, first->name, first, qccHunkAlloc(sizeof(bucket_t)));
else
@ -9948,9 +10106,9 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool
if (scope && qccwarningaction[WARN_SAMENAMEASGLOBAL])
{
def = QCC_PR_GetDef(NULL, name, NULL, false, arraysize, false);
if (def)
{
QCC_PR_ParseWarning(WARN_SAMENAMEASGLOBAL, "Local \"%s\" hides global with same name", name);
if (def && def->type->type == type->type)
{ //allow type differences. this means that arguments called 'min' or 'mins' are accepted with the 'min' builtin or the 'mins' field in existance.
QCC_PR_ParseWarning(WARN_SAMENAMEASGLOBAL, "Local \"%s\" hides global with same name and type", name);
QCC_PR_ParsePrintDef(WARN_SAMENAMEASGLOBAL, def);
}
}

View file

@ -97,7 +97,7 @@ QCC_def_t def_ret, def_parms[MAX_PARMS];
//QCC_def_t *def_for_type[9] = {&def_void, &def_string, &def_float, &def_vector, &def_entity, &def_field, &def_function, &def_pointer, &def_integer};
void QCC_PR_LexWhitespace (void);
void QCC_PR_LexWhitespace (pbool inhibitpreprocessor);
@ -747,7 +747,7 @@ pbool QCC_PR_Precompiler(void)
while(1)
{
QCC_PR_LexWhitespace();
QCC_PR_LexWhitespace(false);
if (!QCC_PR_SimpleGetToken())
{
if (!*pr_file_p)
@ -1488,7 +1488,7 @@ void QCC_PR_LexString (void)
if (len >= sizeof(pr_immediate_string)-1)
QCC_Error(ERR_INVALIDSTRINGIMMEDIATE, "String length exceeds %i", sizeof(pr_immediate_string)-1);
QCC_PR_LexWhitespace();
QCC_PR_LexWhitespace(false);
if (*pr_file_p == '\"') //have annother go
{
pr_file_p++;
@ -1835,11 +1835,11 @@ void QCC_PR_LexVector (void)
}
pr_token_type = tt_immediate;
pr_immediate_type = type_vector;
QCC_PR_LexWhitespace ();
QCC_PR_LexWhitespace (false);
for (i=0 ; i<3 ; i++)
{
pr_immediate.vector[i] = QCC_PR_LexFloat ();
QCC_PR_LexWhitespace ();
QCC_PR_LexWhitespace (false);
if (*pr_file_p == '\'' && i == 1)
{
@ -1920,7 +1920,7 @@ void QCC_PR_LexPunctuation (void)
PR_LexWhitespace
==============
*/
void QCC_PR_LexWhitespace (void)
void QCC_PR_LexWhitespace (pbool inhibitpreprocessor)
{
int c;
@ -1932,6 +1932,7 @@ void QCC_PR_LexWhitespace (void)
if (c=='\n')
{
pr_file_p++;
if (!inhibitpreprocessor)
QCC_PR_NewLine (false);
if (!pr_file_p)
return;
@ -1950,6 +1951,7 @@ void QCC_PR_LexWhitespace (void)
if (*pr_file_p == '\n')
pr_file_p++; //don't break on eof.
if (!inhibitpreprocessor)
QCC_PR_NewLine(false);
continue;
}
@ -1962,6 +1964,7 @@ void QCC_PR_LexWhitespace (void)
{
if (pr_file_p[0]=='\n')
{
if (!inhibitpreprocessor)
QCC_PR_NewLine(true);
}
if (pr_file_p[1] == 0)
@ -2274,6 +2277,7 @@ CompilerConstant_t *QCC_PR_DefineName(char *name)
cnst->used = false;
cnst->numparams = 0;
cnst->evil = false;
strcpy(cnst->name, name);
cnst->namelen = strlen(name);
cnst->value = cnst->name + strlen(cnst->name);
@ -2323,27 +2327,43 @@ void QCC_PR_ConditionCompilation(void)
if (*pr_file_p == '(')
{
s = pr_file_p+1;
while(*pr_file_p++)
pr_file_p++;
while(qcc_iswhitesameline(*pr_file_p))
pr_file_p++;
s = pr_file_p;
for (;;)
{
if (*pr_file_p == ',')
if (*pr_file_p == ',' || *pr_file_p == ')')
{
int nl;
nl = pr_file_p-s;
while(qcc_iswhitesameline(s[nl]))
nl--;
if (cnst->numparams >= MAXCONSTANTPARAMS)
QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS);
strncpy(cnst->params[cnst->numparams], s, pr_file_p-s);
cnst->params[cnst->numparams][pr_file_p-s] = '\0';
if (nl >= MAXCONSTANTPARAMLENGTH)
QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "parameter name is too long (max %i)", MAXCONSTANTPARAMLENGTH);
if (nl == 3 && s[0] == '.' && s[1] == '.' && s[2] == '.')
{
cnst->varg = true;
if (*pr_file_p != ')')
QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "varadic argument must be last");
}
else
{
memcpy(cnst->params[cnst->numparams], s, nl);
cnst->params[cnst->numparams][nl] = '\0';
cnst->numparams++;
}
if (*pr_file_p++ == ')')
break;
while(qcc_iswhitesameline(*pr_file_p))
pr_file_p++;
s = pr_file_p;
}
if (*pr_file_p == ')')
if(!*pr_file_p++)
{
if (cnst->numparams >= MAXCONSTANTPARAMS)
QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS);
strncpy(cnst->params[cnst->numparams], s, pr_file_p-s);
cnst->params[cnst->numparams][pr_file_p-s] = '\0';
cnst->numparams++;
pr_file_p++;
QCC_PR_ParseError(ERR_EXPECTED, "missing ) in macro parameter list", MAXCONSTANTPARAMS);
break;
}
}
@ -2402,8 +2422,10 @@ so if present, the preceeding \\\n and following \\\n must become an actual \n i
;
if (*exploitcheck == '#')
{
QCC_PR_ParseWarning(WARN_EVILPREPROCESSOR, "preprocessor directive within preprocessor macro %s", cnst->name);
*d++ = '\n';
if (!cnst->evil)
QCC_PR_ParseWarning(WARN_EVILPREPROCESSOR, "preprocessor directive within preprocessor macro %s", cnst->name);
cnst->evil = true;
preprocessorhack = true;
}
else if (preprocessorhack)
@ -2417,9 +2439,28 @@ so if present, the preceeding \\\n and following \\\n must become an actual \n i
{
break;
}
if (!quote && s[0]=='/'&&(s[1]=='/'||s[1]=='*'))
if (!quote && s[0]=='/'&&s[1]=='/')
break; //c++ style comments can just be ignored
if (!quote && s[0]=='/'&&s[1]=='*')
{ //multi-line c style comments become part of the define itself. this also negates the need for \ at the end of lines.
//although we don't bother embedding.
s+=2;
for(;;)
{
if (!s[0])
{
QCC_PR_ParseWarning(WARN_DUPLICATEPRECOMPILER, "EOF inside quote in define %s", cnst->name);
break;
}
if (s[0]=='*'&&s[1]=='/')
{
s+=2;
break;
}
s++;
}
continue;
}
if (*s == '\"')
quote=!quote;
@ -2542,8 +2583,7 @@ int QCC_PR_CheckCompConst(void)
int plevel=0;
pr_file_p++;
while(*pr_file_p == ' ' || *pr_file_p == '\t')
pr_file_p++;
QCC_PR_LexWhitespace(false);
start = pr_file_p;
while(1)
{
@ -2557,6 +2597,10 @@ int QCC_PR_CheckCompConst(void)
if (*pr_file_p == '(')
plevel++;
else if (!plevel && (*pr_file_p == ',' || *pr_file_p == ')'))
{
if (*pr_file_p == ',' && c->varg && param >= c->numparams)
; //skip extra trailing , arguments if we're varging.
else
{
paramoffset[param++] = start;
start = pr_file_p+1;
@ -2568,15 +2612,13 @@ int QCC_PR_CheckCompConst(void)
}
*pr_file_p = '\0';
pr_file_p++;
while(*pr_file_p == ' ' || *pr_file_p == '\t')
{
pr_file_p++;
start++;
}
QCC_PR_LexWhitespace(false);
start = pr_file_p;
// move back by one char because we move forward by one at the end of the loop
pr_file_p--;
if (param == MAXCONSTANTPARAMS)
if (param == MAXCONSTANTPARAMS || param > c->numparams)
QCC_PR_ParseError(ERR_TOOMANYPARAMS, "Too many parameters in macro call");
}
} else if (*pr_file_p == ')' )
plevel--;
else if(*pr_file_p == '\n')
@ -2601,12 +2643,13 @@ int QCC_PR_CheckCompConst(void)
{
whitestart = bufferlen;
starttok = pr_file_p;
while(qcc_iswhite(*pr_file_p)) //copy across whitespace
/*while(qcc_iswhite(*pr_file_p)) //copy across whitespace
{
if (!*pr_file_p)
break;
pr_file_p++;
}
}*/
QCC_PR_LexWhitespace(true);
if (starttok != pr_file_p)
{
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, starttok, pr_file_p - starttok);
@ -2653,7 +2696,8 @@ int QCC_PR_CheckCompConst(void)
{
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, "#", 1);
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, qcc_token, strlen(qcc_token));
//QCC_PR_ParseWarning(0, "Stringification ignored");
if (!c->evil)
QCC_PR_ParseWarning(0, "'#' is not followed by a macro parameter in %s", c->name);
}
continue; //already did this one
}
@ -2663,7 +2707,7 @@ int QCC_PR_CheckCompConst(void)
if (!pr_file_p)
break;
for (p = 0; p < param; p++)
for (p = 0; p < c->numparams; p++)
{
if (!STRCMP(qcc_token, c->params[p]))
{
@ -2671,7 +2715,9 @@ int QCC_PR_CheckCompConst(void)
break;
}
}
if (p == param)
if (c->varg && !STRCMP(qcc_token, "__VA_ARGS__"))
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, paramoffset[c->numparams], strlen(paramoffset[c->numparams]));
else if (p == c->numparams)
QCC_PR_ExpandStrCat(&buffer, &bufferlen, &buffermax, qcc_token, strlen(qcc_token));
}
@ -2863,7 +2909,7 @@ void QCC_PR_Lex (void)
return;
}
QCC_PR_LexWhitespace ();
QCC_PR_LexWhitespace (false);
pr_token_line_last = pr_token_line;
pr_token_line = pr_source_line;
@ -2975,18 +3021,26 @@ void QCC_PR_Lex (void)
//=============================================================================
pbool QCC_Temp_Describe(QCC_def_t *def, char *buffer, int buffersize);
void QCC_PR_ParsePrintDef (int type, QCC_def_t *def)
{
if (!qccwarningaction[type])
return;
if (def->s_file)
{
char buffer[512];
if (flag_msvcstyle)
printf ("%s(%i) : %s %s is defined here\n", strings + def->s_file, def->s_line, TypeName(def->type, buffer, sizeof(buffer)), def->name);
char tybuffer[512];
char tmbuffer[512];
if (QCC_Temp_Describe(def, tmbuffer, sizeof(tmbuffer)))
{
printf ("%s:%i: (%s)(%s)\n", strings + def->s_file, def->s_line, TypeName(def->type, tybuffer, sizeof(tybuffer)), tmbuffer);
}
else
printf ("%s:%i: %s %s is defined here\n", strings + def->s_file, def->s_line, TypeName(def->type, buffer, sizeof(buffer)), def->name);
{
if (flag_msvcstyle)
printf ("%s(%i) : %s %s is defined here\n", strings + def->s_file, def->s_line, TypeName(def->type, tybuffer, sizeof(tybuffer)), def->name);
else
printf ("%s:%i: %s %s is defined here\n", strings + def->s_file, def->s_line, TypeName(def->type, tybuffer, sizeof(tybuffer)), def->name);
}
}
}
void *errorscope;
@ -3418,6 +3472,8 @@ int typecmp(QCC_type_t *a, QCC_type_t *b)
return 1;
if (a->vargs != b->vargs)
return 1;
if (a->vargcount != b->vargcount)
return 1;
if (a->size != b->size)
return 1;
@ -3461,6 +3517,9 @@ int typecmp_lax(QCC_type_t *a, QCC_type_t *b)
else if (a->size != b->size)
return 1;
if (a->vargcount != b->vargcount)
return 1;
t = a->num_parms;
minargs = t;
t = b->num_parms;
@ -3714,6 +3773,7 @@ char pr_parm_names[MAX_PARMS+MAX_EXTRA_PARMS][MAX_NAME];
#else
char pr_parm_names[MAX_PARMS][MAX_NAME];
#endif
char *pr_parm_argcount_name;
int recursivefunctiontype;
@ -3734,6 +3794,8 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
ftype->aux_type = returntype; // return type
ftype->num_parms = 0;
if (definenames)
pr_parm_argcount_name = NULL;
if (!QCC_PR_CheckToken (")"))
{
@ -3788,6 +3850,21 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
numparms++;
} while (QCC_PR_CheckToken (","));
if (ftype->vargs)
{
if (!QCC_PR_CheckToken (")"))
{
name = QCC_PR_ParseName();
if (definenames)
{
pr_parm_argcount_name = qccHunkAlloc(strlen(name)+1);
strcpy(pr_parm_argcount_name, name);
}
ftype->vargcount = true;
QCC_PR_Expect (")");
}
}
else
QCC_PR_Expect (")");
}
ftype->num_parms = numparms;
@ -3812,6 +3889,7 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
ftype->aux_type = returntype; // return type
ftype->num_parms = 0;
pr_parm_argcount_name = NULL;
if (!QCC_PR_CheckToken (")"))
{

View file

@ -23,7 +23,7 @@ pbool qcc_nopragmaoptimise;
extern unsigned int locals_marshalled;
pbool QCC_PR_SimpleGetToken (void);
void QCC_PR_LexWhitespace (void);
void QCC_PR_LexWhitespace (pbool inhibitpreprocessor);
void *FS_ReadToMem(char *fname, void *membuf, int *len);
void FS_CloseFromMem(void *mem);
@ -722,7 +722,7 @@ pbool QCC_WriteData (int crc)
else
{
if (numpr_globals >= 32768) //not much of a different format. Rewrite output to get it working on original executors?
printf("An enhanced QCVM will be required (FTE/QF/KK)\n");
printf("Globals exceeds 32k - an enhanced QCVM will be required\n");
else
printf("Progs should run on any QuakeC VM\n");
break;
@ -1872,7 +1872,7 @@ int QCC_PR_FinishCompilation (void)
// check to make sure all functions prototyped have code
for (d=pr.def_head.next ; d ; d=d->next)
{
if (d->type->type == ev_function && !d->scope)// function parms are ok
if (d->type->type == ev_function && d->constant)// function parms are ok
{
// f = G_FUNCTION(d->ofs);
// if (!f || (!f->code && !f->builtin) )
@ -1880,18 +1880,19 @@ int QCC_PR_FinishCompilation (void)
{
if (!strncmp(d->name, "ArrayGet*", 9))
{
QCC_PR_EmitArrayGetFunction(d, d->name+9);
QCC_PR_EmitArrayGetFunction(d, d->generatedfor, d->name+9);
pr_scope = NULL;
continue;
}
if (!strncmp(d->name, "ArraySet*", 9))
{
QCC_PR_EmitArraySetFunction(d, d->name+9);
QCC_PR_EmitArraySetFunction(d, d->generatedfor, d->name+9);
pr_scope = NULL;
continue;
}
if (!strncmp(d->name, "spawnfunc_", 10))
{
//not all of these will have a class defined, as some will be regular spawn functions, so don't error on that
t = QCC_TypeForName(d->name+10);
if (t)
{
@ -3203,7 +3204,7 @@ void QCC_main (int argc, char **argv) //as part of the quake engine
numpr_globals=0;
Hash_InitTable(&globalstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2)));
Hash_InitTable(&localstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2)));
Hash_InitTable(&localstable, 128, qccHunkAlloc(Hash_BytesForBuckets(128)));
Hash_InitTable(&floatconstdefstable, MAX_REGS/2+1, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2+1)));
Hash_InitTable(&stringconstdefstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2)));
Hash_InitTable(&stringconstdefstable_trans, 1000, qccHunkAlloc(Hash_BytesForBuckets(1000)));
@ -3380,7 +3381,7 @@ newstyle:
}
pr_file_p = qccmsrc;
QCC_PR_LexWhitespace();
QCC_PR_LexWhitespace(false);
qccmsrc = pr_file_p;
s = qccmsrc;

View file

@ -578,6 +578,7 @@ static int multicasttype;
static int requireextension;
static qboolean ignoreprotocol;
static int te_515sevilhackworkaround;
qboolean ssqc_deprecated_warned;
#define svc_setfrags 14
#define svc_updatecolors 17
@ -760,19 +761,21 @@ void NPP_NQFlush(void)
{
default:
if (te_515sevilhackworkaround)
{
if (sv.csqcdebug)
{
/*shift the data up by two bytes, but don't care about the first byte*/
memmove(buffer+3, buffer+1, bufferlen-1);
/*replace the svc itself*/
buffer[0] = svcfte_cgamepacket;
/*add a length in the 2nd/3rd bytes*/
/*add a length in the 2nd/3rd bytes, if needed*/
buffer[1] = (bufferlen-1);
buffer[2] = (bufferlen-1) >> 8;
bufferlen += 2;
}
/*replace the svc itself*/
buffer[0] = svcfte_cgamepacket;
}
break;
case TENQ_EXPLOSION2: //happens with rogue.
bufferlen -= 2; //trim the colour
@ -985,6 +988,9 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
protocollen = 3;
ignoreprotocol = true;
break;
case svcfte_cgamepacket:
protocollen = sizeof(buffer);
break;
default:
Con_DPrintf("NQWriteByte: bad protocol %i\n", (int)data);
protocollen = sizeof(buffer);
@ -1131,9 +1137,15 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
else
{
te_515sevilhackworkaround = true;
Con_Printf("NQWriteByte: unknown tempentity %i\n", data);
if (!ssqc_deprecated_warned)
{
ssqc_deprecated_warned = true;
Con_Printf("NQWriteByte: invalid tempentity %i. Future errors will be dprinted. You may need to enable sv_csqcdebug.\n", data);
PR_StackTrace(svprogfuncs);
}
else
Con_DPrintf("NQWriteByte: unknown tempentity %i\n", data);
}
break;
}
break;
@ -1844,6 +1856,9 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw)
case svc_setpause:
protocollen = 2;
break;
case svcfte_cgamepacket:
protocollen = sizeof(buffer);
break;
default:
Con_DPrintf("QWWriteByte: bad protocol %i\n", (int)data);
protocollen = sizeof(buffer);

View file

@ -96,6 +96,7 @@ char cvargroup_progs[] = "Progs variables";
evalc_t evalc_idealpitch, evalc_pitch_speed;
qboolean ssqc_deprecated_warned;
int pr_teamfield;
unsigned int h2infoplaque[2]; /*hexen2 stat*/
@ -1342,6 +1343,8 @@ void Q_InitProgs(void)
progsnum_t prnum, oldprnum=-1;
int d1, d2;
ssqc_deprecated_warned = false;
QC_Clear();
Q_SetProgsParms(false);
@ -8659,48 +8662,6 @@ static void QCBUILTIN PF_ChangePic(pubprogfuncs_t *prinst, struct globalvars_s *
}
}
int SV_TagForName(int modelindex, char *tagname)
{
model_t *model = SVPR_GetCModel(&sv.world, modelindex);
if (!model)
return 0;
return Mod_TagNumForName(model, tagname);
}
static void QCBUILTIN PF_setattachment(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
edict_t *e = G_EDICT(prinst, OFS_PARM0);
edict_t *tagentity = G_EDICT(prinst, OFS_PARM1);
char *tagname = PR_GetStringOfs(prinst, OFS_PARM2);
model_t *model;
int tagidx;
tagidx = 0;
if (tagentity != (edict_t*)sv.world.edicts && tagname && tagname[0])
{
model = SVPR_GetCModel(&sv.world, tagentity->v->modelindex);
if (model)
{
tagidx = Mod_TagNumForName(model, tagname);
if (tagidx == 0)
Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname, tagname, NUM_FOR_EDICT(prinst, tagentity), model->name);
}
else
Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): Couldn't load model\n", NUM_FOR_EDICT(prinst, e), NUM_FOR_EDICT(prinst, tagentity), tagname);
}
e->xv->tag_entity = EDICT_TO_PROG(prinst,tagentity);
e->xv->tag_index = tagidx;
}
//the first implementation of this function was (float type, float num, string name)
//it is now float num, float type, .field
//EXT_CSQC_1
@ -8949,21 +8910,6 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd)
return false;
}
qbyte qcpvs[(MAX_MAP_LEAFS+7)/8];
//#240 float(vector viewpos, entity viewee) checkpvs (FTE_QC_CHECKPVS)
//note: this requires a correctly setorigined entity.
static void QCBUILTIN PF_checkpvs(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *viewpos = G_VECTOR(OFS_PARM0);
edict_t *ent = G_EDICT(prinst, OFS_PARM1);
//FIXME: Make all alternatives of FatPVS not recalulate the pvs.
//and yeah, this is overkill what with the whole fat thing and all.
sv.world.worldmodel->funcs.FatPVS(sv.world.worldmodel, viewpos, qcpvs, sizeof(qcpvs), false);
G_FLOAT(OFS_RETURN) = sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &((wedict_t*)ent)->pvsinfo, qcpvs);
}
//entity(string match [, float matchnum]) matchclient = #241;
static void QCBUILTIN PF_matchclient(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -9776,7 +9722,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"putentityfieldstring",PF_putentityfieldstring,0,0, 0, 500, "float(float fieldnum, entity ent, string s)"},//DP_QC_ENTITYDATA
{"WritePicture", PF_WritePicture, 0, 0, 0, 501, "void(float to, string s, float sz)"},//DP_SV_WRITEPICTURE
{"ReadPicture", PF_Fixme, 0, 0, 0, 501, "string()"},//DP_SV_WRITEPICTURE
// {"boxparticles", PF_Fixme, 0, 0, 0, 502, "void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, float flags)"},
{"boxparticles", PF_Fixme, 0, 0, 0, 502, "void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, optional float flags)"},
{"whichpack", PF_whichpack, 0, 0, 0, 503, D("string(string filename, optional float makereferenced)", "Returns the pak file name that contains the file specified. progs/player.mdl will generally return something like 'pak0.pak'. If makereferenced is true, clients will automatically be told that the returned package should be pre-downloaded and used, even if allow_download_refpackages is not set.")},//DP_QC_WHICHPACK
{"getentity", PF_Fixme, 0, 0, 0, 504, "__variant(float entnum, float fieldnum)"},//DP_CSQC_QUERYRENDERENTITY
// {"undefined", PF_Fixme, 0, 0, 0, 505, ""},
@ -10419,6 +10365,7 @@ void PR_DumpPlatform_f(void)
{"CSQC_Parse_StuffCmd", "noref void(string msg)", CS, "Gives the CSQC a chance to intercept stuffcmds. Use the tokenize builtin to parse the message. Unrecognised commands would normally be localcmded, but its probably better to drop unrecognised stuffcmds completely."},
{"CSQC_Parse_CenterPrint", "noref float(string msg)", CS, "Gives the CSQC a chance to intercept centerprints. Return true if you wish the engine to otherwise ignore the centerprint."},
{"CSQC_Parse_Print", "noref void(string printmsg, float printlvl)", CS, "Gives the CSQC a chance to intercept sprint/bprint builtin calls. CSQC should filter by the client's current msg setting and then pass the message on to the print command, or handle them itself."},
{"CSQC_Parse_Event", "noref void()", CS, "Called when the client receives an SVC_CGAMEPACKET. The csqc should read the data or call the error builtin if it does not recognise the message."},
{"CSQC_InputEvent", "noref float(float evtype, float scanx, float chary, float devid)", CS, "Called whenever a key is pressed, the mouse is moved, etc. evtype will be one of the IE_* constants. The other arguments vary depending on the evtype. Key presses are not guarenteed to have both scan and unichar values set at the same time."},
{"CSQC_Input_Frame", "noref void()", CS, "Called just before each time clientcommandframe is updated. You can edit the input_* globals in order to apply your own player inputs within csqc, which may allow you a convienient way to pass certain info to ssqc."},
{"CSQC_ConsoleCommand", "noref float(string cmd)", CS, "Called if the user uses any console command registed via registercommand."},
@ -10428,7 +10375,7 @@ void PR_DumpPlatform_f(void)
{"CSQC_Event_Sound", "noref float(float entnum, float channel, float soundname, float vol, float attenuation, vector pos, float pitchmod)", CS},
// {"CSQC_ServerSound", "//void()", CS},
{"CSQC_LoadResource", "noref float(string resname, string restype)", CS, "Called each time some resource is being loaded. CSQC can invoke various draw calls to provide a loading screen, until WorldLoaded is called."},
{"CSQC_Parse_TempEntity", "noref float()", CS, "Please don't use this."},
{"CSQC_Parse_TempEntity", "noref float()", CS, "Please don't use this. Use CSQC_Parse_Event and multicasts instead."},
{"GameCommand", "noref void(string cmdtext)", CS|MENU},
@ -10447,7 +10394,7 @@ void PR_DumpPlatform_f(void)
{"FONT_DEFAULT", "const float", CS|MENU, NULL, 0},
{"TRUE", "const float", ALL, NULL, 1},
{"FALSE", "const float", ALL, NULL, 0},
{"FALSE", "const float", ALL, "File not found...", 0},
{"MOVETYPE_NONE", "const float", QW|NQ|CS, NULL, MOVETYPE_NONE},
{"MOVETYPE_WALK", "const float", QW|NQ|CS, NULL, MOVETYPE_WALK},
@ -10460,7 +10407,7 @@ void PR_DumpPlatform_f(void)
{"MOVETYPE_BOUNCE", "const float", QW|NQ|CS, NULL, MOVETYPE_BOUNCE},
{"MOVETYPE_BOUNCEMISSILE", "const float", QW|NQ|CS, NULL, MOVETYPE_BOUNCEMISSILE},
{"MOVETYPE_FOLLOW", "const float", QW|NQ|CS, NULL, MOVETYPE_FOLLOW},
{"MOVETYPE_WALLWALK", "const float", QW|NQ|CS, NULL, MOVETYPE_WALLWALK},
{"MOVETYPE_WALLWALK", "const float", QW|NQ|CS, "Players using this movetype will be able to orient themselves to walls, and then run up them.", MOVETYPE_WALLWALK},
{"MOVETYPE_PHYSICS", "const float", QW|NQ|CS, NULL, MOVETYPE_PHYSICS},
{"SOLID_NOT", "const float", QW|NQ|CS, NULL, SOLID_NOT},
@ -10493,16 +10440,19 @@ void PR_DumpPlatform_f(void)
{"CONTENT_SKY", "const float", QW|NQ|CS, NULL, Q1CONTENTS_SKY},
{"CONTENT_LADDER", "const float", QW|NQ|CS, NULL, Q1CONTENTS_LADDER},
{"CHAN_AUTO", "const float", QW|NQ|CS, NULL, CHAN_AUTO},
{"CHAN_AUTO", "const float", QW|NQ|CS, "The automatic channel, play as many sounds on this channel as you want, and they'll all play, however the other channels will replace each other.", CHAN_AUTO},
{"CHAN_WEAPON", "const float", QW|NQ|CS, NULL, CHAN_WEAPON},
{"CHAN_VOICE", "const float", QW|NQ|CS, NULL, CHAN_VOICE},
{"CHAN_ITEM", "const float", QW|NQ|CS, NULL, CHAN_ITEM},
{"CHAN_BODY", "const float", QW|NQ|CS, NULL, CHAN_BODY},
{"ATTN_NONE", "const float", QW|NQ|CS, NULL, ATTN_NONE},
{"ATTN_NORM", "const float", QW|NQ|CS, NULL, ATTN_NORM},
{"ATTN_IDLE", "const float", QW|NQ|CS, NULL, 2}, //including these for completeness, despite them being defined by the gamecode rather than the engine api.
{"ATTN_STATIC", "const float", QW|NQ|CS, NULL, 3},
{"ATTN_NONE", "const float", QW|NQ|CS, "Sounds with this attenuation can be heard throughout the map", ATTN_NONE},
{"ATTN_NORM", "const float", QW|NQ|CS, "Standard attenuation", ATTN_NORM},
{"ATTN_IDLE", "const float", QW|NQ|CS, "Extra attenuation so that sounds don't travel too far.", 2}, //including these for completeness, despite them being defined by the gamecode rather than the engine api.
{"ATTN_STATIC", "const float", QW|NQ|CS, "Even more attenuation to avoid torches drowing out everything else throughout the map.", 3},
//not putting other svcs here, qc shouldn't otherwise need to generate svcs directly.
{"SVC_CGAMEPACKET", "const float", QW|NQ, "Direct ssqc->csqc message. Must only be multicast. The data triggers a CSQC_Parse_Event call in the csqc for the csqc to read the contents. The server *may* insert length information for clients connected via proxies which are not able to cope with custom csqc payloads.", svcfte_cgamepacket},
{"MSG_BROADCAST", "const float", QW|NQ, NULL, MSG_BROADCAST},
{"MSG_ONE", "const float", QW|NQ, NULL, MSG_ONE},
@ -10544,9 +10494,9 @@ void PR_DumpPlatform_f(void)
{"INFOKEY_P_PROTOCOL", "const string", QW|NQ, "The network protocol the client is using to connect to the server.", 0, "\"protocol\""},
{"INFOKEY_P_MUTED", "const string", CS, "0: we can see the result of the player's say/say_team commands. 1: we see no say/say_team messages from this player. Use the ignore command to toggle this value.", 0, "\"ignored\""},
{"INFOKEY_P_VOIP_MUTED","const string", CS, "0: we can hear this player when they speak (assuming voip is generally enabled). 1: we ignore everything this player says. Use cl_voip_mute to change the values.", 0, "\"vignored\""},
{"INFOKEY_P_ENTERTIME", "const string", CS, NULL, 0, "\"entertime\""},
{"INFOKEY_P_FRAGS", "const string", CS, NULL, 0, "\"frags\""},
{"INFOKEY_P_PACKETLOSS","const string", CS, NULL, 0, "\"pl\""},
{"INFOKEY_P_ENTERTIME", "const string", CS, "Reads the timestamp at which the player entered the game, in terms of csqc's time global.", 0, "\"entertime\""},
{"INFOKEY_P_FRAGS", "const string", CS, "Reads a player's frag count.", 0, "\"frags\""},
{"INFOKEY_P_PACKETLOSS","const string", CS, "Reads a player's packetloss, as a percentage.", 0, "\"pl\""},
{"INFOKEY_P_VOIPSPEAKING","const string", CS, "Boolean value that says whether the given player is currently sending voice information.", 0, "\"voipspeaking\""},
{"INFOKEY_P_VOIPLOUDNESS","const string", CS, "Only valid for the local player. Gives a value between 0 and 1 to indicate to the user how loud their mic is.", 0, "\"voiploudness\""},
@ -10572,10 +10522,11 @@ void PR_DumpPlatform_f(void)
{"MOVE_NOMONSTERS", "const float", QW|NQ|CS, NULL, MOVE_NOMONSTERS},
{"MOVE_MISSILE", "const float", QW|NQ|CS, NULL, MOVE_MISSILE},
{"MOVE_HITMODEL", "const float", QW|NQ|CS, "Traces will impact the actual mesh of the model instead of merely their bounding box. Should generally only be used for tracelines. Note that this flag is unreliable as an object can animate through projectiles. The bounding box MUST be set to completely encompass the entity or those extra areas will be non-solid (leaving a hole for things to go through).", MOVE_HITMODEL},
{"MOVE_TRIGGERS", "const float", QW|NQ|CS, NULL, MOVE_TRIGGERS},
{"MOVE_EVERYTHING", "const float", QW|NQ|CS, NULL, MOVE_EVERYTHING},
{"MOVE_TRIGGERS", "const float", QW|NQ|CS, "This trace type will impact only triggers. It will ignore non-solid entities.", MOVE_TRIGGERS},
{"MOVE_EVERYTHING", "const float", QW|NQ|CS, "This type of trace will hit solids and triggers alike. Even non-solid entities.", MOVE_EVERYTHING},
{"MOVE_LAGGED", "const float", QW|NQ, "Will use antilag based upon the player's latency. Traces will be performed against old positions for entities instead of their current origin.", MOVE_LAGGED},
{"MOVE_ENTCHAIN", "const float", QW|NQ|CS, "Returns a list of entities impacted via the trace_ent.chain field", MOVE_ENTCHAIN},
{"MOVE_ONLYENT", "const float", QW|NQ|CS, "Traces that use this trace type will collide against *only* the entity specified, and will ignore all owner/solid/dimension etc fields, they will still adhere to contents though.", MOVE_ONLYENT},
{"EF_BRIGHTFIELD", "const float", QW|NQ|CS, NULL, EF_BRIGHTFIELD},
{"EF_MUZZLEFLASH", "const float", NQ|CS, NULL, EF_MUZZLEFLASH},
@ -10610,7 +10561,7 @@ void PR_DumpPlatform_f(void)
// {"EV_FUNCTION", "const float", QW|NQ, NULL, ev_function},
// {"EV_POINTER", "const float", QW|NQ, NULL, ev_pointer},
{"EV_INTEGER", "const float", QW|NQ, NULL, ev_integer},
// {"EV_INTEGER", "const float", QW|NQ, NULL, ev_variant},
// {"EV_VARIANT", "const float", QW|NQ, NULL, ev_variant},
// {"EV_STRUCT", "const float", QW|NQ, NULL, ev_struct},
// {"EV_UNION", "const float", QW|NQ, NULL, ev_union},
@ -10639,21 +10590,21 @@ void PR_DumpPlatform_f(void)
{"VF_SIZE", "const float", CS, NULL, VF_SIZE},
{"VF_SIZE_X", "const float", CS, NULL, VF_SIZE_X},
{"VF_SIZE_Y", "const float", CS, NULL, VF_SIZE_Y},
{"VF_VIEWPORT", "const float", CS, NULL, VF_VIEWPORT},
{"VF_VIEWPORT", "const float", CS, "vector+vector. Two argument shortcut for VF_MIN and VF_SIZE", VF_VIEWPORT},
{"VF_FOV", "const float", CS, "sets both fovx and fovy. consider using afov instead.", VF_FOV},
{"VF_FOVX", "const float", CS, "horizontal field of view. does not consider aspect at all.", VF_FOVX},
{"VF_FOVY", "const float", CS, "vertical field of view. does not consider aspect at all.", VF_FOVY},
{"VF_ORIGIN", "const float", CS, NULL, VF_ORIGIN},
{"VF_ORIGIN", "const float", CS, "The origin of the view. Not of the player.", VF_ORIGIN},
{"VF_ORIGIN_X", "const float", CS, NULL, VF_ORIGIN_X},
{"VF_ORIGIN_Y", "const float", CS, NULL, VF_ORIGIN_Y},
{"VF_ORIGIN_Z", "const float", CS, NULL, VF_ORIGIN_Z},
{"VF_ANGLES", "const float", CS, NULL, VF_ANGLES},
{"VF_ANGLES", "const float", CS, "The angles the view will be drawn at. Not the angle the client reports to the server.", VF_ANGLES},
{"VF_ANGLES_X", "const float", CS, NULL, VF_ANGLES_X},
{"VF_ANGLES_Y", "const float", CS, NULL, VF_ANGLES_Y},
{"VF_ANGLES_Z", "const float", CS, NULL, VF_ANGLES_Z},
{"VF_DRAWWORLD", "const float", CS, NULL, VF_DRAWWORLD},
{"VF_DRAWENGINESBAR", "const float", CS, NULL, VF_ENGINESBAR},
{"VF_DRAWCROSSHAIR", "const float", CS, NULL, VF_DRAWCROSSHAIR},
{"VF_DRAWWORLD", "const float", CS, "boolean. If set to 1, the engine will draw the world and static/persistant rtlights. If 0, the world will be skipped and everything will be fullbright.", VF_DRAWWORLD},
{"VF_DRAWENGINESBAR", "const float", CS, "boolean. If set to 1, the sbar will be drawn, and viewsize will be honoured automatically.", VF_ENGINESBAR},
{"VF_DRAWCROSSHAIR", "const float", CS, "boolean. If set to 1, the engine will draw its default crosshair.", VF_DRAWCROSSHAIR},
{"VF_CL_VIEWANGLES", "const float", CS, NULL, VF_CL_VIEWANGLES_V},
{"VF_CL_VIEWANGLES_X", "const float", CS, NULL, VF_CL_VIEWANGLES_X},

View file

@ -200,10 +200,12 @@ and the extension fields are added on the end and can have extra vm-specific stu
comfieldfloat(fatness,NULL)/*FTE_PEXT_FATNESS*/\
comfieldfloat(alpha,NULL)/*DP_ENT_ALPHA*/\
comfieldentity(tag_entity,NULL)\
comfieldfloat(tag_index,NULL)\
comfieldfloat(skeletonindex,NULL) /*FTE_CSQC_SKELETONOBJECTS*/\
comfieldvector(colormod,NULL)\
comfieldvector(glowmod,NULL)\
comfieldvector(gravitydir,NULL)\
comfieldfunction(camera_transform,".vector(vector org, vector ang)", NULL)\
comfieldfloat(pmove_flags,NULL)/*EXT_CSQC_1*/\
comfieldfloat(friction,NULL)/*DP_...PHYSICS*/\
comfieldfloat(erp,NULL)/*DP_...PHYSICS*/\
@ -229,7 +231,6 @@ and the extension fields are added on the end and can have extra vm-specific stu
comfieldfloat(button7,NULL)\
comfieldfloat(button8,NULL)\
comfieldfloat(viewzoom,NULL)/*DP_VIEWZOOM*/\
comfieldfloat(tag_index,NULL)\
comfieldfloat(glow_size,NULL)\
comfieldfloat(glow_color,NULL)\
comfieldfloat(glow_trail,NULL)\

View file

@ -260,7 +260,7 @@ void SVNQ_CreateBaseline (void)
if (!svent->baseline.modelindex)
svent->baseline.modelindex = playermodel;
}
svent->baseline.modelindex&=255;
svent->baseline.modelindex&=255; //FIXME
}
}
@ -598,6 +598,83 @@ void SV_UpdateMaxPlayers(int newmax)
sv.allocated_client_slots = svs.allocated_client_slots;
}
static void SV_SetupNetworkBuffers(qboolean bigcoords)
{
int i;
//determine basic primitive sizes.
if (bigcoords)
{
svs.netprim.coordsize = 4;
svs.netprim.anglesize = 2;
}
else
{
svs.netprim.coordsize = 2;
svs.netprim.anglesize = 1;
}
//FIXME: this should be part of sv_new_f or something instead, so that any angles sent by clients won't be invalid
for (i = 0; i < svs.allocated_client_slots; i++)
{
svs.clients[i].datagram.prim = svs.netprim;
svs.clients[i].netchan.message.prim = svs.netprim;
}
//
sv.datagram.maxsize = sizeof(sv.datagram_buf);
sv.datagram.data = sv.datagram_buf;
sv.datagram.allowoverflow = true;
sv.datagram.prim = svs.netprim;
sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
sv.reliable_datagram.data = sv.reliable_datagram_buf;
sv.reliable_datagram.prim = svs.netprim;
sv.multicast.maxsize = sizeof(sv.multicast_buf);
sv.multicast.data = sv.multicast_buf;
sv.multicast.prim = svs.netprim;
#ifdef NQPROT
sv.nqdatagram.maxsize = sizeof(sv.nqdatagram_buf);
sv.nqdatagram.data = sv.nqdatagram_buf;
sv.nqdatagram.allowoverflow = true;
sv.nqdatagram.prim = svs.netprim;
sv.nqreliable_datagram.maxsize = sizeof(sv.nqreliable_datagram_buf);
sv.nqreliable_datagram.data = sv.nqreliable_datagram_buf;
sv.nqreliable_datagram.prim = svs.netprim;
sv.nqmulticast.maxsize = sizeof(sv.nqmulticast_buf);
sv.nqmulticast.data = sv.nqmulticast_buf;
sv.nqmulticast.prim = svs.netprim;
#endif
#ifdef Q2SERVER
sv.q2datagram.maxsize = sizeof(sv.q2datagram_buf);
sv.q2datagram.data = sv.q2datagram_buf;
sv.q2datagram.allowoverflow = true;
sv.q2datagram.prim = svs.netprim;
sv.q2reliable_datagram.maxsize = sizeof(sv.q2reliable_datagram_buf);
sv.q2reliable_datagram.data = sv.q2reliable_datagram_buf;
sv.q2reliable_datagram.prim = svs.netprim;
sv.q2multicast.maxsize = sizeof(sv.q2multicast_buf);
sv.q2multicast.data = sv.q2multicast_buf;
sv.q2multicast.prim = svs.netprim;
#endif
sv.master.maxsize = sizeof(sv.master_buf);
sv.master.data = sv.master_buf;
sv.master.prim = msg_nullnetprim;
sv.signon.maxsize = sizeof(sv.signon_buffers[0]);
sv.signon.data = sv.signon_buffers[0];
sv.signon.prim = svs.netprim;
sv.num_signon_buffers = 1;
}
/*
================
SV_SpawnServer
@ -677,21 +754,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
T_FreeStrings();
}
if (sv_bigcoords.value)
{
svs.netprim.coordsize = 4;
svs.netprim.anglesize = 2;
}
else
{
svs.netprim.coordsize = 2;
svs.netprim.anglesize = 1;
}
for (i = 0; i < svs.allocated_client_slots; i++)
{
svs.clients[i].datagram.prim = svs.netprim;
svs.clients[i].netchan.message.prim = svs.netprim;
svs.clients[i].nextservertimeupdate = 0;
if (!svs.clients[i].state) //bots with the net_preparse module.
svs.clients[i].userinfo[0] = '\0'; //clear the userinfo to clear the name
@ -732,57 +796,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
// wipe the entire per-level structure
memset (&sv, 0, sizeof(sv));
sv.datagram.maxsize = sizeof(sv.datagram_buf);
sv.datagram.data = sv.datagram_buf;
sv.datagram.allowoverflow = true;
sv.datagram.prim = svs.netprim;
sv.reliable_datagram.maxsize = sizeof(sv.reliable_datagram_buf);
sv.reliable_datagram.data = sv.reliable_datagram_buf;
sv.reliable_datagram.prim = svs.netprim;
sv.multicast.maxsize = sizeof(sv.multicast_buf);
sv.multicast.data = sv.multicast_buf;
sv.multicast.prim = svs.netprim;
#ifdef NQPROT
sv.nqdatagram.maxsize = sizeof(sv.nqdatagram_buf);
sv.nqdatagram.data = sv.nqdatagram_buf;
sv.nqdatagram.allowoverflow = true;
sv.nqdatagram.prim = svs.netprim;
sv.nqreliable_datagram.maxsize = sizeof(sv.nqreliable_datagram_buf);
sv.nqreliable_datagram.data = sv.nqreliable_datagram_buf;
sv.nqreliable_datagram.prim = svs.netprim;
sv.nqmulticast.maxsize = sizeof(sv.nqmulticast_buf);
sv.nqmulticast.data = sv.nqmulticast_buf;
sv.nqmulticast.prim = svs.netprim;
#endif
#ifdef Q2SERVER
sv.q2datagram.maxsize = sizeof(sv.q2datagram_buf);
sv.q2datagram.data = sv.q2datagram_buf;
sv.q2datagram.allowoverflow = true;
sv.q2datagram.prim = svs.netprim;
sv.q2reliable_datagram.maxsize = sizeof(sv.q2reliable_datagram_buf);
sv.q2reliable_datagram.data = sv.q2reliable_datagram_buf;
sv.q2reliable_datagram.prim = svs.netprim;
sv.q2multicast.maxsize = sizeof(sv.q2multicast_buf);
sv.q2multicast.data = sv.q2multicast_buf;
sv.q2multicast.prim = svs.netprim;
#endif
sv.master.maxsize = sizeof(sv.master_buf);
sv.master.data = sv.master_buf;
sv.master.prim = msg_nullnetprim;
sv.signon.maxsize = sizeof(sv.signon_buffers[0]);
sv.signon.data = sv.signon_buffers[0];
sv.signon.prim = svs.netprim;
sv.num_signon_buffers = 1;
SV_SetupNetworkBuffers(sv_bigcoords.ival);
if (allow_download_refpackages.ival)
FS_ReferenceControl(1, 1);
@ -1084,7 +1098,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
switch (svs.gametype)
{
case GT_MAX:
default:
SV_Error("bad gametype");
break;
case GT_Q1QVM:
case GT_PROGS:
@ -1146,8 +1161,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
#endif
}
break;
case GT_QUAKE2:
#ifdef Q2SERVER
case GT_QUAKE2:
SV_UpdateMaxPlayers(svq2_maxclients);
for (i=0 ; i<sv.allocated_client_slots ; i++)
{
@ -1155,18 +1170,19 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
q2ent->s.number = i+1;
svs.clients[i].q2edict = q2ent;
}
#endif
break;
case GT_QUAKE3:
#endif
#ifdef Q3SERVER
case GT_QUAKE3:
SV_UpdateMaxPlayers(32);
#endif
break;
case GT_HALFLIFE:
#endif
#ifdef HLSERVER
case GT_HALFLIFE:
SVHL_SetupGame();
#endif
SV_UpdateMaxPlayers(32);
break;
#endif
}
//fixme: is this right?
@ -1271,7 +1287,6 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
if (progstype == PROG_QW)
// run the frame start qc function to let progs check cvars
SV_ProgStartFrame (); //prydon gate seems to fail because of this allowance
}
// load and spawn all other entities
@ -1336,24 +1351,23 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
switch(svs.gametype)
{
case GT_MAX:
default:
break;
case GT_Q1QVM:
case GT_PROGS:
sv.world.edict_size = PR_LoadEnts(svprogfuncs, file?file :sv.world.worldmodel->entities, spawnflagmask);
break;
case GT_QUAKE2:
#ifdef Q2SERVER
case GT_QUAKE2:
ge->SpawnEntities(sv.name, file?file :sv.world.worldmodel->entities, startspot?startspot:"");
#endif
break;
#endif
case GT_QUAKE3:
break;
case GT_HALFLIFE:
#ifdef HLSERVER
SVHL_SpawnEntities(file?file :sv.world.worldmodel->entities));
case GT_HALFLIFE:
SVHL_SpawnEntities(file?file :sv.world.worldmodel->entities); break;
#endif
break;
}
#ifndef SERVERONLY
@ -1462,6 +1476,33 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
SCR_ImageName(server);
#endif
/*world is now spawned. switch to big coords if there are entities outside the bounds of the map*/
if (!*sv_bigcoords.string && svprogfuncs)
{
float extent = 0, ne;
//fixme: go off bsp extents instead?
for(i = 1; i < sv.world.num_edicts; i++)
{
ent = EDICT_NUM(svprogfuncs, i);
for (j = 0; j < 3; j++)
{
ne = fabs(ent->v->origin[j]);
if (extent < ne)
extent = ne;
}
}
if (extent > (1u<<15)/8)
{
if (sv.num_signon_buffers > 1 || sv.signon.cursize)
Con_Printf("Cannot auto-enable extended coords as the init buffer was used\n");
else
{
Con_Printf("Switching to extended coord sizes\n");
SV_SetupNetworkBuffers(true);
}
}
}
/*DP_BOTCLIENT bots should move over to the new map too*/
if (svs.gametype == GT_PROGS || svs.gametype == GT_Q1QVM)
{

View file

@ -1709,8 +1709,13 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
int i;
int maxpacketentities;
extern cvar_t pr_maxedicts;
client->maxmodels = 256;
//some gamecode can't cope with some extensions for some reasons... and I'm too lazy to fix the code to cope.
if (svs.gametype == GT_HALFLIFE)
client->fteprotocolextensions2 &= ~PEXT2_REPLACEMENTDELTAS;
//
client->maxmodels = 256;
if (client->fteprotocolextensions & PEXT_256PACKETENTITIES)
maxpacketentities = MAX_EXTENDED_PACKET_ENTITIES;
else
@ -5034,7 +5039,7 @@ void SV_Init (quakeparms_t *parms)
#ifdef SVRANKING
Rank_RegisterCommands();
#endif
Cbuf_AddText("alias restart \"map .\"\nalias newgame \"map start\"\n", RESTRICT_LOCAL);
Cbuf_AddText("alias restart \"map .\"\nalias startmap_sp \"map start\"\n", RESTRICT_LOCAL);
#ifndef SERVERONLY
if (isDedicated)

View file

@ -257,6 +257,60 @@ static void ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce
out[i] = 0;
}
static void WPhys_PortalTransform(world_t *w, wedict_t *ent, wedict_t *portal, vec3_t org, vec3_t move)
{
int oself = *w->g.self;
void *pr_globals = PR_globals(w->progs, PR_CURRENT);
*w->g.self = EDICT_TO_PROG(w->progs, portal);
//transform origin+velocity etc
VectorCopy(org, G_VECTOR(OFS_PARM0));
VectorAngles(ent->v->angles, vup, G_VECTOR(OFS_PARM1));
VectorCopy(ent->v->velocity, w->g.v_forward);
VectorCopy(move, w->g.v_right);
VectorCopy(ent->xv->gravitydir, w->g.v_up);
if (!DotProduct(w->g.v_up, w->g.v_up))
w->g.v_up[2] = -1;
PR_ExecuteProgram (w->progs, portal->xv->camera_transform);
VectorCopy(G_VECTOR(OFS_RETURN), org);
// VectorCopy(w->g.v_forward, ent->v->velocity);
VectorCopy(w->g.v_right, move);
// VectorCopy(w->g.v_up, ent->xv->gravitydir);
//transform the angles too
VectorCopy(org, G_VECTOR(OFS_PARM0));
if (ent->entnum <= svs.allocated_client_slots)
{
VectorCopy(ent->v->v_angle, ent->v->angles);
ent->v->fixangle = true;
}
else
ent->v->angles[0] *= -1;
VectorAngles(ent->v->angles, vup, G_VECTOR(OFS_PARM1));
AngleVectors(ent->v->angles, w->g.v_forward, w->g.v_right, w->g.v_up);
PR_ExecuteProgram (w->progs, portal->xv->camera_transform);
VectorAngles(w->g.v_forward, w->g.v_up, ent->v->angles);
if (ent->entnum <= svs.allocated_client_slots)
ent->v->angles[0] *= -1;
/*
avelocity is horribly dependant upon eular angles. trying to treat it as a matrix is folly.
if (DotProduct(ent->v->avelocity, ent->v->avelocity))
{
ent->v->avelocity[0] *= -1;
AngleVectors(ent->v->avelocity, w->g.v_forward, w->g.v_right, w->g.v_up);
PR_ExecuteProgram (w->progs, portal->xv->camera_transform);
VectorAngles(w->g.v_forward, w->g.v_up, ent->v->avelocity);
ent->v->avelocity[0] *= -1;
}
*/
*w->g.self = oself;
}
/*
@ -285,6 +339,7 @@ static int WPhys_FlyMove (world_t *w, wedict_t *ent, const vec3_t gravitydir, fl
vec3_t end;
float time_left;
int blocked;
wedict_t *impact;
vec3_t diff;
numbumps = 4;
@ -301,7 +356,26 @@ static int WPhys_FlyMove (world_t *w, wedict_t *ent, const vec3_t gravitydir, fl
for (i=0 ; i<3 ; i++)
end[i] = ent->v->origin[i] + time_left * ent->v->velocity[i];
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, false, (wedict_t*)ent);
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, (wedict_t*)ent);
impact = trace.ent;
if (impact && impact->v->solid == SOLID_PORTAL)
{
vec3_t move;
vec3_t from;
float firstfrac = trace.fraction;
Con_Printf("Player hit portal %i\n", impact->entnum);
VectorCopy(trace.endpos, from); //just in case
VectorSubtract(end, trace.endpos, move);
WPhys_PortalTransform(w, ent, impact, trace.endpos, move);
VectorAdd(trace.endpos, move, end);
trace = World_Move (w, from, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, (wedict_t*)ent);
trace.fraction = firstfrac + (1-firstfrac)*trace.fraction;
//if we follow the portal, then we need to fix up some velocities.
if (trace.fraction > 0)
VectorCopy (ent->v->velocity, primal_velocity);
}
if (trace.startsolid)
{ // entity is trapped in another solid
@ -463,6 +537,7 @@ static trace_t WPhys_PushEntity (world_t *w, wedict_t *ent, vec3_t push, unsigne
{
trace_t trace;
vec3_t end;
wedict_t *impact;
VectorAdd (ent->v->origin, push, end);
@ -470,12 +545,28 @@ static trace_t WPhys_PushEntity (world_t *w, wedict_t *ent, vec3_t push, unsigne
traceflags |= MOVE_LAGGED;
if (ent->v->movetype == MOVETYPE_FLYMISSILE)
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_MISSILE|traceflags, (wedict_t*)ent);
traceflags |= MOVE_MISSILE;
else if (ent->v->solid == SOLID_TRIGGER || ent->v->solid == SOLID_NOT)
// only clip against bmodels
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS|traceflags, (wedict_t*)ent);
traceflags |= MOVE_NOMONSTERS;
else
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL|traceflags, (wedict_t*)ent);
traceflags |= MOVE_NORMAL;
trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, traceflags, (wedict_t*)ent);
impact = trace.ent;
if (impact && impact->v->solid == SOLID_PORTAL)
{
vec3_t move;
vec3_t from;
float firstfrac = trace.fraction;
VectorCopy(trace.endpos, from); //just in case
VectorSubtract(end, trace.endpos, move);
WPhys_PortalTransform(w, ent, impact, from, move);
VectorAdd(from, move, end);
trace = World_Move (w, from, ent->v->mins, ent->v->maxs, end, traceflags, (wedict_t*)ent);
trace.fraction = firstfrac + (1-firstfrac)*trace.fraction;
}
/*hexen2's movetype_swim does not allow swimming entities to move out of water. this implementation is quite hacky, but matches hexen2 well enough*/
if (ent->v->movetype == MOVETYPE_H2SWIM)

View file

@ -7368,6 +7368,7 @@ void SV_ClientThink (void)
VectorCopy (sv_player->v->v_angle, v_angle);
// VectorAdd (sv_player->v->v_angle, sv_player->v->punchangle, v_angle);
//FIXME: gravitydir stuff, the roll value gets destroyed for intents
angles[ROLL] = V_CalcRoll (sv_player->v->angles, sv_player->v->velocity)*4;
if (!sv_player->v->fixangle)
{

View file

@ -23,15 +23,21 @@ I think globals.maxentities is the hard cap, rather than current max like in q1.
//I hope you're c99 and have a __func__
#endif
#define ignore(s) Con_Printf("Fixme: " s "\n")
extern cvar_t temp1;
#define ignore(s) Con_DPrintf("Fixme: " s "\n")
#define notimpl(l) Con_Printf("halflife sv builtin not implemented on line %i\n", l)
#define notimpf(f) Con_Printf("halflife sv builtin %s not implemented\n", f)
#define bi_begin() if (temp1.ival)Con_Printf("enter %s\n", __func__)
#define bi_end() if (temp1.ival)Con_Printf("leave %s\n", __func__)
#define bi_trace() bi_begin(); bi_end()
dllhandle_t *hlgamecode;
SVHL_Globals_t SVHL_Globals;
SVHL_GameFuncs_t SVHL_GameFuncs;
static zonegroup_t hlmapmemgroup; //flushed at end-of-map.
#define MAX_HL_EDICTS 2048
hledict_t *SVHL_Edict;
int SVHL_NumActiveEnts;
@ -44,13 +50,18 @@ int lastusermessage;
string_t QDECL GHL_AllocString(char *string)
{
char *news;
news = Hunk_Alloc(strlen(string)+1);
bi_begin();
if (!string)
return 0;
news = ZG_Malloc(&hlmapmemgroup, strlen(string)+1);
memcpy(news, string, strlen(string)+1);
bi_end();
return news - SVHL_Globals.stringbase;
}
int QDECL GHL_PrecacheModel(char *name)
{
int i;
bi_trace();
if (name[0] <= ' ')
{
@ -98,6 +109,7 @@ int QDECL GHL_PrecacheModel(char *name)
int QDECL GHL_PrecacheSound(char *name)
{
int i;
bi_trace();
if (name[0] <= ' ')
{
@ -144,6 +156,7 @@ void QDECL GHL_SetModel(hledict_t *ed, char *modelname)
{
model_t *mod;
int mdlidx = GHL_PrecacheModel(modelname);
bi_trace();
ed->v.modelindex = mdlidx;
ed->v.model = sv.strings.model_precache[mdlidx] - SVHL_Globals.stringbase;
@ -159,18 +172,21 @@ void QDECL GHL_SetModel(hledict_t *ed, char *modelname)
unk QDECL GHL_ModelIndex(unk){notimpf(__func__);}
int QDECL GHL_ModelFrames(int midx)
{
bi_trace();
//returns the number of frames(sequences I assume) this model has
ignore("ModelFrames");
return 1;
}
void QDECL GHL_SetSize(hledict_t *ed, float *mins, float *maxs)
{
bi_trace();
VectorCopy(mins, ed->v.mins);
VectorCopy(maxs, ed->v.maxs);
SVHL_LinkEdict(ed, false);
}
void QDECL GHL_ChangeLevel(char *nextmap, char *startspot)
{
bi_trace();
Cbuf_AddText(va("changelevel %s %s@%f@%f@%f\n", nextmap, startspot, SVHL_Globals.landmark[0], SVHL_Globals.landmark[1], SVHL_Globals.landmark[2]), RESTRICT_PROGS);
}
unk QDECL GHL_GetSpawnParms(unk){notimpf(__func__);}
@ -178,15 +194,21 @@ unk QDECL GHL_SaveSpawnParms(unk){notimpf(__func__);}
float QDECL GHL_VecToYaw(float *inv)
{
vec3_t outa;
bi_trace();
VectorAngles(inv, NULL, outa);
return outa[1];
}
void QDECL GHL_VecToAngles(float *inv, float *outa)
{
bi_trace();
VectorAngles(inv, NULL, outa);
}
unk QDECL GHL_MoveToOrigin(unk){notimpf(__func__);}
void QDECL GHL_MoveToOrigin(hledict_t *ent, vec3_t dest, float dist, int moveflags)
{
bi_trace();
ignore("GHL_MoveToOrigin");
}
unk QDECL GHL_ChangeYaw(unk){notimpf(__func__);}
unk QDECL GHL_ChangePitch(unk){notimpf(__func__);}
hledict_t *QDECL GHL_FindEntityByString(hledict_t *last, char *field, char *value)
@ -195,6 +217,7 @@ hledict_t *QDECL GHL_FindEntityByString(hledict_t *last, char *field, char *valu
int i;
int ofs;
string_t str;
bi_trace();
if (!strcmp(field, "targetname"))
ofs = (char*)&((hledict_t *)NULL)->v.targetname - (char*)NULL;
else if (!strcmp(field, "classname"))
@ -227,6 +250,8 @@ hledict_t *QDECL GHL_FindEntityInSphere(hledict_t *last, float *org, float radiu
vec3_t eorg;
hledict_t *ent;
bi_trace();
radius = radius*radius;
if (last)
@ -260,6 +285,8 @@ hledict_t *QDECL GHL_FindClientInPVS(hledict_t *ed)
vec3_t ofs;
hledict_t *other;
bi_trace();
//fixme: we need to track some state
//a different client should be returned each call _per ent_ (so it can be used once per frame)
@ -297,10 +324,12 @@ hledict_t *QDECL GHL_FindClientInPVS(hledict_t *ed)
unk QDECL GHL_EntitiesInPVS(unk){notimpf(__func__);}
void QDECL GHL_MakeVectors(float *angles)
{
bi_trace();
AngleVectors(angles, SVHL_Globals.v_forward, SVHL_Globals.v_right, SVHL_Globals.v_up);
}
void QDECL GHL_AngleVectors(float *angles, float *forward, float *right, float *up)
{
bi_trace();
AngleVectors(angles, forward, right, up);
}
@ -310,6 +339,7 @@ hledict_t *QDECL GHL_CreateEntity(void)
{
int i;
static int spawnnumber;
bi_trace();
spawnnumber++;
for (i = sv.allocated_client_slots; i < SVHL_NumActiveEnts; i++)
@ -338,6 +368,7 @@ hledict_t *QDECL GHL_CreateEntity(void)
}
void QDECL GHL_RemoveEntity(hledict_t *ed)
{
bi_trace();
SVHL_UnlinkEdict(ed);
ed->isfree = true;
ed->freetime = sv.time+2;
@ -346,6 +377,7 @@ hledict_t *QDECL GHL_CreateNamedEntity(string_t name)
{
void (QDECL *spawnfunc)(hlentvars_t *evars);
hledict_t *ed;
bi_trace();
ed = GHL_CreateEntity();
if (!ed)
return NULL;
@ -358,41 +390,50 @@ hledict_t *QDECL GHL_CreateNamedEntity(string_t name)
}
void *QDECL GHL_PvAllocEntPrivateData(hledict_t *ed, long quant)
{
bi_trace();
if (!ed)
return NULL;
ed->moddata = Z_Malloc(quant);
ed->moddata = ZG_Malloc(&hlmapmemgroup, quant);
return ed->moddata;
}
unk QDECL GHL_PvEntPrivateData(unk)
{
bi_trace();
notimpf(__func__);
}
unk QDECL GHL_FreeEntPrivateData(unk)
{
bi_trace();
notimpf(__func__);
}
unk QDECL GHL_GetVarsOfEnt(unk)
{
bi_trace();
notimpf(__func__);
}
hledict_t *QDECL GHL_PEntityOfEntOffset(int ednum)
{
bi_trace();
return (hledict_t *)(ednum + (char*)SVHL_Edict);
}
int QDECL GHL_EntOffsetOfPEntity(hledict_t *ed)
{
bi_trace();
return (char*)ed - (char*)SVHL_Edict;
}
int QDECL GHL_IndexOfEdict(hledict_t *ed)
{
bi_trace();
return ed - SVHL_Edict;
}
hledict_t *QDECL GHL_PEntityOfEntIndex(int idx)
{
bi_trace();
return &SVHL_Edict[idx];
}
unk QDECL GHL_FindEntityByVars(unk)
{
bi_trace();
notimpf(__func__);
}
@ -405,6 +446,7 @@ int QDECL GHL_DropToFloor(hledict_t *ed)
vec3_t top;
vec3_t bottom;
trace_t tr;
bi_trace();
VectorCopy(ed->v.origin, top);
VectorCopy(ed->v.origin, bottom);
top[2] += 1;
@ -415,25 +457,30 @@ int QDECL GHL_DropToFloor(hledict_t *ed)
}
int QDECL GHL_WalkMove(hledict_t *ed, float yaw, float dist, int mode)
{
bi_trace();
ignore("walkmove");
return 1;
}
void QDECL GHL_SetOrigin(hledict_t *ed, float *neworg)
{
bi_trace();
VectorCopy(neworg, ed->v.origin);
SVHL_LinkEdict(ed, false);
}
void QDECL GHL_EmitSound(hledict_t *ed, int chan, char *soundname, float vol, float atten, int flags, int pitch)
{
bi_trace();
SV_StartSound(ed-SVHL_Edict, ed->v.origin, ~0, chan, soundname, vol*255, atten, pitch);
}
void QDECL GHL_EmitAmbientSound(hledict_t *ed, float *org, char *soundname, float vol, float atten, unsigned int flags, int pitch)
{
bi_trace();
SV_StartSound(0, org, ~0, 0, soundname, vol*255, atten, 0);
}
void QDECL GHL_TraceLine(float *start, float *end, int flags, hledict_t *ignore, hltraceresult_t *result)
{
trace_t t;
bi_trace();
t = SVHL_Move(start, vec3_origin, vec3_origin, end, flags, 0, ignore);
@ -455,6 +502,7 @@ unk QDECL GHL_TraceMonsterHull(unk){notimpf(__func__);}
void QDECL GHL_TraceHull(float *start, float *end, int flags, int hullnum, hledict_t *ignore, hltraceresult_t *result)
{
trace_t t;
bi_trace();
t = SVHL_Move(start, sv.world.worldmodel->hulls[hullnum].clip_mins, sv.world.worldmodel->hulls[hullnum].clip_maxs, end, flags, 0, ignore);
@ -473,6 +521,7 @@ unk QDECL GHL_TraceModel(unk){notimpf(__func__);}
char *QDECL GHL_TraceTexture(hledict_t *againstent, vec3_t start, vec3_t end)
{
trace_t tr;
bi_trace();
sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, 0, NULL, start, end, vec3_origin, vec3_origin, MASK_WORLDSOLID, &tr);
return tr.surface->name;
}
@ -480,25 +529,30 @@ unk QDECL GHL_TraceSphere(unk){notimpf(__func__);}
unk QDECL GHL_GetAimVector(unk){notimpf(__func__);}
void QDECL GHL_ServerCommand(char *cmd)
{
bi_trace();
Cbuf_AddText(cmd, RESTRICT_PROGS);
}
void QDECL GHL_ServerExecute(void)
{
bi_trace();
Cbuf_ExecuteLevel(RESTRICT_PROGS);
}
unk QDECL GHL_ClientCommand(unk){notimpf(__func__);}
unk QDECL GHL_ParticleEffect(unk){notimpf(__func__);}
void QDECL GHL_LightStyle(int stylenum, char *stylestr)
{
bi_trace();
PF_applylightstyle(stylenum, stylestr, 7);
}
int QDECL GHL_DecalIndex(char *decalname)
{
bi_trace();
Con_Printf("Fixme: precache decal %s\n", decalname);
return 0;
}
int QDECL GHL_PointContents(float *org)
{
bi_trace();
return Q1CONTENTS_EMPTY;
}
@ -507,6 +561,8 @@ vec3_t svhl_messageorigin;
hledict_t *svhl_messageent;
void QDECL GHL_MessageBegin(int dest, int type, float *org, hledict_t *ent)
{
bi_trace();
svhl_messagedest = dest;
if (org)
VectorCopy(org, svhl_messageorigin);
@ -528,6 +584,8 @@ void QDECL GHL_MessageEnd(unk)
unsigned short len;
client_t *cl;
bi_trace();
if (!sv.multicast.cursize)
{
Con_Printf("MessageEnd called without MessageBegin\n");
@ -570,35 +628,43 @@ void QDECL GHL_MessageEnd(unk)
}
void QDECL GHL_WriteByte(int value)
{
bi_trace();
MSG_WriteByte(&sv.multicast, value);
}
void QDECL GHL_WriteChar(int value)
{
bi_trace();
MSG_WriteChar(&sv.multicast, value);
}
void QDECL GHL_WriteShort(int value)
{
bi_trace();
MSG_WriteShort(&sv.multicast, value);
}
void QDECL GHL_WriteLong(int value)
{
bi_trace();
MSG_WriteLong(&sv.multicast, value);
}
void QDECL GHL_WriteAngle(float value)
{
bi_trace();
MSG_WriteAngle8(&sv.multicast, value);
}
void QDECL GHL_WriteCoord(float value)
{
coorddata i = MSG_ToCoord(value, 2);
bi_trace();
SZ_Write (&sv.multicast, (void*)&i, 2);
}
void QDECL GHL_WriteString(char *string)
{
bi_trace();
MSG_WriteString(&sv.multicast, string);
}
void QDECL GHL_WriteEntity(int entnum)
{
bi_trace();
MSG_WriteEntity(&sv.multicast, entnum);
}
@ -608,6 +674,11 @@ void QDECL GHL_AlertMessage(int level, char *fmt, ...)
va_list argptr;
char string[1024];
bi_trace();
if (level == 2 && !developer.ival)
return;
va_start (argptr, fmt);
vsnprintf (string,sizeof(string)-1, fmt,argptr);
va_end (argptr);
@ -616,11 +687,13 @@ void QDECL GHL_AlertMessage(int level, char *fmt, ...)
}
void QDECL GHL_EngineFprintf(FILE *f, char *fmt, ...)
{
bi_trace();
SV_Error("Halflife gamecode tried to use EngineFprintf\n");
}
unk QDECL GHL_SzFromIndex(unk){notimpf(__func__);}
void *QDECL GHL_GetModelPtr(hledict_t *ed)
{
bi_trace();
#ifdef SERVERONLY
return NULL;
#else
@ -633,6 +706,7 @@ void *QDECL GHL_GetModelPtr(hledict_t *ed)
}
int QDECL GHL_RegUserMsg(char *msgname, int msgsize)
{
bi_trace();
//we use 1 as the code to choose others.
if (lastusermessage <= 1)
return -1;
@ -660,44 +734,53 @@ unk QDECL GHL_GetBonePosition(unk){notimpf(__func__);}
hlintptr_t QDECL GHL_FunctionFromName(char *name)
{
bi_trace();
return (hlintptr_t)Sys_GetAddressForName(hlgamecode, name);
}
char *QDECL GHL_NameForFunction(hlintptr_t function)
{
bi_trace();
return Sys_GetNameForAddress(hlgamecode, (void*)function);
}
unk QDECL GHL_ClientPrintf(unk)
{
bi_trace();
// SV_ClientPrintf(
notimpf(__func__);
}
void QDECL GHL_ServerPrint(char *msg)
{
bi_trace();
Con_Printf("%s", msg);
}
char *QDECL GHL_Cmd_Args(void)
{
bi_trace();
return Cmd_Args();
}
char *QDECL GHL_Cmd_Argv(int arg)
{
bi_trace();
return Cmd_Argv(arg);
}
int QDECL GHL_Cmd_Argc(unk)
{
bi_trace();
return Cmd_Argc();
}
unk QDECL GHL_GetAttachment(unk){notimpf(__func__);}
void QDECL GHL_CRC32_Init(hlcrc_t *crc)
{
unsigned short crc16 = *crc;
bi_trace();
QCRC_Init(&crc16);
*crc = crc16;
}
void QDECL GHL_CRC32_ProcessBuffer(hlcrc_t *crc, qbyte *p, int len)
{
unsigned short crc16 = *crc;
bi_trace();
while(len-->0)
{
QCRC_ProcessByte(&crc16, *p++);
@ -707,20 +790,24 @@ void QDECL GHL_CRC32_ProcessBuffer(hlcrc_t *crc, qbyte *p, int len)
void QDECL GHL_CRC32_ProcessByte(hlcrc_t *crc, qbyte b)
{
unsigned short crc16 = *crc;
bi_trace();
QCRC_ProcessByte(&crc16, b);
*crc = crc16;
}
hlcrc_t QDECL GHL_CRC32_Final(hlcrc_t crc)
{
unsigned short crc16 = crc;
bi_trace();
return QCRC_Value(crc16);
}
long QDECL GHL_RandomLong(long minv, long maxv)
{
bi_trace();
return minv + frandom()*(maxv-minv);
}
float QDECL GHL_RandomFloat(float minv, float maxv)
{
bi_trace();
return minv + frandom()*(maxv-minv);
}
unk QDECL GHL_SetView(unk){notimpf(__func__);}
@ -730,6 +817,7 @@ void *QDECL GHL_LoadFileForMe(char *name, int *size_out)
{
int fsize;
void *fptr;
bi_trace();
fsize = FS_LoadFile(name, &fptr);
if (size_out)
*size_out = fsize;
@ -739,6 +827,7 @@ void *QDECL GHL_LoadFileForMe(char *name, int *size_out)
}
void QDECL GHL_FreeFile(void *fptr)
{
bi_trace();
FS_FreeFile(fptr);
}
unk QDECL GHL_EndSection(unk){notimpf(__func__);}
@ -747,6 +836,8 @@ int QDECL GHL_CompareFileTime(char *fname1, char *fname2, int *result)
{
flocation_t loc1, loc2;
struct stat stat1, stat2;
bi_trace();
//results:
//1 = f1 is newer
//0 = equal age
@ -771,6 +862,7 @@ int QDECL GHL_CompareFileTime(char *fname1, char *fname2, int *result)
void QDECL GHL_GetGameDir(char *gamedir)
{
extern char gamedirfile[];
bi_trace();
//warning: the output buffer size is not specified!
Q_strncpyz(gamedir, gamedirfile, MAX_QPATH);
}
@ -778,16 +870,19 @@ unk QDECL GHL_Cvar_RegisterVariable(unk){notimpf(__func__);}
unk QDECL GHL_FadeClientVolume(unk){notimpf(__func__);}
unk QDECL GHL_SetClientMaxspeed(unk)
{
bi_trace();
notimpf(__func__);
}
unk QDECL GHL_CreateFakeClient(unk){notimpf(__func__);}
unk QDECL GHL_RunPlayerMove(unk){notimpf(__func__);}
int QDECL GHL_NumberOfEntities(void)
{
bi_trace();
return 0;
}
char *QDECL GHL_GetInfoKeyBuffer(hledict_t *ed)
{
bi_trace();
if (!ed)
return svs.info;
@ -795,6 +890,7 @@ char *QDECL GHL_GetInfoKeyBuffer(hledict_t *ed)
}
char *QDECL GHL_InfoKeyValue(char *infostr, char *key)
{
bi_trace();
return Info_ValueForKey(infostr, key);
}
unk QDECL GHL_SetKeyValue(unk){notimpf(__func__);}
@ -805,6 +901,7 @@ unk QDECL GHL_PrecacheGeneric(unk){notimpf(__func__);}
int QDECL GHL_GetPlayerUserId(hledict_t *ed)
{
unsigned int clnum = (ed - SVHL_Edict) - 1;
bi_trace();
if (clnum >= sv.allocated_client_slots)
return -1;
return svs.clients[clnum].userid;
@ -813,6 +910,7 @@ unk QDECL GHL_BuildSoundMsg(unk){notimpf(__func__);}
int QDECL GHL_IsDedicatedServer(void)
{
bi_trace();
#ifdef SERVERONLY
return 1;
#else
@ -834,6 +932,7 @@ void SVHL_FreeCvars(void)
{
cvar_t *nc;
hlcvar_t *n;
//forget all
while (hlcvar_malloced)
{
@ -860,8 +959,8 @@ void SVHL_FreeCvar(hlcvar_t *var)
{
cvar_t *nc;
hlcvar_t **ref;
//unlink (free if it was malloced)
//unlink (free if it was malloced)
ref = &hlcvar_malloced;
while (*ref)
{
@ -898,6 +997,7 @@ hlcvar_t *QDECL GHL_CVarGetPointer(char *varname)
{
cvar_t *var;
hlcvar_t *hlvar;
bi_trace();
var = Cvar_Get(varname, "", 0, "HalfLife");
if (!var)
{
@ -920,6 +1020,7 @@ hlcvar_t *QDECL GHL_CVarGetPointer(char *varname)
void QDECL GHL_CVarRegister(hlcvar_t *hlvar)
{
cvar_t *var;
bi_trace();
var = Cvar_Get(hlvar->name, hlvar->string, 0, "HalfLife");
if (!var)
{
@ -938,6 +1039,7 @@ void QDECL GHL_CVarRegister(hlcvar_t *hlvar)
float QDECL GHL_CVarGetFloat(char *vname)
{
cvar_t *var = Cvar_FindVar(vname);
bi_trace();
if (var)
return var->value;
Con_Printf("cvar %s does not exist\n", vname);
@ -946,6 +1048,7 @@ float QDECL GHL_CVarGetFloat(char *vname)
char *QDECL GHL_CVarGetString(char *vname)
{
cvar_t *var = Cvar_FindVar(vname);
bi_trace();
if (var)
return var->string;
Con_Printf("cvar %s does not exist\n", vname);
@ -954,6 +1057,7 @@ char *QDECL GHL_CVarGetString(char *vname)
void QDECL GHL_CVarSetFloat(char *vname, float value)
{
cvar_t *var = Cvar_FindVar(vname);
bi_trace();
if (var)
Cvar_SetValue(var, value);
else
@ -962,6 +1066,7 @@ void QDECL GHL_CVarSetFloat(char *vname, float value)
void QDECL GHL_CVarSetString(char *vname, char *value)
{
cvar_t *var = Cvar_FindVar(vname);
bi_trace();
if (var)
Cvar_Set(var, value);
else
@ -971,15 +1076,22 @@ void QDECL GHL_CVarSetString(char *vname, char *value)
unk QDECL GHL_GetPlayerWONId(unk){notimpf(__func__);}
unk QDECL GHL_Info_RemoveKey(unk){notimpf(__func__);}
unk QDECL GHL_GetPhysicsKeyValue(unk){notimpf(__func__);}
unk QDECL GHL_SetPhysicsKeyValue(unk){notimpf(__func__);}
void QDECL GHL_SetPhysicsKeyValue(hledict_t *ent, char *key, char *value)
{
bi_begin();
notimpf(__func__);
bi_end();
}
unk QDECL GHL_GetPhysicsInfoString(unk){notimpf(__func__);}
unsigned short QDECL GHL_PrecacheEvent(int eventtype, char *eventname)
{
bi_trace();
Con_Printf("Fixme: GHL_PrecacheEvent: %s\n", eventname);
return 0;
}
void QDECL GHL_PlaybackEvent(int flags, hledict_t *ent, unsigned short eventidx, float delay, float *origin, float *angles, float f1, float f2, int i1, int i2, int b1, int b2)
{
bi_trace();
ignore("GHL_PlaybackEvent not implemented");
}
unk QDECL GHL_SetFatPVS(unk){notimpf(__func__);}
@ -991,6 +1103,7 @@ unk QDECL GHL_DeltaAddEncoder(unk){notimpf(__func__);}
unk QDECL GHL_GetCurrentPlayer(unk){notimpf(__func__);}
int QDECL GHL_CanSkipPlayer(hledict_t *playerent)
{
bi_trace();
return false;
// notimpf(__func__);
}
@ -1006,9 +1119,17 @@ unk QDECL GHL_AddServerCommand(unk){notimpf(__func__);}
unk QDECL GHL_Voice_GetClientListening(unk){notimpf(__func__);}
qboolean QDECL GHL_Voice_SetClientListening(int listener, int sender, int shouldlisten)
{
bi_trace();
return false;
}
unk QDECL GHL_GetPlayerAuthId(unk){notimpf(__func__);}
char *QDECL GHL_GetPlayerAuthId(hledict_t *playered)
{
unsigned int clnum = (playered - SVHL_Edict) - 1;
bi_trace();
if (clnum >= sv.allocated_client_slots)
return NULL;
return svs.clients[clnum].guid;
}
unk QDECL GHL_SequenceGet(unk){notimpf(__func__);}
unk QDECL GHL_SequencePickSentence(unk){notimpf(__func__);}
unk QDECL GHL_GetFileSize(unk){notimpf(__func__);}
@ -1234,7 +1355,8 @@ void SV_ReadLibListDotGam(void)
int SVHL_InitGame(void)
{
char *gamedll;
char *path;
void *iterator;
char path[MAX_OSPATH];
char fullname[MAX_OSPATH];
void (WINAPI *GiveFnptrsToDll) (funcs, globals);
int (QDECL *GetEntityAPI)(SVHL_GameFuncs_t *pFunctionTable, int apivers);
@ -1256,37 +1378,33 @@ int SVHL_InitGame(void)
if (hlgamecode)
{
SVHL_Edict = Hunk_Alloc(sizeof(*SVHL_Edict) * MAX_HL_EDICTS);
ZG_FreeGroup(&hlmapmemgroup);
SVHL_Edict = ZG_Malloc(&hlmapmemgroup, sizeof(*SVHL_Edict) * MAX_HL_EDICTS);
SVHL_Globals.maxentities = MAX_HL_EDICTS; //I think this is correct
return 1;
}
hlgamecode = NULL;//Sys_LoadLibrary("C:/Incoming/d/Half-Life/sdks/hlsdk-2.3-p3/hlsdk-2.3-p3/multiplayer/dlls/debugmp/mp.dll", hlgamefuncs);
if (!hlgamecode)
{
gamedll = Info_ValueForKey(svs.info, "*gamedll");
path = NULL;
while((path = COM_NextPath (path)))
iterator = NULL;
while(COM_IteratePaths(&iterator, path, sizeof(path)))
{
if (!path)
return 0; // couldn't find one anywhere
snprintf (fullname, sizeof(fullname), "%s/%s", path, gamedll);
snprintf (fullname, sizeof(fullname), "%s%s", path, gamedll);
hlgamecode = Sys_LoadLibrary(fullname, hlgamefuncs);
if (hlgamecode)
break;
}
}
if (!hlgamecode)
return 0;
SVHL_Edict = Hunk_Alloc(sizeof(*SVHL_Edict) * MAX_HL_EDICTS);
SVHL_Edict = ZG_Malloc(&hlmapmemgroup, sizeof(*SVHL_Edict) * MAX_HL_EDICTS);
SVHL_Globals.maxentities = MAX_HL_EDICTS; //I think this is correct
GiveFnptrsToDll(&SVHL_Builtins, &SVHL_Globals);
if (!GetEntityAPI(&SVHL_GameFuncs, HALFLIFE_API_VERSION))
{
Con_Printf(CON_ERROR "Error: %s is incompatible (FTE is %i)\n", fullname, HALFLIFE_API_VERSION);
Con_Printf(CON_ERROR "Error: %s is incompatible (FTE is compiled for %i)\n", fullname, HALFLIFE_API_VERSION);
if (GetEntityAPI(&SVHL_GameFuncs, 138))
Con_Printf(CON_ERROR "mod is 138\n");
Sys_CloseLibrary(hlgamecode);
@ -1294,7 +1412,9 @@ int SVHL_InitGame(void)
return 0;
}
bi_begin();
SVHL_GameFuncs.GameDLLInit();
bi_end();
return 1;
}
@ -1321,7 +1441,7 @@ void SVHL_SpawnEntities(char *entstring)
int i;
//initialise globals
SVHL_Globals.stringbase = "";
SVHL_Globals.stringbase = ""; //uninitialised strings are considered empty and not crashy. this ensures that is true.
SVHL_Globals.maxclients = svs.allocated_client_slots;
SVHL_Globals.deathmatch = deathmatch.value;
SVHL_Globals.coop = coop.value;
@ -1330,6 +1450,7 @@ void SVHL_SpawnEntities(char *entstring)
SVHL_NumActiveEnts = 0;
sv.allocated_client_slots = 0;
//touch world.
world = GHL_CreateNamedEntity(GHL_AllocString("worldspawn"));
@ -1337,7 +1458,6 @@ void SVHL_SpawnEntities(char *entstring)
GHL_SetModel(world, sv.modelname);
//spawn player ents
sv.allocated_client_slots = 0;
for (i = 0; i < SVHL_Globals.maxclients; i++)
{
sv.allocated_client_slots++;
@ -1428,7 +1548,9 @@ void SVHL_SpawnEntities(char *entstring)
SVHL_GameFuncs.DispatchSpawn(ed);
}
bi_begin();
SVHL_GameFuncs.ServerActivate(SVHL_Edict, SVHL_NumActiveEnts, sv.allocated_client_slots);
bi_end();
}
void SVHL_ShutdownGame(void)
@ -1443,6 +1565,8 @@ void SVHL_ShutdownGame(void)
memset(&SVHL_Globals, 0, sizeof(SVHL_Globals));
memset(&SVHL_GameFuncs, 0, sizeof(SVHL_GameFuncs));
memset(&SVHL_GameFuncsEx, 0, sizeof(SVHL_GameFuncsEx));
ZG_FreeGroup(&hlmapmemgroup);
}
qboolean HLSV_ClientCommand(client_t *client)
@ -1450,20 +1574,24 @@ qboolean HLSV_ClientCommand(client_t *client)
hledict_t *ed = &SVHL_Edict[client - svs.clients + 1];
if (!hlgamecode)
return false;
bi_begin();
SVHL_GameFuncs.ClientCommand(ed);
bi_end();
return true;
}
qboolean SVHL_ClientConnect(client_t *client, netadr_t adr, char rejectmessage[128])
{
qboolean result;
char ipadr[256];
NET_AdrToString(ipadr, sizeof(ipadr), adr);
NET_AdrToString(ipadr, sizeof(ipadr), &adr);
strcpy(rejectmessage, "Rejected by gamecode");
if (!SVHL_GameFuncs.ClientConnect(&SVHL_Edict[client-svs.clients+1], client->name, ipadr, rejectmessage))
return false;
bi_begin();
result = SVHL_GameFuncs.ClientConnect(&SVHL_Edict[client-svs.clients+1], client->name, ipadr, rejectmessage);
bi_end();
return true;
return result;
}
void SVHL_BuildStats(client_t *client, int *si, float *sf, char **ss)
@ -1480,17 +1608,21 @@ void SVHL_PutClientInServer(client_t *client)
{
hledict_t *ed = &SVHL_Edict[client - svs.clients + 1];
ed->isfree = false;
bi_begin();
SVHL_GameFuncs.ClientPutInServer(&SVHL_Edict[client-svs.clients+1]);
bi_end();
}
void SVHL_DropClient(client_t *drop)
{
hledict_t *ed = &SVHL_Edict[drop - svs.clients + 1];
bi_begin();
SVHL_GameFuncs.ClientDisconnect(&SVHL_Edict[drop-svs.clients+1]);
bi_end();
ed->isfree = true;
}
void SVHL_RunCmdR(hledict_t *ed, usercmd_t *ucmd)
static void SVHL_RunCmdR(hledict_t *ed, usercmd_t *ucmd)
{
int i;
hledict_t *other;
@ -1690,6 +1822,8 @@ void SVHL_RunCmd(client_t *cl, usercmd_t *ucmd)
ed->v.angles[1] = SHORT2ANGLE(ucmd->angles[1]);
ed->v.angles[2] = SHORT2ANGLE(ucmd->angles[2]);
bi_begin();
SVHL_GameFuncs.PlayerPreThink(ed);
SVHL_RunCmdR(ed, ucmd);
@ -1700,6 +1834,8 @@ void SVHL_RunCmd(client_t *cl, usercmd_t *ucmd)
}
SVHL_GameFuncs.PlayerPostThink(ed);
bi_end();
}
@ -1755,6 +1891,8 @@ void SVHL_Snapshot_Build(client_t *client, packet_entities_t *pack, qbyte *pvs,
s->frame = e->v.sequence1;
s->effects = e->v.effects;
s->skinnum = e->v.skin;
s->scale = 16;
s->trans = 255;
VectorCopy(e->v.angles, s->angles);
VectorCopy(e->v.origin, s->origin);
}

View file

@ -413,7 +413,7 @@ typedef struct
unk (QDECL *SaveSpawnParms)(unk);
float (QDECL *VecToYaw)(float *inv);
void (QDECL *VecToAngles)(float *inv, float *outa);
unk (QDECL *MoveToOrigin)(unk);
void (QDECL *MoveToOrigin)(hledict_t *ent, vec3_t dest, float dist, int moveflags);
unk (QDECL *ChangeYaw)(unk);
unk (QDECL *ChangePitch)(unk);
hledict_t *(QDECL *FindEntityByString)(hledict_t *last, char *field, char *value);
@ -524,7 +524,7 @@ typedef struct
unk (QDECL *GetPlayerWONId)(unk);
unk (QDECL *Info_RemoveKey)(unk);
unk (QDECL *GetPhysicsKeyValue)(unk);
unk (QDECL *SetPhysicsKeyValue)(unk);
void (QDECL *SetPhysicsKeyValue)(hledict_t *ent, char *key, char *value);
unk (QDECL *GetPhysicsInfoString)(unk);
unsigned short (QDECL *PrecacheEvent)(int eventtype, char *eventname);
void (QDECL *PlaybackEvent)(int flags, hledict_t *ent, unsigned short eventidx, float delay, float *origin, float *angles, float f1, float f2, int i1, int i2, int b1, int b2);
@ -549,7 +549,7 @@ typedef struct
unk (QDECL *Voice_GetClientListening)(unk);
qboolean (QDECL *Voice_SetClientListening)(int listener, int sender, int shouldlisten);
//140
unk (QDECL *GetPlayerAuthId)(unk);
char *(QDECL *GetPlayerAuthId)(hledict_t *playerent);
unk (QDECL *SequenceGet)(unk);
unk (QDECL *SequencePickSentence)(unk);
unk (QDECL *GetFileSize)(unk);

View file

@ -648,6 +648,7 @@ SV_Push
============
*/
#define MAX_PUSHED_ENTITIES 1024
qboolean SVHL_Push (hledict_t *pusher, vec3_t move, vec3_t amove)
{
int i, e;
@ -655,8 +656,8 @@ qboolean SVHL_Push (hledict_t *pusher, vec3_t move, vec3_t amove)
vec3_t mins, maxs;
vec3_t pushorig;
int num_moved;
hledict_t *moved_edict[MAX_EDICTS];
vec3_t moved_from[MAX_EDICTS];
hledict_t *moved_edict[MAX_PUSHED_ENTITIES];
vec3_t moved_from[MAX_PUSHED_ENTITIES];
float oldsolid;
if (amove[0] || amove[1] || amove[2])
@ -715,6 +716,8 @@ qboolean SVHL_Push (hledict_t *pusher, vec3_t move, vec3_t amove)
continue;
}
if (num_moved < MAX_PUSHED_ENTITIES)
{
VectorCopy (check->v.origin, moved_from[num_moved]);
moved_edict[num_moved] = check;
num_moved++;
@ -755,6 +758,7 @@ qboolean SVHL_Push (hledict_t *pusher, vec3_t move, vec3_t amove)
SVHL_LinkEdict (check, false);
continue;
}
}
VectorCopy (pushorig, pusher->v.origin);
SVHL_LinkEdict (pusher, false);

View file

@ -37,7 +37,7 @@ qboolean Mod_LoadQ3Model (model_t *mod, void *buffer);
qboolean Mod_LoadZymoticModel (model_t *mod, void *buffer);
qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer);
qbyte mod_novis[MAX_MAP_LEAFS/8];
qbyte mod_novis[(MAX_MAP_LEAFS+7)/8];
#define MAX_MOD_KNOWN 512
model_t mod_known[MAX_MOD_KNOWN];
@ -323,7 +323,7 @@ qbyte *Mod_DecompressVis (qbyte *in, model_t *model, qbyte *decompressed)
qbyte *Mod_LeafPVS (mleaf_t *leaf, model_t *model, qbyte *buffer)
{
static qbyte decompressed[MAX_MAP_LEAFS/8];
static qbyte decompressed[(MAX_MAP_LEAFS+7)/8];
if (leaf == model->leafs)
return mod_novis;

View file

@ -1019,7 +1019,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
int mdlidx = ent->v->modelindex;
// get the clipping hull
if (ent->v->solid == SOLID_BSP && mdlidx)
if ((ent->v->solid == SOLID_BSP || ent->v->solid == SOLID_PORTAL) && mdlidx)
{
model = w->Get_CModel(w, mdlidx);
if (!model || (model->type != mod_brush && model->type != mod_heightmap))
@ -1040,7 +1040,13 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
}
// trace a line through the apropriate clipping hull
if (ent->v->solid != SOLID_BSP)
if (ent->v->solid == SOLID_PORTAL)
{
//solid_portal cares only about origins and as such has no mins/max
TransformedTrace(model, 0, ent->v->frame, start, end, vec3_origin, vec3_origin, &trace, eorg, ent->v->angles, hitcontentsmask);
hitmodel = false;
}
else if (ent->v->solid != SOLID_BSP)
{
ent->v->angles[0]*=-1; //carmack made bsp models rotate wrongly.
TransformedTrace(model, hullnum, ent->v->frame, start, end, mins, maxs, &trace, eorg, ent->v->angles, hitcontentsmask);
@ -1533,6 +1539,9 @@ static void World_ClipToLinks (world_t *w, areanode_t *node, moveclip_t *clip)
else
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->hitcontentsmask);
if (trace.startsolid && touch->v->solid == SOLID_PORTAL)
continue;
if (trace.allsolid || trace.startsolid ||
trace.fraction < clip->trace.fraction)
{