1
0
Fork 0
forked from fte/fteqw
fteqw/engine/client/clhl_game.c
Spoike c08a0aa139 fix some of the things that baker didn't like. sorry it took so long.
try to appease msvc6, just because.
update the downloads menu. now even betterer!...
fix proquake server angle snapping precision issue.
also accept _glow textures as an alternative to the more standard _luma.
compat for dp_water shader terms. tcgen stuff is still fscked up.
menu tooltip code can now properly deal with variable width etc stuff.
add missing te_flamejet builtin.
r_dynamic -1 can now cope with q3bsp for a small speedup.
added -watch commandline arg, to make it easier to figure out where cvar changes are coming from.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5015 fc73d0e0-1445-4013-8a0c-d673dee63da5
2016-08-25 00:12:14 +00:00

1601 lines
38 KiB
C

#include "quakedef.h"
#include "shader.h"
#ifdef _WIN32
#include "winquake.h"
#endif
#ifdef HLCLIENT
extern unsigned int r2d_be_flags;
struct hlcvar_s *QDECL GHL_CVarGetPointer(char *varname);
#if defined(_MSC_VER)
# if _MSC_VER >= 1300
# define __func__ __FUNCTION__
# else
# define __func__ "unknown"
# endif
#else
//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
#else
#define HLCL_API_VERSION 7
#endif
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;
dllfunction_t funcs[] =
{
{(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 = vgui_init();
return !!vgui_panel;
}
#define HLPIC model_t*
typedef struct
{
int l;
int r;
int t;
int b;
} hlsubrect_t;
typedef struct
{
vec3_t origin;
#if HLCL_API_VERSION >= 7
vec3_t viewangles;
int weapons;
float fov;
#else
float viewheight;
float maxspeed;
vec3_t viewangles;
vec3_t punchangles;
int keys;
int weapons;
float fov;
float idlescale;
float mousesens;
#endif
} hllocalclientdata_t;
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;
typedef struct
{
char name[64];
char sprite[64];
int unk;
int forscrwidth;
hlsubrect_t rect;
} hlspriteinf_t;
typedef struct
{
char *name;
short ping;
qbyte isus;
qbyte isspec;
qbyte pl;
//pad3
char *model;
short tcolour;
short bcolour;
} hlplayerinfo_t;
typedef struct
{
int size;
int width;
int height;
int flags;
int charheight;
short charwidths[256];
} hlscreeninfo_t;
typedef struct
{
int effect;
byte_vec4_t c1;
byte_vec4_t c2;
float x;
float y;
float fadein;
float fadeout;
float holdtime;
float fxtime;
char *name;
char *message;
} hlmsginfo_t;
typedef struct
{
HLPIC (QDECL *pic_load) (char *picname);
int (QDECL *pic_getnumframes) (HLPIC pic);
int (QDECL *pic_getheight) (HLPIC pic, int frame);
int (QDECL *pic_getwidth) (HLPIC pic, int frame);
void (QDECL *pic_select) (HLPIC pic, int r, int g, int b);
void (QDECL *pic_drawcuropaque) (int frame, int x, int y, void *loc);
void (QDECL *pic_drawcuralphatest) (int frame, int x, int y, void *loc);
void (QDECL *pic_drawcuradditive) (int frame, int x, int y, void *loc);
void (QDECL *pic_enablescissor) (int x, int y, int width, int height);
void (QDECL *pic_disablescissor) (void);
hlspriteinf_t *(QDECL *pic_parsepiclist) (char *filename, int *numparsed);
void (QDECL *fillrgba) (int x, int y, int width, int height, int r, int g, int b, int a);
int (QDECL *getscreeninfo) (hlscreeninfo_t *info);
void (QDECL *setcrosshair) (HLPIC pic, hlsubrect_t rect, int r, int g, int b); //I worry about stuff like this
struct hlcvar_s *(QDECL *cvar_register) (char *name, char *defvalue, int flags);
float (QDECL *cvar_getfloat) (char *name);
char *(QDECL *cvar_getstring) (char *name);
void (QDECL *cmd_register) (char *name, void (*func) (void));
void (QDECL *hooknetmsg) (char *msgname, void *func);
void (QDECL *forwardcmd) (char *command);
void (QDECL *localcmd) (char *command);
void (QDECL *getplayerinfo) (int entnum, hlplayerinfo_t *result);
void (QDECL *startsound_name) (char *name, float vol);
void (QDECL *startsound_idx) (int idx, float vol);
void (QDECL *anglevectors) (float *ina, float *outf, float *outr, float *outu);
hlmsginfo_t *(QDECL *get_message_info) (char *name); //translated+scaled+etc intro stuff
int (QDECL *drawchar) (int x, int y, int charnum, int r, int g, int b);
int (QDECL *drawstring) (int x, int y, char *string);
#if HLCL_API_VERSION >= 7
void (QDECL *settextcolour) (float r, float b, float g);
#endif
void (QDECL *drawstring_getlen) (char *string, int *outlen, int *outheight);
void (QDECL *consoleprint) (char *str);
void (QDECL *centerprint) (char *str);
#if HLCL_API_VERSION >= 7
int (QDECL *getwindowcenterx)(void); //yes, really, window center. for use with Get/SetCursorPos, the windows function.
int (QDECL *getwindowcentery)(void); //yes, really, window center. for use with Get/SetCursorPos, the windows function.
void (QDECL *getviewnangles)(float*ang);
void (QDECL *setviewnangles)(float*ang);
void (QDECL *getmaxclients)(float*ang);
void (QDECL *cvar_setvalue)(char *cvarname, char *value);
int (QDECL *cmd_argc)(void);
char *(QDECL *cmd_argv)(int i);
void (QDECL *con_printf)(char *fmt, ...);
void (QDECL *con_dprintf)(char *fmt, ...);
void (QDECL *con_notificationprintf)(int pos, char *fmt, ...);
void (QDECL *con_notificationprintfex)(void *info, char *fmt, ...); //arg1 is of specific type
char *(QDECL *physkey)(char *key);
char *(QDECL *serverkey)(char *key);
float (QDECL *getclientmaxspeed)(void);
int (QDECL *checkparm)(char *str, char **next);
int (QDECL *keyevent)(int key, int down);
void (QDECL *getmousepos)(int *outx, int *outy);
int (QDECL *movetypeisnoclip)(void);
struct hlclent_s *(QDECL *getlocalplayer)(void);
struct hlclent_s *(QDECL *getviewent)(void);
struct hlclent_s *(QDECL *getentidx)(int idx);
float (QDECL *getlocaltime)(void);
void (QDECL *calcshake)(void);
void (QDECL *applyshake)(float *,float *,float);
int (QDECL *pointcontents)(float *point, float *truecon);
int (QDECL *waterentity)(float *point);
void (QDECL *traceline) (float *start, float *end, int flags, int hull, int forprediction);
model_t *(QDECL *loadmodel)(char *modelname, int *mdlindex);
int (QDECL *addrentity)(int type, void *ent);
model_t *(QDECL *modelfrompic) (HLPIC pic);
void (QDECL *soundatloc)(char*sound, float volume, float *org);
unsigned short (QDECL *precacheevent)(int evtype, char *name);
void (QDECL *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);
void (QDECL *weaponanimate)(int anim, int body);
float (QDECL *randfloat) (float minv, float maxv);
long (QDECL *randlong) (long minv, long maxv);
void (QDECL *hookevent) (char *name, void (*func)(struct hlevent_s *event));
int (QDECL *con_isshown) (void);
char *(QDECL *getgamedir) (void);
struct hlcvar_s *(QDECL *cvar_find) (char *name);
char *(QDECL *lookupbinding) (char *command);
char *(QDECL *getlevelname) (void);
void (QDECL *getscreenfade) (struct hlsfade_s *fade);
void (QDECL *setscreenfade) (struct hlsfade_s *fade);
void *(QDECL *vgui_getpanel) (void);
void (QDECL *vgui_paintback) (int extents[4]);
void *(QDECL *loadfile) (char *path, int onhunk, int *length);
char *(QDECL *parsefile) (char *data, char *token);
void (QDECL *freefile) (void *file);
struct hl_tri_api_s
{
int vers;
int sentinal;
} *triapi;
struct hl_sfx_api_s
{
int vers;
int sentinal;
} *efxapi;
struct hl_event_api_s
{
int vers;
int sentinal;
} *eventapi;
struct hl_demo_api_s
{
int (QDECL *isrecording)(void);
int (QDECL *isplaying)(void);
int (QDECL *istimedemo)(void);
void (QDECL *writedata)(int size, void *data);
int sentinal;
} *demoapi;
struct hl_net_api_s
{
int vers;
int sentinal;
} *netapi;
struct hl_voicetweek_s
{
int sentinal;
} *voiceapi;
int (QDECL *forcedspectator) (void);
model_t *(QDECL *loadmapsprite) (char *name);
void (QDECL *fs_addgamedir) (char *basedir, char *appname);
int (QDECL *expandfilename) (char *filename, char *outbuff, int outsize);
char *(QDECL *player_key) (int pnum, char *key);
void (QDECL *player_setkey) (char *key, char *value); //wait, no pnum?
qboolean (QDECL *getcdkey) (int playernum, char key[16]);
int (QDECL *trackerfromplayer) (int pl);
int (QDECL *playerfromtracker) (int tr);
int (QDECL *sendcmd_unreliable) (char *cmd);
void (QDECL *getsysmousepos) (long *xandy);
void (QDECL *setsysmousepos) (int x, int y);
void (QDECL *setmouseenable) (qboolean enable);
#endif
int sentinal;
} CLHL_enginecgamefuncs_t;
typedef struct
{
int (QDECL *HUD_VidInit) (void);
int (QDECL *HUD_Init) (void);
int (QDECL *HUD_Shutdown) (void);
int (QDECL *HUD_Redraw) (float maptime, int inintermission);
int (QDECL *HUD_UpdateClientData) (hllocalclientdata_t *localclientdata, float maptime);
int (QDECL *HUD_Reset) (void);
#if HLCL_API_VERSION >= 7
void (QDECL *CL_CreateMove) (float frametime, hlusercmd_t *cmd, int isplaying);
void (QDECL *IN_ActivateMouse) (void);
void (QDECL *IN_DeactivateMouse) (void);
void (QDECL *IN_MouseEvent) (int buttonmask);
#endif
} CLHL_cgamefuncs_t;
//FIXME
typedef struct
{
vec3_t origin;
vec3_t oldorigin;
int firstframe;
int numframes;
int type;
vec3_t angles;
int flags;
float alpha;
float start;
float framerate;
model_t *model;
int skinnum;
} explosion_t;
typedef struct
{
char name[64];
int (QDECL *hook) (char *name, int bufsize, void *bufdata);
} CLHL_UserMessages_t;
CLHL_UserMessages_t usermsgs[256];
int numnewhooks;
CLHL_UserMessages_t pendingusermsgs[256];
static HLPIC selectedpic;
float hl_viewmodelsequencetime;
int hl_viewmodelsequencecur;
int hl_viewmodelsequencebody;
HLPIC QDECL CLGHL_pic_load (char *picname)
{
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
return 0;
}
static mspriteframe_t *getspriteframe(HLPIC pic, int frame)
{
msprite_t *psprite;
mspritegroup_t *pgroup;
bi_trace();
if (!pic)
return NULL;
psprite = pic->meshinfo;
if (!psprite)
return NULL;
if (psprite->frames[frame].type == SPR_SINGLE)
return psprite->frames[frame].frameptr;
else
{
pgroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
return pgroup->frames[0];
}
}
static mpic_t *getspritepic(HLPIC pic, int frame)
{
mspriteframe_t *f;
bi_trace();
f = getspriteframe(pic, frame);
if (f)
return f->shader;
return NULL;
}
int QDECL CLGHL_pic_getheight (HLPIC pic, int frame)
{
mspriteframe_t *pframe;
bi_trace();
pframe = getspriteframe(pic, frame);
if (!pframe)
return 0;
return pframe->shader->width;
}
int QDECL CLGHL_pic_getwidth (HLPIC pic, int frame)
{
mspriteframe_t *pframe;
bi_trace();
pframe = getspriteframe(pic, frame);
if (!pframe)
return 0;
return pframe->shader->height;
}
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;
//faster SW render: no blends/holes
pic->flags &= ~1;
R2D_Image(x, y,
loc->r-loc->l, loc->b-loc->t,
(float)loc->l/pic->width, (float)loc->t/pic->height,
(float)loc->r/pic->width, (float)loc->b/pic->height,
pic);
}
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
pic->flags |= 1;
R2D_Image(x, y,
loc->r-loc->l, loc->b-loc->t,
(float)loc->l/pic->width, (float)loc->t/pic->height,
(float)loc->r/pic->width, (float)loc->b/pic->height,
pic);
}
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;
r2d_be_flags = BEF_FORCEADDITIVE;
//use some kind of alpha
pic->flags |= 1;
if (loc)
{
R2D_Image(x, y,
loc->r-loc->l, loc->b-loc->t,
(float)loc->l/pic->width, (float)loc->t/pic->height,
(float)loc->r/pic->width, (float)loc->b/pic->height,
pic);
}
else
{
R2D_Image(x, y,
pic->width, pic->height,
0, 0,
1, 1,
pic);
}
r2d_be_flags = 0;
}
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)
{
hlspriteinf_t *result;
int entry;
int entries;
void *file;
char *pos;
bi_trace();
*numparsed = 0;
FS_LoadFile(filename, &file);
if (!file)
return NULL;
pos = file;
pos = COM_Parse(pos);
entries = atoi(com_token);
//name, res, pic, x, y, w, h
result = Z_Malloc(sizeof(*result)*entries);
for (entry = 0; entry < entries; entry++)
{
pos = COM_Parse(pos);
Q_strncpyz(result[entry].name, com_token, sizeof(result[entry].name));
pos = COM_Parse(pos);
result[entry].forscrwidth = atoi(com_token);
pos = COM_Parse(pos);
Q_strncpyz(result[entry].sprite, com_token, sizeof(result[entry].name));
pos = COM_Parse(pos);
result[entry].rect.l = atoi(com_token);
pos = COM_Parse(pos);
result[entry].rect.t = atoi(com_token);
pos = COM_Parse(pos);
result[entry].rect.r = result[entry].rect.l+atoi(com_token);
pos = COM_Parse(pos);
result[entry].rect.b = result[entry].rect.t+atoi(com_token);
if (pos)
*numparsed = entry;
}
if (!pos || COM_Parse(pos))
Con_Printf("unexpected end of file\n");
FS_FreeFile(file);
return result;
}
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;
info->width = vid.width;
info->height = vid.height;
info->flags = 0;
info->charheight = 8;
for (i = 0; i < 256; i++)
info->charwidths[i] = 8;
return true;
}
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
return NULL;
}
float QDECL CLGHL_cvar_getfloat (char *name)
{
cvar_t *var = Cvar_FindVar(name);
bi_trace();
if (var)
return var->value;
return 0;
}
char *QDECL CLGHL_cvar_getstring (char *name)
{
cvar_t *var = Cvar_FindVar(name);
bi_trace();
if (var)
return var->string;
return "";
}
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++)
{
if (!strcmp(usermsgs[i].name, msgname))
{
usermsgs[i].hook = func;
break; //one per name
}
}
//we already asked for it perhaps?
for (i = 0; i < numnewhooks; i++)
{
if (!strcmp(pendingusermsgs[i].name, msgname))
{
pendingusermsgs[i].hook = func;
return; //nothing to do
}
}
Q_strncpyz(pendingusermsgs[numnewhooks].name, msgname, sizeof(pendingusermsgs[i].name));
pendingusermsgs[numnewhooks].hook = func;
numnewhooks++;
}
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;
player = &cl.players[entnum];
result->name = player->name;
result->ping = player->ping;
result->tcolour = player->rtopcolor;
result->bcolour = player->rbottomcolor;
result->isus = true;
result->isspec = player->spectator;
result->pl = player->pl;
if (player->qwskin)
result->model = player->qwskin->name;
else
result->model = "";
}
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);
return;
}
S_StartSound (-1, -1, sfx, vec3_origin, vol, 1, 0, 0, 0);
}
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);
return;
}
S_StartSound (-1, -1, sfx, vec3_origin, vol, 1, 0, 0, 0);
}
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 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 = -1;
ret->y = -1;
*(int*)&ret->c1 = 0xffffffff;
*(int*)&ret->c2 = 0xffffffff;
ret->effect = 0;
ret->fadein = 1;
ret->fadeout = 1.5;
ret->fxtime = 0;
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__);}
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
#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)
{
if (i && i+1<com_argc)
*next = com_argv[i+1];
else
*next = NULL;
}
return i;
}
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
Con_Printf("CLGHL_keyevent: Unrecognised HL key code\n");
return true; //fixme: check the return type
}
void QDECL CLGHL_getmousepos(int *outx, int *outy){notimpf(__func__);}
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;}
void QDECL CLGHL_calcshake(void){notimpf(__func__);}
void QDECL CLGHL_applyshake(float *origin, float *angles, float factor){notimpf(__func__);}
int QDECL CLGHL_pointcontents(float *point, float *truecon){notimpf(__func__);return 0;}
int QDECL CLGHL_entcontents(float *point){notimpf(__func__);return 0;}
void QDECL CLGHL_traceline(float *start, float *end, int flags, int hull, int forprediction){notimpf(__func__);}
model_t *QDECL CLGHL_loadmodel(char *modelname, int *mdlindex){notimpf(__func__);return Mod_ForName(modelname, false);}
int QDECL CLGHL_addrentity(int type, void *ent){notimpf(__func__);return 0;}
model_t *QDECL CLGHL_modelfrompic(HLPIC pic){notimpf(__func__);return NULL;}
void QDECL CLGHL_soundatloc(char*sound, float volume, float *org){notimpf(__func__);}
unsigned short QDECL CLGHL_precacheevent(int evtype, char *name){notimpf(__func__);return 0;}
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;
}
float QDECL CLGHL_randfloat(float minv, float maxv){notimpf(__func__);return minv;}
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;
}
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__);
}
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);
}
else
notimpf(__func__); //don't leak, just fail
if (length)
*length = flen;
return ptr;
}
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);
}
int QDECL CLGHL_forcedspectator(void)
{
bi_trace();
return cls.demoplayback;
}
model_t *QDECL CLGHL_loadmapsprite(char *name)
{
bi_trace();
notimpf(__func__);return NULL;
}
void QDECL CLGHL_fs_addgamedir(char *basedir, char *appname){notimpf(__func__);}
int QDECL CLGHL_expandfilename(char *filename, char *outbuff, int outsize){notimpf(__func__);return false;}
char *QDECL CLGHL_player_key(int pnum, char *key){notimpf(__func__);return NULL;}
void QDECL CLGHL_player_setkey(char *key, char *value){notimpf(__func__);return;}
qboolean QDECL CLGHL_getcdkey(int playernum, char key[16]){notimpf(__func__);return false;}
int QDECL CLGHL_trackerfromplayer(int pslot){notimpf(__func__);return 0;}
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
}
void QDECL CLGHL_setmouseenable(qboolean enable)
{
extern cvar_t _windowed_mouse;
bi_trace();
Cvar_Set(&_windowed_mouse, enable?"1":"0");
}
#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__);
}
struct hl_demo_api_s hl_demo_api =
{
CLGHL_demo_isrecording,
CLGHL_demo_isplaying,
CLGHL_demo_istimedemo,
CLGHL_demo_writedata,
0xdeadbeef
};
#endif
CLHL_cgamefuncs_t CLHL_cgamefuncs;
CLHL_enginecgamefuncs_t CLHL_enginecgamefuncs =
{
CLGHL_pic_load,
CLGHL_pic_getnumframes,
CLGHL_pic_getheight,
CLGHL_pic_getwidth,
CLGHL_pic_select,
CLGHL_pic_drawcuropaque,
CLGHL_pic_drawcuralphtest,
CLGHL_pic_drawcuradditive,
CLGHL_pic_enablescissor,
CLGHL_pic_disablescissor,
CLGHL_pic_parsepiclist,
CLGHL_fillrgba,
CLGHL_getscreeninfo,
CLGHL_setcrosshair,
CLGHL_cvar_register,
CLGHL_cvar_getfloat,
CLGHL_cvar_getstring,
CLGHL_cmd_register,
CLGHL_hooknetmsg,
CLGHL_forwardcmd,
CLGHL_localcmd,
CLGHL_getplayerinfo,
CLGHL_startsound_name,
CLGHL_startsound_idx,
CLGHL_anglevectors,
CLGHL_get_message_info,
CLGHL_drawchar,
CLGHL_drawstring,
#if HLCL_API_VERSION >= 7
CLGHL_settextcolour,
#endif
CLGHL_drawstring_getlen,
CLGHL_consoleprint,
CLGHL_centerprint,
#if HLCL_API_VERSION >= 7
CLGHL_getwindowcenterx,
CLGHL_getwindowcentery,
CLGHL_getviewnangles,
CLGHL_setviewnangles,
CLGHL_getmaxclients,
CLGHL_cvar_setvalue,
CLGHL_cmd_argc,
CLGHL_cmd_argv,
CLGHL_con_printf,
CLGHL_con_dprintf,
CLGHL_con_notificationprintf,
CLGHL_con_notificationprintfex,
CLGHL_physkey,
CLGHL_serverkey,
CLGHL_getclientmaxspeed,
CLGHL_checkparm,
CLGHL_keyevent,
CLGHL_getmousepos,
CLGHL_movetypeisnoclip,
CLGHL_getlocalplayer,
CLGHL_getviewent,
CLGHL_getentidx,
CLGHL_getlocaltime,
CLGHL_calcshake,
CLGHL_applyshake,
CLGHL_pointcontents,
CLGHL_entcontents,
CLGHL_traceline,
CLGHL_loadmodel,
CLGHL_addrentity,
CLGHL_modelfrompic,
CLGHL_soundatloc,
CLGHL_precacheevent,
CLGHL_playevent,
CLGHL_weaponanimate,
CLGHL_randfloat,
CLGHL_randlong,
CLGHL_hookevent,
CLGHL_con_isshown,
CLGHL_getgamedir,
CLGHL_cvar_find,
CLGHL_lookupbinding,
CLGHL_getlevelname,
CLGHL_getscreenfade,
CLGHL_setscreenfade,
CLGHL_vgui_getpanel,
CLGHL_vgui_paintback,
CLGHL_loadfile,
CLGHL_parsefile,
CLGHL_freefile,
NULL, //triapi;
NULL, //efxapi;
NULL, //eventapi;
&hl_demo_api,
NULL, //netapi;
//sdk 2.3+
NULL, //voiceapi;
CLGHL_forcedspectator,
CLGHL_loadmapsprite,
CLGHL_fs_addgamedir,
CLGHL_expandfilename,
CLGHL_player_key,
CLGHL_player_setkey,
CLGHL_getcdkey,
CLGHL_trackerfromplayer,
CLGHL_playerfromtracker,
CLGHL_sendcmd_unreliable,
CLGHL_getsysmousepos,
CLGHL_setsysmousepos,
CLGHL_setmouseenable,
#endif
0xdeadbeef
};
dllhandle_t *clg;
int CLHL_GamecodeDoesMouse(void)
{
#if HLCL_API_VERSION >= 7
if (clg && CLHL_cgamefuncs.CL_CreateMove)
return true;
#endif
return false;
}
int CLHL_MouseEvent(unsigned int buttonmask)
{
#if HLCL_API_VERSION >= 7
if (!CLHL_GamecodeDoesMouse())
return false;
CLHL_cgamefuncs.IN_MouseEvent(buttonmask);
return true;
#else
return false;
#endif
}
void CLHL_SetMouseActive(int activate)
{
#if HLCL_API_VERSION >= 7
static int oldactive;
if (!clg)
{
oldactive = false;
return;
}
if (activate == oldactive)
return;
oldactive = activate;
if (activate)
{
if (CLHL_cgamefuncs.IN_ActivateMouse)
CLHL_cgamefuncs.IN_ActivateMouse();
}
else
{
if (CLHL_cgamefuncs.IN_DeactivateMouse)
CLHL_cgamefuncs.IN_DeactivateMouse();
}
#endif
}
void CLHL_UnloadClientGame(void)
{
if (!clg)
return;
CLHL_SetMouseActive(false);
if (CLHL_cgamefuncs.HUD_Shutdown)
CLHL_cgamefuncs.HUD_Shutdown();
Sys_CloseLibrary(clg);
memset(&CLHL_cgamefuncs, 0, sizeof(CLHL_cgamefuncs));
clg = NULL;
hl_viewmodelsequencetime = 0;
}
void CLHL_LoadClientGame(void)
{
char fullname[MAX_OSPATH];
char path[MAX_OSPATH];
void *iterator;
int (QDECL *initfunc)(CLHL_enginecgamefuncs_t *funcs, int version);
dllfunction_t funcs[] =
{
{(void*)&initfunc, "Initialize"},
{NULL}
};
CLHL_UnloadClientGame();
memset(&CLHL_cgamefuncs, 0, sizeof(CLHL_cgamefuncs));
clg = NULL;
iterator = NULL;
//FIXME: dlls in gamepaths is evil
while(COM_IteratePaths(&iterator, path, sizeof(path), NULL, 0))
{
snprintf (fullname, sizeof(fullname), "%s%s", path, "cl_dlls/client");
clg = Sys_LoadLibrary(fullname, funcs);
if (clg)
break;
}
if (!clg)
return;
if (!initfunc(&CLHL_enginecgamefuncs, HLCL_API_VERSION))
{
Con_Printf("HalfLife cldll is not version %i\n", HLCL_API_VERSION);
Sys_CloseLibrary(clg);
clg = NULL;
return;
}
CLHL_cgamefuncs.HUD_VidInit = (void*)Sys_GetAddressForName(clg, "HUD_VidInit");
CLHL_cgamefuncs.HUD_Init = (void*)Sys_GetAddressForName(clg, "HUD_Init");
CLHL_cgamefuncs.HUD_Shutdown = (void*)Sys_GetAddressForName(clg, "HUD_Shutdown");
CLHL_cgamefuncs.HUD_Redraw = (void*)Sys_GetAddressForName(clg, "HUD_Redraw");
CLHL_cgamefuncs.HUD_UpdateClientData = (void*)Sys_GetAddressForName(clg, "HUD_UpdateClientData");
CLHL_cgamefuncs.HUD_Reset = (void*)Sys_GetAddressForName(clg, "HUD_Reset");
#if HLCL_API_VERSION >= 7
CLHL_cgamefuncs.CL_CreateMove = (void*)Sys_GetAddressForName(clg, "CL_CreateMove");
CLHL_cgamefuncs.IN_ActivateMouse = (void*)Sys_GetAddressForName(clg, "IN_ActivateMouse");
CLHL_cgamefuncs.IN_DeactivateMouse = (void*)Sys_GetAddressForName(clg, "IN_DeactivateMouse");
CLHL_cgamefuncs.IN_MouseEvent = (void*)Sys_GetAddressForName(clg, "IN_MouseEvent");
#endif
VGui_Setup();
if (CLHL_cgamefuncs.HUD_Init)
CLHL_cgamefuncs.HUD_Init();
if (CLHL_cgamefuncs.HUD_VidInit)
CLHL_cgamefuncs.HUD_VidInit();
{
struct hlkbutton_s
{
int down[2]; // key nums holding it down
int state; // low bit is down state
} *but;
struct hlkbutton_s *(QDECL *pKB_Find) (const char *foo) = (void*)Sys_GetAddressForName(clg, "KB_Find");
if (pKB_Find)
{
but = pKB_Find("in_mlook");
if (but)
but->state |= 1;
}
}
}
int CLHL_BuildUserInput(int msecs, usercmd_t *cmd)
{
#if HLCL_API_VERSION >= 7
hlusercmd_t hlcmd;
if (!clg || !CLHL_cgamefuncs.CL_CreateMove)
return false;
CLHL_cgamefuncs.CL_CreateMove(msecs/255.0f, &hlcmd, cls.state>=ca_active && !cls.demoplayback);
#define ANGLE2SHORT(x) (x) * (65536/360.0)
cmd->msec = msecs;
cmd->angles[0] = ANGLE2SHORT(hlcmd.viewangles[0]);
cmd->angles[1] = ANGLE2SHORT(hlcmd.viewangles[1]);
cmd->angles[2] = ANGLE2SHORT(hlcmd.viewangles[2]);
cmd->forwardmove = hlcmd.forwardmove;
cmd->sidemove = hlcmd.sidemove;
cmd->upmove = hlcmd.upmove;
cmd->weapon = hlcmd.weaponselect;
cmd->impulse = hlcmd.impulse;
cmd->buttons = hlcmd.buttons & 0xff; //FIXME: quake's protocols are more limited than this
cmd->lightlevel = hlcmd.lightlevel;
return true;
#else
return false;
#endif
}
int CLHL_DrawHud(void)
{
extern kbutton_t in_attack;
hllocalclientdata_t state;
int ret;
if (!clg || !CLHL_cgamefuncs.HUD_Redraw)
return false;
memset(&state, 0, sizeof(state));
// state.origin;
// state.viewangles;
#if HLCL_API_VERSION < 7
// state.viewheight;
// state.maxspeed;
// state.punchangles;
state.idlescale = 0;
state.mousesens = 0;
state.keys = (in_attack.state[0]&3)?1:0;
#endif
state.weapons = cl.playerview[0].stats[STAT_ITEMS];
state.fov = 90;
V_StopPitchDrift(&cl.playerview[0]);
CLHL_cgamefuncs.HUD_UpdateClientData(&state, cl.time);
ret = CLHL_cgamefuncs.HUD_Redraw(cl.time, cl.intermissionmode != IM_NONE);
return ret;
}
int CLHL_AnimateViewEntity(entity_t *ent)
{
float time;
if (!hl_viewmodelsequencetime)
return false;
time = cl.time - hl_viewmodelsequencetime;
ent->framestate.g[FS_REG].frame[0] = hl_viewmodelsequencecur;
ent->framestate.g[FS_REG].frame[1] = hl_viewmodelsequencecur;
ent->framestate.g[FS_REG].frametime[0] = time;
ent->framestate.g[FS_REG].frametime[1] = time;
return true;
}
explosion_t *CL_AllocExplosion (vec3_t org);
int CLHL_ParseGamePacket(void)
{
int subcode;
char *end;
char *str;
int tempi;
end = net_message.data+msg_readcount+2+MSG_ReadShort();
if (end > net_message.data+net_message.cursize)
return false;
subcode = MSG_ReadByte();
if (usermsgs[subcode].hook)
if (usermsgs[subcode].hook(usermsgs[subcode].name, end - (net_message.data+msg_readcount), net_message.data+msg_readcount))
{
msg_readcount = end - net_message.data;
return true;
}
switch(subcode)
{
case 1:
//register the server-sent code.
tempi = MSG_ReadByte();
str = MSG_ReadString();
Q_strncpyz(usermsgs[tempi].name, str, sizeof(usermsgs[tempi].name));
//get the builtin to reregister its hooks.
for (tempi = 0; tempi < numnewhooks; tempi++)
CLGHL_hooknetmsg(pendingusermsgs[tempi].name, pendingusermsgs[tempi].hook);
break;
case svc_temp_entity:
{
vec3_t startp, endp, vel;
float ang;
int midx;
int mscale;
int mrate;
int flags;
int lifetime;
explosion_t *ef;
subcode = MSG_ReadByte();
switch(subcode)
{
case 3:
MSG_ReadPos(startp);
midx = MSG_ReadShort();
mscale = MSG_ReadByte();
mrate = MSG_ReadByte();
flags = MSG_ReadByte();
if (!(flags & 8))
P_RunParticleEffectType(startp, NULL, 1, pt_explosion);
if (!(flags & 4))
S_StartSound(0, 0, S_PrecacheSound("explosion"), startp, 1, 1, 0, 0, 0);
if (!(flags & 2))
CL_NewDlight(0, startp, 200, 1, 2.0,2.0,2.0);
ef = CL_AllocExplosion(startp);
ef->start = cl.time;
ef->model = cl.model_precache[midx];
ef->framerate = mrate;
ef->firstframe = 0;
ef->numframes = ef->model->numframes;
if (!(flags & 1))
ef->flags = RF_ADDITIVE;
else
ef->flags = 0;
break;
case 4:
MSG_ReadPos(startp);
P_RunParticleEffectType(startp, NULL, 1, pt_tarexplosion);
break;
case 5:
MSG_ReadPos(startp);
MSG_ReadShort();
MSG_ReadByte();
MSG_ReadByte();
break;
case 6:
MSG_ReadPos(startp);
MSG_ReadPos(endp);
break;
case 9:
MSG_ReadPos(startp);
P_RunParticleEffectType(startp, NULL, 1, ptdp_spark);
break;
case 22:
MSG_ReadShort();
MSG_ReadShort();
MSG_ReadByte();
MSG_ReadByte();
MSG_ReadByte();
MSG_ReadByte();
MSG_ReadByte();
break;
case 23:
MSG_ReadPos(startp);
MSG_ReadShort();
MSG_ReadByte();
MSG_ReadByte();
MSG_ReadByte();
break;
case 106:
MSG_ReadPos(startp);
MSG_ReadPos(vel);
ang = MSG_ReadAngle();
midx = MSG_ReadShort();
MSG_ReadByte();
lifetime = MSG_ReadByte();
ef = CL_AllocExplosion(startp);
ef->start = cl.time;
ef->angles[1] = ang;
ef->model = cl.model_precache[midx];
ef->firstframe = 0;
ef->numframes = lifetime;
ef->flags = 0;
ef->framerate = 10;
break;
case 108:
MSG_ReadPos(startp);
MSG_ReadPos(endp);
MSG_ReadPos(vel);
MSG_ReadByte();
MSG_ReadShort();
MSG_ReadByte();
MSG_ReadByte();
MSG_ReadByte();
break;
case 109:
MSG_ReadPos(startp);
MSG_ReadShort();
MSG_ReadByte();
break;
case 116:
MSG_ReadPos(startp);
MSG_ReadByte();
break;
case 117:
MSG_ReadPos(startp);
MSG_ReadByte()+256;
break;
case 118:
MSG_ReadPos(startp);
MSG_ReadByte()+256;
break;
default:
Con_Printf("CLHL_ParseGamePacket: Unable to parse gamecode tempent %i\n", subcode);
msg_readcount = end - net_message.data;
break;
}
}
if (msg_readcount != end - net_message.data)
{
Con_Printf("CLHL_ParseGamePacket: Gamecode temp entity %i not parsed correctly read %i bytes too many\n", subcode, msg_readcount - (end - net_message.data));
msg_readcount = end - net_message.data;
}
break;
case svc_intermission:
//nothing.
cl.intermissionmode = IM_NQSCORES;
break;
case svc_cdtrack:
{
unsigned int firsttrack;
unsigned int looptrack;
firsttrack = MSG_ReadByte ();
looptrack = MSG_ReadByte ();
Media_NumberedTrack (firsttrack, looptrack);
}
break;
case 35: //svc_weaponanimation:
tempi = MSG_ReadByte();
CLGHL_weaponanimate(tempi, MSG_ReadByte());
break;
case 37: //svc_roomtype
tempi = MSG_ReadShort();
// S_SetUnderWater(tempi==14||tempi==15||tempi==16);
break;
default:
Con_Printf("Unrecognised gamecode packet %i (%s)\n", subcode, usermsgs[subcode].name);
msg_readcount = end - net_message.data;
break;
}
if (msg_readcount != end - net_message.data)
{
Con_Printf("CLHL_ParseGamePacket: Gamecode packet %i not parsed correctly read %i bytestoo many\n", subcode, msg_readcount - (end - net_message.data));
msg_readcount = end - net_message.data;
}
return true;
}
#endif