1
0
Fork 0
forked from fte/fteqw

fix autotrack issues.

tweak gameclock to work properly with demos.
tried to fix stealth chat messages.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4896 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-06-14 01:28:01 +00:00
parent cb5bbfee2a
commit bdc8ae1281
22 changed files with 425 additions and 214 deletions

View file

@ -45,8 +45,6 @@ enum
TM_MODHINTS, //using the mod's //at hints TM_MODHINTS, //using the mod's //at hints
TM_STATS //parsing mvd stats and making our own choices TM_STATS //parsing mvd stats and making our own choices
} autotrackmode; } autotrackmode;
int autotrack_hint; //the latest hint from the mod, might be negative for invalid.
int autotrack_killer; //if someone kills the guy we're tracking, this is the guy we should switch to.
char *autotrack_statsrule; char *autotrack_statsrule;
static void QDECL CL_AutoTrackChanged(cvar_t *v, char *oldval) static void QDECL CL_AutoTrackChanged(cvar_t *v, char *oldval)
{ {
@ -148,10 +146,13 @@ static int CL_FindHighTrack(int seat, char *rule)
//set a default to the currently tracked player, to reuse the current player we're tracking if someone lower equalises. //set a default to the currently tracked player, to reuse the current player we're tracking if someone lower equalises.
j = cl.playerview[seat].cam_spec_track; j = cl.playerview[seat].cam_spec_track;
if (j >= 0) if (j >= 0 && cl.players[j].name[0] && !cl.players[j].spectator)
max = CL_TrackScore(&cl.players[j], rule); max = CL_TrackScore(&cl.players[j], rule);
else else
{
max = -9999; max = -9999;
j = -1;
}
for (i = 0; i < cl.allocated_client_slots; i++) for (i = 0; i < cl.allocated_client_slots; i++)
{ {
@ -183,15 +184,15 @@ static int CL_AutoTrack_Choose(int seat)
{ {
int best = -1; int best = -1;
if (autotrackmode == TM_KILLER) if (autotrackmode == TM_KILLER)
best = autotrack_killer; best = cl.autotrack_killer;
if (autotrackmode == TM_MODHINTS && seat == 0 && autotrack_hint >= 0) if (autotrackmode == TM_MODHINTS && seat == 0 && cl.autotrack_hint >= 0)
best = autotrack_hint; best = cl.autotrack_hint;
if (autotrackmode == TM_STATS && cls.demoplayback == DPB_MVD) if (autotrackmode == TM_STATS && cls.demoplayback == DPB_MVD)
best = CL_FindHighTrack(seat, autotrack_statsrule); best = CL_FindHighTrack(seat, autotrack_statsrule);
if (autotrackmode == TM_HIGHTRACK || best == -1) if (autotrackmode == TM_HIGHTRACK || best == -1)
best = CL_FindHighTrack(seat, "f"); best = CL_FindHighTrack(seat, "f");
//TM_USER should generally avoid autotracking //TM_USER should generally avoid autotracking
autotrack_killer = best; //killer should continue to track whatever is currently tracked until its changed by frag message parsing cl.autotrack_killer = best; //killer should continue to track whatever is currently tracked until its changed by frag message parsing
return best; return best;
} }
@ -402,8 +403,13 @@ static void Cam_CheckHighTarget(playerview_t *pv)
j = CL_AutoTrack_Choose(pv - cl.playerview); j = CL_AutoTrack_Choose(pv - cl.playerview);
if (j >= 0) if (j >= 0)
{ {
if (!pv->cam_locked || pv->cam_spec_track != j) if (pv->cam_spec_track != j || !pv->cam_locked)
{ {
if (cl.teamplay)
Stats_Message("Now tracking:\n%s\n%s", cl.players[j].name, cl.players[j].team);
else
Stats_Message("Now tracking:\n%s", cl.players[j].name);
pv->cam_auto++;
Cam_Lock(pv, j); Cam_Lock(pv, j);
//un-lock any higher seats watching our new target. this keeps things ordered. //un-lock any higher seats watching our new target. this keeps things ordered.
for (spv = pv+1; spv >= cl.playerview && spv < &cl.playerview[cl.splitclients]; spv++) for (spv = pv+1; spv >= cl.playerview && spv < &cl.playerview[cl.splitclients]; spv++)
@ -577,12 +583,12 @@ void Cam_SetAutoTrack(int userid)
{ //this is a hint from the server about who to track { //this is a hint from the server about who to track
int slot; int slot;
playerview_t *pv = &cl.playerview[0]; playerview_t *pv = &cl.playerview[0];
autotrack_hint = -1; cl.autotrack_hint = -1;
for (slot = 0; slot < cl.allocated_client_slots; slot++) for (slot = 0; slot < cl.allocated_client_slots; slot++)
{ {
if (cl.players[slot].userid == userid) if (cl.players[slot].userid == userid)
{ {
autotrack_hint = slot; cl.autotrack_hint = slot;
return; return;
} }
} }
@ -719,6 +725,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
{ {
Cam_Unlock(pv); Cam_Unlock(pv);
VectorCopy(pv->viewangles, cmd->angles); VectorCopy(pv->viewangles, cmd->angles);
autotrackmode = TM_USER;
return; return;
} }
} }
@ -728,7 +735,7 @@ void Cam_FinishMove(playerview_t *pv, usercmd_t *cmd)
else else
{ {
pv->cam_oldbuttons &= ~BUTTON_ATTACK; pv->cam_oldbuttons &= ~BUTTON_ATTACK;
if (!pv->cam_auto) if (!pv->cam_auto && autotrackmode == TM_USER)
{ {
if ((cmd->buttons & BUTTON_JUMP) && !(pv->cam_oldbuttons & BUTTON_JUMP)) if ((cmd->buttons & BUTTON_JUMP) && !(pv->cam_oldbuttons & BUTTON_JUMP))
Cam_TrackCrosshairedPlayer(pv); Cam_TrackCrosshairedPlayer(pv);

View file

@ -322,6 +322,7 @@ void CL_MakeActive(char *gamename)
Con_DPrintf("%i additional FS searches\n", fs_finds); Con_DPrintf("%i additional FS searches\n", fs_finds);
fs_finds = 0; fs_finds = 0;
} }
cl.matchgametimestart = 0;
cls.state = ca_active; cls.state = ca_active;
S_Purge(true); S_Purge(true);
CL_UpdateWindowTitle(); CL_UpdateWindowTitle();
@ -1408,6 +1409,8 @@ void CL_ClearState (void)
cl.gametime = 0; cl.gametime = 0;
cl.gametimemark = 0; cl.gametimemark = 0;
cl.splitclients = 1; cl.splitclients = 1;
cl.autotrack_hint = -1;
cl.autotrack_killer = -1;
} }
/* /*
@ -1932,7 +1935,7 @@ void CL_CheckServerInfo(void)
else else
cl.matchstate = MATCH_DONTKNOW; cl.matchstate = MATCH_DONTKNOW;
if (oldstate != cl.matchstate) if (oldstate != cl.matchstate)
cl.matchgametime = 0; cl.matchgametimestart = cl.gametime;
CL_CheckServerPacks(); CL_CheckServerPacks();
@ -4688,10 +4691,6 @@ double Host_Frame (double time)
spare = 0; spare = 0;
host_frametime = (realtime - oldrealtime)*cl.gamespeed; host_frametime = (realtime - oldrealtime)*cl.gamespeed;
if (!cl.paused)
{
cl.matchgametime += host_frametime;
}
oldrealtime = realtime; oldrealtime = realtime;
CL_ProgressDemoTime(); CL_ProgressDemoTime();

View file

@ -5384,13 +5384,31 @@ void CL_PrintChat(player_info_t *plr, char *msg, int plrflags)
*(msg - 2) = 0; // it's assumed that msg has 2 chars before it due to strstr *(msg - 2) = 0; // it's assumed that msg has 2 chars before it due to strstr
}*/ }*/
if (*msg == '\r')
{
name = msg;
msg = strstr(msg, ": ");
if (msg)
{
name++;
*msg = 0;
msg+=2;
plrflags &= ~TPM_TEAM|TPM_OBSERVEDTEAM;
}
else
{
msg = name;
name = NULL;
}
}
if (msg[0] == '/' && msg[1] == 'm' && msg[2] == 'e' && msg[3] == ' ') if (msg[0] == '/' && msg[1] == 'm' && msg[2] == 'e' && msg[3] == ' ')
{ {
msg += 4; msg += 4;
memessage = true; // special /me formatting memessage = true; // special /me formatting
} }
if (plr) // use special formatting with a real chat message if (plr && !name) // use special formatting with a real chat message
name = plr->name; // use player's name name = plr->name; // use player's name
if (cl_standardchat.ival) if (cl_standardchat.ival)
@ -5463,6 +5481,8 @@ void CL_PrintChat(player_info_t *plr, char *msg, int plrflags)
else else
Q_strncatz(fullchatmessage, " ", sizeof(fullchatmessage)); Q_strncatz(fullchatmessage, " ", sizeof(fullchatmessage));
} }
else
Q_strncatz(fullchatmessage, "\1", sizeof(fullchatmessage));
// print message // print message
if (cl_parsewhitetext.value && (cl_parsewhitetext.value == 1 || (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM)))) if (cl_parsewhitetext.value && (cl_parsewhitetext.value == 1 || (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM))))
@ -6668,8 +6688,9 @@ void CLNQ_ParseProQuakeMessage (char *s)
break; break;
case pqc_match_time: case pqc_match_time:
cl.matchgametime = MSG_ReadBytePQ(&s)*60; cl.matchgametimestart = MSG_ReadBytePQ(&s)*60;
cl.matchgametime += MSG_ReadBytePQ(&s); cl.matchgametimestart += MSG_ReadBytePQ(&s);
cl.matchgametimestart = cl.gametime - cl.matchgametimestart;
break; break;
case pqc_match_reset: case pqc_match_reset:

View file

@ -239,6 +239,7 @@ cvar_t show_speed = SCVAR("show_speed", "0");
cvar_t show_speed_x = SCVAR("show_speed_x", "-1"); cvar_t show_speed_x = SCVAR("show_speed_x", "-1");
cvar_t show_speed_y = SCVAR("show_speed_y", "-9"); cvar_t show_speed_y = SCVAR("show_speed_y", "-9");
cvar_t scr_loadingrefresh = SCVAR("scr_loadingrefresh", "0"); cvar_t scr_loadingrefresh = SCVAR("scr_loadingrefresh", "0");
cvar_t scr_showobituaries = CVAR("scr_showobituaries", "0");
void *scr_curcursor; void *scr_curcursor;
@ -263,6 +264,7 @@ void CLSCR_Init(void)
Cvar_Register(&show_speed_x, cl_screengroup); Cvar_Register(&show_speed_x, cl_screengroup);
Cvar_Register(&show_speed_y, cl_screengroup); Cvar_Register(&show_speed_y, cl_screengroup);
Cvar_Register(&scr_neticontimeout, cl_screengroup); Cvar_Register(&scr_neticontimeout, cl_screengroup);
Cvar_Register(&scr_showobituaries, cl_screengroup);
memset(&key_customcursor, 0, sizeof(key_customcursor)); memset(&key_customcursor, 0, sizeof(key_customcursor));
@ -425,6 +427,8 @@ void VARGS Stats_Message(char *msg, ...)
va_list argptr; va_list argptr;
char str[2048]; char str[2048];
cprint_t *p = &scr_centerprint[0]; cprint_t *p = &scr_centerprint[0];
if (!scr_showobituaries.ival)
return;
if (p->time_off >= 0) if (p->time_off >= 0)
return; return;
@ -1433,23 +1437,18 @@ void SCR_DrawGameClock(void)
else else
timelimit = 0; timelimit = 0;
if (cl.playerview[0].statsf[STAT_MATCHSTARTTIME]) if (cl.matchstate == MATCH_STANDBY)
showtime = cl.servertime;
else if (cl.playerview[0].statsf[STAT_MATCHSTARTTIME])
showtime = timelimit - (cl.servertime - cl.playerview[0].statsf[STAT_MATCHSTARTTIME]); showtime = timelimit - (cl.servertime - cl.playerview[0].statsf[STAT_MATCHSTARTTIME]);
else else
showtime = timelimit - cl.matchgametime; showtime = timelimit - (cl.servertime - cl.matchgametimestart);
if (showtime < 0) if (showtime < 0)
{
showtime *= -1; showtime *= -1;
minutes = showtime/60;
seconds = (int)showtime - (minutes*60);
}
else
{
minutes = showtime/60;
seconds = (int)showtime - (minutes*60);
}
minutes = showtime/60;
seconds = (int)showtime - (minutes*60);
sprintf(str, " %02i:%02i", minutes, seconds); sprintf(str, " %02i:%02i", minutes, seconds);
SCR_StringXY(str, show_gameclock_x.value, show_gameclock_y.value); SCR_StringXY(str, show_gameclock_x.value, show_gameclock_y.value);

View file

@ -632,6 +632,7 @@ struct playerview_s
int cam_oldbuttons; // int cam_oldbuttons; //
vec3_t cam_viewangles; // vec3_t cam_viewangles; //
double cam_lastviewtime; // double cam_lastviewtime; //
float cam_reautotrack; // timer to throttle tracking changes.
int cam_spec_track; // player# of who we are tracking int cam_spec_track; // player# of who we are tracking
enum enum
{ {
@ -682,6 +683,8 @@ typedef struct
int movesequence; // client->server frames int movesequence; // client->server frames
int spectator; int spectator;
int autotrack_hint; //the latest hint from the mod, might be negative for invalid.
int autotrack_killer; //if someone kills the guy we're tracking, this is the guy we should switch to.
double last_ping_request; // while showing scoreboard double last_ping_request; // while showing scoreboard
double last_servermessage; double last_servermessage;
@ -818,7 +821,7 @@ typedef struct
qboolean sendprespawn; qboolean sendprespawn;
int contentstage; int contentstage;
double matchgametime; double matchgametimestart;
enum { enum {
MATCH_DONTKNOW, MATCH_DONTKNOW,
MATCH_COUNTDOWN, MATCH_COUNTDOWN,

View file

@ -111,6 +111,11 @@ qboolean Stats_HaveKills(void)
void VARGS Stats_Message(char *msg, ...); void VARGS Stats_Message(char *msg, ...);
qboolean Stats_TrackerImageLoaded(char *in)
{
qboolean error;
return Font_TrackerValid(unicode_decode(&error, in, &in, true));
}
static char *Stats_GenTrackerImageString(char *in) static char *Stats_GenTrackerImageString(char *in)
{ //images are of the form "foo \sg\ bar \q\" { //images are of the form "foo \sg\ bar \q\"
//which should eg be remapped to: "foo ^Ue200 bar foo ^Ue201" //which should eg be remapped to: "foo ^Ue200 bar foo ^Ue201"
@ -237,7 +242,7 @@ void Stats_FragMessage(int p1, int wid, int p2, qboolean teamkill)
} }
} }
Q_snprintfz(message, sizeof(message), "%s%s ^7%s %s%s\n", p1c, p1n, w->image?w->image:w->abrev, p2c, p2n); Q_snprintfz(message, sizeof(message), "%s%s ^7%s %s%s\n", p1c, p1n, Stats_TrackerImageLoaded(w->image)?w->image:w->abrev, p2c, p2n);
tracker = Con_FindConsole("tracker"); tracker = Con_FindConsole("tracker");
if (!tracker) if (!tracker)

View file

@ -99,6 +99,7 @@ void SCR_SetLoadingFile(char *str);
void Font_Init(void); void Font_Init(void);
void Font_Shutdown(void); void Font_Shutdown(void);
int Font_RegisterTrackerImage(const char *image); //returns a unicode char value that can be used to embed the char within a line of text. int Font_RegisterTrackerImage(const char *image); //returns a unicode char value that can be used to embed the char within a line of text.
qboolean Font_TrackerValid(unsigned int imid);
struct font_s *Font_LoadFont(float height, const char *fontfilename); struct font_s *Font_LoadFont(float height, const char *fontfilename);
void Font_Free(struct font_s *f); void Font_Free(struct font_s *f);
void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py); void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py);

View file

@ -1342,7 +1342,7 @@ void V_CalcRefdef (playerview_t *pv)
viewheight += pv->crouch; viewheight += pv->crouch;
if (pv->stats[STAT_HEALTH] < 0 && pv->cam_spec_track >= 0 && v_deathtilt.value) // PF_GIB will also set PF_DEAD if (pv->stats[STAT_HEALTH] < 0 && (!cl.spectator || pv->cam_locked) && v_deathtilt.value) // PF_GIB will also set PF_DEAD
{ {
if (!cl.spectator || cl_chasecam.ival) if (!cl.spectator || cl_chasecam.ival)
r_refdef.viewangles[ROLL] = 80*v_deathtilt.value; // dead view angle r_refdef.viewangles[ROLL] = 80*v_deathtilt.value; // dead view angle

View file

@ -2207,9 +2207,13 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
*plr = player; *plr = player;
} }
} }
}
if (!flags) // search for fake player // if (i == cl.allocated_client_slots)
// return flags;
}
/*
if (!flags) // search for fake/non player
{ {
if ((name = strstr(s, ": "))) // use name as temp if ((name = strstr(s, ": "))) // use name as temp
{ {
@ -2220,6 +2224,7 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
flags |= TPM_TEAM; flags |= TPM_TEAM;
} }
} }
*/
return flags; return flags;
} }

