mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-10 22:51:57 +00:00
ffc2a08589
Added version+time+date to segfault lots. try to use vbo+vao as needed. added a manifest file in order to disable uac emulation and its virtual store lies. particles now support a sort of namespace. eg: an effect called "cfg.effect" will load up the 'cfg' particle config and use its 'effect' effect (but not replace any explicit effects). You can still create particle effects called 'cfg.effect' with no issue. Added support for fsarchive plugins. Added a sys_register_file_associations command. .bsp not yet handled, but demo playback should work fine. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4324 fc73d0e0-1445-4013-8a0c-d673dee63da5
568 lines
14 KiB
C++
568 lines
14 KiB
C++
//included directly from plugin.c
|
|
//this is the client-only things.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static plugin_t *menuplug; //plugin that has the current menu
|
|
static plugin_t *protocolclientplugin;
|
|
|
|
|
|
|
|
qintptr_t VARGS Plug_Menu_Control(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
if (qrenderer == QR_NONE)
|
|
return 0;
|
|
|
|
switch(VM_LONG(arg[0]))
|
|
{
|
|
case 0: //take away all menus
|
|
case 1:
|
|
if (menuplug)
|
|
{
|
|
plugin_t *oldplug = currentplug;
|
|
currentplug = menuplug;
|
|
Plug_Menu_Event(3, 0);
|
|
menuplug = NULL;
|
|
currentplug = oldplug;
|
|
key_dest = key_game;
|
|
}
|
|
if (VM_LONG(arg[0]) != 1)
|
|
return 1;
|
|
//give us menu control
|
|
menuplug = currentplug;
|
|
key_dest = key_menu;
|
|
m_state = m_plugin;
|
|
return 1;
|
|
case 2: //weather it's us or not.
|
|
return currentplug == menuplug && m_state == m_plugin;
|
|
case 3: //weather a menu is active
|
|
return key_dest == key_menu;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
qintptr_t VARGS Plug_Key_GetKeyCode(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
int modifier;
|
|
return Key_StringToKeynum(VM_POINTER(arg[0]), &modifier);
|
|
}
|
|
|
|
|
|
|
|
|
|
qintptr_t VARGS Plug_SCR_CenterPrint(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
if (qrenderer == QR_NONE)
|
|
return 0;
|
|
|
|
SCR_CenterPrint(0, VM_POINTER(arg[0]), true);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
//Make SURE that the engine has resolved all cvar pointers into globals before this happens.
|
|
plugin_t *plugin;
|
|
char name[64];
|
|
qboolean picfromwad;
|
|
mpic_t *pic;
|
|
} pluginimagearray_t;
|
|
int pluginimagearraylen;
|
|
pluginimagearray_t *pluginimagearray;
|
|
|
|
qintptr_t VARGS Plug_Draw_LoadImage(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
char *name = VM_POINTER(arg[0]);
|
|
qboolean fromwad = arg[1];
|
|
int i;
|
|
|
|
mpic_t *pic;
|
|
|
|
if (!*name)
|
|
return 0;
|
|
|
|
for (i = 0; i < pluginimagearraylen; i++)
|
|
{
|
|
if (!pluginimagearray[i].plugin)
|
|
break;
|
|
if (pluginimagearray[i].plugin == currentplug)
|
|
{
|
|
if (!strcmp(name, pluginimagearray[i].name))
|
|
break;
|
|
}
|
|
}
|
|
if (i == pluginimagearraylen)
|
|
{
|
|
pluginimagearraylen++;
|
|
pluginimagearray = BZ_Realloc(pluginimagearray, pluginimagearraylen*sizeof(pluginimagearray_t));
|
|
pluginimagearray[i].pic = NULL;
|
|
}
|
|
|
|
if (pluginimagearray[i].pic)
|
|
return i+1; //already loaded.
|
|
|
|
if (qrenderer != QR_NONE)
|
|
{
|
|
if (fromwad)
|
|
pic = R2D_SafePicFromWad(name);
|
|
else
|
|
pic = R2D_SafeCachePic(name);
|
|
}
|
|
else
|
|
pic = NULL;
|
|
|
|
Q_strncpyz(pluginimagearray[i].name, name, sizeof(pluginimagearray[i].name));
|
|
pluginimagearray[i].picfromwad = fromwad;
|
|
pluginimagearray[i].pic = pic;
|
|
pluginimagearray[i].plugin = currentplug;
|
|
return i + 1;
|
|
}
|
|
|
|
void Plug_DrawReloadImages(void)
|
|
{
|
|
int i;
|
|
for (i = 0; i < pluginimagearraylen; i++)
|
|
{
|
|
if (!pluginimagearray[i].plugin)
|
|
{
|
|
pluginimagearray[i].pic = NULL;
|
|
continue;
|
|
}
|
|
|
|
pluginimagearray[i].pic = R2D_SafePicFromWad(pluginimagearray[i].name);
|
|
//pluginimagearray[i].pic = R2D_SafeCachePic(pluginimagearray[i].name);
|
|
//pluginimagearray[i].pic = NULL;
|
|
}
|
|
}
|
|
|
|
static void Plug_FreePlugImages(plugin_t *plug)
|
|
{
|
|
int i;
|
|
for (i = 0; i < pluginimagearraylen; i++)
|
|
{
|
|
if (pluginimagearray[i].plugin == plug)
|
|
{
|
|
pluginimagearray[i].plugin = 0;
|
|
pluginimagearray[i].pic = NULL;
|
|
pluginimagearray[i].name[0] = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
//int R2D_Image (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image)
|
|
qintptr_t VARGS Plug_Draw_Image(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
mpic_t *pic;
|
|
int i;
|
|
if (qrenderer == QR_NONE)
|
|
return 0;
|
|
|
|
i = VM_LONG(arg[8]);
|
|
if (i <= 0 || i > pluginimagearraylen)
|
|
return -1; // you fool
|
|
i = i - 1;
|
|
if (pluginimagearray[i].plugin != currentplug)
|
|
return -1;
|
|
|
|
if (pluginimagearray[i].pic)
|
|
pic = pluginimagearray[i].pic;
|
|
else if (pluginimagearray[i].picfromwad)
|
|
return 0; //wasn't loaded.
|
|
else
|
|
{
|
|
pic = R2D_SafeCachePic(pluginimagearray[i].name);
|
|
if (!pic)
|
|
return -1;
|
|
}
|
|
|
|
R2D_Image(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), VM_FLOAT(arg[3]), VM_FLOAT(arg[4]), VM_FLOAT(arg[5]), VM_FLOAT(arg[6]), VM_FLOAT(arg[7]), pic);
|
|
return 1;
|
|
}
|
|
//x1,y1,x2,y2
|
|
qintptr_t VARGS Plug_Draw_Line(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
switch(qrenderer) //FIXME: I don't want qrenderer seen outside the refresh
|
|
{
|
|
#ifdef GLQUAKE
|
|
case QR_OPENGL:
|
|
qglDisable(GL_TEXTURE_2D);
|
|
qglBegin(GL_LINES);
|
|
qglVertex2f(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]));
|
|
qglVertex2f(VM_FLOAT(arg[2]), VM_FLOAT(arg[3]));
|
|
qglEnd();
|
|
qglEnable(GL_TEXTURE_2D);
|
|
break;
|
|
#endif
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
qintptr_t VARGS Plug_Draw_Character(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
int x, y;
|
|
if (qrenderer == QR_NONE)
|
|
return 0;
|
|
Font_BeginString(font_conchar, arg[0], arg[1], &x, &y);
|
|
Font_DrawChar(x, y, CON_WHITEMASK | 0xe000 | (unsigned int)arg[2]);
|
|
Font_EndString(font_conchar);
|
|
return 0;
|
|
}
|
|
|
|
qintptr_t VARGS Plug_Draw_Fill(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
float x, y, width, height;
|
|
if (qrenderer == QR_NONE)
|
|
return 0;
|
|
x = VM_FLOAT(arg[0]);
|
|
y = VM_FLOAT(arg[1]);
|
|
width = VM_FLOAT(arg[2]);
|
|
height = VM_FLOAT(arg[3]);
|
|
|
|
R2D_FillBlock(x, y, width, height);
|
|
return 0;
|
|
}
|
|
qintptr_t VARGS Plug_Draw_ColourP(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
if (arg[0]<0 || arg[0]>255)
|
|
return false;
|
|
|
|
R2D_ImagePaletteColour(arg[0], 1);
|
|
return 1;
|
|
}
|
|
qintptr_t VARGS Plug_Draw_Colour3f(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
R2D_ImageColours(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), 1);
|
|
return 1;
|
|
}
|
|
qintptr_t VARGS Plug_Draw_Colour4f(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
R2D_ImageColours(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]), VM_FLOAT(arg[2]), VM_FLOAT(arg[3]));
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
qintptr_t VARGS Plug_LocalSound(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
if (qrenderer == QR_NONE)
|
|
return false;
|
|
|
|
S_LocalSound(VM_POINTER(arg[0]));
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
qintptr_t VARGS Plug_CL_GetStats(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
int i;
|
|
int pnum = VM_LONG(arg[0]);
|
|
unsigned int *stats = VM_POINTER(arg[1]);
|
|
int pluginstats = VM_LONG(arg[2]);
|
|
int max;
|
|
|
|
if (VM_OOB(arg[1], arg[2]*4))
|
|
return 0;
|
|
|
|
if (qrenderer == QR_NONE || !cls.state)
|
|
return 0;
|
|
|
|
max = pluginstats;
|
|
if (max > MAX_CL_STATS)
|
|
max = MAX_CL_STATS;
|
|
for (i = 0; i < max; i++)
|
|
{ //fill stats with the right player's stats
|
|
stats[i] = cl.playerview[pnum].stats[i];
|
|
}
|
|
for (; i < pluginstats; i++) //plugin has too many stats (wow)
|
|
stats[i] = 0; //fill the rest.
|
|
return max;
|
|
}
|
|
|
|
#define PLUGMAX_SCOREBOARDNAME 64
|
|
typedef struct {
|
|
int topcolour;
|
|
int bottomcolour;
|
|
int frags;
|
|
char name[PLUGMAX_SCOREBOARDNAME];
|
|
int ping;
|
|
int pl;
|
|
int starttime;
|
|
int userid;
|
|
int spectator;
|
|
char userinfo[1024];
|
|
char team[8];
|
|
} vmplugclientinfo_t;
|
|
|
|
qintptr_t VARGS Plug_GetPlayerInfo(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
int i, pt;
|
|
vmplugclientinfo_t *out;
|
|
|
|
if (VM_OOB(arg[1], sizeof(vmplugclientinfo_t)))
|
|
return -1;
|
|
if (VM_LONG(arg[0]) < -1 || VM_LONG(arg[0] ) >= MAX_CLIENTS)
|
|
return -2;
|
|
|
|
i = VM_LONG(arg[0]);
|
|
out = VM_POINTER(arg[1]);
|
|
if (out)
|
|
{
|
|
if (i == -1)
|
|
{
|
|
i = cl.playernum[0];
|
|
if (i < 0)
|
|
{
|
|
memset(out, 0, sizeof(*out));
|
|
return 0;
|
|
}
|
|
}
|
|
out->bottomcolour = cl.players[i].rbottomcolor;
|
|
out->topcolour = cl.players[i].rtopcolor;
|
|
out->frags = cl.players[i].frags;
|
|
Q_strncpyz(out->name, cl.players[i].name, PLUGMAX_SCOREBOARDNAME);
|
|
out->ping = cl.players[i].ping;
|
|
out->pl = cl.players[i].pl;
|
|
out->starttime = cl.players[i].entertime;
|
|
out->userid = cl.players[i].userid;
|
|
out->spectator = cl.players[i].spectator;
|
|
Q_strncpyz(out->userinfo, cl.players[i].userinfo, sizeof(out->userinfo));
|
|
Q_strncpyz(out->team, cl.players[i].team, sizeof(out->team));
|
|
}
|
|
|
|
pt = Cam_TrackNum(0);
|
|
if (pt < 0)
|
|
return (cl.playernum[0] == i);
|
|
else
|
|
return pt == i;
|
|
}
|
|
|
|
qintptr_t VARGS Plug_LocalPlayerNumber(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
return cl.playernum[0];
|
|
}
|
|
|
|
qintptr_t VARGS Plug_GetServerInfo(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
char *outptr = VM_POINTER(arg[0]);
|
|
unsigned int outlen = VM_LONG(arg[1]);
|
|
|
|
if (VM_OOB(arg[0], outlen))
|
|
return false;
|
|
|
|
Q_strncpyz(outptr, cl.serverinfo, outlen);
|
|
|
|
return true;
|
|
}
|
|
|
|
qintptr_t VARGS Plug_SetUserInfo(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
char *key = VM_POINTER(arg[0]);
|
|
char *value = VM_POINTER(arg[1]);
|
|
|
|
CL_SetInfo(0, key, value);
|
|
|
|
return true;
|
|
}
|
|
|
|
qintptr_t VARGS Plug_GetLocationName(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
float *locpoint = VM_POINTER(arg[0]);
|
|
char *locname = VM_POINTER(arg[1]);
|
|
unsigned int locnamelen = VM_LONG(arg[2]);
|
|
char *result;
|
|
|
|
if (VM_OOB(arg[1], locnamelen))
|
|
return 0;
|
|
|
|
result = TP_LocationName(locpoint);
|
|
Q_strncpyz(locname, result, locnamelen);
|
|
return VM_LONG(arg[1]);
|
|
}
|
|
|
|
qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
char *name = VM_POINTER(arg[0]);
|
|
char *text = VM_POINTER(arg[1]);
|
|
console_t *con;
|
|
|
|
if (qrenderer == QR_NONE)
|
|
return false;
|
|
|
|
con = Con_FindConsole(name);
|
|
if (!con)
|
|
{
|
|
con = Con_Create(name, 0);
|
|
Con_SetActive(con);
|
|
|
|
if (currentplug->conexecutecommand)
|
|
{
|
|
con->userdata = currentplug;
|
|
con->linebuffered = Plug_SubConsoleCommand;
|
|
}
|
|
}
|
|
|
|
Con_PrintCon(con, text);
|
|
|
|
return 1;
|
|
}
|
|
qintptr_t VARGS Plug_Con_RenameSub(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
char *name = VM_POINTER(arg[0]);
|
|
console_t *con;
|
|
if (qrenderer == QR_NONE)
|
|
return false;
|
|
con = Con_FindConsole(name);
|
|
if (!con)
|
|
return 0;
|
|
|
|
Q_strncpyz(con->name, name, sizeof(con->name));
|
|
|
|
return 1;
|
|
}
|
|
qintptr_t VARGS Plug_Con_IsActive(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
char *name = VM_POINTER(arg[0]);
|
|
console_t *con;
|
|
if (qrenderer == QR_NONE)
|
|
return false;
|
|
con = Con_FindConsole(name);
|
|
if (!con)
|
|
return false;
|
|
|
|
return Con_IsActive(con);
|
|
}
|
|
qintptr_t VARGS Plug_Con_SetActive(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
char *name = VM_POINTER(arg[0]);
|
|
console_t *con;
|
|
if (qrenderer == QR_NONE)
|
|
return false;
|
|
con = Con_FindConsole(name);
|
|
if (!con)
|
|
con = Con_Create(name, 0);
|
|
|
|
Con_SetActive(con);
|
|
return true;
|
|
}
|
|
qintptr_t VARGS Plug_Con_Destroy(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
char *name = VM_POINTER(arg[0]);
|
|
console_t *con;
|
|
if (qrenderer == QR_NONE)
|
|
return false;
|
|
con = Con_FindConsole(name);
|
|
if (!con)
|
|
return false;
|
|
|
|
Con_Destroy(con);
|
|
return true;
|
|
}
|
|
qintptr_t VARGS Plug_Con_NameForNum(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
char num = VM_LONG(arg[0]);
|
|
char *buffer = VM_POINTER(arg[1]);
|
|
int buffersize = VM_LONG(arg[2]);
|
|
if (VM_OOB(arg[1], buffersize) || buffersize < 1)
|
|
return false;
|
|
if (qrenderer == QR_NONE)
|
|
return false;
|
|
|
|
return Con_NameForNum(num, buffer, buffersize);
|
|
}
|
|
|
|
qintptr_t VARGS Plug_S_RawAudio(void *offset, quintptr_t mask, const qintptr_t *arg)
|
|
{
|
|
int sourceid = VM_LONG(arg[0]);
|
|
qbyte *data = VM_POINTER(arg[1]);
|
|
int speed = VM_LONG(arg[2]);
|
|
int samples = VM_LONG(arg[3]);
|
|
int channels = VM_LONG(arg[4]);
|
|
int width = VM_LONG(arg[5]);
|
|
|
|
int datasize = samples * channels * width;
|
|
|
|
if (VM_OOB(arg[1], datasize) || datasize < 1)
|
|
return false;
|
|
|
|
S_RawAudio(sourceid, data, speed, samples, channels, width);
|
|
return 0;
|
|
}
|
|
|
|
void Plug_Client_Init(void)
|
|
{
|
|
Plug_RegisterBuiltin("CL_GetStats", Plug_CL_GetStats, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Menu_Control", Plug_Menu_Control, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Key_GetKeyCode", Plug_Key_GetKeyCode, PLUG_BIF_NEEDSRENDERER);
|
|
|
|
Plug_RegisterBuiltin("Draw_LoadImage", Plug_Draw_LoadImage, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Draw_Image", Plug_Draw_Image, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Draw_Character", Plug_Draw_Character, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Draw_Fill", Plug_Draw_Fill, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Draw_Line", Plug_Draw_Line, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Draw_Colourp", Plug_Draw_ColourP, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Draw_Colour3f", Plug_Draw_Colour3f, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Draw_Colour4f", Plug_Draw_Colour4f, PLUG_BIF_NEEDSRENDERER);
|
|
|
|
Plug_RegisterBuiltin("Con_SubPrint", Plug_Con_SubPrint, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Con_RenameSub", Plug_Con_RenameSub, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Con_IsActive", Plug_Con_IsActive, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Con_SetActive", Plug_Con_SetActive, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Con_Destroy", Plug_Con_Destroy, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("Con_NameForNum", Plug_Con_NameForNum, PLUG_BIF_NEEDSRENDERER);
|
|
|
|
Plug_RegisterBuiltin("LocalSound", Plug_LocalSound, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("SCR_CenterPrint", Plug_SCR_CenterPrint, PLUG_BIF_NEEDSRENDERER);
|
|
|
|
Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("LocalPlayerNumber", Plug_LocalPlayerNumber, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("GetServerInfo", Plug_GetServerInfo, PLUG_BIF_NEEDSRENDERER);
|
|
Plug_RegisterBuiltin("SetUserInfo", Plug_SetUserInfo, PLUG_BIF_NEEDSRENDERER);
|
|
|
|
Plug_RegisterBuiltin("S_RawAudio", Plug_S_RawAudio, PLUG_BIF_NEEDSRENDERER);
|
|
}
|
|
|
|
void Plug_Client_Close(plugin_t *plug)
|
|
{
|
|
Plug_FreePlugImages(plug);
|
|
|
|
|
|
if (menuplug == plug)
|
|
{
|
|
menuplug = NULL;
|
|
key_dest = key_game;
|
|
}
|
|
if (protocolclientplugin == plug)
|
|
{
|
|
protocolclientplugin = NULL;
|
|
if (cls.protocol == CP_PLUGIN)
|
|
cls.protocol = CP_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
void Plug_Client_Shutdown(void)
|
|
{
|
|
BZ_Free(pluginimagearray);
|
|
pluginimagearray = NULL;
|
|
pluginimagearraylen = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|