made max_clients more dynamic on the server to attempt to reduce bss usage. hopefully this will help the webgl port without resulting in extra crashes.
tweaked shadowmaps. now seems faster than stencil shadows. cubemap orientation should now match other engines. tweaked terrain. rtlights work. added pvs tests for embedded terrain. sections are now saved in chunks instead, which should mean windows doesn't have a panic attack at 16 million files in a single directory. hurrah. first pass at realigning menu options to cope with variable-width fonts. still need to do pure-text items. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4514 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
38305b4f06
commit
fb86222fc7
94 changed files with 4766 additions and 2413 deletions
|
@ -71,28 +71,6 @@ qboolean Cam_DrawViewModel(playerview_t *pv)
|
|||
}
|
||||
}
|
||||
|
||||
// returns true if we should draw this player, we don't if we are chase camming
|
||||
qboolean Cam_DrawEntity(playerview_t *pv, int entitykey)
|
||||
{
|
||||
// if (!entitykey)
|
||||
return true;
|
||||
// if (playernum == cl.playernum[pnum])
|
||||
// return false;
|
||||
if (cl.spectator)
|
||||
{
|
||||
if (pv->cam_auto && pv->cam_locked && (cl_chasecam.value||scr_chatmode==2) &&
|
||||
pv->cam_spec_track+1 == entitykey && r_secondaryview != 2)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selfcam == 1 && !r_refdef.externalview)
|
||||
if (entitykey == pv->viewentity)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int Cam_TrackNum(playerview_t *pv)
|
||||
{
|
||||
if (!pv->cam_auto)
|
||||
|
@ -136,7 +114,7 @@ void Cam_Lock(playerview_t *pv, int playernum)
|
|||
|
||||
Sbar_Changed();
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
CL_NewTranslation(i);
|
||||
}
|
||||
|
||||
|
@ -152,7 +130,7 @@ trace_t Cam_DoTrace(vec3_t vec1, vec3_t vec2)
|
|||
#endif
|
||||
|
||||
VectorCopy (vec1, pmove.origin);
|
||||
return PM_PlayerTrace(pmove.origin, vec2);
|
||||
return PM_PlayerTrace(pmove.origin, vec2, MASK_PLAYERSOLID);
|
||||
}
|
||||
|
||||
extern vec3_t player_mins;
|
||||
|
@ -327,7 +305,7 @@ static void Cam_CheckHighTarget(playerview_t *pv)
|
|||
playerview_t *spv;
|
||||
|
||||
j = -1;
|
||||
for (i = 0, max = -9999; i < MAX_CLIENTS; i++)
|
||||
for (i = 0, max = -9999; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
s = &cl.players[i];
|
||||
if (s->name[0] && !s->spectator && s->frags > max)
|
||||
|
@ -536,7 +514,7 @@ void Cam_TrackCrosshairedPlayer(playerview_t *pv)
|
|||
player = frame->playerstate + pv->playernum;
|
||||
VectorCopy(player->origin, selforg);
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
player = frame->playerstate + i;
|
||||
VectorSubtract(player->origin, selforg, dir);
|
||||
|
|
|
@ -24,8 +24,8 @@ extern int mod_numknown;
|
|||
#define VM_FROMMHANDLE(a) ((a&&((unsigned int)a)<=mod_numknown)?mod_known+a-1:NULL)
|
||||
#define VM_TOMHANDLE(a) (a?a-mod_known+1:0)
|
||||
|
||||
#define VM_FROMSHANDLE(a) (a?r_shaders+a-1:NULL)
|
||||
#define VM_TOSHANDLE(a) (a?a-r_shaders+1:0)
|
||||
#define VM_FROMSHANDLE(a) (a?r_shaders[a-1]:NULL)
|
||||
#define VM_TOSHANDLE(a) (a?a->id+1:0)
|
||||
|
||||
extern model_t box_model;
|
||||
|
||||
|
@ -859,8 +859,15 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
|
|||
{
|
||||
float *org = VM_POINTER(arg[1]);
|
||||
vec3_t *axis = VM_POINTER(arg[2]);
|
||||
int inwater = VM_LONG(arg[3]);
|
||||
|
||||
S_UpdateListener(org, axis[0], axis[1], axis[2]);
|
||||
r_refdef.audio.defaulted = false;
|
||||
//r_refdef.audio.entity = VM_LONG(arg[0]);
|
||||
VectorCopy(org, r_refdef.audio.origin);
|
||||
VectorCopy(axis[0], r_refdef.audio.forward);
|
||||
VectorCopy(axis[1], r_refdef.audio.right);
|
||||
VectorCopy(axis[2], r_refdef.audio.up);
|
||||
r_refdef.audio.inwater = inwater;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -664,8 +664,8 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
|
|||
{
|
||||
news->light[0] = MSG_ReadShort();
|
||||
news->light[1] = MSG_ReadShort();
|
||||
news->light[1] = MSG_ReadShort();
|
||||
news->light[1] = MSG_ReadShort();
|
||||
news->light[2] = MSG_ReadShort();
|
||||
news->light[3] = MSG_ReadShort();
|
||||
news->lightstyle = MSG_ReadByte();
|
||||
news->lightpflags = MSG_ReadByte();
|
||||
}
|
||||
|
@ -1183,12 +1183,7 @@ void DP5_ParseDelta(entity_state_t *s)
|
|||
int num;
|
||||
num = s->number;
|
||||
*s = nullentitystate;
|
||||
s->trans = 255;
|
||||
s->scale = 16;
|
||||
s->number = num;
|
||||
s->colormod[0] = (256)/8;
|
||||
s->colormod[1] = (256)/8;
|
||||
s->colormod[2] = (256)/8;
|
||||
s->solid = ES_SOLID_BSP;
|
||||
// s->active = true;
|
||||
}
|
||||
|
@ -3245,11 +3240,12 @@ void CL_LinkPacketEntities (void)
|
|||
dl = CL_NewDlight(state->number, ent->origin, state->light[3]?state->light[3]:350, 0.1, colour[0], colour[1], colour[2]);
|
||||
dl->corona = (state->lightpflags & PFLAGS_CORONA)?1:0;
|
||||
dl->coronascale = 0.25;
|
||||
dl->style = state->lightstyle;
|
||||
dl->flags &= ~LFLAG_FLASHBLEND;
|
||||
dl->flags |= (state->lightpflags & PFLAGS_NOSHADOW)?LFLAG_NOSHADOWS:0;
|
||||
if (state->skinnum)
|
||||
{
|
||||
VectorCopy(angles, ent->angles);
|
||||
VectorCopy(ent->angles, angles);
|
||||
angles[0]*=-1; //pflags matches alias models.
|
||||
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
|
||||
VectorInverse(dl->axis[1]);
|
||||
|
@ -4207,7 +4203,7 @@ void CL_LinkPlayers (void)
|
|||
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
|
||||
predictplayers = false;
|
||||
|
||||
for (j=0, info=cl.players, state=frame->playerstate ; j < MAX_CLIENTS
|
||||
for (j=0, info=cl.players, state=frame->playerstate ; j < cl.allocated_client_slots
|
||||
; j++, info++, state++)
|
||||
{
|
||||
nametagseen[j] = false;
|
||||
|
@ -4742,7 +4738,7 @@ void CL_SetUpPlayerPrediction(qboolean dopred)
|
|||
frame = &cl.inframes[cl.parsecount&UPDATE_MASK];
|
||||
|
||||
for (j=0, pplayer = predicted_players, state=frame->playerstate;
|
||||
j < MAX_CLIENTS;
|
||||
j < cl.allocated_client_slots;
|
||||
j++, pplayer++, state++)
|
||||
{
|
||||
|
||||
|
@ -4826,7 +4822,7 @@ void CL_SetSolidPlayers (void)
|
|||
if (pmove.numphysent == MAX_PHYSENTS) //too many.
|
||||
return;
|
||||
|
||||
for (j=0, pplayer = predicted_players; j < MAX_CLIENTS; j++, pplayer++)
|
||||
for (j=0, pplayer = predicted_players; j < cl.allocated_client_slots; j++, pplayer++)
|
||||
{
|
||||
if (!pplayer->active)
|
||||
continue; // not present this frame
|
||||
|
|
|
@ -37,7 +37,7 @@ int Player_IdtoSlot (int id)
|
|||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < MAX_CLIENTS; j++)
|
||||
for (j = 0; j < cl.allocated_client_slots; j++)
|
||||
{
|
||||
if (cl.players[j].name[0] && cl.players[j].userid == id)
|
||||
return j;
|
||||
|
@ -49,7 +49,7 @@ int Player_StringtoSlot(char *arg)
|
|||
{
|
||||
int i, slot;
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
if (cl.players[i].name[0] && !strncmp(arg, cl.players[i].name, MAX_SCOREBOARDNAME - 1))
|
||||
return i;
|
||||
|
@ -70,7 +70,7 @@ int Player_NametoSlot(char *name)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
if (cl.players[i].name[0] && !strncmp(cl.players[i].name, name, MAX_SCOREBOARDNAME - 1))
|
||||
return i;
|
||||
|
@ -80,7 +80,7 @@ int Player_NametoSlot(char *name)
|
|||
|
||||
int Player_SlottoId (int slot)
|
||||
{
|
||||
return (slot >= 0 && slot < MAX_CLIENTS && cl.players[slot].name[0]) ? cl.players[slot].userid : -1;
|
||||
return (slot >= 0 && slot < cl.allocated_client_slots && cl.players[slot].name[0]) ? cl.players[slot].userid : -1;
|
||||
}
|
||||
|
||||
char *Player_MyName (void)
|
||||
|
@ -128,7 +128,7 @@ static void Display_Ignorelist(void)
|
|||
|
||||
x = 0;
|
||||
foundone = false;
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
if (cl.players[i].name[0] && cl.players[i].ignored)
|
||||
{
|
||||
|
@ -147,7 +147,7 @@ static void Display_Ignorelist(void)
|
|||
|
||||
x = 0;
|
||||
foundone = false;
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
if (cl.players[i].name[0] && cl.players[i].ignored)
|
||||
{
|
||||
|
@ -410,7 +410,7 @@ static void Ignoreteam_f(void)
|
|||
return;
|
||||
}
|
||||
arg = Cmd_Argv(1);
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
if (cl.players[i].name[0] && !cl.players[i].spectator && !strcmp(arg, cl.players[i].team))
|
||||
{
|
||||
|
@ -476,7 +476,7 @@ static void UnignoreAll_f (void)
|
|||
Con_Printf("%s : no arguments expected\n", Cmd_Argv(0));
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
Ignorelist_Del(i);
|
||||
Con_Printf("User ignore list cleared\n");
|
||||
}
|
||||
|
|
|
@ -300,7 +300,7 @@ void CL_MakeActive(char *gamename)
|
|||
|
||||
SCR_EndLoadingPlaque();
|
||||
|
||||
Mod_Flush(false);
|
||||
Mod_Purge(MP_MAPCHANGED);
|
||||
|
||||
TP_ExecTrigger("f_spawn");
|
||||
}
|
||||
|
@ -3740,6 +3740,12 @@ void Host_DoRunFile(hrf_t *f)
|
|||
return;
|
||||
}
|
||||
|
||||
if (f->flags & HRF_MANIFEST)
|
||||
{
|
||||
Host_DoRunFile(f);
|
||||
return;
|
||||
}
|
||||
|
||||
VFS_SEEK(f->srcfile, 0);
|
||||
|
||||
f->dstfile = FS_OpenVFS(qname, "rb", FS_GAME);
|
||||
|
@ -4042,7 +4048,15 @@ double Host_Frame (double time)
|
|||
|
||||
if (cls.state == ca_onserver && cl.validsequence && cl.worldmodel)
|
||||
{ // first update is the final signon stage
|
||||
CL_MakeActive("QuakeWorld");
|
||||
if (cls.protocol == CP_NETQUAKE)
|
||||
{
|
||||
//nq can send 'frames' without any entities before we're on the server, leading to short periods where the local player's position is not known. this is bad. so be more cautious with nq. this might break csqc.
|
||||
CL_TransitionEntities();
|
||||
if (cl.currentpackentities->num_entities)
|
||||
CL_MakeActive("Quake");
|
||||
}
|
||||
else
|
||||
CL_MakeActive("QuakeWorld");
|
||||
}
|
||||
}
|
||||
CL_AllowIndependantSendCmd(true);
|
||||
|
@ -4070,6 +4084,13 @@ double Host_Frame (double time)
|
|||
if (host_speeds.ival)
|
||||
time1 = Sys_DoubleTime ();
|
||||
|
||||
r_refdef.audio.defaulted = true;
|
||||
VectorClear(r_refdef.audio.origin);
|
||||
VectorSet(r_refdef.audio.forward, 1, 0, 0);
|
||||
VectorSet(r_refdef.audio.right, 0, 1, 0);
|
||||
VectorSet(r_refdef.audio.up, 0, 0, 1);
|
||||
r_refdef.audio.inwater = false;
|
||||
|
||||
if (SCR_UpdateScreen && !vid.isminimized)
|
||||
{
|
||||
extern mleaf_t *r_viewleaf;
|
||||
|
@ -4081,30 +4102,16 @@ double Host_Frame (double time)
|
|||
scr_chatmode = 0;
|
||||
|
||||
SCR_UpdateScreen ();
|
||||
if (cls.state >= ca_active && r_viewleaf)
|
||||
S_SetUnderWater(r_viewleaf->contents <= Q1CONTENTS_WATER);
|
||||
else
|
||||
S_SetUnderWater(false);
|
||||
}
|
||||
|
||||
if (host_speeds.ival)
|
||||
time2 = Sys_DoubleTime ();
|
||||
|
||||
// update audio
|
||||
#ifdef CSQC_DAT
|
||||
if (!CSQC_SettingListener())
|
||||
#endif
|
||||
{
|
||||
if (cls.state == ca_active)
|
||||
{
|
||||
if (cls.protocol != CP_QUAKE3)
|
||||
S_UpdateListener (r_origin, vpn, vright, vup);
|
||||
}
|
||||
else
|
||||
S_UpdateListener (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
|
||||
S_UpdateListener (r_refdef.audio.origin, r_refdef.audio.forward, r_refdef.audio.right, r_refdef.audio.up);
|
||||
S_SetUnderWater(r_refdef.audio.inwater);
|
||||
|
||||
S_Update ();
|
||||
}
|
||||
S_Update ();
|
||||
|
||||
CDAudio_Update();
|
||||
|
||||
|
@ -4278,9 +4285,11 @@ void CL_ExecInitialConfigs(char *resetcommand)
|
|||
int qrc, hrc, def;
|
||||
|
||||
Cbuf_AddText("cl_warncmd 0\n", RESTRICT_LOCAL);
|
||||
Cbuf_AddText("unbindall", RESTRICT_LOCAL);
|
||||
Cbuf_AddText("cvarreset *", RESTRICT_LOCAL);
|
||||
Cbuf_AddText("unbindall\n", RESTRICT_LOCAL);
|
||||
Cbuf_AddText("cvar_purgedefaults\n", RESTRICT_LOCAL); //reset cvar defaults to their engine-specified values. the tail end of 'exec default.cfg' will update non-cheat defaults to mod-specified values.
|
||||
Cbuf_AddText("cvarreset *\n", RESTRICT_LOCAL); //reset all cvars to their current (engine) defaults
|
||||
Cbuf_AddText(resetcommand, RESTRICT_LOCAL);
|
||||
Cbuf_AddText("\n", RESTRICT_LOCAL);
|
||||
|
||||
//who should we imitate?
|
||||
qrc = COM_FDepthFile("quake.rc", true); //q1
|
||||
|
@ -4293,7 +4302,7 @@ void CL_ExecInitialConfigs(char *resetcommand)
|
|||
Cbuf_AddText ("exec hexen.rc\n", RESTRICT_LOCAL);
|
||||
else
|
||||
{ //they didn't give us an rc file!
|
||||
Cbuf_AddText ("bind ~ toggleconsole\n", RESTRICT_LOCAL); //we expect default.cfg to not exist. :(
|
||||
Cbuf_AddText ("bind ~ toggleconsole\n", RESTRICT_LOCAL); //in case default.cfg does not exist. :(
|
||||
Cbuf_AddText ("exec default.cfg\n", RESTRICT_LOCAL);
|
||||
if (COM_FCheckExists ("config.cfg"))
|
||||
Cbuf_AddText ("exec config.cfg\n", RESTRICT_LOCAL);
|
||||
|
@ -4404,6 +4413,7 @@ void Host_Init (quakeparms_t *parms)
|
|||
NET_InitClient ();
|
||||
Netchan_Init ();
|
||||
Renderer_Init();
|
||||
Mod_Init(true);
|
||||
|
||||
// W_LoadWadFile ("gfx.wad");
|
||||
Key_Init ();
|
||||
|
@ -4502,6 +4512,7 @@ void Host_Shutdown(void)
|
|||
CL_FreeDlights();
|
||||
CL_FreeVisEdicts();
|
||||
M_Shutdown();
|
||||
Mod_Shutdown(true);
|
||||
#ifndef CLIENTONLY
|
||||
SV_Shutdown();
|
||||
#else
|
||||
|
|
|
@ -11,29 +11,28 @@
|
|||
|
||||
|
||||
//despite not supporting nq or q2, we still load them. We just filter them. This is to make sure we properly write the listing files.
|
||||
enum {
|
||||
enum mastertype_e
|
||||
{
|
||||
MT_BAD, //this would be an error
|
||||
MT_MASTERHTTPNQ, //an http/ftp based master server with NQ servers
|
||||
MT_MASTERHTTPQW,//an http/ftp based master server with QW servers
|
||||
MT_MASTERHTTPJSON,//quakeone's server listing
|
||||
MT_BCASTQW, //-1status
|
||||
MT_BCASTQ2, //-1status
|
||||
MT_BCASTQ3,
|
||||
MT_BCASTNQ, //see code
|
||||
MT_BCASTDP,
|
||||
MT_SINGLEQW, //-1status
|
||||
MT_SINGLEQ2, //-1status
|
||||
MT_SINGLEQ3,
|
||||
MT_SINGLENQ, //see code.
|
||||
MT_SINGLEDP,
|
||||
MT_MASTERQW, //c\n\0
|
||||
MT_MASTERQ2, //query
|
||||
MT_MASTERQ3,
|
||||
MT_MASTERDP //-1getservers %s 3 empty full\x0A
|
||||
MT_MASTERHTTPJSON,
|
||||
MT_MASTERHTTP,
|
||||
MT_MASTERUDP,
|
||||
MT_BCAST,
|
||||
MT_SINGLE,
|
||||
};
|
||||
enum masterprotocol_e
|
||||
{
|
||||
MP_UNSPECIFIED,
|
||||
MP_QW,
|
||||
MP_Q2,
|
||||
MP_Q3,
|
||||
MP_NQ,
|
||||
MP_DP
|
||||
};
|
||||
|
||||
|
||||
typedef enum{
|
||||
typedef enum
|
||||
{
|
||||
SLKEY_PING,
|
||||
SLKEY_MAP,
|
||||
SLKEY_NAME,
|
||||
|
@ -60,7 +59,8 @@ typedef enum{
|
|||
SLKEY_CUSTOM
|
||||
} hostcachekey_t;
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
SLIST_TEST_CONTAINS,
|
||||
SLIST_TEST_NOTCONTAIN,
|
||||
SLIST_TEST_LESSEQUAL,
|
||||
|
@ -75,12 +75,14 @@ typedef enum {
|
|||
|
||||
|
||||
//contains info about a server in greater detail. Could be too mem intensive.
|
||||
typedef struct serverdetailedinfo_s {
|
||||
typedef struct serverdetailedinfo_s
|
||||
{
|
||||
char info[MAX_SERVERINFO_STRING];
|
||||
|
||||
int numplayers;
|
||||
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
int userid;
|
||||
int frags;
|
||||
float time;
|
||||
|
@ -93,7 +95,8 @@ typedef struct serverdetailedinfo_s {
|
|||
} serverdetailedinfo_t;
|
||||
|
||||
//hold minimum info.
|
||||
typedef struct serverinfo_s {
|
||||
typedef struct serverinfo_s
|
||||
{
|
||||
char name[64]; //hostname.
|
||||
netadr_t adr;
|
||||
|
||||
|
@ -127,18 +130,20 @@ typedef struct serverinfo_s {
|
|||
struct serverinfo_s *next;
|
||||
} serverinfo_t;
|
||||
|
||||
typedef struct master_s{
|
||||
typedef struct master_s
|
||||
{
|
||||
struct master_s *next;
|
||||
netadr_t adr;
|
||||
char *address; //text based address (http servers)
|
||||
struct dl_download *dl;
|
||||
int type;
|
||||
int servertype; //filled in for http servers
|
||||
qbyte mastertype;
|
||||
qbyte protocoltype;
|
||||
int sends; /*needs to resend?*/
|
||||
char name[1];
|
||||
} master_t;
|
||||
|
||||
extern struct selectedserver_s {
|
||||
extern struct selectedserver_s
|
||||
{
|
||||
qboolean inuse;
|
||||
netadr_t adr;
|
||||
|
||||
|
@ -147,7 +152,8 @@ extern struct selectedserver_s {
|
|||
int linenum;
|
||||
} selectedserver;
|
||||
|
||||
typedef struct player_s {
|
||||
typedef struct player_s
|
||||
{
|
||||
char name[16];
|
||||
int frags;
|
||||
int colour;
|
||||
|
@ -167,7 +173,7 @@ void Master_SetupSockets(void);
|
|||
void CL_QueryServers(void);
|
||||
int Master_CheckPollSockets(void);
|
||||
void MasterInfo_Shutdown(void);
|
||||
void MasterInfo_Request(master_t *mast, qboolean evenifwedonthavethefiles);
|
||||
void MasterInfo_Request(master_t *mast);
|
||||
serverinfo_t *Master_InfoForServer (netadr_t *addr);
|
||||
serverinfo_t *Master_InfoForNum (int num);
|
||||
unsigned int Master_TotalCount(void);
|
||||
|
|
|
@ -4422,7 +4422,7 @@ void CL_MuzzleFlash (int destsplit)
|
|||
|
||||
if (s1->number == i)
|
||||
{
|
||||
dl = CL_AllocDlight (-i);
|
||||
dl = CL_AllocDlight (i);
|
||||
VectorCopy (s1->origin, dl->origin);
|
||||
AngleVectors(s1->angles, dl->axis[0], dl->axis[1], dl->axis[2]);
|
||||
break;
|
||||
|
@ -4430,7 +4430,7 @@ void CL_MuzzleFlash (int destsplit)
|
|||
}
|
||||
if (pnum==pack->num_entities)
|
||||
{ //that ent number doesn't exist, go for a player with that number
|
||||
if ((unsigned)(i) <= MAX_CLIENTS && i > 0)
|
||||
if ((unsigned)(i) <= cl.allocated_client_slots && i > 0)
|
||||
{
|
||||
pl = &cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[i-1];
|
||||
|
||||
|
@ -4449,14 +4449,15 @@ void CL_MuzzleFlash (int destsplit)
|
|||
|
||||
dl->radius = 200 + (rand()&31);
|
||||
dl->minlight = 32;
|
||||
dl->die = cl.time + 0.1334;
|
||||
dl->color[0] = 1.0;
|
||||
dl->color[1] = 0.4;
|
||||
dl->color[2] = 0.2;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->color[0] = 1.3;
|
||||
dl->color[1] = 0.9;
|
||||
dl->color[2] = 0.5;
|
||||
|
||||
dl->channelfade[0] = 1.5;
|
||||
dl->channelfade[1] = 0.75;
|
||||
dl->channelfade[2] = 0.375;
|
||||
dl->decay = 500;
|
||||
}
|
||||
|
||||
#ifdef Q2CLIENT
|
||||
|
@ -5075,7 +5076,7 @@ void CL_PrintStandardMessage(char *msg, int printlevel)
|
|||
fullmessage[0] = 0;
|
||||
|
||||
// search for player names in message
|
||||
for (i = 0, p = cl.players; i < MAX_CLIENTS; p++, i++)
|
||||
for (i = 0, p = cl.players; i < cl.allocated_client_slots; p++, i++)
|
||||
{
|
||||
char *v;
|
||||
char *name;
|
||||
|
@ -6162,16 +6163,16 @@ qboolean CLNQ_ParseNQPrints(char *s)
|
|||
return false;
|
||||
*s = 0;
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
if (!strcmp(start, cl.players[i].name))
|
||||
break;
|
||||
}
|
||||
if (i == MAX_CLIENTS)
|
||||
if (i == cl.allocated_client_slots)
|
||||
{
|
||||
|
||||
}
|
||||
if (i != MAX_CLIENTS)
|
||||
if (i != cl.allocated_client_slots)
|
||||
{
|
||||
cl.players[i].ping = atoi(pingstart);
|
||||
}
|
||||
|
@ -6520,7 +6521,7 @@ void CLNQ_ParseServerMessage (void)
|
|||
int a;
|
||||
i = MSG_ReadByte ();
|
||||
a = MSG_ReadByte ();
|
||||
if (i < MAX_CLIENTS)
|
||||
if (i < cl.allocated_client_slots)
|
||||
{
|
||||
cl.players[i].rtopcolor = a&0x0f;
|
||||
cl.players[i].rbottomcolor = (a&0xf0)>>4;
|
||||
|
|
|
@ -614,7 +614,7 @@ void CL_CalcClientTime(void)
|
|||
if (oldst == 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
cl.players[i].entertime += cl.servertime;
|
||||
}
|
||||
|
|
|
@ -285,8 +285,8 @@ extern model_t mod_known[];
|
|||
#define VM_FROMMHANDLE(a) (a?mod_known+a-1:NULL)
|
||||
#define VM_TOMHANDLE(a) (a?a-mod_known+1:0)
|
||||
|
||||
#define VM_FROMSHANDLE(a) (a?r_shaders+a-1:NULL)
|
||||
#define VM_TOSHANDLE(a) (a?a-r_shaders+1:0)
|
||||
#define VM_FROMSHANDLE(a) (a?r_shaders[a-1]:NULL)
|
||||
#define VM_TOSHANDLE(a) (a?a->id+1:0)
|
||||
|
||||
|
||||
struct q3refEntity_s {
|
||||
|
|
|
@ -1160,7 +1160,6 @@ qboolean CSQC_MousePosition(float xabs, float yabs, int devid);
|
|||
qboolean CSQC_Accelerometer(float x, float y, float z);
|
||||
int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation, float pitchmod);
|
||||
void CSQC_ParseEntities(void);
|
||||
qboolean CSQC_SettingListener(void);
|
||||
|
||||
qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state);
|
||||
void CSQC_DeltaStart(float time);
|
||||
|
@ -1188,7 +1187,6 @@ void CL_CalcClientTime(void);
|
|||
// cl_cam.c
|
||||
//
|
||||
qboolean Cam_DrawViewModel(playerview_t *pv);
|
||||
qboolean Cam_DrawEntity(playerview_t *pv, int entitykey);
|
||||
int Cam_TrackNum(playerview_t *pv);
|
||||
void Cam_Unlock(playerview_t *pv);
|
||||
void Cam_Lock(playerview_t *pv, int playernum);
|
||||
|
|
|
@ -510,7 +510,7 @@ static int Stats_ExtractName(char **line)
|
|||
int ml = 0;
|
||||
int l;
|
||||
bm = -1;
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
if (!qm_strcmp(cl.players[i].name, *line))
|
||||
{
|
||||
|
|
|
@ -2173,12 +2173,8 @@ void BoostGamma(qbyte *rgba, int width, int height)
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(GLQUAKE) || defined(D3DQUAKE)
|
||||
|
||||
#ifdef DDS
|
||||
#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
|
||||
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
|
||||
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
|
||||
|
@ -2186,6 +2182,7 @@ void BoostGamma(qbyte *rgba, int width, int height)
|
|||
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
|
||||
#endif
|
||||
|
||||
#ifdef IMAGEFMT_DDS
|
||||
typedef struct {
|
||||
unsigned int dwSize;
|
||||
unsigned int dwFlags;
|
||||
|
@ -2209,7 +2206,7 @@ typedef struct {
|
|||
} ddsheader;
|
||||
|
||||
|
||||
texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize)
|
||||
texid_tf GL_ReadTextureDDS(char *iname, unsigned char *buffer, int filesize)
|
||||
{
|
||||
extern int gl_filter_min;
|
||||
extern int gl_filter_max;
|
||||
|
@ -2223,7 +2220,7 @@ texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize)
|
|||
int divsize, blocksize;
|
||||
|
||||
ddsheader fmtheader;
|
||||
if (*(int*)buffer != *(int*)"DDS ")
|
||||
if (*(int*)buffer != *(int*)"DDS " || qrenderer != QR_OPENGL)
|
||||
return r_nulltex;
|
||||
buffer+=4;
|
||||
|
||||
|
@ -2302,6 +2299,158 @@ texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef IMAGEFMT_BLP
|
||||
texid_tf GL_ReadBLPFile(char *iname, unsigned char *buffer, int filesize)
|
||||
{
|
||||
extern int gl_filter_min;
|
||||
extern int gl_filter_max;
|
||||
|
||||
//FIXME: cba with endian.
|
||||
int miplevel;
|
||||
int w, h, i;
|
||||
struct blp_s
|
||||
{
|
||||
char blp2[4];
|
||||
int type;
|
||||
qbyte encoding;
|
||||
qbyte alphadepth;
|
||||
qbyte alphaencoding;
|
||||
qbyte hasmips;
|
||||
unsigned int xres;
|
||||
unsigned int yres;
|
||||
unsigned int mipoffset[16];
|
||||
unsigned int mipsize[16];
|
||||
unsigned int palette[256];
|
||||
} *blp;
|
||||
unsigned int *tmpmem = NULL;
|
||||
unsigned char *in;
|
||||
unsigned int inlen;
|
||||
texid_tf texnum;
|
||||
|
||||
blp = (void*)buffer;
|
||||
|
||||
if (memcmp(blp->blp2, "BLP2", 4) || blp->type != 1 || qrenderer != QR_OPENGL)
|
||||
return r_nulltex;
|
||||
|
||||
w = blp->xres;
|
||||
h = blp->yres;
|
||||
|
||||
texnum = GL_AllocNewTexture(iname, w, h, 0);
|
||||
GL_MTBind(0, GL_TEXTURE_2D, texnum);
|
||||
|
||||
for (miplevel = 0; ; )
|
||||
{
|
||||
//if we ran out of mips to load, give up.
|
||||
if (miplevel == 16 || !blp->mipoffset[miplevel] || !blp->mipsize[miplevel] || blp->mipoffset[miplevel]+blp->mipsize[miplevel] > filesize)
|
||||
{
|
||||
//if we got at least one mip, cap the mips. might help save some ram? naaah...
|
||||
//if this is the first mip, well, its completely fucked.
|
||||
if (miplevel--)
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, miplevel);
|
||||
break;
|
||||
}
|
||||
in = buffer + blp->mipoffset[miplevel];
|
||||
inlen = blp->mipsize[miplevel];
|
||||
if (blp->encoding == 2)
|
||||
{
|
||||
int type;
|
||||
int blocksize;
|
||||
//dxt compression
|
||||
switch(blp->alphaencoding)
|
||||
{
|
||||
default:
|
||||
case 0: //dxt1
|
||||
if (blp->alphadepth)
|
||||
type = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
else
|
||||
type = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||
blocksize = 8;
|
||||
break;
|
||||
case 1: //dxt2/3
|
||||
type = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
blocksize = 16;
|
||||
break;
|
||||
case 7: //dxt4/5
|
||||
type = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
blocksize = 16;
|
||||
break;
|
||||
}
|
||||
if (inlen != ((w+3)/4) * ((h+3)/4) * blocksize)
|
||||
{
|
||||
Con_Printf("%s: mip level %i does not contain the correct amount of data\n", iname, miplevel);
|
||||
if (miplevel--)
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, miplevel);
|
||||
break;
|
||||
}
|
||||
qglCompressedTexImage2DARB(GL_TEXTURE_2D, miplevel, type, w, h, 0, inlen, in);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inlen != w*h+((w*h*blp->alphadepth+7)>>3))
|
||||
{
|
||||
Con_Printf("%s: mip level %i does not contain the correct amount of data\n", iname, miplevel);
|
||||
if (miplevel--)
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, miplevel);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tmpmem)
|
||||
tmpmem = malloc(4*w*h);
|
||||
|
||||
//8bit palette index
|
||||
for (i = 0; i < w*h; i++)
|
||||
tmpmem[i] = blp->palette[*in++] | 0xff000000;
|
||||
|
||||
switch(blp->alphadepth)
|
||||
{
|
||||
case 0:
|
||||
//BGRX palette, 8bit
|
||||
break;
|
||||
case 1:
|
||||
//BGRX palette, 8bit
|
||||
//1bit trailing alpha
|
||||
for (i = 0; i < w*h; i++)
|
||||
tmpmem[i] = (tmpmem[i] & 0xffffff) | (*in++?0xff000000:0);
|
||||
break;
|
||||
case 4:
|
||||
//BGRX palette, 8bit
|
||||
//4bit trailing alpha
|
||||
for (i = 0; i < w*h; i++)
|
||||
tmpmem[i] = (tmpmem[i] & 0xffffff) | (*in++*0x11000000);
|
||||
break;
|
||||
case 8:
|
||||
//BGRX palette, 8bit
|
||||
//8bit trailing alpha
|
||||
for (i = 0; i < w*h; i++)
|
||||
tmpmem[i] = (tmpmem[i] & 0xffffff) | (*in++<<24);
|
||||
break;
|
||||
}
|
||||
qglTexImage2D(GL_TEXTURE_2D, miplevel, GL_RGBA, w, h, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, tmpmem);
|
||||
}
|
||||
|
||||
miplevel++;
|
||||
if ((w <= 1 && h <= 1) || !blp->hasmips)
|
||||
break;
|
||||
w = (w+1)>>1;
|
||||
h = (h+1)>>1;
|
||||
}
|
||||
if (tmpmem)
|
||||
free(tmpmem);
|
||||
|
||||
if (miplevel>1)
|
||||
{
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
||||
}
|
||||
else
|
||||
{
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
|
||||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
||||
}
|
||||
return texnum;
|
||||
}
|
||||
#endif
|
||||
|
||||
//returns r8g8b8a8
|
||||
qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, qboolean *hasalpha, char *fname)
|
||||
{
|
||||
|
@ -2344,6 +2493,63 @@ qbyte *Read32BitImageFile(qbyte *buf, int len, int *width, int *height, qboolean
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void *R_FlipImage32(void *in, int *inoutwidth, int *inoutheight, qboolean flipx, qboolean flipy, qboolean flipd)
|
||||
{
|
||||
int x, y;
|
||||
unsigned int *in32, *inr, *out32;
|
||||
void *out;
|
||||
int inwidth = *inoutwidth;
|
||||
int inheight = *inoutheight;
|
||||
int rowstride = inwidth;
|
||||
int colstride = 1;
|
||||
|
||||
//simply return if no operation
|
||||
if (!flipx && !flipy && !flipd)
|
||||
return in;
|
||||
|
||||
inr = in;
|
||||
out32 = out = BZ_Malloc(inwidth*inheight*4);
|
||||
|
||||
if (flipy)
|
||||
{
|
||||
inr += inwidth*inheight-inwidth;//start on the bottom row
|
||||
rowstride *= -1; //and we need to move up instead
|
||||
}
|
||||
if (flipx)
|
||||
{
|
||||
colstride *= -1; //move backwards
|
||||
inr += inwidth-1; //start at the end of the row
|
||||
}
|
||||
if (flipd)
|
||||
{
|
||||
//switch the dimensions
|
||||
int tmp = inwidth;
|
||||
inwidth = inheight;
|
||||
inheight = tmp;
|
||||
//make sure the caller gets the new dimensions
|
||||
*inoutwidth = inwidth;
|
||||
*inoutheight = inheight;
|
||||
//switch the strides
|
||||
tmp = colstride;
|
||||
colstride = rowstride;
|
||||
rowstride = tmp;
|
||||
}
|
||||
|
||||
//rows->rows, columns->columns
|
||||
for (y = 0; y < inheight; y++)
|
||||
{
|
||||
in32 = inr; //reset the input after each row, so we have truely independant row+column strides
|
||||
inr += rowstride;
|
||||
for (x = 0; x < inheight; x++)
|
||||
{
|
||||
*out32++ = *in32;
|
||||
in32 += colstride;
|
||||
}
|
||||
}
|
||||
BZ_Free(in);
|
||||
return out;
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
|
@ -2359,7 +2565,10 @@ static struct
|
|||
{".png", 1}, //pngs, fairly common, but slow
|
||||
#endif
|
||||
{".tga", 1}, //fairly fast to load
|
||||
#ifdef DDS
|
||||
#ifdef IMAGEFMT_BLP
|
||||
{".blp", 1}, //blizzard picture, for the luls
|
||||
#endif
|
||||
#ifdef IMAGEFMT_DDS
|
||||
{".dds", 1}, //compressed or something
|
||||
#endif
|
||||
{"", 1} //someone forgot an extension
|
||||
|
@ -2433,11 +2642,32 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
|
|||
if ((flags & IF_TEXTYPE) == IF_CUBEMAP)
|
||||
{
|
||||
int j;
|
||||
char *suf[] =
|
||||
static struct
|
||||
{
|
||||
"rt", "lf", "ft", "bk", "up", "dn", //FIXME: This is inverted and thus wrong
|
||||
"px", "nx", "py", "ny", "pz", "nz",
|
||||
"posx", "negx", "posy", "negy", "posz", "negz"
|
||||
char *suffix;
|
||||
qboolean flipx, flipy, flipd;
|
||||
} cmscheme[] =
|
||||
{
|
||||
{"rt", true, false, true},
|
||||
{"lf", false, true, true},
|
||||
{"ft", true, true, false},
|
||||
{"bk", false, false, false},
|
||||
{"up", true, false, true},
|
||||
{"dn", true, false, true},
|
||||
|
||||
{"px", false, false, false},
|
||||
{"nx", false, false, false},
|
||||
{"py", false, false, false},
|
||||
{"ny", false, false, false},
|
||||
{"pz", false, false, false},
|
||||
{"nz", false, false, false},
|
||||
|
||||
{"posx", false, false, false},
|
||||
{"negx", false, false, false},
|
||||
{"posy", false, false, false},
|
||||
{"negy", false, false, false},
|
||||
{"posz", false, false, false},
|
||||
{"negz", false, false, false}
|
||||
};
|
||||
flags |= IF_REPLACE;
|
||||
|
||||
|
@ -2451,9 +2681,9 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
|
|||
continue;
|
||||
|
||||
buf = NULL;
|
||||
for (j = 0; j < sizeof(suf)/sizeof(suf[0])/6; j++)
|
||||
for (j = 0; j < sizeof(cmscheme)/sizeof(cmscheme[0])/6; j++)
|
||||
{
|
||||
snprintf(fname, sizeof(fname)-1, "%s%s%s", nicename, suf[i + 6*j], tex_extensions[e].name);
|
||||
snprintf(fname, sizeof(fname)-1, "%s%s%s", nicename, cmscheme[i + 6*j].suffix, tex_extensions[e].name);
|
||||
buf = COM_LoadFile (fname, 5);
|
||||
if (buf)
|
||||
break;
|
||||
|
@ -2467,6 +2697,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
|
|||
extern cvar_t vid_hardwaregamma;
|
||||
if (!(flags&IF_NOGAMMA) && !vid_hardwaregamma.value)
|
||||
BoostGamma(data, image_width, image_height);
|
||||
data = R_FlipImage32(data, &image_width, &image_height, cmscheme[i + 6*j].flipx, cmscheme[i + 6*j].flipy, cmscheme[i + 6*j].flipd);
|
||||
tex = R_LoadTexture32 (name, image_width, image_height, data, (flags | IF_REPLACE) + (i << IF_TEXTYPESHIFT));
|
||||
|
||||
BZ_Free(data);
|
||||
|
@ -2496,11 +2727,11 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
|
|||
return tex;
|
||||
}
|
||||
|
||||
#ifdef DDS
|
||||
#ifdef IMAGEFMT_DDS
|
||||
snprintf(fname, sizeof(fname)-1, "dds/%s.dds", nicename); /*should be safe if its null*/
|
||||
if ((buf = COM_LoadFile (fname, 5)))
|
||||
{
|
||||
tex = GL_LoadTextureDDS(name, buf, com_filesize);
|
||||
tex = GL_ReadTextureDDS(name, buf, com_filesize);
|
||||
if (TEXVALID(tex))
|
||||
{
|
||||
BZ_Free(buf);
|
||||
|
@ -2510,7 +2741,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (strchr(name, '/')) //never look in a root dir for the pic
|
||||
if (strchr(name, '/') || strchr(name, '\\')) //never look in a root dir for the pic
|
||||
i = 0;
|
||||
else
|
||||
i = 1;
|
||||
|
@ -2540,14 +2771,26 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags)
|
|||
TRACE(("dbg: Mod_LoadHiResTexture: trying %s\n", fname));
|
||||
if ((buf = COM_LoadFile (fname, 5)))
|
||||
{
|
||||
#ifdef DDS
|
||||
tex = GL_LoadTextureDDS(name, buf, com_filesize);
|
||||
#ifdef IMAGEFMT_DDS
|
||||
tex = GL_ReadTextureDDS(name, buf, com_filesize);
|
||||
if (TEXVALID(tex))
|
||||
{
|
||||
BZ_Free(buf);
|
||||
return tex;
|
||||
}
|
||||
#endif
|
||||
#ifdef IMAGEFMT_BLP
|
||||
if (buf[0] == 'B' && buf[1] == 'L' && buf[2] == 'P' && buf[3] == '2')
|
||||
{
|
||||
tex = GL_ReadBLPFile(name, buf, com_filesize);
|
||||
if (TEXVALID(tex))
|
||||
{
|
||||
BZ_Free(buf);
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
hasalpha = false;
|
||||
if ((data = Read32BitImageFile(buf, com_filesize, &image_width, &image_height, &hasalpha, fname)))
|
||||
{
|
||||
|
|
|
@ -473,11 +473,8 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
|
|||
|
||||
if (option->slider.text)
|
||||
{
|
||||
if (!menu->cursoritem && menu->selecteditem == option)
|
||||
Draw_AltFunString(x, y, option->slider.text);
|
||||
else
|
||||
Draw_FunString(x, y, option->slider.text);
|
||||
x += strlen(option->slider.text)*8+28;
|
||||
Draw_FunStringWidth(x, y, option->slider.text, option->slider.textwidth, true, !menu->cursoritem && menu->selecteditem == option);
|
||||
x += option->slider.textwidth + 3*8;
|
||||
}
|
||||
|
||||
if (range < 0)
|
||||
|
@ -522,11 +519,8 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
|
|||
|
||||
if (option->check.text)
|
||||
{
|
||||
if (!menu->cursoritem && menu->selecteditem == option)
|
||||
Draw_AltFunString(x, y, option->check.text);
|
||||
else
|
||||
Draw_FunString(x, y, option->check.text);
|
||||
x += strlen(option->check.text)*8+28;
|
||||
Draw_FunStringWidth(x, y, option->check.text, option->check.textwidth, true, !menu->cursoritem && menu->selecteditem == option);
|
||||
x += option->check.textwidth + 3*8;
|
||||
}
|
||||
#if 0
|
||||
if (on)
|
||||
|
@ -545,12 +539,8 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
|
|||
int x = xpos+option->common.posx;
|
||||
int y = ypos+option->common.posy;
|
||||
|
||||
//Fixme: variable width fonts
|
||||
if (!menu->cursoritem && menu->selecteditem == option)
|
||||
Draw_AltFunString(x, y, option->edit.caption);
|
||||
else
|
||||
Draw_FunString(x, y, option->edit.caption);
|
||||
x+=strlen(option->edit.caption)*8+8;
|
||||
Draw_FunStringWidth(x, y, option->edit.caption, option->edit.captionwidth, true, !menu->cursoritem && menu->selecteditem == option);
|
||||
x += option->edit.captionwidth + 3*8;
|
||||
if (option->edit.slim)
|
||||
x += 8; // more space for cursor
|
||||
else
|
||||
|
@ -571,11 +561,9 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
|
|||
int keys[2];
|
||||
char *keyname;
|
||||
|
||||
if (!menu->cursoritem && menu->selecteditem == option)
|
||||
Draw_AltFunString(x, y, option->bind.caption);
|
||||
else
|
||||
Draw_FunString(x, y, option->bind.caption);
|
||||
x += strlen(option->bind.caption)*8+28;
|
||||
Draw_FunStringWidth(x, y, option->bind.caption, option->bind.captionwidth, true, !menu->cursoritem && menu->selecteditem == option);
|
||||
x += option->bind.captionwidth + 3*8;
|
||||
|
||||
{
|
||||
extern cvar_t cl_forcesplitclient;
|
||||
|
||||
|
@ -609,11 +597,9 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
|
|||
int x = xpos+option->common.posx;
|
||||
int y = ypos+option->common.posy;
|
||||
|
||||
if (!menu->cursoritem && menu->selecteditem == option)
|
||||
Draw_AltFunString(x, y, option->combo.caption);
|
||||
else
|
||||
Draw_FunString(x, y, option->combo.caption);
|
||||
x += strlen(option->combo.caption)*8+24;
|
||||
Draw_FunStringWidth(x, y, option->combo.caption, option->combo.captionwidth, true, !menu->cursoritem && menu->selecteditem == option);
|
||||
x += option->combo.captionwidth + 3*8;
|
||||
|
||||
if (option->combo.numoptions)
|
||||
{
|
||||
if (!menu->cursoritem && menu->selecteditem == option)
|
||||
|
@ -719,18 +705,19 @@ menutext_t *MC_AddRedText(menu_t *menu, int x, int y, const char *text, qboolean
|
|||
return n;
|
||||
}
|
||||
|
||||
menubind_t *MC_AddBind(menu_t *menu, int x, int y, const char *caption, char *command)
|
||||
menubind_t *MC_AddBind(menu_t *menu, int cx, int bx, int y, const char *caption, char *command)
|
||||
{
|
||||
menubind_t *n = Z_Malloc(sizeof(menutext_t) + strlen(caption)+1 + strlen(command)+1);
|
||||
n->common.type = mt_bind;
|
||||
n->common.iszone = true;
|
||||
n->common.posx = x;
|
||||
n->common.posx = cx;
|
||||
n->common.posy = y;
|
||||
n->captionwidth = bx-cx;
|
||||
n->caption = (char *)(n+1);
|
||||
strcpy(n->caption, caption);
|
||||
n->command = n->caption+strlen(n->caption)+1;
|
||||
strcpy(n->command, command);
|
||||
n->common.width = strlen(caption)*8 + 64;
|
||||
n->common.width = n->captionwidth + 64;
|
||||
n->common.height = 8;
|
||||
|
||||
n->common.next = menu->options;
|
||||
|
@ -850,15 +837,20 @@ menupicture_t *MC_AddCursor(menu_t *menu, int x, int y)
|
|||
return n;
|
||||
}
|
||||
|
||||
menuedit_t *MC_AddEdit(menu_t *menu, int x, int y, char *text, char *def)
|
||||
menuedit_t *MC_AddEdit(menu_t *menu, int cx, int ex, int y, char *text, char *def)
|
||||
{
|
||||
menuedit_t *n = Z_Malloc(sizeof(menuedit_t));
|
||||
menuedit_t *n = Z_Malloc(sizeof(menuedit_t)+strlen(text)+1);
|
||||
n->slim = false;
|
||||
n->common.type = mt_edit;
|
||||
n->common.iszone = true;
|
||||
n->common.posx = x;
|
||||
n->common.posx = cx;
|
||||
n->common.posy = y;
|
||||
n->common.width = ex-cx+(17)*8;
|
||||
n->common.height = n->slim?8:16;
|
||||
n->modified = true;
|
||||
n->caption = text;
|
||||
n->captionwidth = ex-cx;
|
||||
n->caption = (char *)(n+1);
|
||||
strcpy((char *)(n+1), text);
|
||||
Q_strncpyz(n->text, def, sizeof(n->text));
|
||||
|
||||
n->common.next = menu->options;
|
||||
|
@ -866,19 +858,21 @@ menuedit_t *MC_AddEdit(menu_t *menu, int x, int y, char *text, char *def)
|
|||
return n;
|
||||
}
|
||||
|
||||
menuedit_t *MC_AddEditCvar_Full(menu_t *menu, int x, int y, char *text, char *name, qboolean isslim)
|
||||
menuedit_t *MC_AddEditCvar(menu_t *menu, int cx, int ex, int y, char *text, char *name, qboolean isslim)
|
||||
{
|
||||
menuedit_t *n = Z_Malloc(sizeof(menuedit_t)+strlen(text)+1);
|
||||
cvar_t *cvar;
|
||||
cvar = Cvar_Get(name, "", CVAR_USERCREATED|CVAR_ARCHIVE, NULL); //well, this is a menu/
|
||||
n->slim = isslim;
|
||||
n->common.type = mt_edit;
|
||||
n->common.iszone = true;
|
||||
n->common.posx = x;
|
||||
n->common.posx = cx;
|
||||
n->common.posy = y;
|
||||
n->common.width = (strlen(text)+17)*8;
|
||||
n->common.height = 8;
|
||||
n->common.width = ex-cx+(17)*8;
|
||||
n->common.height = n->slim?8:16;
|
||||
n->common.tooltip = cvar->description;
|
||||
n->modified = true;
|
||||
n->captionwidth = ex-cx;
|
||||
n->caption = (char *)(n+1);
|
||||
strcpy((char *)(n+1), text);
|
||||
n->cvar = cvar;
|
||||
|
@ -889,21 +883,10 @@ menuedit_t *MC_AddEditCvar_Full(menu_t *menu, int x, int y, char *text, char *na
|
|||
Q_strncpyz(n->text, cvar->string, sizeof(n->text));
|
||||
|
||||
n->common.next = menu->options;
|
||||
n->slim = isslim;
|
||||
menu->options = (menuoption_t *)n;
|
||||
return n;
|
||||
}
|
||||
|
||||
menuedit_t *MC_AddEditCvarSlim(menu_t *menu, int x, int y, char *text, char *name)
|
||||
{
|
||||
return MC_AddEditCvar_Full(menu, x, y, text, name, true);
|
||||
}
|
||||
|
||||
menuedit_t *MC_AddEditCvar(menu_t *menu, int x, int y, char *text, char *name)
|
||||
{
|
||||
return MC_AddEditCvar_Full(menu, x, y, text, name, false);
|
||||
}
|
||||
|
||||
menubox_t *MC_AddBox(menu_t *menu, int x, int y, int width, int height)
|
||||
{
|
||||
menubox_t *n = Z_Malloc(sizeof(menubox_t));
|
||||
|
@ -934,15 +917,16 @@ menucustom_t *MC_AddCustom(menu_t *menu, int x, int y, void *dptr, int dint)
|
|||
return n;
|
||||
}
|
||||
|
||||
menucheck_t *MC_AddCheckBox(menu_t *menu, int x, int y, const char *text, cvar_t *var, int bits)
|
||||
menucheck_t *MC_AddCheckBox(menu_t *menu, int tx, int cx, int y, const char *text, cvar_t *var, int bits)
|
||||
{
|
||||
menucheck_t *n = Z_Malloc(sizeof(menucheck_t)+strlen(text)+1);
|
||||
n->common.type = mt_checkbox;
|
||||
n->common.iszone = true;
|
||||
n->common.posx = x;
|
||||
n->common.posx = tx;
|
||||
n->common.posy = y;
|
||||
n->common.height = 8;
|
||||
n->common.width = (strlen(text)+7)*8;
|
||||
n->textwidth = cx - tx;
|
||||
n->common.width = cx-tx + 7*8;
|
||||
n->common.tooltip = var?var->description:NULL;
|
||||
n->text = (char *)(n+1);
|
||||
strcpy((char *)(n+1), text);
|
||||
|
@ -961,15 +945,16 @@ menucheck_t *MC_AddCheckBox(menu_t *menu, int x, int y, const char *text, cvar_t
|
|||
menu->options = (menuoption_t *)n;
|
||||
return n;
|
||||
}
|
||||
menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int x, int y, const char *text, qboolean (*func) (menucheck_t *option, menu_t *menu, chk_set_t set), int bits)
|
||||
menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int tx, int cx, int y, const char *text, qboolean (*func) (menucheck_t *option, menu_t *menu, chk_set_t set), int bits)
|
||||
{
|
||||
menucheck_t *n = Z_Malloc(sizeof(menucheck_t)+strlen(text)+1);
|
||||
n->common.type = mt_checkbox;
|
||||
n->common.iszone = true;
|
||||
n->common.posx = x;
|
||||
n->common.posx = tx;
|
||||
n->common.posy = y;
|
||||
n->common.height = 8;
|
||||
n->common.width = (strlen(text)+7)*8;
|
||||
n->textwidth = cx - tx;
|
||||
n->common.width = cx-tx + 7*8;
|
||||
n->text = (char *)(n+1);
|
||||
strcpy((char *)(n+1), text);
|
||||
n->func = func;
|
||||
|
@ -981,17 +966,18 @@ menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int x, int y, const char *text, qb
|
|||
}
|
||||
|
||||
//delta may be 0
|
||||
menuslider_t *MC_AddSlider(menu_t *menu, int x, int y, const char *text, cvar_t *var, float min, float max, float delta)
|
||||
menuslider_t *MC_AddSlider(menu_t *menu, int tx, int sx, int y, const char *text, cvar_t *var, float min, float max, float delta)
|
||||
{
|
||||
menuslider_t *n = Z_Malloc(sizeof(menuslider_t)+strlen(text)+1);
|
||||
n->common.type = mt_slider;
|
||||
n->common.iszone = true;
|
||||
n->common.posx = x;
|
||||
n->common.posx = tx;
|
||||
n->common.posy = y;
|
||||
n->common.height = 8;
|
||||
n->common.width = (strlen(text)+SLIDER_RANGE+5)*8;
|
||||
n->common.width = sx-tx + (SLIDER_RANGE+5)*8;
|
||||
n->common.tooltip = var->description;
|
||||
n->var = var;
|
||||
n->textwidth = sx-tx;
|
||||
n->text = (char *)(n+1);
|
||||
strcpy((char *)(n+1), text);
|
||||
|
||||
|
@ -1016,7 +1002,7 @@ menuslider_t *MC_AddSlider(menu_t *menu, int x, int y, const char *text, cvar_t
|
|||
return n;
|
||||
}
|
||||
|
||||
menucombo_t *MC_AddCombo(menu_t *menu, int x, int y, const char *caption, const char **ops, int initialvalue)
|
||||
menucombo_t *MC_AddCombo(menu_t *menu, int tx, int cx, int y, const char *caption, const char **ops, int initialvalue)
|
||||
{
|
||||
int numopts;
|
||||
int optlen;
|
||||
|
@ -1046,10 +1032,11 @@ menucombo_t *MC_AddCombo(menu_t *menu, int x, int y, const char *caption, const
|
|||
optbuf = (char*)(newops + numopts+1);
|
||||
n->common.type = mt_combo;
|
||||
n->common.iszone = true;
|
||||
n->common.posx = x;
|
||||
n->common.posx = tx;
|
||||
n->common.posy = y;
|
||||
n->common.height = 8;
|
||||
n->common.width = strlen(caption)*8 + maxoptlen*8;
|
||||
n->common.width = cx-tx + maxoptlen*8;
|
||||
n->captionwidth = cx-tx;
|
||||
n->caption = caption;
|
||||
n->options = (const char **)newops;
|
||||
|
||||
|
@ -1074,7 +1061,7 @@ menucombo_t *MC_AddCombo(menu_t *menu, int x, int y, const char *caption, const
|
|||
|
||||
return n;
|
||||
}
|
||||
menucombo_t *MC_AddCvarCombo(menu_t *menu, int x, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values)
|
||||
menucombo_t *MC_AddCvarCombo(menu_t *menu, int tx, int cx, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values)
|
||||
{
|
||||
int numopts;
|
||||
int optlen;
|
||||
|
@ -1108,11 +1095,12 @@ menucombo_t *MC_AddCvarCombo(menu_t *menu, int x, int y, const char *caption, cv
|
|||
optbuf = (char*)(newvalues + numopts+1);
|
||||
n->common.type = mt_combo;
|
||||
n->common.iszone = true;
|
||||
n->common.posx = x;
|
||||
n->common.posx = tx;
|
||||
n->common.posy = y;
|
||||
n->common.height = 8;
|
||||
n->common.width = strlen(caption)*8 + maxoptlen*8;
|
||||
n->common.width = cx-tx + maxoptlen*8;
|
||||
n->common.tooltip = cvar->description;
|
||||
n->captionwidth = cx-tx;
|
||||
|
||||
strcpy(optbuf, caption);
|
||||
n->caption = optbuf;
|
||||
|
@ -2148,21 +2136,21 @@ int MC_AddBulk(struct menu_s *menu, menubulk_t *bulk, int xstart, int xtextend,
|
|||
}
|
||||
break;
|
||||
case mt_checkbox:
|
||||
control = (union menuoption_s *)MC_AddCheckBox(menu, x, y, bulk->text, bulk->cvar, bulk->flags);
|
||||
control = (union menuoption_s *)MC_AddCheckBox(menu, xleft, xtextend, y, bulk->text, bulk->cvar, bulk->flags);
|
||||
control->check.func = bulk->func;
|
||||
break;
|
||||
case mt_slider:
|
||||
control = (union menuoption_s *)MC_AddSlider(menu, x, y, bulk->text, bulk->cvar, bulk->min, bulk->max, bulk->delta);
|
||||
control = (union menuoption_s *)MC_AddSlider(menu, xleft, xtextend, y, bulk->text, bulk->cvar, bulk->min, bulk->max, bulk->delta);
|
||||
break;
|
||||
case mt_combo:
|
||||
switch (bulk->variant)
|
||||
{
|
||||
default:
|
||||
case 0: // cvar combo
|
||||
control = (union menuoption_s *)MC_AddCvarCombo(menu, x, y, bulk->text, bulk->cvar, bulk->options, bulk->values);
|
||||
control = (union menuoption_s *)MC_AddCvarCombo(menu, xleft, xtextend, y, bulk->text, bulk->cvar, bulk->options, bulk->values);
|
||||
break;
|
||||
case 1: // combo with return value
|
||||
control = (union menuoption_s *)MC_AddCombo(menu, x, y, bulk->text, bulk->options, bulk->selectedoption);
|
||||
control = (union menuoption_s *)MC_AddCombo(menu, xleft, xtextend, y, bulk->text, bulk->options, bulk->selectedoption);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -2172,11 +2160,11 @@ int MC_AddBulk(struct menu_s *menu, menubulk_t *bulk, int xstart, int xtextend,
|
|||
default:
|
||||
case 0:
|
||||
y += 4;
|
||||
control = (union menuoption_s *)MC_AddEditCvar(menu, x, y, bulk->text, bulk->cvarname);
|
||||
control = (union menuoption_s *)MC_AddEditCvar(menu, xleft, xtextend, y, bulk->text, bulk->cvarname, false);
|
||||
spacing += 4;
|
||||
break;
|
||||
case 1:
|
||||
control = (union menuoption_s *)MC_AddEditCvarSlim(menu, x, y, bulk->text, bulk->cvarname);
|
||||
control = (union menuoption_s *)MC_AddEditCvar(menu, xleft, xtextend, y, bulk->text, bulk->cvarname, true);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -83,7 +83,7 @@ static void SL_DrawColumnTitle (int *x, int y, int xlen, int mx, char *str, qboo
|
|||
R2D_ImageColours((sin(realtime*4.4)*0.25)+0.5, (sin(realtime*4.4)*0.25)+0.5, 0.08, 1.0);
|
||||
R2D_FillBlock(xmin, y, xlen, 8);
|
||||
}
|
||||
Draw_FunStringWidth(xmin, y, str, xlen);
|
||||
Draw_FunStringWidth(xmin, y, str, xlen, false, false);
|
||||
|
||||
if (x != NULL)
|
||||
*x -= xlen + 8;
|
||||
|
@ -232,7 +232,7 @@ static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu)
|
|||
serverhighlight[(int)stype][2],
|
||||
1.0);
|
||||
}
|
||||
else if (thisone == info->scrollpos + (mousecursor_y-16)/8 && mousecursor_x < x)
|
||||
else if (thisone == info->scrollpos + (int)(mousecursor_y-16)/8 && mousecursor_x < x)
|
||||
R2D_ImageColours((sin(realtime*4.4)*0.25)+0.5, (sin(realtime*4.4)*0.25)+0.5, 0.08, 1.0);
|
||||
else if (selectedserver.inuse && NET_CompareAdr(&si->adr, &selectedserver.adr))
|
||||
R2D_ImageColours(((sin(realtime*4.4)*0.25)+0.5) * 0.5, ((sin(realtime*4.4)*0.25)+0.5)*0.5, 0.08*0.5, 1.0);
|
||||
|
@ -246,14 +246,14 @@ static void SL_ServerDraw (int x, int y, menucustom_t *ths, menu_t *menu)
|
|||
}
|
||||
R2D_FillBlock(0, y, ths->common.width, 8);
|
||||
|
||||
if (sb_showtimelimit.value) {Draw_FunStringWidth((x-3*8), y, va("%i", si->tl), 3*8); x-=4*8;}
|
||||
if (sb_showfraglimit.value) {Draw_FunStringWidth((x-3*8), y, va("%i", si->fl), 3*8); x-=4*8;}
|
||||
if (sb_showplayers.value) {Draw_FunStringWidth((x-5*8), y, va("%2i/%2i", si->players, si->maxplayers), 5*8); x-=6*8;}
|
||||
if (sb_showmap.value) {Draw_FunStringWidth((x-8*8), y, si->map, 8*8); x-=9*8;}
|
||||
if (sb_showgamedir.value) {Draw_FunStringWidth((x-8*8), y, si->gamedir, 8*8); x-=9*8;}
|
||||
if (sb_showping.value) {Draw_FunStringWidth((x-3*8), y, va("%i", si->ping), 3*8); x-=4*8;}
|
||||
if (sb_showaddress.value) {Draw_FunStringWidth((x-21*8), y, NET_AdrToString(adr, sizeof(adr), &si->adr), 21*8); x-=22*8;}
|
||||
Draw_FunStringWidth(0, y, si->name, x);
|
||||
if (sb_showtimelimit.value) {Draw_FunStringWidth((x-3*8), y, va("%i", si->tl), 3*8, false, false); x-=4*8;}
|
||||
if (sb_showfraglimit.value) {Draw_FunStringWidth((x-3*8), y, va("%i", si->fl), 3*8, false, false); x-=4*8;}
|
||||
if (sb_showplayers.value) {Draw_FunStringWidth((x-5*8), y, va("%2i/%2i", si->players, si->maxplayers), 5*8, false, false); x-=6*8;}
|
||||
if (sb_showmap.value) {Draw_FunStringWidth((x-8*8), y, si->map, 8*8, false, false); x-=9*8;}
|
||||
if (sb_showgamedir.value) {Draw_FunStringWidth((x-8*8), y, si->gamedir, 8*8, false, false); x-=9*8;}
|
||||
if (sb_showping.value) {Draw_FunStringWidth((x-3*8), y, va("%i", si->ping), 3*8, false, false); x-=4*8;}
|
||||
if (sb_showaddress.value) {Draw_FunStringWidth((x-21*8), y, NET_AdrToString(adr, sizeof(adr), &si->adr), 21*8, false, false); x-=22*8;}
|
||||
Draw_FunStringWidth(0, y, si->name, x, false, false);
|
||||
}
|
||||
}
|
||||
static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key)
|
||||
|
@ -414,9 +414,9 @@ static void SL_ServerPlayer (int x, int y, menucustom_t *ths, menu_t *menu)
|
|||
R2D_FillBlock (x, y, 28, 4);
|
||||
R2D_ImagePaletteColour (Sbar_ColorForMap(selectedserver.detail->players[i].botc), 1.0);
|
||||
R2D_FillBlock (x, y+4, 28, 4);
|
||||
Draw_FunStringWidth (x, y, va("%3i", selectedserver.detail->players[i].frags), 28);
|
||||
Draw_FunStringWidth (x, y, va("%3i", selectedserver.detail->players[i].frags), 28, false, false);
|
||||
|
||||
Draw_FunStringWidth (x+28, y, selectedserver.detail->players[i].name, 12*8);
|
||||
Draw_FunStringWidth (x+28, y, selectedserver.detail->players[i].name, 12*8, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -644,27 +644,27 @@ void M_Menu_ServerList2_f(void)
|
|||
|
||||
strcpy(info->refreshtext, "Refresh");
|
||||
|
||||
MC_AddCheckBox(menu, 0, vid.height - 64+8*1, "Ping ", &sb_showping, 1);
|
||||
MC_AddCheckBox(menu, 0, vid.height - 64+8*2, "Address ", &sb_showaddress, 1);
|
||||
MC_AddCheckBox(menu, 0, vid.height - 64+8*3, "Map ", &sb_showmap, 1);
|
||||
MC_AddCheckBox(menu, 0, vid.height - 64+8*4, "Gamedir ", &sb_showgamedir, 1);
|
||||
MC_AddCheckBox(menu, 0, vid.height - 64+8*5, "Players ", &sb_showplayers, 1);
|
||||
MC_AddCheckBox(menu, 0, vid.height - 64+8*6, "Fraglimit", &sb_showfraglimit, 1);
|
||||
MC_AddCheckBox(menu, 0, vid.height - 64+8*7, "Timelimit", &sb_showtimelimit, 1);
|
||||
MC_AddCheckBox(menu, 0, 72, vid.height - 64+8*1, "Ping ", &sb_showping, 1);
|
||||
MC_AddCheckBox(menu, 0, 72, vid.height - 64+8*2, "Address ", &sb_showaddress, 1);
|
||||
MC_AddCheckBox(menu, 0, 72, vid.height - 64+8*3, "Map ", &sb_showmap, 1);
|
||||
MC_AddCheckBox(menu, 0, 72, vid.height - 64+8*4, "Gamedir ", &sb_showgamedir, 1);
|
||||
MC_AddCheckBox(menu, 0, 72, vid.height - 64+8*5, "Players ", &sb_showplayers, 1);
|
||||
MC_AddCheckBox(menu, 0, 72, vid.height - 64+8*6, "Fraglimit", &sb_showfraglimit, 1);
|
||||
MC_AddCheckBox(menu, 0, 72, vid.height - 64+8*7, "Timelimit", &sb_showtimelimit, 1);
|
||||
|
||||
#ifdef NQPROT
|
||||
MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*1, "List NQ ", SL_ReFilter, 1);
|
||||
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*1, "List NQ ", SL_ReFilter, 1);
|
||||
#endif
|
||||
MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*2, "List QW ", SL_ReFilter, 2);
|
||||
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*2, "List QW ", SL_ReFilter, 2);
|
||||
#ifdef Q2CLIENT
|
||||
MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*3, "List Q2 ", SL_ReFilter, 3);
|
||||
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*3, "List Q2 ", SL_ReFilter, 3);
|
||||
#endif
|
||||
#ifdef Q3CLIENT
|
||||
MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*4, "List Q3 ", SL_ReFilter, 4);
|
||||
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*4, "List Q3 ", SL_ReFilter, 4);
|
||||
#endif
|
||||
MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*5, "Only Favs ", SL_ReFilter, 5);
|
||||
MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*6, "Hide Empty", SL_ReFilter, 6);
|
||||
MC_AddCheckBoxFunc(menu, 128, vid.height - 64+8*7, "Hide Full ", SL_ReFilter, 7);
|
||||
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*5, "Only Favs ", SL_ReFilter, 5);
|
||||
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*6, "Hide Empty", SL_ReFilter, 6);
|
||||
MC_AddCheckBoxFunc(menu, 128, 208, vid.height - 64+8*7, "Hide Full ", SL_ReFilter, 7);
|
||||
|
||||
MC_AddCommand(menu, 64, 0, info->refreshtext, SL_DoRefresh);
|
||||
|
||||
|
|
|
@ -353,8 +353,8 @@ void M_Menu_Setup_f (void)
|
|||
MC_AddPicture(menu, 0, 173, 36, 42, "pics/m_main_logo");
|
||||
|
||||
menu->selecteditem = (menuoption_t*)
|
||||
(info->nameedit = MC_AddEdit(menu, 64, 40, "Your name", name.string));
|
||||
(info->modeledit = MC_AddCvarCombo(menu, 64, 72, "model", &skin, (const char **)modeloptions, (const char **)modeloptions));
|
||||
(info->nameedit = MC_AddEdit(menu, 64, 160, 40, "Your name", name.string));
|
||||
(info->modeledit = MC_AddCvarCombo(menu, 64, 160,72, "model", &skin, (const char **)modeloptions, (const char **)modeloptions));
|
||||
info->modeledit->selectedoption = !strncmp(skin.string, "female", 6);
|
||||
cu = MC_AddCustom(menu, 172-16, 88+16, NULL, 0);
|
||||
cu->draw = MSetupQ2_TransDraw;
|
||||
|
@ -401,8 +401,8 @@ void M_Menu_Setup_f (void)
|
|||
// MC_AddPicture(menu, 72, 32, Draw_CachePic ("gfx/mp_menu.lmp") );
|
||||
|
||||
menu->selecteditem = (menuoption_t*)
|
||||
(info->nameedit = MC_AddEdit(menu, 64, 40, "Your name", name.string));
|
||||
(info->teamedit = MC_AddEdit(menu, 64, 56, "Your team", team.string));
|
||||
(info->nameedit = MC_AddEdit(menu, 64, 160, 40, "Your name", name.string));
|
||||
(info->teamedit = MC_AddEdit(menu, 64, 160, 56, "Your team", team.string));
|
||||
if (mgt == MGT_HEXEN2)
|
||||
{
|
||||
static const char *classnames[] =
|
||||
|
@ -415,10 +415,10 @@ void M_Menu_Setup_f (void)
|
|||
NULL
|
||||
};
|
||||
cvar_t *pc = Cvar_Get("cl_playerclass", "1", CVAR_USERINFO|CVAR_ARCHIVE, "Hexen2");
|
||||
(info->classedit = MC_AddCombo(menu, 64, 72, "Your class", (const char **)classnames, pc->ival-1));
|
||||
(info->classedit = MC_AddCombo(menu, 64, 160, 72, "Your class", (const char **)classnames, pc->ival-1));
|
||||
}
|
||||
else
|
||||
(info->skinedit = MC_AddEdit(menu, 64, 72, "Your skin", skin.string));
|
||||
(info->skinedit = MC_AddEdit(menu, 64, 160, 72, "Your skin", skin.string));
|
||||
|
||||
ci = MC_AddCustom(menu, 172+32, 88, NULL, 0);
|
||||
ci->draw = MSetup_TransDraw;
|
||||
|
@ -600,7 +600,7 @@ void M_Menu_GameOptions_f (void)
|
|||
menu->selecteditem = (menuoption_t*)
|
||||
MC_AddCommand (menu, 64, y, " Start game", MultiBeginGame);y+=16;
|
||||
|
||||
info->hostnameedit = MC_AddEdit (menu, 64, y, " Hostname", name.string);y+=16;
|
||||
info->hostnameedit = MC_AddEdit (menu, 64, 160, y, " Hostname", name.string);y+=16;
|
||||
|
||||
for (players = 0; players < sizeof(numplayeroptions)/ sizeof(numplayeroptions[0]); players++)
|
||||
{
|
||||
|
@ -608,22 +608,22 @@ void M_Menu_GameOptions_f (void)
|
|||
break;
|
||||
}
|
||||
|
||||
info->numplayers = MC_AddCombo (menu, 64, y, "Max players", (const char **)numplayeroptions, players);y+=8;
|
||||
info->numplayers = MC_AddCombo (menu, 64, 160, y, "Max players", (const char **)numplayeroptions, players);y+=8;
|
||||
|
||||
info->deathmatch = MC_AddCombo (menu, 64, y, " Deathmatch", (const char **)deathmatchoptions, deathmatch.value);y+=8;
|
||||
info->teamplay = MC_AddCombo (menu, 64, y, " Teamplay", (const char **)teamplayoptions, teamplay.value);y+=8;
|
||||
info->skill = MC_AddCombo (menu, 64, y, " Skill", (const char **)skilloptions, skill.value);y+=8;
|
||||
info->rundedicated = MC_AddCheckBox(menu, 64, y, " dedicated", NULL, 0);y+=8;
|
||||
info->deathmatch = MC_AddCombo (menu, 64, 160, y, " Deathmatch", (const char **)deathmatchoptions, deathmatch.value);y+=8;
|
||||
info->teamplay = MC_AddCombo (menu, 64, 160, y, " Teamplay", (const char **)teamplayoptions, teamplay.value);y+=8;
|
||||
info->skill = MC_AddCombo (menu, 64, 160, y, " Skill", (const char **)skilloptions, skill.value);y+=8;
|
||||
info->rundedicated = MC_AddCheckBox(menu, 64, 160, y, " dedicated", NULL, 0);y+=8;
|
||||
y+=8;
|
||||
info->timelimit = MC_AddCombo (menu, 64, y, " Time Limit", (const char **)timelimitoptions, timelimit.value/5);y+=8;
|
||||
info->fraglimit = MC_AddCombo (menu, 64, y, " Frag Limit", (const char **)fraglimitoptions, fraglimit.value/10);y+=8;
|
||||
info->timelimit = MC_AddCombo (menu, 64, 160, y, " Time Limit", (const char **)timelimitoptions, timelimit.value/5);y+=8;
|
||||
info->fraglimit = MC_AddCombo (menu, 64, 160, y, " Frag Limit", (const char **)fraglimitoptions, fraglimit.value/10);y+=8;
|
||||
y+=8;
|
||||
MC_AddSlider (menu, 64-7*8, y, "Extra edict support", &pr_maxedicts, 512, 2047, 256);y+=8;
|
||||
MC_AddSlider (menu, 64-7*8, 160, y, "Extra edict support", &pr_maxedicts, 512, 2047, 256);y+=8;
|
||||
y+=8;
|
||||
if (mgt == MGT_QUAKE2)
|
||||
info->mapnameedit = MC_AddEdit (menu, 64, y, " map", "base1");
|
||||
info->mapnameedit = MC_AddEdit (menu, 64, 160, y, " map", "base1");
|
||||
else
|
||||
info->mapnameedit = MC_AddEdit (menu, 64, y, " map", "start");
|
||||
info->mapnameedit = MC_AddEdit (menu, 64, 160, y, " map", "start");
|
||||
y += 16;
|
||||
|
||||
menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 54, 32, NULL, false);
|
||||
|
|
|
@ -290,7 +290,6 @@ struct audiomenuinfo *M_Menu_Audio_Setup(menu_t *menu)
|
|||
return info;
|
||||
}
|
||||
|
||||
menucombo_t *MC_AddCvarCombo(menu_t *menu, int x, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values);
|
||||
void M_Menu_Audio_f (void)
|
||||
{
|
||||
int y;
|
||||
|
@ -544,6 +543,7 @@ const char *presetexec[] =
|
|||
"r_drawflame 0;"
|
||||
"r_waterstyle 0;"
|
||||
"r_lavastyle 0;"
|
||||
"r_coronas 0;"
|
||||
"r_shadow_realtime_dlight 0;"
|
||||
"r_shadow_realtime_world 0;"
|
||||
"r_glsl_offsetmapping 0;"
|
||||
|
@ -567,7 +567,7 @@ const char *presetexec[] =
|
|||
"r_lavastyle 1;"
|
||||
"r_nolightdir 0;"
|
||||
|
||||
, // normal (faithful) options, with content replacement thrown in
|
||||
, // normal (faithful) options, but with content replacement thrown in
|
||||
#ifdef MINIMAL
|
||||
"r_particlesystem classic;"
|
||||
#else
|
||||
|
@ -582,6 +582,7 @@ const char *presetexec[] =
|
|||
"r_replacemodels \"md3 md2\";"
|
||||
"r_waterwarp 1;"
|
||||
"r_drawflame 1;"
|
||||
"r_coronas 1;"
|
||||
|
||||
, // nice options
|
||||
"r_stains 0.75;"
|
||||
|
@ -1382,25 +1383,25 @@ void M_Menu_Singleplayer_Cheats_Quake (void)
|
|||
MC_AddWhiteText(menu, 16, y, " €<><E282AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>‚ ", false); y+=8;
|
||||
y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
info->skillcombo = MC_AddCombo(menu,16, y, " Difficulty", skilloptions, currentskill); y+=8;
|
||||
info->mapcombo = MC_AddCombo(menu,16, y, " Map", mapoptions_q1, currentmap); y+=8;
|
||||
MC_AddCheckBox(menu, 16, y, " Cheats", &sv_cheats,0); y+=8;
|
||||
info->skillcombo = MC_AddCombo(menu,16,170, y, "Difficulty", skilloptions, currentskill); y+=8;
|
||||
info->mapcombo = MC_AddCombo(menu,16,170, y, "Map", mapoptions_q1, currentmap); y+=8;
|
||||
MC_AddCheckBox(menu, 16, 170, y, "Cheats", &sv_cheats,0); y+=8;
|
||||
#endif
|
||||
#ifdef TEXTEDITOR
|
||||
MC_AddCheckBox(menu, 16, y, " Debugger", &debugger, 0); y+=8;
|
||||
MC_AddCheckBox(menu, 16, 170, y, "Debugger", &debugger, 0); y+=8;
|
||||
#endif
|
||||
MC_AddConsoleCommand(menu, 16, y, " Toggle Godmode", "god\n"); y+=8;
|
||||
MC_AddConsoleCommand(menu, 16, y, " Toggle Flymode", "fly\n"); y+=8;
|
||||
MC_AddConsoleCommand(menu, 16, y, " Toggle Noclip", "noclip\n"); y+=8;
|
||||
MC_AddConsoleCommand(menu, 16, y, " Quad Damage", "impulse 255\n"); y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
MC_AddSlider(menu, 16, y, " Gravity", &sv_gravity,0,800,25); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Gravity", &sv_gravity,0,800,25); y+=8;
|
||||
#endif
|
||||
MC_AddSlider(menu, 16, y, " Forward Speed", &cl_forwardspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, y, " Side Speed", &cl_sidespeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, y, " Back Speed", &cl_backspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Forward Speed", &cl_forwardspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Side Speed", &cl_sidespeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Back Speed", &cl_backspeed,0,1000,50); y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
MC_AddSlider(menu, 16, y, " Max Movement Speed", &sv_maxspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Max Movement Speed", &sv_maxspeed,0,1000,50); y+=8;
|
||||
#endif
|
||||
MC_AddConsoleCommand(menu, 16, y, " Silver & Gold Keys", "impulse 13\nimpulse 14\n"); y+=8;
|
||||
MC_AddConsoleCommand(menu, 16, y, "All Weapons & Items", "impulse 9\n"); y+=8;
|
||||
|
@ -1496,20 +1497,20 @@ void M_Menu_Singleplayer_Cheats_Quake2 (void)
|
|||
MC_AddWhiteText(menu, 16, y, " €<><E282AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>‚ ", false); y+=8;
|
||||
y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
info->skillcombo = MC_AddCombo(menu,16, y, " Difficulty", skilloptions, currentskill); y+=8;
|
||||
info->mapcombo = MC_AddCombo(menu,16, y, " Map", mapoptions_q2, currentmap); y+=8;
|
||||
MC_AddCheckBox(menu, 16, y, " Cheats", &sv_cheats,0); y+=8;
|
||||
info->skillcombo = MC_AddCombo(menu,16,170, y, "Difficulty", skilloptions, currentskill); y+=8;
|
||||
info->mapcombo = MC_AddCombo(menu,16,170, y, "Map", mapoptions_q2, currentmap); y+=8;
|
||||
MC_AddCheckBox(menu, 16, 170, y, "Cheats", &sv_cheats,0); y+=8;
|
||||
#endif
|
||||
MC_AddConsoleCommand(menu, 16, y, " Toggle Godmode", "god\n"); y+=8;
|
||||
MC_AddConsoleCommand(menu, 16, y, " Toggle Noclip", "noclip\n"); y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
MC_AddSlider(menu, 16, y, " Gravity", &sv_gravity,0,850,25); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Gravity", &sv_gravity,0,850,25); y+=8;
|
||||
#endif
|
||||
MC_AddSlider(menu, 16, y, " Forward Speed", &cl_forwardspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, y, " Side Speed", &cl_sidespeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, y, " Back Speed", &cl_backspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Forward Speed", &cl_forwardspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Side Speed", &cl_sidespeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Back Speed", &cl_backspeed,0,1000,50); y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
MC_AddSlider(menu, 16, y, " Max Movement Speed", &sv_maxspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Max Movement Speed", &sv_maxspeed,0,1000,50); y+=8;
|
||||
#endif
|
||||
MC_AddConsoleCommand(menu, 16, y, " Unlimited Ammo", "dmflags 8192\n"); y+=8;
|
||||
MC_AddConsoleCommand(menu, 16, y, " Quad Damage", "give quad damage\n"); y+=8;
|
||||
|
@ -1854,23 +1855,23 @@ void M_Menu_Singleplayer_Cheats_Hexen2 (void)
|
|||
MC_AddWhiteText(menu, 16, y, " €<><E282AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>‚ ", false); y+=8;
|
||||
y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
info->skillcombo = MC_AddCombo(menu,16, y, " Difficulty", skilloptions, currentskill); y+=8;
|
||||
info->skillcombo = MC_AddCombo(menu,16,170, y, "Difficulty", skilloptions, currentskill); y+=8;
|
||||
#endif
|
||||
info->mapcombo = MC_AddCombo(menu,16, y, " Map", mapoptions, currentmap); y+=8;
|
||||
info->mapcombo = MC_AddCombo(menu,16,170, y, "Map", mapoptions, currentmap); y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
MC_AddCheckBox(menu, 16, y, " Cheats", &sv_cheats,0); y+=8;
|
||||
MC_AddCheckBox(menu, 16, 170, y, "Cheats", &sv_cheats,0); y+=8;
|
||||
#endif
|
||||
MC_AddConsoleCommand(menu, 16, y, " Toggle Godmode", "god\n"); y+=8;
|
||||
MC_AddConsoleCommand(menu, 16, y, " Toggle Flymode", "fly\n"); y+=8;
|
||||
MC_AddConsoleCommand(menu, 16, y, " Toggle Noclip", "noclip\n"); y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
MC_AddSlider(menu, 16, y, " Gravity", &sv_gravity,0,800,25); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Gravity", &sv_gravity,0,800,25); y+=8;
|
||||
#endif
|
||||
MC_AddSlider(menu, 16, y, " Forward Speed", &cl_forwardspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, y, " Side Speed", &cl_sidespeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, y, " Back Speed", &cl_backspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Forward Speed", &cl_forwardspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Side Speed", &cl_sidespeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Back Speed", &cl_backspeed,0,1000,50); y+=8;
|
||||
#ifndef CLIENTONLY
|
||||
MC_AddSlider(menu, 16, y, " Max Movement Speed", &sv_maxspeed,0,1000,50); y+=8;
|
||||
MC_AddSlider(menu, 16, 170, y, "Max Movement Speed", &sv_maxspeed,0,1000,50); y+=8;
|
||||
#endif
|
||||
MC_AddConsoleCommand(menu, 16, y, " Sheep Transformation", "impulse 14\n"); y+=8;
|
||||
MC_AddConsoleCommand(menu, 16, y, " Change To Paladin (lvl3+)", "impulse 171\n"); y+=8;
|
||||
|
|
|
@ -5,32 +5,66 @@
|
|||
|
||||
int selectitem;
|
||||
menu_t *menu_script;
|
||||
cvar_t menualias = SCVAR("menualias", "");
|
||||
|
||||
void M_Script_Option (menu_t *menu, char *optionvalue)
|
||||
{
|
||||
menuoption_t *mo;
|
||||
|
||||
char buf[8192];
|
||||
//update the option
|
||||
Cbuf_AddText(va("set option %s\n", COM_QuotedString(optionvalue, buf, sizeof(buf))), RESTRICT_LOCAL);
|
||||
|
||||
//expand private arguments
|
||||
for (mo = menu->options, *buf = 0; mo; mo = mo->common.next)
|
||||
{
|
||||
if (mo->common.type == mt_edit)
|
||||
{
|
||||
if (strlen(buf) + strlen(mo->edit.text) + 2 >= sizeof(buf))
|
||||
break;
|
||||
memmove(buf+strlen(mo->edit.text)+1, buf, strlen(buf)+1);
|
||||
memcpy(buf, mo->edit.text, strlen(mo->edit.text));
|
||||
buf[strlen(mo->edit.text)] = ' ';
|
||||
}
|
||||
}
|
||||
Cmd_TokenizeString(buf, false, false);
|
||||
Cmd_ExpandString(menu->data, buf, sizeof(buf), RESTRICT_SERVER, true, true);
|
||||
|
||||
//and execute it as-is
|
||||
Cbuf_AddText(buf, RESTRICT_LOCAL);
|
||||
Cbuf_AddText("\n", RESTRICT_LOCAL);
|
||||
}
|
||||
|
||||
void M_Script_Remove (menu_t *menu)
|
||||
{
|
||||
menu_script = NULL;
|
||||
Cbuf_AddText(va("set option cancel\n%s\n", menualias.string), RESTRICT_LOCAL);
|
||||
Cvar_Set(&menualias, "");
|
||||
if (menu == menu_script)
|
||||
menu_script = NULL;
|
||||
|
||||
M_Script_Option(menu, "cancel");
|
||||
}
|
||||
qboolean M_Script_Key (int key, menu_t *menu)
|
||||
{
|
||||
if (menu->selecteditem && menu->selecteditem->common.type == mt_edit)
|
||||
return false;
|
||||
if (key >= '0' && key <= '9' && *menualias.string)
|
||||
if (key >= '0' && key <= '9' && menu->data)
|
||||
{
|
||||
if (key == '0') //specal case so that "hello" < "0"... (plus matches common impulses)
|
||||
Cbuf_AddText(va("set option %i\n%s\n", 10, menualias.string), RESTRICT_LOCAL);
|
||||
M_Script_Option(menu, "10");
|
||||
else
|
||||
Cbuf_AddText(va("set option %i\n%s\n", key-'0', menualias.string), RESTRICT_LOCAL);
|
||||
M_Script_Option(menu, va("%i", key-'0'));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void M_MenuS_Callback_f (void)
|
||||
{
|
||||
if (menu_script)
|
||||
{
|
||||
M_Script_Option(menu_script, Cmd_Argv(1));
|
||||
}
|
||||
}
|
||||
void M_MenuS_Clear_f (void)
|
||||
{
|
||||
Cvar_Set(&menualias, "");
|
||||
if (menu_script)
|
||||
{
|
||||
M_RemoveMenu(menu_script);
|
||||
|
@ -76,10 +110,12 @@ void M_MenuS_Script_f (void) //create a menu.
|
|||
menu_script->remove = M_Script_Remove;
|
||||
menu_script->key = M_Script_Key;
|
||||
|
||||
if (Cmd_Argc() == 1 || !*alias)
|
||||
Cvar_Set(&menualias, "_");
|
||||
Key_Dest_Remove(kdm_console);
|
||||
|
||||
if (Cmd_Argc() == 1)
|
||||
menu_script->data = Cmd_ParseMultiline(true);
|
||||
else
|
||||
Cvar_Set(&menualias, alias);
|
||||
menu_script->data = Z_StrDup(alias);
|
||||
}
|
||||
|
||||
void M_MenuS_Box_f (void)
|
||||
|
@ -115,7 +151,7 @@ void M_MenuS_CheckBox_f (void)
|
|||
cvar = Cvar_Get(cvarname, text, 0, "User variables");
|
||||
if (!cvar)
|
||||
return;
|
||||
MC_AddCheckBox(menu_script, x, y, text, cvar, bitmask);
|
||||
MC_AddCheckBox(menu_script, x, x+160, y, text, cvar, bitmask);
|
||||
}
|
||||
|
||||
void M_MenuS_Slider_f (void)
|
||||
|
@ -136,7 +172,7 @@ void M_MenuS_Slider_f (void)
|
|||
cvar = Cvar_Get(cvarname, text, 0, "User variables");
|
||||
if (!cvar)
|
||||
return;
|
||||
MC_AddSlider(menu_script, x, y, text, cvar, min, max, 0);
|
||||
MC_AddSlider(menu_script, x, x+160, y, text, cvar, min, max, 0);
|
||||
}
|
||||
|
||||
void M_MenuS_Picture_f (void)
|
||||
|
@ -175,7 +211,22 @@ void M_MenuS_Edit_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
MC_AddEditCvar(menu_script, x, y, text, def);
|
||||
MC_AddEditCvar(menu_script, x, x+160, y, text, def, false);
|
||||
}
|
||||
void M_MenuS_EditPriv_f (void)
|
||||
{
|
||||
int x = atoi(Cmd_Argv(1));
|
||||
int y = atoi(Cmd_Argv(2));
|
||||
char *text = Cmd_Argv(3);
|
||||
char *def = Cmd_Argv(4);
|
||||
|
||||
if (!menu_script)
|
||||
{
|
||||
Con_Printf("%s with no active menu\n", Cmd_Argv(0));
|
||||
return;
|
||||
}
|
||||
|
||||
MC_AddEdit(menu_script, x, x+160, y, text, def);
|
||||
}
|
||||
|
||||
void M_MenuS_Text_f (void)
|
||||
|
@ -195,7 +246,7 @@ void M_MenuS_Text_f (void)
|
|||
MC_AddBufferedText(menu_script, x, y, text, false, false);
|
||||
else
|
||||
{
|
||||
option = (menuoption_t *)MC_AddConsoleCommand(menu_script, x, y, text, va("set option %s\n%s\n", command, menualias.string));
|
||||
option = (menuoption_t *)MC_AddConsoleCommand(menu_script, x, y, text, va("menucallback %s\n", command));
|
||||
if (selectitem-- == 0)
|
||||
menu_script->selecteditem = option;
|
||||
}
|
||||
|
@ -218,7 +269,7 @@ void M_MenuS_TextBig_f (void)
|
|||
MC_AddConsoleCommandQBigFont(menu_script, x, y, text, command);
|
||||
else
|
||||
{
|
||||
option = (menuoption_t *)MC_AddConsoleCommandQBigFont(menu_script, x, y, text, va("set option %s\n%s\n", command, menualias.string));
|
||||
option = (menuoption_t *)MC_AddConsoleCommandQBigFont(menu_script, x, y, text, va("menucallback %s\n", command));
|
||||
if (selectitem-- == 0)
|
||||
menu_script->selecteditem = option;
|
||||
}
|
||||
|
@ -240,7 +291,7 @@ void M_MenuS_Bind_f (void)
|
|||
if (!*caption)
|
||||
caption = command;
|
||||
|
||||
MC_AddBind(menu_script, x, y, command, caption);
|
||||
MC_AddBind(menu_script, x, x+160, y, command, caption);
|
||||
}
|
||||
|
||||
void M_MenuS_Comboi_f (void)
|
||||
|
@ -278,7 +329,7 @@ void M_MenuS_Comboi_f (void)
|
|||
}
|
||||
opts[opt] = NULL;
|
||||
|
||||
MC_AddCvarCombo(menu_script, x, y, caption, var, (const char **)opts, (const char **)values);
|
||||
MC_AddCvarCombo(menu_script, x, x+160, y, caption, var, (const char **)opts, (const char **)values);
|
||||
}
|
||||
|
||||
char *Hunk_TempString(char *s)
|
||||
|
@ -352,7 +403,7 @@ void M_MenuS_Combos_f (void)
|
|||
}
|
||||
opts[opt] = NULL;
|
||||
|
||||
MC_AddCvarCombo(menu_script, x, y, caption, var, (const char **)opts, (const char **)values);
|
||||
MC_AddCvarCombo(menu_script, x, x+160, y, caption, var, (const char **)opts, (const char **)values);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -370,10 +421,12 @@ menutext 0 24 "Cancel"
|
|||
*/
|
||||
void M_Script_Init(void)
|
||||
{
|
||||
Cmd_AddCommand("menuclear", M_MenuS_Clear_f);
|
||||
Cmd_AddCommandD("menuclear", M_MenuS_Clear_f, "Pop the currently scripted menu.");
|
||||
Cmd_AddCommandD("menucallback", M_MenuS_Callback_f, "Explicitly invoke the active script menu's callback function with the given option set.");
|
||||
Cmd_AddCommand("conmenu", M_MenuS_Script_f);
|
||||
Cmd_AddCommand("menubox", M_MenuS_Box_f);
|
||||
Cmd_AddCommand("menuedit", M_MenuS_Edit_f);
|
||||
Cmd_AddCommand("menueditpriv", M_MenuS_EditPriv_f);
|
||||
Cmd_AddCommand("menutext", M_MenuS_Text_f);
|
||||
Cmd_AddCommand("menutextbig", M_MenuS_TextBig_f);
|
||||
Cmd_AddCommand("menupic", M_MenuS_Picture_f);
|
||||
|
@ -382,6 +435,4 @@ void M_Script_Init(void)
|
|||
Cmd_AddCommand("menubind", M_MenuS_Bind_f);
|
||||
Cmd_AddCommand("menucomboi", M_MenuS_Comboi_f);
|
||||
Cmd_AddCommand("menucombos", M_MenuS_Combos_f);
|
||||
|
||||
Cvar_Register(&menualias, "Scripting");
|
||||
}
|
||||
|
|
|
@ -413,13 +413,13 @@ void M_Menu_Keys_f (void)
|
|||
"3",
|
||||
"4"
|
||||
};
|
||||
MC_AddCvarCombo(menu, 16, y, "Force client", &cl_forcesplitclient, (const char **)texts, (const char **)values);
|
||||
MC_AddCvarCombo(menu, 16, 170, y, "Force client", &cl_forcesplitclient, (const char **)texts, (const char **)values);
|
||||
y+=8;
|
||||
}
|
||||
|
||||
while (bindnames->name)
|
||||
{
|
||||
MC_AddBind(menu, 16, y, bindnames->name, bindnames->command);
|
||||
MC_AddBind(menu, 16, 170, y, bindnames->name, bindnames->command);
|
||||
y += 8;
|
||||
|
||||
bindnames++;
|
||||
|
|
|
@ -143,8 +143,8 @@ typedef struct { //must be first of each structure type.
|
|||
menutype_t type;
|
||||
int posx;
|
||||
int posy;
|
||||
int width;
|
||||
int height;
|
||||
int width; //total width
|
||||
int height; //total height
|
||||
int extracollide; // dirty hack to stretch collide box left (the real fix is to have separate collide/render rects)
|
||||
char *tooltip;
|
||||
qboolean noselectionsound:1;
|
||||
|
@ -164,6 +164,7 @@ typedef struct {
|
|||
#define MAX_EDIT_LENGTH 256
|
||||
typedef struct {
|
||||
menucommon_t common;
|
||||
int captionwidth;
|
||||
const char *caption;
|
||||
cvar_t *cvar;
|
||||
char text[MAX_EDIT_LENGTH];
|
||||
|
@ -180,6 +181,7 @@ typedef struct {
|
|||
float largechange;
|
||||
float vx;
|
||||
cvar_t *var;
|
||||
int textwidth;
|
||||
const char *text;
|
||||
} menuslider_t;
|
||||
|
||||
|
@ -187,6 +189,7 @@ typedef enum {CHK_CHECKED, CHK_TOGGLE} chk_set_t;
|
|||
typedef struct menucheck_s {
|
||||
menucommon_t common;
|
||||
const char *text;
|
||||
int textwidth;
|
||||
cvar_t *var;
|
||||
int bits;
|
||||
float value;
|
||||
|
@ -221,6 +224,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
menucommon_t common;
|
||||
|
||||
int captionwidth;
|
||||
const char *caption;
|
||||
const char **options;
|
||||
const char **values;
|
||||
|
@ -231,6 +235,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
menucommon_t common;
|
||||
int captionwidth;
|
||||
char *caption;
|
||||
char *command;
|
||||
} menubind_t;
|
||||
|
@ -288,28 +293,27 @@ typedef struct menu_s {
|
|||
menutext_t *MC_AddBufferedText(menu_t *menu, int x, int y, const char *text, qboolean rightalign, qboolean red);
|
||||
menutext_t *MC_AddRedText(menu_t *menu, int x, int y, const char *text, qboolean rightalign);
|
||||
menutext_t *MC_AddWhiteText(menu_t *menu, int x, int y, const char *text, qboolean rightalign);
|
||||
menubind_t *MC_AddBind(menu_t *menu, int x, int y, const char *caption, char *command);
|
||||
menubind_t *MC_AddBind(menu_t *menu, int cx, int bx, int y, const char *caption, char *command);
|
||||
menubox_t *MC_AddBox(menu_t *menu, int x, int y, int width, int height);
|
||||
menupicture_t *MC_AddPicture(menu_t *menu, int x, int y, int width, int height, char *picname);
|
||||
menupicture_t *MC_AddSelectablePicture(menu_t *menu, int x, int y, char *picname);
|
||||
menupicture_t *MC_AddCenterPicture(menu_t *menu, int y, int height, char *picname);
|
||||
menupicture_t *MC_AddCursor(menu_t *menu, int x, int y);
|
||||
menuslider_t *MC_AddSlider(menu_t *menu, int x, int y, const char *text, cvar_t *var, float min, float max, float delta);
|
||||
menucheck_t *MC_AddCheckBox(menu_t *menu, int x, int y, const char *text, cvar_t *var, int cvarbitmask);
|
||||
menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int x, int y, const char *text, qboolean (*func) (menucheck_t *option, menu_t *menu, chk_set_t set), int bits);
|
||||
menuslider_t *MC_AddSlider(menu_t *menu, int tx, int sx, int y, const char *text, cvar_t *var, float min, float max, float delta);
|
||||
menucheck_t *MC_AddCheckBox(menu_t *menu, int tx, int cx, int y, const char *text, cvar_t *var, int cvarbitmask);
|
||||
menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int tx, int cx, int y, const char *text, qboolean (*func) (menucheck_t *option, menu_t *menu, chk_set_t set), int bits);
|
||||
menubutton_t *MC_AddConsoleCommand(menu_t *menu, int x, int y, const char *text, const char *command);
|
||||
menubutton_t *MC_AddConsoleCommandQBigFont(menu_t *menu, int x, int y, const char *text, const char *command);
|
||||
mpic_t *QBigFontWorks(void);
|
||||
menubutton_t *MC_AddConsoleCommandHexen2BigFont(menu_t *menu, int x, int y, const char *text, const char *command);
|
||||
menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int x, int y, const char *text, char *command, ...);
|
||||
menubutton_t *MC_AddCommand(menu_t *menu, int x, int y, char *text, qboolean (*command) (union menuoption_s *,struct menu_s *,int));
|
||||
menucombo_t *MC_AddCombo(menu_t *menu, int x, int y, const char *caption, const char **text, int initialvalue);
|
||||
menucombo_t *MC_AddCombo(menu_t *menu, int tx, int cx, int y, const char *caption, const char **ops, int initialvalue);
|
||||
menucombo_t *MC_AddCvarCombo(menu_t *menu, int tx, int cx, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values);
|
||||
menubutton_t *MC_AddCommand(menu_t *menu, int x, int y, char *text, qboolean (*command) (union menuoption_s *,struct menu_s *,int));
|
||||
menuedit_t *MC_AddEdit(menu_t *menu, int x, int y, char *text, char *def);
|
||||
menuedit_t *MC_AddEditCvar(menu_t *menu, int x, int y, char *text, char *name);
|
||||
menuedit_t *MC_AddEditCvarSlim(menu_t *menu, int x, int y, char *text, char *name);
|
||||
menuedit_t *MC_AddEdit(menu_t *menu, int cx, int ex, int y, char *text, char *def);
|
||||
menuedit_t *MC_AddEditCvar(menu_t *menu, int cx, int ex, int y, char *text, char *name, qboolean slim);
|
||||
menucustom_t *MC_AddCustom(menu_t *menu, int x, int y, void *dptr, int dint);
|
||||
menucombo_t *MC_AddCvarCombo(menu_t *menu, int x, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values);
|
||||
|
||||
typedef struct menubulk_s {
|
||||
menutype_t type;
|
||||
|
|
|
@ -110,9 +110,16 @@ void R_DrawTextField(int x, int y, int w, int h, char *text, unsigned int defaul
|
|||
|
||||
#endif
|
||||
|
||||
extern void Mod_Init (void);
|
||||
//mod_purge flags
|
||||
enum mod_purge_e
|
||||
{
|
||||
MP_MAPCHANGED, //new map. old stuff no longer needed
|
||||
MP_FLUSH, //user flush command. anything flushable goes.
|
||||
MP_RESET //*everything* is destroyed. renderer is going down.
|
||||
};
|
||||
|
||||
extern void Mod_ClearAll (void);
|
||||
extern void Mod_Flush (qboolean force);
|
||||
extern void Mod_Purge (enum mod_purge_e type);
|
||||
extern struct model_s *Mod_ForName (char *name, qboolean crash);
|
||||
extern struct model_s *Mod_FindName (char *name);
|
||||
extern void *Mod_Extradata (struct model_s *mod); // handles caching
|
||||
|
@ -138,7 +145,7 @@ char *Mod_GetBoneName(struct model_s *model, int bonenum);
|
|||
|
||||
void Draw_FunString(float x, float y, const void *str);
|
||||
void Draw_AltFunString(float x, float y, const void *str);
|
||||
void Draw_FunStringWidth(float x, float y, const void *str, int width);
|
||||
void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean rightalign, qboolean highlight);
|
||||
|
||||
extern int r_regsequence;
|
||||
|
||||
|
|
|
@ -593,7 +593,7 @@ int Master_KeyForName(char *keyname)
|
|||
|
||||
|
||||
|
||||
void Master_AddMaster (char *address, int type, char *description)
|
||||
void Master_AddMaster (char *address, enum mastertype_e mastertype, enum masterprotocol_e protocol, char *description)
|
||||
{
|
||||
netadr_t adr;
|
||||
master_t *mast;
|
||||
|
@ -610,7 +610,7 @@ void Master_AddMaster (char *address, int type, char *description)
|
|||
return;
|
||||
}
|
||||
|
||||
if (type < MT_SINGLEQW) //broadcasts
|
||||
if (mastertype == MT_BCAST) //broadcasts
|
||||
{
|
||||
if (adr.type == NA_IP)
|
||||
adr.type = NA_BROADCAST_IP;
|
||||
|
@ -622,13 +622,14 @@ void Master_AddMaster (char *address, int type, char *description)
|
|||
|
||||
for (mast = master; mast; mast = mast->next)
|
||||
{
|
||||
if (NET_CompareAdr(&mast->adr, &adr) && mast->type == type) //already exists.
|
||||
if (NET_CompareAdr(&mast->adr, &adr) && mast->mastertype == mastertype && mast->protocoltype == protocol) //already exists.
|
||||
return;
|
||||
}
|
||||
mast = Z_Malloc(sizeof(master_t)+strlen(description)+1+strlen(address)+1);
|
||||
mast->adr = adr;
|
||||
mast->address = mast->name + strlen(description)+1;
|
||||
mast->type = type;
|
||||
mast->mastertype = mastertype;
|
||||
mast->protocoltype = protocol;
|
||||
strcpy(mast->name, description);
|
||||
strcpy(mast->address, address);
|
||||
|
||||
|
@ -663,25 +664,32 @@ void MasterInfo_Shutdown(void)
|
|||
Z_Free(visibleservers);
|
||||
}
|
||||
|
||||
void Master_AddMasterHTTP (char *address, int mastertype, char *description)
|
||||
void Master_AddMasterHTTP (char *address, int mastertype, int protocoltype, char *description)
|
||||
{
|
||||
master_t *mast;
|
||||
int servertype;
|
||||
/* int servertype;
|
||||
|
||||
if (mastertype == MT_MASTERHTTPQW)
|
||||
servertype = 0;
|
||||
else
|
||||
if (protocoltype == MP_DP)
|
||||
servertype = SS_DARKPLACES;
|
||||
else if (protocoltype == MP_Q2)
|
||||
servertype = SS_QUAKE2;
|
||||
else if (protocoltype == MP_Q3)
|
||||
servertype = SS_QUAKE3;
|
||||
else if (protocoltype == MP_NQ)
|
||||
servertype = SS_NETQUAKE;
|
||||
|
||||
else
|
||||
servertype = 0;
|
||||
*/
|
||||
for (mast = master; mast; mast = mast->next)
|
||||
{
|
||||
if (!strcmp(mast->address, address) && mast->type == mastertype) //already exists.
|
||||
if (!strcmp(mast->address, address) && mast->mastertype == mastertype && mast->protocoltype == protocoltype) //already exists.
|
||||
return;
|
||||
}
|
||||
mast = Z_Malloc(sizeof(master_t)+strlen(description)+1+strlen(address)+1);
|
||||
mast->address = mast->name + strlen(description)+1;
|
||||
mast->type = mastertype;
|
||||
mast->servertype = servertype;
|
||||
mast->mastertype = mastertype;
|
||||
mast->protocoltype = protocoltype;
|
||||
// mast->servertype = servertype;
|
||||
strcpy(mast->name, description);
|
||||
strcpy(mast->address, address);
|
||||
|
||||
|
@ -690,13 +698,16 @@ void Master_AddMasterHTTP (char *address, int mastertype, char *description)
|
|||
}
|
||||
|
||||
//build a linked list of masters. Doesn't duplicate addresses.
|
||||
qboolean Master_LoadMasterList (char *filename, int defaulttype, int depth)
|
||||
qboolean Master_LoadMasterList (char *filename, qboolean withcomment, int defaulttype, int defaultprotocol, int depth)
|
||||
{
|
||||
vfsfile_t *f;
|
||||
char line[1024];
|
||||
char file[1024];
|
||||
char *name, *next;
|
||||
char name[1024];
|
||||
char entry[1024];
|
||||
char *next, *sep;
|
||||
int servertype;
|
||||
int protocoltype;
|
||||
qboolean favourite;
|
||||
|
||||
if (depth <= 0)
|
||||
return false;
|
||||
|
@ -711,120 +722,126 @@ qboolean Master_LoadMasterList (char *filename, int defaulttype, int depth)
|
|||
if (*line == '#') //comment
|
||||
continue;
|
||||
|
||||
next = COM_Parse(line);
|
||||
*name = 0;
|
||||
favourite = false;
|
||||
servertype = defaulttype;
|
||||
protocoltype = defaultprotocol;
|
||||
|
||||
next = COM_ParseOut(line, entry, sizeof(entry));
|
||||
if (!*com_token)
|
||||
continue;
|
||||
|
||||
if (!strcmp(com_token, "file")) //special case. Add a port if you have a server named 'file'... (unlikly)
|
||||
//special cases. Add a port if you have a server named 'file'... (unlikly)
|
||||
if (!strcmp(entry, "file"))
|
||||
{
|
||||
next = COM_Parse(next);
|
||||
if (withcomment)
|
||||
next = COM_ParseOut(next, name, sizeof(name));
|
||||
next = COM_ParseOut(next, entry, sizeof(entry));
|
||||
if (!next)
|
||||
continue;
|
||||
Q_strncpyz(file, com_token, sizeof(file));
|
||||
servertype = MT_BAD;
|
||||
}
|
||||
else if (!strcmp(entry, "master"))
|
||||
{
|
||||
if (withcomment)
|
||||
next = COM_ParseOut(next, name, sizeof(name));
|
||||
next = COM_ParseOut(next, entry, sizeof(entry));
|
||||
if (!next)
|
||||
continue;
|
||||
servertype = MT_MASTERUDP;
|
||||
}
|
||||
else if (!strcmp(entry, "url"))
|
||||
{
|
||||
if (withcomment)
|
||||
next = COM_ParseOut(next, name, sizeof(name));
|
||||
next = COM_ParseOut(next, entry, sizeof(entry));
|
||||
servertype = MT_MASTERHTTP;
|
||||
}
|
||||
else
|
||||
*file = '\0';
|
||||
|
||||
*next = '\0';
|
||||
next++;
|
||||
name = COM_Parse(next);
|
||||
servertype = -1;
|
||||
next = COM_Parse(next);
|
||||
|
||||
if (!strcmp(com_token, "single:qw"))
|
||||
servertype = MT_SINGLEQW;
|
||||
else if (!strcmp(com_token, "single:q2"))
|
||||
servertype = MT_SINGLEQ2;
|
||||
else if (!strcmp(com_token, "single:q3"))
|
||||
servertype = MT_SINGLEQ3;
|
||||
else if (!strcmp(com_token, "single:dp"))
|
||||
servertype = MT_SINGLEDP;
|
||||
else if (!strcmp(com_token, "single:nq") || !strcmp(com_token, "single:q1"))
|
||||
servertype = MT_SINGLENQ;
|
||||
else if (!strcmp(com_token, "single"))
|
||||
servertype = MT_SINGLEQW;
|
||||
for(sep = com_token; sep; sep = next)
|
||||
{
|
||||
next = strchr(sep, ':');
|
||||
if (next)
|
||||
*next = 0;
|
||||
|
||||
else if (!strcmp(com_token, "master:dp"))
|
||||
servertype = MT_MASTERDP;
|
||||
else if (!strcmp(com_token, "master:qw"))
|
||||
servertype = MT_MASTERQW;
|
||||
else if (!strcmp(com_token, "master:q2"))
|
||||
servertype = MT_MASTERQ2;
|
||||
else if (!strcmp(com_token, "master:q3"))
|
||||
servertype = MT_MASTERQ3;
|
||||
else if (!strcmp(com_token, "master:httpjson"))
|
||||
servertype = MT_MASTERHTTPJSON;
|
||||
else if (!strcmp(com_token, "master:httpnq"))
|
||||
servertype = MT_MASTERHTTPNQ;
|
||||
else if (!strcmp(com_token, "master:httpqw"))
|
||||
servertype = MT_MASTERHTTPQW;
|
||||
else if (!strcmp(com_token, "master")) //any other sort of master, assume it's a qw master.
|
||||
servertype = MT_MASTERQW;
|
||||
if (!strcmp(sep, "single"))
|
||||
servertype = MT_SINGLE;
|
||||
else if (!strcmp(sep, "master"))
|
||||
servertype = MT_MASTERUDP;
|
||||
else if (!strcmp(sep, "masterhttp"))
|
||||
servertype = MT_MASTERHTTP;
|
||||
else if (!strcmp(sep, "masterhttpjson"))
|
||||
servertype = MT_MASTERHTTPJSON;
|
||||
else if (!strcmp(sep, "bcast"))
|
||||
servertype = MT_BCAST;
|
||||
|
||||
else if (!strcmp(com_token, "bcast:qw"))
|
||||
servertype = MT_BCASTQW;
|
||||
else if (!strcmp(com_token, "bcast:q2"))
|
||||
servertype = MT_BCASTQ2;
|
||||
else if (!strcmp(com_token, "bcast:q3"))
|
||||
servertype = MT_BCASTQ3;
|
||||
else if (!strcmp(com_token, "bcast:nq"))
|
||||
servertype = MT_BCASTNQ;
|
||||
else if (!strcmp(com_token, "bcast:dp"))
|
||||
servertype = MT_BCASTDP;
|
||||
else if (!strcmp(com_token, "bcast"))
|
||||
servertype = MT_BCASTQW;
|
||||
else if (!strcmp(com_token, "qw"))
|
||||
protocoltype = MP_QW;
|
||||
else if (!strcmp(com_token, "q2"))
|
||||
protocoltype = MP_Q2;
|
||||
else if (!strcmp(com_token, "q3"))
|
||||
protocoltype = MP_Q3;
|
||||
else if (!strcmp(com_token, "nq"))
|
||||
protocoltype = MP_NQ;
|
||||
else if (!strcmp(com_token, "dp"))
|
||||
protocoltype = MP_DP;
|
||||
|
||||
else if (!strcmp(com_token, "favorite:qw"))
|
||||
servertype = -MT_SINGLEQW;
|
||||
else if (!strcmp(com_token, "favorite:q2"))
|
||||
servertype = -MT_SINGLEQ2;
|
||||
else if (!strcmp(com_token, "favorite:q3"))
|
||||
servertype = -MT_SINGLEQ3;
|
||||
else if (!strcmp(com_token, "favorite:nq"))
|
||||
servertype = -MT_SINGLENQ;
|
||||
else if (!strcmp(com_token, "favorite"))
|
||||
servertype = -MT_SINGLEQW;
|
||||
//legacy compat
|
||||
else if (!strcmp(com_token, "httpjson"))
|
||||
{
|
||||
servertype = MT_MASTERHTTPJSON;
|
||||
protocoltype = MP_NQ;
|
||||
}
|
||||
else if (!strcmp(com_token, "httpnq"))
|
||||
{
|
||||
servertype = MT_MASTERHTTP;
|
||||
protocoltype = MP_NQ;
|
||||
}
|
||||
else if (!strcmp(com_token, "httpqw"))
|
||||
{
|
||||
servertype = MT_MASTERHTTP;
|
||||
protocoltype = MP_QW;
|
||||
}
|
||||
|
||||
else if (!strcmp(com_token, "favourite") || !strcmp(com_token, "favorite"))
|
||||
favourite = true;
|
||||
}
|
||||
|
||||
if (!*name)
|
||||
{
|
||||
sep = name;
|
||||
while(*next == ' ' || *next == '\t')
|
||||
next++;
|
||||
while (*next && sep < name+sizeof(name)-1)
|
||||
*sep++ = *next++;
|
||||
*sep = 0;
|
||||
}
|
||||
|
||||
if (servertype == MT_BAD)
|
||||
Master_LoadMasterList(entry, false, servertype, protocoltype, depth);
|
||||
else
|
||||
{
|
||||
name = next; //go back one token.
|
||||
servertype = defaulttype;
|
||||
}
|
||||
//favourites are added explicitly, with their name and stuff
|
||||
if (favourite && servertype == MT_SINGLE)
|
||||
{
|
||||
if (NET_StringToAdr(entry, 0, &net_from))
|
||||
CL_ReadServerInfo(va("\\hostname\\%s", name), -servertype, true);
|
||||
else
|
||||
Con_Printf("Failed to resolve address - \"%s\"\n", entry);
|
||||
}
|
||||
|
||||
while(*name <= ' ' && *name != 0) //skip whitespace
|
||||
name++;
|
||||
|
||||
next = name + strlen(name)-1;
|
||||
while(*next <= ' ' && next > name)
|
||||
{
|
||||
*next = '\0';
|
||||
next--;
|
||||
}
|
||||
|
||||
|
||||
if (*file)
|
||||
Master_LoadMasterList(file, servertype, depth);
|
||||
else if (servertype < 0)
|
||||
{
|
||||
if (NET_StringToAdr(line, 0, &net_from))
|
||||
CL_ReadServerInfo(va("\\hostname\\%s", name), -servertype, true);
|
||||
else
|
||||
Con_Printf("Failed to resolve address - \"%s\"\n", line);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (servertype)
|
||||
{
|
||||
case MT_MASTERHTTPJSON:
|
||||
case MT_MASTERHTTPNQ:
|
||||
case MT_MASTERHTTPQW:
|
||||
Master_AddMasterHTTP(line, servertype, name);
|
||||
case MT_MASTERHTTP:
|
||||
Master_AddMasterHTTP(entry, servertype, protocoltype, name);
|
||||
break;
|
||||
default:
|
||||
Master_AddMaster(line, servertype, name);
|
||||
Master_AddMaster(entry, servertype, protocoltype, name);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
VFS_CLOSE(f);
|
||||
|
@ -832,7 +849,6 @@ qboolean Master_LoadMasterList (char *filename, int defaulttype, int depth)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void NET_SendPollPacket(int len, void *data, netadr_t to)
|
||||
{
|
||||
int ret;
|
||||
|
@ -959,12 +975,12 @@ int Master_CheckPollSockets(void)
|
|||
#ifdef Q2CLIENT
|
||||
if (!strcmp(s, "print"))
|
||||
{
|
||||
CL_ReadServerInfo(MSG_ReadString(), MT_SINGLEQ2, false);
|
||||
CL_ReadServerInfo(MSG_ReadString(), MP_Q2, false);
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(s, "info")) //parse a bit more...
|
||||
{
|
||||
CL_ReadServerInfo(MSG_ReadString(), MT_SINGLEQ2, false);
|
||||
CL_ReadServerInfo(MSG_ReadString(), MP_Q2, false);
|
||||
continue;
|
||||
}
|
||||
#ifdef IPPROTO_IPV6
|
||||
|
@ -985,7 +1001,7 @@ int Master_CheckPollSockets(void)
|
|||
#ifdef Q3CLIENT
|
||||
if (!strcmp(s, "statusResponse"))
|
||||
{
|
||||
CL_ReadServerInfo(MSG_ReadString(), MT_SINGLEQ3, false);
|
||||
CL_ReadServerInfo(MSG_ReadString(), MP_Q3, false);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
@ -1006,7 +1022,7 @@ int Master_CheckPollSockets(void)
|
|||
}
|
||||
if (!strcmp(s, "infoResponse")) //parse a bit more...
|
||||
{
|
||||
CL_ReadServerInfo(MSG_ReadString(), MT_SINGLEDP, false);
|
||||
CL_ReadServerInfo(MSG_ReadString(), MP_DP, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1025,7 +1041,7 @@ int Master_CheckPollSockets(void)
|
|||
|
||||
if (c == A2C_PRINT) //qw server reply.
|
||||
{
|
||||
CL_ReadServerInfo(MSG_ReadString(), MT_SINGLEQW, false);
|
||||
CL_ReadServerInfo(MSG_ReadString(), MP_QW, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1070,7 +1086,7 @@ int Master_CheckPollSockets(void)
|
|||
// Q_strcat(name, name);
|
||||
}
|
||||
|
||||
CL_ReadServerInfo(va("\\hostname\\%s\\map\\%s\\maxclients\\%i\\clients\\%i", name, map, maxusers, users), MT_SINGLENQ, false);
|
||||
CL_ReadServerInfo(va("\\hostname\\%s\\map\\%s\\maxclients\\%i\\clients\\%i", name, map, maxusers, users), MP_NQ, false);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
|
@ -1136,14 +1152,18 @@ void SListOptionChanged(serverinfo_t *newserver)
|
|||
}
|
||||
|
||||
#ifdef WEBCLIENT
|
||||
void MasterInfo_ProcessHTTP(vfsfile_t *file, int type)
|
||||
void MasterInfo_ProcessHTTP(struct dl_download *dl)
|
||||
{
|
||||
master_t *mast = dl->user_ctx;
|
||||
vfsfile_t *file = dl->file;
|
||||
int protocoltype = mast->protocoltype;
|
||||
netadr_t adr;
|
||||
char *s;
|
||||
char *el;
|
||||
serverinfo_t *info;
|
||||
char adrbuf[MAX_ADR_SIZE];
|
||||
char linebuffer[2048];
|
||||
mast->dl = NULL;
|
||||
|
||||
if (!file)
|
||||
return;
|
||||
|
@ -1173,7 +1193,18 @@ void MasterInfo_ProcessHTTP(vfsfile_t *file, int type)
|
|||
info = Z_Malloc(sizeof(serverinfo_t));
|
||||
info->adr = adr;
|
||||
info->sends = 1;
|
||||
info->special = type;
|
||||
|
||||
if (protocoltype == MP_DP)
|
||||
info->special = SS_DARKPLACES;
|
||||
else if (protocoltype == MP_Q2)
|
||||
info->special = SS_QUAKE2;
|
||||
else if (protocoltype == MP_Q3)
|
||||
info->special = SS_QUAKE3;
|
||||
else if (protocoltype == MP_NQ)
|
||||
info->special = SS_NETQUAKE;
|
||||
else
|
||||
info->special = 0;
|
||||
|
||||
info->refreshtime = 0;
|
||||
info->ping = 0xffff;
|
||||
|
||||
|
@ -1307,25 +1338,10 @@ void MasterInfo_ProcessHTTPJSON(struct dl_download *dl)
|
|||
Con_Printf("Unable to query master at \"%s\"\n", dl->url);
|
||||
}
|
||||
}
|
||||
|
||||
// wrapper functions for the different server types
|
||||
void MasterInfo_ProcessHTTPNQ(struct dl_download *dl)
|
||||
{
|
||||
master_t *mast = dl->user_ctx;
|
||||
mast->dl = NULL;
|
||||
MasterInfo_ProcessHTTP(dl->file, SS_NETQUAKE);
|
||||
}
|
||||
|
||||
void MasterInfo_ProcessHTTPQW(struct dl_download *dl)
|
||||
{
|
||||
master_t *mast = dl->user_ctx;
|
||||
mast->dl = NULL;
|
||||
MasterInfo_ProcessHTTP(dl->file, SS_GENERICQUAKEWORLD);
|
||||
}
|
||||
#endif
|
||||
|
||||
//don't try sending to servers we don't support
|
||||
void MasterInfo_Request(master_t *mast, qboolean evenifwedonthavethefiles)
|
||||
void MasterInfo_Request(master_t *mast)
|
||||
{
|
||||
//static int mastersequence; // warning: unused variable âmastersequenceâ
|
||||
if (!mast)
|
||||
|
@ -1334,68 +1350,9 @@ void MasterInfo_Request(master_t *mast, qboolean evenifwedonthavethefiles)
|
|||
if (mast->sends)
|
||||
mast->sends--;
|
||||
|
||||
switch(mast->type)
|
||||
//these are generic requests
|
||||
switch(mast->mastertype)
|
||||
{
|
||||
#ifdef Q3CLIENT
|
||||
case MT_BCASTQ3:
|
||||
case MT_SINGLEQ3:
|
||||
NET_SendPollPacket (14, va("%c%c%c%cgetstatus\n", 255, 255, 255, 255), mast->adr);
|
||||
break;
|
||||
case MT_MASTERQ3:
|
||||
{
|
||||
char *str;
|
||||
str = va("%c%c%c%cgetservers %u empty full\x0A\n", 255, 255, 255, 255, 68);
|
||||
NET_SendPollPacket (strlen(str), str, mast->adr);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef Q2CLIENT
|
||||
case MT_BCASTQ2:
|
||||
case MT_SINGLEQ2:
|
||||
#endif
|
||||
case MT_SINGLEQW:
|
||||
case MT_BCASTQW:
|
||||
NET_SendPollPacket (11, va("%c%c%c%cstatus\n", 255, 255, 255, 255), mast->adr);
|
||||
break;
|
||||
#ifdef NQPROT
|
||||
case MT_BCASTNQ:
|
||||
case MT_SINGLENQ:
|
||||
SZ_Clear(&net_message);
|
||||
net_message.packing = SZ_RAWBYTES;
|
||||
net_message.currentbit = 0;
|
||||
MSG_WriteLong(&net_message, 0);// save space for the header, filled in later
|
||||
MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
|
||||
MSG_WriteString(&net_message, NET_GAMENAME_NQ); //look for either sort of server
|
||||
MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
|
||||
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
|
||||
NET_SendPollPacket(net_message.cursize, net_message.data, mast->adr);
|
||||
SZ_Clear(&net_message);
|
||||
break;
|
||||
case MT_MASTERDP:
|
||||
{
|
||||
char *str;
|
||||
str = va("%c%c%c%cgetservers %s %u empty full"/*\x0A\n"*/, 255, 255, 255, 255, com_protocolname.string, 3);
|
||||
NET_SendPollPacket (strlen(str), str, mast->adr);
|
||||
}
|
||||
break;
|
||||
case MT_SINGLEDP:
|
||||
case MT_BCASTDP:
|
||||
{
|
||||
char *str;
|
||||
str = va("%c%c%c%cgetinfo", 255, 255, 255, 255);
|
||||
NET_SendPollPacket (strlen(str), str, mast->adr);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case MT_MASTERQW:
|
||||
NET_SendPollPacket (3, "c\n", mast->adr);
|
||||
break;
|
||||
#ifdef Q2CLIENT
|
||||
case MT_MASTERQ2:
|
||||
if (evenifwedonthavethefiles || COM_FDepthFile("pics/colormap.pcx", true)!=0x7fffffff) //only query this master if we expect to be able to load it's maps.
|
||||
NET_SendPollPacket (6, "query", mast->adr);
|
||||
break;
|
||||
#endif
|
||||
#ifdef WEBCLIENT
|
||||
case MT_MASTERHTTPJSON:
|
||||
if (!mast->dl)
|
||||
|
@ -1405,30 +1362,94 @@ void MasterInfo_Request(master_t *mast, qboolean evenifwedonthavethefiles)
|
|||
mast->dl->user_ctx = mast;
|
||||
}
|
||||
break;
|
||||
case MT_MASTERHTTPNQ:
|
||||
case MT_MASTERHTTP:
|
||||
if (!mast->dl)
|
||||
{
|
||||
mast->dl = HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPNQ);
|
||||
if (mast->dl)
|
||||
mast->dl->user_ctx = mast;
|
||||
}
|
||||
break;
|
||||
case MT_MASTERHTTPQW:
|
||||
if (!mast->dl)
|
||||
{
|
||||
mast->dl = HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTPQW);
|
||||
mast->dl = HTTP_CL_Get(mast->address, NULL, MasterInfo_ProcessHTTP);
|
||||
if (mast->dl)
|
||||
mast->dl->user_ctx = mast;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case MT_MASTERUDP:
|
||||
switch(mast->protocoltype)
|
||||
{
|
||||
#ifdef Q3CLIENT
|
||||
case MP_Q3:
|
||||
{
|
||||
char *str;
|
||||
str = va("%c%c%c%cgetservers %u empty full\x0A\n", 255, 255, 255, 255, 68);
|
||||
NET_SendPollPacket (strlen(str), str, mast->adr);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef Q2CLIENT
|
||||
case MP_Q2:
|
||||
NET_SendPollPacket (6, "query", mast->adr);
|
||||
break;
|
||||
#endif
|
||||
case MP_QW:
|
||||
NET_SendPollPacket (3, "c\n", mast->adr);
|
||||
break;
|
||||
#ifdef NQPROT
|
||||
case MP_NQ:
|
||||
//there is no nq udp master protocol
|
||||
break;
|
||||
case MP_DP:
|
||||
{
|
||||
char *str;
|
||||
str = va("%c%c%c%cgetservers %s %u empty full"/*\x0A\n"*/, 255, 255, 255, 255, com_protocolname.string, 3);
|
||||
NET_SendPollPacket (strlen(str), str, mast->adr);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case MT_BCAST:
|
||||
case MT_SINGLE: //FIXME: properly add the server and flag it for resending instead of directly pinging it
|
||||
switch(mast->protocoltype)
|
||||
{
|
||||
#ifdef Q3CLIENT
|
||||
case MP_Q3:
|
||||
NET_SendPollPacket (14, va("%c%c%c%cgetstatus\n", 255, 255, 255, 255), mast->adr);
|
||||
break;
|
||||
#endif
|
||||
#ifdef Q2CLIENT
|
||||
case MP_Q2:
|
||||
#endif
|
||||
case MP_QW:
|
||||
NET_SendPollPacket (11, va("%c%c%c%cstatus\n", 255, 255, 255, 255), mast->adr);
|
||||
break;
|
||||
#ifdef NQPROT
|
||||
case MP_NQ:
|
||||
SZ_Clear(&net_message);
|
||||
net_message.packing = SZ_RAWBYTES;
|
||||
net_message.currentbit = 0;
|
||||
MSG_WriteLong(&net_message, 0);// save space for the header, filled in later
|
||||
MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
|
||||
MSG_WriteString(&net_message, NET_GAMENAME_NQ); //look for either sort of server
|
||||
MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
|
||||
*((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
|
||||
NET_SendPollPacket(net_message.cursize, net_message.data, mast->adr);
|
||||
SZ_Clear(&net_message);
|
||||
break;
|
||||
case MP_DP:
|
||||
{
|
||||
char *str;
|
||||
str = va("%c%c%c%cgetinfo", 255, 255, 255, 255);
|
||||
NET_SendPollPacket (strlen(str), str, mast->adr);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MasterInfo_WriteServers(void)
|
||||
{
|
||||
char *typename;
|
||||
char *typename, *protoname;
|
||||
master_t *mast;
|
||||
serverinfo_t *server;
|
||||
vfsfile_t *mf, *qws;
|
||||
|
@ -1443,58 +1464,51 @@ void MasterInfo_WriteServers(void)
|
|||
|
||||
for (mast = master; mast; mast=mast->next)
|
||||
{
|
||||
switch(mast->type)
|
||||
switch(mast->mastertype)
|
||||
{
|
||||
case MT_MASTERQW:
|
||||
typename = "master:qw";
|
||||
case MT_MASTERUDP:
|
||||
typename = "master";
|
||||
break;
|
||||
case MT_MASTERQ2:
|
||||
typename = "master:q2";
|
||||
case MT_MASTERHTTP:
|
||||
typename = "masterhttp";
|
||||
break;
|
||||
case MT_MASTERQ3:
|
||||
typename = "master:q3";
|
||||
case MT_MASTERHTTPJSON:
|
||||
typename = "masterjson";
|
||||
break;
|
||||
case MT_MASTERDP:
|
||||
typename = "master:dp";
|
||||
case MT_BCAST:
|
||||
typename = "bcast";
|
||||
break;
|
||||
case MT_MASTERHTTPNQ:
|
||||
typename = "master:httpnq";
|
||||
break;
|
||||
case MT_MASTERHTTPQW:
|
||||
typename = "master:httpqw";
|
||||
break;
|
||||
case MT_BCASTQW:
|
||||
typename = "bcast:qw";
|
||||
break;
|
||||
case MT_BCASTQ2:
|
||||
typename = "bcast:q2";
|
||||
break;
|
||||
case MT_BCASTQ3:
|
||||
typename = "bcast:q3";
|
||||
break;
|
||||
case MT_BCASTNQ:
|
||||
typename = "bcast:nq";
|
||||
break;
|
||||
case MT_SINGLEQW:
|
||||
typename = "single:qw";
|
||||
break;
|
||||
case MT_SINGLEQ2:
|
||||
typename = "single:q2";
|
||||
break;
|
||||
case MT_SINGLEQ3:
|
||||
typename = "single:q3";
|
||||
break;
|
||||
case MT_SINGLENQ:
|
||||
typename = "single:nq";
|
||||
break;
|
||||
case MT_SINGLEDP:
|
||||
typename = "single:dp";
|
||||
case MT_SINGLE:
|
||||
typename = "single";
|
||||
break;
|
||||
default:
|
||||
typename = "writeerror";
|
||||
typename = "??";
|
||||
break;
|
||||
}
|
||||
switch(mast->protocoltype)
|
||||
{
|
||||
case MP_QW:
|
||||
protoname = ":qw";
|
||||
break;
|
||||
case MP_Q2:
|
||||
protoname = ":q2";
|
||||
break;
|
||||
case MP_Q3:
|
||||
protoname = ":q3";
|
||||
break;
|
||||
case MP_NQ:
|
||||
protoname = ":nq";
|
||||
break;
|
||||
case MP_DP:
|
||||
protoname = ":dp";
|
||||
break;
|
||||
default:
|
||||
case MP_UNSPECIFIED:
|
||||
protoname = "";
|
||||
break;
|
||||
}
|
||||
if (mast->address)
|
||||
VFS_PUTS(mf, va("%s\t%s\t%s\n", mast->address , typename, mast->name));
|
||||
VFS_PUTS(mf, va("%s\t%s\t%s\n", mast->address, typename, protoname, mast->name));
|
||||
else
|
||||
VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &mast->adr), typename, mast->name));
|
||||
}
|
||||
|
@ -1516,7 +1530,7 @@ void MasterInfo_WriteServers(void)
|
|||
VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:q2", server->name));
|
||||
else if (server->special & SS_NETQUAKE)
|
||||
VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:nq", server->name));
|
||||
else if (qws) //servers.txt doesn't support the extra info.
|
||||
else if (qws) //servers.txt doesn't support the extra info, so don't write it if its not needed
|
||||
VFS_PUTS(qws, va("%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), server->name));
|
||||
else //read only? damn them!
|
||||
VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:qw", server->name));
|
||||
|
@ -1534,71 +1548,78 @@ void MasterInfo_WriteServers(void)
|
|||
void MasterInfo_Refresh(void)
|
||||
{
|
||||
master_t *mast;
|
||||
if (!Master_LoadMasterList("masters.txt", MT_MASTERQW, 5))
|
||||
qboolean loadedone;
|
||||
|
||||
loadedone = false;
|
||||
loadedone |= Master_LoadMasterList("masters.txt", false, MT_MASTERUDP, MP_QW, 5); //fte listing
|
||||
loadedone |= Master_LoadMasterList("sources.txt", true, MT_MASTERUDP, MP_QW, 5); //merge with ezquake compat listing
|
||||
|
||||
if (!loadedone)
|
||||
{
|
||||
Master_LoadMasterList("servers.txt", MT_SINGLEQW, 1);
|
||||
Master_LoadMasterList("servers.txt", false, MT_MASTERUDP, MP_QW, 1);
|
||||
|
||||
// if (q1servers) //qw master servers
|
||||
{
|
||||
Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quakeworld", MT_MASTERHTTPQW, "gameaholic's QW master");
|
||||
//Master_AddMaster("satan.idsoftware.com:27000", MT_MASTERQW, "id Limbo");
|
||||
//Master_AddMaster("satan.idsoftware.com:27002", MT_MASTERQW, "id CTF");
|
||||
//Master_AddMaster("satan.idsoftware.com:27003", MT_MASTERQW, "id TeamFortress");
|
||||
//Master_AddMaster("satan.idsoftware.com:27004", MT_MASTERQW, "id Miscilaneous");
|
||||
//Master_AddMaster("satan.idsoftware.com:27006", MT_MASTERQW, "id Deathmatch Only");
|
||||
//Master_AddMaster("150.254.66.120:27000", MT_MASTERQW, "Poland's master server.");
|
||||
//Master_AddMaster("62.112.145.129:27000", MT_MASTERQW, "Ocrana master server.");
|
||||
//Master_AddMaster("master.edome.net", MT_MASTERQW, "edome master server.");
|
||||
//Master_AddMaster("qwmaster.barrysworld.com", MT_MASTERQW, "barrysworld master server.");
|
||||
//Master_AddMaster("213.221.174.165:27000", MT_MASTERQW, "unknown1 master server.");
|
||||
//Master_AddMaster("195.74.0.8", MT_MASTERQW, "unknown2 master server.");
|
||||
//Master_AddMaster("204.182.161.2", MT_MASTERQW, "unknown5 master server.");
|
||||
//Master_AddMaster("kubus.rulez.pl:27000",MT_MASTERQW, "Kubus");
|
||||
//Master_AddMaster("telefrag.me:27000",MT_MASTERQW, "Telefrag.ME");
|
||||
//Master_AddMaster("master.teamdamage.com:27000", MT_MASTERQW, "TeamDamage");
|
||||
Master_AddMaster("master.quakeservers.net:27000", MT_MASTERQW, "QuakeServers.net");
|
||||
// Master_AddMaster("masterserver.exhale.de:27000", MT_MASTERQW, "team exhale");
|
||||
Master_AddMaster("qwmaster.fodquake.net:27000", MT_MASTERQW, "Fodquake master server.");
|
||||
Master_AddMaster("qwmaster.ocrana.de:27000", MT_MASTERQW, "Ocrana2 master server.");
|
||||
Master_AddMaster("255.255.255.255:27500", MT_BCASTQW, "Nearby QuakeWorld UDP servers.");
|
||||
Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quakeworld", MT_MASTERHTTP, MP_QW, "gameaholic's QW master");
|
||||
Master_AddMasterHTTP("http://www.quakeservers.net/lists/servers/global.txt",MT_MASTERHTTP, MP_QW, "QuakeServers.net (http)");
|
||||
//Master_AddMaster("satan.idsoftware.com:27000", MT_MASTERUDP, MP_QW, "id Limbo");
|
||||
//Master_AddMaster("satan.idsoftware.com:27002", MT_MASTERUDP, MP_QW, "id CTF");
|
||||
//Master_AddMaster("satan.idsoftware.com:27003", MT_MASTERUDP, MP_QW, "id TeamFortress");
|
||||
//Master_AddMaster("satan.idsoftware.com:27004", MT_MASTERUDP, MP_QW, "id Miscilaneous");
|
||||
//Master_AddMaster("satan.idsoftware.com:27006", MT_MASTERUDP, MP_QW, "id Deathmatch Only");
|
||||
//Master_AddMaster("150.254.66.120:27000", MT_MASTERUDP, MP_QW, "Poland's master server.");
|
||||
//Master_AddMaster("62.112.145.129:27000", MT_MASTERUDP, MP_QW, "Ocrana master server.");
|
||||
//Master_AddMaster("master.edome.net", MT_MASTERUDP, MP_QW, "edome master server.");
|
||||
//Master_AddMaster("qwmaster.barrysworld.com", MT_MASTERUDP, MP_QW, "barrysworld master server.");
|
||||
//Master_AddMaster("213.221.174.165:27000", MT_MASTERUDP, MP_QW, "unknown1 master server.");
|
||||
//Master_AddMaster("195.74.0.8", MT_MASTERUDP, MP_QW, "unknown2 master server.");
|
||||
//Master_AddMaster("204.182.161.2", MT_MASTERUDP, MP_QW, "unknown5 master server.");
|
||||
//Master_AddMaster("kubus.rulez.pl:27000", MT_MASTERUDP, MP_QW, "Kubus");
|
||||
//Master_AddMaster("telefrag.me:27000", MT_MASTERUDP, MP_QW, "Telefrag.ME");
|
||||
//Master_AddMaster("master.teamdamage.com:27000", MT_MASTERUDP, MP_QW, "TeamDamage");
|
||||
Master_AddMaster("master.quakeservers.net:27000", MT_MASTERUDP, MP_QW, "QuakeServers.net");
|
||||
// Master_AddMaster("masterserver.exhale.de:27000", MT_MASTERUDP, MP_QW, "team exhale");
|
||||
Master_AddMaster("qwmaster.fodquake.net:27000", MT_MASTERUDP, MP_QW, "Fodquake master server.");
|
||||
Master_AddMaster("qwmaster.ocrana.de:27000", MT_MASTERUDP, MP_QW, "Ocrana2 master server.");
|
||||
Master_AddMaster("255.255.255.255:27500", MT_BCAST, MP_QW, "Nearby QuakeWorld UDP servers.");
|
||||
}
|
||||
|
||||
// if (q1servers) //nq master servers
|
||||
{
|
||||
//Master_AddMaster("12.166.196.192:27950", MT_MASTERDP, "DarkPlaces Master 3");
|
||||
Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake", MT_MASTERHTTPNQ, "gameaholic's NQ master");
|
||||
Master_AddMasterHTTP("http://servers.quakeone.com/index.php?format=json", MT_MASTERHTTPJSON, "quakeone's server listing");
|
||||
Master_AddMaster("69.59.212.88:27950"/*"ghdigital.com:27950"*/, MT_MASTERDP, "DarkPlaces Master 1"); // LordHavoc
|
||||
Master_AddMaster("64.22.107.125:27950"/*"dpmaster.deathmask.net:27950"*/, MT_MASTERDP, "DarkPlaces Master 2"); // Willis
|
||||
Master_AddMaster("92.62.40.73:27950"/*"dpmaster.tchr.no:27950"*/, MT_MASTERDP, "DarkPlaces Master 3"); // tChr
|
||||
//Master_AddMaster("12.166.196.192:27950", MT_MASTERUDP, MP_DP, "DarkPlaces Master 3");
|
||||
Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake", MT_MASTERHTTP, MP_NQ, "gameaholic's NQ master");
|
||||
Master_AddMasterHTTP("http://servers.quakeone.com/index.php?format=json", MT_MASTERHTTPJSON, MP_NQ, "quakeone's server listing");
|
||||
Master_AddMaster("69.59.212.88:27950"/*"ghdigital.com:27950"*/, MT_MASTERUDP, MP_DP, "DarkPlaces Master 1"); // LordHavoc
|
||||
Master_AddMaster("64.22.107.125:27950"/*"dpmaster.deathmask.net:27950"*/, MT_MASTERUDP, MP_DP, "DarkPlaces Master 2"); // Willis
|
||||
Master_AddMaster("92.62.40.73:27950"/*"dpmaster.tchr.no:27950"*/, MT_MASTERUDP, MP_DP, "DarkPlaces Master 3"); // tChr
|
||||
#ifdef IPPROTO_IPV6
|
||||
//Master_AddMaster("[2001:41d0:2:1628::4450]:27950", MT_MASTERDP, "DarkPlaces Master 4"); // dpmaster.div0.qc.to (admin: divVerent)
|
||||
//Master_AddMaster("[2001:41d0:2:1628::4450]:27950", MT_MASTERUDP, MP_DP, "DarkPlaces Master 4"); // dpmaster.div0.qc.to (admin: divVerent)
|
||||
#endif
|
||||
Master_AddMaster("255.255.255.255:26000", MT_BCASTNQ, "Nearby Quake1 servers");
|
||||
Master_AddMaster("255.255.255.255:26000", MT_BCASTDP, "Nearby DarkPlaces servers");
|
||||
Master_AddMaster("255.255.255.255:26000", MT_BCAST, MP_NQ, "Nearby Quake1 servers");
|
||||
Master_AddMaster("255.255.255.255:26000", MT_BCAST, MP_DP, "Nearby DarkPlaces servers");
|
||||
}
|
||||
|
||||
// if (q2servers) //q2
|
||||
{
|
||||
//Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake2", MT_MASTERHTTPQW, "gameaholic's Q2 master");
|
||||
//Master_AddMaster("satan.idsoftware.com:27900", MT_MASTERQ2, "id q2 Master.");
|
||||
//Master_AddMaster("master.planetgloom.com:27900",MT_MASTERQ2, "Planetgloom.com");
|
||||
//Master_AddMaster("master.q2servers.com:27900", MT_MASTERQ2, "q2servers.com");
|
||||
Master_AddMaster("netdome.biz:27900", MT_MASTERQ2, "Netdome.biz");
|
||||
// Master_AddMaster("masterserver.exhale.de:27900",MT_MASTERQ2, "team exhale");
|
||||
Master_AddMaster("255.255.255.255:27910", MT_BCASTQ2, "Nearby Quake2 UDP servers.");
|
||||
Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake2", MT_MASTERHTTP, MP_QW, "gameaholic's Q2 master");
|
||||
//Master_AddMaster("satan.idsoftware.com:27900", MT_MASTERUDP, MP_Q2, "id q2 Master.");
|
||||
//Master_AddMaster("master.planetgloom.com:27900", MT_MASTERUDP, MP_Q2, "Planetgloom.com");
|
||||
//Master_AddMaster("master.q2servers.com:27900", MT_MASTERUDP, MP_Q2, "q2servers.com");
|
||||
Master_AddMaster("netdome.biz:27900", MT_MASTERUDP, MP_Q2, "Netdome.biz");
|
||||
// Master_AddMaster("masterserver.exhale.de:27900", MT_MASTERUDP, MP_Q2, "team exhale");
|
||||
Master_AddMaster("255.255.255.255:27910", MT_BCAST, MP_Q2, "Nearby Quake2 UDP servers.");
|
||||
#ifdef USEIPX
|
||||
Master_AddMaster("00000000:ffffffffffff:27910", MT_BCASTQ2, "Nearby Quake2 IPX servers.");
|
||||
Master_AddMaster("00000000:ffffffffffff:27910", MT_BCAST, MP_Q2, "Nearby Quake2 IPX servers.");
|
||||
#endif
|
||||
}
|
||||
|
||||
//q3
|
||||
{
|
||||
//Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake3", MT_MASTERHTTPQW, "gameaholic's Q3 master");
|
||||
Master_AddMaster("master.quake3arena.com:27950", MT_MASTERQ3, "Quake3 master server.");
|
||||
// Master_AddMaster("masterserver.exhale.de:27950", MT_MASTERQ3, "team exhale");
|
||||
//Master_AddMaster("master3.quake3arena.com:27950", MT_MASTERQ3, "Quake3 master3 server.");
|
||||
Master_AddMaster("255.255.255.255:27960", MT_BCASTQ3, "Nearby Quake3 UDP servers.");
|
||||
Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake3", MT_MASTERHTTP, MP_Q3, "gameaholic's Q3 master");
|
||||
Master_AddMaster("master.quake3arena.com:27950", MT_MASTERUDP, MP_Q3, "Quake3 master server.");
|
||||
// Master_AddMaster("masterserver.exhale.de:27950", MT_MASTERUDP, MP_Q3, "team exhale");
|
||||
//Master_AddMaster("master3.quake3arena.com:27950", MT_MASTERUDP, MP_Q3, "Quake3 master3 server.");
|
||||
Master_AddMaster("255.255.255.255:27960", MT_BCAST, MP_Q3, "Nearby Quake3 UDP servers.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1658,42 +1679,32 @@ void CL_QueryServers(void)
|
|||
|
||||
for (mast = master; mast; mast=mast->next)
|
||||
{
|
||||
switch (mast->type)
|
||||
switch (mast->protocoltype)
|
||||
{
|
||||
case MT_BAD:
|
||||
case MP_UNSPECIFIED:
|
||||
continue;
|
||||
case MT_MASTERHTTPNQ:
|
||||
case MT_BCASTNQ:
|
||||
case MT_SINGLENQ:
|
||||
case MT_BCASTDP:
|
||||
case MT_SINGLEDP:
|
||||
case MT_MASTERDP:
|
||||
case MP_DP: //dpmaster allows the client to specify the protocol to query. this means it always matches the current game type, so don't bother allowing the user to disable it.
|
||||
break;
|
||||
case MP_NQ:
|
||||
if (sb_hidenetquake.value)
|
||||
continue;
|
||||
break;
|
||||
case MT_MASTERHTTPQW:
|
||||
case MT_BCASTQW:
|
||||
case MT_SINGLEQW:
|
||||
case MT_MASTERQW:
|
||||
case MP_QW:
|
||||
if (sb_hidequakeworld.value)
|
||||
continue;
|
||||
break;
|
||||
case MT_BCASTQ2:
|
||||
case MT_SINGLEQ2:
|
||||
case MT_MASTERQ2:
|
||||
case MP_Q2:
|
||||
if (sb_hidequake2.value)
|
||||
continue;
|
||||
break;
|
||||
case MT_BCASTQ3:
|
||||
case MT_MASTERQ3:
|
||||
case MT_SINGLEQ3:
|
||||
case MP_Q3:
|
||||
if (sb_hidequake3.value)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mast->sends > 0)
|
||||
MasterInfo_Request(mast, false);
|
||||
MasterInfo_Request(mast);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1849,7 +1860,7 @@ void MasterInfo_AddPlayer(netadr_t *serveradr, char *name, int ping, int frags,
|
|||
}
|
||||
|
||||
//we got told about a server, parse it's info
|
||||
int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite)
|
||||
int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favorite)
|
||||
{
|
||||
serverdetailedinfo_t details;
|
||||
|
||||
|
@ -1901,18 +1912,18 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite)
|
|||
else if (!strncmp(DISTRIBUTION, Info_ValueForKey(msg, "*version"), 3))
|
||||
info->special |= SS_FTESERVER;
|
||||
|
||||
if (servertype == MT_SINGLEDP)
|
||||
if (prototype == MP_DP)
|
||||
{
|
||||
if (atoi(Info_ValueForKey(msg, "protocol")) > 60)
|
||||
info->special |= SS_QUAKE3;
|
||||
else
|
||||
info->special |= SS_DARKPLACES;
|
||||
}
|
||||
else if (servertype == MT_SINGLEQ2)
|
||||
else if (prototype == MP_Q2)
|
||||
info->special |= SS_QUAKE2;
|
||||
else if (servertype == MT_SINGLEQ3)
|
||||
else if (prototype == MP_Q3)
|
||||
info->special |= SS_QUAKE3;
|
||||
else if (servertype == MT_SINGLENQ)
|
||||
else if (prototype == MP_NQ)
|
||||
info->special |= SS_NETQUAKE;
|
||||
if (favorite) //was specifically named, not retrieved from a master.
|
||||
info->special |= SS_FAVORITE;
|
||||
|
@ -1936,7 +1947,7 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite)
|
|||
if (!strcmp(Info_ValueForKey(msg, "*progs"), "666") && !strcmp(Info_ValueForKey(msg, "*version"), "2.91"))
|
||||
info->special |= SS_PROXY; //qizmo
|
||||
|
||||
if (servertype == MT_SINGLEQ3 || servertype == MT_SINGLEQ2 || servertype == MT_SINGLEDP)
|
||||
if (prototype == MP_Q3 || prototype == MP_Q2 || prototype == MP_DP)
|
||||
{
|
||||
Q_strncpyz(info->gamedir, Info_ValueForKey(msg, "gamename"), sizeof(info->gamedir));
|
||||
Q_strncpyz(info->map, Info_ValueForKey(msg, "mapname"), sizeof(info->map));
|
||||
|
@ -1966,7 +1977,7 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite)
|
|||
{
|
||||
int clnum;
|
||||
|
||||
for (clnum=0; clnum < MAX_CLIENTS; clnum++)
|
||||
for (clnum=0; clnum < cl.allocated_client_slots; clnum++)
|
||||
{
|
||||
nl = strchr(msg, '\n');
|
||||
if (!nl)
|
||||
|
|
|
@ -560,12 +560,11 @@ void QCBUILTIN PF_shaderforname (pubprogfuncs_t *prinst, struct globalvars_s *pr
|
|||
else
|
||||
shad = R_RegisterSkin(str, NULL);
|
||||
if (shad)
|
||||
G_FLOAT(OFS_RETURN) = shad-r_shaders + 1;
|
||||
G_FLOAT(OFS_RETURN) = shad->id+1;
|
||||
else
|
||||
G_FLOAT(OFS_RETURN) = 0;
|
||||
}
|
||||
|
||||
|
||||
void QCBUILTIN PF_cl_GetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
G_VECTOR(OFS_RETURN)[0] = 1;
|
||||
|
|
|
@ -720,8 +720,8 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out)
|
|||
out->skinnum = in->v->skin;
|
||||
out->fatness = in->xv->fatness;
|
||||
ival = in->xv->forceshader;
|
||||
if (ival >= 1 && ival <= MAX_SHADERS)
|
||||
out->forcedshader = r_shaders + (ival-1);
|
||||
if (ival >= 1 && ival <= r_numshaders)
|
||||
out->forcedshader = r_shaders[(ival-1)];
|
||||
else
|
||||
out->forcedshader = NULL;
|
||||
|
||||
|
@ -817,6 +817,7 @@ static void QCBUILTIN PF_R_DynamicLight_Set(pubprogfuncs_t *prinst, struct globa
|
|||
break;
|
||||
case lfield_angles:
|
||||
AngleVectors(G_VECTOR(OFS_PARM2), l->axis[0], l->axis[1], l->axis[2]);
|
||||
VectorInverse(l->axis[1]);
|
||||
break;
|
||||
case lfield_fov:
|
||||
l->fov = G_FLOAT(OFS_PARM2);
|
||||
|
@ -852,6 +853,7 @@ static void QCBUILTIN PF_R_DynamicLight_Set(pubprogfuncs_t *prinst, struct globa
|
|||
}
|
||||
static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
vec3_t v;
|
||||
dlight_t *l;
|
||||
unsigned int lno = G_FLOAT(OFS_PARM0);
|
||||
enum lightfield_e field = G_FLOAT(OFS_PARM1);
|
||||
|
@ -882,7 +884,10 @@ static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globa
|
|||
G_FLOAT(OFS_RETURN) = l->style;
|
||||
break;
|
||||
case lfield_angles:
|
||||
VectorAngles(l->axis[0], l->axis[2], G_VECTOR(OFS_RETURN));
|
||||
VectorAngles(l->axis[0], l->axis[2], v);
|
||||
G_FLOAT(OFS_RETURN+0) = v[0]?v[0]:0;
|
||||
G_FLOAT(OFS_RETURN+1) = v[1]?v[1]:0;
|
||||
G_FLOAT(OFS_RETURN+2) = v[2]?v[2]:0;
|
||||
break;
|
||||
case lfield_fov:
|
||||
G_FLOAT(OFS_RETURN) = l->fov;
|
||||
|
@ -3617,25 +3622,21 @@ static void QCBUILTIN PF_cs_registercommand (pubprogfuncs_t *prinst, struct glob
|
|||
Cmd_AddCommand(str, CS_ConsoleCommand_f);
|
||||
}
|
||||
|
||||
static qboolean csqc_usinglistener;
|
||||
qboolean CSQC_SettingListener(void)
|
||||
{ //stops the engine from setting the listener positions.
|
||||
if (csqc_usinglistener)
|
||||
{
|
||||
csqc_usinglistener = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static void QCBUILTIN PF_cs_setlistener (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
float *origin = G_VECTOR(OFS_PARM0);
|
||||
float *forward = G_VECTOR(OFS_PARM1);
|
||||
float *right = G_VECTOR(OFS_PARM2);
|
||||
float *up = G_VECTOR(OFS_PARM3);
|
||||
csqc_usinglistener = true;
|
||||
S_UpdateListener(origin, forward, right, up);
|
||||
S_Update();
|
||||
int inwater = (prinst->callargc>4)?G_FLOAT(OFS_PARM4):false;
|
||||
|
||||
r_refdef.audio.defaulted = false;
|
||||
// r_refdef.audio.entity = 0;
|
||||
VectorCopy(origin, r_refdef.audio.origin);
|
||||
VectorCopy(forward, r_refdef.audio.forward);
|
||||
VectorCopy(right, r_refdef.audio.right);
|
||||
VectorCopy(up, r_refdef.audio.up);
|
||||
r_refdef.audio.inwater = inwater;
|
||||
}
|
||||
|
||||
#define RSES_NOLERP 1
|
||||
|
@ -3763,12 +3764,7 @@ void CSQC_PlayerStateToCSQC(int pnum, player_state_t *srcp, csqcedict_t *ent)
|
|||
{
|
||||
ent->xv->entnum = pnum+1;
|
||||
|
||||
if (cl.spectator && !Cam_DrawEntity(0, pnum+1))
|
||||
{
|
||||
ent->v->modelindex = 0;
|
||||
}
|
||||
else
|
||||
ent->v->modelindex = srcp->modelindex;
|
||||
ent->v->modelindex = srcp->modelindex;
|
||||
ent->v->skin = srcp->skinnum;
|
||||
|
||||
CSQC_LerpStateToCSQC(&cl.lerpplayers[pnum], ent, true);
|
||||
|
@ -4130,7 +4126,7 @@ static void QCBUILTIN PF_ReadServerEntityState(pubprogfuncs_t *prinst, struct gl
|
|||
if (!pack)
|
||||
return; //we're lagging. can't do anything, just don't update
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
srcp = &cl.frames[cl.validsequence&UPDATE_MASK].playerstate[i];
|
||||
ent = deltaedplayerents[i];
|
||||
|
@ -5072,8 +5068,6 @@ void CSQC_Shutdown(void)
|
|||
|
||||
in_sensitivityscale = 1;
|
||||
csqc_world.num_edicts = 0;
|
||||
|
||||
csqc_usinglistener = false;
|
||||
}
|
||||
|
||||
//when the qclib needs a file, it calls out to this function.
|
||||
|
@ -5229,7 +5223,6 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
|
|||
csprogs_promiscuous = anycsqc;
|
||||
csprogs_checksum = checksum;
|
||||
|
||||
csqc_usinglistener = false;
|
||||
csqc_mayread = false;
|
||||
|
||||
csqc_singlecheats = cls.demoplayback;
|
||||
|
|
|
@ -1512,7 +1512,7 @@ char *particle_set_high =
|
|||
"randomvel 0\n"
|
||||
|
||||
"lightradius 350\n"
|
||||
"lightrgb 0.4 0.2 0.05\n"
|
||||
"lightrgb 1.4 1.2 1.05\n"
|
||||
"lighttime 0.5\n"
|
||||
"lightradiusfade 350\n"
|
||||
"lightrgbfade 2 2 2 \n"
|
||||
|
|
|
@ -1447,7 +1447,7 @@ start:
|
|||
if (node->visframe != r_visframecount)
|
||||
return;
|
||||
|
||||
for (c = 0, clipplane = frustum; c < FRUSTUMPLANES; c++, clipplane++)
|
||||
for (c = 0, clipplane = r_refdef.frustum; c < r_refdef.frustum_numplanes; c++, clipplane++)
|
||||
{
|
||||
if (!(clipflags & (1 << c)))
|
||||
continue; // don't need to clip against it
|
||||
|
@ -1556,7 +1556,7 @@ static void Surf_OrthoRecursiveWorldNode (mnode_t *node, unsigned int clipflags)
|
|||
if (node->visframe != r_visframecount)
|
||||
return;
|
||||
|
||||
for (c = 0, clipplane = frustum; c < 4; c++, clipplane++)
|
||||
for (c = 0, clipplane = r_refdef.frustum; c < r_refdef.frustum_numplanes; c++, clipplane++)
|
||||
{
|
||||
if (!(clipflags & (1 << c)))
|
||||
continue; // don't need to clip against it
|
||||
|
@ -1813,7 +1813,7 @@ start:
|
|||
if (node->visframe != r_visframecount)
|
||||
return;
|
||||
|
||||
for (c = 0, clipplane = frustum; c < FRUSTUMPLANES; c++, clipplane++)
|
||||
for (c = 0, clipplane = r_refdef.frustum; c < r_refdef.frustum_numplanes; c++, clipplane++)
|
||||
{
|
||||
if (!(clipflags & (1 << c)))
|
||||
continue; // don't need to clip against it
|
||||
|
@ -2065,6 +2065,21 @@ void Surf_SetupFrame(void)
|
|||
VectorCopy(t2, player_maxs);
|
||||
}
|
||||
V_SetContentsColor (r_viewcontents);
|
||||
|
||||
|
||||
if (r_refdef.audio.defaulted)
|
||||
{
|
||||
//first scene is the 'main' scene and audio defaults to that (unless overridden later in the frame)
|
||||
r_refdef.audio.defaulted = false;
|
||||
VectorCopy(r_origin, r_refdef.audio.origin);
|
||||
VectorCopy(vpn, r_refdef.audio.forward);
|
||||
VectorCopy(vright, r_refdef.audio.right);
|
||||
VectorCopy(vup, r_refdef.audio.up);
|
||||
if (r_viewcontents & FTECONTENTS_FLUID)
|
||||
r_refdef.audio.inwater = true;
|
||||
else
|
||||
r_refdef.audio.inwater = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2247,7 +2262,7 @@ void Surf_DrawWorld (void)
|
|||
if (currententity->model->fromgame == fg_quake3)
|
||||
{
|
||||
entvis = surfvis = R_MarkLeaves_Q3 ();
|
||||
Surf_RecursiveQ3WorldNode (cl.worldmodel->nodes, (1<<FRUSTUMPLANES)-1);
|
||||
Surf_RecursiveQ3WorldNode (cl.worldmodel->nodes, (1<<r_refdef.frustum_numplanes)-1);
|
||||
//Surf_LeafWorldNode ();
|
||||
}
|
||||
else
|
||||
|
@ -2453,7 +2468,7 @@ int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe)
|
|||
|
||||
if (deluxe && ((i - numlightmaps)&1))
|
||||
{
|
||||
lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*8)*width*height);
|
||||
lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*4)*width*height);
|
||||
lightmap[i]->width = width;
|
||||
lightmap[i]->height = height;
|
||||
lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1);
|
||||
|
@ -2462,7 +2477,7 @@ int Surf_NewLightmaps(int count, int width, int height, qboolean deluxe)
|
|||
}
|
||||
else
|
||||
{
|
||||
lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*8 + sizeof(stmap)*3)*width*height);
|
||||
lightmap[i] = Z_Malloc(sizeof(*lightmap[i]) + (sizeof(qbyte)*4 + sizeof(stmap)*3)*width*height);
|
||||
lightmap[i]->width = width;
|
||||
lightmap[i]->height = height;
|
||||
lightmap[i]->lightmaps = (qbyte*)(lightmap[i]+1);
|
||||
|
|
|
@ -138,6 +138,17 @@ typedef struct entity_s
|
|||
#endif
|
||||
} entity_t;
|
||||
|
||||
// plane_t structure
|
||||
typedef struct mplane_s
|
||||
{
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
qbyte type; // for texture axis selection and fast side tests
|
||||
qbyte signbits; // signx + signy<<1 + signz<<1
|
||||
qbyte pad[2];
|
||||
} mplane_t;
|
||||
#define MAXFRUSTUMPLANES 7 //4 side, 1 near, 1 far (fog), 1 water plane.
|
||||
|
||||
#define RDFD_FOV 1
|
||||
typedef struct
|
||||
{
|
||||
|
@ -164,6 +175,9 @@ typedef struct
|
|||
float m_projection[16];
|
||||
float m_view[16];
|
||||
|
||||
mplane_t frustum[MAXFRUSTUMPLANES];
|
||||
int frustum_numplanes;
|
||||
|
||||
vec4_t gfog_rgbd;
|
||||
|
||||
vrect_t pxrect; /*vrect, but in pixels rather than virtual coords*/
|
||||
|
@ -177,6 +191,16 @@ typedef struct
|
|||
int postproccube; /*postproc shader wants a cubemap, this is the mask of sides required*/
|
||||
|
||||
qbyte *forcedvis;
|
||||
|
||||
struct
|
||||
{
|
||||
qboolean defaulted;
|
||||
vec3_t origin;
|
||||
vec3_t forward;
|
||||
vec3_t right;
|
||||
vec3_t up;
|
||||
int inwater;
|
||||
} audio;
|
||||
} refdef_t;
|
||||
|
||||
extern refdef_t r_refdef;
|
||||
|
@ -217,7 +241,7 @@ int Surf_LightmapShift (struct model_s *model);
|
|||
#define LMBLOCK_WIDTH 128
|
||||
#define LMBLOCK_HEIGHT 128
|
||||
typedef struct glRect_s {
|
||||
unsigned char l,t,w,h;
|
||||
unsigned short l,t,w,h;
|
||||
} glRect_t;
|
||||
typedef unsigned char stmap;
|
||||
struct mesh_s;
|
||||
|
@ -335,8 +359,8 @@ extern texid_t balltexture;
|
|||
extern texid_t beamtexture;
|
||||
extern texid_t ptritexture;
|
||||
|
||||
void Mod_Init (void);
|
||||
void Mod_Shutdown (void);
|
||||
void Mod_Init (qboolean initial);
|
||||
void Mod_Shutdown (qboolean final);
|
||||
int Mod_TagNumForName(struct model_s *model, char *name);
|
||||
int Mod_SkinNumForName(struct model_s *model, char *name);
|
||||
int Mod_FrameNumForName(struct model_s *model, char *name);
|
||||
|
@ -357,6 +381,11 @@ void Mod_NowLoadExternal(void);
|
|||
void GLR_LoadSkys (void);
|
||||
void R_BloomRegister(void);
|
||||
|
||||
int Mod_RegisterModelFormatText(void *module, const char *formatname, char *magictext, qboolean (QDECL *load) (struct model_s *mod, void *buffer));
|
||||
int Mod_RegisterModelFormatMagic(void *module, const char *formatname, unsigned int magic, qboolean (QDECL *load) (struct model_s *mod, void *buffer));
|
||||
void Mod_UnRegisterModelFormat(int idx);
|
||||
void Mod_UnRegisterAllModelFormats(void *module);
|
||||
|
||||
#ifdef RUNTIMELIGHTING
|
||||
void LightFace (int surfnum);
|
||||
void LightLoadEntities(char *entstring);
|
||||
|
|
|
@ -79,6 +79,7 @@ cvar_t r_drawflat = CVARF ("r_drawflat", "0",
|
|||
CVAR_ARCHIVE | CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM);
|
||||
cvar_t r_wireframe = CVARF ("r_wireframe", "0",
|
||||
CVAR_CHEAT);
|
||||
cvar_t r_refract_fbo = CVARD ("r_refract_fbo", "1", "Use an fbo for refraction. If 0, just renders as a portal and uses a copy of the current framebuffer.");
|
||||
cvar_t gl_miptexLevel = CVAR ("gl_miptexLevel", "0");
|
||||
cvar_t r_drawviewmodel = CVARF ("r_drawviewmodel", "1", CVAR_ARCHIVE);
|
||||
cvar_t r_drawviewmodelinvis = CVAR ("r_drawviewmodelinvis", "0");
|
||||
|
@ -616,6 +617,7 @@ void Renderer_Init(void)
|
|||
Cvar_Register (&r_waterstyle, GRAPHICALNICETIES);
|
||||
Cvar_Register (&r_lavastyle, GRAPHICALNICETIES);
|
||||
Cvar_Register (&r_wireframe, GRAPHICALNICETIES);
|
||||
Cvar_Register (&r_refract_fbo, GRAPHICALNICETIES);
|
||||
Cvar_Register (&r_stereo_separation, GRAPHICALNICETIES);
|
||||
Cvar_Register (&r_stereo_method, GRAPHICALNICETIES);
|
||||
|
||||
|
@ -900,7 +902,7 @@ void R_ShutdownRenderer(void)
|
|||
CL_AllowIndependantSendCmd(false); //FIXME: figure out exactly which parts are going to affect the model loading.
|
||||
|
||||
P_Shutdown();
|
||||
Mod_Shutdown();
|
||||
Mod_Shutdown(false);
|
||||
|
||||
IN_Shutdown();
|
||||
|
||||
|
@ -1095,7 +1097,7 @@ TRACE(("dbg: R_ApplyRenderer: isDedicated = true\n"));
|
|||
#endif
|
||||
}
|
||||
TRACE(("dbg: R_ApplyRenderer: initing mods\n"));
|
||||
Mod_Init();
|
||||
Mod_Init(false);
|
||||
|
||||
// host_hunklevel = Hunk_LowMark();
|
||||
|
||||
|
@ -2020,10 +2022,6 @@ qbyte *R_MarkLeaves_Q1 (void)
|
|||
return vis;
|
||||
}
|
||||
|
||||
|
||||
mplane_t frustum[FRUSTUMPLANES];
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
R_CullBox
|
||||
|
@ -2033,10 +2031,15 @@ Returns true if the box is completely outside the frustom
|
|||
*/
|
||||
qboolean R_CullBox (vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
//this isn't very precise.
|
||||
//checking each plane individually can be problematic
|
||||
//if you have a large object behind the view, it can cross multiple planes, and be infront of each one at some point, yet should still be outside the view.
|
||||
//this is quite noticable with terrain where the potential height of a section is essentually infinite.
|
||||
//note that this is not a concern for spheres, just boxes.
|
||||
int i;
|
||||
|
||||
for (i=0 ; i<FRUSTUMPLANES ; i++)
|
||||
if (BOX_ON_PLANE_SIDE (mins, maxs, &frustum[i]) == 2)
|
||||
for (i = 0; i < r_refdef.frustum_numplanes; i++)
|
||||
if (BOX_ON_PLANE_SIDE (mins, maxs, &r_refdef.frustum[i]) == 2)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -2047,9 +2050,9 @@ qboolean R_CullSphere (vec3_t org, float radius)
|
|||
int i;
|
||||
float d;
|
||||
|
||||
for (i=0 ; i<FRUSTUMPLANES ; i++)
|
||||
for (i = 0; i < r_refdef.frustum_numplanes; i++)
|
||||
{
|
||||
d = DotProduct(frustum[i].normal, org)-frustum[i].dist;
|
||||
d = DotProduct(r_refdef.frustum[i].normal, org)-r_refdef.frustum[i].dist;
|
||||
if (d <= -radius)
|
||||
return true;
|
||||
}
|
||||
|
@ -2157,38 +2160,55 @@ void R_SetFrustum (float projmat[16], float viewmat[16])
|
|||
{
|
||||
if (i & 1)
|
||||
{
|
||||
frustum[i].normal[0] = mvp[3] + mvp[0+i/2];
|
||||
frustum[i].normal[1] = mvp[7] + mvp[4+i/2];
|
||||
frustum[i].normal[2] = mvp[11] + mvp[8+i/2];
|
||||
frustum[i].dist = mvp[15] + mvp[12+i/2];
|
||||
r_refdef.frustum[i].normal[0] = mvp[3] + mvp[0+i/2];
|
||||
r_refdef.frustum[i].normal[1] = mvp[7] + mvp[4+i/2];
|
||||
r_refdef.frustum[i].normal[2] = mvp[11] + mvp[8+i/2];
|
||||
r_refdef.frustum[i].dist = mvp[15] + mvp[12+i/2];
|
||||
}
|
||||
else
|
||||
{
|
||||
frustum[i].normal[0] = mvp[3] - mvp[0+i/2];
|
||||
frustum[i].normal[1] = mvp[7] - mvp[4+i/2];
|
||||
frustum[i].normal[2] = mvp[11] - mvp[8+i/2];
|
||||
frustum[i].dist = mvp[15] - mvp[12+i/2];
|
||||
r_refdef.frustum[i].normal[0] = mvp[3] - mvp[0+i/2];
|
||||
r_refdef.frustum[i].normal[1] = mvp[7] - mvp[4+i/2];
|
||||
r_refdef.frustum[i].normal[2] = mvp[11] - mvp[8+i/2];
|
||||
r_refdef.frustum[i].dist = mvp[15] - mvp[12+i/2];
|
||||
}
|
||||
|
||||
scale = 1/sqrt(DotProduct(frustum[i].normal, frustum[i].normal));
|
||||
frustum[i].normal[0] *= scale;
|
||||
frustum[i].normal[1] *= scale;
|
||||
frustum[i].normal[2] *= scale;
|
||||
frustum[i].dist *= -scale;
|
||||
scale = 1/sqrt(DotProduct(r_refdef.frustum[i].normal, r_refdef.frustum[i].normal));
|
||||
r_refdef.frustum[i].normal[0] *= scale;
|
||||
r_refdef.frustum[i].normal[1] *= scale;
|
||||
r_refdef.frustum[i].normal[2] *= scale;
|
||||
r_refdef.frustum[i].dist *= -scale;
|
||||
|
||||
frustum[i].type = PLANE_ANYZ;
|
||||
frustum[i].signbits = SignbitsForPlane (&frustum[i]);
|
||||
r_refdef.frustum[i].type = PLANE_ANYZ;
|
||||
r_refdef.frustum[i].signbits = SignbitsForPlane (&r_refdef.frustum[i]);
|
||||
}
|
||||
|
||||
r_refdef.frustum_numplanes = 4;
|
||||
|
||||
if (r_refdef.recurse)
|
||||
return;
|
||||
|
||||
#if FRUSTUMPLANES > 4
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[0] = mvp[3] - mvp[2];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[1] = mvp[7] - mvp[6];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[2] = mvp[11] - mvp[10];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].dist = mvp[15] - mvp[14];
|
||||
|
||||
scale = 1/sqrt(DotProduct(r_refdef.frustum[r_refdef.frustum_numplanes].normal, r_refdef.frustum[r_refdef.frustum_numplanes].normal));
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[0] *= scale;
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[1] *= scale;
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[2] *= scale;
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].dist *= -scale;
|
||||
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].type = PLANE_ANYZ;
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].signbits = SignbitsForPlane (&r_refdef.frustum[4]);
|
||||
|
||||
r_refdef.frustum_numplanes++;
|
||||
|
||||
//do far plane
|
||||
//fog will not logically not actually reach 0, though precision issues will force it. we cut off at an exponant of -500
|
||||
if (r_refdef.gfog_rgbd[3]
|
||||
#ifdef TERRAIN
|
||||
&& cl.worldmodel && cl.worldmodel->terrain
|
||||
&& cl.worldmodel && cl.worldmodel->type == mod_heightmap
|
||||
#else
|
||||
&& 0
|
||||
#endif
|
||||
|
@ -2217,38 +2237,22 @@ void R_SetFrustum (float projmat[16], float viewmat[16])
|
|||
culldist = culldist / (-r_refdef.gfog_rgbd[3]);
|
||||
//anything drawn beyond this point is fully obscured by fog
|
||||
|
||||
frustum[4].normal[0] = mvp[3] - mvp[2];
|
||||
frustum[4].normal[1] = mvp[7] - mvp[6];
|
||||
frustum[4].normal[2] = mvp[11] - mvp[10];
|
||||
frustum[4].dist = mvp[15] - mvp[14];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[0] = mvp[3] - mvp[2];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[1] = mvp[7] - mvp[6];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[2] = mvp[11] - mvp[10];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].dist = mvp[15] - mvp[14];
|
||||
|
||||
scale = 1/sqrt(DotProduct(frustum[4].normal, frustum[4].normal));
|
||||
frustum[4].normal[0] *= scale;
|
||||
frustum[4].normal[1] *= scale;
|
||||
frustum[4].normal[2] *= scale;
|
||||
// frustum[4].dist *= scale;
|
||||
frustum[4].dist = DotProduct(r_origin, frustum[4].normal)-culldist;
|
||||
scale = 1/sqrt(DotProduct(r_refdef.frustum[r_refdef.frustum_numplanes].normal, r_refdef.frustum[r_refdef.frustum_numplanes].normal));
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[0] *= scale;
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[1] *= scale;
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[2] *= scale;
|
||||
// r_refdef.frustum[r_refdef.frustum_numplanes].dist *= scale;
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].dist = DotProduct(r_origin, r_refdef.frustum[r_refdef.frustum_numplanes].normal)-culldist;
|
||||
|
||||
frustum[4].type = PLANE_ANYZ;
|
||||
frustum[4].signbits = SignbitsForPlane (&frustum[4]);
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].type = PLANE_ANYZ;
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].signbits = SignbitsForPlane (&r_refdef.frustum[r_refdef.frustum_numplanes]);
|
||||
r_refdef.frustum_numplanes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
frustum[4].normal[0] = mvp[3] - mvp[2];
|
||||
frustum[4].normal[1] = mvp[7] - mvp[6];
|
||||
frustum[4].normal[2] = mvp[11] - mvp[10];
|
||||
frustum[4].dist = mvp[15] - mvp[14];
|
||||
|
||||
scale = 1/sqrt(DotProduct(frustum[4].normal, frustum[4].normal));
|
||||
frustum[4].normal[0] *= scale;
|
||||
frustum[4].normal[1] *= scale;
|
||||
frustum[4].normal[2] *= scale;
|
||||
frustum[4].dist *= -scale;
|
||||
|
||||
frustum[4].type = PLANE_ANYZ;
|
||||
frustum[4].signbits = SignbitsForPlane (&frustum[4]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void R_SetFrustum (void)
|
||||
|
|
|
@ -176,23 +176,36 @@ void Draw_AltFunString(float x, float y, const void *str)
|
|||
}
|
||||
|
||||
//Draws a marked up string no wider than $width virtual pixels.
|
||||
void Draw_FunStringWidth(float x, float y, const void *str, int width)
|
||||
void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean rightalign, qboolean highlight)
|
||||
{
|
||||
conchar_t buffer[2048];
|
||||
conchar_t *w = buffer;
|
||||
conchar_t *w;
|
||||
int px, py;
|
||||
int fw = 0;
|
||||
|
||||
width = (width*vid.rotpixelwidth)/vid.width;
|
||||
|
||||
COM_ParseFunString(CON_WHITEMASK, str, buffer, sizeof(buffer), false);
|
||||
COM_ParseFunString(highlight?CON_ALTMASK:CON_WHITEMASK, str, buffer, sizeof(buffer), false);
|
||||
|
||||
Font_BeginString(font_conchar, x, y, &px, &py);
|
||||
while(*w)
|
||||
if (rightalign)
|
||||
{
|
||||
for (w = buffer; *w; w++)
|
||||
{
|
||||
fw += Font_CharWidth(*w);
|
||||
}
|
||||
px += width;
|
||||
if (fw > width)
|
||||
fw = width;
|
||||
px -= fw;
|
||||
}
|
||||
|
||||
for (w = buffer; *w; w++)
|
||||
{
|
||||
width -= Font_CharWidth(*w);
|
||||
if (width < 0)
|
||||
return;
|
||||
px = Font_DrawChar(px, py, *w++);
|
||||
px = Font_DrawChar(px, py, *w);
|
||||
}
|
||||
Font_EndString(font_conchar);
|
||||
}
|
||||
|
@ -1293,12 +1306,12 @@ void Sbar_SortTeams (playerview_t *pv)
|
|||
|
||||
memset(teams, 0, sizeof(teams));
|
||||
// sort the teams
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
teams[i].plow = 999;
|
||||
|
||||
ownnum = Sbar_PlayerNum(pv);
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
playerteam[i] = -1;
|
||||
s = &cl.players[i];
|
||||
|
@ -2179,7 +2192,7 @@ static void Sbar_DrawTeamStatus(playerview_t *pv)
|
|||
if (track == -1 || !cl.spectator)
|
||||
track = pv->playernum;
|
||||
|
||||
for (p = 0; p < MAX_CLIENTS; p++)
|
||||
for (p = 0; p < cl.allocated_client_slots; p++)
|
||||
{
|
||||
if (pv->playernum == p) //self is not shown
|
||||
continue;
|
||||
|
@ -2539,7 +2552,7 @@ void Sbar_IntermissionNumber (float x, float y, int num, int digits, int color,
|
|||
}
|
||||
|
||||
#define COL_TEAM_LOWAVGHIGH COLUMN("low/avg/high", 12*8, {sprintf (num, "%3i/%3i/%3i", plow, pavg, phigh); Draw_FunString ( x, y, num); })
|
||||
#define COL_TEAM_TEAM COLUMN("team", 4*8, {Draw_FunStringWidth ( x, y, tm->team, 4*8); \
|
||||
#define COL_TEAM_TEAM COLUMN("team", 4*8, {Draw_FunStringWidth ( x, y, tm->team, 4*8, false, false); \
|
||||
if (!strncmp(cl.players[pv->playernum].team, tm->team, 16))\
|
||||
{\
|
||||
Draw_FunString ( x - 1*8, y, "^Ue010");\
|
||||
|
@ -2686,14 +2699,14 @@ ping time frags name
|
|||
int p = s->ping; \
|
||||
if (p < 0 || p > 999) p = 999; \
|
||||
sprintf(num, "%4i", p); \
|
||||
Draw_FunStringWidth(x, y, num, 4*8); \
|
||||
Draw_FunStringWidth(x, y, num, 4*8, false, false); \
|
||||
})
|
||||
|
||||
#define COLUMN_PL COLUMN(pl, 2*8, \
|
||||
{ \
|
||||
int p = s->pl; \
|
||||
sprintf(num, "%2i", p); \
|
||||
Draw_FunStringWidth(x, y, num, 2*8); \
|
||||
Draw_FunStringWidth(x, y, num, 2*8, false, false); \
|
||||
})
|
||||
#define COLUMN_TIME COLUMN(time, 4*8, \
|
||||
{ \
|
||||
|
@ -2703,14 +2716,14 @@ ping time frags name
|
|||
total = cl.servertime - s->entertime; \
|
||||
minutes = (int)total/60; \
|
||||
sprintf (num, "%4i", minutes); \
|
||||
Draw_FunStringWidth(x, y, num, 4*8); \
|
||||
Draw_FunStringWidth(x, y, num, 4*8, false, false); \
|
||||
})
|
||||
#define COLUMN_FRAGS COLUMN(frags, 5*8, \
|
||||
{ \
|
||||
int cx; int cy; \
|
||||
if (s->spectator) \
|
||||
{ \
|
||||
Draw_FunStringWidth(x, y, "spectator", 5*8); \
|
||||
Draw_FunStringWidth(x, y, "spectator", 5*8, false, false); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
|
@ -2745,15 +2758,15 @@ ping time frags name
|
|||
{ \
|
||||
if (!s->spectator) \
|
||||
{ \
|
||||
Draw_FunStringWidth(x, y, s->team, 4*8); \
|
||||
Draw_FunStringWidth(x, y, s->team, 4*8, false, false); \
|
||||
} \
|
||||
})
|
||||
#define COLUMN_NAME COLUMN(name, (cl.teamplay ? 12*8 : 16*8), {Draw_FunStringWidth(x, y, s->name, (cl.teamplay ? 12*8 : 16*8));})
|
||||
#define COLUMN_KILLS COLUMN(kils, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetKills(k)), 4*8);})
|
||||
#define COLUMN_TKILLS COLUMN(tkil, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTKills(k)), 4*8);})
|
||||
#define COLUMN_DEATHS COLUMN(dths, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetDeaths(k)), 4*8);})
|
||||
#define COLUMN_TOUCHES COLUMN(tchs, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTouches(k)), 4*8);})
|
||||
#define COLUMN_CAPS COLUMN(caps, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetCaptures(k)), 4*8);})
|
||||
#define COLUMN_NAME COLUMN(name, (cl.teamplay ? 12*8 : 16*8), {Draw_FunStringWidth(x, y, s->name, (cl.teamplay ? 12*8 : 16*8), false, false);})
|
||||
#define COLUMN_KILLS COLUMN(kils, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetKills(k)), 4*8, false, false);})
|
||||
#define COLUMN_TKILLS COLUMN(tkil, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTKills(k)), 4*8, false, false);})
|
||||
#define COLUMN_DEATHS COLUMN(dths, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetDeaths(k)), 4*8, false, false);})
|
||||
#define COLUMN_TOUCHES COLUMN(tchs, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetTouches(k)), 4*8, false, false);})
|
||||
#define COLUMN_CAPS COLUMN(caps, 4*8, {Draw_FunStringWidth(x, y, va("%4i", Stats_GetCaptures(k)), 4*8, false, false);})
|
||||
|
||||
|
||||
|
||||
|
@ -3185,11 +3198,11 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
|
|||
// team and name
|
||||
if (cl.teamplay)
|
||||
{
|
||||
Draw_FunStringWidth (x+48, y, s->team, 32);
|
||||
Draw_FunStringWidth (x+48+40, y, name, MAX_DISPLAYEDNAME*8);
|
||||
Draw_FunStringWidth (x+48, y, s->team, 32, false, false);
|
||||
Draw_FunStringWidth (x+48+40, y, name, MAX_DISPLAYEDNAME*8, false, false);
|
||||
}
|
||||
else
|
||||
Draw_FunStringWidth (x+48, y, name, MAX_DISPLAYEDNAME*8);
|
||||
Draw_FunStringWidth (x+48, y, name, MAX_DISPLAYEDNAME*8, false, false);
|
||||
y += 8;
|
||||
}
|
||||
|
||||
|
@ -3211,7 +3224,7 @@ static void Sbar_MiniDeathmatchOverlay (playerview_t *pv)
|
|||
tm = teams + k;
|
||||
|
||||
// draw pings
|
||||
Draw_FunStringWidth (x, y, tm->team, 32);
|
||||
Draw_FunStringWidth (x, y, tm->team, 32, false, false);
|
||||
|
||||
// draw total
|
||||
sprintf (num, "%5i", tm->frags);
|
||||
|
|
|
@ -621,10 +621,10 @@ void Skin_NextDownload (void)
|
|||
void Skin_FlushPlayers(void)
|
||||
{ //wipe the skin info
|
||||
int i;
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
cl.players[i].skin = NULL;
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
CL_NewTranslation(i);
|
||||
}
|
||||
|
||||
|
|
|
@ -987,6 +987,13 @@ void VARGS Sys_Error (const char *error, ...)
|
|||
SetHookState(false);
|
||||
#endif
|
||||
|
||||
TL_Shutdown();
|
||||
|
||||
#ifdef USE_MSVCRT_DEBUG
|
||||
if (_CrtDumpMemoryLeaks())
|
||||
OutputDebugStringA("Leaks detected\n");
|
||||
#endif
|
||||
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,13 +167,13 @@ void Validation_CheckIfResponse(char *text)
|
|||
|
||||
namelen = comp - text-1;
|
||||
|
||||
for (f_query_client = 0; f_query_client < MAX_CLIENTS; f_query_client++)
|
||||
for (f_query_client = 0; f_query_client < cl.allocated_client_slots; f_query_client++)
|
||||
{
|
||||
if (strlen(cl.players[f_query_client].name) == namelen)
|
||||
if (!strncmp(cl.players[f_query_client].name, text, namelen))
|
||||
break;
|
||||
}
|
||||
if (f_query_client == MAX_CLIENTS)
|
||||
if (f_query_client == cl.allocated_client_slots)
|
||||
return; //looks like a validation, but it's not from a known client.
|
||||
}
|
||||
|
||||
|
|
|
@ -1416,7 +1416,7 @@ void R_DrawNameTags(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
if (!nametagseen[i])
|
||||
continue;
|
||||
|
|
|
@ -881,7 +881,7 @@ static void CountNearbyPlayers(qboolean dead)
|
|||
|
||||
state = cl.inframes[cl.oldparsecount & UPDATE_MASK].playerstate;
|
||||
info = cl.players;
|
||||
for (i = 0; i < MAX_CLIENTS; i++, info++, state++) {
|
||||
for (i = 0; i < cl.allocated_client_slots; i++, info++, state++) {
|
||||
if (i != cl.playerview[SP].playernum && state->messagenum == cl.oldparsecount && !info->spectator && !ISDEAD(state->frame)) {
|
||||
if (cl.teamplay && !strcmp(info->team, TP_PlayerTeam()))
|
||||
vars.numfriendlies++;
|
||||
|
@ -1760,7 +1760,7 @@ int TP_CountPlayers (void)
|
|||
int i, count;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < MAX_CLIENTS ; i++) {
|
||||
for (i = 0; i < cl.allocated_client_slots ; i++) {
|
||||
if (cl.players[i].name[0] && !cl.players[i].spectator)
|
||||
count++;
|
||||
}
|
||||
|
@ -1779,7 +1779,7 @@ char *TP_EnemyTeam (void)
|
|||
static char enemyteam[MAX_INFO_KEY];
|
||||
char *myteam = TP_PlayerTeam();
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS ; i++) {
|
||||
for (i = 0; i < cl.allocated_client_slots ; i++) {
|
||||
if (cl.players[i].name[0] && !cl.players[i].spectator)
|
||||
{
|
||||
strcpy (enemyteam, cl.players[i].team);
|
||||
|
@ -1804,7 +1804,7 @@ char *TP_EnemyName (void)
|
|||
|
||||
myname = TP_PlayerName ();
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS ; i++) {
|
||||
for (i = 0; i < cl.allocated_client_slots ; i++) {
|
||||
if (cl.players[i].name[0] && !cl.players[i].spectator)
|
||||
{
|
||||
strcpy (enemyname, cl.players[i].name);
|
||||
|
@ -1945,7 +1945,7 @@ static void TP_Colourise_f (void)
|
|||
}
|
||||
|
||||
Skin_FlushPlayers();
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
cl.players[i].colourised = TP_FindColours(cl.players[i].name);
|
||||
CL_NewTranslation(i);
|
||||
|
@ -1989,7 +1989,7 @@ static void TP_TeamColor_f (void)
|
|||
cl_teambottomcolor = bottom;
|
||||
|
||||
if (qrenderer != QR_NONE) //make sure we have the renderer initialised...
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
CL_NewTranslation(i);
|
||||
}
|
||||
}
|
||||
|
@ -2030,7 +2030,7 @@ static void TP_EnemyColor_f (void)
|
|||
cl_enemybottomcolor = bottom;
|
||||
|
||||
if (qrenderer != QR_NONE) //make sure we have the renderer initialised...
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
CL_NewTranslation(i);
|
||||
}
|
||||
}
|
||||
|
@ -2098,7 +2098,7 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr)
|
|||
*offset = 0;
|
||||
*plr = NULL;
|
||||
|
||||
for (i=0, player=cl.players ; i < MAX_CLIENTS ; i++, player++)
|
||||
for (i=0, player=cl.players ; i < cl.allocated_client_slots ; i++, player++)
|
||||
{
|
||||
name = player->name;
|
||||
if (!(*name))
|
||||
|
@ -2562,7 +2562,7 @@ static int CountTeammates (void)
|
|||
|
||||
count = 0;
|
||||
myteam = cl.players[cl.playerview[SP].playernum].team;
|
||||
for (i=0, player=cl.players; i < MAX_CLIENTS ; i++, player++) {
|
||||
for (i=0, player=cl.players; i < cl.allocated_client_slots ; i++, player++) {
|
||||
if (player->name[0] && !player->spectator && (i != cl.playerview[SP].playernum)
|
||||
&& !strcmp(player->team, myteam))
|
||||
count++;
|
||||
|
@ -2588,7 +2588,7 @@ static qboolean CheckTrigger (void)
|
|||
|
||||
count = 0;
|
||||
myteam = cl.players[cl.playerview[SP].playernum].team;
|
||||
for (i = 0, player= cl.players; i < MAX_CLIENTS; i++, player++) {
|
||||
for (i = 0, player= cl.players; i < cl.allocated_client_slots; i++, player++) {
|
||||
if (player->name[0] && !player->spectator && i != cl.playerview[SP].playernum && !strcmp(player->team, myteam))
|
||||
count++;
|
||||
}
|
||||
|
@ -2845,7 +2845,7 @@ static char *Utils_TF_ColorToTeam_Failsafe(int color)
|
|||
memset(teams, 0, sizeof(teams));
|
||||
memset(teamcounts, 0, sizeof(teamcounts));
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < cl.allocated_client_slots; i++)
|
||||
{
|
||||
if (!cl.players[i].name[0] || cl.players[i].spectator)
|
||||
continue;
|
||||
|
@ -2974,7 +2974,7 @@ static void TP_FindPoint (void)
|
|||
|
||||
state = cl.inframes[cl.parsecount & UPDATE_MASK].playerstate;
|
||||
info = cl.players;
|
||||
for (j = 0; j < MAX_CLIENTS; j++, info++, state++)
|
||||
for (j = 0; j < cl.allocated_client_slots; j++, info++, state++)
|
||||
{
|
||||
if (state->messagenum != cl.parsecount || j == cl.playerview[SP].playernum || info->spectator)
|
||||
continue;
|
||||
|
|
|
@ -236,7 +236,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define CL_MASTER //query master servers and stuff for a dynamic server listing.
|
||||
#define R_XFLIP //allow view to be flipped horizontally
|
||||
#define TEXTEDITOR
|
||||
#define DDS //a sort of image file format.
|
||||
#define IMAGEFMT_DDS //a sort of image file format.
|
||||
#define IMAGEFMT_BLP //a sort of image file format.
|
||||
#ifndef RTLIGHTS
|
||||
#define RTLIGHTS //realtime lighting
|
||||
#endif
|
||||
|
@ -403,7 +404,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#ifndef SERVERONLY
|
||||
// undefine things not supported yet for D3D
|
||||
#if defined(D3DQUAKE) && !defined(GLQUAKE)
|
||||
#undef DDS // this is dumb
|
||||
#undef IMAGEFMT_DDS // this is dumb
|
||||
#undef IMAGEFMT_BLP // this is dumb
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -544,6 +544,8 @@ void Cmd_Exec_f (void)
|
|||
s+=3;
|
||||
}
|
||||
// don't execute anything if it was from server (either the stuffcmd/localcmd, or the file)
|
||||
if (!strcmp(name, "default.cfg") && !(Cmd_FromGamecode() || com_file_untrusted))
|
||||
Cbuf_InsertText ("\ncvar_lockdefaults 1\n", ((Cmd_FromGamecode() || com_file_untrusted) ? RESTRICT_INSECURE : Cmd_ExecLevel), true);
|
||||
Cbuf_InsertText (s, ((Cmd_FromGamecode() || com_file_untrusted) ? RESTRICT_INSECURE : Cmd_ExecLevel), true);
|
||||
FS_FreeFile(f);
|
||||
}
|
||||
|
@ -585,6 +587,53 @@ void Cmd_ShowAlias_f (void)
|
|||
Con_Printf("Alias doesn't exist\n");
|
||||
}
|
||||
|
||||
//returns a zoned string.
|
||||
char *Cmd_ParseMultiline(qboolean checkheader)
|
||||
{
|
||||
char *result;
|
||||
char *end;
|
||||
int in = checkheader?0:1;
|
||||
char *s;
|
||||
result = NULL;
|
||||
for(;;)
|
||||
{
|
||||
s = Cbuf_GetNext(Cmd_ExecLevel, false);
|
||||
if (!*s)
|
||||
{
|
||||
if (in)
|
||||
Con_Printf(CON_WARNING "WARNING: Multiline alias was not terminated\n");
|
||||
break;
|
||||
}
|
||||
while (*s <= ' ' && *s)
|
||||
s++;
|
||||
for (end = s + strlen(s)-1; end >= s && *end <= ' '; end--)
|
||||
*end = '\0';
|
||||
if (!strcmp(s, "{"))
|
||||
{
|
||||
in++;
|
||||
if (in == 1)
|
||||
continue; //don't embed the first one in the string, because that would be weird.
|
||||
}
|
||||
else if (!strcmp(s, "}"))
|
||||
{
|
||||
in--;
|
||||
if (!in)
|
||||
break; //phew
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
char *newv = (char*)Z_Malloc(strlen(result) + strlen(s) + 2);
|
||||
sprintf(newv, "%s;%s", result, s);
|
||||
Z_Free(result);
|
||||
result = newv;
|
||||
}
|
||||
else
|
||||
result = Z_StrDup(s);
|
||||
if (!in)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
===============
|
||||
Cmd_Alias_f
|
||||
|
@ -723,41 +772,7 @@ void Cmd_Alias_f (void)
|
|||
|
||||
if (multiline)
|
||||
{ //fun! MULTILINE ALIASES!!!!
|
||||
char *newv;
|
||||
char *end;
|
||||
int in = 1;
|
||||
a->value = NULL;
|
||||
for(;;)
|
||||
{
|
||||
s = Cbuf_GetNext(Cmd_ExecLevel, false);
|
||||
if (!*s)
|
||||
{
|
||||
Con_Printf(CON_WARNING "WARNING: Multiline alias was not terminated\n");
|
||||
break;
|
||||
}
|
||||
while (*s <= ' ' && *s)
|
||||
s++;
|
||||
for (end = s + strlen(s)-1; end >= s && *end <= ' '; end--)
|
||||
*end = '\0';
|
||||
if (!strcmp(s, "{"))
|
||||
in++;
|
||||
else if (!strcmp(s, "}"))
|
||||
{
|
||||
in--;
|
||||
if (!in)
|
||||
break; //phew
|
||||
}
|
||||
if (a->value)
|
||||
{
|
||||
newv = (char*)Z_Malloc(strlen(a->value) + strlen(s) + 2);
|
||||
sprintf(newv, "%s;%s", a->value, s);
|
||||
Z_Free(a->value);
|
||||
a->value = newv;
|
||||
}
|
||||
else
|
||||
a->value = Z_StrDup(s);
|
||||
}
|
||||
|
||||
a->value = Cmd_ParseMultiline(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -977,6 +992,8 @@ void Alias_WipeStuffedAliases(void)
|
|||
|
||||
void Cvar_List_f (void);
|
||||
void Cvar_Reset_f (void);
|
||||
void Cvar_LockDefaults_f(void);
|
||||
void Cvar_PurgeDefaults_f(void);
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
@ -2729,6 +2746,11 @@ void Cmd_set_f(void)
|
|||
Con_Printf ("Server tried setting %s cvar\n", var->name);
|
||||
return;
|
||||
}
|
||||
if (var->flags & CVAR_NOSET)
|
||||
{
|
||||
Con_Printf ("variable %s is readonly\n", var->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Cmd_FromGamecode())
|
||||
{
|
||||
|
@ -3074,6 +3096,8 @@ void Cmd_Init (void)
|
|||
Cmd_AddCommand ("macrolist", Cmd_MacroList_f);
|
||||
Cmd_AddCommand ("cvarlist", Cvar_List_f);
|
||||
Cmd_AddCommand ("cvarreset", Cvar_Reset_f);
|
||||
Cmd_AddCommand ("cvar_lockdefaults", Cvar_LockDefaults_f);
|
||||
Cmd_AddCommand ("cvar_purgedefaults", Cvar_PurgeDefaults_f);
|
||||
Cmd_AddCommand ("fs_flush", COM_RefreshFSCache_f);
|
||||
|
||||
Cmd_AddMacro("time", Macro_Time, true);
|
||||
|
@ -3090,7 +3114,7 @@ void Cmd_Init (void)
|
|||
Cvar_Register (&cl_warncmd, "Warnings");
|
||||
|
||||
#ifndef SERVERONLY
|
||||
rcon_level.ival = atof(rcon_level.defaultstr); //client is restricted to not be allowed to change restrictions.
|
||||
rcon_level.ival = atof(rcon_level.enginevalue); //client is restricted to not be allowed to change restrictions.
|
||||
#else
|
||||
Cvar_Register(&rcon_level, "Access controls"); //server gains versatility.
|
||||
#endif
|
||||
|
|
|
@ -101,6 +101,11 @@ char *VARGS Cmd_Argv (int arg);
|
|||
char *VARGS Cmd_Args (void);
|
||||
extern int Cmd_ExecLevel;
|
||||
|
||||
//if checkheader is false, an opening { is expected to already have been parsed.
|
||||
//otherwise returns the contents of the block much like c.
|
||||
//returns a zoned string.
|
||||
char *Cmd_ParseMultiline(qboolean checkheader);
|
||||
|
||||
extern cvar_t cmd_gamecodelevel, cmd_allowaccess;
|
||||
// The functions that execute commands get their parameters with these
|
||||
// functions. Cmd_Argv () will return an empty string, not a NULL
|
||||
|
|
|
@ -1459,8 +1459,15 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
|
|||
|
||||
if (!inf->groups)
|
||||
{
|
||||
Con_DPrintf("Model with no frames (%s)\n", e->model->name);
|
||||
return false;
|
||||
#ifdef SKELETALMODELS
|
||||
if (inf->ofs_skel_xyz && !inf->ofs_skel_weight)
|
||||
{}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Con_DPrintf("Model with no frames (%s)\n", e->model->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (meshcache.numcolours < inf->numverts)
|
||||
|
@ -1743,16 +1750,25 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//The whole reason why model loading is supported in the server.
|
||||
qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentsmask, trace_t *trace)
|
||||
static float PlaneNearest(vec3_t normal, vec3_t mins, vec3_t maxs)
|
||||
{
|
||||
galiasinfo_t *mod = Mod_Extradata(model);
|
||||
galiasgroup_t *group;
|
||||
galiaspose_t *pose;
|
||||
float result;
|
||||
return 128;
|
||||
#if 1
|
||||
result = fabs(normal[0] * maxs[0]);
|
||||
result += fabs(normal[1] * maxs[1]);
|
||||
result += fabs(normal[2] * maxs[2]);
|
||||
#else
|
||||
result = normal[0] * ((normal[0] < 0)?mins[0]:maxs[0]);
|
||||
result += normal[1] * ((normal[1] < 0)?mins[1]:maxs[1]);
|
||||
result += normal[2] * ((normal[2] < 0)?mins[2]:maxs[2]);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static qboolean Mod_Trace_Trisoup(vecV_t *posedata, index_t *indexes, int numindexes, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace)
|
||||
{
|
||||
qboolean impacted = false;
|
||||
int i;
|
||||
|
||||
float *p1, *p2, *p3;
|
||||
|
@ -1762,88 +1778,166 @@ qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3],
|
|||
|
||||
float planedist;
|
||||
float diststart, distend;
|
||||
float expand;
|
||||
|
||||
float frac;
|
||||
// float temp;
|
||||
|
||||
vec3_t impactpoint;
|
||||
|
||||
for (i = 0; i < numindexes; i+=3)
|
||||
{
|
||||
p1 = posedata[indexes[i+0]];
|
||||
p2 = posedata[indexes[i+1]];
|
||||
p3 = posedata[indexes[i+2]];
|
||||
|
||||
VectorSubtract(p1, p2, edge1);
|
||||
VectorSubtract(p3, p2, edge2);
|
||||
CrossProduct(edge1, edge2, normal);
|
||||
|
||||
expand = PlaneNearest(normal, mins, maxs);
|
||||
planedist = DotProduct(p1, normal);
|
||||
diststart = DotProduct(start, normal);
|
||||
if (diststart <= planedist)
|
||||
continue; //start on back side.
|
||||
distend = DotProduct(end, normal);
|
||||
if (distend >= planedist)
|
||||
continue; //end on front side (as must start - doesn't cross).
|
||||
|
||||
frac = (diststart - planedist - 1) / (diststart-distend);
|
||||
if (frac < 0)
|
||||
frac = 0;
|
||||
|
||||
if (frac >= trace->fraction) //already found one closer.
|
||||
continue;
|
||||
|
||||
impactpoint[0] = start[0] + frac*(end[0] - start[0]);
|
||||
impactpoint[1] = start[1] + frac*(end[1] - start[1]);
|
||||
impactpoint[2] = start[2] + frac*(end[2] - start[2]);
|
||||
|
||||
// temp = DotProduct(impactpoint, normal)-planedist;
|
||||
|
||||
CrossProduct(edge1, normal, edgenormal);
|
||||
// temp = DotProduct(impactpoint, edgenormal)-DotProduct(p2, edgenormal);
|
||||
if (DotProduct(impactpoint, edgenormal) > DotProduct(p2, edgenormal))
|
||||
continue;
|
||||
|
||||
CrossProduct(normal, edge2, edgenormal);
|
||||
if (DotProduct(impactpoint, edgenormal) > DotProduct(p3, edgenormal))
|
||||
continue;
|
||||
|
||||
VectorSubtract(p1, p3, edge3);
|
||||
CrossProduct(normal, edge3, edgenormal);
|
||||
if (DotProduct(impactpoint, edgenormal) > DotProduct(p1, edgenormal))
|
||||
continue;
|
||||
|
||||
trace->fraction = frac;
|
||||
VectorCopy(impactpoint, trace->endpos);
|
||||
VectorCopy(normal, trace->plane.normal);
|
||||
impacted = true;
|
||||
}
|
||||
return impacted;
|
||||
}
|
||||
|
||||
//The whole reason why model loading is supported in the server.
|
||||
qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentsmask, trace_t *trace)
|
||||
{
|
||||
galiasinfo_t *mod = Mod_Extradata(model);
|
||||
galiasgroup_t *group;
|
||||
galiaspose_t *pose;
|
||||
|
||||
float frac;
|
||||
// float temp;
|
||||
|
||||
vecV_t *posedata;
|
||||
index_t *indexes;
|
||||
int surfnum = 0;
|
||||
int cursurfnum = -1;
|
||||
|
||||
vec3_t start_l, end_l;
|
||||
|
||||
if (axis)
|
||||
{
|
||||
start_l[0] = DotProduct(start, axis[0]);
|
||||
start_l[1] = DotProduct(start, axis[1]);
|
||||
start_l[2] = DotProduct(start, axis[2]);
|
||||
end_l[0] = DotProduct(end, axis[0]);
|
||||
end_l[1] = DotProduct(end, axis[1]);
|
||||
end_l[2] = DotProduct(end, axis[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorCopy(start, start_l);
|
||||
VectorCopy(end, end_l);
|
||||
}
|
||||
|
||||
while(mod)
|
||||
{
|
||||
indexes = mod->ofs_indexes;
|
||||
group = mod->groupofs;
|
||||
pose = group[0].poseofs;
|
||||
posedata = pose->ofsverts;
|
||||
#ifdef SKELETALMODELS
|
||||
if (mod->numbones && mod->shares_verts != cursurfnum)
|
||||
if (!mod->groups)
|
||||
{
|
||||
float bonepose[MAX_BONES][12];
|
||||
posedata = alloca(mod->numverts*sizeof(vecV_t));
|
||||
frac = 1;
|
||||
if (group->isheirachical)
|
||||
{
|
||||
if (mod->shares_bones != cursurfnum)
|
||||
R_LerpBones(&frac, (float**)posedata, 1, mod->ofsbones, mod->numbones, bonepose);
|
||||
Alias_TransformVerticies_SW((float*)bonepose, mod->ofsswtransforms, mod->numswtransforms, posedata, NULL);
|
||||
}
|
||||
else
|
||||
Alias_TransformVerticies_SW((float*)posedata, mod->ofsswtransforms, mod->numswtransforms, posedata, NULL);
|
||||
|
||||
cursurfnum = mod->shares_verts;
|
||||
//certain models have no possibility of animation.
|
||||
posedata = mod->ofs_skel_xyz;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
for (i = 0; i < mod->numindexes; i+=3)
|
||||
{
|
||||
p1 = posedata[indexes[i+0]];
|
||||
p2 = posedata[indexes[i+1]];
|
||||
p3 = posedata[indexes[i+2]];
|
||||
group = mod->groupofs;
|
||||
pose = group[0].poseofs;
|
||||
posedata = pose->ofsverts;
|
||||
#ifdef SKELETALMODELS
|
||||
if (mod->numbones && mod->shares_verts != cursurfnum)
|
||||
{
|
||||
float bonepose[MAX_BONES][12];
|
||||
posedata = alloca(mod->numverts*sizeof(vecV_t));
|
||||
frac = 1;
|
||||
if (group->isheirachical)
|
||||
{
|
||||
if (mod->shares_bones != cursurfnum)
|
||||
R_LerpBones(&frac, (float**)posedata, 1, mod->ofsbones, mod->numbones, bonepose);
|
||||
Alias_TransformVerticies_SW((float*)bonepose, mod->ofsswtransforms, mod->numswtransforms, posedata, NULL);
|
||||
}
|
||||
else
|
||||
Alias_TransformVerticies_SW((float*)posedata, mod->ofsswtransforms, mod->numswtransforms, posedata, NULL);
|
||||
|
||||
VectorSubtract(p1, p2, edge1);
|
||||
VectorSubtract(p3, p2, edge2);
|
||||
CrossProduct(edge1, edge2, normal);
|
||||
cursurfnum = mod->shares_verts;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
planedist = DotProduct(p1, normal);
|
||||
diststart = DotProduct(start, normal);
|
||||
if (diststart <= planedist)
|
||||
continue; //start on back side.
|
||||
distend = DotProduct(end, normal);
|
||||
if (distend >= planedist)
|
||||
continue; //end on front side (as must start - doesn't cross).
|
||||
if (Mod_Trace_Trisoup(posedata, indexes, mod->numindexes, start_l, end_l, mins, maxs, trace) && axis)
|
||||
{
|
||||
if (axis)
|
||||
{
|
||||
vec3_t iaxis[3];
|
||||
vec3_t norm;
|
||||
Matrix3x3_RM_Invert_Simple((void *)axis, iaxis);
|
||||
VectorCopy(trace->plane.normal, norm);
|
||||
trace->plane.normal[0] = DotProduct(norm, iaxis[0]);
|
||||
trace->plane.normal[1] = DotProduct(norm, iaxis[1]);
|
||||
trace->plane.normal[2] = DotProduct(norm, iaxis[2]);
|
||||
}
|
||||
|
||||
frac = (diststart - planedist) / (diststart-distend);
|
||||
// frac = traceinfo.truefraction;
|
||||
/*
|
||||
diststart = DotProduct(traceinfo.start, trace->plane.normal);
|
||||
distend = DotProduct(traceinfo.end, trace->plane.normal);
|
||||
if (diststart == distend)
|
||||
frac = 0;
|
||||
else
|
||||
{
|
||||
frac = (diststart - trace->plane.dist) / (diststart-distend);
|
||||
if (frac < 0)
|
||||
frac = 0;
|
||||
else if (frac > 1)
|
||||
frac = 1;
|
||||
}*/
|
||||
|
||||
if (frac >= trace->fraction) //already found one closer.
|
||||
continue;
|
||||
|
||||
impactpoint[0] = start[0] + frac*(end[0] - start[0]);
|
||||
impactpoint[1] = start[1] + frac*(end[1] - start[1]);
|
||||
impactpoint[2] = start[2] + frac*(end[2] - start[2]);
|
||||
|
||||
// temp = DotProduct(impactpoint, normal)-planedist;
|
||||
|
||||
CrossProduct(edge1, normal, edgenormal);
|
||||
// temp = DotProduct(impactpoint, edgenormal)-DotProduct(p2, edgenormal);
|
||||
if (DotProduct(impactpoint, edgenormal) > DotProduct(p2, edgenormal))
|
||||
continue;
|
||||
|
||||
CrossProduct(normal, edge2, edgenormal);
|
||||
if (DotProduct(impactpoint, edgenormal) > DotProduct(p3, edgenormal))
|
||||
continue;
|
||||
|
||||
VectorSubtract(p1, p3, edge3);
|
||||
CrossProduct(normal, edge3, edgenormal);
|
||||
if (DotProduct(impactpoint, edgenormal) > DotProduct(p1, edgenormal))
|
||||
continue;
|
||||
|
||||
trace->fraction = frac;
|
||||
VectorCopy(impactpoint, trace->endpos);
|
||||
VectorCopy(normal, trace->plane.normal);
|
||||
/*okay, this is where it hits this plane*/
|
||||
// trace->endpos[0] = traceinfo.start[0] + frac*(traceinfo.end[0] - traceinfo.start[0]);
|
||||
// trace->endpos[1] = traceinfo.start[1] + frac*(traceinfo.end[1] - traceinfo.start[1]);
|
||||
// trace->endpos[2] = traceinfo.start[2] + frac*(traceinfo.end[2] - traceinfo.start[2]);
|
||||
}
|
||||
|
||||
mod = mod->nextsurf;
|
||||
|
@ -2307,7 +2401,7 @@ void Mod_ParseQ3SkinFile(char *out, char *surfname, char *modelname, int skinnum
|
|||
}
|
||||
|
||||
#if defined(D3DQUAKE) || defined(GLQUAKE)
|
||||
shader_t *Mod_LoadSkinFile(shader_t **shaders, char *surfacename, int skinnumber, unsigned char *rawdata, int width, int height, unsigned char *palette)
|
||||
shader_t *Mod_LoadSkinFile(char *surfacename, int skinnumber, unsigned char *rawdata, int width, int height, unsigned char *palette)
|
||||
{
|
||||
shader_t *shader;
|
||||
char shadername[MAX_QPATH];
|
||||
|
@ -2797,7 +2891,7 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran
|
|||
}
|
||||
#endif
|
||||
|
||||
qboolean Mod_LoadQ1Model (model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadQ1Model (model_t *mod, void *buffer)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
vec2_t *st_array;
|
||||
|
@ -3174,7 +3268,7 @@ static void Q2_LoadSkins(md2_t *pq2inmodel, char *skins)
|
|||
}
|
||||
|
||||
#define MD2_MAX_TRIANGLES 4096
|
||||
qboolean Mod_LoadQ2Model (model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadQ2Model (model_t *mod, void *buffer)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
dmd2stvert_t *pinstverts;
|
||||
|
@ -3965,7 +4059,7 @@ typedef struct {
|
|||
} md3Shader_t;
|
||||
//End of Tenebrae 'assistance'
|
||||
|
||||
qboolean Mod_LoadQ3Model(model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadQ3Model(model_t *mod, void *buffer)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
galiasskin_t *skin;
|
||||
|
@ -4294,7 +4388,7 @@ typedef struct zymvertex_s
|
|||
|
||||
//this can generate multiple meshes (one for each shader).
|
||||
//but only one set of transforms are ever generated.
|
||||
qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadZymoticModel(model_t *mod, void *buffer)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
galiasskin_t *skin;
|
||||
|
@ -4483,7 +4577,7 @@ qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer)
|
|||
skin[j].numshaders = 1; //non-sequenced skins.
|
||||
skin[j].ofsshaders = shaders;
|
||||
|
||||
Mod_LoadSkinFile(shaders, surfname, j, NULL, 0, 0, NULL);
|
||||
shaders[0] = Mod_LoadSkinFile(surfname, j, NULL, 0, 0, NULL);
|
||||
}
|
||||
|
||||
root[i].ofsskins = skin;
|
||||
|
@ -4643,7 +4737,7 @@ typedef struct pskanimkeys_s
|
|||
} pskanimkeys_t;
|
||||
|
||||
|
||||
qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadPSKModel(model_t *mod, void *buffer)
|
||||
{
|
||||
pskchunk_t *chunk;
|
||||
unsigned int pos = 0;
|
||||
|
@ -5316,7 +5410,7 @@ typedef struct dpmvertex_s
|
|||
// immediately followed by 1 or more dpmbonevert_t structures
|
||||
} dpmvertex_t;
|
||||
|
||||
qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadDarkPlacesModel(model_t *mod, void *buffer)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
galiasskin_t *skin;
|
||||
|
@ -5540,7 +5634,7 @@ qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer)
|
|||
skin[j].numshaders = 1; //non-sequenced skins.
|
||||
skin[j].ofsshaders = shaders;
|
||||
|
||||
Mod_LoadSkinFile(shaders, mesh->shadername, j, NULL, 0, 0, NULL);
|
||||
shaders[0] = Mod_LoadSkinFile(mesh->shadername, j, NULL, 0, 0, NULL);
|
||||
}
|
||||
|
||||
m->ofsskins = skin;
|
||||
|
@ -6694,7 +6788,7 @@ galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer, char *modname)
|
|||
#undef EXPECT
|
||||
}
|
||||
|
||||
qboolean Mod_LoadMD5MeshModel(model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadMD5MeshModel(model_t *mod, void *buffer)
|
||||
{
|
||||
galiasinfo_t *root;
|
||||
|
||||
|
@ -6732,7 +6826,7 @@ clampgroup test/idle1.md5anim
|
|||
frames test/idle1.md5anim
|
||||
|
||||
*/
|
||||
qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadCompositeAnim(model_t *mod, void *buffer)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -6932,3 +7026,36 @@ char *Mod_GetBoneName(struct model_s *model, int bonenum)
|
|||
return "";
|
||||
}
|
||||
#endif //#if defined(D3DQUAKE) || defined(GLQUAKE)
|
||||
|
||||
|
||||
void Alias_Register(void)
|
||||
{
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 Model (mdl)", IDPOLYHEADER, Mod_LoadQ1Model);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Hexen2 Model (mdl)", RAPOLYHEADER, Mod_LoadQ1Model);
|
||||
#ifdef MD2MODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake2 Model (md2)", MD2IDALIASHEADER, Mod_LoadQ2Model);
|
||||
#endif
|
||||
#ifdef MD3MODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake3 Model (md3)", MD3_IDENT, Mod_LoadQ3Model);
|
||||
#endif
|
||||
#ifdef HALFLIFEMODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Half-Life Model (mdl)", (('T'<<24)+('S'<<16)+('D'<<8)+'I'), Mod_LoadHLModel);
|
||||
#endif
|
||||
|
||||
#ifdef ZYMOTICMODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Zymotic Model (zym)", (('O'<<24)+('M'<<16)+('Y'<<8)+'Z'), Mod_LoadZymoticModel);
|
||||
#endif
|
||||
#ifdef DPMMODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "DarkPlaces Model (dpm)", (('K'<<24)+('R'<<16)+('A'<<8)+'D'), Mod_LoadDarkPlacesModel);
|
||||
#endif
|
||||
#ifdef PSKMODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Unreal Interchange Model (psk)", ('A'<<0)+('C'<<8)+('T'<<16)+('R'<<24), Mod_LoadPSKModel);
|
||||
#endif
|
||||
#ifdef INTERQUAKEMODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Inter-Quake Model (iqm)", ('I'<<0)+('N'<<8)+('T'<<16)+('E'<<24), Mod_LoadPSKModel);
|
||||
#endif
|
||||
#ifdef MD5MODELS
|
||||
Mod_RegisterModelFormatText(NULL, "MD5 Mesh/Anim (md5mesh)", "MD5Version", Mod_LoadMD5MeshModel);
|
||||
Mod_RegisterModelFormatText(NULL, "External Anim", "EXTERNALANIM", Mod_LoadCompositeAnim);
|
||||
#endif
|
||||
}
|
|
@ -161,32 +161,11 @@ void Alias_TransformVerticies(float *bonepose, galisskeletaltransforms_t *weight
|
|||
qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, int surfnum, entity_t *e, qboolean allowskel);
|
||||
void Alias_FlushCache(void);
|
||||
void Alias_Shutdown(void);
|
||||
void Alias_Register(void);
|
||||
|
||||
void Mod_DoCRC(model_t *mod, char *buffer, int buffersize);
|
||||
|
||||
qboolean Mod_LoadQ1Model (model_t *mod, void *buffer);
|
||||
#ifdef MD2MODELS
|
||||
qboolean Mod_LoadQ2Model (model_t *mod, void *buffer);
|
||||
#endif
|
||||
#ifdef MD3MODELS
|
||||
qboolean Mod_LoadQ3Model(model_t *mod, void *buffer);
|
||||
#endif
|
||||
#ifdef ZYMOTICMODELS
|
||||
qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer);
|
||||
#endif
|
||||
#ifdef DPMMODELS
|
||||
qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer);
|
||||
#endif
|
||||
#ifdef PSKMODELS
|
||||
qboolean Mod_LoadPSKModel(model_t *mod, void *buffer);
|
||||
#endif
|
||||
#ifdef INTERQUAKEMODELS
|
||||
qboolean Mod_LoadInterQuakeModel(model_t *mod, void *buffer);
|
||||
#endif
|
||||
#ifdef MD5MODELS
|
||||
qboolean Mod_LoadMD5MeshModel(model_t *mod, void *buffer);
|
||||
qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer);
|
||||
#endif
|
||||
qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer);
|
||||
#ifdef MAP_PROC
|
||||
qboolean Mod_LoadMap_Proc(model_t *mode, void *buffer);
|
||||
#endif
|
||||
|
|
|
@ -3809,6 +3809,7 @@ void COM_ParsePlusSets (void)
|
|||
}
|
||||
}
|
||||
|
||||
void Cvar_DefaultFree(char *str);
|
||||
/*
|
||||
================
|
||||
COM_CheckRegistered
|
||||
|
@ -3837,8 +3838,14 @@ void COM_CheckRegistered (void)
|
|||
|
||||
newdef = static_registered?"1":"0";
|
||||
|
||||
if (strcmp(registered.defaultstr, newdef))
|
||||
if (strcmp(registered.enginevalue, newdef))
|
||||
{
|
||||
if (registered.defaultstr != registered.enginevalue)
|
||||
{
|
||||
Cvar_DefaultFree(registered.defaultstr);
|
||||
registered.defaultstr = NULL;
|
||||
}
|
||||
registered.enginevalue = newdef;
|
||||
registered.defaultstr = newdef;
|
||||
Cvar_ForceSet(®istered, newdef);
|
||||
if (static_registered)
|
||||
|
@ -4002,7 +4009,9 @@ void COM_Version_f (void)
|
|||
Con_Printf("Compiled with Cygwin\n");
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __clang__
|
||||
Con_Printf("Compiled with clang version: %i.%i.%i (%s)\n",__clang_major__, __clang_minor__, __clang_patchlevel__, __VERSION__);
|
||||
#elif defined(__GNUC__)
|
||||
Con_Printf("Compiled with GCC version: %i.%i.%i (%s)\n",__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__, __VERSION__);
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
|
@ -4225,6 +4234,7 @@ void COM_Init (void)
|
|||
|
||||
|
||||
|
||||
nullentitystate.hexen2flags = SCALE_ORIGIN_ORIGIN;
|
||||
nullentitystate.colormod[0] = 32;
|
||||
nullentitystate.colormod[1] = 32;
|
||||
nullentitystate.colormod[2] = 32;
|
||||
|
|
|
@ -366,7 +366,7 @@ void Cvar_List_f (void)
|
|||
}
|
||||
|
||||
// print default value
|
||||
if (listflags & CLF_DEFAULT)
|
||||
if (cmd->defaultstr && (listflags & CLF_DEFAULT))
|
||||
Con_Printf(", default \"%s\"", cmd->defaultstr);
|
||||
|
||||
// print alternate name
|
||||
|
@ -407,6 +407,48 @@ void Cvar_List_f (void)
|
|||
}
|
||||
}
|
||||
|
||||
void Cvar_LockDefaults_f(void)
|
||||
{
|
||||
cvar_group_t *grp;
|
||||
cvar_t *cmd;
|
||||
for (grp=cvar_groups ; grp ; grp=grp->next)
|
||||
{
|
||||
for (cmd=grp->cvars ; cmd ; cmd=cmd->next)
|
||||
{
|
||||
if (cmd->flags & (CVAR_NOSET | CVAR_CHEAT))
|
||||
continue;
|
||||
|
||||
if (strcmp(cmd->string, cmd->defaultstr))
|
||||
{
|
||||
if (cmd->defaultstr != cmd->enginevalue)
|
||||
Cvar_DefaultFree(cmd->defaultstr);
|
||||
cmd->defaultstr = Cvar_DefaultAlloc(cmd->string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void Cvar_PurgeDefaults_f(void)
|
||||
{
|
||||
cvar_group_t *grp;
|
||||
cvar_t *cmd;
|
||||
for (grp=cvar_groups ; grp ; grp=grp->next)
|
||||
{
|
||||
for (cmd=grp->cvars ; cmd ; cmd=cmd->next)
|
||||
{
|
||||
if (!cmd->enginevalue)
|
||||
continue; //can't reset the cvar's default if its an engine cvar.
|
||||
if (cmd->flags & CVAR_NOSET)
|
||||
continue;
|
||||
|
||||
if (cmd->defaultstr != cmd->enginevalue)
|
||||
{
|
||||
Cvar_DefaultFree(cmd->defaultstr);
|
||||
cmd->defaultstr = cmd->enginevalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define CRF_ALTNAME 0x1
|
||||
void Cvar_Reset_f (void)
|
||||
{
|
||||
|
@ -416,6 +458,8 @@ void Cvar_Reset_f (void)
|
|||
char *var;
|
||||
char *search, *gsearch;
|
||||
char strtmp[512];
|
||||
char *resetval;
|
||||
char *pendingval;
|
||||
|
||||
search = gsearch = NULL;
|
||||
exclflags = 0;
|
||||
|
@ -479,9 +523,9 @@ void Cvar_Reset_f (void)
|
|||
if (gsearch)
|
||||
Q_strlwr(gsearch);
|
||||
|
||||
if (!strcmp(search, "*"))
|
||||
if (search && !strcmp(search, "*"))
|
||||
search = NULL;
|
||||
if (!strcmp(gsearch, "*"))
|
||||
if (gsearch && !strcmp(gsearch, "*"))
|
||||
gsearch = NULL;
|
||||
|
||||
for (grp=cvar_groups ; grp ; grp=grp->next)
|
||||
|
@ -526,8 +570,19 @@ void Cvar_Reset_f (void)
|
|||
|
||||
if ((cmd->flags & CVAR_NOSET) && !search)
|
||||
continue;
|
||||
// reset cvar to default
|
||||
Cvar_Set(cmd, cmd->defaultstr);
|
||||
|
||||
// reset cvar to default only if its okay to do so
|
||||
if (cmd->defaultstr)
|
||||
resetval = cmd->defaultstr;
|
||||
else if (cmd->enginevalue)
|
||||
resetval = cmd->enginevalue;
|
||||
else
|
||||
continue; //no idea what to reset it to.
|
||||
pendingval = cmd->string;
|
||||
if (cmd->latched_string)
|
||||
pendingval = cmd->latched_string;
|
||||
if (strcmp(resetval, pendingval))
|
||||
Cvar_Set(cmd, resetval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -938,7 +993,7 @@ void Cvar_Free(cvar_t *tbf)
|
|||
}
|
||||
unlinked:
|
||||
Z_Free(tbf->string);
|
||||
if (tbf->flags & CVAR_FREEDEFAULT)
|
||||
if (tbf->defaultstr != tbf->enginevalue)
|
||||
Cvar_DefaultFree(tbf->defaultstr);
|
||||
if (tbf->latched_string)
|
||||
Z_Free(tbf->latched_string);
|
||||
|
@ -964,8 +1019,12 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname)
|
|||
|
||||
if (variable->defaultstr)
|
||||
initial = variable->defaultstr;
|
||||
else
|
||||
else if (variable->enginevalue)
|
||||
initial = variable->enginevalue;
|
||||
else if (variable->string)
|
||||
initial = variable->string;
|
||||
else
|
||||
initial = "";
|
||||
|
||||
// check to see if it has already been defined
|
||||
old = Cvar_FindVar (variable->name);
|
||||
|
@ -987,7 +1046,7 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname)
|
|||
variable->string = (char*)Z_Malloc (1);
|
||||
|
||||
//cheat prevention - engine set default is the one that stays.
|
||||
if (variable->flags & CVAR_FREEDEFAULT)
|
||||
if (initial != variable->enginevalue)
|
||||
variable->defaultstr = Cvar_DefaultAlloc(initial);
|
||||
else
|
||||
variable->defaultstr = initial;
|
||||
|
@ -1031,7 +1090,7 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname)
|
|||
|
||||
variable->string = NULL;
|
||||
|
||||
if (variable->flags & CVAR_FREEDEFAULT)
|
||||
if (initial != variable->enginevalue)
|
||||
variable->defaultstr = Cvar_DefaultAlloc(initial);
|
||||
else
|
||||
variable->defaultstr = initial;
|
||||
|
@ -1065,7 +1124,7 @@ cvar_t *Cvar_Get(const char *name, const char *defaultvalue, int flags, const ch
|
|||
var->name = (char *)(var+1);
|
||||
strcpy(var->name, name);
|
||||
var->string = (char*)defaultvalue;
|
||||
var->flags = flags|CVAR_POINTER|CVAR_FREEDEFAULT|CVAR_USERCREATED;
|
||||
var->flags = flags|CVAR_POINTER|CVAR_USERCREATED;
|
||||
|
||||
if (!Cvar_Register(var, group))
|
||||
return NULL;
|
||||
|
@ -1147,16 +1206,18 @@ qboolean Cvar_Command (int level)
|
|||
Con_Printf ("\"%s\" is %s\n", v->name, COM_QuotedString(v->latched_string, buffer, sizeof(buffer)));
|
||||
Con_Printf ("Effective value is %s\n", COM_QuotedString(v->string, buffer, sizeof(buffer)));
|
||||
}
|
||||
Con_Printf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer)));
|
||||
if (v->defaultstr)
|
||||
Con_Printf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcmp(v->string, v->defaultstr))
|
||||
if (v->defaultstr && !strcmp(v->string, v->defaultstr))
|
||||
Con_Printf ("\"%s\" is %s (default)\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer)));
|
||||
else
|
||||
{
|
||||
Con_Printf ("\"%s\" is %s\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer)));
|
||||
Con_Printf("Default: %s\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer)));
|
||||
if (v->defaultstr)
|
||||
Con_Printf("Default: %s\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer)));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -1184,7 +1245,7 @@ qboolean Cvar_Command (int level)
|
|||
{
|
||||
if (Cmd_FromGamecode())
|
||||
{
|
||||
if (!strcmp(v->defaultstr, str)) //returning to default
|
||||
if (!v->defaultstr || !strcmp(v->defaultstr, str)) //returning to default
|
||||
{
|
||||
v->flags &= ~CVAR_SERVEROVERRIDE;
|
||||
if (v->latched_string)
|
||||
|
@ -1200,7 +1261,7 @@ qboolean Cvar_Command (int level)
|
|||
}
|
||||
else if (Cmd_FromGamecode())
|
||||
{//it's not latched yet
|
||||
if (strcmp(v->defaultstr, str))
|
||||
if (v->defaultstr && strcmp(v->defaultstr, str))
|
||||
{ //lock the cvar, unless it's going to it's default value.
|
||||
Cvar_LockFromServer(v, str);
|
||||
return true;
|
||||
|
@ -1325,7 +1386,7 @@ void Cvar_Shutdown(void)
|
|||
var = cvar_groups->cvars;
|
||||
cvar_groups->cvars = var->next;
|
||||
|
||||
if (var->flags & CVAR_FREEDEFAULT)
|
||||
if (var->defaultstr != var->enginevalue)
|
||||
{
|
||||
Cvar_DefaultFree(var->defaultstr);
|
||||
var->defaultstr = NULL;
|
||||
|
|
|
@ -58,24 +58,25 @@ interface from being ambiguous.
|
|||
typedef struct cvar_s
|
||||
{
|
||||
//must match q2's definition
|
||||
char *name;
|
||||
char *string;
|
||||
char *latched_string; // for CVAR_LATCH vars
|
||||
int flags;
|
||||
int modified; // increased each time the cvar is changed
|
||||
float value;
|
||||
struct cvar_s *next;
|
||||
char *name;
|
||||
char *string;
|
||||
char *latched_string; // for CVAR_LATCH vars
|
||||
unsigned int flags;
|
||||
int modified; // increased each time the cvar is changed
|
||||
float value;
|
||||
struct cvar_s *next;
|
||||
|
||||
//free style :)
|
||||
char *name2;
|
||||
char *name2;
|
||||
|
||||
void (*callback) (struct cvar_s *var, char *oldvalue);
|
||||
char *description;
|
||||
char *defaultstr; //default
|
||||
void (*callback) (struct cvar_s *var, char *oldvalue);
|
||||
char *description;
|
||||
char *enginevalue; //when changing manifest dir, the cvar will be reset to this value. never freed.
|
||||
char *defaultstr; //this is the current mod's default value. set on first update.
|
||||
|
||||
|
||||
int ival;
|
||||
qbyte restriction;
|
||||
int ival;
|
||||
qbyte restriction;
|
||||
|
||||
#ifdef HLSERVER
|
||||
struct hlcvar_s *hlcvar;
|
||||
|
@ -122,10 +123,10 @@ typedef struct cvar_group_s
|
|||
|
||||
//freestyle
|
||||
#define CVAR_POINTER (1<<5) // q2 style. May be converted to q1 if needed. These are often specified on the command line and then converted into q1 when registered properly.
|
||||
#define CVAR_FREEDEFAULT (1<<6) //the default string was malloced/needs to be malloced, free on unregister
|
||||
#define CVAR_UNUSED (1<<6) //the default string was malloced/needs to be malloced, free on unregister
|
||||
#define CVAR_NOTFROMSERVER (1<<7) // the console will ignore changes to cvars if set at from the server or any gamecode. This is to protect against security flaws - like qterm
|
||||
#define CVAR_USERCREATED (1<<8) //write a 'set' or 'seta' in front of the var name.
|
||||
#define CVAR_CHEAT (1<<9) //latch to the default, unless cheats are enabled.
|
||||
#define CVAR_CHEAT (1<<9) //latch to the default, unless cheats are enabled.
|
||||
#define CVAR_SEMICHEAT (1<<10) //if strict ruleset, force to 0/blank.
|
||||
#define CVAR_RENDERERLATCH (1<<11) //requires a vid_restart to reapply.
|
||||
#define CVAR_SERVEROVERRIDE (1<<12) //the server has overridden out local value - should probably be called SERVERLATCH
|
||||
|
@ -135,6 +136,8 @@ typedef struct cvar_group_s
|
|||
#define CVAR_SHADERSYSTEM (1<<16) //change flushes shaders.
|
||||
#define CVAR_TELLGAMECODE (1<<17) //tells the gamecode when it has changed, does not prevent changing, added as an optimisation
|
||||
|
||||
#define CVAR_CONFIGDEFAULT (1<<18) //this cvar's default value has been changed to match a config.
|
||||
|
||||
#define CVAR_LASTFLAG CVAR_SHADERSYSTEM
|
||||
|
||||
#define CVAR_LATCHMASK (CVAR_LATCH|CVAR_RENDERERLATCH|CVAR_SERVEROVERRIDE|CVAR_CHEAT|CVAR_SEMICHEAT) //you're only allowed one of these.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#endif
|
||||
|
||||
hashtable_t filesystemhash;
|
||||
qboolean blockcache = true;
|
||||
qboolean com_fschanged = true;
|
||||
static unsigned int fs_restarts;
|
||||
extern cvar_t com_fs_cache;
|
||||
|
@ -339,7 +340,7 @@ static void FS_Manifest_ParseTokens(ftemanifest_t *man)
|
|||
char *newdir = Cmd_Argv(1);
|
||||
|
||||
//reject various evil path arguments.
|
||||
if (!*newdir || strchr(newdir, '\n') || strchr(newdir, '\r') || strchr(newdir, '.') || strchr(newdir, ':') || strchr(newdir, '?') || strchr(newdir, '*') || strchr(newdir, '/') || strchr(newdir, '\\') || strchr(newdir, '$'))
|
||||
if (!*newdir || strchr(newdir, '\n') || strchr(newdir, '\r') || !strcmp(newdir, ".") || !strcmp(newdir, "..") || strchr(newdir, ':') || strchr(newdir, '/') || strchr(newdir, '\\') || strchr(newdir, '$'))
|
||||
{
|
||||
Con_Printf("Illegal path specified: %s\n", newdir);
|
||||
}
|
||||
|
@ -798,7 +799,7 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (com_fs_cache.ival)
|
||||
if (com_fs_cache.ival && !blockcache)
|
||||
{
|
||||
if (com_fschanged)
|
||||
FS_RebuildFSHash();
|
||||
|
@ -1100,7 +1101,7 @@ static const char *FS_GetCleanPath(const char *pattern, char *outbuf, int outlen
|
|||
Q_strncpyz(outbuf, pattern, outlen);
|
||||
pattern = outbuf;
|
||||
|
||||
Con_Printf("Warning: \\ characters in filename %s\n", pattern);
|
||||
Con_DPrintf("Warning: \\ characters in filename %s\n", pattern);
|
||||
while((s = strchr(pattern, '\\')))
|
||||
{
|
||||
*s = '/';
|
||||
|
@ -1615,12 +1616,19 @@ static int QDECL FS_AddWildDataFiles (const char *descriptor, int size, void *vp
|
|||
newpak = FS_GetOldPath(param->oldpaths, pakfile);
|
||||
if (!newpak)
|
||||
{
|
||||
fs_finds++;
|
||||
if (!funcs->FindFile(funcs, &loc, descriptor, NULL))
|
||||
return true; //not found..
|
||||
vfs = funcs->OpenVFS(funcs, &loc, "rb");
|
||||
if (!vfs)
|
||||
return true;
|
||||
if (param->OpenNew == VFSOS_OpenPath)
|
||||
{
|
||||
vfs = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fs_finds++;
|
||||
if (!funcs->FindFile(funcs, &loc, descriptor, NULL))
|
||||
return true; //not found..
|
||||
vfs = funcs->OpenVFS(funcs, &loc, "rb");
|
||||
if (!vfs)
|
||||
return true;
|
||||
}
|
||||
newpak = param->OpenNew (vfs, pakfile);
|
||||
if (!newpak)
|
||||
{
|
||||
|
@ -1815,7 +1823,7 @@ void COM_RefreshFSCache_f(void)
|
|||
void COM_FlushFSCache(void)
|
||||
{
|
||||
searchpath_t *search;
|
||||
if (com_fs_cache.ival != 2)
|
||||
if (com_fs_cache.ival && com_fs_cache.ival != 2)
|
||||
{
|
||||
for (search = com_searchpaths ; search ; search = search->next)
|
||||
{
|
||||
|
@ -2105,7 +2113,7 @@ void COM_Gamedir (const char *dir)
|
|||
/*stuff that makes dp-only mods work a bit better*/
|
||||
#define DPCOMPAT QCFG "set _cl_playermodel \"\"\n set dpcompat_set 1\n set dpcompat_trailparticles 1\nset dpcompat_corruptglobals 1\nset vid_pixelheight 1\n"
|
||||
/*nexuiz/xonotic has a few quirks/annoyances...*/
|
||||
#define NEXCFG DPCOMPAT "set r_particlesdesc effectinfo\nset sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\npr_enable_uriget 0\n"
|
||||
#define NEXCFG DPCOMPAT "set r_particlesdesc effectinfo\nset sv_bigcoords 1\nset sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\npr_enable_uriget 0\n"
|
||||
/*some modern non-compat settings*/
|
||||
#define DMFCFG "set com_parseutf8 1\npm_airstep 1\nsv_demoExtensions 1\n"
|
||||
/*set some stuff so our regular qw client appears more like hexen2*/
|
||||
|
@ -2166,13 +2174,16 @@ const gamemode_info_t gamemode_info[] = {
|
|||
{"-quake4", "q4", "FTE-Quake4", {"q4base/pak00.pk4"}, NULL, {"q4base", "fteq4"}, "Quake 4"},
|
||||
{"-et", "et", "FTE-EnemyTerritory", {"etmain/pak0.pk3"}, NULL, {"etmain", "fteet"}, "Wolfenstein - Enemy Territory"},
|
||||
|
||||
{"-jk2", "jk2", "FTE-JK2", {"base/assets0.pk3"}, NULL, {"base", "fte"}, "Jedi Knight II: Jedi Outcast"},
|
||||
{"-warsow", "warsow", "FTE-Warsow", {"basewsw/pak0.pk3"}, NULL, {"basewsw", "fte"}, "Warsow"},
|
||||
{"-jk2", "jk2", "FTE-JK2", {"base/assets0.pk3"}, NULL, {"base", "ftejk2"}, "Jedi Knight II: Jedi Outcast"},
|
||||
{"-warsow", "warsow", "FTE-Warsow", {"basewsw/pak0.pk3"}, NULL, {"basewsw", "ftewsw"}, "Warsow"},
|
||||
|
||||
{"-doom", "doom", "FTE-Doom", {"doom.wad"}, NULL, {"*doom.wad", "ftedoom"}, "Doom"},
|
||||
{"-doom2", "doom2", "FTE-Doom2", {"doom2.wad"}, NULL, {"*doom2.wad", "ftedoom"}, "Doom2"},
|
||||
{"-doom3", "doom3", "FTE-Doom3", {"doom3.wad"}, NULL, {"*doom2.wad", "ftedoom"}, "Doom2"},
|
||||
|
||||
//for the luls
|
||||
{"-diablo2", NULL, "FTE-Diablo2", {"d2music.mpq"}, NULL, {"**.mpq", "fted2"}, "Diablo 2"},
|
||||
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
@ -2333,9 +2344,35 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
{
|
||||
if (fs_manifest->gamepath[i].path && fs_manifest->gamepath[i].base)
|
||||
{
|
||||
FS_AddGameDirectory(&oldpaths, fs_manifest->gamepath[i].path, va("%s%s", com_quakedir, fs_manifest->gamepath[i].path), reloadflags);
|
||||
if (*com_homedir)
|
||||
FS_AddGameDirectory(&oldpaths, fs_manifest->gamepath[i].path, va("%s%s", com_homedir, fs_manifest->gamepath[i].path), reloadflags);
|
||||
//paths with '*' actually result in loading packages without an actual gamedir. note that this does not imply that we can write anything.
|
||||
if (*fs_manifest->gamepath[i].path == '*')
|
||||
{
|
||||
int j;
|
||||
searchpathfuncs_t *handle = VFSOS_OpenPath(NULL, com_quakedir);
|
||||
searchpath_t *search = (searchpath_t*)Z_Malloc (sizeof(searchpath_t));
|
||||
search->flags = 0;
|
||||
search->handle = handle;
|
||||
Q_strncpyz(search->purepath, "", sizeof(search->purepath));
|
||||
Q_strncpyz(search->logicalpath, com_quakedir, sizeof(search->logicalpath));
|
||||
|
||||
for (j = 0; j < sizeof(searchpathformats)/sizeof(searchpathformats[0]); j++)
|
||||
{
|
||||
if (!searchpathformats[j].extension || !searchpathformats[j].OpenNew || !searchpathformats[j].loadscan)
|
||||
continue;
|
||||
if (reloadflags & (1<<j))
|
||||
{
|
||||
FS_AddDataFiles(&oldpaths, search->purepath, search->logicalpath, search, searchpathformats[j].extension, searchpathformats[j].OpenNew);
|
||||
}
|
||||
}
|
||||
handle->ClosePath(handle);
|
||||
Z_Free(search);
|
||||
}
|
||||
else
|
||||
{
|
||||
FS_AddGameDirectory(&oldpaths, fs_manifest->gamepath[i].path, va("%s%s", com_quakedir, fs_manifest->gamepath[i].path), reloadflags);
|
||||
if (*com_homedir)
|
||||
FS_AddGameDirectory(&oldpaths, fs_manifest->gamepath[i].path, va("%s%s", com_homedir, fs_manifest->gamepath[i].path), reloadflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
com_base_searchpaths = com_searchpaths;
|
||||
|
@ -2343,9 +2380,15 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
{
|
||||
if (fs_manifest->gamepath[i].path && !fs_manifest->gamepath[i].base)
|
||||
{
|
||||
FS_AddGameDirectory(&oldpaths, fs_manifest->gamepath[i].path, va("%s%s", com_quakedir, fs_manifest->gamepath[i].path), reloadflags);
|
||||
if (*com_homedir)
|
||||
FS_AddGameDirectory(&oldpaths, fs_manifest->gamepath[i].path, va("%s%s", com_homedir, fs_manifest->gamepath[i].path), reloadflags);
|
||||
if (*fs_manifest->gamepath[i].path == '*')
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
FS_AddGameDirectory(&oldpaths, fs_manifest->gamepath[i].path, va("%s%s", com_quakedir, fs_manifest->gamepath[i].path), reloadflags);
|
||||
if (*com_homedir)
|
||||
FS_AddGameDirectory(&oldpaths, fs_manifest->gamepath[i].path, va("%s%s", com_homedir, fs_manifest->gamepath[i].path), reloadflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2553,6 +2596,20 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
|
|||
|
||||
if (!strcmp(gamename, "quake"))
|
||||
{
|
||||
char *prefix[] =
|
||||
{
|
||||
"c:/quake/", //quite a lot of people have it in c:\quake, as that's the default install location from the quake cd.
|
||||
"c:/games/quake/", //personally I use this
|
||||
#ifdef _WIN64
|
||||
//quite a few people have nquake installed. we need to an api function to read the directory for non-english-windows users.
|
||||
va("%s/nQuake/", getenv("%ProgramFiles(x86)%")), //64bit builds should look in both places
|
||||
va("%s/nQuake/", getenv("%ProgramFiles%")), //
|
||||
#else
|
||||
va("%s/nQuake/", getenv("%ProgramFiles%")), //32bit builds will get the x86 version anyway.
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
int i;
|
||||
FILE *f;
|
||||
|
||||
//try and find it via steam
|
||||
|
@ -2563,13 +2620,17 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
|
|||
return true;
|
||||
//well, okay, so they don't have quake installed from steam.
|
||||
|
||||
//quite a lot of people have it in c:\quake, as that's the default install location from the quake cd.
|
||||
if ((f = fopen("c:/quake/quake.exe", "rb")))
|
||||
//check various 'unadvertised' paths
|
||||
for (i = 0; prefix[i]; i++)
|
||||
{
|
||||
//HAHAHA! Found it!
|
||||
fclose(f);
|
||||
Q_strncpyz(basepath, "c:/quake", basepathlen);
|
||||
return true;
|
||||
char syspath[MAX_OSPATH];
|
||||
Q_snprintfz(syspath, sizeof(syspath), "%sid1/pak0.pak", prefix[i]);
|
||||
if ((f = fopen("c:/quake/quake.exe", "rb")))
|
||||
{
|
||||
fclose(f);
|
||||
Q_strncpyz(basepath, prefix[i], sizeof(basepath));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2941,6 +3002,25 @@ static void FS_StartupWithGame(int gamenum)
|
|||
}
|
||||
#endif
|
||||
|
||||
static qboolean FS_DirHasAPackage(char *basedir, ftemanifest_t *man)
|
||||
{
|
||||
int j;
|
||||
vfsfile_t *f;
|
||||
for (j = 0; j < sizeof(fs_manifest->package) / sizeof(fs_manifest->package[0]); j++)
|
||||
{
|
||||
if (!man->package[j].path)
|
||||
continue;
|
||||
|
||||
f = VFSOS_Open(va("%s%s", basedir, man->package[j].path), "rb");
|
||||
if (f)
|
||||
{
|
||||
VFS_CLOSE(f);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//just check each possible file, see if one is there.
|
||||
static qboolean FS_DirHasGame(char *basedir, int gameidx)
|
||||
{
|
||||
|
@ -2999,10 +3079,12 @@ static int FS_IdentifyDefaultGame(char *newbase, int sizeof_newbase, qboolean fi
|
|||
//use the game based on an exe name over the filesystem one (could easily have multiple fs path matches).
|
||||
if (gamenum == -1)
|
||||
{
|
||||
char *ev, *v0 = COM_SkipPath(com_argv[0]);
|
||||
for (i = 0; gamemode_info[i].argname; i++)
|
||||
{
|
||||
char *ev = COM_SkipPath(com_argv[0]);
|
||||
ev = strstr(ev, gamemode_info[i].exename);
|
||||
if (!gamemode_info[i].exename)
|
||||
continue;
|
||||
ev = strstr(v0, gamemode_info[i].exename);
|
||||
if (ev && (!strchr(ev, '\\') && !strchr(ev, '/')))
|
||||
gamenum = i;
|
||||
}
|
||||
|
@ -3231,6 +3313,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs)
|
|||
char newbasedir[MAX_OSPATH];
|
||||
qboolean fixedbasedir;
|
||||
qboolean reloadconfigs = false;
|
||||
qboolean builtingame = false;
|
||||
flocation_t loc;
|
||||
|
||||
//if any of these files change location, the configs will be re-execed.
|
||||
|
@ -3277,6 +3360,8 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs)
|
|||
}
|
||||
fs_manifest = man;
|
||||
|
||||
blockcache = true;
|
||||
|
||||
if (man->installation && *man->installation)
|
||||
{
|
||||
for (i = 0; gamemode_info[i].argname; i++)
|
||||
|
@ -3309,6 +3394,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs)
|
|||
man->defaultexec = Z_StrDup(gamemode_info[i].customexec);
|
||||
}
|
||||
|
||||
builtingame = true;
|
||||
if (!fixedbasedir && !FS_DirHasGame(newbasedir, i))
|
||||
if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath)))
|
||||
Q_strncpyz (newbasedir, realpath, sizeof(newbasedir));
|
||||
|
@ -3316,6 +3402,11 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!builtingame && !fixedbasedir && !FS_DirHasAPackage(newbasedir, man))
|
||||
if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath)))
|
||||
Q_strncpyz (newbasedir, realpath, sizeof(newbasedir));
|
||||
|
||||
Q_strncpyz (com_quakedir, newbasedir, sizeof(com_quakedir));
|
||||
//make sure it has a trailing slash, or is empty. woo.
|
||||
FS_CleanDir(com_quakedir, sizeof(com_quakedir));
|
||||
|
@ -3366,6 +3457,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs)
|
|||
#endif
|
||||
}
|
||||
}
|
||||
blockcache = false;
|
||||
}
|
||||
|
||||
COM_Effectinfo_Clear();
|
||||
|
@ -3587,6 +3679,7 @@ void FS_RegisterDefaultFileSystems(void)
|
|||
/*for systems that have case sensitive paths, also include *.PAK */
|
||||
FS_RegisterFileSystemType(NULL, "PAK", FSPAK_LoadArchive, true);
|
||||
#endif
|
||||
FS_RegisterFileSystemType(NULL, "pk3dir", VFSOS_OpenPath, true);
|
||||
#ifdef AVAIL_ZLIB
|
||||
FS_RegisterFileSystemType(NULL, "pk3", FSZIP_LoadArchive, true);
|
||||
FS_RegisterFileSystemType(NULL, "pk4", FSZIP_LoadArchive, true);
|
||||
|
|
|
@ -138,7 +138,8 @@ vfsfile_t *QDECL VFSW32_Open(const char *osname, const char *mode)
|
|||
if (h == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
if (write || append || text)
|
||||
fsize = GetFileSize(h, NULL);
|
||||
if (write || append || text || fsize > 1024*1024*5)
|
||||
{
|
||||
fsize = 0;
|
||||
mh = INVALID_HANDLE_VALUE;
|
||||
|
@ -150,7 +151,6 @@ vfsfile_t *QDECL VFSW32_Open(const char *osname, const char *mode)
|
|||
}
|
||||
else
|
||||
{
|
||||
fsize = GetFileSize(h, NULL);
|
||||
mh = CreateFileMapping(h, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (mh == INVALID_HANDLE_VALUE)
|
||||
mmap = NULL;
|
||||
|
|
|
@ -4217,7 +4217,7 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c
|
|||
}
|
||||
|
||||
#ifdef TERRAIN
|
||||
im->terrain = Mod_LoadTerrainInfo(im, loadname);
|
||||
im->terrain = Mod_LoadTerrainInfo(im, loadname, false);
|
||||
#endif
|
||||
|
||||
return &map_cmodels[0];
|
||||
|
@ -6020,7 +6020,7 @@ unsigned int Q2BSP_PointContents(model_t *mod, vec3_t axis[3], vec3_t p)
|
|||
|
||||
|
||||
int map_checksum;
|
||||
qboolean Mod_LoadQ2BrushModel (model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadQ2BrushModel (model_t *mod, void *buffer)
|
||||
{
|
||||
mod->fromgame = fg_quake2;
|
||||
return CM_LoadMap(mod->name, buffer, true, &map_checksum) != NULL;
|
||||
|
|
|
@ -1041,6 +1041,26 @@ void Matrix4x4_RM_CreateTranslate (float *out, float x, float y, float z)
|
|||
out[15] = 1;
|
||||
}
|
||||
|
||||
void Matrix4x4_CM_LightMatrixFromAxis(float *modelview, const vec3_t px, const vec3_t py, const vec3_t pz, const vec3_t org)
|
||||
{
|
||||
modelview[ 0] = px[0];
|
||||
modelview[ 1] = py[0];
|
||||
modelview[ 2] = pz[0];
|
||||
modelview[ 3] = 0;
|
||||
modelview[ 4] = px[1];
|
||||
modelview[ 5] = py[1];
|
||||
modelview[ 6] = pz[1];
|
||||
modelview[ 7] = 0;
|
||||
modelview[ 8] = px[2];
|
||||
modelview[ 9] = py[2];
|
||||
modelview[10] = pz[2];
|
||||
modelview[11] = 0;
|
||||
modelview[12] = -(px[0]*org[0] + px[1]*org[1] + px[2]*org[2]);
|
||||
modelview[13] = -(py[0]*org[0] + py[1]*org[1] + py[2]*org[2]);
|
||||
modelview[14] = -(pz[0]*org[0] + pz[1]*org[1] + pz[2]*org[2]);
|
||||
modelview[15] = 1;
|
||||
}
|
||||
|
||||
void Matrix4x4_CM_ModelViewMatrixFromAxis(float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg)
|
||||
{
|
||||
float tempmat[16];
|
||||
|
|
|
@ -164,6 +164,7 @@ void Matrix4x4_CM_ModelMatrixFromAxis (float *modelview, const vec3_t pn, const
|
|||
void Matrix4x4_CM_ModelMatrix(float *modelview, vec_t x, vec_t y, vec_t z, vec_t pitch, vec_t yaw, vec_t roll, vec_t scale);
|
||||
void Matrix4x4_CM_ModelViewMatrix (float *modelview, const vec3_t viewangles, const vec3_t vieworg);
|
||||
void Matrix4x4_CM_ModelViewMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg);
|
||||
void Matrix4x4_CM_LightMatrixFromAxis(float *modelview, const vec3_t px, const vec3_t py, const vec3_t pz, const vec3_t vieworg); //
|
||||
void Matrix4_CreateFromQuakeEntity (float *matrix, float x, float y, float z, float pitch, float yaw, float roll, float scale);
|
||||
void Matrix4_Multiply (const float *a, const float *b, float *out);
|
||||
void Matrix3x4_Multiply(const float *a, const float *b, float *out);
|
||||
|
|
|
@ -5514,6 +5514,7 @@ qboolean QDECL ICE_Set(struct icestate_s *con, char *prop, char *value)
|
|||
int codec = atoi(prop+5);
|
||||
if (codec < 96 || codec > 127)
|
||||
return false;
|
||||
codec -= 96;
|
||||
#if !defined(SERVERONLY) && defined(VOICECHAT)
|
||||
if (!S_Voip_RTP_CodecOkay(value))
|
||||
#endif
|
||||
|
@ -5522,7 +5523,6 @@ qboolean QDECL ICE_Set(struct icestate_s *con, char *prop, char *value)
|
|||
con->codec[codec] = NULL;
|
||||
return false;
|
||||
}
|
||||
codec -= 96;
|
||||
Z_Free(con->codec[codec]);
|
||||
con->codec[codec] = Z_StrDup(value);
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ int PM_SlideMove (void)
|
|||
for (i=0 ; i<3 ; i++)
|
||||
end[i] = pmove.origin[i] + time_left * pmove.velocity[i];
|
||||
|
||||
trace = PM_PlayerTrace (pmove.origin, end);
|
||||
trace = PM_PlayerTrace (pmove.origin, end, MASK_PLAYERSOLID);
|
||||
|
||||
if (trace.startsolid || trace.allsolid)
|
||||
{ // entity is trapped in another solid
|
||||
|
@ -272,7 +272,7 @@ int PM_StepSlideMove (qboolean in_air)
|
|||
|
||||
org = (-DotProduct(pmove.gravitydir, originalvel) < 0) ? pmove.origin : original;
|
||||
VectorMA (org, movevars.stepheight, pmove.gravitydir, dest);
|
||||
trace = PM_PlayerTrace (org, dest);
|
||||
trace = PM_PlayerTrace (org, dest, MASK_PLAYERSOLID);
|
||||
if (trace.fraction == 1 || -DotProduct(pmove.gravitydir, trace.plane.normal) < MIN_STEP_NORMAL)
|
||||
return blocked;
|
||||
|
||||
|
@ -291,7 +291,7 @@ int PM_StepSlideMove (qboolean in_air)
|
|||
|
||||
// move up a stair height
|
||||
VectorMA (pmove.origin, -stepsize, pmove.gravitydir, dest);
|
||||
trace = PM_PlayerTrace (pmove.origin, dest);
|
||||
trace = PM_PlayerTrace (pmove.origin, dest, MASK_PLAYERSOLID);
|
||||
if (!trace.startsolid && !trace.allsolid)
|
||||
{
|
||||
VectorCopy (trace.endpos, pmove.origin);
|
||||
|
@ -304,7 +304,7 @@ int PM_StepSlideMove (qboolean in_air)
|
|||
|
||||
// press down the stepheight
|
||||
VectorMA (pmove.origin, stepsize, pmove.gravitydir, dest);
|
||||
trace = PM_PlayerTrace (pmove.origin, dest);
|
||||
trace = PM_PlayerTrace (pmove.origin, dest, MASK_PLAYERSOLID);
|
||||
if (trace.fraction != 1 && -DotProduct(pmove.gravitydir, trace.plane.normal) < MIN_STEP_NORMAL)
|
||||
goto usedown;
|
||||
if (!trace.startsolid && !trace.allsolid)
|
||||
|
@ -396,7 +396,7 @@ void PM_Friction (void)
|
|||
start[1] = stop[1] = pmove.origin[1] + pmove.velocity[1]/speed*16;
|
||||
start[2] = pmove.origin[2] + player_mins[2];
|
||||
stop[2] = start[2] - 34;
|
||||
trace = PM_PlayerTrace (start, stop);
|
||||
trace = PM_PlayerTrace (start, stop, MASK_PLAYERSOLID);
|
||||
if (trace.fraction == 1)
|
||||
friction *= 2;
|
||||
|
||||
|
@ -608,7 +608,7 @@ void PM_LadderMove (void)
|
|||
// assume it is a stair or a slope, so press down from stepheight above
|
||||
VectorMA (pmove.origin, frametime, pmove.velocity, dest);
|
||||
VectorMA(dest, -(movevars.stepheight + 1), pmove.gravitydir, start);
|
||||
trace = PM_PlayerTrace (start, dest);
|
||||
trace = PM_PlayerTrace (start, dest, MASK_PLAYERSOLID);
|
||||
if (!trace.startsolid && !trace.allsolid) // FIXME: check steep slope?
|
||||
{ // walked up the step
|
||||
VectorCopy (trace.endpos, pmove.origin);
|
||||
|
@ -749,7 +749,7 @@ void PM_CategorizePosition (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
trace = PM_PlayerTrace (pmove.origin, point);
|
||||
trace = PM_PlayerTrace (pmove.origin, point, MASK_PLAYERSOLID);
|
||||
if (trace.fraction == 1 || -DotProduct(pmove.gravitydir, trace.plane.normal) < MIN_STEP_NORMAL)
|
||||
pmove.onground = false;
|
||||
else
|
||||
|
@ -829,7 +829,7 @@ void PM_CategorizePosition (void)
|
|||
VectorMA (pmove.origin, 24, flatforward, fwd1);
|
||||
|
||||
//if we hit a wall when going forwards and we are in a ladder region, then we are on a ladder.
|
||||
t = PM_PlayerTrace(pmove.origin, fwd1);
|
||||
t = PM_PlayerTrace(pmove.origin, fwd1, MASK_PLAYERSOLID);
|
||||
if (t.fraction < 1)
|
||||
{
|
||||
pmove.onladder = true;
|
||||
|
|
|
@ -119,6 +119,6 @@ int PM_ExtraBoxContents (vec3_t p); //Peeks for HL-style water.
|
|||
int PM_PointContents (vec3_t point);
|
||||
qboolean PM_TestPlayerPosition (vec3_t point);
|
||||
#ifndef __cplusplus
|
||||
struct trace_s PM_PlayerTrace (vec3_t start, vec3_t stop);
|
||||
struct trace_s PM_PlayerTrace (vec3_t start, vec3_t stop, unsigned int solidmask);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -282,6 +282,9 @@ qboolean PM_TestPlayerPosition (vec3_t pos)
|
|||
if (pe->nonsolid)
|
||||
continue;
|
||||
|
||||
if (pe->forcecontentsmask && !(pe->forcecontentsmask & MASK_PLAYERSOLID))
|
||||
continue;
|
||||
|
||||
// get the clipping hull
|
||||
if (pe->model)
|
||||
{
|
||||
|
@ -297,7 +300,7 @@ qboolean PM_TestPlayerPosition (vec3_t pos)
|
|||
hull = PM_HullForBox (mins, maxs);
|
||||
VectorSubtract(pos, pe->origin, mins);
|
||||
|
||||
if (Q1BSP_HullPointContents(hull, mins) & FTECONTENTS_SOLID)
|
||||
if (Q1BSP_HullPointContents(hull, mins) & MASK_PLAYERSOLID)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -310,7 +313,7 @@ qboolean PM_TestPlayerPosition (vec3_t pos)
|
|||
PM_PlayerTrace
|
||||
================
|
||||
*/
|
||||
trace_t PM_PlayerTrace (vec3_t start, vec3_t end)
|
||||
trace_t PM_PlayerTrace (vec3_t start, vec3_t end, unsigned int solidmask)
|
||||
{
|
||||
trace_t trace, total;
|
||||
int i;
|
||||
|
@ -330,6 +333,8 @@ trace_t PM_PlayerTrace (vec3_t start, vec3_t end)
|
|||
continue;
|
||||
if (pe->info == pmove.skipent)
|
||||
continue;
|
||||
if (pe->forcecontentsmask && !(pe->forcecontentsmask & solidmask))
|
||||
continue;
|
||||
|
||||
if (!pe->model || pe->model->needload)
|
||||
{
|
||||
|
@ -377,5 +382,5 @@ trace_t PM_TraceLine (vec3_t start, vec3_t end)
|
|||
{
|
||||
VectorClear(player_mins);
|
||||
VectorClear(player_maxs);
|
||||
return PM_PlayerTrace(start, end);
|
||||
return PM_PlayerTrace(start, end, MASK_PLAYERSOLID);
|
||||
}
|
||||
|
|
|
@ -1431,6 +1431,7 @@ typedef struct q1usercmd_s
|
|||
#define SCALE_ORIGIN_CENTER 0 // Scaling origin at object center
|
||||
#define SCALE_ORIGIN_BOTTOM 32 // Scaling origin at object bottom
|
||||
#define SCALE_ORIGIN_TOP 64 // Scaling origin at object top
|
||||
#define SCALE_ORIGIN_ORIGIN (64|32) // Scaling origin at object origin
|
||||
#define DRF_TRANSLUCENT 128
|
||||
|
||||
|
||||
|
|
|
@ -739,19 +739,29 @@ int Q1BSP_HullPointContents(hull_t *hull, vec3_t p)
|
|||
|
||||
unsigned int Q1BSP_PointContents(model_t *model, vec3_t axis[3], vec3_t point)
|
||||
{
|
||||
int contents;
|
||||
if (axis)
|
||||
{
|
||||
vec3_t transformed;
|
||||
transformed[0] = DotProduct(point, axis[0]);
|
||||
transformed[1] = DotProduct(point, axis[1]);
|
||||
transformed[2] = DotProduct(point, axis[2]);
|
||||
return Q1BSP_HullPointContents(&model->hulls[0], transformed);
|
||||
return Q1BSP_PointContents(model, NULL, transformed);
|
||||
}
|
||||
if (!model->firstmodelsurface)
|
||||
else
|
||||
{
|
||||
return Q1BSP_TranslateContents(Q1_ModelPointContents(model->nodes, point));
|
||||
if (!model->firstmodelsurface)
|
||||
{
|
||||
contents = Q1BSP_TranslateContents(Q1_ModelPointContents(model->nodes, point));
|
||||
}
|
||||
else
|
||||
contents = Q1BSP_HullPointContents(&model->hulls[0], point);
|
||||
}
|
||||
return Q1BSP_HullPointContents(&model->hulls[0], point);
|
||||
#ifdef TERRAIN
|
||||
if (model->terrain)
|
||||
contents |= Heightmap_PointContents(model, NULL, point);
|
||||
#endif
|
||||
return contents;
|
||||
}
|
||||
|
||||
void Q1BSP_LoadBrushes(model_t *model)
|
||||
|
|
|
@ -592,6 +592,7 @@ void Cache_Flush(void)
|
|||
#ifndef SERVERONLY
|
||||
S_Purge(false);
|
||||
#endif
|
||||
Mod_Purge(MP_FLUSH);
|
||||
}
|
||||
|
||||
static void Hunk_Print_f (void)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "FTEQuake", "..\setup\setup.vdproj", "{E0EE8B50-3A75-42A9-B80A-787675979B0C}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{9767E236-8454-44E9-8999-CD5BDAFBE9BA} = {9767E236-8454-44E9-8999-CD5BDAFBE9BA}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "botlib", "botlib.vcproj", "{0018E098-B12A-4E4D-9B22-6772DA287080}"
|
||||
EndProject
|
||||
|
@ -387,7 +390,7 @@ Global
|
|||
{72269FEE-293D-40BC-A7AE-E429F4496869}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{72269FEE-293D-40BC-A7AE-E429F4496869}.GLDebug|Win32.ActiveCfg = Debug|Win32
|
||||
{72269FEE-293D-40BC-A7AE-E429F4496869}.GLDebug|Win32.Build.0 = Debug|Win32
|
||||
{72269FEE-293D-40BC-A7AE-E429F4496869}.GLDebug|x64.ActiveCfg = Debug|Win32
|
||||
{72269FEE-293D-40BC-A7AE-E429F4496869}.GLDebug|x64.ActiveCfg = Debug|x64
|
||||
{72269FEE-293D-40BC-A7AE-E429F4496869}.GLRelease|Win32.ActiveCfg = Release|Win32
|
||||
{72269FEE-293D-40BC-A7AE-E429F4496869}.GLRelease|Win32.Build.0 = Release|Win32
|
||||
{72269FEE-293D-40BC-A7AE-E429F4496869}.GLRelease|x64.ActiveCfg = Release|Win32
|
||||
|
@ -500,7 +503,6 @@ Global
|
|||
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DRelease|x64.ActiveCfg = Debug Dedicated Server|x64
|
||||
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DRelease|x64.Build.0 = Debug Dedicated Server|x64
|
||||
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug Dedicated Server|Win32.ActiveCfg = Debug Dedicated Server|Win32
|
||||
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug Dedicated Server|Win32.Build.0 = Debug Dedicated Server|Win32
|
||||
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug Dedicated Server|x64.ActiveCfg = Debug Dedicated Server|x64
|
||||
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug Dedicated Server|x64.Build.0 = Debug Dedicated Server|x64
|
||||
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug|Win32.ActiveCfg = Debug Dedicated Server|x64
|
||||
|
|
|
@ -1954,7 +1954,7 @@ void BE_GenPolyBatches(batch_t **batches)
|
|||
}
|
||||
}
|
||||
void R_HalfLife_GenerateBatches(entity_t *e, batch_t **batches);
|
||||
|
||||
model_t *Mod_LoadModel (model_t *mod, qboolean crash);
|
||||
void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemode)
|
||||
{
|
||||
int i;
|
||||
|
@ -2010,7 +2010,10 @@ void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemo
|
|||
if (!ent->model)
|
||||
continue;
|
||||
if (ent->model->needload)
|
||||
continue;
|
||||
{
|
||||
if (!Mod_LoadModel(ent->model, false))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cl.lerpents && (cls.allow_anyparticles)) //allowed or static
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@ void DumpGLState(void);
|
|||
|
||||
#ifdef GLQUAKE
|
||||
|
||||
#define r_refract_fboival gl_config.ext_framebuffer_objects
|
||||
#define r_refract_fboival (gl_config.ext_framebuffer_objects && r_refract_fbo.ival)
|
||||
|
||||
#include "glquake.h"
|
||||
#include "shader.h"
|
||||
|
@ -28,6 +28,7 @@ void DumpGLState(void);
|
|||
extern cvar_t gl_overbright;
|
||||
extern cvar_t gl_ati_truform;
|
||||
extern cvar_t r_wireframe;
|
||||
extern cvar_t r_refract_fbo;
|
||||
|
||||
static const char LIGHTPASS_SHADER[] = "\
|
||||
{\n\
|
||||
|
@ -87,6 +88,7 @@ struct {
|
|||
const shader_t *depthnormshader;
|
||||
texid_t tex_normals;
|
||||
texid_t tex_diffuse;
|
||||
int fbo_current; //the one currently being rendered to
|
||||
int fbo_diffuse;
|
||||
int rb_depth;
|
||||
int rb_stencil;
|
||||
|
@ -957,7 +959,7 @@ void R_IBrokeTheArrays(void)
|
|||
|
||||
#ifdef RTLIGHTS
|
||||
//called from gl_shadow
|
||||
void GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, float shadowscale)
|
||||
int GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, float shadowscale)
|
||||
{
|
||||
extern cvar_t r_shadow_shadowmapping_bias;
|
||||
extern cvar_t r_shadow_shadowmapping_nearclip;
|
||||
|
@ -988,6 +990,8 @@ void GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, f
|
|||
// qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
||||
BE_SelectMode(BEM_DEPTHONLY);
|
||||
|
||||
return shaderstate.fbo_current;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3358,9 +3362,9 @@ static qboolean GLBE_RegisterLightShader(int mode)
|
|||
if (!shaderstate.inited_shader_light[mode])
|
||||
{
|
||||
char *name = va("rtlight%s%s%s",
|
||||
(mode & (1u<<LSHADER_SMAP))?"#PCF":"",
|
||||
(mode & (1u<<LSHADER_SPOT))?"#SPOT":"",
|
||||
(mode & (1u<<LSHADER_CUBE))?"#CUBE":"");
|
||||
(mode & LSHADER_SMAP)?"#PCF":"",
|
||||
(mode & LSHADER_SPOT)?"#SPOT":"",
|
||||
(mode & LSHADER_CUBE)?"#CUBE":"");
|
||||
|
||||
shaderstate.inited_shader_light[mode] = true;
|
||||
shaderstate.shader_light[mode] = R_RegisterCustom(name, SUF_NONE, Shader_LightPass, NULL);
|
||||
|
@ -3383,28 +3387,10 @@ static qboolean GLBE_RegisterLightShader(int mode)
|
|||
qboolean GLBE_SelectDLight(dlight_t *dl, vec3_t colour, unsigned int lmode)
|
||||
{
|
||||
extern cvar_t gl_specular;
|
||||
#ifdef RTLIGHTS
|
||||
float view[16];
|
||||
extern cvar_t r_shadow_shadowmapping, r_shadow_shadowmapping_nearclip;
|
||||
|
||||
/*generate light projection information*/
|
||||
if (lmode == LSHADER_SPOT)
|
||||
{
|
||||
float proj[16];
|
||||
Matrix4x4_CM_Projection_Far(proj, dl->fov, dl->fov, r_shadow_shadowmapping_nearclip.value, dl->radius);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(view, dl->axis[0], dl->axis[1], dl->axis[2], dl->origin);
|
||||
Matrix4_Multiply(proj, view, shaderstate.lightprojmatrix);
|
||||
}
|
||||
if (lmode == LSHADER_SMAP)
|
||||
{
|
||||
// Matrix4x4_CM_Projection_Far(proj, 90, 90, nearplane, dl->radius);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(shaderstate.lightprojmatrix, dl->axis[0], dl->axis[1], dl->axis[2], dl->origin);
|
||||
}
|
||||
#endif
|
||||
|
||||
shaderstate.lastuniform = 0;
|
||||
shaderstate.curdlight = dl;
|
||||
shaderstate.lightmode = 1u<<lmode;
|
||||
shaderstate.lightmode = lmode;
|
||||
|
||||
/*simple info*/
|
||||
shaderstate.lightradius = dl->radius;
|
||||
|
@ -3413,15 +3399,39 @@ qboolean GLBE_SelectDLight(dlight_t *dl, vec3_t colour, unsigned int lmode)
|
|||
VectorCopy(colour, shaderstate.lightcolours);
|
||||
#ifdef RTLIGHTS
|
||||
VectorCopy(dl->lightcolourscales, shaderstate.lightcolourscale);
|
||||
shaderstate.lightcubemap = dl->cubetexture;
|
||||
if (lmode & LSHADER_SPOT)
|
||||
shaderstate.lightcubemap = r_nulltex;
|
||||
else
|
||||
shaderstate.lightcubemap = dl->cubetexture;
|
||||
|
||||
if (lmode != LSHADER_SPOT)
|
||||
{
|
||||
if (TEXVALID(shaderstate.lightcubemap) && GLBE_RegisterLightShader(shaderstate.lightmode | (1u<<LSHADER_CUBE)))
|
||||
shaderstate.lightmode |= 1u<<LSHADER_CUBE;
|
||||
}
|
||||
if (TEXVALID(shaderstate.lightcubemap) && GLBE_RegisterLightShader(shaderstate.lightmode | LSHADER_CUBE))
|
||||
shaderstate.lightmode |= LSHADER_CUBE;
|
||||
if (!GLBE_RegisterLightShader(shaderstate.lightmode))
|
||||
return false;
|
||||
|
||||
/*generate light projection information*/
|
||||
if (shaderstate.lightmode & LSHADER_SPOT)
|
||||
{
|
||||
float view[16];
|
||||
float proj[16];
|
||||
extern cvar_t r_shadow_shadowmapping_nearclip;
|
||||
Matrix4x4_CM_Projection_Far(proj, dl->fov, dl->fov, r_shadow_shadowmapping_nearclip.value, dl->radius);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(view, dl->axis[0], dl->axis[1], dl->axis[2], dl->origin);
|
||||
Matrix4_Multiply(proj, view, shaderstate.lightprojmatrix);
|
||||
}
|
||||
else if (shaderstate.lightmode & (LSHADER_SMAP|LSHADER_CUBE))
|
||||
{
|
||||
Matrix4x4_CM_LightMatrixFromAxis(shaderstate.lightprojmatrix, dl->axis[0], dl->axis[1], dl->axis[2], dl->origin);
|
||||
/*
|
||||
vec3_t down;
|
||||
vec3_t back;
|
||||
vec3_t right;
|
||||
VectorScale(dl->axis[2], -1, down);
|
||||
VectorScale(dl->axis[1], 1, right);
|
||||
VectorScale(dl->axis[0], 1, back);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(shaderstate.lightprojmatrix, down, back, right, dl->origin);
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -3514,6 +3524,10 @@ static void BE_LegacyLighting(void)
|
|||
{
|
||||
mesh = shaderstate.meshes[m];
|
||||
|
||||
//vbo-only mesh.
|
||||
if (!mesh->xyz_array)
|
||||
return;
|
||||
|
||||
col = coloursarray[0] + mesh->vbofirstvert*4;
|
||||
ldir = texcoordarray[0] + mesh->vbofirstvert*3;
|
||||
for (i = 0; i < mesh->numvertexes; i++, col+=4, ldir+=3)
|
||||
|
@ -3613,6 +3627,7 @@ static void BE_LegacyLighting(void)
|
|||
|
||||
static void DrawMeshes(void)
|
||||
{
|
||||
const shader_t *altshader;
|
||||
const shaderpass_t *p;
|
||||
int passno;
|
||||
int flags;
|
||||
|
@ -3678,24 +3693,39 @@ static void DrawMeshes(void)
|
|||
break;
|
||||
#ifdef RTLIGHTS
|
||||
case BEM_LIGHT:
|
||||
if (!shaderstate.shader_light[shaderstate.lightmode])
|
||||
BE_LegacyLighting();
|
||||
altshader = shaderstate.curshader->bemoverrides[shaderstate.lightmode];
|
||||
if (!altshader)
|
||||
altshader = shaderstate.shader_light[shaderstate.lightmode];
|
||||
if (altshader && altshader->prog)
|
||||
BE_RenderMeshProgram(altshader, altshader->passes);
|
||||
else
|
||||
BE_RenderMeshProgram(shaderstate.shader_light[shaderstate.lightmode], shaderstate.shader_light[shaderstate.lightmode]->passes);
|
||||
BE_LegacyLighting();
|
||||
break;
|
||||
case BEM_DEPTHNORM:
|
||||
BE_RenderMeshProgram(shaderstate.depthnormshader, shaderstate.depthnormshader->passes);
|
||||
altshader = shaderstate.curshader->bemoverrides[bemoverride_prelight];
|
||||
if (!altshader)
|
||||
altshader = shaderstate.depthnormshader;
|
||||
if (altshader && altshader->prog)
|
||||
BE_RenderMeshProgram(altshader, altshader->passes);
|
||||
break;
|
||||
#endif
|
||||
case BEM_CREPUSCULAR:
|
||||
if (shaderstate.curshader->flags & SHADER_SKY)
|
||||
BE_RenderMeshProgram(shaderstate.crepskyshader, shaderstate.crepskyshader->passes);
|
||||
else
|
||||
BE_RenderMeshProgram(shaderstate.crepopaqueshader, shaderstate.crepopaqueshader->passes);
|
||||
altshader = shaderstate.curshader->bemoverrides[bemoverride_crepuscular];
|
||||
if (!altshader && (shaderstate.curshader->flags & SHADER_SKY))
|
||||
altshader = shaderstate.crepskyshader;
|
||||
if (!altshader)
|
||||
altshader = shaderstate.crepopaqueshader;
|
||||
|
||||
if (altshader && altshader->prog)
|
||||
BE_RenderMeshProgram(altshader, altshader->passes);
|
||||
break;
|
||||
case BEM_DEPTHONLY:
|
||||
if (shaderstate.depthonlyshader)
|
||||
BE_RenderMeshProgram(shaderstate.depthonlyshader, shaderstate.depthonlyshader->passes);
|
||||
altshader = shaderstate.curshader->bemoverrides[bemoverride_depthonly];
|
||||
if (!altshader)
|
||||
altshader = shaderstate.depthonlyshader;
|
||||
|
||||
if (altshader && altshader->prog)
|
||||
BE_RenderMeshProgram(altshader, altshader->passes);
|
||||
else
|
||||
{
|
||||
GL_DeSelectProgram();
|
||||
|
@ -4165,7 +4195,6 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
}
|
||||
GL_ForceDepthWritable();
|
||||
GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_reflection, r_nulltex, true);
|
||||
qglViewport (0, 0, vid.pixelwidth/2, vid.pixelheight/2);
|
||||
r_refdef.vrect.x = 0;
|
||||
r_refdef.vrect.y = 0;
|
||||
r_refdef.vrect.width = vid.width/2;
|
||||
|
@ -4174,14 +4203,15 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
r_refdef.pxrect.width = vid.pixelwidth/2;
|
||||
r_refdef.pxrect.height = vid.pixelheight/2;
|
||||
r_refdef.pxrect.y = r_refdef.pxrect.height;
|
||||
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
GL_ForceDepthWritable();
|
||||
qglClearColor(0, 0, 0, 0);
|
||||
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
GLR_DrawPortal(batch, cl.worldmodel->batches, 1);
|
||||
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
|
||||
qglViewport (oprect.x, oprect.y - oprect.height, oprect.width, oprect.height);
|
||||
r_refdef.vrect = orect;
|
||||
r_refdef.pxrect = oprect;
|
||||
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
}
|
||||
if (batch->shader->flags & (SHADER_HASREFRACT|SHADER_HASREFRACTDEPTH))
|
||||
{
|
||||
|
@ -4217,7 +4247,6 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
else
|
||||
GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_refraction, r_nulltex, true);
|
||||
|
||||
qglViewport (0, 0, vid.pixelwidth/2, vid.pixelheight/2);
|
||||
r_refdef.vrect.x = 0;
|
||||
r_refdef.vrect.y = 0;
|
||||
r_refdef.vrect.width = vid.width/2;
|
||||
|
@ -4226,6 +4255,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
r_refdef.pxrect.width = vid.pixelwidth/2;
|
||||
r_refdef.pxrect.height = vid.pixelheight/2;
|
||||
r_refdef.pxrect.y = r_refdef.pxrect.height;
|
||||
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
|
||||
GL_ForceDepthWritable();
|
||||
qglClearColor(0, 0, 0, 0);
|
||||
|
@ -4233,9 +4263,9 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
GLR_DrawPortal(batch, cl.worldmodel->batches, ((batch->shader->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
|
||||
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
|
||||
|
||||
qglViewport (oprect.x, oprect.y - oprect.height, oprect.width, oprect.height);
|
||||
r_refdef.vrect = ovrect;
|
||||
r_refdef.pxrect = oprect;
|
||||
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
}
|
||||
else
|
||||
GLR_DrawPortal(batch, cl.worldmodel->batches, 3);
|
||||
|
@ -4245,6 +4275,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
vrect_t orect = r_refdef.vrect, oprect = r_refdef.pxrect;
|
||||
if (!shaderstate.tex_ripplemap.num)
|
||||
{
|
||||
//FIXME: can we use RGB8 instead?
|
||||
shaderstate.tex_ripplemap = GL_AllocNewTexture("***tex_ripplemap***", vid.pixelwidth/2, vid.pixelheight/2, 0);
|
||||
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_ripplemap);
|
||||
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, vid.pixelwidth/2, vid.pixelheight/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
@ -4254,7 +4285,6 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_ripplemap, r_nulltex, false);
|
||||
qglViewport (0, 0, vid.pixelwidth/2, vid.pixelheight/2);
|
||||
r_refdef.vrect.x = 0;
|
||||
r_refdef.vrect.y = 0;
|
||||
r_refdef.vrect.width = vid.width/2;
|
||||
|
@ -4263,6 +4293,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
r_refdef.pxrect.width = vid.pixelwidth/2;
|
||||
r_refdef.pxrect.height = vid.pixelheight/2;
|
||||
r_refdef.pxrect.y = r_refdef.pxrect.height;
|
||||
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
|
||||
qglClearColor(0, 0, 0, 0);
|
||||
qglClear(GL_COLOR_BUFFER_BIT);
|
||||
|
@ -4274,9 +4305,9 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
|
|||
r_refdef.recurse = false;
|
||||
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
|
||||
|
||||
qglViewport (oprect.x, oprect.height + oprect.y, oprect.width, oprect.height);
|
||||
r_refdef.vrect = orect;
|
||||
r_refdef.pxrect = oprect;
|
||||
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
}
|
||||
BE_SelectMode(oldbem);
|
||||
}
|
||||
|
@ -4388,7 +4419,10 @@ void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destco
|
|||
shaderstate.tex_sourcecol = sourcecol;
|
||||
shaderstate.tex_sourcedepth = sourcedepth;
|
||||
if (!destcol.num)
|
||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
{
|
||||
shaderstate.fbo_current = 0;
|
||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_current);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (usedepth)
|
||||
|
@ -4422,6 +4456,7 @@ void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destco
|
|||
}
|
||||
else
|
||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_diffuse);
|
||||
shaderstate.fbo_current = shaderstate.fbo_diffuse;
|
||||
|
||||
if (destdepth.num)
|
||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, destdepth.num, 0);
|
||||
|
@ -4440,6 +4475,8 @@ void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destco
|
|||
}
|
||||
else
|
||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_depthless);
|
||||
|
||||
shaderstate.fbo_current = shaderstate.fbo_depthless;
|
||||
}
|
||||
|
||||
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, destcol.num, 0);
|
||||
|
@ -4585,6 +4622,7 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis)
|
|||
|
||||
if (!r_refdef.recurse)
|
||||
{
|
||||
shaderstate.fbo_current = 0; //just in case something crashed
|
||||
GL_DoSwap();
|
||||
if (shaderstate.wbatch + 50 > shaderstate.maxwbatches)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -72,7 +72,7 @@ void GL_Draw_HL_AliasFrame(short *order, vec3_t *transformed, float tex_w, float
|
|||
=======================================================================================================================
|
||||
*/
|
||||
extern char loadname[];
|
||||
qboolean Mod_LoadHLModel (model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer)
|
||||
{
|
||||
/*~~*/
|
||||
int i;
|
||||
|
|
|
@ -39,14 +39,11 @@ char loadname[32]; // for hunk tags
|
|||
|
||||
void CM_Init(void);
|
||||
|
||||
qboolean Mod_LoadSpriteModel (model_t *mod, void *buffer);
|
||||
qboolean Mod_LoadSprite2Model (model_t *mod, void *buffer);
|
||||
qboolean Mod_LoadBrushModel (model_t *mod, void *buffer);
|
||||
qboolean QDECL Mod_LoadSpriteModel (model_t *mod, void *buffer);
|
||||
qboolean QDECL Mod_LoadSprite2Model (model_t *mod, void *buffer);
|
||||
qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer);
|
||||
#ifdef Q2BSPS
|
||||
qboolean Mod_LoadQ2BrushModel (model_t *mod, void *buffer);
|
||||
#endif
|
||||
#ifdef HALFLIFEMODELS
|
||||
qboolean Mod_LoadHLModel (model_t *mod, void *buffer);
|
||||
qboolean QDECL Mod_LoadQ2BrushModel (model_t *mod, void *buffer);
|
||||
#endif
|
||||
model_t *Mod_LoadModel (model_t *mod, qboolean crash);
|
||||
|
||||
|
@ -58,7 +55,7 @@ qboolean Mod_LoadDoomLevel(model_t *mod);
|
|||
void Mod_LoadDoomSprite (model_t *mod);
|
||||
#endif
|
||||
|
||||
#define MAX_MOD_KNOWN 2048
|
||||
#define MAX_MOD_KNOWN 8192
|
||||
model_t mod_known[MAX_MOD_KNOWN];
|
||||
int mod_numknown;
|
||||
|
||||
|
@ -438,33 +435,51 @@ void Mod_ClearAll (void)
|
|||
mod_datasequence++;
|
||||
}
|
||||
|
||||
//called after all new content has been precached
|
||||
void Mod_Flush(qboolean force)
|
||||
//can be called in one of two ways.
|
||||
//force=true: explicit flush. everything goes, even if its still in use.
|
||||
//force=false: map change. lots of stuff is no longer in use and can be freely flushed.
|
||||
//certain models cannot be safely flushed while still in use. such models will not be flushed even if forced (they may still be partially flushed).
|
||||
void Mod_Purge(enum mod_purge_e ptype)
|
||||
{
|
||||
int i;
|
||||
model_t *mod;
|
||||
qboolean unused;
|
||||
|
||||
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
|
||||
{
|
||||
if (mod->needload)
|
||||
continue;
|
||||
|
||||
unused = mod->datasequence != mod_datasequence;
|
||||
|
||||
//this model isn't active any more.
|
||||
if (mod->datasequence != mod_datasequence || force)
|
||||
if (unused || ptype != MP_MAPCHANGED)
|
||||
{
|
||||
Con_DPrintf("model \"%s\" no longer needed\n", mod->name);
|
||||
if (unused)
|
||||
Con_DPrintf("model \"%s\" no longer needed\n", mod->name);
|
||||
|
||||
#ifdef TERRAIN
|
||||
//we can safely flush all terrain sections at any time
|
||||
if (mod->terrain && ptype != MP_MAPCHANGED)
|
||||
Terr_PurgeTerrainModel(mod, false, true);
|
||||
#endif
|
||||
|
||||
//purge any vbos
|
||||
if (mod->type == mod_brush)
|
||||
{
|
||||
//brush models cannot be safely flushed.
|
||||
if (!unused && ptype != MP_RESET)
|
||||
continue;
|
||||
Surf_Clear(mod);
|
||||
}
|
||||
|
||||
#ifdef TERRAIN
|
||||
//nuke terrain buffers
|
||||
if (mod->terrain)
|
||||
if (mod->type == mod_brush || mod->type == mod_heightmap)
|
||||
{
|
||||
Terr_PurgeTerrainModel(mod, false, false);
|
||||
mod->terrain = NULL;
|
||||
//heightmap/terrain models cannot be safely flushed (brush models might have terrain embedded).
|
||||
if (!unused && ptype != MP_RESET)
|
||||
continue;
|
||||
Terr_FreeModel(mod);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -481,28 +496,71 @@ void Mod_Flush(qboolean force)
|
|||
Mod_Init
|
||||
===============
|
||||
*/
|
||||
void Mod_Init (void)
|
||||
void Mod_Init (qboolean initial)
|
||||
{
|
||||
Mod_ClearAll(); //shouldn't be needed
|
||||
Mod_Flush(true);//shouldn't be needed
|
||||
mod_numknown = 0;
|
||||
Q1BSP_Init();
|
||||
if (!initial)
|
||||
{
|
||||
Mod_ClearAll(); //shouldn't be needed
|
||||
Mod_Purge(MP_RESET);//shouldn't be needed
|
||||
mod_numknown = 0;
|
||||
Q1BSP_Init();
|
||||
|
||||
Cmd_AddCommand("mod_memlist", Mod_MemList_f);
|
||||
Cmd_AddCommand("mod_batchlist", Mod_BatchList_f);
|
||||
Cmd_AddCommand("mod_texturelist", Mod_TextureList_f);
|
||||
Cmd_AddCommand("mod_usetexture", Mod_BlockTextureColour_f);
|
||||
Cmd_AddCommand("mod_memlist", Mod_MemList_f);
|
||||
Cmd_AddCommand("mod_batchlist", Mod_BatchList_f);
|
||||
Cmd_AddCommand("mod_texturelist", Mod_TextureList_f);
|
||||
Cmd_AddCommand("mod_usetexture", Mod_BlockTextureColour_f);
|
||||
}
|
||||
|
||||
if (initial)
|
||||
{
|
||||
Alias_Register();
|
||||
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 Sprite (spr)", IDSPRITEHEADER, Mod_LoadSpriteModel);
|
||||
#ifdef SP2MODELS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake2 Sprite (sp2)", IDSPRITE2HEADER, Mod_LoadSprite2Model);
|
||||
#endif
|
||||
|
||||
//q2/q3bsps
|
||||
#ifdef Q2BSPS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake2/Quake2 Map (bsp)", IDBSPHEADER, Mod_LoadQ2BrushModel);
|
||||
#endif
|
||||
#ifdef Q3BSPS
|
||||
Mod_RegisterModelFormatMagic(NULL, "Raven Map (bsp)", ('R'<<0)+('B'<<8)+('S'<<16)+('P'<<24), Mod_LoadQ2BrushModel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "QFusion Map (bsp)", ('F'<<0)+('B'<<8)+('S'<<16)+('P'<<24), Mod_LoadQ2BrushModel);
|
||||
#endif
|
||||
|
||||
//doom maps
|
||||
#ifdef MAP_DOOM
|
||||
Mod_RegisterModelFormatMagic(NULL, "Doom IWad Map", (('D'<<24)+('A'<<16)+('W'<<8)+'I'), Mod_LoadDoomLevel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Doom PWad Map", (('D'<<24)+('A'<<16)+('W'<<8)+'P'), Mod_LoadDoomLevel);
|
||||
#endif
|
||||
|
||||
//q1-based formats
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 2PSB Map(bsp)", BSPVERSION_LONG1, Mod_LoadBrushModel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 BSP2 Map(bsp)", BSPVERSION_LONG2, Mod_LoadBrushModel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Half-Life Map (bsp)", 30, Mod_LoadBrushModel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 Map (bsp)", 29, Mod_LoadBrushModel);
|
||||
Mod_RegisterModelFormatMagic(NULL, "Quake1 Prerelease Map (bsp)", 28, Mod_LoadBrushModel);
|
||||
}
|
||||
}
|
||||
|
||||
void Mod_Shutdown (void)
|
||||
void Mod_Shutdown (qboolean final)
|
||||
{
|
||||
Mod_ClearAll();
|
||||
Mod_Flush(true);
|
||||
mod_numknown = 0;
|
||||
if (final)
|
||||
{
|
||||
Mod_UnRegisterAllModelFormats(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mod_ClearAll();
|
||||
Mod_Purge(MP_RESET);
|
||||
mod_numknown = 0;
|
||||
|
||||
Cmd_RemoveCommand("mod_batchlist");
|
||||
Cmd_RemoveCommand("mod_texturelist");
|
||||
Cmd_RemoveCommand("mod_usetexture");
|
||||
Cmd_RemoveCommand("mod_memlist");
|
||||
Cmd_RemoveCommand("mod_batchlist");
|
||||
Cmd_RemoveCommand("mod_texturelist");
|
||||
Cmd_RemoveCommand("mod_usetexture");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -604,6 +662,9 @@ model_t *Mod_FindName (char *name)
|
|||
mod->particletrail = -1;
|
||||
}
|
||||
|
||||
if (mod->needload == 2)
|
||||
mod->needload = true;
|
||||
|
||||
//mark it as active, so it doesn't get flushed prematurely
|
||||
mod->datasequence = mod_datasequence;
|
||||
return mod;
|
||||
|
@ -630,6 +691,93 @@ void Mod_TouchModel (char *name)
|
|||
}
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
void *module;
|
||||
char *formatname;
|
||||
char *ident;
|
||||
unsigned int magic;
|
||||
qboolean (QDECL *load) (model_t *mod, void *buffer);
|
||||
} modelloaders[64];
|
||||
|
||||
int Mod_RegisterModelFormatText(void *module, const char *formatname, char *magictext, qboolean (QDECL *load) (model_t *mod, void *buffer))
|
||||
{
|
||||
int i, free = -1;
|
||||
for (i = 0; i < sizeof(modelloaders)/sizeof(modelloaders[0]); i++)
|
||||
{
|
||||
if (modelloaders[i].ident && !strcmp(modelloaders[i].ident, magictext))
|
||||
{
|
||||
free = i;
|
||||
break; //extension match always replaces
|
||||
}
|
||||
else if (!modelloaders[i].load && free < 0)
|
||||
free = i;
|
||||
}
|
||||
if (free < 0)
|
||||
return 0;
|
||||
|
||||
modelloaders[free].module = module;
|
||||
modelloaders[free].formatname = Z_StrDup(formatname);
|
||||
modelloaders[free].magic = 0;
|
||||
modelloaders[free].ident = Z_StrDup(magictext);
|
||||
modelloaders[free].load = load;
|
||||
|
||||
return free+1;
|
||||
}
|
||||
int Mod_RegisterModelFormatMagic(void *module, const char *formatname, unsigned int magic, qboolean (QDECL *load) (model_t *mod, void *buffer))
|
||||
{
|
||||
int i, free = -1;
|
||||
for (i = 0; i < sizeof(modelloaders)/sizeof(modelloaders[0]); i++)
|
||||
{
|
||||
if (modelloaders[i].magic && modelloaders[i].magic == magic)
|
||||
{
|
||||
free = i;
|
||||
break; //extension match always replaces
|
||||
}
|
||||
else if (!modelloaders[i].load && free < 0)
|
||||
free = i;
|
||||
}
|
||||
if (free < 0)
|
||||
return 0;
|
||||
|
||||
modelloaders[free].module = module;
|
||||
if (modelloaders[free].formatname)
|
||||
Z_Free(modelloaders[free].formatname);
|
||||
modelloaders[free].formatname = Z_StrDup(formatname);
|
||||
modelloaders[free].magic = magic;
|
||||
modelloaders[free].ident = NULL;
|
||||
modelloaders[free].load = load;
|
||||
|
||||
return free+1;
|
||||
}
|
||||
|
||||
void Mod_UnRegisterModelFormat(int idx)
|
||||
{
|
||||
idx--;
|
||||
if ((unsigned int)(idx) >= sizeof(modelloaders)/sizeof(modelloaders[0]))
|
||||
return;
|
||||
|
||||
Z_Free(modelloaders[idx].ident);
|
||||
modelloaders[idx].ident = NULL;
|
||||
Z_Free(modelloaders[idx].formatname);
|
||||
modelloaders[idx].formatname = NULL;
|
||||
modelloaders[idx].magic = 0;
|
||||
modelloaders[idx].load = NULL;
|
||||
modelloaders[idx].module = NULL;
|
||||
|
||||
//FS_Restart will be needed
|
||||
}
|
||||
|
||||
void Mod_UnRegisterAllModelFormats(void *module)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sizeof(modelloaders)/sizeof(modelloaders[0]); i++)
|
||||
{
|
||||
if (modelloaders[i].module == module)
|
||||
Mod_UnRegisterModelFormat(i+1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Mod_LoadModel
|
||||
|
@ -644,6 +792,7 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
|
|||
char mdlbase[MAX_QPATH];
|
||||
char *replstr;
|
||||
qboolean doomsprite = false;
|
||||
unsigned int magic, i;
|
||||
|
||||
char *ext;
|
||||
|
||||
|
@ -685,6 +834,9 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (mod->needload == 2)
|
||||
return mod;
|
||||
|
||||
//
|
||||
// load the file
|
||||
//
|
||||
|
@ -783,141 +935,40 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
|
|||
//
|
||||
Mod_DoCRC(mod, (char*)buf, com_filesize);
|
||||
|
||||
switch (LittleLong(*(unsigned *)buf))
|
||||
magic = LittleLong(*(unsigned *)buf);
|
||||
for(i = 0; i < sizeof(modelloaders) / sizeof(modelloaders[0]); i++)
|
||||
{
|
||||
//The binary 3d mesh model formats
|
||||
case RAPOLYHEADER:
|
||||
case IDPOLYHEADER:
|
||||
TRACE(("Mod_LoadModel: Q1 mdl\n"));
|
||||
if (!Mod_LoadQ1Model(mod, buf))
|
||||
if (modelloaders[i].load && modelloaders[i].magic == magic && !modelloaders[i].ident)
|
||||
break;
|
||||
}
|
||||
if (i < sizeof(modelloaders) / sizeof(modelloaders[0]))
|
||||
{
|
||||
if (!modelloaders[i].load(mod, buf))
|
||||
continue;
|
||||
break;
|
||||
|
||||
#ifdef MD2MODELS
|
||||
case MD2IDALIASHEADER:
|
||||
TRACE(("Mod_LoadModel: md2\n"));
|
||||
if (!Mod_LoadQ2Model(mod, buf))
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef MD3MODELS
|
||||
case MD3_IDENT:
|
||||
TRACE(("Mod_LoadModel: md3\n"));
|
||||
if (!Mod_LoadQ3Model (mod, buf))
|
||||
continue;
|
||||
Surf_BuildModelLightmaps(mod);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HALFLIFEMODELS
|
||||
case (('T'<<24)+('S'<<16)+('D'<<8)+'I'):
|
||||
TRACE(("Mod_LoadModel: HL mdl\n"));
|
||||
if (!Mod_LoadHLModel (mod, buf))
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
//Binary skeletal model formats
|
||||
#ifdef ZYMOTICMODELS
|
||||
case (('O'<<24)+('M'<<16)+('Y'<<8)+'Z'):
|
||||
TRACE(("Mod_LoadModel: zym\n"));
|
||||
if (!Mod_LoadZymoticModel(mod, buf))
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
#ifdef DPMMODELS
|
||||
case (('K'<<24)+('R'<<16)+('A'<<8)+'D'):
|
||||
TRACE(("Mod_LoadModel: dpm\n"));
|
||||
if (!Mod_LoadDarkPlacesModel(mod, buf))
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef PSKMODELS
|
||||
case ('A'<<0)+('C'<<8)+('T'<<16)+('R'<<24):
|
||||
TRACE(("Mod_LoadModel: psk\n"));
|
||||
if (!Mod_LoadPSKModel (mod, buf))
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef INTERQUAKEMODELS
|
||||
case ('I'<<0)+('N'<<8)+('T'<<16)+('E'<<24):
|
||||
TRACE(("Mod_LoadModel: IQM\n"));
|
||||
if (!Mod_LoadInterQuakeModel (mod, buf))
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
//Binary Sprites
|
||||
#ifdef SP2MODELS
|
||||
case IDSPRITE2HEADER:
|
||||
TRACE(("Mod_LoadModel: q2 sp2\n"));
|
||||
if (!Mod_LoadSprite2Model (mod, buf))
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case IDSPRITEHEADER:
|
||||
TRACE(("Mod_LoadModel: q1 spr\n"));
|
||||
if (!Mod_LoadSpriteModel (mod, buf))
|
||||
continue;
|
||||
break;
|
||||
|
||||
|
||||
//Binary Map formats
|
||||
#if defined(Q2BSPS) || defined(Q3BSPS)
|
||||
case ('F'<<0)+('B'<<8)+('S'<<16)+('P'<<24):
|
||||
case ('R'<<0)+('B'<<8)+('S'<<16)+('P'<<24):
|
||||
case IDBSPHEADER: //looks like id switched to have proper ids
|
||||
TRACE(("Mod_LoadModel: q2/q3/raven/fusion bsp\n"));
|
||||
if (!Mod_LoadQ2BrushModel (mod, buf))
|
||||
continue;
|
||||
Surf_BuildModelLightmaps(mod);
|
||||
break;
|
||||
#endif
|
||||
#ifdef MAP_DOOM
|
||||
case (('D'<<24)+('A'<<16)+('W'<<8)+'I'): //the id is hacked by the FS .wad loader (main wad).
|
||||
case (('D'<<24)+('A'<<16)+('W'<<8)+'P'): //the id is hacked by the FS .wad loader (patch wad).
|
||||
TRACE(("Mod_LoadModel: doom iwad/pwad map\n"));
|
||||
if (!Mod_LoadDoomLevel (mod))
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case BSPVERSION_LONG1:
|
||||
Con_Printf("WARNING: %s is in a deprecated format\n", mod->name);
|
||||
case 30: //hl
|
||||
case 29: //q1
|
||||
case 28: //prerel
|
||||
case BSPVERSION_LONG2:
|
||||
TRACE(("Mod_LoadModel: hl/q1 bsp\n"));
|
||||
if (!Mod_LoadBrushModel (mod, buf))
|
||||
continue;
|
||||
Surf_BuildModelLightmaps(mod);
|
||||
break;
|
||||
|
||||
//Text based misc types.
|
||||
default:
|
||||
//check for text based headers
|
||||
if (mod->type == mod_brush)
|
||||
Surf_BuildModelLightmaps(mod);
|
||||
}
|
||||
else
|
||||
{
|
||||
COM_Parse((char*)buf);
|
||||
#ifdef MD5MODELS
|
||||
if (!strcmp(com_token, "MD5Version")) //doom3 format, text based, skeletal
|
||||
for(i = 0; i < sizeof(modelloaders) / sizeof(modelloaders[0]); i++)
|
||||
{
|
||||
TRACE(("Mod_LoadModel: md5mesh/md5anim\n"));
|
||||
if (!Mod_LoadMD5MeshModel (mod, buf))
|
||||
continue;
|
||||
break;
|
||||
if (modelloaders[i].load && modelloaders[i].ident && !strcmp(modelloaders[i].ident, com_token))
|
||||
break;
|
||||
}
|
||||
if (!strcmp(com_token, "EXTERNALANIM")) //custom format, text based, specifies skeletal models to load and which md5anim files to use.
|
||||
if (i < sizeof(modelloaders) / sizeof(modelloaders[0]))
|
||||
{
|
||||
TRACE(("Mod_LoadModel: blurgh\n"));
|
||||
if (!Mod_LoadCompositeAnim (mod, buf))
|
||||
if (!modelloaders[i].load(mod, buf))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
Con_Printf(CON_WARNING "Unrecognised model format 0x%x (%c%c%c%c)\n", LittleLong(*(unsigned *)buf), ((char*)buf)[0], ((char*)buf)[1], ((char*)buf)[2], ((char*)buf)[3]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#ifdef MAP_PROC
|
||||
if (!strcmp(com_token, "CM")) //doom3 map.
|
||||
{
|
||||
|
@ -927,19 +978,7 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef TERRAIN
|
||||
if (!strcmp(com_token, "terrain")) //custom format, text based.
|
||||
{
|
||||
TRACE(("Mod_LoadModel: terrain\n"));
|
||||
if (!Terr_LoadTerrainModel(mod, buf))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
Con_Printf(CON_WARNING "Unrecognised model format 0x%x (%c%c%c%c)\n", LittleLong(*(unsigned *)buf), ((char*)buf)[0], ((char*)buf)[1], ((char*)buf)[2], ((char*)buf)[3]);
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
P_LoadedModel(mod);
|
||||
Validation_IncludeFile(mod->name, (char *)buf, com_filesize);
|
||||
|
@ -974,7 +1013,7 @@ model_t *Mod_LoadModel (model_t *mod, qboolean crash)
|
|||
mod->maxs[0] = 16;
|
||||
mod->maxs[1] = 16;
|
||||
mod->maxs[2] = 16;
|
||||
mod->needload = true;
|
||||
mod->needload = 2;
|
||||
mod->engineflags = 0;
|
||||
P_LoadedModel(mod);
|
||||
return mod;
|
||||
|
@ -4007,7 +4046,7 @@ void Mod_FixupMinsMaxs(void)
|
|||
Mod_LoadBrushModel
|
||||
=================
|
||||
*/
|
||||
qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadBrushModel (model_t *mod, void *buffer)
|
||||
{
|
||||
int i, j;
|
||||
dheader_t *header;
|
||||
|
@ -4275,7 +4314,7 @@ TRACE(("LoadBrushModel %i\n", __LINE__));
|
|||
TRACE(("LoadBrushModel %i\n", __LINE__));
|
||||
|
||||
#ifdef TERRAIN
|
||||
lm->terrain = Mod_LoadTerrainInfo(lm, loadname);
|
||||
lm->terrain = Mod_LoadTerrainInfo(lm, loadname, false);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -4445,7 +4484,7 @@ static void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int fra
|
|||
Mod_LoadSpriteModel
|
||||
=================
|
||||
*/
|
||||
qboolean Mod_LoadSpriteModel (model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadSpriteModel (model_t *mod, void *buffer)
|
||||
{
|
||||
int i;
|
||||
int version;
|
||||
|
@ -4569,7 +4608,7 @@ qboolean Mod_LoadSpriteModel (model_t *mod, void *buffer)
|
|||
}
|
||||
|
||||
#ifdef SP2MODELS
|
||||
qboolean Mod_LoadSprite2Model (model_t *mod, void *buffer)
|
||||
qboolean QDECL Mod_LoadSprite2Model (model_t *mod, void *buffer)
|
||||
{
|
||||
int i;
|
||||
int version;
|
||||
|
|
|
@ -232,18 +232,6 @@ typedef struct
|
|||
#define SIDE_BACK 1
|
||||
#define SIDE_ON 2
|
||||
|
||||
|
||||
// plane_t structure
|
||||
// !!! if this is changed, it must be changed in asm_i386.h too !!!
|
||||
typedef struct mplane_s
|
||||
{
|
||||
vec3_t normal;
|
||||
float dist;
|
||||
qbyte type; // for texture axis selection and fast side tests
|
||||
qbyte signbits; // signx + signy<<1 + signz<<1
|
||||
qbyte pad[2];
|
||||
} mplane_t;
|
||||
|
||||
typedef struct vbo_s
|
||||
{
|
||||
unsigned int numvisible;
|
||||
|
@ -992,9 +980,9 @@ qbyte *Mod_LeafPVS (mleaf_t *leaf, model_t *model);
|
|||
#ifdef TERRAIN
|
||||
void Terr_Init(void);
|
||||
void Terr_DrawTerrainModel (batch_t **batch, entity_t *e);
|
||||
qboolean Terr_LoadTerrainModel (model_t *mod, void *buffer);
|
||||
void Terr_PurgeTerrainModel(model_t *mod, qboolean lightmapsonly, qboolean lightmapreusable);
|
||||
void *Mod_LoadTerrainInfo(model_t *mod, char *loadname); //call this after loading a bsp
|
||||
void Terr_FreeModel(model_t *mod);
|
||||
void Terr_PurgeTerrainModel(model_t *hm, qboolean lightmapsonly, qboolean lightmapreusable);
|
||||
void *Mod_LoadTerrainInfo(model_t *mod, char *loadname, qboolean force); //call this after loading a bsp
|
||||
qboolean Terrain_LocateSection(char *name, flocation_t *loc); //used on servers to generate sections for download.
|
||||
qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contentmask, struct trace_s *trace);
|
||||
unsigned int Heightmap_PointContents(model_t *model, vec3_t axis[3], vec3_t org);
|
||||
|
|
|
@ -194,13 +194,14 @@ void R_InitFlashblends(void)
|
|||
"blendfunc gl_one gl_one\n"
|
||||
"rgbgen vertex\n"
|
||||
"alphagen vertex\n"
|
||||
"nodepth\n"
|
||||
"}\n"
|
||||
"}\n"
|
||||
);
|
||||
lpplight_shader = NULL;
|
||||
}
|
||||
|
||||
static qboolean R_BuildDlightMesh(dlight_t *light, float colscale, float radscale, qboolean expand)
|
||||
static qboolean R_BuildDlightMesh(dlight_t *light, float colscale, float radscale, int dtype)
|
||||
{
|
||||
int i, j;
|
||||
// float a;
|
||||
|
@ -231,7 +232,7 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float colscale, float radscal
|
|||
}
|
||||
|
||||
VectorSubtract (light->origin, r_origin, v);
|
||||
if (Length (v) < rad + gl_mindist.value*2)
|
||||
if (dtype != 1 && Length (v) < rad + gl_mindist.value*2)
|
||||
{ // view is inside the dlight
|
||||
return false;
|
||||
}
|
||||
|
@ -250,10 +251,14 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float colscale, float radscal
|
|||
bub_sin++;
|
||||
bub_cos++;
|
||||
}
|
||||
if (!expand)
|
||||
VectorMA(flashblend_vcoords[0], -rad/1.5, vpn, flashblend_vcoords[0]);
|
||||
else
|
||||
if (dtype == 0)
|
||||
{
|
||||
//flashblend 3d-ish
|
||||
VectorMA(flashblend_vcoords[0], -rad/1.5, vpn, flashblend_vcoords[0]);
|
||||
}
|
||||
else if (dtype != 1)
|
||||
{
|
||||
//prepass lights needs to be fully infront of the light. the glsl is a fullscreen-style effect, but we can benefit from early-z and scissoring
|
||||
vec3_t diff;
|
||||
VectorSubtract(r_origin, light->origin, diff);
|
||||
VectorNormalize(diff);
|
||||
|
@ -274,10 +279,11 @@ void R_RenderDlights (void)
|
|||
dlight_t *l;
|
||||
vec3_t waste1, waste2;
|
||||
unsigned int beflags = 0;
|
||||
float intensity;
|
||||
float intensity, cscale;
|
||||
qboolean coronastyle;
|
||||
|
||||
if (r_coronas.value)
|
||||
beflags |= BEF_FORCENODEPTH;
|
||||
if (!r_coronas.value && !r_flashblend.value)
|
||||
return;
|
||||
|
||||
// r_dlightframecount = r_framecount + 1; // because the count hasn't
|
||||
// advanced yet for this frame
|
||||
|
@ -293,32 +299,38 @@ void R_RenderDlights (void)
|
|||
|
||||
if (l->flags & LFLAG_FLASHBLEND)
|
||||
{
|
||||
if (!r_flashblend.value)
|
||||
continue;
|
||||
//dlights emitting from the local player are not visible as flashblends
|
||||
if (l->key == r_refdef.playerview->viewentity)
|
||||
continue; //was a glow
|
||||
if (l->key == -(r_refdef.playerview->viewentity))
|
||||
continue; //was a muzzleflash
|
||||
coronastyle = false;
|
||||
}
|
||||
|
||||
intensity = l->corona * 0.25;
|
||||
if (r_flashblend.value && (l->flags & LFLAG_FLASHBLEND))
|
||||
intensity = l->corona; /*intensity is already in the corona value...*/
|
||||
else
|
||||
intensity = l->corona * r_coronas.value;
|
||||
if (intensity <= 0)
|
||||
coronastyle = true;
|
||||
|
||||
cscale = l->coronascale;
|
||||
intensity = l->corona * 0.25;
|
||||
if (coronastyle)
|
||||
intensity *= r_coronas.value;
|
||||
else
|
||||
intensity *= r_flashblend.value;
|
||||
if (intensity <= 0 || cscale <= 0)
|
||||
continue;
|
||||
|
||||
/*coronas use depth testing to compute visibility*/
|
||||
if (r_coronas.value)
|
||||
if (coronastyle)
|
||||
{
|
||||
if (TraceLineN(r_refdef.vieworg, l->origin, waste1, waste2))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!R_BuildDlightMesh (l, intensity, l->coronascale, false) && r_flashblend.value)
|
||||
if (!R_BuildDlightMesh (l, intensity, cscale, coronastyle) && !coronastyle)
|
||||
AddLightBlend (l->color[0], l->color[1], l->color[2], l->radius * 0.0003);
|
||||
else
|
||||
BE_DrawMesh_Single(flashblend_shader, &flashblend_mesh, NULL, &flashblend_shader->defaulttextures, beflags);
|
||||
BE_DrawMesh_Single(flashblend_shader, &flashblend_mesh, NULL, &flashblend_shader->defaulttextures, (coronastyle?BEF_FORCENODEPTH|BEF_FORCEADDITIVE:0)|beflags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,9 +340,9 @@ void R_GenDlightMesh(struct batch_s *batch)
|
|||
static mesh_t *meshptr;
|
||||
dlight_t *l = cl_dlights + batch->surf_first;
|
||||
|
||||
BE_SelectDLight(l, l->color, LSHADER_STANDARD);
|
||||
BE_SelectDLight(l, l->color, 0);
|
||||
|
||||
if (!R_BuildDlightMesh (l, 2, 1, true))
|
||||
if (!R_BuildDlightMesh (l, 2, 1, 2))
|
||||
{
|
||||
int i;
|
||||
static vec2_t s[4] = {{1, -1}, {-1, -1}, {-1, 1}, {1, 1}};
|
||||
|
@ -693,6 +705,7 @@ void R_ImportRTLights(char *entlump)
|
|||
break;
|
||||
VectorCopy(origin, dl->origin);
|
||||
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
|
||||
VectorInverse(dl->axis[1]);
|
||||
dl->radius = radius;
|
||||
VectorCopy(color, dl->color);
|
||||
dl->flags = 0;
|
||||
|
@ -827,6 +840,7 @@ void R_LoadRTLights(void)
|
|||
dl->lightcolourscales[1] = diffusescale;
|
||||
dl->lightcolourscales[2] = specularscale;
|
||||
AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]);
|
||||
VectorInverse(dl->axis[1]);
|
||||
|
||||
Q_strncpyz(dl->cubemapname, cubename, sizeof(dl->cubemapname));
|
||||
if (*dl->cubemapname)
|
||||
|
|
|
@ -950,12 +950,17 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
|
|||
// qglClipPlane(GL_CLIP_PLANE0, glplane);
|
||||
// qglEnable(GL_CLIP_PLANE0);
|
||||
// }
|
||||
frustum[4].normal[0] = plane.normal[0];
|
||||
frustum[4].normal[1] = plane.normal[1];
|
||||
frustum[4].normal[2] = plane.normal[2];
|
||||
frustum[4].dist = plane.dist + 0.01;
|
||||
if (portaltype == 1 || portaltype == 2)
|
||||
R_ObliqueNearClip(&frustum[4]);
|
||||
if (r_refdef.frustum_numplanes < MAXFRUSTUMPLANES)
|
||||
{
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[0] = plane.normal[0];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[1] = plane.normal[1];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].normal[2] = plane.normal[2];
|
||||
r_refdef.frustum[r_refdef.frustum_numplanes].dist = plane.dist + 0.01;
|
||||
|
||||
if (portaltype == 1 || portaltype == 2)
|
||||
R_ObliqueNearClip(&r_refdef.frustum[r_refdef.frustum_numplanes]);
|
||||
r_refdef.frustum_numplanes++;
|
||||
}
|
||||
R_RenderScene();
|
||||
// if (qglClipPlane)
|
||||
// qglDisable(GL_CLIP_PLANE0);
|
||||
|
@ -970,7 +975,6 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, int portaltype)
|
|||
/*broken stuff*/
|
||||
AngleVectors (r_refdef.viewangles, vpn, vright, vup);
|
||||
VectorCopy (r_refdef.vieworg, r_origin);
|
||||
R_SetFrustum (r_refdef.m_projection, r_refdef.m_view);
|
||||
|
||||
if (qglLoadMatrixf)
|
||||
{
|
||||
|
@ -1394,6 +1398,9 @@ void GLR_RenderView (void)
|
|||
if ((r_refdef.flags & Q2RDF_NOWORLDMODEL) || r_secondaryview)
|
||||
return;
|
||||
|
||||
if (r_secondaryview)
|
||||
return;
|
||||
|
||||
if (r_bloom.value)
|
||||
R_BloomBlend();
|
||||
|
||||
|
|
|
@ -218,7 +218,9 @@ static enum {
|
|||
SPM_DOOM3,
|
||||
} shaderparsemode;
|
||||
|
||||
shader_t *r_shaders;
|
||||
unsigned int r_numshaders;
|
||||
unsigned int r_maxshaders;
|
||||
shader_t **r_shaders;
|
||||
static hashtable_t shader_active_hash;
|
||||
void *shader_active_hash_mem;
|
||||
|
||||
|
@ -1866,21 +1868,10 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarnames, int *cvarty
|
|||
#endif
|
||||
}
|
||||
|
||||
static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr, int qrtype)
|
||||
static char *Shader_ParseBody(char *debugname, char **ptr)
|
||||
{
|
||||
/*accepts:
|
||||
program
|
||||
{
|
||||
BLAH
|
||||
}
|
||||
where BLAH is both vertex+frag with #ifdefs
|
||||
or
|
||||
program fname
|
||||
on one line.
|
||||
*/
|
||||
char *programbody;
|
||||
char *body;
|
||||
char *start, *end;
|
||||
char *hash;
|
||||
|
||||
end = *ptr;
|
||||
while (*end == ' ' || *end == '\t' || *end == '\r')
|
||||
|
@ -1893,7 +1884,7 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p
|
|||
end++;
|
||||
if (*end != '{')
|
||||
{
|
||||
Con_Printf("shader \"%s\" missing program string\n", shader->name);
|
||||
Con_Printf("shader \"%s\" missing program string\n", debugname);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1910,22 +1901,45 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p
|
|||
else if (*end == '{')
|
||||
count++;
|
||||
}
|
||||
programbody = BZ_Malloc(end - start + 1);
|
||||
memcpy(programbody, start, end-start);
|
||||
programbody[end-start] = 0;
|
||||
body = BZ_Malloc(end - start + 1);
|
||||
memcpy(body, start, end-start);
|
||||
body[end-start] = 0;
|
||||
*ptr = end+1;/*skip over it all*/
|
||||
|
||||
shader->prog = malloc(sizeof(*shader->prog));
|
||||
memset(shader->prog, 0, sizeof(*shader->prog));
|
||||
shader->prog->refs = 1;
|
||||
if (!Shader_LoadPermutations(shader->name, shader->prog, programbody, qrtype, 0))
|
||||
{
|
||||
free(shader->prog);
|
||||
shader->prog = NULL;
|
||||
}
|
||||
|
||||
BZ_Free(programbody);
|
||||
return body;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr, int qrtype)
|
||||
{
|
||||
/*accepts:
|
||||
program
|
||||
{
|
||||
BLAH
|
||||
}
|
||||
where BLAH is both vertex+frag with #ifdefs
|
||||
or
|
||||
program fname
|
||||
on one line.
|
||||
*/
|
||||
char *programbody;
|
||||
char *hash;
|
||||
|
||||
programbody = Shader_ParseBody(shader->name, ptr);
|
||||
if (programbody)
|
||||
{
|
||||
shader->prog = malloc(sizeof(*shader->prog));
|
||||
memset(shader->prog, 0, sizeof(*shader->prog));
|
||||
shader->prog->refs = 1;
|
||||
if (!Shader_LoadPermutations(shader->name, shader->prog, programbody, qrtype, 0))
|
||||
{
|
||||
free(shader->prog);
|
||||
shader->prog = NULL;
|
||||
}
|
||||
|
||||
BZ_Free(programbody);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2129,6 +2143,87 @@ static void Shader_DP_Camera(shader_t *shader, shaderpass_t *pass, char **ptr)
|
|||
shader->sort = SHADER_SORT_PORTAL;
|
||||
}
|
||||
|
||||
static void Shader_BEMode(shader_t *shader, shaderpass_t *pass, char **ptr)
|
||||
{
|
||||
int mode;
|
||||
char tokencopy[1024];
|
||||
char *token;
|
||||
char *embed = NULL;
|
||||
token = Shader_ParseString(ptr);
|
||||
if (!Q_stricmp(token, "rtlight"))
|
||||
mode = -1; //all light types
|
||||
else if (!Q_stricmp(token, "rtlight_only"))
|
||||
mode = LSHADER_STANDARD;
|
||||
else if (!Q_stricmp(token, "rtlight_smap"))
|
||||
mode = LSHADER_SMAP;
|
||||
else if (!Q_stricmp(token, "rtlight_spot"))
|
||||
mode = LSHADER_SPOT;
|
||||
else if (!Q_stricmp(token, "rtlight_cube"))
|
||||
mode = LSHADER_CUBE;
|
||||
else if (!Q_stricmp(token, "rtlight_cube_smap"))
|
||||
mode = LSHADER_CUBE|LSHADER_SMAP;
|
||||
else if (!Q_stricmp(token, "rtlight_cube_spot")) //doesn't make sense.
|
||||
mode = LSHADER_CUBE|LSHADER_SPOT;
|
||||
else if (!Q_stricmp(token, "rtlight_spot_smap"))
|
||||
mode = LSHADER_SMAP|LSHADER_SPOT;
|
||||
else if (!Q_stricmp(token, "rtlight_cube_spot_smap")) //doesn't make sense.
|
||||
mode = LSHADER_CUBE|LSHADER_SPOT|LSHADER_SMAP;
|
||||
else if (!Q_stricmp(token, "crepuscular"))
|
||||
mode = bemoverride_crepuscular;
|
||||
else if (!Q_stricmp(token, "depthonly"))
|
||||
mode = bemoverride_depthonly;
|
||||
else if (!Q_stricmp(token, "depthdark"))
|
||||
mode = bemoverride_depthdark;
|
||||
else if (!Q_stricmp(token, "prelight"))
|
||||
mode = bemoverride_prelight;
|
||||
else if (!Q_stricmp(token, "fog"))
|
||||
mode = bemoverride_fog;
|
||||
else
|
||||
{
|
||||
Con_DPrintf(CON_WARNING "Shader %s specifies unknown bemode %s.\n", shader->name, token);
|
||||
return; //not supported.
|
||||
}
|
||||
|
||||
embed = Shader_ParseBody(shader->name, ptr);
|
||||
if (embed)
|
||||
{
|
||||
int l = strlen(embed) + 6;
|
||||
char *b = BZ_Malloc(l);
|
||||
Q_snprintfz(b, l, "{\n%s\n}\n", embed);
|
||||
BZ_Free(embed);
|
||||
embed = b;
|
||||
//generate a unique name
|
||||
Q_snprintfz(tokencopy, sizeof(tokencopy), "%s_mode%i", shader->name, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
token = Shader_ParseString(ptr);
|
||||
Q_strncpyz(tokencopy, token, sizeof(tokencopy)); //make sure things don't go squiff.
|
||||
}
|
||||
|
||||
if (mode == -1)
|
||||
{
|
||||
//shorthand for rtlights
|
||||
for (mode = 0; mode < LSHADER_MODES; mode++)
|
||||
{
|
||||
if ((mode & LSHADER_CUBE) && (mode & LSHADER_SPOT))
|
||||
continue;
|
||||
shader->bemoverrides[mode] = R_RegisterCustom(va("%s%s%s%s",
|
||||
tokencopy,
|
||||
(mode & LSHADER_SMAP)?"#PCF":"",
|
||||
(mode & LSHADER_SPOT)?"#SPOT":"",
|
||||
(mode & LSHADER_CUBE)?"#CUBE":"")
|
||||
, shader->usageflags, embed?Shader_DefaultScript:NULL, embed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->bemoverrides[mode] = R_RegisterCustom(tokencopy, shader->usageflags, embed?Shader_DefaultScript:NULL, embed);
|
||||
}
|
||||
if (embed)
|
||||
BZ_Free(embed);
|
||||
}
|
||||
|
||||
static shaderkey_t shaderkeys[] =
|
||||
{
|
||||
{"cull", Shader_Cull},
|
||||
|
@ -2141,13 +2236,16 @@ static shaderkey_t shaderkeys[] =
|
|||
{"sort", Shader_Sort},
|
||||
{"deformvertexes", Shader_DeformVertexes},
|
||||
{"portal", Shader_Portal},
|
||||
{"lpp_light", Shader_Prelight},
|
||||
{"entitymergable", Shader_EntityMergable},
|
||||
|
||||
//fte extensions
|
||||
{"lpp_light", Shader_Prelight},
|
||||
{"glslprogram", Shader_GLSLProgramName},
|
||||
{"program", Shader_ProgramName}, //legacy
|
||||
{"program", Shader_ProgramName}, //gl or d3d
|
||||
{"hlslprogram", Shader_HLSLProgramName}, //for d3d
|
||||
{"param", Shader_ProgramParam},
|
||||
{"param", Shader_ProgramParam}, //legacy
|
||||
|
||||
{"bemode", Shader_BEMode},
|
||||
|
||||
//dp compat
|
||||
{"dp_camera", Shader_DP_Camera},
|
||||
|
@ -3055,7 +3153,9 @@ qboolean Shader_Init (void)
|
|||
|
||||
if (!r_shaders)
|
||||
{
|
||||
r_shaders = calloc(MAX_SHADERS, sizeof(shader_t));
|
||||
r_numshaders = 0;
|
||||
r_maxshaders = 256;
|
||||
r_shaders = calloc(r_maxshaders, sizeof(*r_shaders));
|
||||
|
||||
shader_hash = calloc (HASH_SIZE, sizeof(*shader_hash));
|
||||
|
||||
|
@ -3216,15 +3316,17 @@ void Shader_Shutdown (void)
|
|||
shader_t *shader;
|
||||
shadercache_t *cache, *cache_next;
|
||||
|
||||
shader = r_shaders;
|
||||
if (!r_shaders)
|
||||
return; /*nothing needs freeing yet*/
|
||||
for (i = 0; i < MAX_SHADERS; i++, shader++)
|
||||
for (i = 0; i < r_numshaders; i++)
|
||||
{
|
||||
if (!shader->uses)
|
||||
shader = r_shaders[i];
|
||||
if (!shader || !shader->uses)
|
||||
continue;
|
||||
|
||||
Shader_Free(shader);
|
||||
Z_Free(r_shaders[i]);
|
||||
r_shaders[i] = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < HASH_SIZE; i++)
|
||||
|
@ -3241,6 +3343,9 @@ void Shader_Shutdown (void)
|
|||
|
||||
Shader_FlushGenerics();
|
||||
|
||||
r_maxshaders = 0;
|
||||
r_numshaders = 0;
|
||||
|
||||
free(r_shaders);
|
||||
r_shaders = NULL;
|
||||
free(shader_hash);
|
||||
|
@ -4977,18 +5082,21 @@ void R_UnloadShader(shader_t *shader)
|
|||
if (shader->uses-- == 1)
|
||||
Shader_Free(shader);
|
||||
}
|
||||
static int R_LoadShader (char *name, unsigned int usageflags, shader_gen_t *defaultgen, const char *genargs)
|
||||
static shader_t *R_LoadShader (char *name, unsigned int usageflags, shader_gen_t *defaultgen, const char *genargs)
|
||||
{
|
||||
int i, f = -1;
|
||||
char shortname[MAX_QPATH];
|
||||
char *hash;
|
||||
shader_t *s;
|
||||
|
||||
if (!*name)
|
||||
name = "gfx/white";
|
||||
|
||||
if (strchr(name, '#'))
|
||||
hash = strchr(name, '#');
|
||||
if (hash) //don't strip anything.
|
||||
{
|
||||
Q_strncpyz(shortname, name, sizeof(shortname));
|
||||
hash = shortname+(hash-name);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5007,17 +5115,16 @@ static int R_LoadShader (char *name, unsigned int usageflags, shader_gen_t *defa
|
|||
//q3 has a separate (internal) shader for every lightmap.
|
||||
if (!((s->usageflags ^ usageflags) & SUF_LIGHTMAP))
|
||||
{
|
||||
i = s - r_shaders;
|
||||
r_shaders[i].uses++;
|
||||
return i;
|
||||
s->uses++;
|
||||
return s;
|
||||
}
|
||||
s = Hash_GetNext(&shader_active_hash, shortname, s);
|
||||
}
|
||||
|
||||
// not loaded, find a free slot
|
||||
for (i = 0; i < MAX_SHADERS; i++)
|
||||
for (i = 0; i < r_numshaders; i++)
|
||||
{
|
||||
if (!r_shaders[i].uses)
|
||||
if (!r_shaders[i] || !r_shaders[i]->uses)
|
||||
{
|
||||
if ( f == -1 ) // free shader
|
||||
{
|
||||
|
@ -5027,13 +5134,32 @@ static int R_LoadShader (char *name, unsigned int usageflags, shader_gen_t *defa
|
|||
}
|
||||
}
|
||||
|
||||
if ( f == -1 )
|
||||
if (f == -1)
|
||||
{
|
||||
Sys_Error( "R_LoadShader: Shader limit exceeded.");
|
||||
return f;
|
||||
shader_t **n;
|
||||
int nm;
|
||||
f = r_numshaders;
|
||||
if (f == r_maxshaders)
|
||||
{
|
||||
nm = r_maxshaders * 2;
|
||||
n = realloc(r_shaders, nm*sizeof(*n));
|
||||
if (!n)
|
||||
{
|
||||
Sys_Error( "R_LoadShader: Shader limit exceeded.");
|
||||
return NULL;
|
||||
}
|
||||
memset(n+r_maxshaders, 0, (nm - r_maxshaders)*sizeof(*n));
|
||||
r_shaders = n;
|
||||
r_maxshaders = nm;
|
||||
}
|
||||
}
|
||||
|
||||
s = &r_shaders[f];
|
||||
s = r_shaders[f];
|
||||
if (!s)
|
||||
s = r_shaders[f] = Z_Malloc(sizeof(*s));
|
||||
s->id = f;
|
||||
if (r_numshaders < f+1)
|
||||
r_numshaders = f+1;
|
||||
|
||||
Q_strncpyz(s->name, shortname, sizeof(s->name));
|
||||
s->usageflags = usageflags;
|
||||
|
@ -5043,6 +5169,10 @@ static int R_LoadShader (char *name, unsigned int usageflags, shader_gen_t *defa
|
|||
else
|
||||
s->genargs = NULL;
|
||||
|
||||
//now strip off the hash so we find the right shader script
|
||||
if (hash)
|
||||
*hash = 0;
|
||||
|
||||
if (ruleset_allow_shaders.ival)
|
||||
{
|
||||
#ifdef GLQUAKE
|
||||
|
@ -5052,21 +5182,21 @@ static int R_LoadShader (char *name, unsigned int usageflags, shader_gen_t *defa
|
|||
{
|
||||
if (Shader_ParseShader(va("%s_gles2", shortname), shortname, s))
|
||||
{
|
||||
return f;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
if (gl_config.glversion >= 3)
|
||||
{
|
||||
if (Shader_ParseShader(va("%s_glsl3", shortname), shortname, s))
|
||||
{
|
||||
return f;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
if (gl_config.arb_shader_objects)
|
||||
{
|
||||
if (Shader_ParseShader(va("%s_glsl", shortname), shortname, s))
|
||||
{
|
||||
return f;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5077,7 +5207,7 @@ static int R_LoadShader (char *name, unsigned int usageflags, shader_gen_t *defa
|
|||
{
|
||||
if (Shader_ParseShader(va("%s_hlsl", shortname), shortname, s))
|
||||
{
|
||||
return f;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5088,14 +5218,14 @@ static int R_LoadShader (char *name, unsigned int usageflags, shader_gen_t *defa
|
|||
{
|
||||
if (Shader_ParseShader(va("%s_hlsl11", shortname), shortname, s))
|
||||
{
|
||||
return f;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (Shader_ParseShader(shortname, shortname, s))
|
||||
{
|
||||
return f;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5113,13 +5243,13 @@ static int R_LoadShader (char *name, unsigned int usageflags, shader_gen_t *defa
|
|||
"}\n");
|
||||
else
|
||||
s->generator(shortname, s, s->genargs);
|
||||
return f;
|
||||
return s;
|
||||
}
|
||||
else
|
||||
{
|
||||
Shader_Free(s);
|
||||
}
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Shader_DoReload(void)
|
||||
|
@ -5147,9 +5277,10 @@ void Shader_DoReload(void)
|
|||
Font_InvalidateColour();
|
||||
Shader_ReloadGenerics();
|
||||
|
||||
for (s = r_shaders, i = 0; i < MAX_SHADERS; i++, s++)
|
||||
for (i = 0; i < r_numshaders; i++)
|
||||
{
|
||||
if (!s->uses)
|
||||
s = r_shaders[i];
|
||||
if (!s || !s->uses)
|
||||
continue;
|
||||
|
||||
strcpy(shortname, s->name);
|
||||
|
@ -5215,6 +5346,7 @@ cin_t *R_ShaderFindCinematic(char *name)
|
|||
#else
|
||||
int i;
|
||||
char shortname[MAX_QPATH];
|
||||
shader_t *s;
|
||||
|
||||
if (!r_shaders)
|
||||
return NULL;
|
||||
|
@ -5224,19 +5356,16 @@ cin_t *R_ShaderFindCinematic(char *name)
|
|||
COM_CleanUpPath(shortname);
|
||||
|
||||
//try and find it
|
||||
for (i = 0; i < MAX_SHADERS; i++)
|
||||
for (i = 0; i < r_numshaders; i++)
|
||||
{
|
||||
if (!r_shaders[i].uses)
|
||||
s = r_shaders[i];
|
||||
if (!s || !s->uses)
|
||||
continue;
|
||||
|
||||
if (!Q_stricmp (shortname, r_shaders[i].name) )
|
||||
break;
|
||||
if (!Q_stricmp (shortname, s->name) )
|
||||
return R_ShaderGetCinematic(s);
|
||||
}
|
||||
if (i == MAX_SHADERS)
|
||||
return NULL;
|
||||
|
||||
//found the named shader.
|
||||
return R_ShaderGetCinematic(&r_shaders[i]);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -5248,7 +5377,7 @@ shader_t *R_RegisterPic (char *name)
|
|||
image_width = 64;
|
||||
image_height = 64;
|
||||
|
||||
shader = &r_shaders[R_LoadShader (name, SUF_2D, Shader_Default2D, NULL)];
|
||||
shader = R_LoadShader (name, SUF_2D, Shader_Default2D, NULL);
|
||||
|
||||
/*worth a try*/
|
||||
if (shader->width <= 0)
|
||||
|
@ -5266,22 +5395,22 @@ shader_t *R_RegisterPic (char *name)
|
|||
|
||||
shader_t *R_RegisterShader (char *name, unsigned int usageflags, const char *shaderscript)
|
||||
{
|
||||
return &r_shaders[R_LoadShader (name, usageflags, Shader_DefaultScript, shaderscript)];
|
||||
return R_LoadShader (name, usageflags, Shader_DefaultScript, shaderscript);
|
||||
}
|
||||
|
||||
shader_t *R_RegisterShader_Lightmap (char *name)
|
||||
{
|
||||
return &r_shaders[R_LoadShader (name, SUF_LIGHTMAP, Shader_DefaultBSPLM, NULL)];
|
||||
return R_LoadShader (name, SUF_LIGHTMAP, Shader_DefaultBSPLM, NULL);
|
||||
}
|
||||
|
||||
shader_t *R_RegisterShader_Vertex (char *name)
|
||||
{
|
||||
return &r_shaders[R_LoadShader (name, 0, Shader_DefaultBSPVertex, NULL)];
|
||||
return R_LoadShader (name, 0, Shader_DefaultBSPVertex, NULL);
|
||||
}
|
||||
|
||||
shader_t *R_RegisterShader_Flare (char *name)
|
||||
{
|
||||
return &r_shaders[R_LoadShader (name, 0, Shader_DefaultBSPFlare, NULL)];
|
||||
return R_LoadShader (name, 0, Shader_DefaultBSPFlare, NULL);
|
||||
}
|
||||
|
||||
shader_t *R_RegisterSkin (char *shadername, char *modname)
|
||||
|
@ -5296,7 +5425,7 @@ shader_t *R_RegisterSkin (char *shadername, char *modname)
|
|||
memcpy(newsname, modname, b - modname);
|
||||
memcpy(newsname + (b-modname), shadername, strlen(shadername)+1);
|
||||
/*if the specified shader does not contain a path, try and load one relative to the name of the model*/
|
||||
shader = &r_shaders[R_LoadShader (newsname, 0, Shader_DefaultSkin, NULL)];
|
||||
shader = R_LoadShader (newsname, 0, Shader_DefaultSkin, NULL);
|
||||
|
||||
R_BuildDefaultTexnums(&shader->defaulttextures, shader);
|
||||
|
||||
|
@ -5305,15 +5434,11 @@ shader_t *R_RegisterSkin (char *shadername, char *modname)
|
|||
return shader;
|
||||
}
|
||||
}
|
||||
shader = &r_shaders[R_LoadShader (shadername, 0, Shader_DefaultSkin, NULL)];
|
||||
shader = R_LoadShader (shadername, 0, Shader_DefaultSkin, NULL);
|
||||
return shader;
|
||||
}
|
||||
shader_t *R_RegisterCustom (char *name, unsigned int usageflags, shader_gen_t *defaultgen, const void *args)
|
||||
{
|
||||
int i;
|
||||
i = R_LoadShader (name, usageflags, defaultgen, args);
|
||||
if (i < 0)
|
||||
return NULL;
|
||||
return &r_shaders[i];
|
||||
return R_LoadShader (name, usageflags, defaultgen, args);
|
||||
}
|
||||
#endif //SERVERONLY
|
||||
|
|
|
@ -61,7 +61,7 @@ cvar_t r_editlights_import_radius = SCVAR ("r_editlights_import_radius", "1");
|
|||
cvar_t r_editlights_import_ambient = SCVAR ("r_editlights_import_ambient", "0");
|
||||
cvar_t r_editlights_import_diffuse = SCVAR ("r_editlights_import_diffuse", "1");
|
||||
cvar_t r_editlights_import_specular = SCVAR ("r_editlights_import_specular", "1"); //excessive, but noticable. its called stylized, okay? shiesh, some people
|
||||
cvar_t r_shadow_shadowmapping = SCVARF ("debug_r_shadow_shadowmapping", "0", 0);
|
||||
cvar_t r_shadow_shadowmapping = SCVARF ("r_shadow_shadowmapping", "1", 0);
|
||||
cvar_t r_shadow_shadowmapping_precision = CVARD ("r_shadow_shadowmapping_precision", "1", "Scales the shadowmap detail level up or down.");
|
||||
extern cvar_t r_shadow_shadowmapping_nearclip;
|
||||
extern cvar_t r_shadow_shadowmapping_bias;
|
||||
|
@ -70,7 +70,7 @@ cvar_t r_sun_colour = CVARFD ("r_sun_colour", "0 0 0", CVAR_ARCHIVE, "Spec
|
|||
|
||||
static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour);
|
||||
|
||||
|
||||
static qbyte lvisb[(MAX_MAP_LEAFS+7)>>3];
|
||||
|
||||
/*
|
||||
called on framebuffer resize.
|
||||
|
@ -975,7 +975,7 @@ static void SHM_MarkLeavesQ2(dlight_t *dl, unsigned char *lvis, unsigned char *v
|
|||
cluster = leaf->cluster;
|
||||
if (cluster == -1)
|
||||
continue;
|
||||
if (lvis[cluster>>3] & vvis[cluster>>3] & (1<<(cluster&7)))
|
||||
if (lvis[cluster>>3] & /*vvis[cluster>>3] &*/ (1<<(cluster&7)))
|
||||
{
|
||||
node = (mnode_t *)leaf;
|
||||
do
|
||||
|
@ -1363,77 +1363,91 @@ static struct shadowmesh_s *SHM_BuildShadowMesh(dlight_t *dl, unsigned char *lvi
|
|||
if (dl->worldshadowmesh && !dl->rebuildcache && dl->worldshadowmesh->type == type)
|
||||
return dl->worldshadowmesh;
|
||||
|
||||
if (!lvis)
|
||||
{
|
||||
int leaf;
|
||||
leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin);
|
||||
lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb));
|
||||
}
|
||||
|
||||
firstedge=0;
|
||||
|
||||
if (cl.worldmodel->type == mod_brush)
|
||||
switch(cl.worldmodel->fromgame)
|
||||
{
|
||||
case fg_quake:
|
||||
case fg_halflife:
|
||||
/*if (!dl->die)
|
||||
{
|
||||
SHM_BeginShadowMesh(dl, true);
|
||||
SHM_MarkLeavesQ1(dl, lvis);
|
||||
SHM_RecursiveWorldNodeQ1_r(dl, cl.worldmodel->nodes);
|
||||
if (!surfonly)
|
||||
SHM_ComposeVolume_BruteForce(dl);
|
||||
}
|
||||
else*/
|
||||
switch(cl.worldmodel->fromgame)
|
||||
{
|
||||
case fg_quake:
|
||||
case fg_halflife:
|
||||
/*if (!dl->die)
|
||||
{
|
||||
SHM_BeginShadowMesh(dl, true);
|
||||
SHM_MarkLeavesQ1(dl, lvis);
|
||||
SHM_RecursiveWorldNodeQ1_r(dl, cl.worldmodel->nodes);
|
||||
if (!surfonly)
|
||||
SHM_ComposeVolume_BruteForce(dl);
|
||||
}
|
||||
else*/
|
||||
{
|
||||
SHM_BeginShadowMesh(dl, type);
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
msurface_t *surf;
|
||||
for (i = 0; i < cl.worldmodel->numsurfaces; i+=2)
|
||||
{
|
||||
surf = &cl.worldmodel->surfaces[i];
|
||||
SHM_Shadow_Cache_Surface(surf);
|
||||
SHM_MeshFrontOnly(surf->mesh->numvertexes, surf->mesh->xyz_array, surf->mesh->numindexes, surf->mesh->indexes);
|
||||
}
|
||||
memset(sh_shmesh->litleaves, 0xff, sh_shmesh->leafbytes);
|
||||
}
|
||||
#else
|
||||
SHM_MarkLeavesQ1(dl, lvis);
|
||||
SHM_RecursiveWorldNodeQ1_r(dl, cl.worldmodel->nodes);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#ifdef Q2BSPS
|
||||
case fg_quake2:
|
||||
SHM_BeginShadowMesh(dl, type);
|
||||
SHM_MarkLeavesQ2(dl, lvis, vvis);
|
||||
SHM_RecursiveWorldNodeQ2_r(dl, cl.worldmodel->nodes);
|
||||
break;
|
||||
#endif
|
||||
#ifdef Q3BSPS
|
||||
case fg_quake3:
|
||||
/*q3 doesn't have edge info*/
|
||||
SHM_BeginShadowMesh(dl, type);
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
msurface_t *surf;
|
||||
for (i = 0; i < cl.worldmodel->numsurfaces; i+=2)
|
||||
{
|
||||
surf = &cl.worldmodel->surfaces[i];
|
||||
SHM_Shadow_Cache_Surface(surf);
|
||||
SHM_MeshFrontOnly(surf->mesh->numvertexes, surf->mesh->xyz_array, surf->mesh->numindexes, surf->mesh->indexes);
|
||||
int i;
|
||||
msurface_t *surf;
|
||||
for (i = 0; i < cl.worldmodel->numsurfaces; i++)
|
||||
{
|
||||
surf = &cl.worldmodel->surfaces[i];
|
||||
SHM_Shadow_Cache_Surface(surf);
|
||||
SHM_MeshFrontOnly(surf->mesh->numvertexes, surf->mesh->xyz_array, surf->mesh->numindexes, surf->mesh->indexes);
|
||||
}
|
||||
memset(sh_shmesh->litleaves, 0xff, sh_shmesh->leafbytes);
|
||||
}
|
||||
memset(sh_shmesh->litleaves, 0xff, sh_shmesh->leafbytes);
|
||||
}
|
||||
#else
|
||||
SHM_MarkLeavesQ1(dl, lvis);
|
||||
SHM_RecursiveWorldNodeQ1_r(dl, cl.worldmodel->nodes);
|
||||
sh_shadowframe++;
|
||||
SHM_RecursiveWorldNodeQ3_r(dl, cl.worldmodel->nodes);
|
||||
if (type == SMT_STENCILVOLUME)
|
||||
SHM_ComposeVolume_BruteForce(dl);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
#ifdef Q2BSPS
|
||||
case fg_quake2:
|
||||
}
|
||||
else
|
||||
{
|
||||
SHM_BeginShadowMesh(dl, type);
|
||||
SHM_MarkLeavesQ2(dl, lvis, vvis);
|
||||
SHM_RecursiveWorldNodeQ2_r(dl, cl.worldmodel->nodes);
|
||||
break;
|
||||
#endif
|
||||
#ifdef Q3BSPS
|
||||
case fg_quake3:
|
||||
/*q3 doesn't have edge info*/
|
||||
SHM_BeginShadowMesh(dl, type);
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
msurface_t *surf;
|
||||
for (i = 0; i < cl.worldmodel->numsurfaces; i++)
|
||||
{
|
||||
surf = &cl.worldmodel->surfaces[i];
|
||||
SHM_Shadow_Cache_Surface(surf);
|
||||
SHM_MeshFrontOnly(surf->mesh->numvertexes, surf->mesh->xyz_array, surf->mesh->numindexes, surf->mesh->indexes);
|
||||
}
|
||||
memset(sh_shmesh->litleaves, 0xff, sh_shmesh->leafbytes);
|
||||
}
|
||||
#else
|
||||
sh_shadowframe++;
|
||||
SHM_RecursiveWorldNodeQ3_r(dl, cl.worldmodel->nodes);
|
||||
if (type == SMT_STENCILVOLUME)
|
||||
SHM_ComposeVolume_BruteForce(dl);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*generate edge polys for map types that need it (q1/q2)*/
|
||||
|
@ -2033,11 +2047,11 @@ void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize)
|
||||
void GL_EndRenderBuffer_DepthOnly(int restorefbo, texid_t depthtexture, int texsize)
|
||||
{
|
||||
if (gl_config.ext_framebuffer_objects)
|
||||
{
|
||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, restorefbo);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2047,6 +2061,7 @@ void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize)
|
|||
}
|
||||
|
||||
//determine the 5 bounding points of a shadowmap light projection side
|
||||
//needs to match Sh_GenShadowFace
|
||||
static void Sh_LightFrustumPlanes(dlight_t *l, vec4_t *planes, int face)
|
||||
{
|
||||
vec3_t tmp;
|
||||
|
@ -2075,64 +2090,86 @@ static void Sh_LightFrustumPlanes(dlight_t *l, vec4_t *planes, int face)
|
|||
}
|
||||
}
|
||||
|
||||
//culling for the face happens in the caller.
|
||||
//these faces should thus match Sh_LightFrustumPlanes
|
||||
static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int smsize, float proj[16])
|
||||
{
|
||||
vec3_t t1,t2;
|
||||
vec3_t t1,t2,t3;
|
||||
texture_t *tex;
|
||||
int tno;
|
||||
|
||||
//FIXME: figure out the four lines bounding the light cone by just adding its +forward+/-right+/-up values. if any point towards a plane (and starts outside that plane), and the point of intersection with that line and the frustum side plane is infront of the near clip plane, then that light frustum needs to be rendered...
|
||||
switch(face)
|
||||
{
|
||||
case 0:
|
||||
//+x - forward
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, l->axis[0], l->axis[1], l->axis[2], l->origin);
|
||||
//down
|
||||
VectorCopy(l->axis[0], t1);
|
||||
VectorCopy(l->axis[1], t2);
|
||||
VectorCopy(l->axis[2], t3);
|
||||
Matrix4x4_CM_LightMatrixFromAxis(r_refdef.m_view, t1, t2, t3, l->origin);
|
||||
r_refdef.flipcull = 0;
|
||||
break;
|
||||
case 1:
|
||||
//+y - right
|
||||
VectorNegate(l->axis[0], t1);
|
||||
VectorNegate(l->axis[1], t2);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, t2, t1, l->axis[2], l->origin);
|
||||
//back
|
||||
VectorCopy(l->axis[2], t1);
|
||||
VectorCopy(l->axis[1], t2);
|
||||
VectorCopy(l->axis[0], t3);
|
||||
Matrix4x4_CM_LightMatrixFromAxis(r_refdef.m_view, t1, t2, t3, l->origin);
|
||||
r_refdef.flipcull = SHADER_CULL_FLIP;
|
||||
break;
|
||||
case 2:
|
||||
//+z - down
|
||||
VectorNegate(l->axis[0], t1);
|
||||
VectorNegate(l->axis[2], t2);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, t2, l->axis[1], t1, l->origin);
|
||||
//right
|
||||
VectorCopy(l->axis[0], t1);
|
||||
VectorCopy(l->axis[2], t2);
|
||||
VectorCopy(l->axis[1], t3);
|
||||
Matrix4x4_CM_LightMatrixFromAxis(r_refdef.m_view, t1, t2, t3, l->origin);
|
||||
r_refdef.flipcull = SHADER_CULL_FLIP;
|
||||
break;
|
||||
case 3:
|
||||
//-x - back
|
||||
VectorNegate(l->axis[0], t1);
|
||||
// VectorNegate(l->axis[1], t2);
|
||||
// VectorNegate(l->axis[2], t3);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, t1, l->axis[1], l->axis[2], l->origin);
|
||||
//up
|
||||
VectorCopy(l->axis[0], t1);
|
||||
VectorCopy(l->axis[1], t2);
|
||||
VectorCopy(l->axis[2], t3);
|
||||
VectorNegate(t3, t3);
|
||||
Matrix4x4_CM_LightMatrixFromAxis(r_refdef.m_view, t1, t2, t3, l->origin);
|
||||
r_refdef.flipcull = SHADER_CULL_FLIP;
|
||||
break;
|
||||
case 4:
|
||||
//-y - left
|
||||
VectorNegate(l->axis[1], t1);
|
||||
VectorNegate(l->axis[0], t2);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, l->axis[1], t2, l->axis[2], l->origin);
|
||||
//forward
|
||||
VectorCopy(l->axis[2], t1);
|
||||
VectorCopy(l->axis[1], t2);
|
||||
VectorCopy(l->axis[0], t3);
|
||||
VectorNegate(t3, t3);
|
||||
Matrix4x4_CM_LightMatrixFromAxis(r_refdef.m_view, t1, t2, t3, l->origin);
|
||||
r_refdef.flipcull = 0;
|
||||
break;
|
||||
case 5:
|
||||
//-z - up
|
||||
VectorNegate(l->axis[0], t2);
|
||||
Matrix4x4_CM_ModelViewMatrixFromAxis(r_refdef.m_view, l->axis[2], l->axis[1], t2, l->origin);
|
||||
//left
|
||||
VectorCopy(l->axis[0], t1);
|
||||
VectorCopy(l->axis[2], t2);
|
||||
VectorCopy(l->axis[1], t3);
|
||||
VectorNegate(t3, t3);
|
||||
Matrix4x4_CM_LightMatrixFromAxis(r_refdef.m_view, t1, t2, t3, l->origin);
|
||||
r_refdef.flipcull = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (l->fov)
|
||||
qglViewport (0, 0, smsize, smsize);
|
||||
{
|
||||
r_refdef.pxrect.x = 0;
|
||||
r_refdef.pxrect.width = smsize;
|
||||
r_refdef.pxrect.height = smsize;
|
||||
r_refdef.pxrect.y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
qglViewport ((face%3 * SHADOWMAP_SIZE) + (SHADOWMAP_SIZE-smsize)/2, ((face>=3)*SHADOWMAP_SIZE) + (SHADOWMAP_SIZE-smsize)/2, smsize, smsize);
|
||||
r_refdef.pxrect.x = (face%3 * SHADOWMAP_SIZE) + (SHADOWMAP_SIZE-smsize)/2;
|
||||
r_refdef.pxrect.width = smsize;
|
||||
r_refdef.pxrect.height = smsize;
|
||||
r_refdef.pxrect.y = r_refdef.pxrect.height - (((face>=3)*SHADOWMAP_SIZE) + (SHADOWMAP_SIZE-smsize)/2);
|
||||
}
|
||||
|
||||
qglViewport (r_refdef.pxrect.x, r_refdef.pxrect.height-r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
|
||||
R_SetFrustum(proj, r_refdef.m_view);
|
||||
|
||||
#ifdef DBG_COLOURNOTDEPTH
|
||||
|
@ -2210,8 +2247,10 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, int sms
|
|||
|
||||
qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
|
||||
{
|
||||
int restorefbo;
|
||||
int f;
|
||||
float oproj[16], oview[16];
|
||||
vrect_t oprect;
|
||||
shadowmesh_t *smesh;
|
||||
int isspot = (l->fov != 0);
|
||||
extern cvar_t r_shadow_shadowmapping_precision;
|
||||
|
@ -2231,11 +2270,11 @@ qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
|
|||
float dist;
|
||||
int fp,lp;
|
||||
Sh_LightFrustumPlanes(l, planes, f);
|
||||
for (fp = 0; fp < FRUSTUMPLANES; fp++)
|
||||
for (fp = 0; fp < r_refdef.frustum_numplanes; fp++)
|
||||
{
|
||||
vec3_t nearest;
|
||||
//make a guess based upon the frustum plane
|
||||
VectorMA(l->origin, l->radius, frustum[fp].normal, nearest);
|
||||
VectorMA(l->origin, l->radius, r_refdef.frustum[fp].normal, nearest);
|
||||
//clip that point to the various planes
|
||||
|
||||
for(lp = 0; lp < 5; lp++)
|
||||
|
@ -2247,11 +2286,11 @@ qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
|
|||
|
||||
// P_RunParticleEffect(nearest, vec3_origin, 15, 1);
|
||||
//give up if the best point for any frustum plane is offscreen
|
||||
dist = DotProduct(frustum[fp].normal, nearest) - frustum[fp].dist;
|
||||
dist = DotProduct(r_refdef.frustum[fp].normal, nearest) - r_refdef.frustum[fp].dist;
|
||||
if (dist <= 0)
|
||||
break;
|
||||
}
|
||||
if (fp == FRUSTUMPLANES)
|
||||
if (fp == r_refdef.frustum_numplanes)
|
||||
sidevisible |= 1u<<f;
|
||||
}
|
||||
}
|
||||
|
@ -2299,11 +2338,11 @@ qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
|
|||
qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
|
||||
}
|
||||
|
||||
smesh = SHM_BuildShadowMesh(l, lvis, NULL, true);
|
||||
smesh = SHM_BuildShadowMesh(l, lvis, NULL, SMT_SHADOWMAP);
|
||||
|
||||
/*set framebuffer*/
|
||||
GL_BeginRenderBuffer_DepthOnly(shadowmap[isspot]);
|
||||
GLBE_SetupForShadowMap(shadowmap[isspot], isspot?smsize:smsize*3, isspot?smsize:smsize*2, (smsize-4) / (float)SHADOWMAP_SIZE);
|
||||
restorefbo = GLBE_SetupForShadowMap(shadowmap[isspot], isspot?smsize:smsize*3, isspot?smsize:smsize*2, (smsize-4) / (float)SHADOWMAP_SIZE);
|
||||
|
||||
BE_Scissor(NULL);
|
||||
qglViewport(0, 0, smsize*3, smsize*2);
|
||||
|
@ -2315,6 +2354,7 @@ qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
|
|||
|
||||
memcpy(oproj, r_refdef.m_projection, sizeof(oproj));
|
||||
memcpy(oview, r_refdef.m_view, sizeof(oview));
|
||||
oprect = r_refdef.pxrect;
|
||||
|
||||
Matrix4x4_CM_Projection_Far(r_refdef.m_projection, l->fov?l->fov:90, l->fov?l->fov:90, r_shadow_shadowmapping_nearclip.value, l->radius);
|
||||
if (!gl_config.nofixedfunc)
|
||||
|
@ -2337,10 +2377,11 @@ qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
|
|||
}
|
||||
|
||||
/*end framebuffer*/
|
||||
GL_EndRenderBuffer_DepthOnly(shadowmap[isspot], smsize);
|
||||
GL_EndRenderBuffer_DepthOnly(restorefbo, shadowmap[isspot], smsize);
|
||||
|
||||
memcpy(r_refdef.m_view, oview, sizeof(r_refdef.m_view));
|
||||
memcpy(r_refdef.m_projection, oproj, sizeof(r_refdef.m_projection));
|
||||
r_refdef.pxrect = oprect;
|
||||
|
||||
if (!gl_config.nofixedfunc)
|
||||
{
|
||||
|
@ -2350,7 +2391,7 @@ qboolean Sh_GenShadowMap (dlight_t *l, qbyte *lvis, int smsize)
|
|||
qglLoadMatrixf(r_refdef.m_view);
|
||||
}
|
||||
|
||||
qglViewport(r_refdef.pxrect.x, vid.pixelheight - r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
qglViewport(r_refdef.pxrect.x, r_refdef.pxrect.y-r_refdef.pxrect.height, r_refdef.pxrect.width, r_refdef.pxrect.height);
|
||||
|
||||
r_refdef.flipcull = oldflip;
|
||||
r_refdef.externalview = oldexternalview;
|
||||
|
@ -2363,7 +2404,6 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis)
|
|||
{
|
||||
vec3_t mins, maxs;
|
||||
qbyte *lvis;
|
||||
qbyte lvisb[MAX_MAP_LEAFS/8];
|
||||
srect_t rect;
|
||||
int smsize;
|
||||
|
||||
|
@ -2647,7 +2687,7 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q
|
|||
struct shadowmesh_s *sm;
|
||||
entity_t *ent;
|
||||
|
||||
sm = SHM_BuildShadowMesh(dl, lvis, vvis, false);
|
||||
sm = SHM_BuildShadowMesh(dl, lvis, vvis, SMT_STENCILVOLUME);
|
||||
if (!sm)
|
||||
Sh_DrawBrushModelShadow(dl, &r_worldentity);
|
||||
else
|
||||
|
@ -2729,8 +2769,6 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
|
|||
qbyte *lvis;
|
||||
srect_t rect;
|
||||
|
||||
qbyte lvisb[MAX_MAP_LEAFS/8];
|
||||
|
||||
vec3_t mins;
|
||||
vec3_t maxs;
|
||||
|
||||
|
@ -2986,12 +3024,11 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis)
|
|||
{
|
||||
int leaf;
|
||||
qbyte *lvis;
|
||||
qbyte lvisb[MAX_MAP_LEAFS/8];
|
||||
|
||||
leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, dl->origin);
|
||||
lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb));
|
||||
|
||||
SHM_BuildShadowMesh(dl, lvis, vvis, true);
|
||||
SHM_BuildShadowMesh(dl, lvis, vvis, SMT_SHADOWLESS);
|
||||
|
||||
if (!Sh_VisOverlaps(lvis, vvis)) //The two viewing areas do not intersect.
|
||||
{
|
||||
|
@ -3124,6 +3161,7 @@ void Sh_PurgeShadowMeshes(void)
|
|||
{
|
||||
SH_FreeShadowMesh(dl->worldshadowmesh);
|
||||
dl->worldshadowmesh = NULL;
|
||||
dl->rebuildcache = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3135,7 +3173,6 @@ void Sh_PreGenerateLights(void)
|
|||
int shadowtype;
|
||||
int leaf;
|
||||
qbyte *lvis;
|
||||
qbyte lvisb[MAX_MAP_LEAFS/8];
|
||||
int i;
|
||||
|
||||
if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival)
|
||||
|
@ -3150,6 +3187,8 @@ void Sh_PreGenerateLights(void)
|
|||
|
||||
for (dl = cl_dlights+rtlights_first, i=rtlights_first; i<rtlights_max; i++, dl++)
|
||||
{
|
||||
dl->rebuildcache = true;
|
||||
|
||||
if (dl->radius)
|
||||
{
|
||||
if (dl->flags & ignoreflags)
|
||||
|
@ -3157,7 +3196,7 @@ void Sh_PreGenerateLights(void)
|
|||
if (dl->flags & LFLAG_CREPUSCULAR)
|
||||
continue;
|
||||
|
||||
if (((!dl->die)?!r_shadow_realtime_world_shadows.ival:!r_shadow_realtime_dlight_shadows.ival) || dl->flags & LFLAG_NOSHADOWS)
|
||||
if (((!dl->die)?!r_shadow_realtime_world_shadows.ival:!r_shadow_realtime_dlight_shadows.ival) || (dl->flags & LFLAG_NOSHADOWS))
|
||||
shadowtype = SMT_SHADOWLESS;
|
||||
else if (dl->flags & LFLAG_SHADOWMAP || r_shadow_shadowmapping.ival)
|
||||
shadowtype = SMT_SHADOWMAP;
|
||||
|
@ -3198,43 +3237,33 @@ void Sh_DrawLights(qbyte *vis)
|
|||
int i;
|
||||
unsigned int ignoreflags;
|
||||
|
||||
if (!r_shadow_realtime_world.ival && !r_shadow_realtime_dlight.ival)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (r_shadow_realtime_world.modified ||
|
||||
r_shadow_realtime_dlight_shadows.modified ||
|
||||
r_shadow_realtime_dlight.modified ||
|
||||
r_shadow_realtime_dlight_shadows.modified ||
|
||||
r_shadow_shadowmapping.modified)
|
||||
{
|
||||
r_shadow_realtime_world.modified =
|
||||
r_shadow_realtime_dlight_shadows.modified =
|
||||
r_shadow_realtime_dlight.modified =
|
||||
r_shadow_realtime_dlight_shadows.modified =
|
||||
r_shadow_shadowmapping.modified =
|
||||
false;
|
||||
//make sure the lighting is reloaded
|
||||
Sh_PreGenerateLights();
|
||||
}
|
||||
|
||||
switch(qrenderer)
|
||||
{
|
||||
#ifdef GLQUAKE
|
||||
case QR_OPENGL:
|
||||
/*no stencil?*/
|
||||
/*if (!gl_config.arb_shader_objects)
|
||||
{
|
||||
Con_Printf("Missing GL extensions: switching off realtime lighting.\n");
|
||||
r_shadow_realtime_world.ival = 0;
|
||||
r_shadow_realtime_dlight.ival = 0;
|
||||
return;
|
||||
}*/
|
||||
if (r_shadow_shadowmapping.ival)
|
||||
{ //if we've no glsl or fbos, shadowmapping ain't possible, so don't use it.
|
||||
if (!gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !gl_config.arb_shadow)
|
||||
{
|
||||
//disable stuff if we can't cope with it
|
||||
Con_Printf("Missing GL extensions: switching off shadowmapping.\n");
|
||||
r_shadow_shadowmapping.ival = 0;
|
||||
}
|
||||
}
|
||||
if (!r_shadow_shadowmapping.ival)
|
||||
{ //if we're using stencil shadows, give up if there's no stencil buffer
|
||||
if (!gl_stencilbits)
|
||||
{
|
||||
Con_Printf("Missing GL extensions: switching off realtime lighting.\n");
|
||||
r_shadow_realtime_world.ival = 0;
|
||||
r_shadow_realtime_dlight.ival = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef D3D9QUAKE
|
||||
case QR_DIRECT3D9:
|
||||
r_shadow_shadowmapping.ival = 0;
|
||||
#ifdef GLQUAKE
|
||||
//the code still has a lot of ifdefs, so will crash if you try it in a merged build.
|
||||
//its not really usable in d3d-only builds either, so no great loss.
|
||||
|
@ -3246,8 +3275,30 @@ void Sh_DrawLights(qbyte *vis)
|
|||
return;
|
||||
}
|
||||
|
||||
if (r_shadow_realtime_world.modified ||
|
||||
r_shadow_realtime_world_shadows.modified ||
|
||||
r_shadow_realtime_dlight.modified ||
|
||||
r_shadow_realtime_dlight_shadows.modified ||
|
||||
r_shadow_shadowmapping.modified)
|
||||
{
|
||||
r_shadow_realtime_world.modified =
|
||||
r_shadow_realtime_world_shadows.modified =
|
||||
r_shadow_realtime_dlight.modified =
|
||||
r_shadow_realtime_dlight_shadows.modified =
|
||||
r_shadow_shadowmapping.modified =
|
||||
false;
|
||||
//make sure the lighting is reloaded
|
||||
Sh_PreGenerateLights();
|
||||
}
|
||||
|
||||
if (!r_shadow_realtime_world.ival && !r_shadow_realtime_dlight.ival)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ignoreflags = (r_shadow_realtime_world.value?LFLAG_REALTIMEMODE:LFLAG_NORMALMODE);
|
||||
|
||||
// if (r_refdef.recurse)
|
||||
for (dl = cl_dlights+rtlights_first, i=rtlights_first; i<rtlights_max; i++, dl++)
|
||||
{
|
||||
if (!dl->radius)
|
||||
|
@ -3296,7 +3347,8 @@ void Sh_DrawLights(qbyte *vis)
|
|||
}
|
||||
}
|
||||
|
||||
if (1)
|
||||
#ifdef GLQUAKE
|
||||
if (gl_config.arb_shader_objects)
|
||||
{
|
||||
dlight_t sun = {0};
|
||||
vec3_t sundir;
|
||||
|
@ -3328,6 +3380,7 @@ void Sh_DrawLights(qbyte *vis)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BE_Scissor(NULL);
|
||||
|
||||
|
|
|
@ -905,6 +905,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
|||
qglBindVertexArray = NULL;
|
||||
}
|
||||
|
||||
gl_config.arb_shadow = GL_CheckExtension("GL_ARB_shadow");
|
||||
gl_config.arb_shadow |= GL_CheckExtension("GL_EXT_shadow_samplers"); //gles2
|
||||
|
||||
#ifndef GL_STATIC
|
||||
if (GL_CheckExtension("GL_ARB_framebuffer_object"))
|
||||
{
|
||||
|
@ -1136,6 +1139,109 @@ static const char *glsl_hdrs[] =
|
|||
"#endif\n"
|
||||
"}\n"
|
||||
,
|
||||
"sys/pcf.h",
|
||||
"#ifndef r_glsl_pcf\n"
|
||||
"#define r_glsl_pcf 9\n"
|
||||
"#endif\n"
|
||||
"#if r_glsl_pcf < 1\n"
|
||||
"#undef r_glsl_pcf\n"
|
||||
"#define r_glsl_pcf 9\n"
|
||||
"#endif\n"
|
||||
"uniform vec4 l_shadowmapproj;\n" //light projection matrix info
|
||||
"uniform vec2 l_shadowmapscale;\n" //xy are the texture scale, z is 1, w is the scale.
|
||||
"vec3 ShadowmapCoord(void)\n"
|
||||
"{\n"
|
||||
"#ifdef SPOT\n"
|
||||
//bias it. don't bother figuring out which side or anything, its not needed
|
||||
//l_projmatrix contains the light's projection matrix so no other magic needed
|
||||
"vtexprojcoord.z -= 0.015;\n"
|
||||
"return (vtexprojcoord.xyz/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n"
|
||||
//"#elif defined(CUBESHADOW)\n"
|
||||
// vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w;
|
||||
// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r
|
||||
"#else\n"
|
||||
//figure out which axis to use
|
||||
//texture is arranged thusly:
|
||||
//forward left up
|
||||
//back right down
|
||||
"vec3 dir = abs(vtexprojcoord.xyz);\n"
|
||||
//assume z is the major axis (ie: forward from the light)
|
||||
"vec3 t = vtexprojcoord.xyz;\n"
|
||||
"float ma = dir.z;\n"
|
||||
"vec3 axis = vec3(0.5/3.0, 0.5/2.0, 0.5);\n"
|
||||
"if (dir.x > ma)\n"
|
||||
"{\n"
|
||||
"ma = dir.x;\n"
|
||||
"t = vtexprojcoord.zyx;\n"
|
||||
"axis.x = 0.5;\n"
|
||||
"}\n"
|
||||
"if (dir.y > ma)\n"
|
||||
"{\n"
|
||||
"ma = dir.y;\n"
|
||||
"t = vtexprojcoord.xzy;\n"
|
||||
"axis.x = 2.5/3.0;\n"
|
||||
"}\n"
|
||||
//if the axis is negative, flip it.
|
||||
"if (t.z > 0.0)\n"
|
||||
"{\n"
|
||||
"axis.y = 1.5/2.0;\n"
|
||||
"t.z = -t.z;\n"
|
||||
"}\n"
|
||||
|
||||
//we also need to pass the result through the light's projection matrix too
|
||||
//the 'matrix' we need only contains 5 actual values. and one of them is a -1. So we might as well just use a vec4.
|
||||
//note: the projection matrix also includes scalers to pinch the image inwards to avoid sampling over borders, as well as to cope with non-square source image
|
||||
//the resulting z is prescaled to result in a value between -0.5 and 0.5.
|
||||
//also make sure we're in the right quadrant type thing
|
||||
"return axis + ((l_shadowmapproj.xyz*t.xyz + vec3(0.0, 0.0, l_shadowmapproj.w)) / -t.z);\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
|
||||
"float ShadowmapFilter(sampler2DShadow samp)\n"
|
||||
"{\n"
|
||||
"vec3 shadowcoord = ShadowmapCoord();\n"
|
||||
|
||||
"#if 0\n"//def GL_ARB_texture_gather
|
||||
"vec2 ipart, fpart;\n"
|
||||
"#define dosamp(x,y) textureGatherOffset(s_t4, ipart.xy, vec2(x,y)))\n"
|
||||
"vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n"
|
||||
"vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));\n"
|
||||
"vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));\n"
|
||||
"vec4 br = step(shadowcoord.z, dosamp(1.0, 1.0));\n"
|
||||
//we now have 4*4 results, woo
|
||||
//we can just average them for 1/16th precision, but that's still limited graduations
|
||||
//the middle four pixels are 'full strength', but we interpolate the sides to effectively give 3*3
|
||||
"vec4 col = vec4(tl.ba, tr.ba) + vec4(bl.rg, br.rg) + " //middle two rows are full strength
|
||||
"mix(vec4(tl.rg, tr.rg), vec4(bl.ba, br.ba), fpart.y);\n" //top+bottom rows
|
||||
"return dot(mix(col.rgb, col.agb, fpart.x), vec3(1.0/9.0));\n" //blend r+a, gb are mixed because its pretty much free and gives a nicer dot instruction instead of lots of adds.
|
||||
"#else\n"
|
||||
"#define dosamp(x,y) shadow2D(samp, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n"
|
||||
"float s = 0.0;\n"
|
||||
"#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n"
|
||||
"s += dosamp(0.0, 0.0);\n"
|
||||
"return s;\n"
|
||||
"#elif r_glsl_pcf >= 5 && r_glsl_pcf < 9\n"
|
||||
"s += dosamp(-1.0, 0.0);\n"
|
||||
"s += dosamp(0.0, -1.0);\n"
|
||||
"s += dosamp(0.0, 0.0);\n"
|
||||
"s += dosamp(0.0, 1.0);\n"
|
||||
"s += dosamp(1.0, 0.0);\n"
|
||||
"return s/5.0;\n"
|
||||
"#else\n"
|
||||
"s += dosamp(-1.0, -1.0);\n"
|
||||
"s += dosamp(-1.0, 0.0);\n"
|
||||
"s += dosamp(-1.0, 1.0);\n"
|
||||
"s += dosamp(0.0, -1.0);\n"
|
||||
"s += dosamp(0.0, 0.0);\n"
|
||||
"s += dosamp(0.0, 1.0);\n"
|
||||
"s += dosamp(1.0, -1.0);\n"
|
||||
"s += dosamp(1.0, 0.0);\n"
|
||||
"s += dosamp(1.0, 1.0);\n"
|
||||
"return s/9.0;\n"
|
||||
"#endif\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -1296,7 +1402,7 @@ GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstan
|
|||
"#ifdef FRAMEBLEND\n"
|
||||
"attribute vec3 v_position2;\n"
|
||||
"uniform vec2 e_vblend;\n"
|
||||
"#define v_position ((v_position*e_vblend.x)+(v_position2*e_vblend.y))\n"
|
||||
"#define v_position ((v_position1*e_vblend.x)+(v_position2*e_vblend.y))\n"
|
||||
"#else\n"
|
||||
"#define v_position v_position1\n"
|
||||
"#endif\n"
|
||||
|
@ -1429,7 +1535,7 @@ GLhandleARB GLSlang_CreateProgramObject (char *name, GLhandleARB vert, GLhandleA
|
|||
qglAttachObjectARB(program, vert);
|
||||
qglAttachObjectARB(program, frag);
|
||||
|
||||
qglBindAttribLocationARB(program, VATTR_VERTEX1, "v_position");
|
||||
qglBindAttribLocationARB(program, VATTR_VERTEX1, "v_position1");
|
||||
qglBindAttribLocationARB(program, VATTR_COLOUR, "v_colour");
|
||||
#if MAXRLIGHTMAPS > 1
|
||||
qglBindAttribLocationARB(program, VATTR_COLOUR2, "v_colour2");
|
||||
|
|
|
@ -118,7 +118,6 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
|
|||
vid.pixelwidth = info->width;
|
||||
vid.pixelheight = info->height;
|
||||
vid.numpages = 3;
|
||||
gl_canstencil = 0;
|
||||
|
||||
const EGLint attribs[] = {
|
||||
EGL_RENDERABLE_TYPE, (sys_glesversion>=2)?EGL_OPENGL_ES2_BIT:EGL_OPENGL_ES_BIT,
|
||||
|
|
|
@ -206,6 +206,7 @@ typedef struct {
|
|||
qboolean arb_texture_compression;
|
||||
// qboolean arb_fragment_program;
|
||||
qboolean arb_shader_objects;
|
||||
qboolean arb_shadow;
|
||||
qboolean ext_framebuffer_objects;
|
||||
qboolean ext_stencil_wrap;
|
||||
qboolean ext_packed_depth_stencil;
|
||||
|
@ -276,8 +277,6 @@ extern vec3_t r_entorigin;
|
|||
extern entity_t *currententity;
|
||||
extern int r_visframecount; // ??? what difs?
|
||||
extern int r_framecount;
|
||||
#define FRUSTUMPLANES 5
|
||||
extern mplane_t frustum[FRUSTUMPLANES];
|
||||
|
||||
extern float r_wateralphaval;
|
||||
extern qboolean r_loadbumpmapping;
|
||||
|
|
|
@ -232,7 +232,7 @@ void QuaternionGLMatrix(float x, float y, float z, float w, vec4_t *GLM);
|
|||
//void UploadTexture(hlmdl_tex_t *ptexture, qbyte *data, qbyte *pal);
|
||||
|
||||
/* HL drawing */
|
||||
qboolean Mod_LoadHLModel (model_t *mod, void *buffer);
|
||||
qboolean QDECL Mod_LoadHLModel (model_t *mod, void *buffer);
|
||||
void R_DrawHLModel(entity_t *curent);
|
||||
|
||||
/* physics stuff */
|
||||
|
|
|
@ -1709,12 +1709,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
"#ifdef PCF\n"
|
||||
"uniform vec4 l_shadowmapproj; //light projection matrix info\n"
|
||||
"uniform vec2 l_shadowmapscale; //xy are the texture scale, z is 1, w is the scale.\n"
|
||||
"#endif\n"
|
||||
|
||||
|
||||
|
||||
|
||||
"#ifdef PCF\n"
|
||||
"vec3 ShadowmapCoord(void)\n"
|
||||
"{\n"
|
||||
"#ifdef SPOT\n"
|
||||
|
@ -1814,6 +1808,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
"#ifdef OFFSETMAPPING\n"
|
||||
"#include \"sys/offsetmapping.h\"\n"
|
||||
"#endif\n"
|
||||
|
||||
"void main ()\n"
|
||||
"{\n"
|
||||
//read raw texture samples (offsetmapping munges the tex coords first)
|
||||
|
@ -2036,16 +2031,67 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
"varying vec2 lm;\n"
|
||||
"varying vec4 vc;\n"
|
||||
|
||||
"#ifdef RTLIGHT\n"
|
||||
"varying vec3 lightvector;\n"
|
||||
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
|
||||
// varying vec3 eyevector;
|
||||
// #endif
|
||||
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
|
||||
"varying vec4 vtexprojcoord;\n"
|
||||
"#endif\n"
|
||||
"#endif\n"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"#ifdef VERTEX_SHADER\n"
|
||||
|
||||
"#ifdef RTLIGHT\n"
|
||||
"uniform vec3 l_lightposition;\n"
|
||||
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
|
||||
// uniform vec3 e_eyepos;
|
||||
// #endif
|
||||
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
|
||||
"uniform mat4 l_cubematrix;\n"
|
||||
"#endif\n"
|
||||
"attribute vec3 v_normal;\n"
|
||||
"attribute vec3 v_svector;\n"
|
||||
"attribute vec3 v_tvector;\n"
|
||||
"#endif\n"
|
||||
|
||||
"attribute vec2 v_texcoord;\n"
|
||||
"attribute vec2 v_lmcoord;\n"
|
||||
"attribute vec4 v_colour;\n"
|
||||
|
||||
"void main (void)\n"
|
||||
"{\n"
|
||||
"tc = v_texcoord.st;\n"
|
||||
"lm = v_lmcoord.st;\n"
|
||||
"vc = v_colour;\n"
|
||||
"gl_Position = ftetransform();\n"
|
||||
|
||||
"#ifdef RTLIGHT\n"
|
||||
//light position is in model space, which is handy.
|
||||
"vec3 lightminusvertex = l_lightposition - v_position.xyz;\n"
|
||||
|
||||
//no bumpmapping, so we can just use distance without regard for actual surface direction. we still do scalecos stuff. you might notice it on steep slopes.
|
||||
"lightvector = lightminusvertex;\n"
|
||||
// lightvector.x = -dot(lightminusvertex, v_svector.xyz);
|
||||
// lightvector.y = dot(lightminusvertex, v_tvector.xyz);
|
||||
// lightvector.z = dot(lightminusvertex, v_normal.xyz);
|
||||
|
||||
// #if defined(SPECULAR)||defined(OFFSETMAPPING)
|
||||
// vec3 eyeminusvertex = e_eyepos - v_position.xyz;
|
||||
// eyevector.x = -dot(eyeminusvertex, v_svector.xyz);
|
||||
// eyevector.y = dot(eyeminusvertex, v_tvector.xyz);
|
||||
// eyevector.z = dot(eyeminusvertex, v_normal.xyz);
|
||||
// #endif
|
||||
"#if defined(PCF) || defined(SPOT) || defined(CUBE)\n"
|
||||
//for texture projections/shadowmapping on dlights
|
||||
"vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));\n"
|
||||
"#endif\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
"#endif\n"
|
||||
|
||||
|
@ -2062,17 +2108,68 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
//mix values
|
||||
"uniform sampler2D s_t4;\n"
|
||||
|
||||
"#ifdef PCF\n"
|
||||
"sampler2DShadow s_t5;\n"
|
||||
"#include \"sys/pcf.h\"\n"
|
||||
"#endif\n"
|
||||
|
||||
//light levels
|
||||
"uniform vec4 e_lmscale;\n"
|
||||
|
||||
"#ifdef RTLIGHT\n"
|
||||
"uniform float l_lightradius;\n"
|
||||
"uniform vec3 l_lightcolour;\n"
|
||||
"uniform vec3 l_lightcolourscale;\n"
|
||||
"#endif\n"
|
||||
|
||||
"void main (void)\n"
|
||||
"{\n"
|
||||
"vec4 r;\n"
|
||||
"vec4 m = texture2D(s_t4, lm);\n"
|
||||
|
||||
"gl_FragColor = fog4(vc*vec4(m.aaa,1.0)*(\n"
|
||||
"texture2D(s_t0, tc)*m.r\n"
|
||||
"+ texture2D(s_t1, tc)*m.g\n"
|
||||
"+ texture2D(s_t2, tc)*m.b\n"
|
||||
"+ texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b))\n"
|
||||
"));\n"
|
||||
"r = texture2D(s_t0, tc)*m.r;\n"
|
||||
"r += texture2D(s_t1, tc)*m.g;\n"
|
||||
"r += texture2D(s_t2, tc)*m.b;\n"
|
||||
"r += texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b));\n"
|
||||
|
||||
//vertex colours provide a scaler that applies even through rtlights.
|
||||
"r *= vc;\n"
|
||||
|
||||
"#ifdef RTLIGHT\n"
|
||||
"vec3 nl = normalize(lightvector);\n"
|
||||
"float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n"
|
||||
"vec3 diff;\n"
|
||||
// #ifdef BUMP
|
||||
// colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));
|
||||
// #else
|
||||
"colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n"
|
||||
// #endif
|
||||
|
||||
// #ifdef SPECULAR
|
||||
// vec3 halfdir = normalize(normalize(eyevector) + nl);
|
||||
// float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);
|
||||
// diff += l_lightcolourscale.z * spec * specs.rgb;
|
||||
// #endif
|
||||
|
||||
|
||||
|
||||
"#if defined(SPOT)\n"
|
||||
"if (vtexprojcoord.w < 0.0) discard;\n"
|
||||
"vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);\n"
|
||||
"colorscale *= 1.0-(dot(spot,spot));\n"
|
||||
"#endif\n"
|
||||
"#ifdef PCF\n"
|
||||
"colorscale *= ShadowmapFilter(s_t5);\n"
|
||||
"#endif\n"
|
||||
|
||||
"r.rgb *= colorscale * l_lightcolour;\n"
|
||||
|
||||
"gl_FragColor = fog4additive(r);\n"
|
||||
"#else\n"
|
||||
//lightmap is greyscale in m.a. probably we should just scale the texture mix, but precision errors when editing make me paranoid.
|
||||
"r *= e_lmscale*vec4(m.aaa,1.0);\n"
|
||||
"gl_FragColor = fog4(r);\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
"#endif\n"
|
||||
},
|
||||
|
|
|
@ -438,6 +438,25 @@ typedef struct {
|
|||
float factor;
|
||||
float unit;
|
||||
} polyoffset_t;
|
||||
|
||||
enum
|
||||
{
|
||||
LSHADER_STANDARD=0u, //stencil or shadowless
|
||||
LSHADER_CUBE=1u<<0, //has a cubemap
|
||||
LSHADER_SMAP=1u<<1, //filter based upon 6 directions of a shadowmap
|
||||
LSHADER_SPOT=1u<<2, //filter based upon a single spotlight shadowmap
|
||||
LSHADER_MODES=1u<<3
|
||||
};
|
||||
enum
|
||||
{
|
||||
//low numbers are used for various rtlight mode combinations
|
||||
bemoverride_crepuscular = LSHADER_MODES, //either black (non-sky) or a special crepuscular_sky shader
|
||||
bemoverride_depthonly, //depth masked. replace if you want alpha test.
|
||||
bemoverride_depthdark, //itself or a pure-black shader. replace for alpha test.
|
||||
bemoverride_prelight, //prelighting
|
||||
bemoverride_fog, //post-render volumetric fog
|
||||
bemoverride_max
|
||||
};
|
||||
struct shader_s
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
|
@ -446,14 +465,17 @@ struct shader_s
|
|||
SUF_LIGHTMAP = 1<<0, //$lightmap passes are valid. otherwise collapsed to an rgbgen
|
||||
SUF_2D = 1<<1 //any loaded textures will obey 2d picmips rather than 3d picmips
|
||||
} usageflags; //
|
||||
int uses;
|
||||
int width;
|
||||
int uses; //released when the uses drops to 0
|
||||
int width; //when used as an image, this is the logical 'width' of the image
|
||||
int height;
|
||||
int numpasses;
|
||||
texnums_t defaulttextures;
|
||||
struct shader_s *next;
|
||||
int id;
|
||||
//end of shared fields.
|
||||
|
||||
shader_t *bemoverrides[bemoverride_max];
|
||||
|
||||
byte_vec4_t fog_color;
|
||||
float fog_dist;
|
||||
float portaldist;
|
||||
|
@ -507,8 +529,9 @@ struct shader_s
|
|||
bucket_t bucket;
|
||||
};
|
||||
|
||||
#define MAX_SHADERS 2048 //fixme: this takes a lot of bss in the r_shaders list
|
||||
extern shader_t *r_shaders;
|
||||
extern unsigned int r_numshaders;
|
||||
extern unsigned int r_maxshaders;
|
||||
extern shader_t **r_shaders;
|
||||
extern int be_maxpasses;
|
||||
|
||||
|
||||
|
@ -552,15 +575,6 @@ mfog_t *CM_FogForOrigin(vec3_t org);
|
|||
#define BEF_FORCECOLOURMOD 256 //q3 shaders default to 'rgbgen identity', and ignore ent colours. this forces ent colours to be considered
|
||||
#define BEF_LINES 512 //draw line pairs instead of triangles.
|
||||
|
||||
enum
|
||||
{
|
||||
LSHADER_STANDARD, //stencil or shadowless
|
||||
LSHADER_CUBE, //has a cubemap
|
||||
LSHADER_SMAP, //shadowmap
|
||||
LSHADER_SPOT, //spotlight+shadowmap
|
||||
LSHADER_MODES
|
||||
};
|
||||
|
||||
#ifdef GLQUAKE
|
||||
void GLBE_Init(void);
|
||||
void GLBE_Shutdown(void);
|
||||
|
@ -650,7 +664,7 @@ void Sh_RegisterCvars(void);
|
|||
//
|
||||
void GLBE_PushOffsetShadow(qboolean foobar);
|
||||
//sets up gl for depth-only FIXME
|
||||
void GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, float shadowscale);
|
||||
int GLBE_SetupForShadowMap(texid_t shadowmaptex, int texwidth, int texheight, float shadowscale);
|
||||
//Called from shadowmapping code into backend
|
||||
void GLBE_BaseEntTextures(void);
|
||||
void D3D9BE_BaseEntTextures(void);
|
||||
|
|
|
@ -215,7 +215,7 @@ r_part te_explosion
|
|||
randomvel 0
|
||||
|
||||
lightradius 350
|
||||
lightrgb 0.4 0.2 0.05
|
||||
lightrgb 1.4 1.2 1.05
|
||||
lighttime 0.5
|
||||
lightradiusfade 350
|
||||
lightrgbfade 2 2 2
|
||||
|
|
|
@ -3194,7 +3194,7 @@ QCC_ref_t *QCC_PR_GenerateAddressOf(QCC_ref_t *retbuf, QCC_ref_t *operand)
|
|||
//&foo (or &((&foo)[5]), which is basically an array). the result is a temp and thus cannot be assigned to (but should be possible to dereference further).
|
||||
return QCC_PR_BuildRef(retbuf,
|
||||
REF_GLOBAL,
|
||||
QCC_PR_Statement(&pr_opcodes[OP_GLOBALADDRESS], operand->base, QCC_SupplyConversion(operand->index, ev_integer, true), NULL),
|
||||
QCC_PR_Statement(&pr_opcodes[OP_GLOBALADDRESS], operand->base, operand->index?QCC_SupplyConversion(operand->index, ev_integer, true):NULL, NULL),
|
||||
NULL,
|
||||
QCC_PR_PointerType(operand->cast),
|
||||
true);
|
||||
|
@ -6703,7 +6703,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags)
|
|||
rhsr = QCC_PR_RefExpression (&rhsbuf, priority, exprflags | EXPR_DISALLOW_ARRAYASSIGN);
|
||||
|
||||
if (conditional&1)
|
||||
QCC_PR_ParseWarning(WARN_ASSIGNMENTINCONDITIONAL, "Assignment in conditional");
|
||||
QCC_PR_ParseWarning(WARN_ASSIGNMENTINCONDITIONAL, "suggest parenthesis for assignment used as truth value .");
|
||||
|
||||
rhsd = QCC_RefToDef(rhsr, true);
|
||||
|
||||
|
|
|
@ -2124,7 +2124,7 @@ void NPP_MVDFlush(void)
|
|||
sv.demostatevalid = true;
|
||||
}
|
||||
entnum = buffer[1] + (buffer[2]<<8);
|
||||
// if (entnum < MAX_CLIENTS)
|
||||
// if (entnum < svs.allocated_client_slots)
|
||||
// break;
|
||||
ent = &sv.demobaselines[entnum];
|
||||
|
||||
|
|
|
@ -211,6 +211,8 @@ void PDECL ED_Spawned (struct edict_s *ent, int loading)
|
|||
ent->xv->dimension_ghost = 0;
|
||||
ent->xv->dimension_solid = 255;
|
||||
ent->xv->dimension_hit = 255;
|
||||
if (progstype != PROG_H2)
|
||||
ent->xv->drawflags = SCALE_ORIGIN_ORIGIN; //if not running hexen2, default the scale origin to the actual origin.
|
||||
|
||||
ent->xv->Version = sv.csqcentversion[ent->entnum];
|
||||
ent->xv->uniquespawnid = sv.csqcentversion[ent->entnum];
|
||||
|
@ -432,7 +434,7 @@ void PDECL PR_SSQC_Relocated(pubprogfuncs_t *pr, char *oldb, char *newb, int old
|
|||
if (sv.strings.model_precache[i] >= oldb && sv.strings.model_precache[i] < oldb+oldlen)
|
||||
sv.strings.model_precache[i] += newb - oldb;
|
||||
}
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < svs.allocated_client_slots; i++)
|
||||
{
|
||||
if (svs.clients[i].name >= oldb && svs.clients[i].name < oldb+oldlen)
|
||||
svs.clients[i].name += newb - oldb;
|
||||
|
@ -6762,7 +6764,7 @@ void SV_AddDebugPolygons(void)
|
|||
if (gfuncs.AddDebugPolygons)
|
||||
{
|
||||
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.world.edicts);
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < sv.allocated_client_slots; i++)
|
||||
if (svs.clients[i].netchan.remote_address.type == NA_LOOPBACK)
|
||||
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, svs.clients[i].edict);
|
||||
PR_ExecuteProgram (svprogfuncs, gfuncs.AddDebugPolygons);
|
||||
|
@ -9554,7 +9556,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
|
||||
{"isdemo", PF_Fixme, 0, 0, 0, 349, D("float()", "Returns if the client is currently playing a demo or not")},// (EXT_CSQC)
|
||||
{"isserver", PF_Fixme, 0, 0, 0, 350, D("float()", "Returns if the client is acting as the server (aka: listen server)")},//(EXT_CSQC)
|
||||
{"SetListener", PF_Fixme, 0, 0, 0, 351, D("void(vector origin, vector forward, vector right, vector up)", "Sets the position of the view, as far as the audio subsystem is concerned. This should be called once per CSQC_UpdateView as it will otherwise revert to default.")},// (EXT_CSQC)
|
||||
{"SetListener", PF_Fixme, 0, 0, 0, 351, D("void(vector origin, vector forward, vector right, vector up, float inwater)", "Sets the position of the view, as far as the audio subsystem is concerned. This should be called once per CSQC_UpdateView as it will otherwise revert to default.")},// (EXT_CSQC)
|
||||
{"registercommand", PF_Fixme, 0, 0, 0, 352, D("void(string cmdname)", "Register the given console command, for easy console use.\nConsole commands that are later used will invoke CSQC_ConsoleCommand.")},//(EXT_CSQC)
|
||||
{"wasfreed", PF_WasFreed,0, 0, 0, 353, D("float(entity ent)", "Quickly check to see if the entity is currently free. This function is only valid during the two-second non-reuse window, after that it may give bad results. Try one second to make it more robust.")},//(EXT_CSQC) (should be availabe on server too)
|
||||
{"serverkey", PF_Fixme, 0, 0, 0, 354, D("string(string key)", "Look up a key in the server's public serverinfo string")},//
|
||||
|
|
|
@ -243,7 +243,7 @@ void SV_Loadgame_f(void)
|
|||
|
||||
|
||||
|
||||
for (clnum = 0; clnum < MAX_CLIENTS; clnum++) //clear the server for the level change.
|
||||
for (clnum = 0; clnum < sv.allocated_client_slots; clnum++) //clear the server for the level change.
|
||||
{
|
||||
cl = &svs.clients[clnum];
|
||||
if (cl->state <= cs_zombie)
|
||||
|
@ -257,13 +257,7 @@ void SV_Loadgame_f(void)
|
|||
|
||||
if (version == 5 || version == 6)
|
||||
{
|
||||
slots = 1;
|
||||
for (clnum = 1; clnum < MAX_CLIENTS; clnum++) //kick all players fully. Load only player 1.
|
||||
{
|
||||
cl = &svs.clients[clnum];
|
||||
cl->istobeloaded = false;
|
||||
cl->state = cs_free;
|
||||
}
|
||||
SV_UpdateMaxPlayers(1);
|
||||
cl = &svs.clients[0];
|
||||
#ifdef SERVERONLY
|
||||
strcpy(cl->name, "");
|
||||
|
@ -279,7 +273,7 @@ void SV_Loadgame_f(void)
|
|||
for (; i < NUM_SPAWN_PARMS; i++)
|
||||
cl->spawn_parms[i] = 0;
|
||||
}
|
||||
else //fte QuakeWorld saves ALL the clients on the server.
|
||||
else //fte saves ALL the clients on the server.
|
||||
{
|
||||
fscanf (f, "%f\n", &tfloat);
|
||||
slots = tfloat;
|
||||
|
@ -289,6 +283,7 @@ void SV_Loadgame_f(void)
|
|||
Con_Printf ("Corrupted save game");
|
||||
return;
|
||||
}
|
||||
SV_UpdateMaxPlayers(slots);
|
||||
for (clnum = 0; clnum < sv.allocated_client_slots; clnum++) //work out which players we had when we saved, and hope they accepted the reconnect.
|
||||
{
|
||||
cl = &svs.clients[clnum];
|
||||
|
@ -311,12 +306,6 @@ void SV_Loadgame_f(void)
|
|||
for (i=0 ; i<NUM_SPAWN_PARMS ; i++)
|
||||
fscanf (f, "%f\n", &cl->spawn_parms[i]);
|
||||
}
|
||||
for (clnum = sv.allocated_client_slots; clnum < MAX_CLIENTS; clnum++)
|
||||
{ //cleanup.
|
||||
cl = &svs.clients[clnum];
|
||||
cl->istobeloaded = false;
|
||||
cl->state = cs_free;
|
||||
}
|
||||
}
|
||||
if (version == 5 || version == 6)
|
||||
{
|
||||
|
@ -431,7 +420,7 @@ void SV_Loadgame_f(void)
|
|||
SV_LinkEdict (ent, false);
|
||||
}
|
||||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<sv.allocated_client_slots ; i++)
|
||||
{
|
||||
ent = EDICT_NUM(svprogfuncs, i+1);
|
||||
svs.clients[i].edict = ent;
|
||||
|
@ -712,7 +701,7 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea
|
|||
|
||||
World_ClearWorld (&sv.world);
|
||||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++)
|
||||
{
|
||||
if (i < sv.allocated_client_slots)
|
||||
ent = EDICT_NUM(svprogfuncs, i+1);
|
||||
|
@ -736,7 +725,7 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea
|
|||
|
||||
eval = PR_FindGlobal(svprogfuncs, "ClientReEnter", 0, NULL);
|
||||
if (eval)
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<sv.allocated_client_slots ; i++)
|
||||
{
|
||||
if (svs.clients[i].spawninfo)
|
||||
{
|
||||
|
@ -1131,7 +1120,7 @@ void SV_Loadgame_f (void)
|
|||
Con_TPrintf (STL_LOADGAMEFROM, filename);
|
||||
|
||||
|
||||
for (clnum = 0; clnum < MAX_CLIENTS; clnum++) //clear the server for the level change.
|
||||
for (clnum = 0; clnum < svs.allocated_client_slots; clnum++) //clear the server for the level change.
|
||||
{
|
||||
cl = &svs.clients[clnum];
|
||||
if (cl->state <= cs_zombie)
|
||||
|
|
|
@ -769,7 +769,8 @@ typedef struct
|
|||
|
||||
struct ftenet_connections_s *sockets;
|
||||
|
||||
client_t clients[MAX_CLIENTS];
|
||||
int allocated_client_slots;
|
||||
client_t *clients;
|
||||
int serverflags; // episode completion information
|
||||
|
||||
double last_heartbeat;
|
||||
|
|
|
@ -615,7 +615,7 @@ void SV_Map_f (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++) //we need to drop all q2 clients. We don't mix q1w with q2.
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++) //we need to drop all q2 clients. We don't mix q1w with q2.
|
||||
{
|
||||
if (svs.clients[i].state>cs_connected) //so that we don't send a datagram
|
||||
svs.clients[i].state=cs_connected;
|
||||
|
@ -627,7 +627,7 @@ void SV_Map_f (void)
|
|||
SCR_ImageName(level);
|
||||
#endif
|
||||
|
||||
for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
|
||||
for (i=0, host_client = svs.clients ; i<svs.allocated_client_slots ; i++, host_client++)
|
||||
{
|
||||
/*pass the new map's name as an extension, so appropriate loading screens can be shown*/
|
||||
if (ISNQCLIENT(host_client))
|
||||
|
@ -649,7 +649,7 @@ void SV_Map_f (void)
|
|||
SCR_SetLoadingFile("server spawned");
|
||||
|
||||
//SV_BroadcastCommand ("cmd new\n");
|
||||
for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
|
||||
for (i=0, host_client = svs.clients ; i<svs.allocated_client_slots ; i++, host_client++)
|
||||
{ //this expanded code cuts out a packet when changing maps...
|
||||
//but more usefully, it stops dp(and probably nq too) from timing out.
|
||||
//make sure its all reset.
|
||||
|
@ -690,7 +690,7 @@ void SV_Map_f (void)
|
|||
|
||||
|
||||
if (isDedicated)
|
||||
Mod_Flush(false);
|
||||
Mod_Purge(MP_MAPCHANGED);
|
||||
}
|
||||
|
||||
void SV_KillServer_f(void)
|
||||
|
@ -1531,7 +1531,7 @@ void SV_Status_f (void)
|
|||
{
|
||||
Con_Printf ("frags userid address name rate ping drop qport dl%% dls\n");
|
||||
Con_Printf ("----- ------ --------------- --------------- ---- ---- ----- ----- --- ----\n");
|
||||
for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
|
||||
for (i=0,cl=svs.clients ; i<svs.allocated_client_slots ; i++,cl++)
|
||||
{
|
||||
if (!cl->state)
|
||||
continue;
|
||||
|
@ -1607,7 +1607,7 @@ void SV_ConSay_f(void)
|
|||
|
||||
Q_strcat(text, p);
|
||||
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
|
||||
for (j = 0, client = svs.clients; j < svs.allocated_client_slots; j++, client++)
|
||||
{
|
||||
if (client->state == cs_free)
|
||||
continue;
|
||||
|
@ -2052,7 +2052,7 @@ void SV_Snap (int uid)
|
|||
char checkname[MAX_OSPATH];
|
||||
int i;
|
||||
|
||||
for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++)
|
||||
for (i = 0, cl = svs.clients; i < svs.allocated_client_slots; i++, cl++)
|
||||
{
|
||||
if (!cl->state)
|
||||
continue;
|
||||
|
@ -2132,7 +2132,7 @@ void SV_SnapAll_f (void)
|
|||
client_t *cl;
|
||||
int i;
|
||||
|
||||
for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++)
|
||||
for (i = 0, cl = svs.clients; i < svs.allocated_client_slots; i++, cl++)
|
||||
{
|
||||
if (cl->state < cs_connected || cl->spectator)
|
||||
continue;
|
||||
|
|
|
@ -93,7 +93,7 @@ void SV_RecordDemo_f (void)
|
|||
fwrite(mapname, 1, sizeof(char)*(strlen(mapname)+1), svdemofile);
|
||||
|
||||
|
||||
for (clnum = 0; clnum < MAX_CLIENTS; clnum++) //clear the server so the clients reconnect and send nice fresh messages.
|
||||
for (clnum = 0; clnum < svs.allocated_client_slots; clnum++) //clear the server so the clients reconnect and send nice fresh messages.
|
||||
{
|
||||
c = &svs.clients[clnum];
|
||||
if (c->state <= cs_zombie)
|
||||
|
@ -149,7 +149,7 @@ void SV_PlayDemo_f(void)
|
|||
|
||||
svs.demoplayback = true;
|
||||
|
||||
for (clnum = 0; clnum < MAX_CLIENTS; clnum++) //clear the server so new clients don't conflict.
|
||||
for (clnum = 0; clnum < svs.allocated_client_slots; clnum++) //clear the server so new clients don't conflict.
|
||||
{
|
||||
c = &svs.clients[clnum];
|
||||
if (c->state <= cs_zombie)
|
||||
|
@ -266,7 +266,7 @@ void SV_LoadClientDemo_f (void)
|
|||
memset(sv.demostate, 0, sizeof(entity_state_t)*MAX_EDICTS);
|
||||
}
|
||||
/*
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < svs.allocated_client_slots; i++)
|
||||
{
|
||||
host_client = &svs.clients[i];
|
||||
if (host_client->state == cs_spawned)
|
||||
|
|
|
@ -513,9 +513,8 @@ void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg,
|
|||
coorddata coordd[3];
|
||||
coorddata angled[3];
|
||||
|
||||
static entity_state_t defaultbaseline;
|
||||
if (from == &((edict_t*)NULL)->baseline)
|
||||
from = &defaultbaseline;
|
||||
from = &nullentitystate;
|
||||
|
||||
// send an update
|
||||
bits = 0;
|
||||
|
@ -865,7 +864,7 @@ static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, entity_state_t *to
|
|||
if (to->tagentity != from->tagentity || to->tagindex != from->tagindex)
|
||||
bits |= UF_TAGINFO;
|
||||
|
||||
if (to->light[0] != from->light[0] || to->light[1] != from->light[1] || to->light[2] != from->light[2] || to->light[3] != from->light[3] || to->lightstyle != from->lightstyle || to->lightpflags != from->lightstyle)
|
||||
if (to->light[0] != from->light[0] || to->light[1] != from->light[1] || to->light[2] != from->light[2] || to->light[3] != from->light[3] || to->lightstyle != from->lightstyle || to->lightpflags != from->lightpflags)
|
||||
bits |= UF_LIGHT;
|
||||
|
||||
if (to->u.q1.traileffectnum != from->u.q1.traileffectnum)
|
||||
|
@ -1123,7 +1122,7 @@ void SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizebuf_t
|
|||
if (!client->pendingentbits)
|
||||
return;
|
||||
|
||||
if (client->delta_sequence <= 0)
|
||||
if (client->delta_sequence < 0)
|
||||
client->pendingentbits[0] = UF_REMOVE;
|
||||
|
||||
//if we're clearing the list and starting from scratch, just wipe all lingering state
|
||||
|
|
|
@ -552,7 +552,7 @@ void SV_UnspawnServer (void) //terminate the running server.
|
|||
sv.csqcentversion = NULL;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < svs.allocated_client_slots; i++)
|
||||
{
|
||||
if (svs.clients[i].frameunion.frames)
|
||||
Z_Free(svs.clients[i].frameunion.frames);
|
||||
|
@ -562,10 +562,42 @@ void SV_UnspawnServer (void) //terminate the running server.
|
|||
*svs.clients[i].namebuf = '\0';
|
||||
svs.clients[i].name = NULL;
|
||||
}
|
||||
free(svs.clients);
|
||||
svs.clients = NULL;
|
||||
svs.allocated_client_slots = 0;
|
||||
SV_FlushLevelCache();
|
||||
NET_CloseServer ();
|
||||
}
|
||||
|
||||
void SV_UpdateMaxPlayers(int newmax)
|
||||
{
|
||||
int i;
|
||||
if (newmax != svs.allocated_client_slots)
|
||||
{
|
||||
for (i = newmax; i < svs.allocated_client_slots; i++)
|
||||
{
|
||||
if (svs.clients[i].state)
|
||||
SV_DropClient(&svs.clients[i]);
|
||||
svs.clients[i].namebuf[0] = '\0'; //kill all bots
|
||||
}
|
||||
if (newmax)
|
||||
svs.clients = realloc(svs.clients, newmax*sizeof(*svs.clients));
|
||||
else
|
||||
{
|
||||
free(svs.clients);
|
||||
svs.clients = NULL;
|
||||
}
|
||||
for (i = svs.allocated_client_slots; i < newmax; i++)
|
||||
{
|
||||
memset(&svs.clients[i], 0, sizeof(svs.clients[i]));
|
||||
svs.clients[i].name = svs.clients[i].namebuf;
|
||||
svs.clients[i].team = svs.clients[i].teambuf;
|
||||
}
|
||||
svs.allocated_client_slots = sv.allocated_client_slots = newmax;
|
||||
}
|
||||
sv.allocated_client_slots = svs.allocated_client_slots;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_SpawnServer
|
||||
|
@ -633,7 +665,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
Rank_Flush();
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < svs.allocated_client_slots; i++)
|
||||
{
|
||||
if (svs.clients[i].state && ISQWCLIENT(&svs.clients[i]))
|
||||
ReloadRanking(&svs.clients[i], svs.clients[i].name);
|
||||
|
@ -656,7 +688,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
svs.netprim.anglesize = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < svs.allocated_client_slots; i++)
|
||||
{
|
||||
svs.clients[i].datagram.prim = svs.netprim;
|
||||
svs.clients[i].netchan.message.prim = svs.netprim;
|
||||
|
@ -800,7 +832,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
#if defined(Q2BSPS)
|
||||
if (usecinematic)
|
||||
{
|
||||
qboolean Mod_LoadQ2BrushModel (model_t *mod, void *buffer);
|
||||
qboolean QDECL Mod_LoadQ2BrushModel (model_t *mod, void *buffer);
|
||||
extern model_t *loadmodel;
|
||||
|
||||
strcpy (sv.name, server);
|
||||
|
@ -966,13 +998,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
Q1QVM_Shutdown();
|
||||
#endif
|
||||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++) //server type changed, so we need to drop all clients. :(
|
||||
{
|
||||
if (svs.clients[i].state)
|
||||
SV_DropClient(&svs.clients[i]);
|
||||
|
||||
svs.clients[i].namebuf[0] = '\0'; //kill all bots
|
||||
}
|
||||
SV_UpdateMaxPlayers(0);
|
||||
}
|
||||
svs.gametype = newgametype;
|
||||
|
||||
|
@ -1049,7 +1075,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
SCR_SetLoadingFile("clients");
|
||||
#endif
|
||||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<svs.allocated_client_slots ; i++)
|
||||
{
|
||||
svs.clients[i].edict = NULL;
|
||||
svs.clients[i].name = svs.clients[i].namebuf;
|
||||
|
@ -1073,14 +1099,17 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
Cvar_Set(&coop, "1");
|
||||
}
|
||||
#endif
|
||||
/*only make one slot for single-player*/
|
||||
if (!isDedicated && !deathmatch.value && !coop.value)
|
||||
sv.allocated_client_slots = 1;
|
||||
else
|
||||
sv.allocated_client_slots = QWMAX_CLIENTS;
|
||||
if (sv_playerslots.ival > 0)
|
||||
sv.allocated_client_slots = sv_playerslots.ival;
|
||||
sv.allocated_client_slots = bound(1, sv.allocated_client_slots, MAX_CLIENTS); //bound it
|
||||
i = sv_playerslots.ival;
|
||||
else
|
||||
{
|
||||
/*only make one slot for single-player*/
|
||||
if (!isDedicated && !deathmatch.value && !coop.value)
|
||||
i = 1;
|
||||
else
|
||||
i = QWMAX_CLIENTS;
|
||||
}
|
||||
SV_UpdateMaxPlayers(i);
|
||||
|
||||
// leave slots at start for clients only
|
||||
for (i=0 ; i<sv.allocated_client_slots ; i++)
|
||||
|
@ -1116,27 +1145,21 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
memset(svs.clients[i].csqcentversions, 0, sizeof(*svs.clients[i].csqcentversions) * svs.clients[i].max_net_ents);
|
||||
#endif
|
||||
}
|
||||
for (; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if (svs.clients[i].state)
|
||||
SV_DropClient(&svs.clients[i]);
|
||||
svs.clients[i].namebuf[0] = '\0'; //kill all bots
|
||||
}
|
||||
break;
|
||||
case GT_QUAKE2:
|
||||
#ifdef Q2SERVER
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
SV_UpdateMaxPlayers(svq2_maxclients);
|
||||
for (i=0 ; i<sv.allocated_client_slots ; i++)
|
||||
{
|
||||
q2ent = Q2EDICT_NUM(i+1);
|
||||
q2ent->s.number = i+1;
|
||||
svs.clients[i].q2edict = q2ent;
|
||||
}
|
||||
sv.allocated_client_slots = svq2_maxclients;
|
||||
#endif
|
||||
break;
|
||||
case GT_QUAKE3:
|
||||
#ifdef Q3SERVER
|
||||
sv.allocated_client_slots = 32;
|
||||
SV_UpdateMaxPlayers(32);
|
||||
#endif
|
||||
break;
|
||||
case GT_HALFLIFE:
|
||||
|
@ -1145,9 +1168,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
//fixme: properly kick any other clients (ie: without notifying gamecode).
|
||||
//fixme: is this right?
|
||||
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<sv.allocated_client_slots ; i++)
|
||||
{
|
||||
Q_strncpyz(svs.clients[i].name, Info_ValueForKey(svs.clients[i].userinfo, "name"), sizeof(svs.clients[i].namebuf));
|
||||
Q_strncpyz(svs.clients[i].team, Info_ValueForKey(svs.clients[i].userinfo, "team"), sizeof(svs.clients[i].teambuf));
|
||||
|
@ -1438,7 +1461,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
|
|||
if (!startspot)
|
||||
{
|
||||
SV_FlushLevelCache(); //to make sure it's caught
|
||||
for (i=0 ; i<MAX_CLIENTS ; i++)
|
||||
for (i=0 ; i<sv.allocated_client_slots ; i++)
|
||||
{
|
||||
if (svs.clients[i].spawninfo)
|
||||
Z_Free(svs.clients[i].spawninfo);
|
||||
|
|
|
@ -164,10 +164,11 @@ cvar_t fraglimit = CVARF("fraglimit", "" , CVAR_SERVERINFO);
|
|||
cvar_t timelimit = CVARF("timelimit", "" , CVAR_SERVERINFO);
|
||||
cvar_t teamplay = CVARF("teamplay", "" , CVAR_SERVERINFO);
|
||||
cvar_t samelevel = CVARF("samelevel", "" , CVAR_SERVERINFO);
|
||||
cvar_t sv_playerslots = CVARD("sv_playerslots", "", "Specify maximum number of player/spectator slots. This should generally be maxclients+maxspectators. Leave blank for a default value. Maximum value of "STRINGIFY(MAX_CLIENTS)".");
|
||||
cvar_t maxclients = CVARAF("maxclients", "8",
|
||||
"sv_maxclients", CVAR_SERVERINFO);
|
||||
cvar_t maxspectators = CVARF("maxspectators", "8", CVAR_SERVERINFO);
|
||||
cvar_t sv_playerslots = CVARAD("sv_playerslots", "",
|
||||
"maxplayers", "Specify maximum number of player/spectator/bot slots, new value takes effect on the next map (this may result in players getting kicked). This should generally be maxclients+maxspectators. Leave blank for a default value.\nMaximum value of "STRINGIFY(MAX_CLIENTS)". Values above 16 will result in issues with vanilla NQ clients. Effective values other than 32 will result in issues with vanilla QW clients.");
|
||||
cvar_t maxclients = CVARAFD("maxclients", "8",
|
||||
"sv_maxclients", CVAR_SERVERINFO, "Specify the maximum number of players allowed on the server at once. Can be changed mid-map.");
|
||||
cvar_t maxspectators = CVARFD("maxspectators", "8", CVAR_SERVERINFO, "Specify the maximum number of spectators allowed on the server at once. Can be changed mid-map.");
|
||||
#ifdef SERVERONLY
|
||||
cvar_t deathmatch = CVARF("deathmatch", "1", CVAR_SERVERINFO); // 0, 1, or 2
|
||||
#else
|
||||
|
@ -389,7 +390,7 @@ void SV_FinalMessage (char *message)
|
|||
MSG_WriteString (&sv.datagram, message);
|
||||
MSG_WriteByte (&sv.datagram, svc_disconnect);
|
||||
|
||||
for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
|
||||
for (i=0, cl = svs.clients ; i<svs.allocated_client_slots ; i++, cl++)
|
||||
if (cl->state >= cs_spawned)
|
||||
if (ISNQCLIENT(cl) || ISQWCLIENT(cl))
|
||||
Netchan_Transmit (&cl->netchan, sv.datagram.cursize
|
||||
|
@ -2195,7 +2196,7 @@ client_t *SVC_DirectConnect(void)
|
|||
newcl->userinfo[sizeof(newcl->userinfo)-1] = '\0';
|
||||
|
||||
// if there is already a slot for this ip, drop it
|
||||
for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
|
||||
for (i=0,cl=svs.clients ; i<svs.allocated_client_slots ; i++,cl++)
|
||||
{
|
||||
if (cl->state == cs_free)
|
||||
continue;
|
||||
|
@ -2945,7 +2946,7 @@ void SVC_ACK (void)
|
|||
int slotnum;
|
||||
char adr[MAX_ADR_SIZE];
|
||||
|
||||
for (slotnum = 0; slotnum < MAX_CLIENTS; slotnum++)
|
||||
for (slotnum = 0; slotnum < svs.allocated_client_slots; slotnum++)
|
||||
{
|
||||
if (svs.clients[slotnum].state)
|
||||
{
|
||||
|
@ -3506,7 +3507,7 @@ qboolean SV_ReadPackets (float *delay)
|
|||
int giveup = 5000; /*we're fucked if we need this to be this high, but at least we can retain some clients if we're really running that slow*/
|
||||
int cookie = 0;
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++) //fixme: shouldn't we be using svs.allocated_client_slots ?
|
||||
for (i = 0; i < svs.allocated_client_slots; i++) //fixme: shouldn't we be using svs.allocated_client_slots ?
|
||||
{
|
||||
cl = &svs.clients[i];
|
||||
while (cl->laggedpacket)
|
||||
|
@ -3613,7 +3614,7 @@ qboolean SV_ReadPackets (float *delay)
|
|||
qport = MSG_ReadShort () & 0xffff;
|
||||
|
||||
// check for packets from connected clients
|
||||
for (i=0, cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
|
||||
for (i=0, cl=svs.clients ; i<svs.allocated_client_slots ; i++,cl++)
|
||||
{
|
||||
if (cl->state == cs_free)
|
||||
continue;
|
||||
|
@ -3701,7 +3702,7 @@ dominping:
|
|||
break;
|
||||
}
|
||||
|
||||
if (i != MAX_CLIENTS)
|
||||
if (i != svs.allocated_client_slots)
|
||||
continue;
|
||||
|
||||
#ifdef Q3SERVER
|
||||
|
@ -3750,7 +3751,7 @@ void SV_CheckTimeouts (void)
|
|||
droptime = realtime - timeout.value;
|
||||
nclients = 0;
|
||||
|
||||
for (i=0,cl=svs.clients ; i<MAX_CLIENTS ; i++,cl++)
|
||||
for (i=0,cl=svs.clients ; i<svs.allocated_client_slots ; i++,cl++)
|
||||
{
|
||||
if (cl->state == cs_connected || cl->state == cs_spawned) {
|
||||
if (!cl->spectator)
|
||||
|
@ -3966,7 +3967,7 @@ static void SV_PauseChanged(void)
|
|||
int i;
|
||||
client_t *cl;
|
||||
// send notification to all clients
|
||||
for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
|
||||
for (i=0, cl = svs.clients ; i<svs.allocated_client_slots ; i++, cl++)
|
||||
{
|
||||
if (!cl->state)
|
||||
continue;
|
||||
|
@ -4785,14 +4786,17 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
|
|||
strcpy(newname, "unnamed");
|
||||
|
||||
// check to see if another user by the same name exists
|
||||
while (1) {
|
||||
for (i=0, client = svs.clients ; i<MAX_CLIENTS ; i++, client++) {
|
||||
while (1)
|
||||
{
|
||||
for (i=0, client = svs.clients ; i<svs.allocated_client_slots ; i++, client++)
|
||||
{
|
||||
if (client->state < cs_connected || client == cl)
|
||||
continue;
|
||||
if (!stricmp(client->name, newname))
|
||||
break;
|
||||
}
|
||||
if (i != MAX_CLIENTS) { // dup name
|
||||
if (i != svs.allocated_client_slots)
|
||||
{ // dup name
|
||||
if (strlen(newname) > sizeof(cl->namebuf) - 1)
|
||||
newname[sizeof(cl->namebuf) - 4] = 0;
|
||||
p = newname;
|
||||
|
@ -4808,7 +4812,8 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
|
|||
memmove(newname+10, p, strlen(p)+1);
|
||||
|
||||
sprintf(newname, "(%d)%-.40s", dupc++, newname+10);
|
||||
} else
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4999,7 +5004,8 @@ void SV_Init (quakeparms_t *parms)
|
|||
#ifdef TERRAIN
|
||||
Terr_Init();
|
||||
#endif
|
||||
Mod_Init ();
|
||||
Mod_Init (true);
|
||||
Mod_Init (false);
|
||||
|
||||
PF_Common_RegisterCvars();
|
||||
}
|
||||
|
|
|
@ -649,6 +649,11 @@ static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec
|
|||
continue;
|
||||
}
|
||||
|
||||
//these pushes are contents brushes, and are not solid. water cannot crush. the player just enters the water.
|
||||
//but, the player will be moved along with the water.
|
||||
if (pusher->v->skin < 0)
|
||||
continue;
|
||||
|
||||
// Con_Printf("Pusher hit %s\n", PR_GetString(w->progs, check->v->classname));
|
||||
if (pusher->v->blocked)
|
||||
{
|
||||
|
@ -768,7 +773,14 @@ static qboolean WPhys_Push (world_t *w, wedict_t *pusher, vec3_t move, vec3_t am
|
|||
|
||||
// try moving the contacted entity
|
||||
VectorAdd (check->v->origin, move, check->v->origin);
|
||||
block = World_TestEntityPosition (w, check);
|
||||
if (pusher->v->skin < 0)
|
||||
{
|
||||
pusher->v->solid = SOLID_NOT;
|
||||
block = World_TestEntityPosition (w, check);
|
||||
pusher->v->solid = oldsolid;
|
||||
}
|
||||
else
|
||||
block = World_TestEntityPosition (w, check);
|
||||
if (!block)
|
||||
{ // pushed ok
|
||||
World_LinkEdict (w, check, false);
|
||||
|
@ -801,6 +813,11 @@ static qboolean WPhys_Push (world_t *w, wedict_t *pusher, vec3_t move, vec3_t am
|
|||
continue;
|
||||
}
|
||||
|
||||
//these pushes are contents brushes, and are not solid. water cannot crush. the player just enters the water.
|
||||
//but, the player will be moved along with the water.
|
||||
if (pusher->v->skin < 0)
|
||||
continue;
|
||||
|
||||
VectorCopy (pushorig, pusher->v->origin);
|
||||
World_LinkEdict (w, pusher, false);
|
||||
|
||||
|
|
|
@ -379,7 +379,7 @@ void VARGS SV_BroadcastPrintf (int level, char *fmt, ...)
|
|||
|
||||
Sys_Printf ("%s", string); // print to the console
|
||||
|
||||
for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
|
||||
for (i=0, cl = svs.clients ; i<svs.allocated_client_slots ; i++, cl++)
|
||||
{
|
||||
if (level < cl->messagelevel)
|
||||
continue;
|
||||
|
@ -422,7 +422,7 @@ void VARGS SV_BroadcastTPrintf (int level, translation_t stringnum, ...)
|
|||
|
||||
Sys_Printf ("%s", string); // print to the console
|
||||
|
||||
for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
|
||||
for (i=0, cl = svs.clients ; i<svs.allocated_client_slots ; i++, cl++)
|
||||
{
|
||||
if (level < cl->messagelevel)
|
||||
continue;
|
||||
|
@ -584,7 +584,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
|
|||
}
|
||||
|
||||
// send the data to all relevent clients
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
|
||||
for (j = 0, client = svs.clients; j < svs.allocated_client_slots; j++, client++)
|
||||
{
|
||||
if (client->state != cs_spawned)
|
||||
continue;
|
||||
|
@ -729,7 +729,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int
|
|||
}
|
||||
|
||||
// send the data to all relevent clients
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
|
||||
for (j = 0, client = svs.clients; j < sv.allocated_client_slots; j++, client++)
|
||||
{
|
||||
if (client->state != cs_spawned)
|
||||
continue;
|
||||
|
@ -897,7 +897,7 @@ void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, char *sam
|
|||
|
||||
if (channel & 256)
|
||||
{
|
||||
channel -= 256;
|
||||
channel &= ~256;
|
||||
reliable = true;
|
||||
}
|
||||
else
|
||||
|
@ -1057,6 +1057,13 @@ void SVQ1_StartSound (float *origin, wedict_t *wentity, int channel, char *sampl
|
|||
{
|
||||
for (i=0 ; i<3 ; i++)
|
||||
origin[i] = entity->v->origin[i]+0.5*(entity->v->mins[i]+entity->v->maxs[i]);
|
||||
|
||||
//add the reliable flag for bsp objects.
|
||||
//these sounds are often looped, and if the start is in the phs and the end isn't/gets dropped, then you end up with an annoying infinitely looping sample.
|
||||
//making them all reliable avoids packetloss and phs issues.
|
||||
//this applies only to pushers. you won't get extra latency on player actions because of this.
|
||||
//be warned that it does mean you might be able to hear people triggering stuff on the other side of the map however.
|
||||
channel |= 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1990,7 +1997,7 @@ void SV_FlushBroadcasts (void)
|
|||
client_t *client;
|
||||
int j;
|
||||
// append the broadcast messages to each client messages
|
||||
for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
|
||||
for (j=0, client = svs.clients ; j<svs.allocated_client_slots ; j++, client++)
|
||||
{
|
||||
if (client->state < cs_connected)
|
||||
continue; // reliables go to all connected or spawned
|
||||
|
@ -2071,7 +2078,7 @@ void SV_UpdateToReliableMessages (void)
|
|||
int curfrags;
|
||||
|
||||
// check for changes to be sent over the reliable streams to all clients
|
||||
for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
|
||||
for (i=0, host_client = svs.clients ; i<svs.allocated_client_slots ; i++, host_client++)
|
||||
{
|
||||
if ((svs.gametype == GT_Q1QVM || svs.gametype == GT_PROGS) && host_client->state == cs_spawned)
|
||||
{
|
||||
|
@ -2184,7 +2191,7 @@ void SV_UpdateToReliableMessages (void)
|
|||
}
|
||||
if (host_client->old_frags != curfrags)
|
||||
{
|
||||
for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
|
||||
for (j=0, client = svs.clients ; j<sv.allocated_client_slots ; j++, client++)
|
||||
{
|
||||
if (client->state < cs_connected)
|
||||
continue;
|
||||
|
@ -2322,7 +2329,7 @@ void SV_SendClientMessages (void)
|
|||
SV_UpdateToReliableMessages ();
|
||||
|
||||
// build individual updates
|
||||
for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
|
||||
for (i=0, c = svs.clients ; i<svs.allocated_client_slots ; i++, c++)
|
||||
{
|
||||
if (c->state <= cs_zombie)
|
||||
continue;
|
||||
|
@ -2712,7 +2719,7 @@ void SV_SendMessagesToAll (void)
|
|||
int i;
|
||||
client_t *c;
|
||||
|
||||
for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
|
||||
for (i=0, c = svs.clients ; i<svs.allocated_client_slots ; i++, c++)
|
||||
if (c->state) // FIXME: should this only send to active?
|
||||
c->send_message = true;
|
||||
|
||||
|
|
|
@ -1486,7 +1486,7 @@ void SVQW_Spawn_f (void)
|
|||
// send current status of all other players
|
||||
|
||||
// normally this could overflow, but no need to check due to backbuf
|
||||
for (i=0, client = svs.clients ; i<MAX_CLIENTS ; i++, client++)
|
||||
for (i=0, client = svs.clients ; i<svs.allocated_client_slots ; i++, client++)
|
||||
SV_FullClientUpdate(client, host_client);
|
||||
SV_MVD_FullClientUpdate(NULL, host_client);
|
||||
|
||||
|
@ -3230,7 +3230,7 @@ void SV_Say (qboolean team)
|
|||
|
||||
mvdrecording = sv.mvdrecording;
|
||||
sv.mvdrecording = false; //so that the SV_ClientPrintf doesn't send to all players.
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
|
||||
for (j = 0, client = svs.clients; j < svs.allocated_client_slots; j++, client++)
|
||||
{
|
||||
if (client->state != cs_spawned && client->state != cs_connected)
|
||||
continue;
|
||||
|
@ -3321,7 +3321,7 @@ void SV_Pings_f (void)
|
|||
#ifdef SERVER_DEMO_PLAYBACK
|
||||
if (sv.demofile)
|
||||
{
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
|
||||
for (j = 0, client = svs.clients; j < svs.allocated_client_slots; j++, client++)
|
||||
{
|
||||
if (!*sv.recordedplayer[j].userinfo)
|
||||
continue;
|
||||
|
@ -3340,7 +3340,7 @@ void SV_Pings_f (void)
|
|||
char *s;
|
||||
ClientReliableWrite_Begin(host_client, svc_stufftext, 15+10*MAX_CLIENTS);
|
||||
ClientReliableWrite_SZ(host_client, "pingplreport", 12);
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS && j < host_client->max_net_clients; j++, client++)
|
||||
for (j = 0, client = svs.clients; j < sv.allocated_client_slots && j < host_client->max_net_clients; j++, client++)
|
||||
{
|
||||
s = va(" %i %i", SV_CalcPing(client, false), client->lossage);
|
||||
ClientReliableWrite_SZ(host_client, s, strlen(s));
|
||||
|
@ -3351,7 +3351,7 @@ void SV_Pings_f (void)
|
|||
}
|
||||
else
|
||||
{
|
||||
for (j = 0, client = svs.clients; j < MAX_CLIENTS && j < host_client->max_net_clients; j++, client++)
|
||||
for (j = 0, client = svs.clients; j < sv.allocated_client_slots && j < host_client->max_net_clients; j++, client++)
|
||||
{
|
||||
if (client->state != cs_spawned)
|
||||
continue;
|
||||
|
@ -3687,7 +3687,7 @@ void SV_SetInfo_f (void)
|
|||
|
||||
basic = SV_UserInfoIsBasic(key);
|
||||
|
||||
for (j = 0; j < MAX_CLIENTS; j++)
|
||||
for (j = 0; j < svs.allocated_client_slots; j++)
|
||||
{
|
||||
client = svs.clients+j;
|
||||
if (client->state < cs_connected)
|
||||
|
@ -5329,18 +5329,23 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node )
|
|||
switch((int)check->v->skin)
|
||||
{
|
||||
case Q1CONTENTS_WATER:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_WATER;
|
||||
break;
|
||||
case Q1CONTENTS_LAVA:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_LAVA;
|
||||
break;
|
||||
case Q1CONTENTS_SLIME:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_SLIME;
|
||||
break;
|
||||
case Q1CONTENTS_SKY:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_SKY;
|
||||
break;
|
||||
case Q1CONTENTS_LADDER:
|
||||
pe->nonsolid = true;
|
||||
pe->forcecontentsmask = FTECONTENTS_LADDER;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -265,7 +265,7 @@ hledict_t *QDECL GHL_FindClientInPVS(hledict_t *ed)
|
|||
|
||||
viewerpvs = sv.world.worldmodel->funcs.LeafPVS(sv.world.worldmodel, sv.world.worldmodel->funcs.LeafnumForPoint(sv.world.worldmodel, ed->v.origin), NULL, 0);
|
||||
|
||||
for (i = 0; i < MAX_CLIENTS; i++)
|
||||
for (i = 0; i < svs.allocated_client_slots; i++)
|
||||
{
|
||||
if (svs.clients[i].state == cs_spawned)
|
||||
{
|
||||
|
|
|
@ -204,7 +204,7 @@ void Mod_Init (void)
|
|||
memset (mod_novis, 0xff, sizeof(mod_novis));
|
||||
Cvar_Register(&sv_nogetlight, "Memory preservation");
|
||||
Cvar_Register (&dpcompat_psa_ungroup, "Darkplaces compatibility");
|
||||
Cvar_Register (&r_noframegrouplerp, "Oooga booga");
|
||||
Cvar_Register (&r_noframegrouplerp, "Graphical Nicaties");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -322,17 +322,17 @@ qbyte *Mod_LeafnumPVS (int ln, model_t *model, qbyte *buffer)
|
|||
|
||||
/*
|
||||
===================
|
||||
Mod_Flush
|
||||
Mod_Purge
|
||||
===================
|
||||
*/
|
||||
void Mod_Flush(qboolean force)
|
||||
void Mod_Purge(enum mod_purge_e type)
|
||||
{
|
||||
int i;
|
||||
model_t *mod;
|
||||
|
||||
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
|
||||
{
|
||||
if (mod->datasequence != mod_datasequence || force)
|
||||
if (mod->datasequence != mod_datasequence || type != MP_MAPCHANGED)
|
||||
{
|
||||
//and obliterate anything else remaining in memory.
|
||||
ZG_FreeGroup(&mod->memgroup);
|
||||
|
@ -1892,7 +1892,7 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
|
|||
}
|
||||
|
||||
#ifdef TERRAIN
|
||||
lm->terrain = Mod_LoadTerrainInfo(lm, loadname);
|
||||
lm->terrain = Mod_LoadTerrainInfo(lm, loadname, false);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
|
|
@ -117,12 +117,6 @@ uniform vec3 l_lightcolourscale;
|
|||
#ifdef PCF
|
||||
uniform vec4 l_shadowmapproj; //light projection matrix info
|
||||
uniform vec2 l_shadowmapscale; //xy are the texture scale, z is 1, w is the scale.
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef PCF
|
||||
vec3 ShadowmapCoord(void)
|
||||
{
|
||||
#ifdef SPOT
|
||||
|
@ -222,6 +216,7 @@ float ShadowmapFilter(void)
|
|||
#ifdef OFFSETMAPPING
|
||||
#include "sys/offsetmapping.h"
|
||||
#endif
|
||||
|
||||
void main ()
|
||||
{
|
||||
//read raw texture samples (offsetmapping munges the tex coords first)
|
||||
|
|
|
@ -4,16 +4,67 @@ varying vec2 tc;
|
|||
varying vec2 lm;
|
||||
varying vec4 vc;
|
||||
|
||||
#ifdef RTLIGHT
|
||||
varying vec3 lightvector;
|
||||
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
|
||||
// varying vec3 eyevector;
|
||||
// #endif
|
||||
#if defined(PCF) || defined(CUBE) || defined(SPOT)
|
||||
varying vec4 vtexprojcoord;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
#ifdef RTLIGHT
|
||||
uniform vec3 l_lightposition;
|
||||
// #if defined(SPECULAR) || defined(OFFSETMAPPING)
|
||||
// uniform vec3 e_eyepos;
|
||||
// #endif
|
||||
#if defined(PCF) || defined(CUBE) || defined(SPOT)
|
||||
uniform mat4 l_cubematrix;
|
||||
#endif
|
||||
attribute vec3 v_normal;
|
||||
attribute vec3 v_svector;
|
||||
attribute vec3 v_tvector;
|
||||
#endif
|
||||
|
||||
attribute vec2 v_texcoord;
|
||||
attribute vec2 v_lmcoord;
|
||||
attribute vec4 v_colour;
|
||||
|
||||
void main (void)
|
||||
{
|
||||
tc = v_texcoord.st;
|
||||
lm = v_lmcoord.st;
|
||||
vc = v_colour;
|
||||
gl_Position = ftetransform();
|
||||
|
||||
#ifdef RTLIGHT
|
||||
//light position is in model space, which is handy.
|
||||
vec3 lightminusvertex = l_lightposition - v_position.xyz;
|
||||
|
||||
//no bumpmapping, so we can just use distance without regard for actual surface direction. we still do scalecos stuff. you might notice it on steep slopes.
|
||||
lightvector = lightminusvertex;
|
||||
// lightvector.x = -dot(lightminusvertex, v_svector.xyz);
|
||||
// lightvector.y = dot(lightminusvertex, v_tvector.xyz);
|
||||
// lightvector.z = dot(lightminusvertex, v_normal.xyz);
|
||||
|
||||
// #if defined(SPECULAR)||defined(OFFSETMAPPING)
|
||||
// vec3 eyeminusvertex = e_eyepos - v_position.xyz;
|
||||
// eyevector.x = -dot(eyeminusvertex, v_svector.xyz);
|
||||
// eyevector.y = dot(eyeminusvertex, v_tvector.xyz);
|
||||
// eyevector.z = dot(eyeminusvertex, v_normal.xyz);
|
||||
// #endif
|
||||
#if defined(PCF) || defined(SPOT) || defined(CUBE)
|
||||
//for texture projections/shadowmapping on dlights
|
||||
vtexprojcoord = (l_cubematrix*vec4(v_position.xyz, 1.0));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -30,16 +81,67 @@ uniform sampler2D s_t3;
|
|||
//mix values
|
||||
uniform sampler2D s_t4;
|
||||
|
||||
#ifdef PCF
|
||||
sampler2DShadow s_t5;
|
||||
#include "sys/pcf.h"
|
||||
#endif
|
||||
|
||||
//light levels
|
||||
uniform vec4 e_lmscale;
|
||||
|
||||
#ifdef RTLIGHT
|
||||
uniform float l_lightradius;
|
||||
uniform vec3 l_lightcolour;
|
||||
uniform vec3 l_lightcolourscale;
|
||||
#endif
|
||||
|
||||
void main (void)
|
||||
{
|
||||
vec4 r;
|
||||
vec4 m = texture2D(s_t4, lm);
|
||||
|
||||
gl_FragColor = fog4(vc*vec4(m.aaa,1.0)*(
|
||||
texture2D(s_t0, tc)*m.r
|
||||
+ texture2D(s_t1, tc)*m.g
|
||||
+ texture2D(s_t2, tc)*m.b
|
||||
+ texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b))
|
||||
));
|
||||
r = texture2D(s_t0, tc)*m.r;
|
||||
r += texture2D(s_t1, tc)*m.g;
|
||||
r += texture2D(s_t2, tc)*m.b;
|
||||
r += texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b));
|
||||
|
||||
//vertex colours provide a scaler that applies even through rtlights.
|
||||
r *= vc;
|
||||
|
||||
#ifdef RTLIGHT
|
||||
vec3 nl = normalize(lightvector);
|
||||
float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);
|
||||
vec3 diff;
|
||||
// #ifdef BUMP
|
||||
// colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(bumps, nl), 0.0));
|
||||
// #else
|
||||
colorscale *= (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));
|
||||
// #endif
|
||||
|
||||
// #ifdef SPECULAR
|
||||
// vec3 halfdir = normalize(normalize(eyevector) + nl);
|
||||
// float spec = pow(max(dot(halfdir, bumps), 0.0), 32.0 * specs.a);
|
||||
// diff += l_lightcolourscale.z * spec * specs.rgb;
|
||||
// #endif
|
||||
|
||||
|
||||
|
||||
#if defined(SPOT)
|
||||
if (vtexprojcoord.w < 0.0) discard;
|
||||
vec2 spot = ((vtexprojcoord.st)/vtexprojcoord.w);
|
||||
colorscale *= 1.0-(dot(spot,spot));
|
||||
#endif
|
||||
#ifdef PCF
|
||||
colorscale *= ShadowmapFilter(s_t5);
|
||||
#endif
|
||||
|
||||
r.rgb *= colorscale * l_lightcolour;
|
||||
|
||||
gl_FragColor = fog4additive(r);
|
||||
#else
|
||||
//lightmap is greyscale in m.a. probably we should just scale the texture mix, but precision errors when editing make me paranoid.
|
||||
r *= e_lmscale*vec4(m.aaa,1.0);
|
||||
gl_FragColor = fog4(r);
|
||||
#endif
|
||||
}
|
||||
#endif
|
|
@ -94,6 +94,7 @@ static int64_t AVIO_Seek(void *opaque, int64_t offset, int whence)
|
|||
{
|
||||
struct decctx *ctx = opaque;
|
||||
int64_t ret = ctx->fileofs;
|
||||
whence &= ~AVSEEK_FORCE;
|
||||
switch(whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
|
@ -110,7 +111,7 @@ static int64_t AVIO_Seek(void *opaque, int64_t offset, int whence)
|
|||
return ctx->filelen;
|
||||
}
|
||||
pFS_Seek(ctx->file, ctx->fileofs & 0xffffffff, ctx->fileofs>>32);
|
||||
return ret;
|
||||
return ctx->fileofs;
|
||||
}
|
||||
|
||||
static void AVDec_Destroy(void *vctx)
|
||||
|
@ -119,12 +120,14 @@ static void AVDec_Destroy(void *vctx)
|
|||
|
||||
// Free the video stuff
|
||||
avpicture_free(&ctx->pFrameRGB);
|
||||
if (ctx->pVCodecCtx)
|
||||
avcodec_close(ctx->pVCodecCtx);
|
||||
av_free(ctx->pVFrame);
|
||||
avcodec_close(ctx->pVCodecCtx);
|
||||
|
||||
// Free the audio decoder
|
||||
if (ctx->pACodecCtx)
|
||||
avcodec_close(ctx->pACodecCtx);
|
||||
av_free(ctx->pAFrame);
|
||||
avcodec_close(ctx->pACodecCtx);
|
||||
|
||||
// Close the video file
|
||||
avformat_close_input(&ctx->pFormatCtx);
|
||||
|
|
|
@ -379,7 +379,7 @@ int Base64_Decode(char *out, int outlen, char *src, int srclen)
|
|||
|
||||
|
||||
|
||||
|
||||
void XMPP_Menu_Password(jclient_t *acc);
|
||||
void RenameConsole(char *totrim);
|
||||
void JCL_Command(int accid, char *consolename);
|
||||
void JCL_LoadConfig(void);
|
||||
|
@ -506,6 +506,9 @@ static int sasl_plain_initial(jclient_t *jcl, char *buf, int bufsize)
|
|||
|
||||
if (jcl->issecure?jcl->allowauth_plaintls:jcl->allowauth_plainnontls)
|
||||
{
|
||||
if (!*jcl->password)
|
||||
return -2;
|
||||
|
||||
//realm isn't specified
|
||||
buf[len++] = 0;
|
||||
memcpy(buf+len, jcl->username, strlen(jcl->username));
|
||||
|
@ -568,6 +571,9 @@ static int sasl_digestmd5_initial(jclient_t *jcl, char *buf, int bufsize)
|
|||
{
|
||||
if (jcl->allowauth_digestmd5)
|
||||
{
|
||||
if (!*jcl->password)
|
||||
return -2;
|
||||
|
||||
//FIXME: randomize the cnonce and check the auth key
|
||||
//although really I'm not entirely sure what the point is.
|
||||
//if we just authenticated with a mitm attacker relay, we're screwed either way.
|
||||
|
@ -645,6 +651,8 @@ static int sasl_scramsha1_initial(jclient_t *jcl, char *buf, int bufsize)
|
|||
{
|
||||
if (jcl->allowauth_scramsha1)
|
||||
{
|
||||
if (!*jcl->password)
|
||||
return -2;
|
||||
strcpy(jcl->authnonce, "abcdefghijklmnopqrstuvwxyz"); //FIXME: should be random, to validate that the server knows our password too
|
||||
|
||||
Q_snprintf(buf, bufsize, "n,,n=%s,r=%s", jcl->username, jcl->authnonce);
|
||||
|
@ -1091,10 +1099,10 @@ static int sasl_oauth2_initial(jclient_t *jcl, char *buf, int bufsize)
|
|||
//in descending priority order
|
||||
saslmethod_t saslmethods[] =
|
||||
{
|
||||
{NULL, sasl_oauth2_initial, NULL}, //potentially avoids having to ask+store their password. a browser is required to obtain auth token for us.
|
||||
{"SCRAM-SHA-1", sasl_scramsha1_initial, sasl_scramsha1_challenge}, //lots of unreadable hashing
|
||||
{"DIGEST-MD5", sasl_digestmd5_initial, sasl_digestmd5_challenge}, //kinda silly
|
||||
{"PLAIN", sasl_plain_initial, NULL} //realm\0username\0password
|
||||
{"PLAIN", sasl_plain_initial, NULL}, //realm\0username\0password
|
||||
{NULL, sasl_oauth2_initial, NULL} //potentially avoids having to ask+store their password. a browser is required to obtain auth token for us.
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1217,6 +1225,22 @@ qintptr_t JCL_ConsoleLink(qintptr_t *args)
|
|||
JCL_AddClientMessagef(jcl, "<presence to='%s' type='unsubscribed'/>", who);
|
||||
return true;
|
||||
}
|
||||
#ifdef FILETRANSFERS
|
||||
else if (!strcmp(what, "fauth"))
|
||||
{
|
||||
JCL_Info_ValueForKey(link, "xmppsid", what, sizeof(what));
|
||||
if (jcl && jcl->status == JCL_ACTIVE)
|
||||
JCL_FT_AcceptFile(jcl, atoi(what), true);
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(what, "fdeny"))
|
||||
{
|
||||
JCL_Info_ValueForKey(link, "xmppsid", what, sizeof(what));
|
||||
if (jcl && jcl->status == JCL_ACTIVE)
|
||||
JCL_FT_AcceptFile(jcl, atoi(what), false);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#ifdef JINGLE
|
||||
else if (!strcmp(what, "jauth"))
|
||||
{
|
||||
|
@ -1287,28 +1311,38 @@ qintptr_t JCL_ConExecuteCommand(qintptr_t *args)
|
|||
{
|
||||
buddy_t *b;
|
||||
char consolename[256];
|
||||
jclient_t *jcl = jclients[0];
|
||||
jclient_t *jcl;
|
||||
int i;
|
||||
|
||||
if (!jcl)
|
||||
{
|
||||
char buffer[256];
|
||||
pCmd_Argv(0, buffer, sizeof(buffer));
|
||||
Con_SubPrintf(buffer, "You were disconnected\n");
|
||||
return true;
|
||||
}
|
||||
pCmd_Argv(0, consolename, sizeof(consolename));
|
||||
for (b = jcl->buddies; b; b = b->next)
|
||||
for (i = 0; i < sizeof(jclients) / sizeof(jclients[0]); i++)
|
||||
{
|
||||
if (!strcmp(b->name, consolename))
|
||||
jcl = jclients[i];
|
||||
if (!jcl)
|
||||
continue;
|
||||
for (b = jcl->buddies; b; b = b->next)
|
||||
{
|
||||
if (b->defaultresource)
|
||||
Q_snprintf(jcl->defaultdest, sizeof(jcl->defaultdest), "%s/%s", b->accountdomain, b->defaultresource->resource);
|
||||
else
|
||||
Q_snprintf(jcl->defaultdest, sizeof(jcl->defaultdest), "%s", b->accountdomain);
|
||||
break;
|
||||
if (!strcmp(b->name, consolename))
|
||||
{
|
||||
if (b->defaultresource)
|
||||
Q_snprintf(jcl->defaultdest, sizeof(jcl->defaultdest), "%s/%s", b->accountdomain, b->defaultresource->resource);
|
||||
else
|
||||
Q_snprintf(jcl->defaultdest, sizeof(jcl->defaultdest), "%s", b->accountdomain);
|
||||
JCL_Command(i, consolename);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
JCL_Command(0, consolename);
|
||||
for (i = 0; i < sizeof(jclients) / sizeof(jclients[0]); i++)
|
||||
{
|
||||
jcl = jclients[i];
|
||||
if (!jcl)
|
||||
continue;
|
||||
JCL_Command(i, consolename);
|
||||
return true;
|
||||
}
|
||||
|
||||
Con_SubPrintf(consolename, "You were disconnected\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1613,7 +1647,7 @@ jclient_t *JCL_Connect(int accnum, char *server, int forcetls, char *account, ch
|
|||
xmltree_t *x;
|
||||
|
||||
res = TrimResourceFromJid(account);
|
||||
if (!res)
|
||||
if (!res || !*res)
|
||||
{
|
||||
//the default resource matches the game that they're trying to play.
|
||||
if (pCvar_GetString("fs_gamename", gamename, sizeof(gamename)))
|
||||
|
@ -1946,11 +1980,11 @@ static char *caps[] =
|
|||
"urn:xmpp:attention:0", //poke.
|
||||
|
||||
//file transfer
|
||||
#ifdef FILETRANSFER
|
||||
#ifdef FILETRANSFERS
|
||||
"http://jabber.org/protocol/si",
|
||||
"http://jabber.org/protocol/si/profile/file-transfer",
|
||||
"http://jabber.org/protocol/ibb",
|
||||
//"http://jabber.org/protocol/bytestreams",
|
||||
"http://jabber.org/protocol/bytestreams",
|
||||
#endif
|
||||
#else
|
||||
//for testing, this is the list of features pidgin supports (which is the other client I'm testing against).
|
||||
|
@ -2202,6 +2236,64 @@ void JCL_ParseIQ(jclient_t *jcl, xmltree_t *tree)
|
|||
{
|
||||
xmltree_t *c;
|
||||
#ifdef FILETRANSFERS
|
||||
/*
|
||||
ot = XML_ChildOfTreeNS(tree, "http://jabber.org/protocol/bytestreams", "query", 0);
|
||||
if (ot)
|
||||
{
|
||||
struct ft_s *ft;
|
||||
char *sid = XML_GetParameter(ot, "sid", "");
|
||||
for (ft = jcl->ft; ft; ft = ft->next)
|
||||
{
|
||||
if (!strcmp(ft->sid, sid) && !strcmp(ft->with, from))
|
||||
{
|
||||
if (ft->allowed && !ft->begun && ft->transmitting == false)
|
||||
{
|
||||
char *jid;
|
||||
char *host;
|
||||
int port;
|
||||
char *req;
|
||||
char digest[20];
|
||||
char domain[41];
|
||||
char *hex="0123456789abcdef";
|
||||
int j, i;
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
c = XML_ChildOfTree(ot, "streamhost", i);
|
||||
if (!c)
|
||||
break;
|
||||
jid = XML_GetParameter(c, "jid", "");
|
||||
host = XML_GetParameter(c, "host", "");
|
||||
port = atoi(XML_GetParameter(c, "port", "0"));
|
||||
if (port <= 0 || port > 65535)
|
||||
continue;
|
||||
ft->stream = pNet_TCPConnect(host, port);
|
||||
if (ft->stream == -1)
|
||||
continue;
|
||||
|
||||
//'authenticate' with socks5 proxy.
|
||||
pNet_Send(ft->stream, "\x05\0x1\x00", 3);
|
||||
|
||||
//sid+requester(them)+target(us)
|
||||
req = va("%s%s%s", ft->sid, ft->with, jcl->jid);
|
||||
SHA1(digest, sizeof(digest), req, strlen(req));
|
||||
//in hex
|
||||
for (req = domain, j=0; j < 20; j++)
|
||||
{
|
||||
*req++ = hex[(digest[j]>>4) & 0xf];
|
||||
*req++ = hex[(digest[j]>>0) & 0xf];
|
||||
}
|
||||
*req = 0;
|
||||
|
||||
//connect with hostname(3).
|
||||
req = va("\x05\0x1\x00\x03%s\x00\x00", domain);
|
||||
pNet_Send(ft->stream, req, strlen(domain)+6);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
ot = XML_ChildOfTreeNS(tree, "http://jabber.org/protocol/ibb", "open", 0);
|
||||
if (ot)
|
||||
{
|
||||
|
@ -2211,9 +2303,9 @@ void JCL_ParseIQ(jclient_t *jcl, xmltree_t *tree)
|
|||
char *stanza = XML_GetParameter(ot, "stanza", "iq");
|
||||
for (ft = jcl->ft; ft; ft = ft->next)
|
||||
{
|
||||
if (!strcmp(ft->sid, sid))
|
||||
if (!strcmp(ft->sid, sid) && !strcmp(ft->with, from))
|
||||
{
|
||||
if (!ft->begun && ft->transmitting == false)
|
||||
if (ft->allowed && !ft->begun && ft->transmitting == false)
|
||||
{
|
||||
if (blocksize > 65536 || strcmp(stanza, "iq"))
|
||||
{ //blocksize: MUST NOT be greater than 65535
|
||||
|
@ -2244,7 +2336,7 @@ void JCL_ParseIQ(jclient_t *jcl, xmltree_t *tree)
|
|||
//if its okay...
|
||||
JCL_AddClientMessagef(jcl, "<iq id='%s' to='%s' type='result'/>", id, from);
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2257,7 +2349,7 @@ void JCL_ParseIQ(jclient_t *jcl, xmltree_t *tree)
|
|||
for (link = &jcl->ft; *link; link = &(*link)->next)
|
||||
{
|
||||
ft = *link;
|
||||
if (!strcmp(ft->sid, sid))
|
||||
if (!strcmp(ft->sid, sid) && !strcmp(ft->with, from))
|
||||
{
|
||||
if (ft->begun && ft->method == FT_IBB)
|
||||
{
|
||||
|
@ -2265,7 +2357,10 @@ void JCL_ParseIQ(jclient_t *jcl, xmltree_t *tree)
|
|||
pFS_Close(ft->file);
|
||||
if (ft->transmitting)
|
||||
{
|
||||
Con_Printf("%s aborted transfer of \"%s\"\n", from, ft->fname);
|
||||
if (ft->eof)
|
||||
Con_Printf("Sent \"%s\" to \"%s\"\n", ft->fname, ft->with);
|
||||
else
|
||||
Con_Printf("%s aborted transfer of \"%s\"\n", from, ft->fname);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2329,47 +2424,35 @@ void JCL_ParseIQ(jclient_t *jcl, xmltree_t *tree)
|
|||
char *md5hash = XML_GetParameter(file, "hash", "");
|
||||
int fsize = strtoul(XML_GetParameter(file, "size", "0"), NULL, 0);
|
||||
char *desc = XML_GetChildBody(file, "desc", "");
|
||||
|
||||
char authlink[512];
|
||||
char denylink[512];
|
||||
|
||||
//file transfer offer
|
||||
struct ft_s *ft = malloc(sizeof(*ft));
|
||||
struct ft_s *ft = malloc(sizeof(*ft) + strlen(from)+1);
|
||||
memset(ft, 0, sizeof(*ft));
|
||||
ft->next = jcl->ft;
|
||||
jcl->ft = ft;
|
||||
ft->privateid = ++jcl->privateidseq;
|
||||
|
||||
ft->transmitting = false;
|
||||
Q_strlcpy(ft->iqid, id, sizeof(ft->iqid));
|
||||
Q_strlcpy(ft->sid, sid, sizeof(ft->sid));
|
||||
Q_strlcpy(ft->fname, fname, sizeof(ft->sid));
|
||||
Base64_Decode(ft->md5hash, sizeof(ft->md5hash), md5hash, strlen(md5hash));
|
||||
ft->size = fsize;
|
||||
ft->file = -1;
|
||||
// ft->with =
|
||||
ft->method = FT_IBB;
|
||||
ft->with = (char*)(ft+1);
|
||||
strcpy(ft->with, from);
|
||||
ft->method = (fsize > 1024*128)?FT_BYTESTREAM:FT_IBB; //favour bytestreams for large files. for small files, just use ibb as it saves sorting out proxies.
|
||||
ft->begun = false;
|
||||
|
||||
Con_Printf("Receiving file \"%s\" from \"%s\" (%i bytes)\n", fname, from, fsize);
|
||||
|
||||
//generate a response.
|
||||
//FIXME: we ought to delay response until after we prompt.
|
||||
repiq = XML_CreateNode(NULL, "iq", "", "");
|
||||
XML_AddParameter(repiq, "type", "result");
|
||||
XML_AddParameter(repiq, "to", from);
|
||||
XML_AddParameter(repiq, "id", id);
|
||||
repsi = XML_CreateNode(repiq, "si", "http://jabber.org/protocol/si", "");
|
||||
XML_CreateNode(repsi, "file", "http://jabber.org/protocol/si/profile/file-transfer", ""); //I don't really get the point of this.
|
||||
c = XML_CreateNode(repsi, "feature", "http://jabber.org/protocol/feature-neg", "");
|
||||
c = XML_CreateNode(c, "x", "jabber:x:data", "");
|
||||
XML_AddParameter(c, "type", "submit");
|
||||
c = XML_CreateNode(c, "field", "", "");
|
||||
XML_AddParameter(c, "var", "stream-method");
|
||||
if (ft->method == FT_IBB)
|
||||
c = XML_CreateNode(c, "value", "", "http://jabber.org/protocol/ibb");
|
||||
else if (ft->method == FT_BYTESTREAM)
|
||||
c = XML_CreateNode(c, "value", "", "http://jabber.org/protocol/bytestreams");
|
||||
//FIXME: make bytestreams work.
|
||||
ft->method = FT_IBB;
|
||||
|
||||
s = XML_GenerateString(repiq, false);
|
||||
JCL_AddClientMessageString(jcl, s);
|
||||
free(s);
|
||||
XML_Destroy(repiq);
|
||||
JCL_GenLink(jcl, authlink, sizeof(authlink), "fauth", from, NULL, va("%i", ft->privateid), "%s", "Accept");
|
||||
JCL_GenLink(jcl, denylink, sizeof(denylink), "fdeny", from, NULL, va("%i", ft->privateid), "%s", "Deny");
|
||||
|
||||
Con_Printf("%s has offered to send you \"%s\" (%i bytes). %s %s\n", from, fname, fsize, authlink, denylink);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2425,7 +2508,7 @@ void JCL_ParseIQ(jclient_t *jcl, xmltree_t *tree)
|
|||
for (link = &jcl->pendingiqs; *link; link = &(*link)->next)
|
||||
{
|
||||
iq = *link;
|
||||
if (!strcmp(iq->id, id) && !strcmp(iq->to, from))
|
||||
if (!strcmp(iq->id, id) && (!strcmp(iq->to, from) || !*iq->to))
|
||||
break;
|
||||
}
|
||||
if (*link)
|
||||
|
@ -3150,6 +3233,7 @@ int JCL_ClientFrame(jclient_t *jcl)
|
|||
char out[512];
|
||||
char *method = NULL;
|
||||
int outlen = -1;
|
||||
qboolean needpass = false;
|
||||
if (jcl->forcetls > 0 && !jcl->issecure)
|
||||
{
|
||||
if (BUILTINISVALID(Net_SetTLSClient))
|
||||
|
@ -3174,18 +3258,23 @@ int JCL_ClientFrame(jclient_t *jcl)
|
|||
if (!strcmp(m->body, method))
|
||||
{
|
||||
outlen = saslmethods[sm].sasl_initial(jcl, out, sizeof(out));
|
||||
if (outlen != -1)
|
||||
if (outlen >= 0)
|
||||
break;
|
||||
if (outlen == -2)
|
||||
needpass = true;
|
||||
}
|
||||
}
|
||||
if (outlen != -1)
|
||||
if (outlen >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (outlen == -2)
|
||||
if (outlen < 0)
|
||||
{
|
||||
XML_Destroy(tree);
|
||||
return JCL_KILL;
|
||||
//can't authenticate for some reason
|
||||
if (needpass)
|
||||
XMPP_Menu_Password(jcl);
|
||||
return JCL_NUKEFROMORBIT;
|
||||
}
|
||||
|
||||
if (outlen >= 0)
|
||||
|
@ -3773,7 +3862,7 @@ void JCL_PrintBuddyList(char *console, jclient_t *jcl, qboolean all)
|
|||
{
|
||||
JCL_FindBuddy(jcl, ft->with, &b, &r);
|
||||
JCL_GenLink(jcl, convolink, sizeof(convolink), NULL, b->accountdomain, r->resource, NULL, "%s", b->name);
|
||||
JCL_GenLink(jcl, actlink, sizeof(actlink), "ftdeny", ft->with, NULL, ft->sid, "%s", "Hang Up");
|
||||
JCL_GenLink(jcl, actlink, sizeof(actlink), "fdeny", ft->with, NULL, ft->sid, "%s", "Cancel");
|
||||
Con_SubPrintf(console, " %s: %s\n", convolink, ft->fname);
|
||||
}
|
||||
#endif
|
||||
|
@ -3860,7 +3949,7 @@ void JCL_AttentionMessage(jclient_t *jcl, char *to, char *msg)
|
|||
}
|
||||
}
|
||||
|
||||
void JCL_ToJID(jclient_t *jcl, char *in, char *out, int outsize)
|
||||
void JCL_ToJID(jclient_t *jcl, char *in, char *out, int outsize, qboolean assumeresource)
|
||||
{
|
||||
//decompose links first
|
||||
if (in[0] == '^' && in[1] == '[')
|
||||
|
@ -3892,7 +3981,23 @@ void JCL_ToJID(jclient_t *jcl, char *in, char *out, int outsize)
|
|||
{
|
||||
if (!strcasecmp(b->name, in))
|
||||
{
|
||||
if (b->defaultresource)
|
||||
if (b->defaultresource && assumeresource)
|
||||
Q_snprintf(out, outsize, "%s/%s", b->accountdomain, b->defaultresource->resource);
|
||||
else
|
||||
Q_strlcpy(out, b->accountdomain, outsize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (assumeresource)
|
||||
{
|
||||
buddy_t *b;
|
||||
for (b = jcl->buddies; b; b = b->next)
|
||||
{
|
||||
if (!strcasecmp(b->accountdomain, in))
|
||||
{
|
||||
if (b->defaultresource && assumeresource)
|
||||
Q_snprintf(out, outsize, "%s/%s", b->accountdomain, b->defaultresource->resource);
|
||||
else
|
||||
Q_strlcpy(out, b->accountdomain, outsize);
|
||||
|
@ -3933,6 +4038,76 @@ void JCL_JoinMUCChat(jclient_t *jcl, char *room, char *server, char *myhandle, c
|
|||
}
|
||||
|
||||
#ifdef FILETRANSFERS
|
||||
void JCL_FT_AcceptFile(jclient_t *jcl, int fileid, qboolean accept)
|
||||
{
|
||||
struct ft_s *ft, **link;
|
||||
char *s;
|
||||
xmltree_t *repiq, *repsi, *c;
|
||||
|
||||
for (link = &jcl->ft; ft=*link; link = &(*link)->next)
|
||||
{
|
||||
if (ft->privateid == fileid)
|
||||
break;
|
||||
}
|
||||
if (!ft)
|
||||
{
|
||||
Con_Printf("File not known\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!accept)
|
||||
{
|
||||
Con_Printf("Declining file \"%s\" from \"%s\" (%i bytes)\n", ft->fname, ft->with, ft->size);
|
||||
|
||||
if (!ft->allowed)
|
||||
{
|
||||
JCL_AddClientMessagef(jcl,
|
||||
"<iq type='error' to='%s' id='%s'>"
|
||||
"<error type='cancel'>"
|
||||
"<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
|
||||
"<text>Offer Declined</text>"
|
||||
"</error>"
|
||||
"</iq>", ft->with, ft->iqid);
|
||||
}
|
||||
else
|
||||
{
|
||||
//FIXME: send a proper cancel
|
||||
}
|
||||
|
||||
pFS_Close(ft->file);
|
||||
*link = ft->next;
|
||||
free(ft);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf("Receiving file \"%s\" from \"%s\" (%i bytes)\n", ft->fname, ft->with, ft->size);
|
||||
ft->allowed = true;
|
||||
|
||||
//generate a response.
|
||||
//FIXME: we ought to delay response until after we prompt.
|
||||
repiq = XML_CreateNode(NULL, "iq", "", "");
|
||||
XML_AddParameter(repiq, "type", "result");
|
||||
XML_AddParameter(repiq, "to", ft->with);
|
||||
XML_AddParameter(repiq, "id", ft->iqid);
|
||||
repsi = XML_CreateNode(repiq, "si", "http://jabber.org/protocol/si", "");
|
||||
XML_CreateNode(repsi, "file", "http://jabber.org/protocol/si/profile/file-transfer", ""); //I don't really get the point of this.
|
||||
c = XML_CreateNode(repsi, "feature", "http://jabber.org/protocol/feature-neg", "");
|
||||
c = XML_CreateNode(c, "x", "jabber:x:data", "");
|
||||
XML_AddParameter(c, "type", "submit");
|
||||
c = XML_CreateNode(c, "field", "", "");
|
||||
XML_AddParameter(c, "var", "stream-method");
|
||||
if (ft->method == FT_IBB)
|
||||
c = XML_CreateNode(c, "value", "", "http://jabber.org/protocol/ibb");
|
||||
else if (ft->method == FT_BYTESTREAM)
|
||||
c = XML_CreateNode(c, "value", "", "http://jabber.org/protocol/bytestreams");
|
||||
|
||||
s = XML_GenerateString(repiq, false);
|
||||
JCL_AddClientMessageString(jcl, s);
|
||||
free(s);
|
||||
XML_Destroy(repiq);
|
||||
}
|
||||
}
|
||||
|
||||
qboolean JCL_FT_IBBChunked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
|
||||
{
|
||||
char *from = XML_GetParameter(x, "from", "");
|
||||
|
@ -3950,6 +4125,13 @@ qboolean JCL_FT_IBBChunked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
|
|||
Base64_Add(rawbuf, sz);
|
||||
Base64_Finish();
|
||||
|
||||
if (sz > 0)
|
||||
{
|
||||
ft->sizedone += sz;
|
||||
if (ft->sizedone == ft->size)
|
||||
ft->eof = true;
|
||||
}
|
||||
|
||||
if (sz && strlen(base64))
|
||||
{
|
||||
x = XML_CreateNode(NULL, "data", "http://jabber.org/protocol/ibb", base64);
|
||||
|
@ -3978,7 +4160,7 @@ qboolean JCL_FT_IBBChunked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true; //the ack can come after the bytestream has already finished sending. don't warn about that.
|
||||
}
|
||||
qboolean JCL_FT_IBBBegun(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
|
||||
{
|
||||
|
@ -4042,6 +4224,42 @@ qboolean JCL_FT_OfferAcked(jclient_t *jcl, xmltree_t *x, struct iq_s *iq)
|
|||
}
|
||||
#endif
|
||||
|
||||
void XMPP_Menu_Password(jclient_t *acc)
|
||||
{
|
||||
int y;
|
||||
pCmd_AddText("conmenu\n"
|
||||
"{\n"
|
||||
"menuclear\n"
|
||||
"if (option == \"SignIn\")\n"
|
||||
"{\n"COMMANDPREFIX" /password ${0}\n}\n"
|
||||
"}\n", false);
|
||||
|
||||
y = 36;
|
||||
pCmd_AddText(va("menutext 48 %i \"^sXMPP Sign In\"\n", y), false); y+=16;
|
||||
pCmd_AddText(va("menutext 48 %i \"^sPlease provide your password for\"\n", y), false); y+=16;
|
||||
pCmd_AddText(va("menueditpriv 48 %i \"%s@%s\" \"example\"\n", y, acc->username, acc->domain), false);y+=16;
|
||||
pCmd_AddText(va("menutext 48 %i \"Sign In\" SignIn\n", y), false);
|
||||
pCmd_AddText(va("menutext 256 %i \"Cancel\" cancel\n", y), false);
|
||||
}
|
||||
void XMPP_Menu_Connect(void)
|
||||
{
|
||||
int y;
|
||||
pCmd_AddText("conmenu\n"
|
||||
"{\n"
|
||||
"menuclear\n"
|
||||
"if (option == \"SignIn\")\n"
|
||||
"{\n"COMMANDPREFIX" /connect ${0}@${1}/${2}\n}\n"
|
||||
"}\n", false);
|
||||
|
||||
y = 36;
|
||||
pCmd_AddText(va("menutext 48 %i \"^sXMPP Sign In\"\n", y), false); y+=16;
|
||||
pCmd_AddText(va("menueditpriv 48 %i \"Username\" \"example\"\n", y), false);y+=16;
|
||||
pCmd_AddText(va("menueditpriv 48 %i \"Domain\" \"gmail.com\"\n", y), false);y+=16;
|
||||
pCmd_AddText(va("menueditpriv 48 %i \"Resource\" \"\"\n", y), false);y+=32;
|
||||
pCmd_AddText(va("menutext 48 %i \"Sign In\" SignIn\n", y), false);
|
||||
pCmd_AddText(va("menutext 256 %i \"Cancel\" cancel\n", y), false);
|
||||
}
|
||||
|
||||
void JCL_Command(int accid, char *console)
|
||||
{
|
||||
char imsg[8192];
|
||||
|
@ -4061,8 +4279,9 @@ void JCL_Command(int accid, char *console)
|
|||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if (!msg)
|
||||
continue;
|
||||
msg = JCL_ParseOut(msg, arg[i], sizeof(arg[i]));
|
||||
*arg[i] = 0;
|
||||
else
|
||||
msg = JCL_ParseOut(msg, arg[i], sizeof(arg[i]));
|
||||
}
|
||||
|
||||
if (arg[0][0] == '/' && arg[0][1] != '/' && strcmp(arg[0]+1, "me"))
|
||||
|
@ -4072,6 +4291,7 @@ void JCL_Command(int accid, char *console)
|
|||
int tls;
|
||||
if (!*arg[1])
|
||||
{
|
||||
XMPP_Menu_Connect();
|
||||
Con_SubPrintf(console, "%s <account@domain/resource> <password> <server>\n", arg[0]+1);
|
||||
return;
|
||||
}
|
||||
|
@ -4163,6 +4383,12 @@ void JCL_Command(int accid, char *console)
|
|||
if (jcl->status == JCL_INACTIVE)
|
||||
jcl->status = JCL_DEAD;
|
||||
}
|
||||
else if (!strcmp(arg[0]+1, "password"))
|
||||
{
|
||||
Q_strncpyz(jcl->password, arg[1], sizeof(jcl->password));
|
||||
if (jcl->status == JCL_INACTIVE)
|
||||
jcl->status = JCL_DEAD;
|
||||
}
|
||||
else if (!strcmp(arg[0]+1, "quit"))
|
||||
{
|
||||
//disconnect from the xmpp server.
|
||||
|
@ -4215,27 +4441,22 @@ void JCL_Command(int accid, char *console)
|
|||
#ifdef JINGLE
|
||||
else if (!strcmp(arg[0]+1, "join"))
|
||||
{
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname));
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname), true);
|
||||
JCL_Join(jcl, nname, NULL, true, ICEP_QWCLIENT);
|
||||
}
|
||||
else if (!strcmp(arg[0]+1, "invite"))
|
||||
{
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname));
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname), true);
|
||||
JCL_Join(jcl, nname, NULL, true, ICEP_QWSERVER);
|
||||
}
|
||||
else if (!strcmp(arg[0]+1, "voice") || !strcmp(arg[0]+1, "call"))
|
||||
{
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname));
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname), true);
|
||||
JCL_Join(jcl, nname, NULL, true, ICEP_VOICE);
|
||||
}
|
||||
else if (!strcmp(arg[0]+1, "kick"))
|
||||
{
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname));
|
||||
JCL_Join(jcl, nname, NULL, false, ICEP_INVALID);
|
||||
}
|
||||
else if (!strcmp(arg[0]+1, "kick"))
|
||||
{
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname));
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname), true);
|
||||
JCL_Join(jcl, nname, NULL, false, ICEP_INVALID);
|
||||
}
|
||||
#endif
|
||||
|
@ -4254,7 +4475,7 @@ void JCL_Command(int accid, char *console)
|
|||
}
|
||||
else
|
||||
{
|
||||
JCL_ToJID(jcl, *arg[2]?arg[2]:console, nname, sizeof(nname));
|
||||
JCL_ToJID(jcl, *arg[2]?arg[2]:console, nname, sizeof(nname), true);
|
||||
|
||||
Con_SubPrintf(console, "Offering %s to %s.\n", fname, nname);
|
||||
|
||||
|
@ -4262,7 +4483,7 @@ void JCL_Command(int accid, char *console)
|
|||
memset(ft, 0, sizeof(*ft));
|
||||
ft->next = jcl->ft;
|
||||
jcl->ft = ft;
|
||||
|
||||
ft->allowed = true;
|
||||
ft->transmitting = true;
|
||||
ft->blocksize = 4096;
|
||||
Q_strlcpy(ft->fname, fname, sizeof(ft->fname));
|
||||
|
@ -4275,20 +4496,20 @@ void JCL_Command(int accid, char *console)
|
|||
|
||||
//generate an offer.
|
||||
xsi = XML_CreateNode(NULL, "si", "http://jabber.org/protocol/si", "");
|
||||
XML_AddParameter(xsi, "profile", "http://jabber.org/protocol/si/profile/file-transfer");
|
||||
XML_AddParameter(xsi, "id", ft->sid);
|
||||
XML_AddParameter(xsi, "profile", "http://jabber.org/protocol/si/profile/file-transfer");
|
||||
XML_AddParameter(xsi, "id", ft->sid);
|
||||
//XML_AddParameter(xsi, "mime-type", "text/plain");
|
||||
xfile = XML_CreateNode(xsi, "file", "http://jabber.org/protocol/si/profile/file-transfer", ""); //I don't really get the point of this.
|
||||
XML_AddParameter(xfile, "name", ft->fname);
|
||||
XML_AddParameteri(xfile, "size", ft->size);
|
||||
XML_AddParameter(xfile, "name", ft->fname);
|
||||
XML_AddParameteri(xfile, "size", ft->size);
|
||||
c = XML_CreateNode(xsi, "feature", "http://jabber.org/protocol/feature-neg", "");
|
||||
c = XML_CreateNode(c, "x", "jabber:x:data", "");
|
||||
XML_AddParameter(c, "type", "form");
|
||||
c = XML_CreateNode(c, "field", "", "");
|
||||
XML_AddParameter(c, "var", "stream-method");
|
||||
XML_AddParameter(c, "type", "listsingle");
|
||||
XML_CreateNode(XML_CreateNode(c, "option", "", ""), "value", "", "http://jabber.org/protocol/ibb");
|
||||
// XML_CreateNode(XML_CreateNode(c, "option", "", ""), "value", "", "http://jabber.org/protocol/bytestreams");
|
||||
c = XML_CreateNode(c, "x", "jabber:x:data", "");
|
||||
XML_AddParameter(c, "type", "form");
|
||||
c = XML_CreateNode(c, "field", "", "");
|
||||
XML_AddParameter(c, "var", "stream-method");
|
||||
XML_AddParameter(c, "type", "listsingle");
|
||||
XML_CreateNode(XML_CreateNode(c, "option", "", ""), "value", "", "http://jabber.org/protocol/ibb");
|
||||
// XML_CreateNode(XML_CreateNode(c, "option", "", ""), "value", "", "http://jabber.org/protocol/bytestreams");
|
||||
|
||||
JCL_SendIQNode(jcl, JCL_FT_OfferAcked, "set", nname, xsi, true)->usrptr = ft;
|
||||
}
|
||||
|
@ -4325,12 +4546,12 @@ void JCL_Command(int accid, char *console)
|
|||
"/me goes to order cod and chips. brb",
|
||||
"/me goes to watch some monty python"
|
||||
};
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname));
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname), true);
|
||||
JCL_AttentionMessage(jcl, nname, msgtab[rand()%(sizeof(msgtab)/sizeof(msgtab[0]))]);
|
||||
}
|
||||
else if (!strcmp(arg[0]+1, "poke"))
|
||||
{
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname));
|
||||
JCL_ToJID(jcl, *arg[1]?arg[1]:console, nname, sizeof(nname), true);
|
||||
JCL_AttentionMessage(jcl, nname, NULL);
|
||||
}
|
||||
else if (!strcmp(arg[0]+1, "raw"))
|
||||
|
@ -4374,7 +4595,7 @@ void JCL_Command(int accid, char *console)
|
|||
}
|
||||
else
|
||||
{
|
||||
JCL_ToJID(jcl, *console?console:jcl->defaultdest, nname, sizeof(nname));
|
||||
JCL_ToJID(jcl, *console?console:jcl->defaultdest, nname, sizeof(nname), true);
|
||||
JCL_SendMessage(jcl, nname, msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -875,6 +875,9 @@ static qboolean JCL_JingleHandleSessionTerminate(jclient_t *jcl, xmltree_t *tree
|
|||
}
|
||||
static qboolean JCL_JingleHandleSessionAccept(jclient_t *jcl, xmltree_t *tree, char *from, struct c2c_s *c2c, buddy_t *b)
|
||||
{
|
||||
//peer accepted our session
|
||||
//make sure it actually was ours, and not theirs. sneaky sneaky.
|
||||
//will generally contain some port info.
|
||||
if (!c2c)
|
||||
{
|
||||
Con_DPrintf("Unknown session acceptance\n");
|
||||
|
@ -972,6 +975,51 @@ qboolean JCL_HandleGoogleSession(jclient_t *jcl, xmltree_t *tree, char *from, ch
|
|||
return true;
|
||||
}
|
||||
#endif
|
||||
enum
|
||||
{
|
||||
JE_ACKNOWLEDGE,
|
||||
JE_UNSUPPORTED,
|
||||
JE_OUTOFORDER,
|
||||
JE_TIEBREAK,
|
||||
JE_UNKNOWNSESSION,
|
||||
JE_UNSUPPORTEDINFO
|
||||
};
|
||||
void JCL_JingleError(jclient_t *jcl, xmltree_t *tree, char *from, char *id, int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case JE_ACKNOWLEDGE:
|
||||
JCL_AddClientMessagef(jcl,
|
||||
"<iq type='result' to='%s' id='%s' />", from, id);
|
||||
break;
|
||||
case JE_UNSUPPORTED:
|
||||
JCL_AddClientMessagef(jcl,
|
||||
"<iq id='%s' to='%s' type='error'>"
|
||||
"<error type='cancel'>"
|
||||
"<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
|
||||
"</error>"
|
||||
"</iq>", id, from);
|
||||
break;
|
||||
case JE_UNKNOWNSESSION:
|
||||
JCL_AddClientMessagef(jcl,
|
||||
"<iq id='%s' to='%s' type='error'>"
|
||||
"<error type='modify'>"
|
||||
"<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
|
||||
"<unknown-session xmlns='urn:xmpp:jingle:errors:1'/>"
|
||||
"</error>"
|
||||
"</iq>", id, from);
|
||||
break;
|
||||
case JE_UNSUPPORTEDINFO:
|
||||
JCL_AddClientMessagef(jcl,
|
||||
"<iq id='%s' to='%s' type='error'>"
|
||||
"<error type='modify'>"
|
||||
"<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>"
|
||||
"<unsupported-info xmlns='urn:xmpp:jingle:errors:1'/>"
|
||||
"</error>"
|
||||
"</iq>", id, from);
|
||||
break;
|
||||
}
|
||||
}
|
||||
qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, char *from, char *id)
|
||||
{
|
||||
char *action = XML_GetParameter(tree, "action", "");
|
||||
|
@ -1002,22 +1050,85 @@ qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, char *from, char *id)
|
|||
//FIXME: transport-info, transport-replace
|
||||
if (!strcmp(action, "session-terminate"))
|
||||
{
|
||||
JCL_JingleHandleSessionTerminate(jcl, tree, c2c, link, b);
|
||||
if (c2c)
|
||||
{
|
||||
JCL_JingleError(jcl, tree, from, id, JE_ACKNOWLEDGE);
|
||||
JCL_JingleHandleSessionTerminate(jcl, tree, c2c, link, b);
|
||||
}
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
//content-accept
|
||||
//content-add
|
||||
//content-modify
|
||||
//content-reject
|
||||
//content-remove
|
||||
//description-info
|
||||
//security-info
|
||||
//
|
||||
else if (!strcmp(action, "content-accept"))
|
||||
{
|
||||
//response from content-add
|
||||
if (c2c)
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNSUPPORTED);
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
else if (!strcmp(action, "content-add"))
|
||||
{
|
||||
//FIXME: must send content-reject
|
||||
if (c2c)
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNSUPPORTED);
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
else if (!strcmp(action, "content-modify"))
|
||||
{
|
||||
//send an error to reject it
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNSUPPORTED);
|
||||
}
|
||||
else if (!strcmp(action, "content-reject"))
|
||||
{
|
||||
//response from content-add. an error until we actually generate content-adds...
|
||||
if (c2c)
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNSUPPORTED);
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
else if (!strcmp(action, "content-remove"))
|
||||
{
|
||||
if (c2c)
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNSUPPORTED);
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
else if (!strcmp(action, "description-info"))
|
||||
{
|
||||
//The description-info action is used to send informational hints about parameters related to the application type, such as the suggested height and width of a video display area or suggested configuration for an audio stream.
|
||||
//just ack and ignore it
|
||||
if (c2c)
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNSUPPORTED);
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
else if (!strcmp(action, "security-info"))
|
||||
{
|
||||
//The security-info action is used to send information related to establishment or maintenance of security preconditions.
|
||||
//no security mechanisms supported...
|
||||
if (c2c)
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNSUPPORTED);
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
else if (!strcmp(action, "session-info"))
|
||||
{
|
||||
if (tree->child)
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNSUPPORTEDINFO);
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_ACKNOWLEDGE); //serves as a ping.
|
||||
}
|
||||
|
||||
else if (!strcmp(action, "transport-info"))
|
||||
{ //peer wants to add ports.
|
||||
if (c2c)
|
||||
{
|
||||
JCL_JingleError(jcl, tree, from, id, JE_ACKNOWLEDGE);
|
||||
JCL_JingleParsePeerPorts(jcl, c2c, tree, from, sid);
|
||||
}
|
||||
else
|
||||
Con_DPrintf("Received transport-info without an active session\n");
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
//FIXME: we need to add support for this to downgrade to raw if someone tries calling through a SIP gateway
|
||||
else if (!strcmp(action, "transport-replace"))
|
||||
|
@ -1025,39 +1136,51 @@ qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, char *from, char *id)
|
|||
if (c2c)
|
||||
{
|
||||
if (1)
|
||||
{
|
||||
JCL_JingleError(jcl, tree, from, id, JE_ACKNOWLEDGE);
|
||||
JCL_JingleSend(jcl, c2c, "transport-reject");
|
||||
}
|
||||
else
|
||||
{
|
||||
JCL_JingleError(jcl, tree, from, id, JE_ACKNOWLEDGE);
|
||||
JCL_JingleParsePeerPorts(jcl, c2c, tree, from, sid);
|
||||
JCL_JingleSend(jcl, c2c, "transport-accept");
|
||||
}
|
||||
}
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
else if (!strcmp(action, "transport-reject"))
|
||||
{
|
||||
JCL_JingleError(jcl, tree, from, id, JE_ACKNOWLEDGE);
|
||||
JCL_JingleSend(jcl, c2c, "session-terminate");
|
||||
}
|
||||
else if (!strcmp(action, "session-accept"))
|
||||
{
|
||||
if (!JCL_JingleHandleSessionAccept(jcl, tree, from, c2c, b))
|
||||
return false;
|
||||
if (c2c)
|
||||
{
|
||||
//response from a message we sent.
|
||||
if (JCL_JingleHandleSessionAccept(jcl, tree, from, c2c, b))
|
||||
JCL_JingleError(jcl, tree, from, id, JE_ACKNOWLEDGE);
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_OUTOFORDER);
|
||||
}
|
||||
else
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNKNOWNSESSION);
|
||||
}
|
||||
else if (!strcmp(action, "session-initiate"))
|
||||
{
|
||||
// Con_Printf("Peer initiating connection!\n");
|
||||
// XML_ConPrintTree(tree, 0);
|
||||
|
||||
if (!JCL_JingleHandleInitiate(jcl, tree, from))
|
||||
return false;
|
||||
JCL_JingleError(jcl, tree, from, id, JE_ACKNOWLEDGE);
|
||||
|
||||
JCL_JingleHandleInitiate(jcl, tree, from);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf("Unknown jingle action: %s\n", action);
|
||||
// XML_ConPrintTree(tree, 0);
|
||||
JCL_JingleError(jcl, tree, from, id, JE_UNSUPPORTED);
|
||||
}
|
||||
|
||||
JCL_AddClientMessagef(jcl,
|
||||
"<iq type='result' to='%s' id='%s' />", from, id);
|
||||
return true;
|
||||
}
|
||||
#endif
|
|
@ -190,14 +190,20 @@ typedef struct jclient_s
|
|||
struct ft_s *next;
|
||||
char fname[MAX_QPATH];
|
||||
int size;
|
||||
int sizedone;
|
||||
char *with;
|
||||
char md5hash[16];
|
||||
int privateid;
|
||||
char iqid[64];
|
||||
char sid[64];
|
||||
int blocksize;
|
||||
unsigned short seq;
|
||||
qhandle_t file;
|
||||
qboolean begun;
|
||||
qboolean transmitting;
|
||||
qhandle_t stream;
|
||||
qboolean begun; //handshake
|
||||
qboolean eof;
|
||||
qboolean transmitting; //we're offering
|
||||
qboolean allowed; //if false, don't handshake the transfer
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -205,6 +211,7 @@ typedef struct jclient_s
|
|||
FT_BYTESTREAM //aka: relay
|
||||
} method;
|
||||
} *ft;
|
||||
int privateidseq;
|
||||
#endif
|
||||
|
||||
buddy_t *buddies;
|
||||
|
@ -232,4 +239,6 @@ void JCL_Join(jclient_t *jcl, char *target, char *sid, qboolean allow, int proto
|
|||
void JCL_JingleTimeouts(jclient_t *jcl, qboolean killall);
|
||||
//jingle iq message handlers
|
||||
qboolean JCL_HandleGoogleSession(jclient_t *jcl, xmltree_t *tree, char *from, char *id);
|
||||
qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, char *from, char *id);
|
||||
qboolean JCL_ParseJingle(jclient_t *jcl, xmltree_t *tree, char *from, char *id);
|
||||
|
||||
void JCL_FT_AcceptFile(jclient_t *jcl, int fileid, qboolean accept);
|
|
@ -390,6 +390,9 @@ void MPQ_BuildHash(searchpathfuncs_t *handle, int depth, void (QDECL *AddFileHas
|
|||
while (*n && *n != '\r' && *n != '\n' && *n != ';')
|
||||
n++;
|
||||
|
||||
if (n-s >= sizeof(name))
|
||||
continue;
|
||||
|
||||
memcpy(name, s, n - s);
|
||||
name[n-s] = 0;
|
||||
//precompute the name->block lookup. fte normally does the hashing outside the archive code.
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
<Platform
|
||||
Name="x64"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
|
@ -169,6 +172,163 @@
|
|||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;FTEPLUGIN"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="zlib64.lib"
|
||||
OutputFile="../../fteplug_mpqamd64.dll"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="../..\engine\libs"
|
||||
ModuleDefinitionFile="../plugin.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TargetEnvironment="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common"
|
||||
PreprocessorDefinitions="WIN32;FTEPLUGIN"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="zlib.lib"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="../..\engine\libs"
|
||||
ModuleDefinitionFile="../plugin.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
|
|
Loading…
Reference in a new issue