View file

@ -2967,9 +2967,8 @@ void Cmd_WriteConfig_f(void)
#else #else
snprintf(fname, sizeof(fname), "fte.cfg"); snprintf(fname, sizeof(fname), "fte.cfg");
#endif #endif
FS_NativePath(fname, FS_GAMEONLY, sysname, sizeof(sysname));
FS_CreatePath(fname, FS_GAMEONLY); f = FS_OpenWithFriends(fname, sysname, sizeof(sysname), 3, "quake.rc", "*.cfg", "configs/*.cfg");
f = FS_OpenVFS(fname, "wbp", FS_GAMEONLY);
all = cfg_save_all.ival; all = cfg_save_all.ival;
} }

View file

@ -2182,7 +2182,7 @@ unsigned int unicode_decode(int *error, const void *in, char **out, qboolean mar
if (markup && ((char*)in)[0] == '^' && ((char*)in)[1] == 'U' && ishexcode(((char*)in)[2]) && ishexcode(((char*)in)[3]) && ishexcode(((char*)in)[4]) && ishexcode(((char*)in)[5])) if (markup && ((char*)in)[0] == '^' && ((char*)in)[1] == 'U' && ishexcode(((char*)in)[2]) && ishexcode(((char*)in)[3]) && ishexcode(((char*)in)[4]) && ishexcode(((char*)in)[5]))
{ {
*out = (char*)in + 6; *out = (char*)in + 6;
charcode = (dehex(((char*)in)[2]) << 12) | (dehex(((char*)in)[2]) << 8) | (dehex(((char*)in)[2]) << 4) | (dehex(((char*)in)[2]) << 0); charcode = (dehex(((char*)in)[2]) << 12) | (dehex(((char*)in)[3]) << 8) | (dehex(((char*)in)[4]) << 4) | (dehex(((char*)in)[5]) << 0);
} }
else if (markup && ((char*)in)[0] == '^' && ((char*)in)[1] == '{') else if (markup && ((char*)in)[0] == '^' && ((char*)in)[1] == '{')
{ {
@ -4720,6 +4720,7 @@ static void Sys_ErrorThread(void *ctx, void *data, size_t a, size_t b)
} }
void COM_WorkerAbort(char *message) void COM_WorkerAbort(char *message)
{ {
int us;
struct com_work_s work; struct com_work_s work;
com_fatalerror = true; com_fatalerror = true;
if (Sys_IsMainThread()) if (Sys_IsMainThread())
@ -4728,6 +4729,7 @@ void COM_WorkerAbort(char *message)
if (!com_workercondition[0]) if (!com_workercondition[0])
return; //Sys_IsMainThread was probably called too early... return; //Sys_IsMainThread was probably called too early...
memset(&work, 0, sizeof(work));
work.func = Sys_ErrorThread; work.func = Sys_ErrorThread;
work.ctx = NULL; work.ctx = NULL;
work.data = message; work.data = message;
@ -4745,8 +4747,36 @@ void COM_WorkerAbort(char *message)
Sys_ConditionSignal(com_workercondition[0]); Sys_ConditionSignal(com_workercondition[0]);
Sys_UnlockConditional(com_workercondition[0]); Sys_UnlockConditional(com_workercondition[0]);
while(com_fatalerror) //find out which worker we are
for (us = WORKERTHREADS-1; us > 0; us--)
if (Sys_IsThread(com_workerthread[us]))
break;
if (us)
{
//and post any pending work we have back over to the main thread, because we're going down as soon as we can.
while(!com_workerdone[us])
{
struct com_work_s *w;
Sys_LockConditional(com_workercondition[us]);
w = com_work_head[us];
if (w)
com_work_head[us] = w->next;
if (!com_work_head[us])
com_work_head[us] = com_work_tail[us] = NULL;
Sys_UnlockConditional(com_workercondition[us]);
if (w)
{
COM_AddWork(0, w->func, w->ctx, w->data, w->a, w->b);
Z_Free(w);
}
else
Sys_ConditionSignal(com_workercondition[0]);
Sys_Sleep(0.1); Sys_Sleep(0.1);
}
com_workerdone[0] = true;
Sys_ConditionSignal(com_workercondition[0]);
}
Sys_ThreadAbort(); Sys_ThreadAbort();
} }
//return if there's *any* loading that needs to be done anywhere. //return if there's *any* loading that needs to be done anywhere.
@ -4880,6 +4910,7 @@ void COM_AssertMainThread(const char *msg)
void COM_DestroyWorkerThread(void) void COM_DestroyWorkerThread(void)
{ {
int i; int i;
COM_WorkerFullSync();
com_fatalerror = false; com_fatalerror = false;
for (i = 0; i < WORKERTHREADS; i++) for (i = 0; i < WORKERTHREADS; i++)
{ {
@ -4917,6 +4948,7 @@ void COM_DestroyWorkerThread(void)
if (com_workercondition[i]) if (com_workercondition[i])
Sys_DestroyConditional(com_workercondition[i]); Sys_DestroyConditional(com_workercondition[i]);
com_workercondition[i] = NULL; com_workercondition[i] = NULL;
com_workerthread[i] = NULL;
} }
if (com_resourcemutex) if (com_resourcemutex)

View file

@ -459,6 +459,8 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r
vfsfile_t *FS_OpenTemp(void); vfsfile_t *FS_OpenTemp(void);
vfsfile_t *FS_OpenTCP(const char *name, int defaultport); vfsfile_t *FS_OpenTCP(const char *name, int defaultport);
vfsfile_t *FS_OpenWithFriends(const char *fname, char *sysname, size_t sysnamesize, int numfriends, ...);
#define countof(array) (sizeof(array)/sizeof(array[0])) #define countof(array) (sizeof(array)/sizeof(array[0]))
#ifdef _WIN32 #ifdef _WIN32
//windows doesn't support utf-8. Which is a shame really, because that's the charset we expect from everything. //windows doesn't support utf-8. Which is a shame really, because that's the charset we expect from everything.
@ -485,7 +487,6 @@ qbyte *QDECL COM_LoadStackFile (const char *path, void *buffer, int bufsize, siz
qbyte *COM_LoadTempFile (const char *path, size_t *fsize); qbyte *COM_LoadTempFile (const char *path, size_t *fsize);
qbyte *COM_LoadTempMoreFile (const char *path, size_t *fsize); //allocates a little bit more without freeing old temp qbyte *COM_LoadTempMoreFile (const char *path, size_t *fsize); //allocates a little bit more without freeing old temp
//qbyte *COM_LoadHunkFile (const char *path); //qbyte *COM_LoadHunkFile (const char *path);
qbyte *COM_LoadMallocFile (const char *path, size_t *fsize);
searchpathfuncs_t *COM_IteratePaths (void **iterator, char *pathbuffer, int pathbuffersize, char *dirname, int dirnamesize); searchpathfuncs_t *COM_IteratePaths (void **iterator, char *pathbuffer, int pathbuffersize, char *dirname, int dirnamesize);
void COM_FlushFSCache(qboolean purge, qboolean domutex); //a file was written using fopen void COM_FlushFSCache(qboolean purge, qboolean domutex); //a file was written using fopen

View file

@ -1480,7 +1480,66 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out
return true; return true;
} }
/*locates and opens a file*/ //returns false to stop the enumeration. check the return value of the fs enumerator to see if it was canceled by this return value.
static int QDECL FS_NullFSEnumerator(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath)
{
return FALSE;
}
//opens a file in the same (writable) path that contains an existing version of the file or one of the other patterns listed
vfsfile_t *FS_OpenWithFriends(const char *fname, char *sysname, size_t sysnamesize, int numfriends, ...)
{
searchpath_t *search;
searchpath_t *lastwritable = NULL;
flocation_t loc;
va_list ap;
int i;
char cleanname[MAX_QPATH];
fname = FS_GetCleanPath(fname, cleanname, sizeof(cleanname));
if (!fname)
return NULL;
for (search = com_searchpaths; search ; search = search->next)
{
if ((search->flags & SPF_EXPLICIT) && (search->flags & SPF_WRITABLE))
lastwritable = search;
if (search->handle->FindFile(search->handle, &loc, fname, NULL))
break;
va_start(ap, numfriends);
for (i = 0; i < numfriends; i++)
{
char *path = va_arg(ap, char*);
if (!search->handle->EnumerateFiles(search->handle, path, FS_NullFSEnumerator, NULL))
break;
}
va_end(ap);
if (i < numfriends)
break;
}
if (lastwritable)
{
//figure out the system path
Q_strncpyz(sysname, lastwritable->logicalpath, sysnamesize);
FS_CleanDir(sysname, sysnamesize);
Q_strncatz(sysname, fname, sysnamesize);
//create the dir if needed and open the file.
COM_CreatePath(sysname);
return VFSOS_Open(sysname, "wbp");
}
return NULL;
}
/*locates and opens a file
modes:
r = read
w = write
a = append
t = text mode (because windows sucks). binary is otherwise assumed.
p = persist (ie: saved games and configs, but not downloads or large content)
*/
vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto) vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto)
{ {
char cleanname[MAX_QPATH]; char cleanname[MAX_QPATH];
@ -2164,6 +2223,8 @@ static searchpath_t *FS_AddPathHandle(searchpath_t **oldpaths, const char *purep
Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); Q_strncpyz(search->purepath, purepath, sizeof(search->purepath));
Q_strncpyz(search->logicalpath, logicalpath, sizeof(search->logicalpath)); Q_strncpyz(search->logicalpath, logicalpath, sizeof(search->logicalpath));
flags &= ~SPF_WRITABLE;
//temp packages also do not nest //temp packages also do not nest
if (!(flags & SPF_TEMPORARY)) if (!(flags & SPF_TEMPORARY))
{ {
@ -2908,21 +2969,21 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
{ {
//paths with a leading * are private, and not announced to clients that ask what the current gamedir is. //paths with a leading * are private, and not announced to clients that ask what the current gamedir is.
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, dir+1); Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, dir+1);
FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE); FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE|(com_homepathenabled?0:SPF_WRITABLE));
if (com_homepathenabled) if (com_homepathenabled)
{ {
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, dir+1); Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, dir+1);
FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE); FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE|SPF_WRITABLE);
} }
} }
else else
{ {
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, dir); Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, dir);
FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT); FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT|(com_homepathenabled?0:SPF_WRITABLE));
if (com_homepathenabled) if (com_homepathenabled)
{ {
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, dir); Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, dir);
FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT); FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT|SPF_WRITABLE);
} }
} }
} }

