2022-03-08 05:31:34 +00:00
|
|
|
#include "q3common.h"
|
|
|
|
#if defined(VM_CG) && defined(HAVE_CLIENT)
|
2005-08-26 22:50:31 +00:00
|
|
|
#include "clq3defs.h"
|
2022-03-08 05:31:34 +00:00
|
|
|
#include "com_mesh.h"
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
//cl_ui.c
|
|
|
|
void CG_Command_f(void);
|
|
|
|
|
|
|
|
#define CGAME_IMPORT_API_VERSION 4
|
|
|
|
|
2021-11-03 20:30:40 +00:00
|
|
|
static model_t *box_model;
|
2022-03-08 05:31:34 +00:00
|
|
|
cvar_t *cl_shownet_ptr, *cl_c2sdupe_ptr, *cl_nodelta_ptr;
|
2011-06-29 18:39:11 +00:00
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
typedef enum {
|
|
|
|
CG_PRINT,
|
|
|
|
CG_ERROR,
|
|
|
|
CG_MILLISECONDS,
|
|
|
|
CG_CVAR_REGISTER,
|
|
|
|
CG_CVAR_UPDATE,
|
|
|
|
CG_CVAR_SET,
|
|
|
|
CG_CVAR_VARIABLESTRINGBUFFER,
|
|
|
|
CG_ARGC,
|
|
|
|
CG_ARGV,
|
|
|
|
CG_ARGS,
|
|
|
|
CG_FS_FOPENFILE, //10
|
|
|
|
CG_FS_READ,
|
|
|
|
CG_FS_WRITE,
|
|
|
|
CG_FS_FCLOSEFILE,
|
|
|
|
CG_SENDCONSOLECOMMAND,
|
|
|
|
CG_ADDCOMMAND,
|
|
|
|
CG_SENDCLIENTCOMMAND,
|
|
|
|
CG_UPDATESCREEN,
|
|
|
|
CG_CM_LOADMAP,
|
|
|
|
CG_CM_NUMINLINEMODELS,
|
|
|
|
CG_CM_INLINEMODEL, //20
|
|
|
|
CG_CM_LOADMODEL,
|
|
|
|
CG_CM_TEMPBOXMODEL,
|
|
|
|
CG_CM_POINTCONTENTS,
|
|
|
|
CG_CM_TRANSFORMEDPOINTCONTENTS,
|
|
|
|
CG_CM_BOXTRACE,
|
|
|
|
CG_CM_TRANSFORMEDBOXTRACE,
|
|
|
|
CG_CM_MARKFRAGMENTS,
|
|
|
|
CG_S_STARTSOUND,
|
|
|
|
CG_S_STARTLOCALSOUND,
|
|
|
|
CG_S_CLEARLOOPINGSOUNDS, //30
|
|
|
|
CG_S_ADDLOOPINGSOUND,
|
|
|
|
CG_S_UPDATEENTITYPOSITION,
|
|
|
|
CG_S_RESPATIALIZE,
|
|
|
|
CG_S_REGISTERSOUND,
|
|
|
|
CG_S_STARTBACKGROUNDTRACK,
|
|
|
|
CG_R_LOADWORLDMAP,
|
|
|
|
CG_R_REGISTERMODEL,
|
|
|
|
CG_R_REGISTERSKIN,
|
|
|
|
CG_R_REGISTERSHADER,
|
|
|
|
CG_R_CLEARSCENE, //40
|
|
|
|
CG_R_ADDREFENTITYTOSCENE,
|
|
|
|
CG_R_ADDPOLYTOSCENE,
|
|
|
|
CG_R_ADDLIGHTTOSCENE,
|
|
|
|
CG_R_RENDERSCENE,
|
|
|
|
CG_R_SETCOLOR,
|
|
|
|
CG_R_DRAWSTRETCHPIC,
|
|
|
|
CG_R_MODELBOUNDS,
|
|
|
|
CG_R_LERPTAG,
|
|
|
|
CG_GETGLCONFIG,
|
|
|
|
CG_GETGAMESTATE, //50
|
|
|
|
CG_GETCURRENTSNAPSHOTNUMBER,
|
|
|
|
CG_GETSNAPSHOT,
|
|
|
|
CG_GETSERVERCOMMAND,
|
|
|
|
CG_GETCURRENTCMDNUMBER,
|
|
|
|
CG_GETUSERCMD,
|
|
|
|
CG_SETUSERCMDVALUE,
|
|
|
|
CG_R_REGISTERSHADERNOMIP,
|
|
|
|
CG_MEMORY_REMAINING,
|
|
|
|
CG_R_REGISTERFONT,
|
|
|
|
CG_KEY_ISDOWN, //60
|
|
|
|
CG_KEY_GETCATCHER,
|
|
|
|
CG_KEY_SETCATCHER,
|
|
|
|
CG_KEY_GETKEY,
|
|
|
|
CG_PC_ADD_GLOBAL_DEFINE,
|
|
|
|
CG_PC_LOAD_SOURCE,
|
|
|
|
CG_PC_FREE_SOURCE,
|
|
|
|
CG_PC_READ_TOKEN,
|
|
|
|
CG_PC_SOURCE_FILE_AND_LINE,
|
|
|
|
CG_S_STOPBACKGROUNDTRACK,
|
|
|
|
CG_REAL_TIME, //70
|
|
|
|
CG_SNAPVECTOR,
|
|
|
|
CG_REMOVECOMMAND,
|
|
|
|
CG_R_LIGHTFORPOINT, //73
|
2014-02-11 17:51:29 +00:00
|
|
|
CG_CIN_PLAYCINEMATIC, //74
|
2005-08-26 22:50:31 +00:00
|
|
|
CG_CIN_STOPCINEMATIC, //75
|
|
|
|
CG_CIN_RUNCINEMATIC, //76
|
|
|
|
CG_CIN_DRAWCINEMATIC, //77
|
|
|
|
CG_CIN_SETEXTENTS, //78
|
|
|
|
CG_R_REMAP_SHADER, //79
|
|
|
|
CG_S_ADDREALLOOPINGSOUND, //80
|
|
|
|
CG_S_STOPLOOPINGSOUND, //81
|
|
|
|
|
|
|
|
CG_CM_TEMPCAPSULEMODEL, //82
|
|
|
|
CG_CM_CAPSULETRACE, //83
|
|
|
|
CG_CM_TRANSFORMEDCAPSULETRACE, //84
|
|
|
|
CG_R_ADDADDITIVELIGHTTOSCENE, //85
|
|
|
|
CG_GET_ENTITY_TOKEN, //86
|
|
|
|
CG_R_ADDPOLYSTOSCENE, //87
|
|
|
|
CG_R_INPVS, //88
|
|
|
|
// 1.32
|
|
|
|
CG_FS_SEEK, //89
|
|
|
|
|
|
|
|
CG_MEMSET = 100,
|
|
|
|
CG_MEMCPY,
|
|
|
|
CG_STRNCPY,
|
|
|
|
CG_SIN,
|
|
|
|
CG_COS,
|
|
|
|
CG_ATAN2,
|
|
|
|
CG_SQRT,
|
|
|
|
CG_FLOOR,
|
|
|
|
CG_CEIL,
|
|
|
|
CG_TESTPRINTINT,
|
|
|
|
CG_TESTPRINTFLOAT,
|
2008-06-01 22:06:22 +00:00
|
|
|
CG_ACOS,
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
|
|
|
|
/*CG_FTE_FINDPARTICLEEFFECT = 200,
|
2008-06-01 22:06:22 +00:00
|
|
|
CG_FTE_SPAWNPARTICLEEFFECT,
|
|
|
|
CG_FTE_SPAWNPARTICLETRAIL,
|
2022-03-08 05:31:34 +00:00
|
|
|
CG_FTE_FREEPARTICLESTATE*/
|
2008-06-01 22:06:22 +00:00
|
|
|
} cgameImport_t;
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2008-06-01 22:06:22 +00:00
|
|
|
/*
|
|
|
|
int CG_FTE_FINDPARTICLEEFFECT(char *particleeffectname) = #200;
|
|
|
|
int CG_FTE_SPAWNPARTICLEEFFECT(vec3_t pos, vec3_t dir, float count, int effectnum, void *pstate) = #201;
|
|
|
|
int CG_FTE_SPAWNPARTICLETRAIL(vec3_t start, vec3_t end, int effectnum, void *pstate) = #202;
|
|
|
|
void CG_FTE_FREEPARTICLESTATE(void *pstate) = #203;
|
|
|
|
*/
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
==================================================================
|
|
|
|
|
|
|
|
functions exported to the main executable
|
|
|
|
|
|
|
|
==================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
CG_INIT,
|
|
|
|
// void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum )
|
|
|
|
// called when the level loads or when the renderer is restarted
|
|
|
|
// all media should be registered at this time
|
|
|
|
// cgame will display loading status by calling SCR_Update, which
|
|
|
|
// will call CG_DrawInformation during the loading process
|
|
|
|
// reliableCommandSequence will be 0 on fresh loads, but higher for
|
|
|
|
// demos, tourney restarts, or vid_restarts
|
|
|
|
|
|
|
|
CG_SHUTDOWN,
|
|
|
|
// void (*CG_Shutdown)( void );
|
|
|
|
// oportunity to flush and close any open files
|
|
|
|
|
|
|
|
CG_CONSOLE_COMMAND,
|
|
|
|
// qboolean (*CG_ConsoleCommand)( void );
|
|
|
|
// a console command has been issued locally that is not recognized by the
|
|
|
|
// main game system.
|
|
|
|
// use Cmd_Argc() / Cmd_Argv() to read the command, return qfalse if the
|
|
|
|
// command is not known to the game
|
|
|
|
|
|
|
|
CG_DRAW_ACTIVE_FRAME,
|
|
|
|
// void (*CG_DrawActiveFrame)( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback );
|
|
|
|
// Generates and draws a game scene and status information at the given time.
|
|
|
|
// If demoPlayback is set, local movement prediction will not be enabled
|
|
|
|
|
|
|
|
CG_CROSSHAIR_PLAYER,
|
|
|
|
// int (*CG_CrosshairPlayer)( void );
|
|
|
|
|
|
|
|
CG_LAST_ATTACKER,
|
|
|
|
// int (*CG_LastAttacker)( void );
|
|
|
|
|
2011-05-29 04:26:29 +00:00
|
|
|
CG_KEY_EVENT,
|
2005-08-26 22:50:31 +00:00
|
|
|
// void (*CG_KeyEvent)( int key, qboolean down );
|
|
|
|
|
|
|
|
CG_MOUSE_EVENT,
|
|
|
|
// void (*CG_MouseEvent)( int dx, int dy );
|
|
|
|
CG_EVENT_HANDLING
|
|
|
|
// void (*CG_EventHandling)(int type);
|
|
|
|
} cgameExport_t;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int Contents_To_Q3(unsigned int fte)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (fte & FTECONTENTS_SOLID) //should use q3 constants.
|
|
|
|
ret |= 1;
|
|
|
|
if (fte & FTECONTENTS_WATER) //should use q3 constants.
|
|
|
|
ret |= 32;
|
|
|
|
if (fte & FTECONTENTS_SLIME) //should use q3 constants.
|
|
|
|
ret |= 16;
|
|
|
|
if (fte & FTECONTENTS_LAVA) //should use q3 constants.
|
|
|
|
ret |= 8;
|
|
|
|
if (fte & FTECONTENTS_SKY) //should use q3 constants.
|
|
|
|
ret |= 0x80000000;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
unsigned int Contents_From_Q3(unsigned int Q3)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (Q3 & 1) //should use q3 constants.
|
|
|
|
ret |= FTECONTENTS_SOLID;
|
|
|
|
if (Q3 & 32) //should use q3 constants.
|
|
|
|
ret |= FTECONTENTS_WATER;
|
|
|
|
if (Q3 & 16) //should use q3 constants.
|
|
|
|
ret |= FTECONTENTS_SLIME;
|
|
|
|
if (Q3 & 8) //should use q3 constants.
|
|
|
|
ret |= FTECONTENTS_LAVA;
|
|
|
|
if (Q3 & 0x80000000) //should use q3 constants.
|
|
|
|
ret |= FTECONTENTS_SKY;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
2022-03-08 05:31:34 +00:00
|
|
|
int stringOffsets[MAX_Q3_CONFIGSTRINGS];
|
|
|
|
char stringData[MAX_Q3_GAMESTATE_CHARS];
|
2005-08-26 22:50:31 +00:00
|
|
|
int dataCount;
|
|
|
|
} gameState_t;
|
2022-03-08 05:31:34 +00:00
|
|
|
static gameState_t cggamestate;
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
void CG_ClearGameState(void)
|
|
|
|
{
|
|
|
|
memset(&cggamestate, 0, sizeof(cggamestate));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CG_InsertIntoGameState(int num, const char *str)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
|
|
|
if (num < 5)
|
|
|
|
{
|
|
|
|
Con_DPrintf("%i: %s", num, str);
|
|
|
|
}
|
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
if (num == CFGSTR_SYSINFO)
|
|
|
|
{
|
|
|
|
//check some things.
|
2022-03-08 05:31:34 +00:00
|
|
|
ccs.servercount = atoi(worldfuncs->GetInfoKey(str, "sv_serverid"));
|
2009-11-04 21:16:50 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
if (cggamestate.dataCount + strlen(str)+1 > countof(cggamestate.stringData))
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
char oldstringData[countof(cggamestate.stringData)];
|
2005-08-26 22:50:31 +00:00
|
|
|
int i;
|
|
|
|
char *oldstr;
|
|
|
|
//copy the old strings to a temporary buffer
|
2022-03-08 05:31:34 +00:00
|
|
|
memcpy(oldstringData, cggamestate.stringData, countof(cggamestate.stringData));
|
2005-08-26 22:50:31 +00:00
|
|
|
cggamestate.dataCount = 0;
|
2022-03-08 05:31:34 +00:00
|
|
|
for (i = 0; i < countof(cggamestate.stringOffsets); i++)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
|
|
|
oldstr = oldstringData+cggamestate.stringOffsets[i];
|
|
|
|
if (*oldstr)
|
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
if (cggamestate.dataCount + strlen(oldstr)+1 > countof(cggamestate.stringData))
|
|
|
|
plugfuncs->EndGame("Too much configstring text\n");
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
cggamestate.dataCount+=1;
|
|
|
|
strcpy(cggamestate.stringData+cggamestate.dataCount, oldstr);
|
|
|
|
cggamestate.stringOffsets[i] = cggamestate.dataCount;
|
|
|
|
cggamestate.dataCount += strlen(oldstr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cggamestate.stringOffsets[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!*str)
|
|
|
|
{
|
|
|
|
cggamestate.stringOffsets[num] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cggamestate.dataCount+=1;
|
|
|
|
strcpy(cggamestate.stringData+cggamestate.dataCount, str);
|
|
|
|
cggamestate.stringOffsets[num] = cggamestate.dataCount;
|
|
|
|
cggamestate.dataCount += strlen(str);
|
|
|
|
}
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
const char *CG_GetConfigString(int num)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
if ((unsigned)num >= countof(cggamestate.stringOffsets))
|
2005-08-26 22:50:31 +00:00
|
|
|
return "";
|
|
|
|
return cggamestate.stringData + cggamestate.stringOffsets[num];
|
|
|
|
}
|
|
|
|
|
|
|
|
int CG_GetGameState(gameState_t *gs)
|
|
|
|
{
|
|
|
|
memcpy(gs, &cggamestate, sizeof(gameState_t));
|
|
|
|
return sizeof(gameState_t);
|
|
|
|
}
|
|
|
|
|
2019-02-24 08:32:45 +00:00
|
|
|
static int CGQ3_GetCurrentCmdNumber(void)
|
|
|
|
{ //Q3 sequences are 1-based, so 1<=idx<=latestsequence are valid
|
|
|
|
//FTE's sequences are 0-based, so 0<=idx<latestsequence are valid
|
2022-03-08 05:31:34 +00:00
|
|
|
return inputfuncs->GetMoveCount()-1;
|
2019-02-24 08:32:45 +00:00
|
|
|
}
|
|
|
|
static qboolean CGQ3_GetUserCmd(int cmdNumber, q3usercmd_t *ucmd)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
2019-02-24 08:32:45 +00:00
|
|
|
//q3 prediction uses for(int frame = CGQ3_GetCurrentCmdNumber() - CMD_BACKUP{64} + 1; frame <= CGQ3_GetCurrentCmdNumber(); frame++)
|
|
|
|
//skipping any that are older than the snapshot's time.
|
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
usercmd_t *cmd;
|
|
|
|
|
2019-02-24 08:32:45 +00:00
|
|
|
//q3 does not do partials.
|
2022-03-08 05:31:34 +00:00
|
|
|
if (cmdNumber < 0)
|
|
|
|
return false; //grr, stoopid q3.
|
|
|
|
if (cmdNumber >= inputfuncs->GetMoveCount())
|
|
|
|
plugfuncs->EndGame("CLQ3_GetUserCmd: %i >= %i", cmdNumber, inputfuncs->GetMoveCount());
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
cmd = inputfuncs->GetMoveEntry(cmdNumber);
|
|
|
|
if (!cmd)
|
2019-02-24 08:32:45 +00:00
|
|
|
return false;
|
2005-08-26 22:50:31 +00:00
|
|
|
ucmd->angles[0] = cmd->angles[0];
|
|
|
|
ucmd->angles[1] = cmd->angles[1];
|
|
|
|
ucmd->angles[2] = cmd->angles[2];
|
|
|
|
ucmd->serverTime = cmd->servertime;
|
|
|
|
ucmd->forwardmove = cmd->forwardmove;
|
|
|
|
ucmd->rightmove = cmd->sidemove;
|
|
|
|
ucmd->upmove = cmd->upmove;
|
|
|
|
ucmd->buttons = cmd->buttons;
|
|
|
|
ucmd->weapon = cmd->weapon;
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
vm_t *cgvm;
|
|
|
|
static const char *mapentspointer;
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2005-09-08 22:52:46 +00:00
|
|
|
extern int keycatcher;
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
qboolean CG_GetServerCommand(int cmdnum)
|
|
|
|
{
|
2019-07-02 04:12:20 +00:00
|
|
|
static char bigconfigstring[65536];
|
2022-03-08 05:31:34 +00:00
|
|
|
char *arg0;
|
2019-07-02 04:12:20 +00:00
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
//quote from cgame code:
|
|
|
|
// get the gamestate from the client system, which will have the
|
|
|
|
// new configstring already integrated
|
|
|
|
|
2019-07-02 04:12:20 +00:00
|
|
|
char *str = ccs.serverCommands[cmdnum & Q3TEXTCMD_MASK];
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
Con_DPrintf("Dispaching %s\n", str);
|
2022-03-08 05:31:34 +00:00
|
|
|
cmdfuncs->TokenizeString(str);
|
|
|
|
arg0 = cmdfuncs->Argv(0, NULL, 0);
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
if (!strcmp(arg0, "bcs0"))
|
2019-07-02 04:12:20 +00:00
|
|
|
{ //start
|
2022-03-08 05:31:34 +00:00
|
|
|
Q_snprintfz(bigconfigstring, sizeof(bigconfigstring), "cs %s \"%s", cmdfuncs->Argv(1, NULL, 0), cmdfuncs->Argv(2, NULL, 0));
|
2014-02-14 09:59:32 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-03-08 05:31:34 +00:00
|
|
|
if (!strcmp(arg0, "bcs1"))
|
2019-07-02 04:12:20 +00:00
|
|
|
{ //continuation
|
2022-03-08 05:31:34 +00:00
|
|
|
Q_strncatz(bigconfigstring, cmdfuncs->Argv(2, NULL, 0), sizeof(bigconfigstring));
|
2014-02-14 09:59:32 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-03-08 05:31:34 +00:00
|
|
|
if (!strcmp(arg0, "bcs2"))
|
2019-07-02 04:12:20 +00:00
|
|
|
{ //end
|
2022-03-08 05:31:34 +00:00
|
|
|
Q_strncatz(bigconfigstring, cmdfuncs->Argv(2, NULL, 0), sizeof(bigconfigstring));
|
2014-02-14 09:59:32 +00:00
|
|
|
Q_strncatz(bigconfigstring, "\"", sizeof(bigconfigstring));
|
2022-03-08 05:31:34 +00:00
|
|
|
cmdfuncs->TokenizeString(bigconfigstring);
|
2014-02-14 09:59:32 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
if (!strcmp(arg0, "cs"))
|
|
|
|
CG_InsertIntoGameState(atoi(cmdfuncs->Argv(1, NULL, 0)), cmdfuncs->Argv(2, NULL, 0));
|
|
|
|
else if (!strcmp(arg0, "map_restart"))
|
2022-03-08 05:34:13 +00:00
|
|
|
clientfuncs->ClearNotify();
|
2022-03-08 05:31:34 +00:00
|
|
|
else if (!strcmp(arg0, "disconnect"))
|
|
|
|
plugfuncs->EndGame("Server disconnected - %s", (cmdfuncs->Argc()>1)?cmdfuncs->Argv(1, NULL, 0):"No reason given");
|
2005-08-26 22:50:31 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-08 22:52:46 +00:00
|
|
|
typedef struct {
|
|
|
|
int firstPoint;
|
|
|
|
int numPoints;
|
2015-03-03 00:14:43 +00:00
|
|
|
} q3markFragment_t;
|
|
|
|
typedef struct {
|
|
|
|
float *points;
|
|
|
|
size_t maxpoints;
|
|
|
|
size_t numpoints;
|
|
|
|
q3markFragment_t *frags;
|
|
|
|
size_t maxfrags;
|
|
|
|
size_t numfrags;
|
|
|
|
} q3markFragment_ctx_t;
|
2016-02-15 06:01:17 +00:00
|
|
|
static void CG_MarkFragments_Callback(void *vctx, vec3_t *fte_restrict points, size_t numtris, shader_t *shader)
|
2015-03-03 00:14:43 +00:00
|
|
|
{
|
2016-02-15 06:01:17 +00:00
|
|
|
q3markFragment_ctx_t *ctx = vctx;
|
2015-03-03 00:14:43 +00:00
|
|
|
size_t i;
|
|
|
|
if (numtris > ctx->maxfrags-ctx->numfrags)
|
|
|
|
numtris = ctx->maxfrags-ctx->numfrags;
|
|
|
|
if (numtris > (ctx->maxpoints-ctx->numpoints)/3)
|
|
|
|
numtris = (ctx->maxpoints-ctx->numpoints)/3;
|
|
|
|
for (i = 0; i < numtris; i++)
|
|
|
|
{
|
|
|
|
ctx->frags[ctx->numfrags].numPoints = 3;
|
|
|
|
ctx->frags[ctx->numfrags].firstPoint = ctx->numpoints;
|
|
|
|
VectorCopy(points[0], ctx->points+3*(ctx->numpoints+0));
|
|
|
|
VectorCopy(points[1], ctx->points+3*(ctx->numpoints+1));
|
|
|
|
VectorCopy(points[2], ctx->points+3*(ctx->numpoints+2));
|
|
|
|
points += 3;
|
|
|
|
ctx->numfrags += 1;
|
|
|
|
ctx->numpoints += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-09-08 22:52:46 +00:00
|
|
|
int CG_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
|
2015-03-03 00:14:43 +00:00
|
|
|
int maxPoints, float *pointBuffer, int maxFragments, q3markFragment_t *fragmentBuffer )
|
2005-09-08 22:52:46 +00:00
|
|
|
{
|
|
|
|
vec3_t center;
|
|
|
|
vec3_t axis[3];
|
|
|
|
vec3_t p[4];
|
|
|
|
int i;
|
|
|
|
float radius;
|
2015-03-03 00:14:43 +00:00
|
|
|
q3markFragment_ctx_t ctx;
|
2005-09-08 22:52:46 +00:00
|
|
|
|
|
|
|
if (numPoints != 4)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
q3 gamecode includes something like this
|
|
|
|
|
|
|
|
originalPoints[0][i] = origin[i] - radius * axis[1][i] - radius * axis[2][i];
|
|
|
|
originalPoints[1][i] = origin[i] + radius * axis[1][i] - radius * axis[2][i];
|
|
|
|
originalPoints[2][i] = origin[i] + radius * axis[1][i] + radius * axis[2][i];
|
|
|
|
originalPoints[3][i] = origin[i] - radius * axis[1][i] + radius * axis[2][i];
|
|
|
|
|
|
|
|
We want that origional axis and the origin
|
|
|
|
axis[0] is given in the 'projection' parameter.
|
|
|
|
|
|
|
|
Yes, reversing this stuff means that we'll have no support for triangles.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VectorClear(center);
|
2009-11-04 21:16:50 +00:00
|
|
|
VectorMA(center, 0.25, points[0], center);
|
|
|
|
VectorMA(center, 0.25, points[1], center);
|
|
|
|
VectorMA(center, 0.25, points[2], center);
|
|
|
|
VectorMA(center, 0.25, points[3], center);
|
2005-09-08 22:52:46 +00:00
|
|
|
|
|
|
|
VectorSubtract(points[0], center, p[0]);
|
|
|
|
VectorSubtract(points[1], center, p[1]);
|
|
|
|
VectorSubtract(points[2], center, p[2]);
|
|
|
|
VectorSubtract(points[3], center, p[3]);
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
2009-11-04 21:16:50 +00:00
|
|
|
axis[1][i] = (p[2][i]-p[1][i]);
|
|
|
|
axis[2][i] = (p[3][i]-p[2][i]);
|
2005-09-08 22:52:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
radius = VectorNormalize(axis[1]);
|
|
|
|
VectorNormalize(axis[2]);
|
2009-11-04 21:16:50 +00:00
|
|
|
VectorNormalize2(projection, axis[0]);
|
|
|
|
|
2015-03-03 00:14:43 +00:00
|
|
|
ctx.points = pointBuffer;
|
|
|
|
ctx.maxpoints = maxPoints;
|
|
|
|
ctx.numpoints = 0;
|
|
|
|
ctx.frags = fragmentBuffer;
|
|
|
|
ctx.numfrags = 0;
|
|
|
|
ctx.maxfrags = maxFragments;
|
2022-03-08 05:31:34 +00:00
|
|
|
scenefuncs->ClipDecal(ccs.worldmodel, center, axis[0], axis[1], axis[2], radius, 0,0, CG_MarkFragments_Callback, &ctx);
|
2015-03-03 00:14:43 +00:00
|
|
|
return ctx.numfrags;
|
2005-09-08 22:52:46 +00:00
|
|
|
}
|
|
|
|
|
2019-01-29 07:18:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
//called by the sound code.
|
|
|
|
static struct
|
|
|
|
{
|
|
|
|
unsigned int entnum;
|
|
|
|
vec3_t origin;
|
|
|
|
// vec3_t velocity;
|
|
|
|
sfx_t *sfx;
|
|
|
|
qboolean ispersistent;
|
|
|
|
} *loopers;
|
|
|
|
static size_t numloopers;
|
|
|
|
static size_t maxloopers;
|
|
|
|
unsigned int CG_GatherLoopingSounds(vec3_t *positions, unsigned int *entnums, sfx_t **sounds, unsigned int max)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
if (max > numloopers)
|
|
|
|
max = numloopers;
|
|
|
|
for (i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
entnums[i] = loopers[i].entnum;
|
|
|
|
VectorCopy(loopers[i].origin, positions[i]);
|
|
|
|
sounds[i] = loopers[i].sfx;
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
static void CG_StopLoopingSounds(unsigned int entnum)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < numloopers; i++)
|
|
|
|
{
|
|
|
|
if (loopers[i].entnum == entnum)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == numloopers)
|
|
|
|
return;
|
|
|
|
loopers[i] = loopers[numloopers-1];
|
|
|
|
numloopers--;
|
|
|
|
}
|
2022-03-08 05:31:34 +00:00
|
|
|
static void CG_StartLoopingSounds(unsigned int entnum, float *origin, float *velocity, int range, const char *soundname, float volume, qboolean persistent)
|
2019-01-29 07:18:07 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < numloopers; i++)
|
|
|
|
{
|
|
|
|
if (loopers[i].entnum == entnum)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == numloopers)
|
|
|
|
{
|
|
|
|
if (numloopers == maxloopers)
|
|
|
|
Z_ReallocElements((void**)&loopers, &maxloopers, maxloopers+1, sizeof(*loopers));
|
|
|
|
numloopers++;
|
|
|
|
}
|
|
|
|
loopers[i].entnum = entnum;
|
|
|
|
VectorCopy(origin, loopers[i].origin);
|
|
|
|
//VectorCopy(velocity, loopers[i].velocity);
|
2022-03-08 05:31:34 +00:00
|
|
|
loopers[i].sfx = audiofuncs->PrecacheSound(soundname);
|
2019-01-29 07:18:07 +00:00
|
|
|
loopers[i].ispersistent = persistent;
|
2022-03-08 05:31:34 +00:00
|
|
|
// loopers[i].range = range;
|
|
|
|
// loopers[i].volume = volume;
|
2019-01-29 07:18:07 +00:00
|
|
|
}
|
|
|
|
static void CG_MoveLoopingSound(unsigned int entnum, float *origin)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < numloopers; i++)
|
|
|
|
{
|
|
|
|
if (loopers[i].entnum == entnum)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == numloopers)
|
|
|
|
return;
|
|
|
|
VectorCopy(origin, loopers[i].origin);
|
|
|
|
}
|
|
|
|
static void CG_ClearLoopingSounds(qboolean clearall)
|
|
|
|
{
|
|
|
|
if (clearall)
|
|
|
|
numloopers = 0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < numloopers; )
|
|
|
|
{
|
|
|
|
if (!loopers[i].ispersistent)
|
|
|
|
{
|
|
|
|
loopers[i] = loopers[numloopers-1];
|
|
|
|
numloopers--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
|
|
|
|
int VM_LerpTag(float *out, model_t *model, int f1, int f2, float l2, char *tagname);
|
|
|
|
|
|
|
|
#define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) plugfuncs->EndGame("Call to cgame trap %u passes invalid pointer\n", (unsigned int)fn); //out of bounds.
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2010-11-02 23:17:25 +00:00
|
|
|
static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
|
|
|
int ret=0;
|
|
|
|
|
|
|
|
//Remember to range check pointers.
|
|
|
|
//The QVM must not be allowed to write to anything outside it's memory.
|
|
|
|
//This includes getting the exe to copy it for it.
|
|
|
|
|
|
|
|
//don't bother with reading, as this isn't a virus risk.
|
|
|
|
//could be a cheat risk, but hey.
|
|
|
|
|
|
|
|
//make sure that any called functions are also range checked.
|
|
|
|
//like reading from files copies names into alternate buffers, allowing stack screwups.
|
|
|
|
//OutputDebugString(va("cl_cg: %i\n", fn));
|
2022-03-08 05:31:34 +00:00
|
|
|
switch((cgameImport_t)fn)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
|
|
|
case CG_PRINT:
|
2022-03-08 05:31:34 +00:00
|
|
|
{
|
|
|
|
const char *text = VM_POINTER(arg[0]);
|
|
|
|
Con_Printf("%s", text);
|
|
|
|
}
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_ERROR:
|
2022-03-08 05:31:34 +00:00
|
|
|
plugfuncs->EndGame("cgame: %s", (char*)VM_POINTER(arg[0]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_ARGC:
|
2022-03-08 05:31:34 +00:00
|
|
|
VM_LONG(ret) = cmdfuncs->Argc();
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_ARGV:
|
|
|
|
VALIDATEPOINTER(arg[1], arg[2]);
|
2022-03-08 05:31:34 +00:00
|
|
|
cmdfuncs->Argv(VM_LONG(arg[0]), VM_POINTER(arg[1]), VM_LONG(arg[2]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_ARGS:
|
|
|
|
VALIDATEPOINTER(arg[0], arg[1]);
|
2022-03-08 05:31:34 +00:00
|
|
|
cmdfuncs->Args(VM_POINTER(arg[0]), VM_LONG(arg[1]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_CVAR_REGISTER:
|
|
|
|
if (arg[0])
|
2013-05-03 04:28:08 +00:00
|
|
|
VALIDATEPOINTER(arg[0], sizeof(q3vmcvar_t));
|
2007-09-17 20:35:39 +00:00
|
|
|
return VMQ3_Cvar_Register(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_LONG(arg[3]));
|
2005-08-26 22:50:31 +00:00
|
|
|
case CG_CVAR_UPDATE:
|
2013-05-03 04:28:08 +00:00
|
|
|
VALIDATEPOINTER(arg[0], sizeof(q3vmcvar_t));
|
2007-09-17 20:35:39 +00:00
|
|
|
return VMQ3_Cvar_Update(VM_POINTER(arg[0]));
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
case CG_CVAR_SET:
|
2022-03-08 05:31:34 +00:00
|
|
|
cvarfuncs->SetString(VM_POINTER(arg[0]), VM_POINTER(arg[1])?VM_POINTER(arg[1]):"");
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_CVAR_VARIABLESTRINGBUFFER:
|
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
cvar_t *var = cvarfuncs->GetNVFDG(VM_POINTER(arg[0]), NULL, 0, NULL, "Q3CG created");
|
2005-08-26 22:50:31 +00:00
|
|
|
if (!VM_LONG(arg[2]))
|
|
|
|
VM_LONG(ret) = 0;
|
|
|
|
else if (!var)
|
|
|
|
{
|
|
|
|
VALIDATEPOINTER(arg[1], 1);
|
|
|
|
*(char *)VM_POINTER(arg[1]) = '\0';
|
|
|
|
VM_LONG(ret) = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VALIDATEPOINTER(arg[1], arg[2]);
|
|
|
|
Q_strncpyz(VM_POINTER(arg[1]), var->string, VM_LONG(arg[2]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_SENDCONSOLECOMMAND:
|
2009-11-04 21:16:50 +00:00
|
|
|
Con_DPrintf("CG_SENDCONSOLECOMMAND: %s", (char*)VM_POINTER(arg[0]));
|
2022-03-08 05:31:34 +00:00
|
|
|
cmdfuncs->AddText(VM_POINTER(arg[0]), false);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_ADDCOMMAND:
|
2022-03-08 05:31:34 +00:00
|
|
|
cmdfuncs->AddCommand(VM_POINTER(arg[0]), NULL, NULL);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_SENDCLIENTCOMMAND:
|
2009-11-04 21:16:50 +00:00
|
|
|
Con_DPrintf("CG_SENDCLIENTCOMMAND: %s", (char*)VM_POINTER(arg[0]));
|
2022-03-08 05:31:34 +00:00
|
|
|
CLQ3_SendClientCommand("%s", (char*)VM_POINTER(arg[0]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_UPDATESCREEN: //force a buffer swap cos loading won't refresh it soon.
|
2022-03-08 05:31:34 +00:00
|
|
|
drawfuncs->RedrawScreen();
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_FS_FOPENFILE: //fopen
|
|
|
|
if (arg[1])
|
|
|
|
VALIDATEPOINTER(arg[1], 4);
|
2007-09-02 19:55:17 +00:00
|
|
|
VM_LONG(ret) = VM_fopen(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_LONG(arg[2]), 1);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_FS_READ: //fread
|
|
|
|
VALIDATEPOINTER(arg[1], 4);
|
2007-09-02 19:55:17 +00:00
|
|
|
VM_LONG(ret) = VM_FRead(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), 1);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_FS_WRITE: //fwrite
|
2014-02-14 09:59:32 +00:00
|
|
|
Con_DPrintf("CG_FS_WRITE: not implemented\n");
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
2022-03-08 05:31:34 +00:00
|
|
|
case CG_FS_SEEK:
|
|
|
|
return VM_FSeek(arg[0], arg[1], arg[2], 1);
|
2005-08-26 22:50:31 +00:00
|
|
|
case CG_FS_FCLOSEFILE: //fclose
|
2007-09-02 19:55:17 +00:00
|
|
|
VM_fclose(VM_LONG(arg[0]), 1);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_CM_POINTCONTENTS: //int trap_CM_PointContents( const vec3_t p, clipHandle_t model );
|
|
|
|
{
|
|
|
|
unsigned int pc;
|
2011-06-29 18:39:11 +00:00
|
|
|
unsigned int modhandle = VM_LONG(arg[1]);
|
|
|
|
model_t *mod;
|
2022-03-08 05:31:34 +00:00
|
|
|
if (modhandle >= countof(ccs.model_precache))
|
2014-09-17 03:04:08 +00:00
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
// if (modhandle == countof(ccs.model_precache)+1)
|
2014-09-17 03:04:08 +00:00
|
|
|
// mod = &capsule_model;
|
|
|
|
// else
|
2021-11-03 20:30:40 +00:00
|
|
|
mod = box_model;
|
2014-09-17 03:04:08 +00:00
|
|
|
}
|
2011-06-29 18:39:11 +00:00
|
|
|
else
|
2022-03-08 05:31:34 +00:00
|
|
|
mod = ccs.model_precache[modhandle];
|
2014-10-05 20:04:11 +00:00
|
|
|
if (mod && mod->loadstate == MLS_LOADED)
|
2011-10-27 15:46:36 +00:00
|
|
|
pc = mod->funcs.NativeContents(mod, 0, 0, NULL, VM_POINTER(arg[0]), vec3_origin, vec3_origin);
|
2005-08-26 22:50:31 +00:00
|
|
|
else
|
2005-09-08 22:52:46 +00:00
|
|
|
pc = 1;//FTECONTENTS_SOLID;
|
|
|
|
VM_LONG(ret) = pc;//Contents_To_Q3(pc);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_CM_TRANSFORMEDPOINTCONTENTS: //int trap_CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles ) {
|
|
|
|
{
|
|
|
|
unsigned int pc;
|
|
|
|
float *p = VM_POINTER(arg[0]);
|
2011-06-29 18:39:11 +00:00
|
|
|
unsigned int modhandle = VM_LONG(arg[1]);
|
2005-08-26 22:50:31 +00:00
|
|
|
float *origin = VM_POINTER(arg[2]);
|
|
|
|
float *angles = VM_POINTER(arg[3]);
|
2011-06-29 18:39:11 +00:00
|
|
|
model_t *mod;
|
2022-03-08 05:31:34 +00:00
|
|
|
if (modhandle >= countof(ccs.model_precache))
|
2014-10-05 20:04:11 +00:00
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
// if (modhandle == countof(ccs.model_precache)+1)
|
2014-10-05 20:04:11 +00:00
|
|
|
// mod = &capsule_model;
|
|
|
|
// else
|
2021-11-03 20:30:40 +00:00
|
|
|
mod = box_model;
|
2014-10-05 20:04:11 +00:00
|
|
|
}
|
2011-06-29 18:39:11 +00:00
|
|
|
else
|
2022-03-08 05:31:34 +00:00
|
|
|
mod = ccs.model_precache[modhandle];
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2014-10-05 20:04:11 +00:00
|
|
|
if (mod && mod->loadstate == MLS_LOADED)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
|
|
|
vec3_t p_l;
|
2010-08-28 17:14:38 +00:00
|
|
|
vec3_t axis[3];
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
// subtract origin offset
|
|
|
|
VectorSubtract (p, origin, p_l);
|
|
|
|
|
|
|
|
// rotate start and end into the models frame of reference
|
|
|
|
if (angles[0] || angles[1] || angles[2])
|
|
|
|
{
|
2010-08-28 17:14:38 +00:00
|
|
|
AngleVectors (angles, axis[0], axis[1], axis[2]);
|
|
|
|
VectorNegate(axis[1], axis[1]);
|
|
|
|
pc = mod->funcs.NativeContents(mod, 0, 0, axis, p_l, vec3_origin, vec3_origin);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
else
|
2010-08-28 17:14:38 +00:00
|
|
|
pc = mod->funcs.NativeContents(mod, 0, 0, NULL, p_l, vec3_origin, vec3_origin);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
2010-08-28 17:14:38 +00:00
|
|
|
else
|
|
|
|
pc = Q3CONTENTS_SOLID;
|
|
|
|
VM_LONG(ret) = pc;
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-09-17 03:04:08 +00:00
|
|
|
case CG_CM_TRANSFORMEDCAPSULETRACE:
|
2005-08-26 22:50:31 +00:00
|
|
|
case CG_CM_TRANSFORMEDBOXTRACE:
|
|
|
|
// void trap_CM_BoxTrace( trace_t *results, const vec3_t start, const vec3_t end,
|
|
|
|
// const vec3_t mins, const vec3_t maxs,
|
|
|
|
// clipHandle_t model, int brushmask );
|
|
|
|
{
|
|
|
|
//FIXME: no protection of result trace.
|
|
|
|
trace_t tr;
|
|
|
|
q3trace_t *results = VM_POINTER(arg[0]);
|
|
|
|
float *start = VM_POINTER(arg[1]);
|
|
|
|
float *end = VM_POINTER(arg[2]);
|
|
|
|
float *mins = VM_POINTER(arg[3]);
|
|
|
|
float *maxs = VM_POINTER(arg[4]);
|
2011-06-29 18:39:11 +00:00
|
|
|
unsigned int modhandle = VM_LONG(arg[5]);
|
|
|
|
int brushmask = VM_LONG(arg[6]);
|
2005-08-26 22:50:31 +00:00
|
|
|
float *origin = VM_POINTER(arg[7]);
|
|
|
|
float *angles = VM_POINTER(arg[8]);
|
2011-06-29 18:39:11 +00:00
|
|
|
model_t *mod;
|
2022-03-08 05:31:34 +00:00
|
|
|
if (modhandle >= countof(ccs.model_precache))
|
2014-10-05 20:04:11 +00:00
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
// if (modhandle == countof(ccs.model_precache)+1)
|
2014-10-05 20:04:11 +00:00
|
|
|
// mod = &capsule_model;
|
|
|
|
// else
|
2021-11-03 20:30:40 +00:00
|
|
|
mod = box_model;
|
2014-10-05 20:04:11 +00:00
|
|
|
}
|
2011-06-29 18:39:11 +00:00
|
|
|
else
|
2022-03-08 05:31:34 +00:00
|
|
|
mod = ccs.model_precache[modhandle];
|
2011-06-29 18:39:11 +00:00
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
if (!mins)
|
|
|
|
mins = vec3_origin;
|
|
|
|
if (!maxs)
|
|
|
|
maxs = vec3_origin;
|
|
|
|
if (!origin)
|
|
|
|
origin = vec3_origin;
|
|
|
|
if (!angles)
|
|
|
|
angles = vec3_origin;
|
2014-10-05 20:04:11 +00:00
|
|
|
if (mod && mod->loadstate == MLS_LOADED)
|
2022-03-08 05:31:34 +00:00
|
|
|
worldfuncs->TransformedTrace(mod, 0, 0, start, end, mins, maxs, fn==CG_CM_TRANSFORMEDCAPSULETRACE, &tr, origin, angles, brushmask);
|
2005-08-26 22:50:31 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
memset(&tr, 0, sizeof(tr));
|
|
|
|
tr.allsolid = tr.startsolid = true;
|
|
|
|
tr.contents = 1;
|
|
|
|
}
|
|
|
|
results->allsolid = tr.allsolid;
|
|
|
|
results->contents = tr.contents;
|
|
|
|
results->fraction = tr.fraction;
|
|
|
|
results->entityNum = 0;
|
|
|
|
results->startsolid = tr.startsolid;
|
|
|
|
results->surfaceFlags = tr.surface?tr.surface->flags:0;
|
|
|
|
memcpy(results->endpos, tr.endpos, sizeof(vec3_t));
|
|
|
|
memcpy(&results->plane, &tr.plane, sizeof(cplane_t));
|
|
|
|
}
|
|
|
|
break;
|
2014-09-17 03:04:08 +00:00
|
|
|
case CG_CM_CAPSULETRACE:
|
2005-08-26 22:50:31 +00:00
|
|
|
case CG_CM_BOXTRACE:
|
|
|
|
// void trap_CM_BoxTrace( trace_t *results, const vec3_t start, const vec3_t end,
|
|
|
|
// const vec3_t mins, const vec3_t maxs,
|
|
|
|
// clipHandle_t model, int brushmask );
|
|
|
|
{
|
|
|
|
//FIXME: no protection of result trace.
|
|
|
|
trace_t tr;
|
|
|
|
q3trace_t *results = VM_POINTER(arg[0]);
|
|
|
|
float *start = VM_POINTER(arg[1]);
|
|
|
|
float *end = VM_POINTER(arg[2]);
|
|
|
|
float *mins = VM_POINTER(arg[3]);
|
|
|
|
float *maxs = VM_POINTER(arg[4]);
|
2022-03-08 05:31:34 +00:00
|
|
|
unsigned int modhandle = VM_LONG(arg[5]);
|
|
|
|
unsigned int brushmask = VM_LONG(arg[6]);
|
2011-06-29 18:39:11 +00:00
|
|
|
model_t *mod;
|
2022-03-08 05:31:34 +00:00
|
|
|
if (modhandle >= countof(ccs.model_precache))
|
2014-10-05 20:04:11 +00:00
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
// if (modhandle == countof(ccs.model_precache)+1)
|
2014-10-05 20:04:11 +00:00
|
|
|
// mod = &capsule_model;
|
|
|
|
// else
|
2021-11-03 20:30:40 +00:00
|
|
|
mod = box_model;
|
2014-10-05 20:04:11 +00:00
|
|
|
}
|
2011-06-29 18:39:11 +00:00
|
|
|
else
|
2022-03-08 05:31:34 +00:00
|
|
|
mod = ccs.model_precache[modhandle];
|
2011-06-29 18:39:11 +00:00
|
|
|
|
2014-10-05 20:04:11 +00:00
|
|
|
if (mod->loadstate != MLS_LOADED)
|
|
|
|
{
|
|
|
|
if (mod->loadstate == MLS_NOTLOADED)
|
2022-03-08 05:31:34 +00:00
|
|
|
scenefuncs->LoadModel(mod->publicname, MLV_SILENTSYNC);
|
2022-06-20 04:54:54 +00:00
|
|
|
if (mod->loadstate == MLS_LOADING && threadfuncs)
|
|
|
|
threadfuncs->WaitForCompletion(mod, &mod->loadstate, MLS_LOADING);
|
2014-10-05 20:04:11 +00:00
|
|
|
if (mod->loadstate != MLS_LOADED)
|
2022-03-08 05:31:34 +00:00
|
|
|
{
|
|
|
|
memset(results, 0, sizeof(*results));
|
|
|
|
results->fraction = 1;
|
|
|
|
break;
|
|
|
|
}
|
2014-10-05 20:04:11 +00:00
|
|
|
}
|
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
if (!mins)
|
|
|
|
mins = vec3_origin;
|
|
|
|
if (!maxs)
|
|
|
|
maxs = vec3_origin;
|
2017-01-29 13:10:53 +00:00
|
|
|
mod->funcs.NativeTrace(mod, 0, NULLFRAMESTATE, NULL, start, end, mins, maxs, fn==CG_CM_CAPSULETRACE, brushmask, &tr);
|
2005-08-26 22:50:31 +00:00
|
|
|
results->allsolid = tr.allsolid;
|
|
|
|
results->contents = tr.contents;
|
|
|
|
results->fraction = tr.fraction;
|
|
|
|
results->entityNum = 0;
|
|
|
|
results->startsolid = tr.startsolid;
|
|
|
|
results->surfaceFlags = tr.surface?tr.surface->flags:0;
|
|
|
|
memcpy(results->endpos, tr.endpos, sizeof(vec3_t));
|
|
|
|
memcpy(&results->plane, &tr.plane, sizeof(cplane_t));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2022-03-08 05:31:52 +00:00
|
|
|
case CG_R_LOADWORLDMAP:
|
|
|
|
{ //rendering
|
|
|
|
scenefuncs->NewMap(worldfuncs->LoadModel(VM_POINTER(arg[0]), MLV_SILENTSYNC));
|
|
|
|
}
|
|
|
|
break;
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
case CG_CM_LOADMAP:
|
2022-03-08 05:31:52 +00:00
|
|
|
{ //collisions
|
2005-08-26 22:50:31 +00:00
|
|
|
int i;
|
2007-09-17 20:35:39 +00:00
|
|
|
char *mapname = VM_POINTER(arg[0]);
|
2022-03-08 05:31:34 +00:00
|
|
|
ccs.worldmodel = ccs.model_precache[0] = worldfuncs->LoadModel(mapname, MLV_SILENTSYNC);
|
|
|
|
if (ccs.worldmodel->loadstate != MLS_LOADED)
|
|
|
|
plugfuncs->EndGame("Couldn't load map %s", mapname);
|
|
|
|
|
|
|
|
|
|
|
|
for (i=1 ; i<=ccs.worldmodel->numsubmodels && i < countof(ccs.model_precache); i++)
|
|
|
|
ccs.model_precache[i] = worldfuncs->LoadModel(worldfuncs->FixName(va("*%i", i), mapname), MLV_SILENTSYNC);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_CM_INLINEMODEL:
|
2022-03-08 05:31:34 +00:00
|
|
|
if ((unsigned int)VM_LONG(arg[0]) > (ccs.worldmodel?ccs.worldmodel->numsubmodels:0))
|
|
|
|
plugfuncs->EndGame("cgame asked for invalid model number\n");
|
2011-06-29 18:39:11 +00:00
|
|
|
VM_LONG(ret) = VM_LONG(arg[0]);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_CM_NUMINLINEMODELS:
|
2022-03-08 05:31:34 +00:00
|
|
|
VM_LONG(ret) = ccs.worldmodel?ccs.worldmodel->numsubmodels:0;
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_CM_TEMPBOXMODEL:
|
2022-03-08 05:31:34 +00:00
|
|
|
box_model = worldfuncs->TempBoxModel(VM_POINTER(arg[0]), VM_POINTER(arg[1]));
|
|
|
|
VM_LONG(ret) = countof(ccs.model_precache);
|
2014-09-17 03:04:08 +00:00
|
|
|
break;
|
|
|
|
case CG_CM_TEMPCAPSULEMODEL:
|
2022-03-08 05:31:34 +00:00
|
|
|
box_model = worldfuncs->TempBoxModel(VM_POINTER(arg[0]), VM_POINTER(arg[1]));
|
|
|
|
VM_LONG(ret) = countof(ccs.model_precache)+1;
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_R_MODELBOUNDS:
|
|
|
|
VALIDATEPOINTER(arg[1], sizeof(vec3_t));
|
|
|
|
VALIDATEPOINTER(arg[2], sizeof(vec3_t));
|
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
model_t *mod = scenefuncs->ModelFromId(arg[0]);
|
2005-08-26 22:50:31 +00:00
|
|
|
if (mod)
|
|
|
|
{
|
2022-06-20 04:54:54 +00:00
|
|
|
if (mod->loadstate == MLS_LOADING && threadfuncs)
|
|
|
|
threadfuncs->WaitForCompletion(mod, &mod->loadstate, MLS_LOADING);
|
2014-10-05 20:04:11 +00:00
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
VectorCopy(mod->mins, ((float*)VM_POINTER(arg[1])));
|
|
|
|
VectorCopy(mod->maxs, ((float*)VM_POINTER(arg[2])));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_R_REGISTERMODEL: //precache model
|
|
|
|
{
|
2014-03-30 08:55:06 +00:00
|
|
|
char *name = VM_POINTER(arg[0]);
|
2005-08-26 22:50:31 +00:00
|
|
|
model_t *mod;
|
2022-03-08 05:31:34 +00:00
|
|
|
if (!name)
|
|
|
|
return 0;
|
|
|
|
mod = scenefuncs->LoadModel(worldfuncs->FixName(name, ccs.worldmodel->name), MLV_SILENTSYNC);
|
2014-10-05 20:04:11 +00:00
|
|
|
if (mod->loadstate == MLS_FAILED || mod->type == mod_dummy)
|
2014-03-30 08:55:06 +00:00
|
|
|
VM_LONG(ret) = 0;
|
|
|
|
else
|
2022-03-08 05:31:34 +00:00
|
|
|
VM_LONG(ret) = scenefuncs->ModelToId(mod);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_R_REGISTERSKIN:
|
2022-03-08 05:31:34 +00:00
|
|
|
VM_LONG(ret) = scenefuncs->RegisterSkinFile(VM_POINTER(arg[0]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_R_REGISTERSHADER:
|
2007-05-25 22:16:29 +00:00
|
|
|
if (!*(char*)VM_POINTER(arg[0]))
|
|
|
|
VM_LONG(ret) = 0;
|
2010-05-01 22:47:47 +00:00
|
|
|
else
|
2022-03-08 05:31:34 +00:00
|
|
|
VM_LONG(ret) = drawfuncs->LoadImage(VM_POINTER(arg[0]));
|
2005-09-14 04:05:10 +00:00
|
|
|
break;
|
2005-08-26 22:50:31 +00:00
|
|
|
case CG_R_REGISTERSHADERNOMIP:
|
2007-05-25 22:16:29 +00:00
|
|
|
if (!*(char*)VM_POINTER(arg[0]))
|
|
|
|
VM_LONG(ret) = 0;
|
2010-05-01 22:47:47 +00:00
|
|
|
else
|
2022-03-08 05:31:34 +00:00
|
|
|
VM_LONG(ret) = drawfuncs->LoadImage(VM_POINTER(arg[0]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
2009-11-04 21:16:50 +00:00
|
|
|
case CG_R_CLEARSCENE: //clear scene (not rtlights, only dynamic ones)
|
2022-03-08 05:31:34 +00:00
|
|
|
scenefuncs->ClearScene();
|
2005-09-08 22:52:46 +00:00
|
|
|
break;
|
|
|
|
case CG_R_ADDPOLYTOSCENE:
|
2022-03-08 05:31:34 +00:00
|
|
|
VQ3_AddPolys(drawfuncs->ShaderFromId(arg[0]), VM_LONG(arg[1]), VM_POINTER(arg[2]), 1);
|
|
|
|
break;
|
|
|
|
case CG_R_ADDPOLYSTOSCENE:
|
|
|
|
VQ3_AddPolys(drawfuncs->ShaderFromId(arg[0]), VM_LONG(arg[1]), VM_POINTER(arg[2]), VM_LONG(arg[3]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_R_ADDREFENTITYTOSCENE: //add ent to scene
|
|
|
|
VQ3_AddEntity(VM_POINTER(arg[0]));
|
|
|
|
break;
|
|
|
|
case CG_R_ADDADDITIVELIGHTTOSCENE:
|
|
|
|
case CG_R_ADDLIGHTTOSCENE: //add light to scene.
|
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
dlight_t *dl = scenefuncs->AllocDlightOrg(-1, VM_POINTER(arg[0]));
|
|
|
|
dl->flags = LFLAG_NORMALMODE|LFLAG_REALTIMEMODE;
|
|
|
|
dl->radius = VM_FLOAT(arg[1]);
|
|
|
|
dl->die = ccs.time+0.1;
|
|
|
|
VectorSet(dl->color, VM_FLOAT(arg[2]), VM_FLOAT(arg[3]), VM_FLOAT(arg[4]));
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CG_R_RENDERSCENE: //render scene
|
|
|
|
VQ3_RenderView(VM_POINTER(arg[0]));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_R_SETCOLOR: //setcolour float*
|
|
|
|
{
|
|
|
|
float *f = VM_POINTER(arg[0]);
|
|
|
|
if (f)
|
2022-03-08 05:31:34 +00:00
|
|
|
drawfuncs->Colour4f(f[0], f[1], f[2], f[3]);
|
2005-08-26 22:50:31 +00:00
|
|
|
else
|
2022-03-08 05:31:34 +00:00
|
|
|
drawfuncs->Colour4f(1, 1, 1, 1);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_R_DRAWSTRETCHPIC:
|
2022-03-08 05:31:34 +00:00
|
|
|
drawfuncs->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]), VM_LONG(arg[8]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_R_LERPTAG: //Lerp tag...
|
|
|
|
VALIDATEPOINTER(arg[0], sizeof(float)*12);
|
2022-03-08 05:31:34 +00:00
|
|
|
VM_LONG(ret) = VM_LerpTag(VM_POINTER(arg[0]), scenefuncs->ModelFromId(arg[1]), VM_LONG(arg[2]), VM_LONG(arg[3]), VM_FLOAT(arg[4]), VM_POINTER(arg[5]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_S_REGISTERSOUND:
|
|
|
|
{
|
|
|
|
sfx_t *sfx;
|
2022-03-08 05:31:34 +00:00
|
|
|
sfx = audiofuncs->PrecacheSound(VM_POINTER(arg[0]));
|
2005-08-26 22:50:31 +00:00
|
|
|
if (sfx)
|
2007-09-17 20:35:39 +00:00
|
|
|
VM_LONG(ret) = VM_TOSTRCACHE(arg[0]);
|
2005-08-26 22:50:31 +00:00
|
|
|
else
|
|
|
|
VM_LONG(ret) = -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_S_STARTLOCALSOUND:
|
|
|
|
if (VM_LONG(arg[0]) != -1 && arg[0])
|
2022-03-08 05:31:34 +00:00
|
|
|
audiofuncs->LocalSound(VM_FROMSTRCACHE(arg[0]), CHAN_AUTO, 1.0);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_S_STARTSOUND:// ( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx )
|
2022-03-08 05:31:34 +00:00
|
|
|
audiofuncs->StartSound(VM_LONG(arg[1])+1, VM_LONG(arg[2]), audiofuncs->PrecacheSound(VM_FROMSTRCACHE(arg[3])), VM_POINTER(arg[0]), NULL, 1, 1, 0, 0, CF_CLI_NODUPES);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_S_ADDLOOPINGSOUND:
|
2014-02-14 09:59:32 +00:00
|
|
|
//entnum, origin, velocity, sfx
|
2022-03-08 05:31:34 +00:00
|
|
|
CG_StartLoopingSounds(VM_LONG(arg[0])+1, VM_POINTER(arg[1]), VM_POINTER(arg[2]), -1, VM_FROMSTRCACHE(arg[3]), 1, false);
|
2014-02-14 09:59:32 +00:00
|
|
|
break;
|
|
|
|
case CG_S_ADDREALLOOPINGSOUND:
|
|
|
|
//entnum, origin, velocity, sfx
|
2022-03-08 05:31:34 +00:00
|
|
|
CG_StartLoopingSounds(VM_LONG(arg[0])+1, VM_POINTER(arg[1]), VM_POINTER(arg[2]), -1, VM_FROMSTRCACHE(arg[3]), 1, true);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
2006-03-14 01:16:44 +00:00
|
|
|
case CG_S_STOPLOOPINGSOUND:
|
2014-02-14 09:59:32 +00:00
|
|
|
//entnum
|
2019-01-29 07:18:07 +00:00
|
|
|
CG_StopLoopingSounds(VM_LONG(arg[0])+1);
|
|
|
|
break;
|
|
|
|
case CG_S_CLEARLOOPINGSOUNDS:
|
|
|
|
//clearall
|
|
|
|
CG_ClearLoopingSounds(VM_LONG(arg[0]));
|
|
|
|
break;
|
|
|
|
case CG_S_UPDATEENTITYPOSITION://void trap_S_UpdateEntityPosition( int entityNum, const vec3_t origin );
|
|
|
|
//entnum, org
|
|
|
|
CG_MoveLoopingSound(VM_LONG(arg[0])+1, VM_POINTER(arg[1]));
|
2006-03-14 01:16:44 +00:00
|
|
|
break;
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
case CG_S_STARTBACKGROUNDTRACK:
|
2022-03-08 05:31:34 +00:00
|
|
|
audiofuncs->ChangeMusicTrack(VM_POINTER(arg[0]), VM_POINTER(arg[1]));
|
2013-08-27 13:18:09 +00:00
|
|
|
return 0;
|
2006-03-14 01:16:44 +00:00
|
|
|
case CG_S_STOPBACKGROUNDTRACK:
|
2022-03-08 05:31:34 +00:00
|
|
|
audiofuncs->ChangeMusicTrack(NULL, NULL);
|
2013-08-27 13:18:09 +00:00
|
|
|
return 0;
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
case CG_S_RESPATIALIZE://void trap_S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
|
2022-03-08 05:31:34 +00:00
|
|
|
audiofuncs->Spacialize(0, VM_LONG(arg[0])+1, VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_LONG(arg[3])?1:0, vec3_origin);
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_KEY_ISDOWN:
|
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
if (inputfuncs->IsKeyDown(VM_LONG(arg[0])))
|
2005-08-26 22:50:31 +00:00
|
|
|
VM_LONG(ret) = 1;
|
|
|
|
else
|
|
|
|
VM_LONG(ret) = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2006-03-14 01:16:44 +00:00
|
|
|
case CG_KEY_GETKEY:
|
|
|
|
{
|
Reworked client support for DPP5+. less code now, its much more graceful.
added waterfog command. waterfog overrides regular fog only when the view is in water.
fixed 64bit printf format specifiers. should work better on winxp64.
fixed some spec angle weirdness.
fixed viewsize 99.99 weirdness with ezhud.
fixed extra offset on the console (exhibited in 64bit builds, but not limited to).
fixed .avi playback, can now actually display frames again.
reimplemented line sparks.
fixed r_editlights_save flipping the light's pitch.
fixed issue with oggs failing to load.
fixed condump to cope with unicode properly.
made sv_bigcoords default except in quake. hexen2 kinda needs it for bsp angle precision.
fixed nq server to not stall weirdly on map changes.
fixed qwprogs svc_cdtrack not bugging out with nq clients on the server.
fixed restart command to load the last map run by the server, instead of start.bsp (when idle)
optimised d3d9 renderer a little. now uses less draw calls, especially with complex scenes. seems to get higher framerates than opengl now.
fixed d3d9 renderer to not bug out quite so much when run fullscreen (shader subsystem is now correctly initialised).
fixed a couple of bugs from font change. also now supports utf-8 in a few more places.
r_editlights_reload no longer generates rtlights inside the void. this resolves a few glitches (but should also help framerates a little).
fixed so corona-only lights won't generate shadowmaps and waste lots of time.
removed lots of #defines from qclib. I should never have made them in the first place, but I was lazy. obviously there's more left that I cba to remove yet.
fixed nested calls with variant-vectors. this fixes csaddon's light editor.
fixed qcc hc calling conventions using redundant stores.
disabled keywords can still be used by using __keyword instead.
fixed ftegccgui grep feature.
fixed motionless-dog qcc bug.
tweaked qcc warnings a little. -Wall is now a viable setting. you should be able to fix all those warnings.
fixed qw svc_intermission + dpp5+ clients bug.
fixed annoying spam about disconnecting in hexen2.
rewrote status command a little to cope with ipv6 addresses more gracefully
fixed significant stall when hibernating/debugging a server with a player sitting on it.
fixed truelightning.
fixed rocketlight overriding pflags.
fixed torches vanishing on vid_restart.
fixed issue with decal scaling.
fixed findentityfield builtin.
fixed fteqcc issue with ptr+1
fixed use of arrays inside class functions.
fixed/implemented fteqcc emulation of pointer opcodes.
added __inout keyword to fteqcc, so that it doesn't feel so horrendous.
fixed sizeof(*foo)
fixed *struct = struct;
fixed recursive structs.
fixed fteqcc warning report.
fixed sdl2 controller support, hopefully.
attempted to implement xinput, including per-player audio playback.
slightly fixed relaxed attitude to mouse focus when running fullscreen.
fixed weird warnings/errors with 'ent.arrayhead' terms. now generates sane errors.
implemented bindmaps (for csqc).
fixed crashing bug with eprint builtin.
implemented subset of music_playlist_* functionality. significant changes to music playback.
fixed some more dpcsqc compat.
fixed binds menu. now displays and accepts modifiers.
fixed issues with huge lightmaps.
fixed protocol determinism with dp clients connecting to fte servers. the initial getchallenge request now inhibits vanilla nq connection requests.
implemented support for 'dupe' userinfo key, allowing clients to request client->server packet duplication. should probably queue them tbh.
implemented sv_saveentfile command.
fixed resume after breaking inside a stepped-over function.
fixed erroneous footer after debugging.
(I wonder just how many things I broke with these fixes)
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4946 fc73d0e0-1445-4013-8a0c-d673dee63da5
2015-07-26 10:56:18 +00:00
|
|
|
int ret[1];
|
2022-03-08 05:31:34 +00:00
|
|
|
inputfuncs->FindKeysForCommand(0, VM_POINTER(arg[0]), ret, NULL, countof(ret));
|
2006-03-14 01:16:44 +00:00
|
|
|
return ret[0];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
case CG_KEY_GETCATCHER:
|
2019-09-04 07:59:40 +00:00
|
|
|
VM_LONG(ret) = Q3_GetKeyCatcher();
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_KEY_SETCATCHER:
|
2019-09-04 07:59:40 +00:00
|
|
|
Q3_SetKeyCatcher(VM_LONG(arg[0]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_GETGLCONFIG:
|
2022-03-08 05:31:34 +00:00
|
|
|
{
|
|
|
|
float vsize[2];
|
|
|
|
q3glconfig_t *cfg;
|
|
|
|
VALIDATEPOINTER(arg[0], sizeof(q3glconfig_t));
|
|
|
|
drawfuncs->GetVideoSize(vsize, NULL);
|
|
|
|
cfg = VM_POINTER(arg[0]);
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2007-09-18 01:08:49 +00:00
|
|
|
//do any needed work
|
2022-03-08 05:31:34 +00:00
|
|
|
memset(cfg, 0, sizeof(*cfg));
|
|
|
|
|
|
|
|
Q_strncpyz(cfg->renderer_string, "", sizeof(cfg->renderer_string));
|
|
|
|
Q_strncpyz(cfg->vendor_string, "", sizeof(cfg->vendor_string));
|
|
|
|
Q_strncpyz(cfg->version_string, "", sizeof(cfg->version_string));
|
|
|
|
Q_strncpyz(cfg->extensions_string, "", sizeof(cfg->extensions_string));
|
|
|
|
|
|
|
|
cfg->colorBits = 32;
|
|
|
|
cfg->depthBits = 24;
|
|
|
|
cfg->stencilBits = 8;//sh_config.stencilbits;
|
|
|
|
cfg->textureCompression = true;//!!sh_config.hw_bc;
|
|
|
|
cfg->textureEnvAddAvailable = true;//sh_config.env_add;
|
|
|
|
|
|
|
|
//these are the only three that really matter.
|
|
|
|
cfg->vidWidth = vsize[0];
|
|
|
|
cfg->vidHeight = vsize[1];
|
|
|
|
cfg->windowAspect = (float)vsize[0]/vsize[1];
|
2007-09-17 20:35:39 +00:00
|
|
|
}
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_GETGAMESTATE:
|
|
|
|
VALIDATEPOINTER(arg[0], sizeof(gameState_t));
|
|
|
|
VM_LONG(ret) = CG_GetGameState(VM_POINTER(arg[0]));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_CM_MARKFRAGMENTS:
|
2005-09-08 22:52:46 +00:00
|
|
|
VM_LONG(ret) = CG_MarkFragments( VM_LONG(arg[0]), VM_POINTER(arg[1]), VM_POINTER(arg[2]), VM_LONG(arg[3]), VM_POINTER(arg[4]), VM_LONG(arg[5]), VM_POINTER(arg[6]) );
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_GETCURRENTSNAPSHOTNUMBER:
|
|
|
|
VALIDATEPOINTER(arg[0], sizeof(int));
|
|
|
|
VALIDATEPOINTER(arg[1], sizeof(int));
|
|
|
|
*(int *)VM_POINTER(arg[0]) = ccs.snap.serverMessageNum;
|
2014-06-12 23:08:42 +00:00
|
|
|
*(int *)VM_POINTER(arg[1]) = ccs.snap.serverTime;
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_GETSNAPSHOT:
|
|
|
|
VALIDATEPOINTER(arg[1], sizeof(snapshot_t));
|
|
|
|
VM_LONG(ret) = CG_FillQ3Snapshot(VM_LONG(arg[0]), VM_POINTER(arg[1]));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_GETCURRENTCMDNUMBER:
|
2019-02-24 08:32:45 +00:00
|
|
|
VM_LONG(ret) = CGQ3_GetCurrentCmdNumber();
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_GETUSERCMD:
|
|
|
|
VALIDATEPOINTER(arg[1], sizeof(q3usercmd_t));
|
|
|
|
VM_LONG(ret) = CGQ3_GetUserCmd(VM_LONG(arg[0]), VM_POINTER(arg[1]));
|
|
|
|
break;
|
2014-03-30 08:55:06 +00:00
|
|
|
case CG_SETUSERCMDVALUE: //weaponselect, zoomsensitivity.
|
2005-08-26 22:50:31 +00:00
|
|
|
ccs.selected_weapon = VM_LONG(arg[0]);
|
2022-03-08 05:32:15 +00:00
|
|
|
inputfuncs->SetSensitivityScale(VM_FLOAT(arg[1]));
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_GETSERVERCOMMAND:
|
|
|
|
VM_LONG(ret) = CG_GetServerCommand(VM_LONG(arg[0]));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_MEMORY_REMAINING:
|
2013-07-14 12:22:51 +00:00
|
|
|
VM_LONG(ret) = 1024*1024*8;//Hunk_LowMemAvailable();
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_MILLISECONDS:
|
2022-03-08 05:31:34 +00:00
|
|
|
VM_LONG(ret) = plugfuncs->GetMilliseconds();
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_REAL_TIME:
|
2019-07-02 04:12:20 +00:00
|
|
|
VALIDATEPOINTER(arg[0], sizeof(q3time_t));
|
|
|
|
return Q3VM_GetRealtime(VM_POINTER(arg[0]));
|
2005-08-26 22:50:31 +00:00
|
|
|
|
|
|
|
case CG_SNAPVECTOR: // ( float *v )
|
|
|
|
VALIDATEPOINTER(arg[0], sizeof(vec3_t));
|
|
|
|
{
|
|
|
|
float *fp = (float *)VM_POINTER(arg[0]);
|
|
|
|
#define rint(x) (int)((x > 0)?(x + 0.5f):(x-0.5f))
|
|
|
|
fp[0] = rint(fp[0]);
|
|
|
|
fp[1] = rint(fp[1]);
|
|
|
|
fp[2] = rint(fp[2]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_PC_ADD_GLOBAL_DEFINE:
|
|
|
|
Con_Printf("CG_PC_ADD_GLOBAL_DEFINE not supported\n");
|
|
|
|
break;
|
|
|
|
case CG_PC_SOURCE_FILE_AND_LINE:
|
|
|
|
Script_Get_File_And_Line(arg[0], VM_POINTER(arg[1]), VM_POINTER(arg[2]));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CG_PC_LOAD_SOURCE:
|
|
|
|
return Script_LoadFile(VM_POINTER(arg[0]));
|
|
|
|
case CG_PC_FREE_SOURCE:
|
|
|
|
Script_Free(arg[0]);
|
|
|
|
break;
|
|
|
|
case CG_PC_READ_TOKEN:
|
|
|
|
//fixme: memory protect.
|
2014-02-14 09:59:32 +00:00
|
|
|
VALIDATEPOINTER(arg[1], sizeof(struct pc_token_s));
|
2005-08-26 22:50:31 +00:00
|
|
|
return Script_Read(arg[0], VM_POINTER(arg[1]));
|
|
|
|
|
|
|
|
// standard Q3
|
|
|
|
case CG_MEMSET:
|
|
|
|
VALIDATEPOINTER(arg[0], arg[2]);
|
2007-09-17 20:35:39 +00:00
|
|
|
{
|
|
|
|
void *dst = VM_POINTER(arg[0]);
|
|
|
|
memset(dst, arg[1], arg[2]);
|
|
|
|
}
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_MEMCPY:
|
|
|
|
VALIDATEPOINTER(arg[0], arg[2]);
|
2007-09-17 20:35:39 +00:00
|
|
|
{
|
|
|
|
void *dst = VM_POINTER(arg[0]);
|
|
|
|
void *src = VM_POINTER(arg[1]);
|
|
|
|
memcpy(dst, src, arg[2]);
|
|
|
|
}
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_STRNCPY:
|
|
|
|
VALIDATEPOINTER(arg[0], arg[2]);
|
2007-09-17 20:35:39 +00:00
|
|
|
{
|
|
|
|
void *dst = VM_POINTER(arg[0]);
|
|
|
|
void *src = VM_POINTER(arg[1]);
|
|
|
|
strncpy(dst, src, arg[2]);
|
|
|
|
}
|
2005-08-26 22:50:31 +00:00
|
|
|
break;
|
|
|
|
case CG_SIN:
|
|
|
|
VM_FLOAT(ret)=(float)sin(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
case CG_COS:
|
|
|
|
VM_FLOAT(ret)=(float)cos(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
case CG_ACOS:
|
|
|
|
VM_FLOAT(ret)=(float)acos(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
case CG_ATAN2:
|
|
|
|
VM_FLOAT(ret)=(float)atan2(VM_FLOAT(arg[0]), VM_FLOAT(arg[1]));
|
|
|
|
break;
|
|
|
|
case CG_SQRT:
|
|
|
|
VM_FLOAT(ret)=(float)sqrt(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
case CG_FLOOR:
|
|
|
|
VM_FLOAT(ret)=(float)floor(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
case CG_CEIL:
|
|
|
|
VM_FLOAT(ret)=(float)ceil(VM_FLOAT(arg[0]));
|
|
|
|
break;
|
|
|
|
|
2014-02-11 17:51:29 +00:00
|
|
|
case CG_R_REMAP_SHADER:
|
2022-03-08 05:31:34 +00:00
|
|
|
scenefuncs->RemapShader(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_FLOAT(arg[2]));
|
2014-02-11 17:51:29 +00:00
|
|
|
break;
|
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
case CG_R_REGISTERFONT:
|
|
|
|
VALIDATEPOINTER(arg[2], sizeof(fontInfo_t));
|
|
|
|
UI_RegisterFont(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_POINTER(arg[2]));
|
|
|
|
break;
|
2008-06-01 22:06:22 +00:00
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
case CG_GET_ENTITY_TOKEN:
|
|
|
|
mapentspointer = cmdfuncs->ParseToken(mapentspointer, VM_POINTER(arg[0]), arg[1], NULL);
|
|
|
|
return !!mapentspointer;
|
|
|
|
|
|
|
|
|
2020-03-07 09:00:40 +00:00
|
|
|
case CG_CIN_PLAYCINEMATIC:
|
|
|
|
return UI_Cin_Play(VM_POINTER(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), VM_LONG(arg[3]), VM_LONG(arg[4]), VM_LONG(arg[5]));
|
|
|
|
case CG_CIN_STOPCINEMATIC:
|
|
|
|
return UI_Cin_Stop(VM_LONG(arg[0]));
|
|
|
|
case CG_CIN_RUNCINEMATIC:
|
|
|
|
return UI_Cin_Run(VM_LONG(arg[0]));
|
|
|
|
case CG_CIN_DRAWCINEMATIC:
|
|
|
|
return UI_Cin_Draw(VM_LONG(arg[0]));
|
|
|
|
case CG_CIN_SETEXTENTS:
|
|
|
|
return UI_Cin_SetExtents(VM_LONG(arg[0]), VM_LONG(arg[1]), VM_LONG(arg[2]), VM_LONG(arg[3]), VM_LONG(arg[4]));
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
/* case CG_FTE_FINDPARTICLEEFFECT:
|
2008-11-09 22:29:28 +00:00
|
|
|
return pe->FindParticleType(VM_POINTER(arg[0]));
|
2008-06-01 22:06:22 +00:00
|
|
|
case CG_FTE_SPAWNPARTICLEEFFECT:
|
2008-11-09 22:29:28 +00:00
|
|
|
return pe->RunParticleEffectState(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_FLOAT(arg[2]), VM_LONG(arg[3]), VM_POINTER(arg[4]));
|
2008-06-01 22:06:22 +00:00
|
|
|
case CG_FTE_SPAWNPARTICLETRAIL:
|
2019-01-29 07:18:07 +00:00
|
|
|
return pe->ParticleTrail(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_LONG(arg[2]), 0, 1, NULL, VM_POINTER(arg[3]));
|
2008-06-01 22:06:22 +00:00
|
|
|
case CG_FTE_FREEPARTICLESTATE:
|
2008-11-09 22:29:28 +00:00
|
|
|
pe->DelinkTrailstate(VM_POINTER(arg[0]));
|
2008-06-01 22:06:22 +00:00
|
|
|
break;
|
2022-03-08 05:31:34 +00:00
|
|
|
*/
|
|
|
|
case CG_CM_LOADMODEL:
|
|
|
|
case CG_REMOVECOMMAND:
|
|
|
|
case CG_TESTPRINTINT:
|
|
|
|
case CG_TESTPRINTFLOAT:
|
|
|
|
case CG_R_INPVS:
|
|
|
|
case CG_R_LIGHTFORPOINT:
|
|
|
|
// default:
|
2011-01-29 19:53:38 +00:00
|
|
|
Con_Printf("Q3CG: Bad system trap: %i\n", (int)fn);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2010-11-02 23:17:25 +00:00
|
|
|
|
|
|
|
static int CG_SystemCallsVM(void *offset, quintptr_t mask, int fn, const int *arg)
|
|
|
|
{
|
|
|
|
if (sizeof(qintptr_t) == sizeof(int))
|
|
|
|
return CG_SystemCalls(offset, mask, fn, (qintptr_t*)arg);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qintptr_t args[10];
|
|
|
|
|
|
|
|
args[0]=arg[0];
|
|
|
|
args[1]=arg[1];
|
|
|
|
args[2]=arg[2];
|
|
|
|
args[3]=arg[3];
|
|
|
|
args[4]=arg[4];
|
|
|
|
args[5]=arg[5];
|
|
|
|
args[6]=arg[6];
|
|
|
|
args[7]=arg[7];
|
|
|
|
args[8]=arg[8];
|
|
|
|
args[9]=arg[9];
|
|
|
|
|
|
|
|
return CG_SystemCalls(offset, mask, fn, args);
|
|
|
|
}
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//I'm not keen on this.
|
|
|
|
//but dlls call it without saying what sort of vm it comes from, so I've got to have them as specifics
|
2010-11-02 23:17:25 +00:00
|
|
|
static qintptr_t EXPORT_FN CG_SystemCallsNative(qintptr_t arg, ...)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
2010-11-02 23:17:25 +00:00
|
|
|
qintptr_t args[10];
|
2005-08-26 22:50:31 +00:00
|
|
|
va_list argptr;
|
|
|
|
|
|
|
|
va_start(argptr, arg);
|
2010-11-02 23:17:25 +00:00
|
|
|
args[0]=va_arg(argptr, qintptr_t);
|
|
|
|
args[1]=va_arg(argptr, qintptr_t);
|
|
|
|
args[2]=va_arg(argptr, qintptr_t);
|
|
|
|
args[3]=va_arg(argptr, qintptr_t);
|
|
|
|
args[4]=va_arg(argptr, qintptr_t);
|
|
|
|
args[5]=va_arg(argptr, qintptr_t);
|
|
|
|
args[6]=va_arg(argptr, qintptr_t);
|
|
|
|
args[7]=va_arg(argptr, qintptr_t);
|
|
|
|
args[8]=va_arg(argptr, qintptr_t);
|
|
|
|
args[9]=va_arg(argptr, qintptr_t);
|
2005-08-26 22:50:31 +00:00
|
|
|
va_end(argptr);
|
|
|
|
|
2019-02-24 08:32:45 +00:00
|
|
|
return CG_SystemCalls(NULL, ~(quintptr_t)0, arg, args);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
int CG_Refresh(double time)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
|
|
|
if (!cgvm)
|
|
|
|
return false;
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
ccs.time = time;
|
|
|
|
vmfuncs->Call(cgvm, CG_DRAW_ACTIVE_FRAME, (int)(ccs.time*1000), 0, false);
|
|
|
|
drawfuncs->Colour4f(1, 1, 1, 1);
|
2005-08-26 22:50:31 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CG_Stop (void)
|
|
|
|
{
|
2019-09-04 07:59:40 +00:00
|
|
|
Q3_SetKeyCatcher(Q3_GetKeyCatcher()&~2);
|
2005-08-26 22:50:31 +00:00
|
|
|
if (cgvm)
|
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
vmfuncs->Call(cgvm, CG_SHUTDOWN);
|
|
|
|
vmfuncs->Destroy(cgvm);
|
2007-09-02 19:55:17 +00:00
|
|
|
VM_fcloseall(1);
|
2005-08-26 22:50:31 +00:00
|
|
|
cgvm = NULL;
|
2022-03-08 05:31:34 +00:00
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-30 08:55:06 +00:00
|
|
|
qboolean CG_VideoRestarted(void)
|
|
|
|
{
|
|
|
|
if (cgvm)
|
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
vmfuncs->Call(cgvm, CG_INIT, ccs.serverMessageNum, ccs.lastServerCommandNum, ccs.playernum);
|
2014-03-30 08:55:06 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-08-26 22:50:31 +00:00
|
|
|
void CG_Start (void)
|
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
CG_Stop();
|
2005-10-22 00:59:00 +00:00
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
box_model = worldfuncs->TempBoxModel(vec3_origin, vec3_origin); //just in case.
|
2021-11-03 20:30:40 +00:00
|
|
|
|
2022-03-08 05:32:15 +00:00
|
|
|
clientfuncs->SetLoadingState(true);
|
2022-03-08 05:31:34 +00:00
|
|
|
cgvm = vmfuncs->Create("cgame", cvarfuncs->GetFloat("com_gamedirnativecode")?CG_SystemCallsNative:NULL, "vm/cgame", CG_SystemCallsVM);
|
2022-03-08 05:32:15 +00:00
|
|
|
clientfuncs->SetLoadingState(false);
|
2005-08-26 22:50:31 +00:00
|
|
|
if (cgvm)
|
|
|
|
{ //hu... cgame doesn't appear to have a query version call!
|
2022-03-08 05:31:34 +00:00
|
|
|
vmfuncs->Call(cgvm, CG_INIT, ccs.serverMessageNum, ccs.lastServerCommandNum, ccs.playernum);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
else
|
2022-03-08 05:31:34 +00:00
|
|
|
plugfuncs->EndGame("Failed to initialise cgame module\n");
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
qboolean CG_ConsoleCommand(void)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
|
|
|
if (!cgvm)
|
|
|
|
return false;
|
2022-03-08 05:31:34 +00:00
|
|
|
// Con_DPrintf("CG_Command: %s %s\n", cmdfuncs->Argv(0), cmdfuncs->Args());
|
|
|
|
return vmfuncs->Call(cgvm, CG_CONSOLE_COMMAND);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
/*void CG_Command_f(void)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
|
|
|
if (cgvm)
|
2005-09-14 04:05:10 +00:00
|
|
|
{
|
|
|
|
Con_DPrintf("CG_Command_f: %s %s\n", Cmd_Argv(0), Cmd_Args());
|
2005-08-26 22:50:31 +00:00
|
|
|
if (!VM_Call(cgvm, CG_CONSOLE_COMMAND))
|
|
|
|
{
|
|
|
|
Cmd_ForwardToServer();
|
|
|
|
}
|
2005-09-14 04:05:10 +00:00
|
|
|
}
|
2022-03-08 05:31:34 +00:00
|
|
|
}*/
|
2005-08-26 22:50:31 +00:00
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
qboolean CG_KeyPressed(int key, int unicode, int down)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
2022-03-08 05:31:34 +00:00
|
|
|
|
|
|
|
if (!cgvm || !(Q3_GetKeyCatcher()&8))
|
2005-08-26 22:50:31 +00:00
|
|
|
return false;
|
2021-07-22 07:17:30 +00:00
|
|
|
|
|
|
|
/* if you change this here, it'll have to be changed in cl_cg.c too */
|
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
/* all these get interpreted as enter in Q3's UI... */
|
|
|
|
case K_JOY1:
|
|
|
|
case K_JOY2:
|
|
|
|
case K_JOY3:
|
|
|
|
case K_JOY4:
|
|
|
|
case K_AUX1:
|
|
|
|
case K_AUX2:
|
|
|
|
case K_AUX3:
|
|
|
|
case K_AUX4:
|
|
|
|
case K_AUX5:
|
|
|
|
case K_AUX6:
|
|
|
|
case K_AUX7:
|
|
|
|
case K_AUX8:
|
|
|
|
case K_AUX9:
|
|
|
|
case K_AUX10:
|
|
|
|
case K_AUX11:
|
|
|
|
case K_AUX14:
|
|
|
|
case K_AUX15:
|
|
|
|
case K_AUX16:
|
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
/* Q3 doesn't know about these keys, remap them */
|
|
|
|
case K_GP_START:
|
|
|
|
key = K_ESCAPE;
|
|
|
|
break;
|
|
|
|
case K_GP_DPAD_UP:
|
|
|
|
key = K_UPARROW;
|
|
|
|
break;
|
|
|
|
case K_GP_DPAD_DOWN:
|
|
|
|
key = K_DOWNARROW;
|
|
|
|
break;
|
|
|
|
case K_GP_DPAD_LEFT:
|
|
|
|
key = K_LEFTARROW;
|
|
|
|
break;
|
|
|
|
case K_GP_DPAD_RIGHT:
|
|
|
|
key = K_RIGHTARROW;
|
|
|
|
break;
|
|
|
|
case K_GP_A:
|
|
|
|
key = K_ENTER;
|
|
|
|
break;
|
2021-07-23 13:36:18 +00:00
|
|
|
case K_GP_B:
|
|
|
|
key = K_ESCAPE;
|
|
|
|
break;
|
|
|
|
case K_GP_X:
|
|
|
|
key = K_BACKSPACE;
|
|
|
|
break;
|
2021-07-22 07:17:30 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
return vmfuncs->Call(cgvm, CG_KEY_EVENT, key, down);
|
2005-08-26 22:50:31 +00:00
|
|
|
}
|
|
|
|
|
2022-03-08 05:31:34 +00:00
|
|
|
void CG_Restart(void)
|
2005-08-26 22:50:31 +00:00
|
|
|
{
|
|
|
|
CG_Stop();
|
|
|
|
CG_Start();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|