View file

@ -74,4 +74,5 @@ void FS_EnumerateKnownGames(qboolean (*callback)(void *usr, ftemanifest_t *man),
#define SPF_EXPLICIT 8 //a root gamedir (bumps depth on gamedir depth checks). #define SPF_EXPLICIT 8 //a root gamedir (bumps depth on gamedir depth checks).
#define SPF_UNTRUSTED 16 //has been downloaded from somewhere. configs inside it should never be execed with local access rights. #define SPF_UNTRUSTED 16 //has been downloaded from somewhere. configs inside it should never be execed with local access rights.
#define SPF_PRIVATE 32 //private to the client. ie: the fte dir. #define SPF_PRIVATE 32 //private to the client. ie: the fte dir.
#define SPF_WRITABLE 64 //safe to write here. lots of weird rules etc.
qboolean FS_LoadPackageFromFile(vfsfile_t *vfs, char *pname, char *localname, int *crc, unsigned int flags); qboolean FS_LoadPackageFromFile(vfsfile_t *vfs, char *pname, char *localname, int *crc, unsigned int flags);

View file

@ -476,7 +476,7 @@ newsection:
if (!strcmp(filename, "p_start")) if (!strcmp(filename, "p_start"))
{ {
section = 3; section = 3;
sprintf (newfiles[i].name, "patches/%s", filename); //the map loader will find these. sprintf (newfiles[i].name, "patches/%s.pat", filename); //the map loader will find these.
break; break;
} }
if (!strcmp(filename, "f_start")) if (!strcmp(filename, "f_start"))
@ -547,7 +547,7 @@ newsection:
section = 0; section = 0;
goto newsection; goto newsection;
} }
sprintf (newfiles[i].name, "patches/%s", filename); sprintf (newfiles[i].name, "patches/%s.pat", filename);
break; break;
case 4: //flats section case 4: //flats section
if (!strcmp(filename, "f_end")) if (!strcmp(filename, "f_end"))
@ -555,7 +555,7 @@ newsection:
section = 0; section = 0;
goto newsection; goto newsection;
} }
sprintf (newfiles[i].name, "flats/%s", filename); sprintf (newfiles[i].name, "flats/%s.raw", filename);
break; break;
} }
} }
@ -572,6 +572,8 @@ newsection:
Con_TPrintf ("Added packfile %s (%i files)\n", desc, numpackfiles); Con_TPrintf ("Added packfile %s (%i files)\n", desc, numpackfiles);
pack->mutex = Sys_CreateMutex();
pack->pub.fsver = FSVER; pack->pub.fsver = FSVER;
pack->pub.GetPathDetails = FSPAK_GetPathDetails; pack->pub.GetPathDetails = FSPAK_GetPathDetails;
pack->pub.ClosePath = FSPAK_ClosePath; pack->pub.ClosePath = FSPAK_ClosePath;

View file

@ -102,6 +102,7 @@ void Sys_SetThreadName(unsigned int dwThreadID, char *threadName);
void Sys_ThreadsInit(void); void Sys_ThreadsInit(void);
//qboolean Sys_IsThread(void *thread); //qboolean Sys_IsThread(void *thread);
qboolean Sys_IsMainThread(void); qboolean Sys_IsMainThread(void);
qboolean Sys_IsThread(void *thread);
void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize); void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize);
void Sys_WaitOnThread(void *thread); void Sys_WaitOnThread(void *thread);
void Sys_DetachThread(void *thread); void Sys_DetachThread(void *thread);

View file

@ -157,12 +157,12 @@ qboolean Sys_IsMainThread(void)
{ {
return mainthread == GetCurrentThreadId(); return mainthread == GetCurrentThreadId();
} }
/*
qboolean Sys_IsThread(void *thread) qboolean Sys_IsThread(void *thread)
{ {
return GetThreadId(thread) == GetCurrentThreadId(); return GetThreadId(thread) == GetCurrentThreadId();
} }
*/
/* Mutex calls */ /* Mutex calls */
/* /*

View file

@ -300,6 +300,25 @@ static image_t *Font_GetTrackerImage(unsigned int imid)
return NULL; return NULL;
return trackerimages[imid].image; return trackerimages[imid].image;
} }
qboolean Font_TrackerValid(unsigned int imid)
{
imid -= TRACKERFIRST;
if (imid >= countof(trackerimages))
return false;
if (!trackerimages[imid].image)
{
if (!*trackerimages[imid].name)
return false;
trackerimages[imid].image = Image_GetTexture(trackerimages[imid].name, NULL, 0, NULL, NULL, 0, 0, TF_INVALID);
}
if (!trackerimages[imid].image)
return false;
if (trackerimages[imid].image->status == TEX_LOADING)
COM_WorkerPartialSync(trackerimages[imid].image, &trackerimages[imid].image->status, TEX_LOADING);
if (trackerimages[imid].image->status != TEX_LOADED)
return false;
return true;
}
//called at load time - initalises font buffers //called at load time - initalises font buffers
void Font_Init(void) void Font_Init(void)
@ -1121,13 +1140,14 @@ void Doom_ExpandPatch(doompatch_t *p, unsigned char *b, int stride)
if (col->length + col->topdelta > p->height) if (col->length + col->topdelta > p->height)
break; break;
src = (unsigned char *)col + 3; /*why 3? why not, I suppose*/ src = (unsigned char *)col + 2; /*why 3? why not, I suppose*/
dst = b + stride*col->topdelta; dst = b + stride*col->topdelta;
for (y = 0; y < col->length; y++) for (y = 0; y < col->length; y++)
{ {
*dst = *src++; *dst = *src++;
dst += stride; dst += stride;
} }
src++;
col = (doomcolumn_t *)((unsigned char*)col + col->length + 4); col = (doomcolumn_t *)((unsigned char*)col + col->length + 4);
} }
b++; b++;
@ -1245,14 +1265,18 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename)
f->charheight = h; f->charheight = h;
} }
FS_FreeFile(dp); FS_FreeFile(dp);
} }
/*if all loaded okay, replicate the chars to the quake-compat range (both white+red chars)*/ /*if all loaded okay, replicate the chars to the quake-compat range (both white+red chars)*/
if (i == '_'+1) if (i == '_'+1)
{ {
//doom doesn't have many chars, so make sure the lower case chars exist.
for (i = 'a'; i <= 'z'; i++)
f->chars[i] = f->chars[i-'a'+'A'];
//no space char either
f->chars[' '].advance = 8; f->chars[' '].advance = 8;
f->singletexture = R_LoadTexture8("doomfont", PLANEWIDTH, PLANEHEIGHT, buf, 0, true); f->singletexture = R_LoadTexture8("doomfont", PLANEWIDTH, PLANEHEIGHT, buf, 0, true);
for (i = 0xe000; i <= 0xe0ff; i++) for (i = 0xe000; i <= 0xe0ff; i++)
{ {

View file

@ -62,7 +62,7 @@ model_t *Mod_LoadModel (model_t *mod, enum mlverbosity_e verbose);
static void Mod_PrintFormats_f(void); static void Mod_PrintFormats_f(void);
#ifdef MAP_DOOM #ifdef MAP_DOOM
qboolean Mod_LoadDoomLevel(model_t *mod); qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize);
#endif #endif
#ifdef DSPMODELS #ifdef DSPMODELS
@ -1392,7 +1392,7 @@ TRACE(("dbg: Mod_LoadTextures: inittexturedescs\n"));
if (!*mt->name) //I HATE MAPPERS! if (!*mt->name) //I HATE MAPPERS!
{ {
sprintf(mt->name, "unnamed%i", i); sprintf(mt->name, "unnamed%i", i);
Con_Printf(CON_WARNING "warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, mt->name); Con_DPrintf(CON_WARNING "warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, mt->name);
} }
mt->width = LittleLong (mt->width); mt->width = LittleLong (mt->width);

View file

@ -1520,7 +1520,7 @@ static qboolean Sh_VisOverlaps(qbyte *v1, qbyte *v2)
{ {
int i, m; int i, m;
if (!v2 || !v1) if (!v2 || !v1)
return false; return true;
m = (cl.worldmodel->numclusters+7)>>3; m = (cl.worldmodel->numclusters+7)>>3;
for (i=(m&~3) ; i<m ; i++) for (i=(m&~3) ; i<m ; i++)

View file

@ -3,6 +3,20 @@
#include "glquake.h" #include "glquake.h"
#include "shader.h" #include "shader.h"
char *va2(char *buffer, size_t buffersize, const char *format, ...)
{
va_list argptr;
va_start (argptr, format);
buffer[--buffersize] = 0;
vsnprintf (buffer, buffersize, format, argptr);
va_end (argptr);
return buffer;
}
int SignbitsForPlane (mplane_t *out); int SignbitsForPlane (mplane_t *out);
int PlaneTypeForNormal ( vec3_t normal ); int PlaneTypeForNormal ( vec3_t normal );
@ -208,7 +222,7 @@ unsigned int vertexsglbase;
typedef struct typedef struct
{ {
char name[8]; char name[16];
shader_t *shader; shader_t *shader;
unsigned short width; unsigned short width;
unsigned short height; unsigned short height;
@ -272,7 +286,12 @@ int Doom_PointContents(model_t *model, vec3_t axis[3], vec3_t p)
return FTECONTENTS_EMPTY; return FTECONTENTS_EMPTY;
} }
qboolean Doom_Trace(model_t *model, int hulloverride, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int contentstype, trace_t *trace) /*
fixme:
use q2-style bsp collision using the trisoup for flats collisions.
use blockmap for walls
*/
qboolean Doom_Trace(model_t *model, int hulloverride, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, qboolean iscapsule, unsigned int contentstype, trace_t *trace)
{ {
#if 0 #if 0
#define TRACESTEP 16 #define TRACESTEP 16
@ -657,8 +676,8 @@ qboolean Doom_Trace(model_t *model, int hulloverride, int frame, vec3_t axis[3],
trace->allsolid = trace->startsolid = false; trace->allsolid = trace->startsolid = false;
//Con_Printf("total = %f\n", trace->fraction); //Con_Printf("total = %f\n", trace->fraction);
return trace->fraction==1;
#endif #endif
return trace->fraction==1;
} }
@ -688,7 +707,7 @@ void Doom_LoadPalette(void)
if (!paletteloaded) if (!paletteloaded)
{ {
paletteloaded = true; paletteloaded = true;
file = FS_LoadMallocFile("wad/playpal"); file = FS_LoadMallocFile("wad/playpal", NULL);
if (file) if (file)
{ {
memcpy(doompalette, file, 768); memcpy(doompalette, file, 768);
@ -706,10 +725,9 @@ void Doom_LoadPalette(void)
} }
} }
#endif #endif
int Doom_LoadFlat(char *flatname) int Doom_LoadFlat(model_t *mod, char *flatname)
{ {
#ifndef SERVERONLY #ifndef SERVERONLY
char *file;
char texname[64]; char texname[64];
int texnum; int texnum;
@ -725,23 +743,10 @@ int Doom_LoadFlat(char *flatname)
memset(gldoomtextures + numgldoomtextures, 0, sizeof(gldoomtextures[numgldoomtextures])); memset(gldoomtextures + numgldoomtextures, 0, sizeof(gldoomtextures[numgldoomtextures]));
numgldoomtextures++; numgldoomtextures++;
strncpy(gldoomtextures[texnum].name, texname, 8); Q_strncpyz(gldoomtextures[texnum].name, texname, sizeof(gldoomtextures[texnum].name));
gldoomtextures[texnum].shader = R_RegisterShader(texname, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\n}\n}\n");
gldoomtextures[texnum].width = 64; gldoomtextures[texnum].width = 64;
gldoomtextures[texnum].height = 64; gldoomtextures[texnum].height = 64;
gldoomtextures[texnum].meshptr = &gldoomtextures[texnum].mesh;
gldoomtextures[texnum].batch.mesh = &gldoomtextures[texnum].meshptr;
gldoomtextures[texnum].batch.next = loadmodel->batches[gldoomtextures[texnum].shader->sort];
loadmodel->batches[gldoomtextures[texnum].shader->sort] = &gldoomtextures[texnum].batch;
file = FS_LoadMallocFile(texname);
if (file)
{
gldoomtextures[texnum].shader->defaulttextures.base = R_LoadTexture8Pal24(texname, 64, 64, file, doompalette, 0);
Z_Free(file);
}
return texnum; return texnum;
#else #else
@ -814,7 +819,8 @@ static void GLR_DrawWall(int texnum, int s, int t, float x1, float y1, float z1,
mesh->numvertexes += 4; mesh->numvertexes += 4;
mesh->numindexes += 6; mesh->numindexes += 6;
BE_DrawMesh_Single(tex->shader, mesh, NULL, &tex->shader->defaulttextures, 0); if (tex->shader)
BE_DrawMesh_Single(tex->shader, mesh, NULL, 0);
} }
static void GLR_DrawFlats(int floortexnum, int floorheight, int ceiltexnum, int ceilheight, int numverts, unsigned short *verts, unsigned int colour4b) static void GLR_DrawFlats(int floortexnum, int floorheight, int ceiltexnum, int ceilheight, int numverts, unsigned short *verts, unsigned int colour4b)
@ -859,7 +865,8 @@ static void GLR_DrawFlats(int floortexnum, int floorheight, int ceiltexnum, int
mesh->numvertexes += numverts; mesh->numvertexes += numverts;
mesh->numindexes += numverts; mesh->numindexes += numverts;
BE_DrawMesh_Single(floortex->shader, mesh, NULL, &floortex->shader->defaulttextures, 0); if (floortex->shader)
BE_DrawMesh_Single(floortex->shader, mesh, NULL, 0);
} }
//ceiling //ceiling
@ -898,7 +905,8 @@ static void GLR_DrawFlats(int floortexnum, int floorheight, int ceiltexnum, int
mesh->numvertexes += numverts; mesh->numvertexes += numverts;
mesh->numindexes += numverts; mesh->numindexes += numverts;
BE_DrawMesh_Single(ceiltex->shader, mesh, NULL, &ceiltex->shader->defaulttextures, 0); if (ceiltex->shader)
BE_DrawMesh_Single(ceiltex->shader, mesh, NULL, 0);
} }
} }
@ -1125,7 +1133,7 @@ void GLR_DoomWorld(void)
for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan. for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan.
{ {
t = &gldoomtextures[texnum]; t = &gldoomtextures[texnum];
if (t->mesh.numindexes) if (t->mesh.numindexes && t->shader)
{ {
t->batch.next = cl.worldmodel->batches[t->shader->sort]; t->batch.next = cl.worldmodel->batches[t->shader->sort];
cl.worldmodel->batches[t->shader->sort] = &t->batch; cl.worldmodel->batches[t->shader->sort] = &t->batch;
@ -1375,7 +1383,7 @@ static unsigned short *Triangulate_Finish(int *numtris, unsigned short *old, int
return out; return out;
} }
static void Triangulate_Sectors(dsector_t *sectorl, qboolean glbspinuse) static void Triangulate_Sectors(model_t *mod, dsector_t *sectorl, qboolean glbspinuse)
{ {
int seg, nsec; int seg, nsec;
int i, sec=-1; int i, sec=-1;
@ -1448,8 +1456,8 @@ static void Triangulate_Sectors(dsector_t *sectorl, qboolean glbspinuse)
for (i = 0; i < sectorc; i++) for (i = 0; i < sectorc; i++)
{ {
sectorm[i].ceilingtex = Doom_LoadFlat(sectorl[i].ceilingtexture); sectorm[i].ceilingtex = Doom_LoadFlat(mod, sectorl[i].ceilingtexture);
sectorm[i].floortex = Doom_LoadFlat(sectorl[i].floortexture); sectorm[i].floortex = Doom_LoadFlat(mod, sectorl[i].floortexture);
sectorm[i].lightlev = sectorl[i].lightlevel; sectorm[i].lightlev = sectorl[i].lightlevel;
sectorm[i].specialtype = sectorl[i].specialtype; sectorm[i].specialtype = sectorl[i].specialtype;
sectorm[i].tag = sectorl[i].tag; sectorm[i].tag = sectorl[i].tag;
@ -1464,9 +1472,9 @@ static void *textures2;
static char *pnames; static char *pnames;
static void Doom_LoadTextureInfos(void) static void Doom_LoadTextureInfos(void)
{ {
textures1 = FS_LoadMallocFile("wad/texture1"); textures1 = FS_LoadMallocFile("wad/texture1", NULL);
textures2 = FS_LoadMallocFile("wad/texture2"); textures2 = FS_LoadMallocFile("wad/texture2", NULL);
pnames = FS_LoadMallocFile("wad/pnames"); pnames = FS_LoadMallocFile("wad/pnames", NULL);
} }
typedef struct { typedef struct {
@ -1494,7 +1502,7 @@ typedef struct {
short ypos; short ypos;
} doomimage_t; } doomimage_t;
static void Doom_ExtractPName(unsigned int *out, doomimage_t *di, int outwidth, int outheight, int x, int y) static void Doom_ExtractPName(unsigned int *out, doomimage_t *di, size_t imgsize, int outwidth, int outheight, int x, int y)
{ {
unsigned int *colpointers; unsigned int *colpointers;
int c, fr, rc, extra; int c, fr, rc, extra;
@ -1518,7 +1526,7 @@ static void Doom_ExtractPName(unsigned int *out, doomimage_t *di, int outwidth,
if (c+x >= outwidth) if (c+x >= outwidth)
break; break;
if (colpointers[c] >= com_filesize) if (colpointers[c] >= imgsize)
break; break;
coldata = data + colpointers[c]; coldata = data + colpointers[c];
while(1) while(1)
@ -1535,7 +1543,8 @@ static void Doom_ExtractPName(unsigned int *out, doomimage_t *di, int outwidth,
if (fr<0) if (fr<0)
{ {
coldata -= fr; //plus coldata += -fr; //plus
rc -= -fr;
fr = 0; fr = 0;
} }
@ -1587,11 +1596,16 @@ static texid_t Doom_LoadPatchFromTexWad(char *name, void *texlump, unsigned shor
tc = (ddoomtexturecomponant_t*)(tx+1); tc = (ddoomtexturecomponant_t*)(tx+1);
for (i = 0; i < tx->componantcount; i++, tc++) for (i = 0; i < tx->componantcount; i++, tc++)
{ {
doomimage_t *img;
size_t imgsize;
strncpy(patch+8, pnames+4+8*tc->patchnum, 8); strncpy(patch+8, pnames+4+8*tc->patchnum, 8);
Q_strlwr(patch+8); Q_strlwr(patch+8);
patch[16] = '\0'; patch[16] = '\0';
Q_strncatz(patch, ".pat", sizeof(patch));
Doom_ExtractPName(tex, (doomimage_t *)COM_LoadTempFile(patch), tx->width, tx->height, tc->xoffset, tc->yoffset); img = (doomimage_t *)FS_LoadMallocFile(patch, &imgsize);
Doom_ExtractPName(tex, img, imgsize, tx->width, tx->height, tc->xoffset, tc->yoffset);
BZ_Free(img);
} }
*hasalpha = false; *hasalpha = false;
@ -1614,15 +1628,15 @@ static texid_t Doom_LoadPatchFromTexWad(char *name, void *texlump, unsigned shor
return r_nulltex; return r_nulltex;
} }
static int Doom_LoadPatch(char *name) static int Doom_LoadPatch(model_t *mod, char *name)
{ {
texid_t tex;
qboolean hasalpha = false; qboolean hasalpha = false;
int texnum; int texnum;
size_t nlen = strnlen(name, 8);
for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan. for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan.
{ {
if(!strncmp(name, gldoomtextures[texnum].name, 8)) if(!memcmp(name, gldoomtextures[texnum].name, nlen) && !gldoomtextures[texnum].name[nlen])
{ {
return texnum; return texnum;
} }
@ -1634,32 +1648,59 @@ static int Doom_LoadPatch(char *name)
memset(gldoomtextures + numgldoomtextures, 0, sizeof(gldoomtextures[numgldoomtextures])); memset(gldoomtextures + numgldoomtextures, 0, sizeof(gldoomtextures[numgldoomtextures]));
numgldoomtextures++; numgldoomtextures++;
strncpy(gldoomtextures[texnum].name, name, 8); memcpy(gldoomtextures[texnum].name, name, nlen);
gldoomtextures[texnum].name[nlen] = 0;
tex = r_nulltex;
if (textures1 && !TEXVALID(tex))
tex = Doom_LoadPatchFromTexWad(name, textures1, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha);
if (textures2 && !TEXVALID(tex))
tex = Doom_LoadPatchFromTexWad(name, textures2, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha);
if (!TEXVALID(tex))
{
//all else failed.
gldoomtextures[texnum].width = image_width;
gldoomtextures[texnum].height = image_height;
gldoomtextures[texnum].meshptr = &gldoomtextures[texnum].mesh;
gldoomtextures[texnum].batch.mesh = &gldoomtextures[texnum].meshptr;
gldoomtextures[texnum].batch.next = loadmodel->batches[gldoomtextures[texnum].shader->sort];
loadmodel->batches[gldoomtextures[texnum].shader->sort] = &gldoomtextures[texnum].batch;
}
if (hasalpha)
gldoomtextures[texnum].shader = R_RegisterShader(name, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\nalphafunc ge128\n}\n}\n");
else
gldoomtextures[texnum].shader = R_RegisterShader(name, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\n}\n}\n");
gldoomtextures[texnum].shader->defaulttextures.base = tex;
return texnum; return texnum;
} }
static void Doom_LoadShaders(void *ctx, void *data, size_t a, size_t b)
{
model_t *mod = ctx;
texnums_t tn;
qboolean hasalpha = false;
qboolean isflat;
int texnum;
char tmp[MAX_QPATH];
for (texnum = 0; texnum < numgldoomtextures; texnum++) //a hash table might be a good plan.
{
isflat = !strncmp(gldoomtextures[texnum].name, "flats/", 6);
memset(&tn, 0, sizeof(tn));
if (isflat)
{
void *file = FS_LoadMallocFile(va2(tmp, sizeof(tmp), "%s.raw", gldoomtextures[texnum].name), NULL);
if (file)
{
tn.base = Image_GetTexture(gldoomtextures[texnum].name, NULL, 0, file, doompalette, 64, 64, TF_8PAL24);
Z_Free(file);
}
gldoomtextures[texnum].width = 64;
gldoomtextures[texnum].height = 64;
}
else
{
if (textures1 && !TEXVALID(tn.base))
tn.base = Doom_LoadPatchFromTexWad(gldoomtextures[texnum].name, textures1, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha);
if (textures2 && !TEXVALID(tn.base))
tn.base = Doom_LoadPatchFromTexWad(gldoomtextures[texnum].name, textures2, &gldoomtextures[texnum].width, &gldoomtextures[texnum].height, &hasalpha);
}
if (!TEXVALID(tn.base))
{
gldoomtextures[texnum].width = 64;
gldoomtextures[texnum].height = 64;
hasalpha = false;
}
if (hasalpha)
gldoomtextures[texnum].shader = R_RegisterShader(gldoomtextures[texnum].name, SUF_NONE, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\nalphafunc ge128\n}\n}\n");
else
gldoomtextures[texnum].shader = R_RegisterShader(gldoomtextures[texnum].name, SUF_NONE, "{\n{\nmap $diffuse\nrgbgen vertex\nalphagen vertex\n}\n}\n");
R_BuildDefaultTexnums(&tn, gldoomtextures[texnum].shader);
}
};
static void Doom_Purge (struct model_s *mod) static void Doom_Purge (struct model_s *mod)
{ {
int texnum; int texnum;
@ -1674,7 +1715,7 @@ static void Doom_Purge (struct model_s *mod)
gldoomtextures = NULL; gldoomtextures = NULL;
} }
#endif #endif
static void CleanWalls(dsidedef_t *sidedefsl) static void CleanWalls(model_t *mod, dsidedef_t *sidedefsl)
{ {
int i; int i;
char texname[64]; char texname[64];
@ -1697,7 +1738,7 @@ static void CleanWalls(dsidedef_t *sidedefsl)
else else
{ {
strncpy(lastmiddle, texname, 8); strncpy(lastmiddle, texname, 8);
sidedefsm[i].middletex = lastmidtex = Doom_LoadPatch(texname);//Mod_LoadHiResTexture(texname, true, false); sidedefsm[i].middletex = lastmidtex = Doom_LoadPatch(mod, texname);
} }
} }
@ -1712,7 +1753,7 @@ static void CleanWalls(dsidedef_t *sidedefsl)
else else
{ {
strncpy(lastlower, texname, 8); strncpy(lastlower, texname, 8);
sidedefsm[i].lowertex = lastlowtex = Doom_LoadPatch(texname);//Mod_LoadHiResTexture(texname, true, true); sidedefsm[i].lowertex = lastlowtex = Doom_LoadPatch(mod, texname);
} }
} }
@ -1727,7 +1768,7 @@ static void CleanWalls(dsidedef_t *sidedefsl)
else else
{ {
strncpy(lastupper, texname, 8); strncpy(lastupper, texname, 8);
sidedefsm[i].uppertex = lastuptex = Doom_LoadPatch(texname);//Mod_LoadHiResTexture(texname, true, false); sidedefsm[i].uppertex = lastuptex = Doom_LoadPatch(mod, texname);
} }
} }
#endif #endif
@ -1737,14 +1778,16 @@ static void CleanWalls(dsidedef_t *sidedefsl)
} }
} }
void QuakifyThings(dthing_t *thingsl) void QuakifyThings(model_t *mod, dthing_t *thingsl)
{ {
int sector; int sector;
int spawnflags; int spawnflags;
char *name; char *name;
int i; int i;
int zpos; int zpos;
static char newlump[1024*1024]; static char newlump[1024*1024]; //FIXME
char thingname[MAX_QPATH];
char *ptr = newlump; char *ptr = newlump;
vec3_t point; vec3_t point;
@ -1793,7 +1836,7 @@ void QuakifyThings(dthing_t *thingsl)
break; break;
default: default:
name = va("thing_%i", thingsl[i].type); name = va2(thingname, sizeof(thingname), "thing_%i", thingsl[i].type);
break; break;
} }
@ -1815,7 +1858,7 @@ void QuakifyThings(dthing_t *thingsl)
if (thingsl[i].flags & THING_DEAF) if (thingsl[i].flags & THING_DEAF)
spawnflags |= 1; spawnflags |= 1;
sprintf(ptr, "{\n" Q_snprintfz(ptr, newlump+sizeof(newlump)-ptr, "{\n"
"\"classname\" \"%s\"\n" "\"classname\" \"%s\"\n"
"\"origin\" \"%i %i %i\"\n" "\"origin\" \"%i %i %i\"\n"
"\"spawnflags\" \"%i\"\n" "\"spawnflags\" \"%i\"\n"
@ -1829,8 +1872,8 @@ void QuakifyThings(dthing_t *thingsl)
ptr += strlen(ptr); ptr += strlen(ptr);
} }
loadmodel->entities = BZ_Malloc(ptr-newlump+1); mod->entities = BZ_Malloc(ptr-newlump+1);
memcpy(loadmodel->entities, newlump, ptr-newlump+1); memcpy(mod->entities, newlump, ptr-newlump+1);
} }
void Doom_GeneratePlanes(ddoomnode_t *nodel) void Doom_GeneratePlanes(ddoomnode_t *nodel)
@ -1949,11 +1992,13 @@ static void Doom_LoadVerticies(char *name)
int stdc, glc; int stdc, glc;
int *gl2; int *gl2;
int i; int i;
size_t fsize;
char tmp[MAX_QPATH];
std = (void *)COM_LoadTempFile (va("%s.vertexes", name)); std = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.vertexes", name), &fsize);
stdc = com_filesize/sizeof(*std); stdc = fsize/sizeof(*std);
gl2 = (void *)COM_LoadTempMoreFile (va("%s.gl_vert", name)); gl2 = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.gl_vert", name), &fsize);
if (!gl2) if (!gl2)
{ {
glc = 0; glc = 0;
@ -1962,18 +2007,17 @@ static void Doom_LoadVerticies(char *name)
else if (gl2[0] == *(int*)"gNd2") else if (gl2[0] == *(int*)"gNd2")
{ {
gl2++; gl2++;
glc = (com_filesize-4)/sizeof(int)/2; glc = (fsize-4)/sizeof(int)/2;
gl1 = NULL; gl1 = NULL;
} }
else else
{ {
glc = com_filesize/sizeof(*gl1); glc = fsize/sizeof(*gl1);
gl1 = (ddoomvertex_t*)gl2; gl1 = (ddoomvertex_t*)gl2;
} }
if (!stdc) if (stdc)
return; {
vertexesc = stdc + glc; vertexesc = stdc + glc;
vertexesl = BZ_Malloc(vertexesc*sizeof(*vertexesl)); vertexesl = BZ_Malloc(vertexesc*sizeof(*vertexesl));
@ -2001,14 +2045,19 @@ static void Doom_LoadVerticies(char *name)
} }
} }
} }
Z_Free(std);
Z_Free(gl2);
}
static void Doom_LoadSSectors(char *name) static void Doom_LoadSSectors(char *name)
{ {
ssectorsl = (void *)FS_LoadMallocFile (va("%s.gl_ssect", name)); size_t fsize;
char tmp[MAX_QPATH];
ssectorsl = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.gl_ssect", name), &fsize);
if (!ssectorsl) if (!ssectorsl)
ssectorsl = (void *)FS_LoadMallocFile (va("%s.ssectors", name)); ssectorsl = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.ssectors", name), &fsize);
//FIXME: "gNd3" means that it's glbsp version 3. //FIXME: "gNd3" means that it's glbsp version 3.
ssectorsc = com_filesize/sizeof(*ssectorsl); ssectorsc = fsize/sizeof(*ssectorsl);
} }
static void Doom_LoadSSegs(char *name) static void Doom_LoadSSegs(char *name)
@ -2019,12 +2068,14 @@ static void Doom_LoadSSegs(char *name)
dgl_seg1_t *s1; dgl_seg1_t *s1;
dseg_t *s0; dseg_t *s0;
int i; int i;
size_t fsize;
char tmp[MAX_QPATH];
file = (void *)FS_LoadMallocFile (va("%s.gl_segs", name)); file = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.gl_segs", name), &fsize);
if (!file) if (!file)
{ {
s0 = (void *)FS_LoadMallocFile (va("%s.segs", name)); s0 = (void *)FS_LoadMallocFile (va2(tmp, sizeof(tmp), "%s.segs", name), &fsize);
segsc = com_filesize/sizeof(*s0); segsc = fsize/sizeof(*s0);
segsl = BZ_Malloc(segsc * sizeof(*segsl)); segsl = BZ_Malloc(segsc * sizeof(*segsl));
for (i = 0; i < segsc; i++) for (i = 0; i < segsc; i++)
@ -2039,7 +2090,7 @@ static void Doom_LoadSSegs(char *name)
else if (*(int *)file == *(int *)"gNd3") else if (*(int *)file == *(int *)"gNd3")
{ {
s3 = file; s3 = file;
segsc = com_filesize/sizeof(*s3); segsc = fsize/sizeof(*s3);
segsl = s3; segsl = s3;
} }
@ -2048,7 +2099,7 @@ static void Doom_LoadSSegs(char *name)
else else
{ {
s1 = file; s1 = file;
segsc = com_filesize/sizeof(*s1); segsc = fsize/sizeof(*s1);
segsl = BZ_Malloc(segsc * sizeof(*segsl)); segsl = BZ_Malloc(segsc * sizeof(*segsl));
for (i = 0; i < segsc; i++) for (i = 0; i < segsc; i++)
@ -2071,37 +2122,38 @@ static void Doom_LoadSSegs(char *name)
} }
} }
qboolean Mod_LoadDoomLevel(model_t *mod) qboolean QDECL Mod_LoadDoomLevel(model_t *mod, void *buffer, size_t fsize)
{ {
int h; int h;
dsector_t *sectorl; dsector_t *sectorl;
dsidedef_t *sidedefsl; dsidedef_t *sidedefsl;
char name[MAX_QPATH]; char name[MAX_QPATH];
char tmp[MAX_QPATH];
int *gl_nodes; int *gl_nodes;
COM_StripExtension(mod->name, name, sizeof(name)); if (fsize != 4)
if (!COM_LoadTempFile(va("%s", mod->name)))
{ {
Con_Printf("Wad map %s does not exist\n", mod->name); Con_Printf("Wad map %s does actually exist... weird.\n", mod->name);
return false; return false;
} }
gl_nodes = (void *)FS_LoadMallocFile (va("%s.gl_nodes", name)); COM_StripExtension(mod->name, name, sizeof(name));
if (gl_nodes && com_filesize>0)
gl_nodes = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.gl_nodes", name), &fsize);
if (gl_nodes && fsize>0)
{ {
nodel = (void *)gl_nodes; nodel = (void *)gl_nodes;
nodec = com_filesize/sizeof(*nodel); nodec = fsize/sizeof(*nodel);
} }
else else
{ {
gl_nodes=NULL; gl_nodes=NULL;
nodel = (void *)FS_LoadMallocFile (va("%s.nodes", name)); nodel = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.nodes", name), &fsize);
nodec = com_filesize/sizeof(*nodel); nodec = fsize/sizeof(*nodel);
} }
sectorl = (void *)FS_LoadMallocFile (va("%s.sectors", name)); sectorl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sectors", name), &fsize);
sectorc = com_filesize/sizeof(*sectorl); sectorc = fsize/sizeof(*sectorl);
#ifndef SERVERONLY #ifndef SERVERONLY
numgldoomtextures=0; numgldoomtextures=0;
@ -2114,14 +2166,14 @@ qboolean Mod_LoadDoomLevel(model_t *mod)
Doom_LoadSSegs(name); Doom_LoadSSegs(name);
Doom_LoadSSectors(name); Doom_LoadSSectors(name);
thingsl = (void *)FS_LoadMallocFile (va("%s.things", name)); thingsl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.things", name), &fsize);
thingsc = com_filesize/sizeof(*thingsl); thingsc = fsize/sizeof(*thingsl);
linedefsl = (void *)FS_LoadMallocFile (va("%s.linedefs", name)); linedefsl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.linedefs", name), &fsize);
linedefsc = com_filesize/sizeof(*linedefsl); linedefsc = fsize/sizeof(*linedefsl);
sidedefsl = (void *)FS_LoadMallocFile (va("%s.sidedefs", name)); sidedefsl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.sidedefs", name), &fsize);
sidedefsc = com_filesize/sizeof(*sidedefsl); sidedefsc = fsize/sizeof(*sidedefsl);
blockmapl = (void *)FS_LoadMallocFile (va("%s.blockmap", name)); blockmapl = (void *)FS_LoadMallocFile (va2(tmp,sizeof(tmp),"%s.blockmap", name), &fsize);
// blockmaps = com_filesize; // blockmaps = fsize;
#ifndef SERVERONLY #ifndef SERVERONLY
Doom_LoadTextureInfos(); Doom_LoadTextureInfos();
#endif #endif
@ -2151,17 +2203,17 @@ qboolean Mod_LoadDoomLevel(model_t *mod)
Doom_SetModelFunc(mod); Doom_SetModelFunc(mod);
mod->needload = false;
mod->fromgame = fg_doom; mod->fromgame = fg_doom;
mod->type = mod_brush; mod->type = mod_brush;
mod->nodes = (void*)0x1; mod->nodes = (void*)0x1;
CleanWalls(sidedefsl); CleanWalls(mod, sidedefsl);
Triangulate_Sectors(sectorl, !!gl_nodes); Triangulate_Sectors(mod, sectorl, !!gl_nodes);
QuakifyThings(thingsl); QuakifyThings(mod, thingsl);
COM_AddWork(0, Doom_LoadShaders, mod, NULL, 0, 0);
return true; return true;
} }

View file

@ -466,7 +466,7 @@ static edict_t *QDECL Q1QVMPF_EntAlloc(pubprogfuncs_t *pf)
static int QDECL Q1QVMPF_LoadEnts(pubprogfuncs_t *pf, const char *mapstring, float spawnflags) static int QDECL Q1QVMPF_LoadEnts(pubprogfuncs_t *pf, const char *mapstring, float spawnflags)
{ {
q1qvmentstring = mapstring; q1qvmentstring = mapstring;
VM_Call(q1qvm, GAME_LOADENTS); VM_Call(q1qvm, GAME_LOADENTS, 0, 0, 0);
q1qvmentstring = NULL; q1qvmentstring = NULL;
return sv.world.edict_size; return sv.world.edict_size;
} }
@ -1310,6 +1310,7 @@ void Q1QVM_Shutdown(void)
Q_strncpyz(svs.clients[i].namebuf, svs.clients[i].name, sizeof(svs.clients[i].namebuf)); Q_strncpyz(svs.clients[i].namebuf, svs.clients[i].name, sizeof(svs.clients[i].namebuf));
svs.clients[i].name = svs.clients[i].namebuf; svs.clients[i].name = svs.clients[i].namebuf;
} }
VM_Call(q1qvm, GAME_SHUTDOWN, 0, 0, 0);
VM_Destroy(q1qvm); VM_Destroy(q1qvm);
q1qvm = NULL; q1qvm = NULL;
VM_fcloseall(VMFSID_Q1QVM); VM_fcloseall(VMFSID_Q1QVM);
@ -1332,7 +1333,7 @@ void Q1QVM_Event_Touch(world_t *w, wedict_t *s, wedict_t *o)
pr_global_struct->self = EDICT_TO_PROG(w->progs, s); pr_global_struct->self = EDICT_TO_PROG(w->progs, s);
pr_global_struct->other = EDICT_TO_PROG(w->progs, o); pr_global_struct->other = EDICT_TO_PROG(w->progs, o);
pr_global_struct->time = w->physicstime; pr_global_struct->time = w->physicstime;
VM_Call(q1qvm, GAME_EDICT_TOUCH); VM_Call(q1qvm, GAME_EDICT_TOUCH, 0, 0, 0);
pr_global_struct->self = oself; pr_global_struct->self = oself;
pr_global_struct->other = oother; pr_global_struct->other = oother;
@ -1342,7 +1343,7 @@ void Q1QVM_Event_Think(world_t *w, wedict_t *s)
{ {
pr_global_struct->self = EDICT_TO_PROG(w->progs, s); pr_global_struct->self = EDICT_TO_PROG(w->progs, s);
pr_global_struct->other = EDICT_TO_PROG(w->progs, w->edicts); pr_global_struct->other = EDICT_TO_PROG(w->progs, w->edicts);
VM_Call(q1qvm, GAME_EDICT_THINK); VM_Call(q1qvm, GAME_EDICT_THINK, 0, 0, 0);
} }
qboolean Q1QVM_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldwatertype, int newwatertype) qboolean Q1QVM_Event_ContentsTransition(world_t *w, wedict_t *ent, int oldwatertype, int newwatertype)
@ -1424,7 +1425,7 @@ qboolean PR_LoadQ1QVM(void)
q1qvmprogfuncs.stringtable = VM_MemoryBase(q1qvm); q1qvmprogfuncs.stringtable = VM_MemoryBase(q1qvm);
ret = VM_Call(q1qvm, GAME_INIT, (qintptr_t)(sv.time*1000), rand()); ret = VM_Call(q1qvm, GAME_INIT, (qintptr_t)(sv.time*1000), rand(), 0, 0, 0);
if (!ret) if (!ret)
{ {
Q1QVM_Shutdown(); Q1QVM_Shutdown();
@ -1466,9 +1467,6 @@ qboolean PR_LoadQ1QVM(void)
sv.world.edict_size = gd->sizeofent; sv.world.edict_size = gd->sizeofent;
vevars = (qintptr_t)gd->ents; vevars = (qintptr_t)gd->ents;
evars = ((char*)VM_MemoryBase(q1qvm) + vevars); evars = ((char*)VM_MemoryBase(q1qvm) + vevars);
//FIXME: range check this pointer
//FIXME: range check the globals pointer
//WARNING: global is not remapped yet... //WARNING: global is not remapped yet...
//This code is written evilly, but works well enough //This code is written evilly, but works well enough
@ -1527,7 +1525,7 @@ qboolean PR_LoadQ1QVM(void)
pr_global_ptrs->dimension_send = &dimensionsend; pr_global_ptrs->dimension_send = &dimensionsend;
pr_global_ptrs->physics_mode = &physics_mode; pr_global_ptrs->physics_mode = &physics_mode;
dimensionsend = 255; dimensionsend = dimensiondefault = 255;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&gd->global->parm1 + i)); pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&gd->global->parm1 + i));
for (; i < NUM_SPAWN_PARMS; i++) for (; i < NUM_SPAWN_PARMS; i++)
@ -1571,12 +1569,12 @@ void Q1QVM_ClientConnect(client_t *cl)
// call the spawn function // call the spawn function
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict);
VM_Call(q1qvm, GAME_CLIENT_CONNECT, cl->spectator); VM_Call(q1qvm, GAME_CLIENT_CONNECT, cl->spectator, 0, 0, 0);
// actually spawn the player // actually spawn the player
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict);
VM_Call(q1qvm, GAME_PUT_CLIENT_IN_SERVER, cl->spectator); VM_Call(q1qvm, GAME_PUT_CLIENT_IN_SERVER, cl->spectator, 0, 0, 0);
} }
qboolean Q1QVM_GameConsoleCommand(void) qboolean Q1QVM_GameConsoleCommand(void)
@ -1595,7 +1593,7 @@ qboolean Q1QVM_GameConsoleCommand(void)
pr_global_struct->self = 0; pr_global_struct->self = 0;
pr_global_struct->other = 0; pr_global_struct->other = 0;
VM_Call(q1qvm, GAME_CONSOLE_COMMAND); //mod uses Cmd_Argv+co to get args VM_Call(q1qvm, GAME_CONSOLE_COMMAND, 0, 0, 0); //mod uses Cmd_Argv+co to get args
pr_global_struct->self = oldself; pr_global_struct->self = oldself;
pr_global_struct->other = oldother; pr_global_struct->other = oldother;
@ -1610,7 +1608,7 @@ qboolean Q1QVM_ClientSay(edict_t *player, qboolean team)
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, player); pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, player);
washandled = VM_Call(q1qvm, GAME_CLIENT_SAY, team); washandled = VM_Call(q1qvm, GAME_CLIENT_SAY, team, 0, 0, 0);
return washandled; return washandled;
} }
@ -1622,53 +1620,53 @@ qboolean Q1QVM_UserInfoChanged(edict_t *player)
pr_global_struct->time = sv.world.physicstime; pr_global_struct->time = sv.world.physicstime;
pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, player); pr_global_struct->self = Q1QVMPF_EdictToProgs(svprogfuncs, player);
return VM_Call(q1qvm, GAME_CLIENT_USERINFO_CHANGED); return VM_Call(q1qvm, GAME_CLIENT_USERINFO_CHANGED, 0, 0, 0);
} }
void Q1QVM_PlayerPreThink(void) void Q1QVM_PlayerPreThink(void)
{ {
VM_Call(q1qvm, GAME_CLIENT_PRETHINK, host_client->spectator); VM_Call(q1qvm, GAME_CLIENT_PRETHINK, host_client->spectator, 0, 0, 0);
} }
void Q1QVM_RunPlayerThink(void) void Q1QVM_RunPlayerThink(void)
{ {
VM_Call(q1qvm, GAME_EDICT_THINK); VM_Call(q1qvm, GAME_EDICT_THINK, 0, 0, 0);
VM_Call(q1qvm, GAME_CLIENT_THINK, host_client->spectator); VM_Call(q1qvm, GAME_CLIENT_THINK, host_client->spectator, 0, 0, 0);
} }
void Q1QVM_PostThink(void) void Q1QVM_PostThink(void)
{ {
VM_Call(q1qvm, GAME_CLIENT_POSTTHINK, host_client->spectator); VM_Call(q1qvm, GAME_CLIENT_POSTTHINK, host_client->spectator, 0, 0, 0);
} }
void Q1QVM_StartFrame(void) void Q1QVM_StartFrame(void)
{ {
VM_Call(q1qvm, GAME_START_FRAME, (qintptr_t)(sv.time*1000)); VM_Call(q1qvm, GAME_START_FRAME, (qintptr_t)(sv.time*1000), 0, 0, 0);
} }
void Q1QVM_Blocked(void) void Q1QVM_Blocked(void)
{ {
VM_Call(q1qvm, GAME_EDICT_BLOCKED); VM_Call(q1qvm, GAME_EDICT_BLOCKED, 0, 0, 0);
} }
void Q1QVM_SetNewParms(void) void Q1QVM_SetNewParms(void)
{ {
VM_Call(q1qvm, GAME_SETNEWPARMS); VM_Call(q1qvm, GAME_SETNEWPARMS, 0, 0, 0);
} }
void Q1QVM_SetChangeParms(void) void Q1QVM_SetChangeParms(void)
{ {
VM_Call(q1qvm, GAME_SETCHANGEPARMS); VM_Call(q1qvm, GAME_SETCHANGEPARMS, 0, 0, 0);
} }
void Q1QVM_ClientCommand(void) void Q1QVM_ClientCommand(void)
{ {
VM_Call(q1qvm, GAME_CLIENT_COMMAND); VM_Call(q1qvm, GAME_CLIENT_COMMAND, 0, 0, 0);
} }
void Q1QVM_GameCodePausedTic(float pausedduration) void Q1QVM_GameCodePausedTic(float pausedduration)
{ {
VM_Call(q1qvm, GAME_PAUSED_TIC, (qintptr_t)(pausedduration*1000)); VM_Call(q1qvm, GAME_PAUSED_TIC, (qintptr_t)(pausedduration*1000), 0, 0, 0);
} }
void Q1QVM_DropClient(client_t *cl) void Q1QVM_DropClient(client_t *cl)
@ -1677,7 +1675,7 @@ void Q1QVM_DropClient(client_t *cl)
Q_strncpyz(cl->namebuf, cl->name, sizeof(cl->namebuf)); Q_strncpyz(cl->namebuf, cl->name, sizeof(cl->namebuf));
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict);
VM_Call(q1qvm, GAME_CLIENT_DISCONNECT); VM_Call(q1qvm, GAME_CLIENT_DISCONNECT, 0, 0, 0);
cl->name = cl->namebuf; cl->name = cl->namebuf;
} }