diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 428701fd..4ce9a0c4 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -106,7 +106,7 @@ qboolean Cam_DrawViewModel(int pnum) } else { - if (selfcam == 1 && r_secondaryview != 3) + if (selfcam == 1 && !r_refdef.externalview) return true; return false; } @@ -125,7 +125,7 @@ qboolean Cam_DrawPlayer(int pnum, int playernum) } else { - if (selfcam == 1 && r_secondaryview != 3) + if (selfcam == 1 && !r_refdef.externalview) if (playernum == (cl.viewentity[pnum]?cl.viewentity[pnum]-1:(cl.playernum[pnum]))) return false; } diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 529d7c23..ec1b4e41 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -453,7 +453,7 @@ int VM_LerpTag(void *out, model_t *model, int f1, int f2, float l2, char *tagnam #define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) Host_EndGame("Call to cgame trap %i passes invalid pointer\n", fn); //out of bounds. -static int CG_SystemCallsEx(void *offset, unsigned int mask, int fn, const int *arg) +static qintptr_t CG_SystemCallsEx(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg) { int ret=0; @@ -1048,7 +1048,7 @@ static int CG_SystemCallsEx(void *offset, unsigned int mask, int fn, const int * return ret; } #ifdef _DEBUG -static int CG_SystemCallsExWrapper(void *offset, unsigned int mask, int fn, const int *arg) +static qintptr_t CG_SystemCallsExWrapper(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg) { //this is so we can use edit and continue properly (vc doesn't like function pointers for edit+continue) return CG_SystemCallsEx(offset, mask, fn, arg); } diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index ae2fb199..49cc34b1 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1171,7 +1171,7 @@ void CL_Record_f (void) for (i = 0; i < cl.num_statics; i++) { - ent = cl_static_entities + i; + ent = &cl_static_entities[i].ent; MSG_WriteByte (&buf, svc_spawnstatic); diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 1d04a002..7363a045 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1434,6 +1434,50 @@ static void CL_UpdateNetFrameLerpState(qboolean force, unsigned int curframe, le } } +void CL_LinkStaticEntities(void *pvs) +{ + int i; + entity_t *ent, *stat; + model_t *clmodel; + extern cvar_t r_drawflame, gl_part_flame; + +// if (!cl_staticentities.ival) +// return; + + if (!cl.worldmodel) + return; + + for (i = 0; i < cl.num_statics; i++) + { + if (cl_numvisedicts == MAX_VISEDICTS) + break; + stat = &cl_static_entities[i].ent; + + clmodel = stat->model; + + if ((!r_drawflame.ival) && (clmodel->engineflags & MDLF_FLAME)) + continue; + + if (!cl.worldmodel->funcs.EdictInFatPVS(cl.worldmodel, &cl_static_entities[i].pvscache, pvs)) + continue; + /*pvs test*/ + + ent = &cl_visedicts[cl_numvisedicts++]; + *ent = *stat; + ent->framestate.g[FS_REG].frametime[0] = cl.time; + ent->framestate.g[FS_REG].frametime[1] = cl.time; + + // emit particles for statics (we don't need to cheat check statics) + if (clmodel->particleeffect >= 0 && gl_part_flame.ival) + { + // TODO: this is ugly.. assumes ent is in static entities, and subtracts + // pointer math to get an index to use in cl_static emit + // there needs to be a cleaner method for this + P_EmitEffect(ent->origin, clmodel->particleeffect, &cl_static_entities[i].emit); + } + } +} + /* =============== CL_LinkPacketEntities @@ -1669,9 +1713,11 @@ qboolean CL_MayLerp(void) return true; if (cls.protocol == CP_NETQUAKE) //this includes DP protocols. - return !cl_nolerp_netquake.value; + return !cl_nolerp_netquake.ival; #endif - return !cl_nolerp.value; + if (cl_nolerp.ival == 2 && cls.gamemode != GAME_DEATHMATCH) + return true; + return !cl_nolerp.ival; } void CL_LinkPacketEntities (void) diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 64c235e5..bcb6504b 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -29,19 +29,19 @@ float in_sensitivityscale = 1; void CL_SpareMsec_Callback (struct cvar_s *var, char *oldvalue); -cvar_t cl_nodelta = SCVAR("cl_nodelta","0"); +cvar_t cl_nodelta = CVAR("cl_nodelta","0"); -cvar_t cl_c2spps = SCVAR("cl_c2spps", "0"); +cvar_t cl_c2spps = CVAR("cl_c2spps", "0"); cvar_t cl_c2sImpulseBackup = SCVAR("cl_c2sImpulseBackup","3"); -cvar_t cl_netfps = SCVAR("cl_netfps", "0"); -cvar_t cl_sparemsec = SCVARC("cl_sparemsec", "10", CL_SpareMsec_Callback); -cvar_t cl_queueimpulses = SCVAR("cl_queueimpulses", "0"); -cvar_t cl_smartjump = SCVAR("cl_smartjump", "1"); +cvar_t cl_netfps = CVAR("cl_netfps", "0"); +cvar_t cl_sparemsec = CVARC("cl_sparemsec", "10", CL_SpareMsec_Callback); +cvar_t cl_queueimpulses = CVAR("cl_queueimpulses", "0"); +cvar_t cl_smartjump = CVAR("cl_smartjump", "1"); -cvar_t cl_prydoncursor = SCVAR("cl_prydoncursor", ""); //for dp protocol -cvar_t cl_instantrotate = SCVARF("cl_instantrotate", "1", CVAR_SEMICHEAT); +cvar_t cl_prydoncursor = CVAR("cl_prydoncursor", ""); //for dp protocol +cvar_t cl_instantrotate = CVARF("cl_instantrotate", "1", CVAR_SEMICHEAT); -cvar_t prox_inmenu = SCVAR("prox_inmenu", "0"); +cvar_t prox_inmenu = CVAR("prox_inmenu", "0"); usercmd_t independantphysics[MAX_SPLITS]; vec3_t mousemovements[MAX_SPLITS]; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index d1e94761..6205e858 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -45,52 +45,52 @@ cvar_t cl_timeout = SCVAR("cl_timeout", "60"); cvar_t cl_shownet = SCVAR("cl_shownet","0"); // can be 0, 1, or 2 -cvar_t cl_sbar = SCVARFC("cl_sbar", "0", CVAR_ARCHIVE, CL_Sbar_Callback); -cvar_t cl_hudswap = SCVARF("cl_hudswap", "0", CVAR_ARCHIVE); -cvar_t cl_maxfps = SCVARF("cl_maxfps", "1000", CVAR_ARCHIVE); -cvar_t cl_nopext = SCVARF("cl_nopext", "0", CVAR_ARCHIVE); -cvar_t cl_pext_mask = SCVAR("cl_pext_mask", "0xffffffff"); -cvar_t cl_nolerp = SCVAR("cl_nolerp", "1"); -cvar_t cl_nolerp_netquake = SCVAR("cl_nolerp_netquake", "0"); -cvar_t hud_tracking_show = SCVAR("hud_tracking_show", "1"); +cvar_t cl_sbar = CVARFC("cl_sbar", "0", CVAR_ARCHIVE, CL_Sbar_Callback); +cvar_t cl_hudswap = CVARF("cl_hudswap", "0", CVAR_ARCHIVE); +cvar_t cl_maxfps = CVARF("cl_maxfps", "1000", CVAR_ARCHIVE); +cvar_t cl_nopext = CVARF("cl_nopext", "0", CVAR_ARCHIVE); +cvar_t cl_pext_mask = CVAR("cl_pext_mask", "0xffffffff"); +cvar_t cl_nolerp = CVAR("cl_nolerp", "2"); +cvar_t cl_nolerp_netquake = CVAR("cl_nolerp_netquake", "0"); +cvar_t hud_tracking_show = CVAR("hud_tracking_show", "1"); -cvar_t cfg_save_name = SCVARF("cfg_save_name", "fte", CVAR_ARCHIVE); +cvar_t cfg_save_name = CVARF("cfg_save_name", "fte", CVAR_ARCHIVE); -cvar_t cl_splitscreen = SCVAR("cl_splitscreen", "0"); +cvar_t cl_splitscreen = CVAR("cl_splitscreen", "0"); -cvar_t lookspring = SCVARF("lookspring","0", CVAR_ARCHIVE); -cvar_t lookstrafe = SCVARF("lookstrafe","0", CVAR_ARCHIVE); -cvar_t sensitivity = SCVARF("sensitivity","10", CVAR_ARCHIVE); +cvar_t lookspring = CVARF("lookspring","0", CVAR_ARCHIVE); +cvar_t lookstrafe = CVARF("lookstrafe","0", CVAR_ARCHIVE); +cvar_t sensitivity = CVARF("sensitivity","10", CVAR_ARCHIVE); -cvar_t cl_staticsounds = SCVAR("cl_staticsounds", "1"); +cvar_t cl_staticsounds = CVAR("cl_staticsounds", "1"); -cvar_t m_pitch = SCVARF("m_pitch","0.022", CVAR_ARCHIVE); -cvar_t m_yaw = SCVARF("m_yaw","0.022", CVAR_ARCHIVE); -cvar_t m_forward = SCVARF("m_forward","1", CVAR_ARCHIVE); -cvar_t m_side = SCVARF("m_side","0.8", CVAR_ARCHIVE); +cvar_t m_pitch = CVARF("m_pitch","0.022", CVAR_ARCHIVE); +cvar_t m_yaw = CVARF("m_yaw","0.022", CVAR_ARCHIVE); +cvar_t m_forward = CVARF("m_forward","1", CVAR_ARCHIVE); +cvar_t m_side = CVARF("m_side","0.8", CVAR_ARCHIVE); -cvar_t entlatency = SCVAR("entlatency", "20"); -cvar_t cl_predict_players = SCVAR("cl_predict_players", "1"); -cvar_t cl_predict_players2 = SCVAR("cl_predict_players2", "1"); -cvar_t cl_solid_players = SCVAR("cl_solid_players", "1"); -cvar_t cl_noblink = SCVAR("cl_noblink", "0"); -cvar_t cl_servername = SCVAR("cl_servername", "none"); -cvar_t cl_serveraddress = SCVAR("cl_serveraddress", "none"); -cvar_t qtvcl_forceversion1 = SCVAR("qtvcl_forceversion1", "0"); -cvar_t qtvcl_eztvextensions = SCVAR("qtvcl_eztvextensions", "0"); +cvar_t entlatency = CVAR("entlatency", "20"); +cvar_t cl_predict_players = CVAR("cl_predict_players", "1"); +cvar_t cl_predict_players2 = CVAR("cl_predict_players2", "1"); +cvar_t cl_solid_players = CVAR("cl_solid_players", "1"); +cvar_t cl_noblink = CVAR("cl_noblink", "0"); +cvar_t cl_servername = CVAR("cl_servername", "none"); +cvar_t cl_serveraddress = CVAR("cl_serveraddress", "none"); +cvar_t qtvcl_forceversion1 = CVAR("qtvcl_forceversion1", "0"); +cvar_t qtvcl_eztvextensions = CVAR("qtvcl_eztvextensions", "0"); -cvar_t cl_demospeed = FCVAR("cl_demospeed", "demo_setspeed", "1", 0); +cvar_t cl_demospeed = CVARAF("cl_demospeed", "1", "demo_setspeed", 0); -cvar_t cl_loopbackprotocol = SCVAR("cl_loopbackprotocol", "qw"); +cvar_t cl_loopbackprotocol = CVAR("cl_loopbackprotocol", "qw"); -cvar_t cl_indepphysics = SCVAR("cl_indepphysics", "0"); +cvar_t cl_indepphysics = CVAR("cl_indepphysics", "0"); cvar_t localid = SCVAR("localid", ""); -cvar_t cl_antibunch = SCVAR("cl_antibunch", "0"); +cvar_t cl_antibunch = CVAR("cl_antibunch", "0"); -cvar_t r_drawflame = SCVAR("r_drawflame", "1"); +cvar_t r_drawflame = CVAR("r_drawflame", "1"); static qboolean allowremotecmd = true; @@ -99,33 +99,33 @@ extern int total_loading_size, current_loading_size, loading_stage; // // info mirrors // -cvar_t password = SCVARF("password", "", CVAR_USERINFO | CVAR_NOUNSAFEEXPAND); //this is parhaps slightly dodgy... -cvar_t spectator = SCVARF("spectator", "", CVAR_USERINFO); -cvar_t name = SCVARFC("name", "unnamed", CVAR_ARCHIVE | CVAR_USERINFO, Name_Callback); -cvar_t team = SCVARF("team", "", CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t skin = SCVARF("skin", "", CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t model = SCVARF("model", "", CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t topcolor = SCVARF("topcolor", "", CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t bottomcolor = SCVARF("bottomcolor", "", CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t rate = SCVARF("rate", "10000"/*"6480"*/, CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t drate = SCVARF("drate", "100000", CVAR_ARCHIVE | CVAR_USERINFO); // :) -cvar_t noaim = SCVARF("noaim", "", CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t msg = SCVARF("msg", "1", CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t b_switch = SCVARF("b_switch", "", CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t w_switch = SCVARF("w_switch", "", CVAR_ARCHIVE | CVAR_USERINFO); -cvar_t cl_nofake = SCVAR("cl_nofake", "2"); -cvar_t cl_chatsound = SCVAR("cl_chatsound","1"); -cvar_t cl_enemychatsound = SCVAR("cl_enemychatsound", "misc/talk.wav"); -cvar_t cl_teamchatsound = SCVAR("cl_teamchatsound", "misc/talk.wav"); +cvar_t password = CVARF("password", "", CVAR_USERINFO | CVAR_NOUNSAFEEXPAND); //this is parhaps slightly dodgy... +cvar_t spectator = CVARF("spectator", "", CVAR_USERINFO); +cvar_t name = CVARFC("name", "unnamed", CVAR_ARCHIVE | CVAR_USERINFO, Name_Callback); +cvar_t team = CVARF("team", "", CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t skin = CVARF("skin", "", CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t model = CVARF("model", "", CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t topcolor = CVARF("topcolor", "", CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t bottomcolor = CVARF("bottomcolor", "", CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t rate = CVARF("rate", "10000"/*"6480"*/, CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t drate = CVARF("drate", "100000", CVAR_ARCHIVE | CVAR_USERINFO); // :) +cvar_t noaim = CVARF("noaim", "", CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t msg = CVARF("msg", "1", CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t b_switch = CVARF("b_switch", "", CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t w_switch = CVARF("w_switch", "", CVAR_ARCHIVE | CVAR_USERINFO); +cvar_t cl_nofake = CVAR("cl_nofake", "2"); +cvar_t cl_chatsound = CVAR("cl_chatsound","1"); +cvar_t cl_enemychatsound = CVAR("cl_enemychatsound", "misc/talk.wav"); +cvar_t cl_teamchatsound = CVAR("cl_teamchatsound", "misc/talk.wav"); -cvar_t r_torch = SCVARF("r_torch", "0", CVAR_CHEAT); -cvar_t r_rocketlight = SCVARC("r_rocketlight", "1", Cvar_Limiter_ZeroToOne_Callback); -cvar_t r_lightflicker = SCVAR("r_lightflicker", "1"); -cvar_t cl_r2g = SCVAR("cl_r2g", "0"); -cvar_t r_powerupglow = SCVAR("r_powerupglow", "1"); -cvar_t v_powerupshell = SCVAR("v_powerupshell", "0"); -cvar_t cl_gibfilter = SCVAR("cl_gibfilter", "0"); -cvar_t cl_deadbodyfilter = SCVAR("cl_deadbodyfilter", "0"); +cvar_t r_torch = CVARF("r_torch", "0", CVAR_CHEAT); +cvar_t r_rocketlight = CVARC("r_rocketlight", "1", Cvar_Limiter_ZeroToOne_Callback); +cvar_t r_lightflicker = CVAR("r_lightflicker", "1"); +cvar_t cl_r2g = CVAR("cl_r2g", "0"); +cvar_t r_powerupglow = CVAR("r_powerupglow", "1"); +cvar_t v_powerupshell = CVAR("v_powerupshell", "0"); +cvar_t cl_gibfilter = CVAR("cl_gibfilter", "0"); +cvar_t cl_deadbodyfilter = CVAR("cl_deadbodyfilter", "0"); cvar_t cl_gunx = SCVAR("cl_gunx", "0"); cvar_t cl_guny = SCVAR("cl_guny", "0"); @@ -153,7 +153,8 @@ cvar_t cl_parsewhitetext = SCVAR("cl_parsewhitetext", "1"); cvar_t cl_dlemptyterminate = SCVAR("cl_dlemptyterminate", "1"); -cvar_t host_mapname = FCVAR("mapname", "host_mapname", "", 0); +cvar_t host_mapname = CVARAF("mapname", "", + "host_mapname", 0); cvar_t ruleset_allow_playercount = SCVAR("ruleset_allow_playercount", "1"); cvar_t ruleset_allow_frj = SCVAR("ruleset_allow_frj", "1"); @@ -165,7 +166,7 @@ cvar_t ruleset_allow_larger_models = SCVAR("ruleset_allow_larger_models", "1"); cvar_t ruleset_allow_modified_eyes = SCVAR("ruleset_allow_modified_eyes", "0"); cvar_t ruleset_allow_sensative_texture_replacements = SCVAR("ruleset_allow_sensative_texture_replacements", "1"); cvar_t ruleset_allow_localvolume = SCVAR("ruleset_allow_localvolume", "1"); -cvar_t ruleset_allow_shaders = SCVAR("ruleset_allow_shaders", "1"); +cvar_t ruleset_allow_shaders = SCVARF("ruleset_allow_shaders", "1", CVAR_SHADERSYSTEM); extern cvar_t cl_hightrack; extern cvar_t vid_renderer; @@ -181,9 +182,7 @@ client_state_t cl; // alot of this should probably be dynamically allocated entity_state_t *cl_baselines; -efrag_t cl_efrags[MAX_EFRAGS]; -entity_t cl_static_entities[MAX_STATIC_ENTITIES]; -trailstate_t *cl_static_emit[MAX_STATIC_ENTITIES]; +static_entity_t cl_static_entities[MAX_STATIC_ENTITIES]; lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; //lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; dlight_t *cl_dlights; @@ -1053,7 +1052,6 @@ void CL_ClearState (void) r_worldentity.model = NULL; // clear other arrays - memset (cl_efrags, 0, sizeof(cl_efrags)); // memset (cl_dlights, 0, sizeof(cl_dlights)); memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); @@ -1066,14 +1064,6 @@ void CL_ClearState (void) } cl_baselines_count = 0; -// -// allocate the efrags and chain together into a free list -// - cl.free_efrags = cl_efrags; - for (i=0 ; imemsize < MINIMUM_MEMORY) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", parms->memsize / (float)0x100000); + Cvar_Init(); Memory_Init (parms->membase, parms->memsize); Sys_Init(); @@ -3637,7 +3648,8 @@ void Host_FinishInit(void) { //they didn't give us an rc file! Cbuf_AddText ("bind ~ toggleconsole\n", RESTRICT_LOCAL); //we expect default.cfg to not exist. :( Cbuf_AddText ("exec default.cfg\n", RESTRICT_LOCAL); - Cbuf_AddText ("exec config.cfg\n", RESTRICT_LOCAL); + if (COM_FCheckExists ("config.cfg")) + Cbuf_AddText ("exec config.cfg\n", RESTRICT_LOCAL); if (COM_FCheckExists ("q3config.cfg")) Cbuf_AddText ("exec q3config.cfg\n", RESTRICT_LOCAL); Cbuf_AddText ("exec autoexec.cfg\n", RESTRICT_LOCAL); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index cee63854..6acd13f4 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -421,6 +421,7 @@ void CL_DisenqueDownload(char *filename) } } +#ifdef WEBCLIENT void CL_WebDownloadFinished(struct dl_download *dl) { if (dl->status == DL_FAILED) @@ -433,6 +434,7 @@ void CL_WebDownloadFinished(struct dl_download *dl) CL_DownloadFinished(); } } +#endif void CL_SendDownloadStartRequest(char *filename, char *localname) { @@ -446,6 +448,7 @@ void CL_SendDownloadStartRequest(char *filename, char *localname) COM_StripExtension (localname, cls.downloadtempname, sizeof(cls.downloadtempname)-5); strcat (cls.downloadtempname, ".tmp"); +#ifdef WEBCLIENT if (!strncmp(cls.downloadremotename, "http://", 7)) { cls.downloadmethod = DL_HTTP; @@ -454,6 +457,7 @@ void CL_SendDownloadStartRequest(char *filename, char *localname) CL_DownloadFailed(cls.downloadremotename); } else +#endif { CL_SendClientCommand(true, "download %s", filename); @@ -787,10 +791,10 @@ void Model_CheckDownloads (void) // Con_TPrintf (TLC_CHECKINGMODELS); + R_SetSky(cl.skyname); #ifdef Q2CLIENT if (cls.protocol == CP_QUAKE2) { -// R_SetSky(cl.skyname); for (i = 0; i < Q2MAX_IMAGES; i++) { char picname[256]; @@ -845,18 +849,19 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) float giveuptime = Sys_DoubleTime()+0.1; //small things get padded into a single frame #define atstage() ((cl.contentstage == stage++ && !dontactuallyload)?++cl.contentstage:false) -#define endstage() if (giveuptimeDelinkTrailstate (&cl_static_emit[i]); + pe->DelinkTrailstate (&cl_static_entities[i].emit); break; } @@ -3137,9 +3145,9 @@ void CL_ParseStatic (int version) Con_Printf ("Too many static entities"); return; } - ent = &cl_static_entities[i]; + ent = &cl_static_entities[i].ent; memset(ent, 0, sizeof(*ent)); - cl_static_emit[i] = NULL; + cl_static_entities[i].emit = NULL; ent->keynum = es.number; @@ -3171,8 +3179,12 @@ void CL_ParseStatic (int version) Con_TPrintf (TLC_PARSESTATICWITHNOMAP); return; } - - R_AddEfrags (ent); + if (ent->model) + { + VectorAdd(es.origin, ent->model->mins, mins); + VectorAdd(es.origin, ent->model->maxs, maxs); + cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &cl_static_entities[i].pvscache, mins, maxs); + } } /* @@ -4525,9 +4537,9 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n } #endif #ifdef CSQC_DAT - else - if (CSQC_StuffCmd(destsplit, stufftext)) - {} + else if (CSQC_StuffCmd(destsplit, stufftext, msg)) + { + } #endif else { @@ -4666,7 +4678,7 @@ void CL_ParseServerMessage (void) { SHOWNET(svc_strings[cmd]); - destsplit = MSG_ReadByte(); + destsplit = MSG_ReadByte() % MAX_SPLITS; cmd = MSG_ReadByte(); } else @@ -4902,11 +4914,11 @@ void CL_ParseServerMessage (void) break; case svc_killedmonster: - cl.stats[0][STAT_MONSTERS]++; + cl.stats[destsplit][STAT_MONSTERS]++; break; case svc_foundsecret: - cl.stats[0][STAT_SECRETS]++; + cl.stats[destsplit][STAT_SECRETS]++; break; case svc_updatestat: diff --git a/engine/client/cl_plugin.inc b/engine/client/cl_plugin.inc index 632a8493..427d2a87 100644 --- a/engine/client/cl_plugin.inc +++ b/engine/client/cl_plugin.inc @@ -62,22 +62,6 @@ qintptr_t VARGS Plug_SCR_CenterPrint(void *offset, quintptr_t mask, const qintpt SCR_CenterPrint(0, VM_POINTER(arg[0]), true); return 0; } -qintptr_t VARGS Plug_Media_ShowFrameRGBA_32(void *offset, quintptr_t mask, const qintptr_t *arg) -{ - void *src = VM_POINTER(arg[0]); - int srcwidth = VM_LONG(arg[1]); - int srcheight = VM_LONG(arg[2]); -// int x = VM_LONG(arg[3]); -// int y = VM_LONG(arg[4]); -// int width = VM_LONG(arg[5]); -// int height = VM_LONG(arg[6]); - - if (qrenderer == QR_NONE) - return 0; - - Media_ShowFrameRGBA_32(src, srcwidth, srcheight); - return 0; -} @@ -568,7 +552,6 @@ void Plug_Client_Init(void) Plug_RegisterBuiltin("LocalSound", Plug_LocalSound, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("SCR_CenterPrint", Plug_SCR_CenterPrint, PLUG_BIF_NEEDSRENDERER); - Plug_RegisterBuiltin("Media_ShowFrameRGBA_32", Plug_Media_ShowFrameRGBA_32, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER); Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER); diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 1438afb2..27f73033 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -243,14 +243,6 @@ CENTER PRINTING typedef struct { unsigned int flags; -#define CPRINT_BALIGN (1<<0) //B -#define CPRINT_OBITUARTY (1<<1) //O -#define CPRINT_TALIGN (1<<2) //T -#define CPRINT_LALIGN (1<<3) //L -#define CPRINT_RALIGN (1<<4) //R -#define CPRINT_PERSIST (1<<5) //P -#define CPRINT_BACKGROUND (1<<6) //P -#define CPRINT_TYPEWRITER (1<<7) // conchar_t string[1024]; unsigned int charcount; @@ -539,6 +531,24 @@ extern qboolean sb_showscores; } } +void R_DrawTextField(int x, int y, int w, int h, char *text, unsigned int defaultmask, unsigned int fieldflags) +{ + cprint_t p; + vrect_t r; + + r.x = x; + r.y = y; + r.width = w; + r.height = h; + + p.flags = fieldflags; + p.charcount = COM_ParseFunString(defaultmask, text, p.string, sizeof(p.string), false) - p.string; + p.time_off = scr_centertime.value; + p.time_start = cl.time; + + SCR_DrawCenterString(&r, &p); +} + void SCR_DrawCursor(int prydoncursornum) { extern cvar_t cl_cursor, cl_cursorbias, cl_cursorsize; @@ -1488,7 +1498,7 @@ void SCR_DrawLoading (void) unsigned int tsize; qboolean sizeextra; - x = vid.conwidth/2 - 160; + x = vid.width/2 - 160; CL_GetDownloadSizes(&fcount, &tsize, &sizeextra); //downloading files? diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 5bddbe5e..fce595de 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -234,10 +234,10 @@ sfx_t *cl_sfx_ric2; sfx_t *cl_sfx_ric3; sfx_t *cl_sfx_r_exp3; -cvar_t cl_expsprite = SCVAR("cl_expsprite", "0"); -cvar_t r_explosionlight = SCVARC("r_explosionlight", "1", Cvar_Limiter_ZeroToOne_Callback); -cvar_t cl_truelightning = SCVARF("cl_truelightning", "0", CVAR_SEMICHEAT); -cvar_t cl_beam_trace = SCVAR("cl_beam_trace", "0"); +cvar_t cl_expsprite = CVAR("cl_expsprite", "0"); +cvar_t r_explosionlight = CVARC("r_explosionlight", "1", Cvar_Limiter_ZeroToOne_Callback); +cvar_t cl_truelightning = CVARF("cl_truelightning", "0", CVAR_SEMICHEAT); +cvar_t cl_beam_trace = CVAR("cl_beam_trace", "0"); typedef struct { sfx_t **sfx; @@ -1762,7 +1762,7 @@ void CL_Laser (vec3_t start, vec3_t end, int colors) ex->firstframe = 0; ex->numframes = 10; ex->alpha = 0.33f; - ex->model = (void*)0xDEAFF00D; //something not null + ex->model = NULL; ex->skinnum = (colors >> ((rand() % 4)*8)) & 0xff; VectorCopy (start, ex->origin); VectorCopy (end, ex->oldorigin); @@ -1913,7 +1913,7 @@ void CLQ2_ParseTEnt (void) ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explode].modelname, false); ex->firstframe = 0; ex->numframes = 4; - ex->flags = Q2RF_FULLBRIGHT; + ex->flags = Q2RF_FULLBRIGHT|Q2RF_ADDITIVE|RF_NOSHADOW; ex->angles[0] = acos(dir[2])/M_PI*180; // PMM - fixed to correct for pitch of 0 @@ -2240,7 +2240,7 @@ void CLQ2_ParseTEnt (void) ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explode].modelname, false); ex->firstframe = 0; ex->numframes = 4; - ex->flags = Q2RF_FULLBRIGHT; + ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW; ex->angles[0] = acos(dir[2])/M_PI*180; // PMM - fixed to correct for pitch of 0 @@ -2290,7 +2290,7 @@ void CLQ2_ParseTEnt (void) ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explode].modelname, false); ex->firstframe = 0; ex->numframes = 4; - ex->flags = Q2RF_FULLBRIGHT; + ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW; ex->angles[0] = acos(dir[2])/M_PI*180; // PMM - fixed to correct for pitch of 0 @@ -2343,7 +2343,7 @@ void CLQ2_ParseTEnt (void) ex = CL_AllocExplosion (); VectorCopy (pos, ex->origin); // ex->type = ex_poly; - ex->flags = Q2RF_FULLBRIGHT; + ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW; ex->angles[1] = rand() % 360; ex->model = Mod_ForName (q2tentmodels[q2cl_mod_explo4].modelname, false); if (rand() < RAND_MAX/2) @@ -2530,7 +2530,7 @@ void CLQ2_ParseTEnt (void) MSG_ReadPos (pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->origin); - ex->flags = Q2RF_FULLBRIGHT; + ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW; ex->start = cl.q2frame.servertime - 100; CL_NewDlightRGB(0, pos, 350, 0.5, 0.2, 0.1, 0); P_RunParticleEffectTypeString(pos, NULL, 1, "te_muzzleflash"); @@ -2539,7 +2539,7 @@ void CLQ2_ParseTEnt (void) MSG_ReadPos (pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->origin); - ex->flags = Q2RF_FULLBRIGHT; + ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW; ex->start = cl.q2frame.servertime - 100; CL_NewDlightRGB(0, pos, 350, 0.5, 0.2, 0.1, 0); P_RunParticleEffectTypeString(pos, NULL, 1, "te_blue_muzzleflash"); @@ -2548,7 +2548,7 @@ void CLQ2_ParseTEnt (void) MSG_ReadPos (pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->origin); - ex->flags = Q2RF_FULLBRIGHT; + ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW; ex->start = cl.q2frame.servertime - 100; CL_NewDlightRGB(0, pos, 350, 0.5, 0.2, 0, 0.2); P_RunParticleEffectTypeString(pos, NULL, 1, "te_smart_muzzleflash"); @@ -2559,7 +2559,7 @@ void CLQ2_ParseTEnt (void) MSG_ReadPos (pos); ex = CL_AllocExplosion (); VectorCopy (pos, ex->origin); - ex->flags = Q2RF_FULLBRIGHT; + ex->flags = Q2RF_FULLBRIGHT|RF_NOSHADOW; ex->start = cl.q2frame.servertime - 100; CL_NewDlightRGB(0, pos, 350, 0.5, 0.2, 0, 0.2); P_RunParticleEffectTypeString(pos, NULL, 1, "te_deathfield"); @@ -2824,7 +2824,7 @@ void CL_UpdateExplosions (void) for (i=0, ex=cl_explosions; i < explosions_running; i++, ex++) { - if (!ex->model) + if (!ex->model && !ex->flags) continue; lastrunningexplosion = i; @@ -2844,6 +2844,7 @@ void CL_UpdateExplosions (void) if ((int)f >= numframes || (int)f < 0) { ex->model = NULL; + ex->flags = 0; continue; } if (of < 0) diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index d0129892..73c866a8 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -685,7 +685,7 @@ void UI_RegisterFont(char *fontName, int pointSize, fontInfo_t *font) #ifndef _DEBUG static #endif -int UI_SystemCallsEx(void *offset, unsigned int mask, int fn, const int *arg) +int UI_SystemCallsEx(void *offset, quintptr_t mask, int fn, const int *arg) { int ret=0; char adrbuf[MAX_ADR_SIZE]; @@ -1333,21 +1333,21 @@ static int UI_SystemCallsExWrapper(void *offset, unsigned int mask, int fn, cons //I'm not keen on this. //but dlls call it without saying what sort of vm it comes from, so I've got to have them as specifics -static int EXPORT_FN UI_SystemCalls(int arg, ...) +static qintptr_t EXPORT_FN UI_SystemCalls(qintptr_t arg, ...) { - int args[9]; + qintptr_t args[9]; va_list argptr; va_start(argptr, arg); - args[0]=va_arg(argptr, int); - args[1]=va_arg(argptr, int); - args[2]=va_arg(argptr, int); - args[3]=va_arg(argptr, int); - args[4]=va_arg(argptr, int); - args[5]=va_arg(argptr, int); - args[6]=va_arg(argptr, int); - args[7]=va_arg(argptr, int); - args[8]=va_arg(argptr, int); + args[0]=va_arg(argptr, qintptr_t); + args[1]=va_arg(argptr, qintptr_t); + args[2]=va_arg(argptr, qintptr_t); + args[3]=va_arg(argptr, qintptr_t); + args[4]=va_arg(argptr, qintptr_t); + args[5]=va_arg(argptr, qintptr_t); + args[6]=va_arg(argptr, qintptr_t); + args[7]=va_arg(argptr, qintptr_t); + args[8]=va_arg(argptr, qintptr_t); va_end(argptr); return UI_SystemCallsEx(NULL, ~0, arg, args); diff --git a/engine/client/client.h b/engine/client/client.h index 40966e8c..c7a271af 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -270,7 +270,6 @@ typedef struct dlight_s } face [6]; int style; //multiply by style values if > 0 float fov; //spotlight - int refresh; float dist; struct dlight_s *next; } dlight_t; @@ -582,7 +581,6 @@ typedef struct // refresh related state struct model_s *worldmodel; // cl_entitites[0].model - struct efrag_s *free_efrags; int num_entities; // stored bottom up in cl_entities array int num_statics; // stored top down in cl_entitiers @@ -701,11 +699,16 @@ extern cvar_t ruleset_allow_shaders; extern client_state_t cl; +typedef struct +{ + entity_t ent; + trailstate_t *emit; + pvscache_t pvscache; +} static_entity_t; + // FIXME, allocate dynamically extern entity_state_t *cl_baselines; -extern efrag_t cl_efrags[MAX_EFRAGS]; -extern entity_t cl_static_entities[MAX_STATIC_ENTITIES]; -extern trailstate_t *cl_static_emit[MAX_STATIC_ENTITIES]; +extern static_entity_t cl_static_entities[MAX_STATIC_ENTITIES]; extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; extern dlight_t *cl_dlights; extern unsigned int cl_maxdlights; @@ -956,6 +959,7 @@ void CLDP_ParsePointParticles(qboolean compact); // void CL_SetSolidPlayers (int playernum); void CL_SetUpPlayerPrediction(qboolean dopred); +void CL_LinkStaticEntities(void *pvs); void CL_EmitEntities (void); void CL_ClearProjectiles (void); void CL_ParseProjectiles (int modelindex, qboolean nails2); @@ -998,7 +1002,7 @@ qboolean CSQC_Init (unsigned int checksum); void CSQC_RegisterCvarsAndThings(void); qboolean CSQC_DrawView(void); void CSQC_Shutdown(void); -qboolean CSQC_StuffCmd(int lplayernum, char *cmd); +qboolean CSQC_StuffCmd(int lplayernum, char *cmd, char *cmdend); qboolean CSQC_LoadResource(char *resname, char *restype); qboolean CSQC_ParsePrint(char *message, int printlevel); qboolean CSQC_ParseGamePacket(void); @@ -1184,15 +1188,16 @@ int SCR_StringToPalIndex (char *rgbstring, float rgbinputscale); struct model_s; void CL_AddVWeapModel(entity_t *player, struct model_s *model); +/*q2 cinematics*/ +struct cinematics_s; +void CIN_StopCinematic (struct cinematics_s *cin); +struct cinematics_s *CIN_PlayCinematic (char *arg); +int CIN_RunCinematic (struct cinematics_s *cin, qbyte **outdata, int *outwidth, int *outheight, qbyte **outpalette); +/*media playing system*/ qboolean Media_PlayingFullScreen(void); void Media_Init(void); qboolean Media_PlayFilm(char *name); -void CIN_FinishCinematic (void); -qboolean CIN_PlayCinematic (char *arg); -qboolean CIN_DrawCinematic (void); -qboolean CIN_RunCinematic (void); - typedef struct cin_s cin_t; struct cin_s *Media_StartCin(char *name); texid_t Media_UpdateForShader(cin_t *cin); diff --git a/engine/client/clq2_cin.c b/engine/client/clq2_cin.c index 1a00bea7..2bcad4ad 100644 --- a/engine/client/clq2_cin.c +++ b/engine/client/clq2_cin.c @@ -7,7 +7,7 @@ typedef struct int count; } cblock_t; -typedef struct +typedef struct cinematics_s { qboolean restart_sound; int s_rate; @@ -35,66 +35,32 @@ typedef struct int cinematicframe; } cinematics_t; -cinematics_t cin; - - - -void CIN_StopCinematic (void) +void CIN_StopCinematic (cinematics_t *cin) { - Media_PlayFilm(""); - cin.cinematictime = 0; // done - if (cin.pic) + cin->cinematictime = 0; // done + if (cin->pic) { - Z_Free (cin.pic); - cin.pic = NULL; + Z_Free (cin->pic); + cin->pic = NULL; } - if (cin.pic_pending) + if (cin->pic_pending) { - Z_Free (cin.pic_pending); - cin.pic_pending = NULL; + Z_Free (cin->pic_pending); + cin->pic_pending = NULL; } - if (cin.cinematicpalette_active) + if (cin->cinematic_file) { -// re.CinematicSetPalette(NULL); - cin.cinematicpalette_active = false; + VFS_CLOSE (cin->cinematic_file); + cin->cinematic_file = NULL; } - if (cin.cinematic_file) + if (cin->hnodes1) { - VFS_CLOSE (cin.cinematic_file); - cin.cinematic_file = NULL; - } - if (cin.hnodes1) - { - Z_Free (cin.hnodes1); - cin.hnodes1 = NULL; + Z_Free (cin->hnodes1); + cin->hnodes1 = NULL; } - // switch back down to 11 khz sound if necessary - if (cin.restart_sound) - { - cin.restart_sound = false; - S_Restart_f (); - } - -} - -/* -==================== -SCR_FinishCinematic - -Called when either the cinematic completes, or it is aborted -==================== -*/ -void CIN_FinishCinematic (void) -{ - // tell the server to advance to the next map / cinematic (a q2 hack) - if (cls.state == ca_active) - { - CL_SendClientCommand(true, "nextserver %i", cl.servercount); - } - - S_RawAudio(0, NULL, 0, 0, 0, 0); + Z_Free(cin); } //========================================================================== @@ -104,7 +70,7 @@ void CIN_FinishCinematic (void) SmallestNode1 ================== */ -static int SmallestNode1 (int numhnodes) +static int SmallestNode1 (cinematics_t *cin, int numhnodes) { int i; int best, bestnode; @@ -113,13 +79,13 @@ static int SmallestNode1 (int numhnodes) bestnode = -1; for (i=0 ; ih_used[i]) continue; - if (!cin.h_count[i]) + if (!cin->h_count[i]) continue; - if (cin.h_count[i] < best) + if (cin->h_count[i] < best) { - best = cin.h_count[i]; + best = cin->h_count[i]; bestnode = i; } } @@ -127,7 +93,7 @@ static int SmallestNode1 (int numhnodes) if (bestnode == -1) return -1; - cin.h_used[bestnode] = true; + cin->h_used[bestnode] = true; return bestnode; } @@ -139,7 +105,7 @@ Huff1TableInit Reads the 64k counts table and initializes the node trees ================== */ -static void Huff1TableInit (void) +static void Huff1TableInit (cinematics_t *cin) { int prev; int j; @@ -147,41 +113,41 @@ static void Huff1TableInit (void) qbyte counts[256]; int numhnodes; - cin.hnodes1 = Z_Malloc (256*256*2*4); - memset (cin.hnodes1, 0, 256*256*2*4); + cin->hnodes1 = Z_Malloc (256*256*2*4); + memset (cin->hnodes1, 0, 256*256*2*4); for (prev=0 ; prev<256 ; prev++) { - memset (cin.h_count,0,sizeof(cin.h_count)); - memset (cin.h_used,0,sizeof(cin.h_used)); + memset (cin->h_count,0,sizeof(cin->h_count)); + memset (cin->h_used,0,sizeof(cin->h_used)); // read a row of counts - VFS_READ (cin.cinematic_file, counts, sizeof(counts)); + VFS_READ (cin->cinematic_file, counts, sizeof(counts)); for (j=0 ; j<256 ; j++) - cin.h_count[j] = counts[j]; + cin->h_count[j] = counts[j]; // build the nodes numhnodes = 256; - nodebase = cin.hnodes1 + prev*256*2; + nodebase = cin->hnodes1 + prev*256*2; while (numhnodes != 511) { node = nodebase + (numhnodes-256)*2; // pick two lowest counts - node[0] = SmallestNode1 (numhnodes); + node[0] = SmallestNode1 (cin, numhnodes); if (node[0] == -1) break; // no more - node[1] = SmallestNode1 (numhnodes); + node[1] = SmallestNode1 (cin, numhnodes); if (node[1] == -1) break; - cin.h_count[numhnodes] = cin.h_count[node[0]] + cin.h_count[node[1]]; + cin->h_count[numhnodes] = cin->h_count[node[0]] + cin->h_count[node[1]]; numhnodes++; } - cin.numhnodes1[prev] = numhnodes-1; + cin->numhnodes1[prev] = numhnodes-1; } } @@ -190,7 +156,7 @@ static void Huff1TableInit (void) Huff1Decompress ================== */ -static cblock_t Huff1Decompress (cblock_t in) +static cblock_t Huff1Decompress (cinematics_t *cin, cblock_t in) { qbyte *input; qbyte *out_p; @@ -208,10 +174,10 @@ static cblock_t Huff1Decompress (cblock_t in) // read bits - hnodesbase = cin.hnodes1 - 256*2; // nodes 0-255 aren't stored + hnodesbase = cin->hnodes1 - 256*2; // nodes 0-255 aren't stored hnodes = hnodesbase; - nodenum = cin.numhnodes1[0]; + nodenum = cin->numhnodes1[0]; while (count) { inbyte = *input++; @@ -222,7 +188,7 @@ static cblock_t Huff1Decompress (cblock_t in) *out_p++ = nodenum; if (!--count) break; - nodenum = cin.numhnodes1[nodenum]; + nodenum = cin->numhnodes1[nodenum]; } nodenum = hnodes[nodenum*2 + (inbyte&1)]; inbyte >>=1; @@ -233,7 +199,7 @@ static cblock_t Huff1Decompress (cblock_t in) *out_p++ = nodenum; if (!--count) break; - nodenum = cin.numhnodes1[nodenum]; + nodenum = cin->numhnodes1[nodenum]; } nodenum = hnodes[nodenum*2 + (inbyte&1)]; inbyte >>=1; @@ -244,7 +210,7 @@ static cblock_t Huff1Decompress (cblock_t in) *out_p++ = nodenum; if (!--count) break; - nodenum = cin.numhnodes1[nodenum]; + nodenum = cin->numhnodes1[nodenum]; } nodenum = hnodes[nodenum*2 + (inbyte&1)]; inbyte >>=1; @@ -255,7 +221,7 @@ static cblock_t Huff1Decompress (cblock_t in) *out_p++ = nodenum; if (!--count) break; - nodenum = cin.numhnodes1[nodenum]; + nodenum = cin->numhnodes1[nodenum]; } nodenum = hnodes[nodenum*2 + (inbyte&1)]; inbyte >>=1; @@ -266,7 +232,7 @@ static cblock_t Huff1Decompress (cblock_t in) *out_p++ = nodenum; if (!--count) break; - nodenum = cin.numhnodes1[nodenum]; + nodenum = cin->numhnodes1[nodenum]; } nodenum = hnodes[nodenum*2 + (inbyte&1)]; inbyte >>=1; @@ -277,7 +243,7 @@ static cblock_t Huff1Decompress (cblock_t in) *out_p++ = nodenum; if (!--count) break; - nodenum = cin.numhnodes1[nodenum]; + nodenum = cin->numhnodes1[nodenum]; } nodenum = hnodes[nodenum*2 + (inbyte&1)]; inbyte >>=1; @@ -288,7 +254,7 @@ static cblock_t Huff1Decompress (cblock_t in) *out_p++ = nodenum; if (!--count) break; - nodenum = cin.numhnodes1[nodenum]; + nodenum = cin->numhnodes1[nodenum]; } nodenum = hnodes[nodenum*2 + (inbyte&1)]; inbyte >>=1; @@ -299,7 +265,7 @@ static cblock_t Huff1Decompress (cblock_t in) *out_p++ = nodenum; if (!--count) break; - nodenum = cin.numhnodes1[nodenum]; + nodenum = cin->numhnodes1[nodenum]; } nodenum = hnodes[nodenum*2 + (inbyte&1)]; inbyte >>=1; @@ -319,7 +285,7 @@ static cblock_t Huff1Decompress (cblock_t in) SCR_ReadNextFrame ================== */ -qbyte *CIN_ReadNextFrame (void) +qbyte *CIN_ReadNextFrame (cinematics_t *cin) { int r; int command; @@ -331,9 +297,9 @@ qbyte *CIN_ReadNextFrame (void) int start, end, count; // read the next frame - r = VFS_READ (cin.cinematic_file, &command, 4); + r = VFS_READ (cin->cinematic_file, &command, 4); if (r == 0) // we'll give it one more chance - r = VFS_READ (cin.cinematic_file, &command, 4); + r = VFS_READ (cin->cinematic_file, &command, 4); if (r != 4) return NULL; @@ -343,39 +309,38 @@ qbyte *CIN_ReadNextFrame (void) if (command == 1) { // read palette - VFS_READ (cin.cinematic_file, cin.cinematicpalette, sizeof(cin.cinematicpalette)); - cin.cinematicpalette_active=0; // dubious.... exposes an edge case + VFS_READ (cin->cinematic_file, cin->cinematicpalette, sizeof(cin->cinematicpalette)); } // decompress the next frame - VFS_READ (cin.cinematic_file, &size, 4); + VFS_READ (cin->cinematic_file, &size, 4); size = LittleLong(size); if (size > sizeof(compressed) || size < 1) Host_Error ("Bad compressed frame size"); - VFS_READ (cin.cinematic_file, compressed, size); + VFS_READ (cin->cinematic_file, compressed, size); // read sound - start = cin.cinematicframe*cin.s_rate/14; - end = (cin.cinematicframe+1)*cin.s_rate/14; + start = cin->cinematicframe*cin->s_rate/14; + end = (cin->cinematicframe+1)*cin->s_rate/14; count = end - start; - VFS_READ (cin.cinematic_file, samples, count*cin.s_width*cin.s_channels); + VFS_READ (cin->cinematic_file, samples, count*cin->s_width*cin->s_channels); - if (cin.s_width == 1) - COM_CharBias(samples, count*cin.s_channels); - else if (cin.s_width == 2) - COM_SwapLittleShortBlock((short *)samples, count*cin.s_channels); + if (cin->s_width == 1) + COM_CharBias(samples, count*cin->s_channels); + else if (cin->s_width == 2) + COM_SwapLittleShortBlock((short *)samples, count*cin->s_channels); - S_RawAudio (0, samples, cin.s_rate, count, cin.s_channels, cin.s_width); + S_RawAudio (0, samples, cin->s_rate, count, cin->s_channels, cin->s_width); in.data = compressed; in.count = size; - huf1 = Huff1Decompress (in); + huf1 = Huff1Decompress (cin, in); pic = huf1.data; - cin.cinematicframe++; + cin->cinematicframe++; return pic; } @@ -385,52 +350,51 @@ qbyte *CIN_ReadNextFrame (void) ================== SCR_RunCinematic +0 = error +1 = success +2 = success but nothing changed ================== */ -qboolean CIN_DrawCinematic (void); -qboolean CIN_RunCinematic (void) +int CIN_RunCinematic (cinematics_t *cin, qbyte **outdata, int *outwidth, int *outheight, qbyte **outpalette) { int frame; - if (cin.cinematictime <= 0) + if (cin->cinematictime <= 0) { - CIN_StopCinematic (); - return false; + cin->cinematictime = realtime; + cin->cinematicframe = -1; } - if (cin.cinematictime-3 > realtime*1000) - cin.cinematictime = realtime*1000; + if (cin->cinematictime-3 > realtime*1000) + cin->cinematictime = realtime*1000; -/* if (key_dest != key_game) - { // pause if menu or console is up - cin.cinematictime = realtime - cin.cinematicframe*1000/14; - return true; - }*/ - - frame = (realtime*1000 - cin.cinematictime)*14/1000; - if (frame <= cin.cinematicframe) - return true; - if (frame > cin.cinematicframe+1) + frame = (realtime*1000 - cin->cinematictime)*14/1000; + if (frame <= cin->cinematicframe) { - Con_Printf ("Dropped frame: %i > %i\n", frame, cin.cinematicframe+1); - cin.cinematictime = realtime*1000 - cin.cinematicframe*1000/14; + *outdata = cin->pic; + *outwidth = cin->width; + *outheight = cin->height; + *outpalette = cin->cinematicpalette; + return 2; } - if (cin.pic) - Z_Free (cin.pic); - cin.pic = cin.pic_pending; - cin.pic_pending = NULL; - cin.pic_pending = CIN_ReadNextFrame (); - if (!cin.pic_pending) + if (frame > cin->cinematicframe+1) { - CIN_StopCinematic (); - CIN_FinishCinematic (); - cin.cinematictime = 1; // hack to get the black screen behind loading - SCR_BeginLoadingPlaque (); - cin.cinematictime = 0; - return false; + Con_Printf ("Dropped frame: %i > %i\n", frame, cin->cinematicframe+1); + cin->cinematictime = realtime*1000 - cin->cinematicframe*1000/14; + } + if (cin->pic) + Z_Free (cin->pic); + cin->pic = CIN_ReadNextFrame (cin); + if (!cin->pic) + { + return 0; } - return true; + *outdata = cin->pic; + *outwidth = cin->width; + *outheight = cin->height; + *outpalette = cin->cinematicpalette; + return 1; } /* @@ -441,9 +405,10 @@ Returns true if a cinematic is active, meaning the view rendering should be skipped ================== */ +/* qboolean CIN_DrawCinematic (void) { - if (cin.cinematictime <= 0) + if (cin->cinematictime <= 0) { return false; } @@ -472,6 +437,7 @@ qboolean CIN_DrawCinematic (void) return true; } +*/ /* ================== @@ -479,67 +445,54 @@ SCR_PlayCinematic ================== */ -qboolean CIN_PlayCinematic (char *arg) +cinematics_t *CIN_PlayCinematic (char *arg) { int width, height; char name[MAX_OSPATH]; // int old_khz; + vfsfile_t *file; - // make sure CD isn't playing music - CDAudio_Stop(); + cinematics_t *cin = NULL; - cin.cinematicframe = 0; + file = FS_OpenVFS(arg, "rb", FS_GAME); - cin.cinematic_file = FS_OpenVFS(arg, "rb", FS_GAME); - - if (!cin.cinematic_file) + if (!file) { snprintf (name, sizeof(name), "video/%s", arg); - cin.cinematic_file = FS_OpenVFS(name, "rb", FS_GAME); + file = FS_OpenVFS(name, "rb", FS_GAME); } - if (!cin.cinematic_file) + if (file) + cin = Z_Malloc(sizeof(*cin)); + if (cin) { -// Com_Error (ERR_DROP, "Cinematic %s not found.\n", name); + cin->cinematicframe = 0; + cin->cinematic_file = file; - CIN_FinishCinematic (); + VFS_READ (cin->cinematic_file, &width, 4); + VFS_READ (cin->cinematic_file, &height, 4); + cin->width = LittleLong(width); + cin->height = LittleLong(height); - cin.cinematictime = 0; // done + VFS_READ (cin->cinematic_file, &cin->s_rate, 4); + cin->s_rate = LittleLong(cin->s_rate); + VFS_READ (cin->cinematic_file, &cin->s_width, 4); + cin->s_width = LittleLong(cin->s_width); + VFS_READ (cin->cinematic_file, &cin->s_channels, 4); + cin->s_channels = LittleLong(cin->s_channels); + + Huff1TableInit (cin); + + cin->cinematicframe = 0; + cin->pic = CIN_ReadNextFrame (cin); + cin->cinematictime = Sys_DoubleTime ()*1000+0.001; + } + else + { + cin->cinematictime = 0; // done Con_Printf(CON_WARNING "Cinematic %s not found.\n", name); - return true; } - - SCR_EndLoadingPlaque (); - - VFS_READ (cin.cinematic_file, &width, 4); - VFS_READ (cin.cinematic_file, &height, 4); - cin.width = LittleLong(width); - cin.height = LittleLong(height); - - VFS_READ (cin.cinematic_file, &cin.s_rate, 4); - cin.s_rate = LittleLong(cin.s_rate); - VFS_READ (cin.cinematic_file, &cin.s_width, 4); - cin.s_width = LittleLong(cin.s_width); - VFS_READ (cin.cinematic_file, &cin.s_channels, 4); - cin.s_channels = LittleLong(cin.s_channels); - - Huff1TableInit (); - - // switch up to 22 khz sound if necessary - /*old_khz = Cvar_VariableValue ("snd_khz"); - if (old_khz != cin.s_rate/1000) - { - cin.restart_sound = true; - Cvar_SetValue ("snd_khz", cin.s_rate/1000); - S_Restart_f (); - Cvar_SetValue ("snd_khz", old_khz); - }*/ - - cin.cinematicframe = 0; - cin.pic = CIN_ReadNextFrame (); - cin.cinematictime = Sys_DoubleTime ()*1000+0.001; - - return true; + return cin; } #endif diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index 3e44844b..ad7f5932 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -880,7 +880,8 @@ void CLQ3_SendCmd(usercmd_t *cmd) CLQ3_SendClientCommand("userinfo \"%s\"", cls.userinfo); } - cl.gametime = ccs.serverTime = ccs.snap.serverTime + (Sys_Milliseconds()-ccs.snap.localTime); + ccs.serverTime = ccs.snap.serverTime + (Sys_Milliseconds()-ccs.snap.localTime); + cl.servertime = ccs.serverTime / 1000.0f; //reuse the q1 array cmd->servertime = ccs.serverTime; diff --git a/engine/client/console.c b/engine/client/console.c index b56676e5..b2455437 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -569,23 +569,6 @@ void Con_PrintCon (console_t *con, char *txt) cr = true; break; case '\n': - -#pragma message("Really inefficient consistancy checking, with no side effects other than sys_errors") -{ -conline_t *cl; -cl = con->oldest; -if (cl->older) -Sys_Error("older?\n"); -while(cl->newer) -{ - if (cl->newer->older != cl) - Sys_Error("bad backlink\n"); -cl = cl->newer; -} -if (cl != con->current) -Sys_Error("not newest?\n"); -} - cr = false; while (con->linecount >= con_maxlines.value) { @@ -1416,7 +1399,13 @@ void Con_DrawConsole (int lines, qboolean noback) if (!haveprogress && lines == vid.height) { - char *version = va(DISTRIBUTION " Quake %i", build_number()); +#ifdef SVNREVISION + #define STRINGIFY2(arg) #arg + #define STRINGIFY(arg) STRINGIFY2(arg) + char *version = va(DISTRIBUTION " Quake B%i" IFMINIMAL("m","") " (R%s)\n", build_number(), STRINGIFY(SVNREVISION)); +#else + char *version = va(DISTRIBUTION " Quake %i" IFMINIMAL("m",""), build_number()); +#endif int i; Font_BeginString(font_conchar, vid.width, lines, &x, &y); y -= Font_CharHeight(); diff --git a/engine/client/keys.c b/engine/client/keys.c index 341725c6..88998f6e 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -57,8 +57,8 @@ qboolean deltaused[K_MAX][KEY_MODIFIERSTATES]; void Con_Selectioncolour_Callback(struct cvar_s *var, char *oldvalue); extern cvar_t con_displaypossibilities; -cvar_t con_selectioncolour = SCVARFC("con_selectioncolour", "0", CVAR_RENDERERCALLBACK, Con_Selectioncolour_Callback); -cvar_t con_echochat = SCVAR("con_echochat", "0"); +cvar_t con_selectioncolour = CVARFC("con_selectioncolour", "0", CVAR_RENDERERCALLBACK, Con_Selectioncolour_Callback); +cvar_t con_echochat = CVAR("con_echochat", "0"); extern cvar_t cl_chatmode; static int KeyModifier (qboolean shift, qboolean alt, qboolean ctrl) diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 8fefb866..a00a8c40 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -205,7 +205,7 @@ void MenuTooltipSplit(menu_t *menu, const char *text) return; // calc a line maximum, use a third of the screen or 30 characters, whichever is bigger - lnmax = (vid.width / 24) - 2; + lnmax = (vid.width / 24) - 2; if (lnmax < 30) lnmax = 30; // word wrap @@ -329,12 +329,18 @@ qboolean MI_Selectable(menuoption_t *op) void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) { int i; - mpic_t *p; + mpic_t *p; + + int mgt; + + mgt = M_GameType(); + while (option) { if (mousemoved && !bindingactive) { if (omousex > xpos+option->common.posx && omousex < xpos+option->common.posx+option->common.width) + { if (omousey > ypos+option->common.posy && omousey < ypos+option->common.posy+option->common.height) { if (MI_Selectable(option)) @@ -342,7 +348,13 @@ void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) if (menu->selecteditem != option) { if (!option->common.noselectionsound) - S_LocalSound ("misc/menu1.wav"); + { + if (mgt == MGT_HEXEN2) + S_LocalSound ("raven/menu1.wav"); + else + S_LocalSound ("misc/menu1.wav"); + } + menu->selecteditem = option; menu->tooltiptime = realtime + 1; MenuTooltipSplit(menu, menu->selecteditem->common.tooltip); @@ -351,6 +363,7 @@ void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) menu->cursoritem->common.posy = menu->selecteditem->common.posy; } } + } } if (!option->common.ishidden) switch(option->common.type) @@ -396,7 +409,7 @@ void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) if (!p) p = Draw_SafeCachePic(option->picture.picturename); - Draw_ScalePic(xpos+option->common.posx, ypos+option->common.posy, option->common.width, option->common.height, p); + Draw_ScalePic(xpos+option->common.posx, ypos+option->common.posy, option->common.width?option->common.width:p->width, option->common.height?option->common.height:p->height, p); break; case mt_picture: p = Draw_SafeCachePic(option->picture.picturename); @@ -524,9 +537,9 @@ void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu) x += strlen(option->bind.caption)*8+28; { l = strlen (option->bind.command); - + M_FindKeysForCommand (option->bind.command, keys); - + if (bindingactive && menu->selecteditem == option) { Draw_FunString (x, y, "Press key"); @@ -625,7 +638,7 @@ menutext_t *MC_AddWhiteText(menu_t *menu, int x, int y, const char *text, qboole { menutext_t *n = Z_Malloc(sizeof(menutext_t)); n->common.type = mt_text; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->text = text; @@ -642,7 +655,7 @@ menutext_t *MC_AddBufferedText(menu_t *menu, int x, int y, const char *text, qbo { menutext_t *n = Z_Malloc(sizeof(menutext_t) + strlen(text)+1); n->common.type = mt_text; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->text = (char *)(n+1); @@ -669,7 +682,7 @@ menubind_t *MC_AddBind(menu_t *menu, int x, int y, const char *caption, char *co { 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.iszone = true; n->common.posx = x; n->common.posy = y; n->caption = (char *)(n+1); @@ -800,7 +813,7 @@ menuedit_t *MC_AddEdit(menu_t *menu, int x, int y, char *text, char *def) { menuedit_t *n = Z_Malloc(sizeof(menuedit_t)); n->common.type = mt_edit; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->modified = true; @@ -818,11 +831,12 @@ menuedit_t *MC_AddEditCvar(menu_t *menu, int x, int y, char *text, char *name) cvar_t *cvar; cvar = Cvar_Get(name, "", CVAR_USERCREATED|CVAR_ARCHIVE, NULL); //well, this is a menu/ n->common.type = mt_edit; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->common.width = (strlen(text)+17)*8; n->common.height = 8; + n->common.tooltip = cvar->description; n->modified = true; n->caption = (char *)(n+1); strcpy((char *)(n+1), text); @@ -869,19 +883,24 @@ menucheck_t *MC_AddCheckBox(menu_t *menu, int x, int y, const char *text, cvar_t { menucheck_t *n = Z_Malloc(sizeof(menucheck_t)+strlen(text)+1); n->common.type = mt_checkbox; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->common.height = 8; n->common.width = (strlen(text)+7)*8; + n->common.tooltip = var?var->description:NULL; n->text = (char *)(n+1); strcpy((char *)(n+1), text); n->var = var; n->bits = bits; + #ifdef _DEBUG if (var) if (!(var->flags & CVAR_ARCHIVE)) Con_Printf("Warning: %s is not set for archiving\n", var->name); + else if (var->flags & CVAR_RENDERERLATCH) + Con_Printf("Warning: %s requires a vid_restart\n", var->name); + #endif n->common.next = menu->options; menu->options = (menuoption_t *)n; @@ -891,7 +910,7 @@ menucheck_t *MC_AddCheckBoxFunc(menu_t *menu, int x, int y, const char *text, qb { menucheck_t *n = Z_Malloc(sizeof(menucheck_t)+strlen(text)+1); n->common.type = mt_checkbox; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->common.height = 8; @@ -908,14 +927,15 @@ 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 *n = Z_Malloc(sizeof(menuslider_t)+strlen(text)+1); n->common.type = mt_slider; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->common.height = 8; n->common.width = (strlen(text)+SLIDER_RANGE+5)*8; + n->common.tooltip = var->description; n->var = var; n->text = (char *)(n+1); strcpy((char *)(n+1), text); @@ -924,8 +944,10 @@ menuslider_t *MC_AddSlider(menu_t *menu, int x, int y, const char *text, cvar_t { n->current = var->value; +#ifdef _DEBUG if (!(var->flags & CVAR_ARCHIVE)) Con_Printf("Warning: %s is not set for archiving\n", var->name); +#endif } n->min = min; @@ -962,15 +984,15 @@ menucombo_t *MC_AddCombo(menu_t *menu, int x, int y, const char *caption, const optbufsize += optlen+1+sizeof(char*); numopts++; } - - + + n = Z_Malloc(sizeof(*n) + optbufsize); newops = (char **)(n+1); optbuf = (char*)(newops + numopts+1); n->common.type = mt_combo; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; - n->common.posy = y; + n->common.posy = y; n->common.height = 8; n->common.width = strlen(caption)*8 + maxoptlen*8; n->caption = caption; @@ -988,7 +1010,7 @@ menucombo_t *MC_AddCombo(menu_t *menu, int x, int y, const char *caption, const } newops[i] = NULL; - if (initialvalue >= n->numoptions) + if (initialvalue >= n->numoptions) { Con_Printf("WARNING: Fixed initialvalue for %s\n", caption); initialvalue = n->numoptions-1; @@ -1022,19 +1044,20 @@ menucombo_t *MC_AddCvarCombo(menu_t *menu, int x, int y, const char *caption, cv optbufsize += strlen(values[numopts])+1+sizeof(char*); numopts++; } - - + + n = Z_Malloc(sizeof(*n) + optbufsize); newops = (char **)(n+1); newvalues = (char**)(newops + numopts+1); optbuf = (char*)(newvalues + numopts+1); n->common.type = mt_combo; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; - n->common.posy = y; + n->common.posy = y; n->common.height = 8; n->common.width = strlen(caption)*8 + maxoptlen*8; + n->common.tooltip = cvar->description; strcpy(optbuf, caption); n->caption = optbuf; @@ -1076,7 +1099,7 @@ menubutton_t *MC_AddConsoleCommand(menu_t *menu, int x, int y, const char *text, { menubutton_t *n = Z_Malloc(sizeof(menubutton_t)+strlen(text)+1+strlen(command)+1); n->common.type = mt_button; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->common.height = 8; @@ -1095,7 +1118,7 @@ menubutton_t *MC_AddConsoleCommandQBigFont(menu_t *menu, int x, int y, const cha { menubutton_t *n = Z_Malloc(sizeof(menubutton_t)+strlen(text)+1+strlen(command)+1); n->common.type = mt_qbuttonbigfont; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->common.height = 20; @@ -1113,7 +1136,7 @@ menubutton_t *MC_AddConsoleCommandHexen2BigFont(menu_t *menu, int x, int y, cons { menubutton_t *n = Z_Malloc(sizeof(menubutton_t)+strlen(text)+1+strlen(command)+1); n->common.type = mt_hexen2buttonbigfont; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->common.height = 8; @@ -1132,7 +1155,7 @@ menubutton_t *MC_AddCommand(menu_t *menu, int x, int y, char *text, qboolean (*c { menubutton_t *n = Z_Malloc(sizeof(menubutton_t)); n->common.type = mt_button; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; n->text = text; @@ -1151,17 +1174,17 @@ menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int x, int y, const char va_list argptr; static char string[1024]; menubutton_t *n; - + va_start (argptr, command); vsnprintf (string,sizeof(string)-1, command,argptr); - va_end (argptr); + va_end (argptr); n = Z_Malloc(sizeof(menubutton_t) + strlen(string)+1); n->common.type = mt_button; - n->common.iszone = true; + n->common.iszone = true; n->common.posx = x; n->common.posy = y; - n->text = text; + n->text = text; n->command = (char *)(n+1); strcpy((char *)(n+1), string); @@ -1368,7 +1391,7 @@ void M_HideMenu (menu_t *menu) } } void M_RemoveMenu (menu_t *menu) -{ +{ menuoption_t *op, *oop; if (menu->remove) menu->remove(menu); @@ -1499,7 +1522,7 @@ menuoption_t *M_NextSelectableItem(menu_t *m, menuoption_t *old) if (!old) old = M_NextItem(m, old); - + op = old; while (1) @@ -1526,11 +1549,11 @@ menuoption_t *M_NextSelectableItem(menu_t *m, menuoption_t *old) menuoption_t *M_PrevSelectableItem(menu_t *m, menuoption_t *old) { - menuoption_t *op; + menuoption_t *op; if (!old) old = currentmenu->options; - + op = old; while (1) @@ -1553,9 +1576,12 @@ menuoption_t *M_PrevSelectableItem(menu_t *m, menuoption_t *old) void M_Complex_Key(int key, int unicode) { + int mgt; + mgt = M_GameType(); + if (!currentmenu) return; //erm... - + if (currentmenu->key) if (currentmenu->key(key, currentmenu)) return; @@ -1569,7 +1595,10 @@ void M_Complex_Key(int key, int unicode) { if (bindingactive) { - S_LocalSound ("misc/menu1.wav"); + if (mgt == MGT_HEXEN2) + S_LocalSound ("raven/menu1.wav"); + else + S_LocalSound ("misc/menu1.wav"); if (key != K_ESCAPE && key != '`') { @@ -1579,22 +1608,29 @@ void M_Complex_Key(int key, int unicode) return; } } - + switch(key) { case K_MOUSE2: case K_ESCAPE: //remove M_RemoveMenu(currentmenu); - S_LocalSound ("misc/menu3.wav"); + if (mgt == MGT_HEXEN2) + S_LocalSound ("raven/menu3.wav"); + else + S_LocalSound ("misc/menu3.wav"); break; case K_TAB: case K_DOWNARROW: currentmenu->selecteditem = M_NextSelectableItem(currentmenu, currentmenu->selecteditem); - if (currentmenu->selecteditem) + if (currentmenu->selecteditem) { - S_LocalSound ("misc/menu1.wav"); + if (mgt == MGT_HEXEN2) + S_LocalSound ("raven/menu1.wav"); + else + S_LocalSound ("misc/menu1.wav"); + if (currentmenu->cursoritem) currentmenu->cursoritem->common.posy = currentmenu->selecteditem->common.posy; } @@ -1602,9 +1638,13 @@ void M_Complex_Key(int key, int unicode) case K_UPARROW: currentmenu->selecteditem = M_PrevSelectableItem(currentmenu, currentmenu->selecteditem); - if (currentmenu->selecteditem) + if (currentmenu->selecteditem) { - S_LocalSound ("misc/menu1.wav"); + if (mgt == MGT_HEXEN2) + S_LocalSound ("raven/menu1.wav"); + else + S_LocalSound ("misc/menu1.wav"); + if (currentmenu->cursoritem) currentmenu->cursoritem->common.posy = currentmenu->selecteditem->common.posy; } @@ -1632,7 +1672,10 @@ void M_Complex_Key(int key, int unicode) else if (key == K_ENTER || key == K_MOUSE1) { Cbuf_AddText(currentmenu->selecteditem->button.command, RESTRICT_LOCAL); - S_LocalSound ("misc/menu2.wav"); + if (mgt == MGT_HEXEN2) + S_LocalSound ("raven/menu2.wav"); + else + S_LocalSound ("misc/menu2.wav"); } break; case mt_custom: @@ -1675,7 +1718,7 @@ qboolean MC_GuiKey(int key, menu_t *menu) guiinfo_t *info = (guiinfo_t *)menu->data; switch(key) { - case K_ESCAPE: + case K_ESCAPE: if (info->dropout) MC_GuiKey(key, info->dropout); else @@ -1715,7 +1758,7 @@ qboolean MC_GuiKey(int key, menu_t *menu) gui->text[1] = "Hello again"; gui->text[2] = "Hello yet again"; for (y = 0, i = 0; gui->text[i]; i++, y+=1*8) - { + { info->op[i] = MC_AddRedText(info->dropout, 0, y, gui->text[i], false); } } @@ -1798,7 +1841,7 @@ void M_Menu_Main_f (void) mainm = M_CreateMenu(sizeof(guiinfo_t)); mainm->key = MC_GuiKey; mainm->xpos=0; - gui = (guiinfo_t *)mainm->data; + gui = (guiinfo_t *)mainm->data; gui->text[0] = "Single"; gui->text[1] = "Multiplayer"; gui->text[2] = "Quit"; @@ -1806,7 +1849,7 @@ void M_Menu_Main_f (void) { gui->op[i] = MC_AddRedText(mainm, x, 0, gui->text[i], false); x+=(strlen(gui->text[i])+1)*8; - } + } return; } */ @@ -1817,12 +1860,12 @@ void M_Menu_Main_f (void) if (mgt == MGT_QUAKE2) //quake2 main menu. { if (Draw_SafeCachePic("pics/m_main_game")) - { + { m_state = m_complex; key_dest = key_menu; - mainm = M_CreateMenu(0); - mainm->key = MC_Main_Key; + mainm = M_CreateMenu(0); + mainm->key = MC_Main_Key; MC_AddPicture(mainm, 0, 4, 38, 166, "pics/m_main_plaque"); p = Draw_SafeCachePic("pics/m_main_logo"); @@ -1867,8 +1910,8 @@ void M_Menu_Main_f (void) { m_state = m_complex; key_dest = key_menu; - mainm = M_CreateMenu(0); - mainm->key = MC_Main_Key; + mainm = M_CreateMenu(0); + mainm->key = MC_Main_Key; MC_AddPicture(mainm, 16, 0, 35, 176, "gfx/menu/hplaque.lmp"); p = Draw_SafeCachePic("gfx/menu/title0.lmp"); @@ -1901,7 +1944,7 @@ void M_Menu_Main_f (void) { m_state = m_complex; key_dest = key_menu; - mainm = M_CreateMenu(0); + mainm = M_CreateMenu(0); p = Draw_SafeCachePic("gfx/ttl_main.lmp"); if (!p) @@ -1935,7 +1978,7 @@ void M_Menu_Main_f (void) { m_state = m_complex; key_dest = key_menu; - mainm = M_CreateMenu(0); + mainm = M_CreateMenu(0); p = Draw_SafeCachePic("gfx/ttl_main.lmp"); if (!p) diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index efd617b2..943873b8 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -801,12 +801,14 @@ struct cin_s { qbyte *outdata; qbyte *outpalette; int outunchanged; + qboolean ended; texid_t texture; qboolean (*decodeframe)(cin_t *cin, qboolean nosound); void (*doneframe)(cin_t *cin); - void (*shutdown)(cin_t *cin); //warning: don't free cin_t + void (*shutdown)(cin_t *cin); //warning: doesn't free cin_t + void (*rewind)(cin_t *cin); //these are any interactivity functions you might want... void (*cursormove) (struct cin_s *cin, float posx, float posy); //pos is 0-1 void (*key) (struct cin_s *cin, int code, int unicode, int event); @@ -856,6 +858,10 @@ struct cin_s { roq_info *roqfilm; } roq; + struct { + struct cinematics_s *cin; + } q2cin; + float filmstarttime; float nextframetime; float filmlasttime; @@ -864,7 +870,7 @@ struct cin_s { qbyte *framedata; //Z_Malloced buffer }; -cin_t *fullscreenvid; +shader_t *videoshader; ////////////////////////////////////////////////////////////////////////////////// //AVI Support (windows) @@ -1159,6 +1165,7 @@ qboolean Media_Roq_DecodeFrame (cin_t *cin, qboolean nosound) } else { + cin->ended = true; cin->roq.roqfilm->frame_num = 0; cin->roq.roqfilm->aud_pos = cin->roq.roqfilm->roq_start; cin->roq.roqfilm->vid_pos = cin->roq.roqfilm->roq_start; @@ -1275,33 +1282,44 @@ cin_t *Media_Static_TryLoad(char *name) #ifdef Q2CLIENT void Media_Cin_Shutdown(struct cin_s *cin) { - CIN_FinishCinematic(); + CIN_StopCinematic(cin->q2cin.cin); } qboolean Media_Cin_DecodeFrame(cin_t *cin, qboolean nosound) { - //FIXME! - if (CIN_RunCinematic()) + cin->outunchanged = cin->outdata!=NULL; + switch (CIN_RunCinematic(cin->q2cin.cin, &cin->outdata, &cin->outwidth, &cin->outheight, &cin->outpalette)) { - CIN_DrawCinematic(); - return true; + default: + case 0: + cin->ended = true; + return cin->outdata!=NULL; + case 1: + cin->outunchanged = false; + return cin->outdata!=NULL; + case 2: + return cin->outdata!=NULL; } - return false; } cin_t *Media_Cin_TryLoad(char *name) { + struct cinematics_s *q2cin; cin_t *cin; char *dot = strrchr(name, '.'); if (dot && (!strcmp(dot, ".cin"))) { - if (CIN_PlayCinematic(name)) + q2cin = CIN_PlayCinematic(name); + if (q2cin) { cin = Z_Malloc(sizeof(cin_t)); + cin->q2cin.cin = q2cin; cin->filmtype = MFT_CIN; cin->decodeframe = Media_Cin_DecodeFrame; cin->shutdown = Media_Cin_Shutdown; + + cin->outtype = TF_8PAL24; return cin; } } @@ -1598,7 +1616,7 @@ cin_t *Media_Gecko_TryLoad(char *name) qboolean Media_PlayingFullScreen(void) { - return fullscreenvid!=NULL; + return videoshader!=NULL; } void Media_ShutdownCin(cin_t *cin) @@ -1659,11 +1677,46 @@ qboolean Media_DecodeFrame(cin_t *cin, qboolean nosound) qboolean Media_PlayFilm(char *name) { - Media_ShutdownCin(fullscreenvid); - fullscreenvid = Media_StartCin(name); + cin_t *cin; + static char sname[MAX_QPATH]; - if (fullscreenvid) + if (videoshader) { + R_UnloadShader(videoshader); + videoshader = NULL; + } + + if (!*name) + { + if (cls.state == ca_active) + { + CL_SendClientCommand(true, "nextserver %i", cl.servercount); + } + S_RawAudio(0, NULL, 0, 0, 0, 0); + videoshader = NULL; + } + else + { + snprintf(sname, sizeof(sname), "cinematic/%s", name); + videoshader = R_RegisterCustom(sname, Shader_DefaultCinematic, sname+10); + + cin = R_ShaderGetCinematic(videoshader); + if (cin) + { + cin->ended = false; + if (cin->rewind) + cin->rewind(cin); + } + } + +// Media_ShutdownCin(fullscreenvid); +// fullscreenvid = Media_StartCin(name); + + if (videoshader) + { + CDAudio_Stop(); + SCR_EndLoadingPlaque(); + Con_ClearNotify(); if (key_dest == key_menu) { @@ -1679,39 +1732,23 @@ qboolean Media_PlayFilm(char *name) } qboolean Media_ShowFilm(void) { - if (!fullscreenvid) - return false; - if (!Media_DecodeFrame(fullscreenvid, false)) + if (videoshader) { - Media_ShutdownCin(fullscreenvid); - fullscreenvid = NULL; - return false; + cin_t *cin = R_ShaderGetCinematic(videoshader); + if (cin && cin->ended) + Media_PlayFilm(""); + else + { + Draw_ImageColours(1, 1, 1, 1); + Draw_ScalePic(0, 0, vid.width, vid.height, videoshader); + + SCR_SetUpToDrawConsole(); + if (scr_con_current) + SCR_DrawConsole (false); + return true; + } } - - switch(fullscreenvid->outtype) - { - case TF_RGBA32: - if (Media_ShowFrameRGBA_32) - Media_ShowFrameRGBA_32(fullscreenvid->outdata, fullscreenvid->outwidth, fullscreenvid->outheight); - break; - case TF_TRANS8: - case TF_SOLID8: - Media_ShowFrame8bit(fullscreenvid->outdata, fullscreenvid->outwidth, fullscreenvid->outheight, fullscreenvid->outpalette); - break; - case TF_BGR24_FLIP: - Media_ShowFrameBGR_24_Flip(fullscreenvid->outdata, fullscreenvid->outwidth, fullscreenvid->outheight); - break; - case TF_BGRA32: -#pragma message("Media_ShowFilm: BGRA comes out as RGBA") -// Media_ShowFrameBGRA_32 - Media_ShowFrameRGBA_32(fullscreenvid->outdata, fullscreenvid->outwidth, fullscreenvid->outheight); - break; - } - - if (fullscreenvid->doneframe) - fullscreenvid->doneframe(fullscreenvid); - - return true; + return false; } #if defined(GLQUAKE) || defined(D3DQUAKE) @@ -1728,7 +1765,7 @@ texid_t Media_UpdateForShader(cin_t *cin) { if (!TEXVALID(cin->texture)) cin->texture = R_AllocNewTexture(cin->outwidth, cin->outheight); - R_Upload(cin->texture, "cin", cin->outtype, cin->outdata, cin->outwidth, cin->outheight, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA); + R_Upload(cin->texture, "cin", cin->outtype, cin->outdata, cin->outpalette, cin->outwidth, cin->outheight, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA); } if (cin->doneframe) @@ -1742,7 +1779,7 @@ texid_t Media_UpdateForShader(cin_t *cin) void Media_Send_Command(cin_t *cin, char *command) { if (!cin) - cin = fullscreenvid; + cin = R_ShaderGetCinematic(videoshader); if (!cin || !cin->key) return; cin->changestream(cin, command); @@ -1750,7 +1787,7 @@ void Media_Send_Command(cin_t *cin, char *command) void Media_Send_KeyEvent(cin_t *cin, int button, int unicode, int event) { if (!cin) - cin = fullscreenvid; + cin = R_ShaderGetCinematic(videoshader); if (!cin || !cin->key) return; cin->key(cin, button, unicode, event); @@ -1758,7 +1795,7 @@ void Media_Send_KeyEvent(cin_t *cin, int button, int unicode, int event) void Media_Send_MouseMove(cin_t *cin, float x, float y) { if (!cin) - cin = fullscreenvid; + cin = R_ShaderGetCinematic(videoshader); if (!cin || !cin->key) return; cin->cursormove(cin, x, y); @@ -1770,7 +1807,7 @@ void Media_Send_Resize(cin_t *cin, int x, int y) void Media_Send_GetSize(cin_t *cin, int *x, int *y) { if (!cin) - cin = fullscreenvid; + cin = R_ShaderGetCinematic(videoshader); if (!cin || !cin->key) return; cin->getsize(cin, x, y); diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 044bae6c..31641a97 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -3,6 +3,35 @@ #include "quakedef.h" #include "winquake.h" +menu_t *M_Options_Title(int *y, int infosize) +{ + struct menu_s *menu; + *y = 32; + + key_dest = key_menu; + m_state = m_complex; + + menu = M_CreateMenu(infosize); + + switch(M_GameType()) + { + case MGT_QUAKE2: //q2... + MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_options"); + *y += 32; + break; + case MGT_HEXEN2://h2 + MC_AddPicture(menu, 16, 0, 35, 176, "gfx/menu/hplaque.lmp"); + MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title3.lmp"); + *y += 32; + break; + default: //q1 + MC_AddPicture(menu, 16, 4, 32, 144, "gfx/qplaque.lmp"); + MC_AddCenterPicture(menu, 4, 24, "gfx/p_option.lmp"); + break; + } + return menu; +} + //these are awkward/strange qboolean M_Options_AlwaysRun (menucheck_t *option, struct menu_s *menu, chk_set_t set) { @@ -19,7 +48,7 @@ qboolean M_Options_AlwaysRun (menucheck_t *option, struct menu_s *menu, chk_set_ Cvar_SetValue (&cl_forwardspeed, 400); Cvar_SetValue (&cl_backspeed, 400); return true; - } + } } qboolean M_Options_InvertMouse (menucheck_t *option, struct menu_s *menu, chk_set_t set) { @@ -29,76 +58,75 @@ qboolean M_Options_InvertMouse (menucheck_t *option, struct menu_s *menu, chk_se { Cvar_SetValue (&m_pitch, -m_pitch.value); return m_pitch.value < 0; - } + } } //options menu. void M_Menu_Options_f (void) { - int mgt; extern cvar_t cl_standardchat; extern cvar_t cl_standardmsg, crosshair; #ifdef _WIN32 extern qboolean vid_isfullscreen; #endif - menu_t *menu; - int y = 32; - - key_dest = key_menu; - m_state = m_complex; - - menu = M_CreateMenu(0); - - mgt = M_GameType(); - if (mgt == MGT_QUAKE2) - { //q2... - MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_options"); - y += 32; - } - else if (mgt == MGT_HEXEN2) - { //h2 - MC_AddPicture(menu, 16, 0, 35, 176, "gfx/menu/hplaque.lmp"); - MC_AddCenterPicture(menu, 0, 60, "gfx/menu/title3.lmp"); - y+=32; - } - else - { //q1 - MC_AddPicture(menu, 16, 4, 32, 144, "gfx/qplaque.lmp"); - MC_AddCenterPicture(menu, 4, 24, "gfx/p_option.lmp"); - } + int y; + menu_t *menu = M_Options_Title(&y, 0); + int mgt = M_GameType(); menu->selecteditem = (union menuoption_s *) - MC_AddConsoleCommand(menu, 16, y, " Customize controls", "menu_keys\n"); y+=8; - MC_AddConsoleCommand(menu, 16, y, " Go to console", "toggleconsole\nplay misc/menu2.wav\n"); y+=8; - MC_AddConsoleCommand(menu, 16, y, " Reset to defaults", "exec default.cfg\nplay misc/menu2.wav\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Customize controls", "menu_keys\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Go to console", "toggleconsole\nplay misc/menu2.wav\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Reset to defaults", "exec default.cfg\nplay misc/menu2.wav\n"); y+=8; - MC_AddSlider(menu, 16, y, " Mouse Speed", &sensitivity, 1, 10, 0.5); y+=8; - MC_AddSlider(menu, 16, y, " Crosshair", &crosshair, 0, 22, 1); y+=8; + MC_AddSlider(menu, 16, y, " Mouse Speed", &sensitivity, 1, 10, 0.5); y+=8; + MC_AddSlider(menu, 16, y, " Crosshair", &crosshair, 0, 22, 1); y+=8; - MC_AddCheckBox(menu, 16, y, " Always Run", NULL,0)->func = M_Options_AlwaysRun; y+=8; - MC_AddCheckBox(menu, 16, y, " Invert Mouse", NULL,0)->func = M_Options_InvertMouse; y+=8; - MC_AddCheckBox(menu, 16, y, " Lookspring", &lookspring,0); y+=8; - MC_AddCheckBox(menu, 16, y, " Lookstrafe", &lookstrafe,0); y+=8; - MC_AddCheckBox(menu, 16, y, " Use old status bar", &cl_sbar,0); y+=8; - MC_AddCheckBox(menu, 16, y, " HUD on left side", &cl_hudswap,0); y+=8; - MC_AddCheckBox(menu, 16, y, " Old-style chatting", &cl_standardchat,0);y+=8; - MC_AddCheckBox(menu, 16, y, " Old-style messages", &cl_standardmsg,0);y+=8; - y+=4;MC_AddEditCvar(menu, 16, y, " Imitate FPS", "cl_netfps"); y+=8+4; - y+=4;MC_AddEditCvar(menu, 16, y, " Auto status format", "tp_autostatus"); y+=8+4; + MC_AddCheckBox(menu, 16, y, " Always Run", NULL,0)->func = M_Options_AlwaysRun; y+=8; + MC_AddCheckBox(menu, 16, y, " Invert Mouse", NULL,0)->func = M_Options_InvertMouse; y+=8; + MC_AddCheckBox(menu, 16, y, " Lookspring", &lookspring,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Lookstrafe", &lookstrafe,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Use old status bar", &cl_sbar,0); y+=8; + MC_AddCheckBox(menu, 16, y, " HUD on left side", &cl_hudswap,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Old-style chatting", &cl_standardchat,0);y+=8; + MC_AddCheckBox(menu, 16, y, " Old-style messages", &cl_standardmsg,0);y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Imitate FPS", "cl_netfps"); y+=8+4; - MC_AddConsoleCommand(menu, 16, y, " Video Options", "menu_video\n"); y+=8; - MC_AddConsoleCommand(menu, 16, y, " FPS Options", "menu_fps\n"); y+=8; - MC_AddConsoleCommand(menu, 16, y, " Audio Options", "menu_audio\n"); y+=8; - MC_AddConsoleCommand(menu, 16, y, " Downloads", "menu_download\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Video Options", "menu_video\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Shadow & Lighting Options", "menu_shadow_lighting\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " 3D Rendering Options", "menu_3d\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Texture Options", "menu_textures\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Particle Options", "menu_particles\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " FPS Options", "menu_fps\n"); y+=8; + + if ((mgt != MGT_QUAKE2) && (mgt != MGT_HEXEN2)) + { + MC_AddConsoleCommand(menu, 16, y, " Teamplay Options", "menu_teamplay\n"); y+=8; + } + + if (mgt == MGT_QUAKE2) + { + MC_AddConsoleCommand(menu, 16, y, "Singleplayer Cheat Options", "menu_quake2_spcheats\n"); y+=8; + } + else if (mgt == MGT_HEXEN2) + { + MC_AddConsoleCommand(menu, 16, y, "Singleplayer Cheat Options", "menu_hexen2_spcheats\n"); y+=8; + } + else + { + MC_AddConsoleCommand(menu, 16, y, "Singleplayer Cheat Options", "menu_spcheats\n"); y+=8; + } + + MC_AddConsoleCommand(menu, 16, y, " Audio Options", "menu_audio\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Downloads", "menu_download\n"); y+=8; #ifdef _WIN32 - if (!vid_isfullscreen) + if (!vid_isfullscreen) #endif { MC_AddCheckBox(menu, 16, y, " Use Mouse", &_windowed_mouse,0); y+=8; } - menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, 32, NULL, false); + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 225, 32, NULL, false); } #ifndef __CYGWIN__ @@ -128,7 +156,7 @@ qboolean M_Audio_Key (int key, struct menu_s *menu) return true; } - + if (key == K_DOWNARROW) { info->testsoundsource->common.posy+=10; @@ -228,10 +256,9 @@ void M_Menu_Audio_Speakers_f (void) 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 = 32; menu_t *menu; - int mgt; - extern cvar_t nosound, precache, snd_leftisright, snd_khz, snd_eax, snd_speakers, ambient_level; + int cursorpositionY; + extern cvar_t nosound, precache, snd_leftisright, snd_khz, snd_eax, snd_speakers, ambient_level, bgmvolume, snd_playersoundvolume, ambient_fade, cl_staticsounds, snd_inactive, _snd_mixahead, snd_usemultipledevices, snd_noextraupdate, snd_show, bgmbuffer; static const char *soundqualityoptions[] = { "11025 Hz", @@ -263,42 +290,40 @@ void M_Menu_Audio_f (void) NULL }; - key_dest = key_menu; - m_state = m_complex; + int y; + menu = M_Options_Title(&y, 0); - menu = M_CreateMenu(0); - - mgt = M_GameType(); - - if (mgt == MGT_QUAKE2) - { - MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_options"); - y += 32; - } - else if (mgt == MGT_HEXEN2) - { - } - else - { - MC_AddPicture(menu, 16, 4, 32, 144, "gfx/qplaque.lmp"); - MC_AddCenterPicture(menu, 4, 24, "gfx/p_option.lmp"); - } + cursorpositionY = (y + 24); menu->selecteditem = (union menuoption_s *) - MC_AddSlider(menu, 16, y, " CD Music Volume", &bgmvolume, 0, 1, 0.1);y+=8; - MC_AddSlider(menu, 16, y, " Sound Volume", &volume, 0, 1, 0.1);y+=8; - MC_AddSlider(menu, 16, y, " Ambient Volume", &ambient_level, 0, 1, 0.1);y+=8; - MC_AddCheckBox(menu, 16, y, " no sound", &nosound,0);y+=8; - MC_AddCheckBox(menu, 16, y, " precache", &precache,0);y+=8; - MC_AddCheckBox(menu, 16, y, " Low Quality Sound", &loadas8bit,0);y+=8; - MC_AddCheckBox(menu, 16, y, " Flip Sound", &snd_leftisright,0);y+=8; - MC_AddCheckBox(menu, 16, y, " Experimental EAX 2", &snd_eax,0);y+=8; - MC_AddCvarCombo(menu, 16, y, " Speaker setup", &snd_speakers, speakeroptions, speakervalues);y+=8; - MC_AddCvarCombo(menu, 16, y, " Sound speed", &snd_khz, soundqualityoptions, soundqualityvalues);y+=8; - MC_AddConsoleCommand(menu, 16, y, " Restart sound", "snd_restart\n");y+=8; + MC_AddRedText(menu, 16, y, " Sound Options", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; - menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, 32, NULL, false); + MC_AddSlider(menu, 16, y, " CD Music Volume", &bgmvolume, 0, 1, 0.1);y+=8; + MC_AddSlider(menu, 16, y, " CD Music Buffer", &bgmbuffer, 0, 10240, 1024);y+=8; + MC_AddSlider(menu, 16, y, " Sound Volume", &volume, 0, 1, 0.1);y+=8; + MC_AddSlider(menu, 16, y, " Player Sound Volume", &snd_playersoundvolume,0,1,0.1);y+=8; + MC_AddSlider(menu, 16, y, " Ambient Volume", &ambient_level, 0, 1, 0.1);y+=8; + MC_AddSlider(menu, 16, y, " Ambient Fade", &ambient_fade, 0, 1000, 1);y+=8; + MC_AddCheckBox(menu, 16, y, " No Sound", &nosound,0);y+=8; + MC_AddCheckBox(menu, 16, y, " Static Sounds", &cl_staticsounds,0);y+=8; + MC_AddCheckBox(menu, 16, y, " Precache", &precache,0);y+=8; + MC_AddCheckBox(menu, 16, y, " Experimental EAX 2", &snd_eax,0);y+=8; + MC_AddCvarCombo(menu, 16, y, " Speaker Setup", &snd_speakers, speakeroptions, speakervalues);y+=8; + MC_AddCvarCombo(menu, 16, y, " Sound Speed", &snd_khz, soundqualityoptions, soundqualityvalues);y+=8; + MC_AddSlider(menu, 16, y, " Sound Mixahead", &_snd_mixahead,0,1,0.05);y+=8; + MC_AddCheckBox(menu, 16, y, " Multiple Devices", &snd_usemultipledevices,0);y+=8; + MC_AddCheckBox(menu, 16, y, " No Extra Sound Update", &snd_noextraupdate,0);y+=8; + MC_AddCheckBox(menu, 16, y, " Low Quality Sound (8bit)", &loadas8bit,0);y+=8; + MC_AddCheckBox(menu, 16, y, " Flip Sound", &snd_leftisright,0);y+=8; + MC_AddCheckBox(menu, 16, y, "Play Sound While Inactive", &snd_inactive,0);y+=8; + //MC_AddCombo(menu, 16, y, " Show Sounds Playing", &snd_show,0);y+=8; + y+=8; + MC_AddConsoleCommand(menu, 16, y, " = Restart Sound =", "snd_restart\n");y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 225, cursorpositionY, NULL, false); } #else @@ -312,10 +337,9 @@ void M_Menu_Audio_f (void) void M_Menu_Particles_f (void) { - int y = 32; menu_t *menu; - int mgt; - extern cvar_t r_bouncysparks, r_part_rain, gl_part_flame, r_particlesystem; + int cursorpositionY; + extern cvar_t r_bouncysparks, r_part_rain, gl_part_flame, r_particlesystem, r_grenadetrail, r_rockettrail, r_part_sparks_textured, r_part_sparks_trifan, r_part_rain_quantity, r_part_beams, r_particle_tracelimit; char *psystemopts[] = { @@ -330,40 +354,34 @@ void M_Menu_Particles_f (void) NULL }; - key_dest = key_menu; - m_state = m_complex; + int y; + menu = M_Options_Title(&y, 0); - menu = M_CreateMenu(0); - - mgt = M_GameType(); - - if (mgt == MGT_QUAKE2) - { - MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_options"); - y += 32; - } - else if (mgt == MGT_HEXEN2) - { - } - else - { - MC_AddPicture(menu, 16, 4, 32, 144, "gfx/qplaque.lmp"); - MC_AddCenterPicture(menu, 4, 24, "gfx/p_option.lmp"); - } + cursorpositionY = (y + 24); menu->selecteditem = (union menuoption_s *) - MC_AddCvarCombo(menu, 16, y, " particle system", &r_particlesystem, psystemopts, psystemvals);y+=8; + MC_AddRedText(menu, 16, y, " Particle Options", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + + MC_AddCvarCombo(menu, 16, y, " particle system", &r_particlesystem, psystemopts, psystemvals);y+=8; //fixme: hide the rest of the options if r_particlesystem==classic - MC_AddConsoleCommand(menu, 16, y, " Choose particle set", "menu_particlesets");y+=8; - MC_AddCheckBox(menu, 16, y, " sparks bounce", &r_bouncysparks,0);y+=8; -// MC_AddSlider(menu, 16, y, " exp spark count", &r_particles_in_explosion, 16, 1024);y+=8; - MC_AddCheckBox(menu, 16, y, " texture emittance", &r_part_rain, 0);y+=8; - MC_AddCheckBox(menu, 16, y, " model emitters", &gl_part_flame, 0);y+=8; + MC_AddConsoleCommand(menu, 16, y, " Choose particle set", "menu_particlesets");y+=8; +// MC_AddSlider(menu, 16, y, " exp spark count", &r_particles_in_explosion, 16, 1024);y+=8; + MC_AddSlider(menu, 16, y, " Grenade Trail", &r_grenadetrail,0,10,1); y+=8; + MC_AddSlider(menu, 16, y, " Rocket Trail", &r_rockettrail,0,10,1); y+=8; + MC_AddCheckBox(menu, 16, y, " Bouncy Sparks", &r_bouncysparks,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Textured Sparks", &r_part_sparks_textured,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Trifan Sparks", &r_part_sparks_trifan,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Rain", &r_part_rain,0); y+=8; + MC_AddSlider(menu, 16, y, " Rain Quantity", &r_part_rain_quantity,0,10,1); y+=8; + MC_AddCheckBox(menu, 16, y, " Torch Flame", &gl_part_flame,0); y+=8; + MC_AddSlider(menu, 16, y, " Particle Tracelimit", &r_particle_tracelimit,0,2000,50); y+=8; + MC_AddCheckBox(menu, 16, y, " Particle Beams", &r_part_beams,0); y+=8; - - menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, 32, NULL, false); + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, cursorpositionY, NULL, false); } enum { @@ -389,21 +407,18 @@ presetinfo_t preset[] = {"r_particlesystem", {"none", "classic", "script", "script", "script"}}, {"r_stains", {"0", "0", "0.75", "0.75", "0.75"}}, {"r_drawflat", {"1", "0", "0", "0", "0"}}, - {"gl_miptexLevel", {"3", "0", "0", "0", "0"}}, {"r_nolerp", {"1", "0", "0", "0", "0"}}, {"r_nolightdir", {"1", "1", "0", "0", "0"}}, - {"r_dynamic", {"0", "0", "1", "0", "0"}}, + {"r_dynamic", {"0", "0", "1", "1", "1"}}, {"r_bloom", {"0", "0", "0", "0", "1"}}, {"gl_flashblend", {"0", "1", "0", "1", "2"}}, {"gl_bump", {"0", "0", "0", "1", "1"}}, - {"r_skin_overlays", {"0", "0", "1", "1", "1"}}, {"gl_specular", {"0", "0", "0", "1", "1"}}, {"r_loadlit", {"0", "1", "1", "2", "2"}}, {"r_fastsky", {"1", "0", "0", "-1", "-1"}}, {"r_waterlayers", {"0", "2", "", "4", "4"}}, - {"r_shadows", {"0", "0", "0", "1", "1"}}, - {"r_shadow_realtime_world",{"0", "0", "0", "0", "1"}}, - {"r_shadow_realtime_dlight",{"0", "0", "0", "1", "1"}}, +{"r_shadow_realtime_dlight",{"0", "0", "0", "1", "1"}}, +{"r_shadow_realtime_world", {"0", "0", "0", "0", "1"}}, {"gl_detail", {"0", "0", "0", "1", "1"}}, {"gl_load24bit", {"0", "0", "1", "1", "1"}}, {"r_replacemodels", {"", "", "md3 md2", "md3 md2", "md3 md2"}}, @@ -417,9 +432,9 @@ static void ApplyPreset (int presetnum) for (i = 1; preset[i].cvarname; i++) { Cbuf_AddText(preset[i].cvarname, Cmd_ExecLevel); - Cbuf_AddText(" \"", Cmd_ExecLevel); + Cbuf_AddText(" ", Cmd_ExecLevel); Cbuf_AddText(preset[i].value[presetnum], Cmd_ExecLevel); - Cbuf_AddText("\"\n", Cmd_ExecLevel); + Cbuf_AddText("\n", Cmd_ExecLevel); } } @@ -445,83 +460,1801 @@ void FPS_Preset_f (void) void M_Menu_FPS_f (void) { - char *loadlitoptions[] = {" off", " load", " generate", NULL}; - char *numbervalues[] = {"0", "1", "2"}; - int y = 32; menu_t *menu; - int mgt; + int cursorpositionY; int i, len; -#ifdef GLQUAKE - extern cvar_t gl_compress, gl_detail, gl_bump, gl_specular, r_flashblend, r_shadow_realtime_world, r_shadow_realtime_dlight, gl_motionblur, r_nolightdir; -#endif - extern cvar_t r_stains, r_bloodstains, r_loadlits, r_dynamic, v_contentblend, show_fps; - key_dest = key_menu; - m_state = m_complex; + extern cvar_t v_contentblend, show_fps, cl_r2g, cl_gibfilter, cl_expsprite, cl_deadbodyfilter; - menu = M_CreateMenu(0); + int y; + menu = M_Options_Title(&y, 0); - mgt = M_GameType(); - - if (mgt == MGT_QUAKE2) - { - MC_AddCenterPicture(menu, 4, 24, "pics/m_banner_options"); - y += 32; - } - else if (mgt == MGT_HEXEN2) - { - } - else - { - MC_AddPicture(menu, 16, 4, 32, 144, "gfx/qplaque.lmp"); - MC_AddCenterPicture(menu, 4, 24, "gfx/p_option.lmp"); - } + cursorpositionY = (y + 24); menu->selecteditem = (union menuoption_s *) - MC_AddConsoleCommand(menu, 48, y, " Particle Options", "menu_particles\n"); y+=8; + MC_AddRedText(menu, 16, y, " FPS Options", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; for (i = 0; i < PRESET_MAX; i++) { len = strlen(preset[0].value[i]); - MC_AddConsoleCommand(menu, 48+8*(9-len), y, va("(preset) %s", preset[0].value[i]), va("fps_preset %s\n", preset[0].value[i])); y+=8; + MC_AddConsoleCommand(menu, 116, y, va("(preset) %s", preset[0].value[i]), va("fps_preset %s\n", preset[0].value[i])); y+=8; } + MC_AddCheckBox(menu, 16, y, " Show FPS", &show_fps,0);y+=8; - MC_AddCheckBox(menu, 48, y, " Show FPS", &show_fps,0);y+=8; + MC_AddCheckBox(menu, 16, y, " Content blend", &v_contentblend,0);y+=8; + MC_AddCheckBox(menu, 16, y, " Gib Filter", &cl_gibfilter,0); y+=8; + MC_AddSlider(menu, 16, y, " Dead Body Filter", &cl_deadbodyfilter,0,2,1); y+=8; + MC_AddCheckBox(menu, 16, y, " Explosion Sprite", &cl_expsprite,0); y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Skybox", "r_skybox");y+=8;y+=4; + MC_AddCheckBox(menu, 16, y, " Rockets to Grenades", &cl_r2g,0); y+=8; - MC_AddCheckBox(menu, 48, y, " Content blend", &v_contentblend,0);y+=8; - - y+=4;MC_AddEditCvar(menu, 48, y, " Skybox", "r_skybox");y+=8;y+=4; - - switch(qrenderer) - { -#ifdef GLQUAKE - case QR_OPENGL: - MC_AddCvarCombo(menu, 48, y, " Coloured lighting", &r_loadlits, loadlitoptions, numbervalues);y+=8; - MC_AddCheckBox(menu, 48, y, " 32 bit textures", &gl_load24bit,0);y+=8; - MC_AddCheckBox(menu, 48, y, " Detail Texturing", &gl_detail,0);y+=8; - MC_AddCheckBox(menu, 48, y, " Bumpmaps", &gl_bump,0);y+=8; - MC_AddCheckBox(menu, 48, y, " Specular Textures", &gl_specular,0);y+=8; - MC_AddCheckBox(menu, 48, y, " Tex Compression", &gl_compress,0);y+=8; - - MC_AddCheckBox(menu, 48, y, " Stainmaps", &r_stains,0);y+=8; - MC_AddCheckBox(menu, 48, y, " Blood stains", &r_bloodstains,0);y+=8; - - MC_AddCheckBox(menu, 48, y, " Flat mdl Lighting", &r_nolightdir,0);y+=8; - MC_AddCheckBox(menu, 48, y, "Old Dynamic lights", &r_dynamic,0);y+=8; - MC_AddCheckBox(menu, 48, y, " Flashblending", &r_flashblend,0);y+=8; - MC_AddCheckBox(menu, 48, y, " Realtime DLights", &r_shadow_realtime_dlight,0);y+=8; - MC_AddCheckBox(menu, 48, y, " DLights Shadows", &r_shadow_realtime_dlight_shadows,0);y+=8; - MC_AddCheckBox(menu, 48, y, " Realtime WLights", &r_shadow_realtime_world,0);y+=8; - MC_AddCheckBox(menu, 48, y, " World Shadows", &r_shadow_realtime_world_shadows,0);y+=8; - - MC_AddCheckBox(menu, 48, y, " Waterwarp", &r_waterwarp,0);y+=8; - MC_AddSlider(menu, 48, y, " Motion blur", &gl_motionblur, 0, 0.99, 0);y+=8; - break; -#endif - default: - break; - } - - menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, 32, NULL, false); + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 188, cursorpositionY, NULL, false); +} + +//copy and pasted from renderer.c +qboolean M_VideoApply2 (union menuoption_s *op,struct menu_s *menu,int key) +{ + if (key != K_ENTER) + return false; + + // r_shadows too + + + Cbuf_AddText("vid_restart\n", RESTRICT_LOCAL); + + M_RemoveMenu(menu); + Cbuf_AddText("menu_options\n", RESTRICT_LOCAL); + return true; +} + +typedef struct { + menucombo_t *multisamplingcombo; +} threeDmenuinfo_t; + +qboolean M_VideoApply3D (union menuoption_s *op,struct menu_s *menu,int key) +{ + threeDmenuinfo_t *info = menu->data; + int currentmsaalevel; + extern cvar_t vid_multisample; + + if (key != K_ENTER) + return false; + + if (vid_multisample.value == 8) + currentmsaalevel = 4; + else if (vid_multisample.value == 6) + currentmsaalevel = 3; + else if (vid_multisample.value == 4) + currentmsaalevel = 2; + else if (vid_multisample.value == 2) + currentmsaalevel = 1; + else if (vid_multisample.value <= 1) + currentmsaalevel = 0; + else + currentmsaalevel = 0; + + if (info->multisamplingcombo->selectedoption != currentmsaalevel) // if MSAA doesn't change, don't bother applying it when the video system is restarted + { + switch(info->multisamplingcombo->selectedoption) + { + case 0: + Cbuf_AddText("vid_multisample 0\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("vid_multisample 2\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("vid_multisample 4\n", RESTRICT_LOCAL); + break; + case 3: + Cbuf_AddText("vid_multisample 6\n", RESTRICT_LOCAL); + break; + case 4: + Cbuf_AddText("vid_multisample 8\n", RESTRICT_LOCAL); + break; + } + } + #ifdef _DEBUG + else + { + Con_Printf("MSAA: Selected option matches current CVAR value (%d & %d), no change made.\n",info->multisamplingcombo->selectedoption, currentmsaalevel); + } + #endif + + Cbuf_AddText("vid_restart\n", RESTRICT_LOCAL); + + M_RemoveMenu(menu); + Cbuf_AddText("menu_3d\n", RESTRICT_LOCAL); + return true; +} + +void M_Menu_3D_f (void) +{ + static const char *msaalevels[] = + { + "Off", + "2x", + "4x", + "6x", + "8x", + NULL + }; + + threeDmenuinfo_t *info; + menu_t *menu; + int cursorpositionY; + int currentmsaalevel; +#ifndef MINIMAL + extern cvar_t r_xflip; +#endif + extern cvar_t r_novis, gl_dither, cl_item_bobbing, r_waterwarp, r_nolerp, r_fastsky, gl_nocolors, gl_lerpimages, gl_keeptjunctions, gl_lateswap, r_mirroralpha, r_wateralpha, r_drawviewmodel, gl_maxdist, gl_motionblur, gl_motionblurscale, gl_blend2d, gl_blendsprites, r_flashblend, gl_cshiftenabled, vid_multisample; + + int y; + menu = M_Options_Title(&y, sizeof(threeDmenuinfo_t)); + info = menu->data; + + cursorpositionY = (y + 24); + + if (vid_multisample.value == 8) + currentmsaalevel = 4; + else if (vid_multisample.value == 6) + currentmsaalevel = 3; + else if (vid_multisample.value == 4) + currentmsaalevel = 2; + else if (vid_multisample.value == 2) + currentmsaalevel = 1; + else if (vid_multisample.value <= 1) + currentmsaalevel = 0; + else + currentmsaalevel = 0; + + menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " 3D Renderering Options", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + + MC_AddCheckBox(menu, 16, y, " Calculate VIS", &r_novis,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Water Warp", &r_waterwarp,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Model Interpollation", &r_nolerp,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Toggle Sky", &r_fastsky,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Lerp Images", &gl_lerpimages,0); y+=8; + MC_AddSlider(menu, 16, y, " Maximum Distance", &gl_maxdist,1,8192,128); y+=8; + MC_AddCheckBox(menu, 16, y, " GL Swapbuffer Delay", &gl_lateswap,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Mirror Reflections", &r_mirroralpha,0); y+=8; + #ifndef MINIMAL + MC_AddCheckBox(menu, 16, y, " Flip Horizontal View", &r_xflip,0); y+=8; + #endif + MC_AddCheckBox(menu, 16, y, " Water Transparency", &r_wateralpha,0); y+=8; + MC_AddSlider(menu, 16, y, " View Model Transparency", &r_drawviewmodel,0,1,0.1); y+=8; + MC_AddCheckBox(menu, 16, y, "Ignore Player Model Colors", &gl_nocolors,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Toggle Colinear Vertexes", &gl_keeptjunctions,0); y+=8; + MC_AddSlider(menu, 16, y, " Motion Blur", &gl_motionblur,0,1,0.5); y+=8; + MC_AddSlider(menu, 16, y, " Motion Blur Scale", &gl_motionblurscale,0,1,0.5); y+=8; + MC_AddCheckBox(menu, 16, y, " 2D Blending", &gl_blend2d,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Sprite Blending", &gl_blendsprites,0); y+=8; + MC_AddSlider(menu, 16, y, " Flash Blending", &r_flashblend,0,2,1); y+=8; + MC_AddCheckBox(menu, 16, y, " Poly Blending", &gl_cshiftenabled,0); y+=8; + MC_AddCheckBox(menu, 16, y, " 16bit Color Dithering", &gl_dither,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Model Bobbing", &cl_item_bobbing,0); y+=8; + info->multisamplingcombo = MC_AddCombo(menu, 16, y, " Multisample Anti-Aliasing", msaalevels, currentmsaalevel); y+=8; + y+=8; + MC_AddCommand(menu, 16, y, " Apply", M_VideoApply3D); y+=8; + + //menu->selecteditem = (union menuoption_s *)info->multisamplingcombo; + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 225, cursorpositionY, NULL, false); +} + +typedef struct { + menucombo_t *texturefiltercombo; + menucombo_t *anisotropycombo; + menucombo_t *maxtexturesizecombo; + menucombo_t *bloomsamplesizecombo; + menucombo_t *bloomdiamondcombo; +} texturemenuinfo_t; + +qboolean M_VideoApplyTextures (union menuoption_s *op,struct menu_s *menu,int key) +{ + texturemenuinfo_t *info = menu->data; +#ifndef MINIMAL + int currentbloomdiamond; + int currentbloomsamplesize; + + extern cvar_t r_bloom_sample_size, r_bloom_diamond_size; +#endif + + if (key != K_ENTER) + return false; + + switch(info->texturefiltercombo->selectedoption) + { + case 0: + Cbuf_AddText("gl_texturemode gl_nearest_mipmap_nearest\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("gl_texturemode gl_linear_mipmap_nearest\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("gl_texturemode gl_linear_mipmap_linear\n", RESTRICT_LOCAL); + break; + } + + switch(info->anisotropycombo->selectedoption) + { + case 0: + Cbuf_AddText("gl_texture_anisotropic_filtering 0\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("gl_texture_anisotropic_filtering 2\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("gl_texture_anisotropic_filtering 4\n", RESTRICT_LOCAL); + break; + case 3: + Cbuf_AddText("gl_texture_anisotropic_filtering 8\n", RESTRICT_LOCAL); + break; + case 4: + Cbuf_AddText("gl_texture_anisotropic_filtering 16\n", RESTRICT_LOCAL); + break; + } + + switch(info->maxtexturesizecombo->selectedoption) + { + case 0: + Cbuf_AddText("gl_max_size 128\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("gl_max_size 196\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("gl_max_size 256\n", RESTRICT_LOCAL); + break; + case 3: + Cbuf_AddText("gl_max_size 384\n", RESTRICT_LOCAL); + break; + case 4: + Cbuf_AddText("gl_max_size 512\n", RESTRICT_LOCAL); + break; + case 5: + Cbuf_AddText("gl_max_size 768\n", RESTRICT_LOCAL); + break; + case 6: + Cbuf_AddText("gl_max_size 1024\n", RESTRICT_LOCAL); + break; + case 7: + Cbuf_AddText("gl_max_size 2048\n", RESTRICT_LOCAL); + break; + case 8: + Cbuf_AddText("gl_max_size 4096\n", RESTRICT_LOCAL); + break; + case 9: + Cbuf_AddText("gl_max_size 8192\n", RESTRICT_LOCAL); + break; + } + +#ifndef MINIMAL + if (r_bloom_sample_size.value >= 512) + currentbloomsamplesize = 7; + else if (r_bloom_sample_size.value == 384) + currentbloomsamplesize = 6; + else if (r_bloom_sample_size.value == 256) + currentbloomsamplesize = 5; + else if (r_bloom_sample_size.value == 192) + currentbloomsamplesize = 4; + else if (r_bloom_sample_size.value == 128) + currentbloomsamplesize = 3; + else if (r_bloom_sample_size.value == 96) + currentbloomsamplesize = 2; + else if (r_bloom_sample_size.value == 64) + currentbloomsamplesize = 1; + else if (r_bloom_sample_size.value <= 32) + currentbloomsamplesize = 0; + else + currentbloomsamplesize = 0; + + if (info->bloomsamplesizecombo->selectedoption != currentbloomsamplesize) + { + switch(info->bloomsamplesizecombo->selectedoption) + { + case 0: + Cbuf_AddText("r_bloom_sample_size 32\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("r_bloom_sample_size 64\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("r_bloom_sample_size 96\n", RESTRICT_LOCAL); + break; + case 3: + Cbuf_AddText("r_bloom_sample_size 128\n", RESTRICT_LOCAL); + break; + case 4: + Cbuf_AddText("r_bloom_sample_size 192\n", RESTRICT_LOCAL); + break; + case 5: + Cbuf_AddText("r_bloom_sample_size 256\n", RESTRICT_LOCAL); + break; + case 6: + Cbuf_AddText("r_bloom_sample_size 384\n", RESTRICT_LOCAL); + break; + case 7: + Cbuf_AddText("r_bloom_sample_size 512\n", RESTRICT_LOCAL); + break; + } + } + #ifdef _DEBUG + else + { + Con_Printf("Bloom Sample Size: Selected option matches current CVAR value (%d & %d), no change made.\n",info->bloomsamplesizecombo->selectedoption, currentbloomsamplesize); + } + #endif + + if (r_bloom_diamond_size.value >= 10) + currentbloomdiamond = 4; + else if (r_bloom_diamond_size.value >= 8) + currentbloomdiamond = 3; + else if (r_bloom_diamond_size.value >= 6) + currentbloomdiamond = 2; + else if (r_bloom_diamond_size.value >= 4) + currentbloomdiamond = 1; + else if (r_bloom_diamond_size.value <= 2) + currentbloomdiamond = 0; + else + currentbloomdiamond = 0; + + if (info->bloomdiamondcombo->selectedoption != currentbloomdiamond) + { + switch(info->bloomdiamondcombo->selectedoption) + { + case 0: + Cbuf_AddText("r_bloom_diamond_size 2\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("r_bloom_diamond_size 4\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("r_bloom_diamond_size 6\n", RESTRICT_LOCAL); + break; + case 3: + Cbuf_AddText("r_bloom_diamond_size 8\n", RESTRICT_LOCAL); + break; + case 4: + Cbuf_AddText("r_bloom_diamond_size 10\n", RESTRICT_LOCAL); + break; + } + } + #ifdef _DEBUG + else + { + Con_Printf("Bloom Diamond Size: Selected option matches current CVAR value (%d & %d), no change made.\n",info->bloomdiamondcombo->selectedoption, currentbloomdiamond); + } + #endif +#endif + + Cbuf_AddText("vid_restart\n", RESTRICT_LOCAL); + + M_RemoveMenu(menu); + Cbuf_AddText("menu_textures\n", RESTRICT_LOCAL); + return true; +} + +void M_Menu_Textures_f (void) +{ + static const char *texturefilternames[] = + { + "Nearest", + "Bilinear", + "Trilinear", + NULL + }; + + static const char *anisotropylevels[] = + { + "Off", + "2x", + "4x", + "8x", + "16x", + NULL + }; + + static const char *texturesizeoptions[] = + { + // uncommented out the unreadable console text ones + //"1x1", + //"2x2", + //"4x4", + //"8x8", + //"16x16", + //"32x32", + //"64x64", + "128x128", + "196x196", + "256x256", + "384x384", + "512x512", + "768x768", + "1024x1024", + "2048x2048", + "4096x4096", + "8192x8192", + NULL + }; + +#ifndef MINIMAL + static const char *bloomsamplesizeoptions[] = + { + "32x32", + "64x64", + "96x96", + "128x128", + "192x192", + "256x256", + "384x384", + "512x512", + NULL + }; + + static const char *bloomdiamondoptions[] = + { + "2x", + "4x", + "6x", + "8x", + "10x", + NULL + }; +#endif + + texturemenuinfo_t *info; + int cursorpositionY; + int currenttexturefilter; + int currentanisotropylevel; + int currentmaxtexturesize; +#ifndef MINIMAL + int currentbloomsamplesize; + int currentbloomdiamond; + + extern cvar_t r_bloom_sample_size, r_bloom_darken, r_bloom_intensity, r_bloom_diamond_size, r_bloom_alpha, r_bloom_fast_sample; +#endif + extern cvar_t r_bloom, gl_load24bit, gl_specular, r_waterlayers, gl_bump, gl_detail, gl_detailscale, gl_compress, gl_savecompressedtex, gl_ztrick, gl_triplebuffer, gl_picmip, gl_picmip2d, gl_playermip, gl_max_size, r_stains, r_bloodstains, r_stainfadetime, r_stainfadeammount, gl_skyboxdist, r_drawflat, gl_schematics, gl_texturemode, gl_texture_anisotropic_filtering; + int y; + menu_t *menu = M_Options_Title(&y, sizeof(*info)); + info = menu->data; + + cursorpositionY = (y + 24); + +#ifndef MINIMAL + + if (r_bloom_sample_size.value >= 512) + currentbloomsamplesize = 7; + else if (r_bloom_sample_size.value == 384) + currentbloomsamplesize = 6; + else if (r_bloom_sample_size.value == 256) + currentbloomsamplesize = 5; + else if (r_bloom_sample_size.value == 192) + currentbloomsamplesize = 4; + else if (r_bloom_sample_size.value == 128) + currentbloomsamplesize = 3; + else if (r_bloom_sample_size.value == 96) + currentbloomsamplesize = 2; + else if (r_bloom_sample_size.value == 64) + currentbloomsamplesize = 1; + else if (r_bloom_sample_size.value <= 32) + currentbloomsamplesize = 0; + else + currentbloomsamplesize = 0; + + if (r_bloom_diamond_size.value >= 10) + currentbloomdiamond = 4; + else if (r_bloom_diamond_size.value >= 8) + currentbloomdiamond = 3; + else if (r_bloom_diamond_size.value >= 6) + currentbloomdiamond = 2; + else if (r_bloom_diamond_size.value >= 4) + currentbloomdiamond = 1; + else if (r_bloom_diamond_size.value <= 2) + currentbloomdiamond = 0; + else + currentbloomdiamond = 0; +#endif + + if (!Q_strcasecmp(gl_texturemode.string, "gl_nearest_mipmap_nearest")) + currenttexturefilter = 0; + else if (!Q_strcasecmp(gl_texturemode.string, "gl_linear_mipmap_linear")) + currenttexturefilter = 2; + else if (!Q_strcasecmp(gl_texturemode.string, "gl_linear_mipmap_nearest")) + currenttexturefilter = 1; + else + currenttexturefilter = 1; + + if (gl_texture_anisotropic_filtering.value >= 16) + currentanisotropylevel = 4; + else if (gl_texture_anisotropic_filtering.value == 8) + currentanisotropylevel = 3; + else if (gl_texture_anisotropic_filtering.value == 4) + currentanisotropylevel = 2; + else if (gl_texture_anisotropic_filtering.value == 2) + currentanisotropylevel = 1; + else if (gl_texture_anisotropic_filtering.value <= 1) + currentanisotropylevel = 0; + else + currentanisotropylevel = 0; + + if (gl_max_size.value >= 8192) + currentmaxtexturesize = 9; + else if (gl_max_size.value == 4096) + currentmaxtexturesize = 8; + else if (gl_max_size.value == 2048) + currentmaxtexturesize = 7; + else if (gl_max_size.value == 1024) + currentmaxtexturesize = 6; + else if (gl_max_size.value == 768) + currentmaxtexturesize = 5; + else if (gl_max_size.value == 512) + currentmaxtexturesize = 4; + else if (gl_max_size.value == 384) + currentmaxtexturesize = 3; + else if (gl_max_size.value == 256) + currentmaxtexturesize = 2; + else if (gl_max_size.value == 196) + currentmaxtexturesize = 1; + else if (gl_max_size.value <= 128) + currentmaxtexturesize = 0; + else + currentmaxtexturesize = 0; + + MC_AddRedText(menu, 16, y, " Texturing Options", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + + info->texturefiltercombo = MC_AddCombo(menu, 16, y, " Texture Filter", texturefilternames, currenttexturefilter); y+=8; + info->anisotropycombo = MC_AddCombo(menu, 16, y, " Anisotropy Level", anisotropylevels, currentanisotropylevel); y+=8; + MC_AddCheckBox(menu, 16, y, " 32bit Textures", &gl_load24bit,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Bloom", &r_bloom,0); y+=8; +#ifndef MINIMAL + MC_AddCheckBox(menu, 16, y, " Bloom Fast Sample", &r_bloom_fast_sample,0); y+=8; + info->bloomsamplesizecombo = MC_AddCombo(menu,16, y," Bloom Sample Size", bloomsamplesizeoptions, currentbloomsamplesize); y+=8; + MC_AddSlider(menu, 16, y, " Bloom Darken", &r_bloom_darken,0,5,0.25); y+=8; + MC_AddSlider(menu, 16, y, " Bloom Intensity", &r_bloom_intensity,0,20,1); y+=8; + info->bloomdiamondcombo = MC_AddCombo(menu,16, y, " Bloom Diamond Size", bloomdiamondoptions, currentbloomdiamond); y+=8; + MC_AddSlider(menu, 16, y, " Bloom Alpha", &r_bloom_alpha,0,1,0.1); y+=8; +#endif + MC_AddCheckBox(menu, 16, y, " Bumpmapping", &gl_bump,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Specular Highlights", &gl_specular,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Texture Detail", &gl_detail,0); y+=8; + MC_AddSlider(menu, 16, y, " Texture Detail Scale", &gl_detailscale,0,10,1); y+=8; + MC_AddCheckBox(menu, 16, y, " Texture Compression", &gl_compress,0); y+=8; + MC_AddCheckBox(menu, 16, y, "Save Compressed Textures", &gl_savecompressedtex,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Z Trick", &gl_ztrick,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Triple Buffering", &gl_triplebuffer,0); y+=8; + MC_AddSlider(menu, 16, y, " 3D Texture Picmip", &gl_picmip,0,16,1); y+=8; + MC_AddSlider(menu, 16, y, " 2D Texture Picmip", &gl_picmip2d,0,16,1); y+=8; + MC_AddSlider(menu, 16, y, " Model Texture Picmip", &gl_playermip,0,16,1); y+=8; + info->maxtexturesizecombo = MC_AddCombo(menu,16, y, " Maximum Texture Size", texturesizeoptions, currentmaxtexturesize); y+=8; + MC_AddCheckBox(menu, 16, y, " Stain Maps", &r_stains,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Blood Stains", &r_bloodstains,0); y+=8; + MC_AddSlider(menu, 16, y, " Stain Fade Time (secs)", &r_stainfadetime,0,30,0.5); y+=8; + MC_AddSlider(menu, 16, y, " Stain Fade Ammount", &r_stainfadeammount,0,30,1); y+=8; + MC_AddSlider(menu, 16, y, " Skybox Distance", &gl_skyboxdist,0,10000,100); y+=8; + MC_AddSlider(menu, 16, y, " Draw Flat Surfaces", &r_drawflat,0,2,1); y+=8; + MC_AddCheckBox(menu, 16, y, " Map Schematics", &gl_schematics,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Smooth Models", &gl_smoothmodels,0); y+=8; + MC_AddSlider(menu, 16, y, " Water Layers", &r_waterlayers,0,10,1); y+=8; + y+=8; + MC_AddCommand(menu, 16, y, " Apply", M_VideoApplyTextures); y+=8; + + menu->selecteditem = (union menuoption_s *)info->texturefiltercombo; + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 220, cursorpositionY, NULL, false); +} + +typedef struct { + menucombo_t *loadlitcombo; +} shadowlightingmenuinfo_t; + +qboolean M_VideoApplyShadowLighting (union menuoption_s *op,struct menu_s *menu,int key) +{ + shadowlightingmenuinfo_t *info = menu->data; + + if (key != K_ENTER) + return false; + + switch(info->loadlitcombo->selectedoption) + { + case 0: + Cbuf_AddText("r_loadlit 0\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("r_loadlit 1\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("r_loadlit 2\n", RESTRICT_LOCAL); + break; + } + + Cbuf_AddText("vid_restart\n", RESTRICT_LOCAL); + + M_RemoveMenu(menu); + Cbuf_AddText("menu_shadow_lighting\n", RESTRICT_LOCAL); + return true; +} + +void M_Menu_Shadow_Lighting_f (void) +{ + shadowlightingmenuinfo_t *info; + int cursorpositionY; + int currentloadlit; +#ifndef MINIMAL + extern cvar_t r_vertexlight; +#endif + extern cvar_t r_noaliasshadows, r_shadows, r_shadow_realtime_world, r_loadlits, gl_maxshadowlights, r_lightmap_saturation, r_dynamic, r_vertexdlights, r_lightstylesmooth, r_lightstylespeed, r_nolightdir, r_shadow_realtime_world_lightmaps, r_shadow_glsl_offsetmapping, r_shadow_glsl_offsetmapping_bias, r_shadow_glsl_offsetmapping_scale, r_shadow_bumpscale_basetexture, r_shadow_bumpscale_bumpmap, r_fb_bmodels, r_fb_models, gl_overbright, r_rocketlight, r_powerupglow, v_powerupshell, r_lightflicker, r_explosionlight; + + static const char *loadlitoptions[] = + { + "Off", + "On", + "On (Regenerate Lighting)", + NULL + }; + + int y; + menu_t *menu = M_Options_Title(&y, sizeof(*info)); + info = menu->data; + + cursorpositionY = (y + 24); + + currentloadlit = r_loadlits.value; + + menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Shadow & Lighting Options", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + + //MC_AddSlider(menu, 16, y, " Light Map Mode", &gl_lightmapmode,0,2,1); y+=8; + MC_AddSlider(menu, 16, y, " Light Map Saturation", &r_lightmap_saturation,0,1,0.1); y+=8; + MC_AddCheckBox(menu, 16, y, " Dynamic Lighting", &r_dynamic,0); y+=8; + #ifndef MINIMAL + MC_AddCheckBox(menu, 16, y, " Vertex Lighting", &r_vertexlight,0); y+=8; + #endif + MC_AddCheckBox(menu, 16, y, " Dynamic Vertex Lights", &r_vertexdlights,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Lightstyle Smoothing", &r_lightstylesmooth,0); y+=8; + MC_AddSlider(menu, 16, y, " Lightstyle Animation Speed", &r_lightstylespeed,0,50,1); y+=8; + MC_AddCheckBox(menu, 16, y, " Fullbright BSP Models", &r_fb_bmodels,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Fullbright Alias Models", &r_fb_models,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Overbright Bits", &gl_overbright,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Rocket Dynamic Lighting", &r_rocketlight,0); y+=8; + MC_AddSlider(menu, 16, y, " Powerup Glow", &r_powerupglow,0,2,1); y+=8; + MC_AddCheckBox(menu, 16, y, " Powerup Shell", &v_powerupshell,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Light Flickering", &r_lightflicker,0); y+=8; + MC_AddSlider(menu, 16, y, " Explosion Light", &r_explosionlight,0,1,0.1); y+=8; + MC_AddCheckBox(menu, 16, y, " Surface Direction Model Lighting", &r_nolightdir,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Alias Model Shadows", &r_noaliasshadows,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Realtime World Lighting", &r_shadow_realtime_world,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Realtime World Shadows", &r_shadow_realtime_world_shadows,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Realtime World Lightmaps", &r_shadow_realtime_world_lightmaps,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Realtime Dynamic Lights", &r_shadow_realtime_dlight,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Realtime Dynamic Light Shadows", &r_shadow_realtime_dlight_shadows,0); y+=8; + MC_AddCheckBox(menu, 16, y, " GLSL Shadow Offsetmapping", &r_shadow_glsl_offsetmapping,0); y+=8; + MC_AddSlider(menu, 16, y, " GLSL Shadow Offsetmapping Bias", &r_shadow_glsl_offsetmapping_bias,0,1,0.01); y+=8; + MC_AddSlider(menu, 16, y, " GLSL Shadow Offsetmapping Scale", &r_shadow_glsl_offsetmapping_scale,0,-1,0.01); y+=8; + MC_AddSlider(menu, 16, y, " Shadow Bumpscale Basetexture", &r_shadow_bumpscale_basetexture,0,10,1); y+=8; + MC_AddSlider(menu, 16, y, " Shadow Bumpscale Bumpmap", &r_shadow_bumpscale_bumpmap,0,50,1); y+=8; + info->loadlitcombo = MC_AddCombo(menu,16, y, " LIT Loading", loadlitoptions, currentloadlit); y+=8; + MC_AddSlider(menu, 16, y, " Maximum Shadow Lights", &gl_maxshadowlights,0,1000,2); y+=8; + y+=8; + MC_AddCommand(menu, 16, y, " Apply", M_VideoApplyShadowLighting); y+=8; + + menu->selecteditem = (union menuoption_s *)info->loadlitcombo; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 285, cursorpositionY, NULL, false); +} + +typedef struct { +menucombo_t *noskinscombo; +} teamplaymenuinfo_t; + +qboolean M_Apply_Teamplay (union menuoption_s *op,struct menu_s *menu,int key) +{ + teamplaymenuinfo_t *info = menu->data; + + if (key != K_ENTER) + return false; + + switch(info->noskinscombo->selectedoption) + { + case 0: + Cbuf_AddText("noskins 0\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("noskins 1\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("noskins 2\n", RESTRICT_LOCAL); + break; + } + + M_RemoveMenu(menu); + Cbuf_AddText("menu_teamplay\n", RESTRICT_LOCAL); + return true; +} + +void M_Menu_Teamplay_f (void) +{ + static const char *noskinsoptions[] = + { + "Enable Skins (Download)", + "Disable Skins", + "Enable Skins (No Download))", + NULL + }; + + teamplaymenuinfo_t *info; + int cursorpositionY; + int currentnoskins; + extern cvar_t cl_parseSay, cl_triggers, tp_forceTriggers, tp_loadlocs, cl_parseFunChars, cl_noblink, noskins; + + int y; + menu_t *menu = M_Options_Title(&y, sizeof(*info)); + info = menu->data; + + cursorpositionY = (y + 24); + + currentnoskins = noskins.value; + + MC_AddRedText(menu, 16, y, " Teamplay Options", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + + info->noskinscombo = MC_AddCombo(menu, 16, y, " Skins", noskinsoptions, currentnoskins); y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Enemy Skin", "cl_enemyskin"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Team Skin", "cl_teamskin"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Base Skin", "baseskin"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Fake Name", "cl_fakename"); y+=8+4; + MC_AddCheckBox(menu, 16, y, " Parse Fun Chars", &cl_parseFunChars,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Parse Macros", &cl_parseSay,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Load Locs", &tp_loadlocs,0); y+=8; + MC_AddCheckBox(menu, 16, y, " No Blink", &cl_noblink,0); y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Sound Trigger", "tp_soundtrigger"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Fake Name", "cl_fakename"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Weapon Order", "tp_weapon_order"); y+=8+4; + MC_AddCheckBox(menu, 16, y, " Teamplay Triggers", &cl_triggers,0); y+=8; + MC_AddCheckBox(menu, 16, y, "Force Teamplay Triggers", &tp_forceTriggers,0); y+=8; + + MC_AddCommand(menu, 16, y, " Apply", M_Apply_Teamplay); y+=8; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, "Teamplay Location Names", "menu_teamplay_locations\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Teamplay Item Needs", "menu_teamplay_needs\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Teamplay Item Names", "menu_teamplay_items\n"); y+=8; + + menu->selecteditem = (union menuoption_s *)info->noskinscombo; + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, cursorpositionY, NULL, false); +} + +void M_Menu_Teamplay_Locations_f (void) +{ + menu_t *menu; + int cursorpositionY; + + + int y; + menu = M_Options_Title(&y, 0); + + cursorpositionY = (y + 24); + + //menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Teamplay Location Names", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Green Armor ", "loc_name_ga"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Grenade Launcher", "loc_name_gl"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Lightning Gun", "loc_name_lg"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Nailgun", "loc_name_ng"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Pentagram", "loc_name_pent"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Quad", "loc_name_quad"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Red Armor", "loc_name_ra"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Ring", "loc_name_ring"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Rocket Launcher", "loc_name_rl"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Seperator", "loc_name_seperator"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Super Nailgun", "loc_name_sng"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Super Shotgun", "loc_name_ssg"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Suit", "loc_name_suit"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Yellow Armor", "loc_name_ya"); y+=8+4; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, "<- Teamplay Options", "menu_teamplay\n"); y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 232, cursorpositionY, NULL, false); +} + +void M_Menu_Teamplay_Needs_f (void) +{ + menu_t *menu; + int cursorpositionY; + + int y; + menu = M_Options_Title(&y, 0); + + cursorpositionY = (y + 24); + + //menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Teamplay Needed Items", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Cells", "tp_need_cells"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Green Armor", "tp_need_ga"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Health", "tp_need_health"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Nails", "tp_need_nails"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Red Armor", "tp_need_ra"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Rocket Launcher", "tp_need_rl"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Rockets", "tp_need_rockets"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Shells", "tp_need_shells"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Weapon", "tp_need_weapon"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Yellow Armor", "tp_need_ya"); y+=8+4; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, "<- Teamplay Options", "menu_teamplay\n"); y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, cursorpositionY, NULL, false); +} + +void M_Menu_Teamplay_Items_f (void) +{ + menu_t *menu; + int cursorpositionY; + + int y; + menu = M_Options_Title(&y, 0); + + cursorpositionY = (y + 24); + + //menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Teamplay Item Names", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + MC_AddConsoleCommand(menu, 16, y, " -> Teamplay Armor Names", "menu_teamplay_armor\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " -> Teamplay Weapon Names", "menu_teamplay_weapons\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " -> Teamplay Powerup Names", "menu_teamplay_powerups\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " -> Teamplay Ammo & Health Names", "menu_teamplay_ammo_health\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " -> Teamplay Team Fortress Item Names", "menu_teamplay_team_fortress\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " -> Teamplay Status, Location & Misc Names", "menu_teamplay_status_location_misc\n"); y+=8; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, " <- Teamplay Options", "menu_teamplay\n"); y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 64, cursorpositionY, NULL, false); +} + +void M_Menu_Teamplay_Items_Armor_f (void) +{ + menu_t *menu; + int cursorpositionY; + + int y; + menu = M_Options_Title(&y, 0); + + cursorpositionY = (y + 24); + + //menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Teamplay Armor Names", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Armor", "tp_name_armor"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Armor Type - Green", "tp_name_armortype_ga"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Armor Type - Red", "tp_name_armortype_ra"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Armor Type - Yellow", "tp_name_armortype_ya"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Green Armor", "tp_name_ga"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Red Armor", "tp_name_ra"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Yellow Armor", "tp_name_ya"); y+=8+4; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, "<- Teamplay Item Names", "menu_teamplay_items\n"); y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 232, cursorpositionY, NULL, false); +} + +void M_Menu_Teamplay_Items_Weapons_f (void) +{ + menu_t *menu; + int cursorpositionY; + int y; + menu = M_Options_Title(&y, 0); + + cursorpositionY = (y + 24); + + //menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Teamplay Weapon Names", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Axe", "tp_name_axe"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Grenade Launcher", "tp_name_gl"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Lightning Gun", "tp_name_lg"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Nailgun", "tp_name_ng"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Rocket Launcher", "tp_name_rl"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Shotgun", "tp_name_sg"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Super Nailgun", "tp_name_sng"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Super Shotgun", "tp_name_ssg"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Weapon", "tp_name_weapon"); y+=8+4; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, "<- Teamplay Item Names", "menu_teamplay_items\n"); y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, cursorpositionY, NULL, false); +} + +void M_Menu_Teamplay_Items_Powerups_f (void) +{ + menu_t *menu; + int cursorpositionY; + int y; + menu = M_Options_Title(&y, 0); + + cursorpositionY = (y + 24); + + //menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Teamplay Powerup Names", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Pentagram", "tp_name_pent"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Pented", "tp_name_pented"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Quad", "tp_name_quad"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Quaded", "tp_name_quaded"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Ring", "tp_name_ring"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Eyes (Ring)", "tp_name_eyes"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Resistance Rune", "tp_name_rune_1"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Strength Rune", "tp_name_rune_2"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Haste Rune", "tp_name_rune_3"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Regeneration Rune", "tp_name_rune_4"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Suit", "tp_name_suit"); y+=8+4; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, "<- Teamplay Item Names", "menu_teamplay_items\n"); y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, cursorpositionY, NULL, false); +} + +void M_Menu_Teamplay_Items_Ammo_Health_f (void) +{ + menu_t *menu; + int cursorpositionY; + + int y; + menu = M_Options_Title(&y, 0); + + cursorpositionY = (y + 24); + + //menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Teamplay Ammo & Health Names", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Backpack", "tp_name_backpack"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Cells", "tp_name_cells"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Nails", "tp_name_nails"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Rockets", "tp_name_rockets"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Shells", "tp_name_shells"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Health", "tp_name_health"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Mega Health", "tp_name_mh"); y+=8+4; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, "<- Teamplay Item Names", "menu_teamplay_items\n"); y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, cursorpositionY, NULL, false); +} + +void M_Menu_Teamplay_Items_Team_Fortress_f (void) +{ + menu_t *menu; + int cursorpositionY; + + int y; + menu = M_Options_Title(&y, 0); + + cursorpositionY = (y + 24); + + //menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Teamplay Team Fortress Item Names", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " Sentry Gun", "tp_name_sentry"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Dispenser", "tp_name_disp"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Flag", "tp_name_flag"); y+=8+4; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, "<- Teamplay Item Names", "menu_teamplay_items\n"); y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, cursorpositionY, NULL, false); +} + +void M_Menu_Teamplay_Items_Status_Location_Misc_f (void) +{ + menu_t *menu; + int cursorpositionY; + + int y; + menu = M_Options_Title(&y, 0); + + cursorpositionY = (y + 24); + + //menu->selecteditem = (union menuoption_s *) + + MC_AddRedText(menu, 16, y, " Teamplay Status, Location & Misc. Names", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; + y+=4;MC_AddEditCvar(menu, 16, y, " At (Location)", "tp_name_at"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Enemy", "tp_name_enemy"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " None", "tp_name_none"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Nothing", "tp_name_nothing"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Seperator", "tp_name_seperator"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Someplace", "tp_name_someplace"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Status Blue", "tp_name_status_blue"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Status Green", "tp_name_status_green"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Status Red", "tp_name_status_red"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Status Yellow", "tp_name_status_yellow"); y+=8+4; + y+=4;MC_AddEditCvar(menu, 16, y, " Teammate", "tp_name_teammate"); y+=8+4; + + y+=8; + MC_AddConsoleCommand(menu, 16, y, "<- Teamplay Item Names", "menu_teamplay_items\n"); y+=8; + + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 200, cursorpositionY, NULL, false); +} + +typedef struct { +menucombo_t *skillcombo; +menucombo_t *mapcombo; +} singleplayerinfo_t; + +static const char *maplist_q1[] = +{ + "start", + "e1m1", + "e1m2", + "e1m3", + "e1m4", + "e1m5", + "e1m6", + "e1m7", + "e1m8", + "e2m1", + "e2m2", + "e2m3", + "e2m4", + "e2m5", + "e2m6", + "e2m7", + "e3m1", + "e3m2", + "e3m3", + "e3m4", + "e3m5", + "e3m6", + "e3m7", + "e4m1", + "e4m2", + "e4m3", + "e4m4", + "e4m5", + "e4m6", + "e4m7", + "e4m8", + "end" +}; +static const char *mapoptions_q1[] = +{ + "Start (Introduction)", + "E1M1 (The Slipgate Complex)", + "E1M2 (Castle Of The Damned)", + "E1M3 (The Necropolis)", + "E1M4 (The Grisly Grotto)", + "E1M5 (Gloom Keep)", + "E1M6 (The Door To Chthon)", + "E1M7 (The House Of Chthon)", + "E1M8 (Ziggarat Vertigo)", + "E2M1 (The Installation)", + "E2M2 (The Ogre Citadel)", + "E2M3 (The Crypt Of Decay)", + "E2M4 (The Ebon Fortress)", + "E2M5 (The Wizard's Manse)", + "E2M6 (The Dismal Oubliette", + "E2M7 (The Underearth)", + "E3M1 (Termination Central)", + "E3M2 (The Vaults Of Zin)", + "E3M3 (The Tomb Of Terror)", + "E3M4 (Satan's Dark Delight)", + "E3M5 (The Wind Tunnels)", + "E3M6 (Chambers Of Torment)", + "E3M7 (Tha Haunted Halls)", + "E4M1 (The Sewage System)", + "E4M2 (The Tower Of Despair)", + "E4M3 (The Elder God Shrine)", + "E4M4 (The Palace Of Hate)", + "E4M5 (Hell's Atrium)", + "E4M6 (The Pain Maze)", + "E4M7 (Azure Agony)", + "E4M8 (The Nameless City)", + "End (Shub-Niggurath's Pit)", + NULL +}; + + +static const char *maplist_q2[] = +{ + "base1", + "base2", + "base3", + "train", + "bunk1", + "ware1", + "ware2", + "jail1", + "jail2", + "jail3", + "jail4", + "jail5", + "security", + "mintro", + "mine1", + "mine2", + "mine3", + "mine4", + "fact1", + "fact3", + "fact2", + "power1", + "power2", + "cool1", + "waste1", + "waste2", + "waste3", + "biggun", + "hangar1", + "space", + "lab", + "hangar2", + "command", + "strike", + "city1", + "city2", + "city3", + "boss1", + "boss2" +}; +static const char *mapoptions_q2[] = +{ + "base1 (Unit 1 Base Unit: Outer Base)", + "base2 (Unit 1 Base Unit: Installation)", + "base3 (Unit 1 Base Unit: Comm Center)", + "train (Unit 1 Base Unit: Lost Station)", + "bunk1 (Unit 2 Warehouse Unit: Ammo Depot)", + "ware1 (Unit 2 Warehouse Unit: Supply Station)", + "ware2 (Unit 2 Warehouse Unit: Warehouse)", + "jail1 (Unit 3 Jail Unit: Main Gate)", + "jail2 (Unit 3 Jail Unit: Destination Center)", + "jail3 (Unit 3 Jail Unit: Security Compex)", + "jail4 (Unit 3 Jail Unit: Torture Chambers)", + "jail5 (Unit 3 Jail Unit: Guard House)", + "security (Unit 3 Jail Unit: Grid Control)", + "mintro (Unit 4 Mine Unit: Mine Entrance)", + "mine1 (Unit 4 Mine Unit: Upper Mines)", + "mine2 (Unit 4 Mine Unit: Borehole)", + "mine3 (Unit 4 Mine Unit: Drilling Area)", + "mine4 (Unit 4 Mine Unit: Lower Mines)", + "fact1 (Unit 5 Factory Unit: Receiving Center)", + "fact3 (Unit 5 Factory Unit: Sudden Death)", + "fact2 (Unit 5 Factory Unit: Processing Plant)", + "power1 (Unit 6 Power Unit/Big Gun: Power Plant)", + "power2 (Unit 6 Power Unit/Big Gun: The Reactor)", + "cool1 (Unit 6 Power Unit/Big Gun: Cooling Facility)", + "waste1 (Unit 6 Power Unit/Big Gun: Toxic Waste Dump)", + "waste2 (Unit 6 Power Unit/Big Gun: Pumping Station 1)", + "waste3 (Unit 6 Power Unit/Big Gun: Pumping Station 2)", + "biggun (Unit 6 Power Unit/Big Gun: Big Gun)", + "hangar1 (Unit 7 Hangar Unit: Outer Hangar)", + "space (Unit 7 Hangar Unit: Comm Satelite)", + "lab (Unit 7 Hangar Unit: Research Lab)", + "hangar2 (Unit 7 Hangar Unit: Inner Hangar)", + "command (Unit 7 Hangar Unit: Launch Command)", + "strike (Unit 7 Hangar Unit: Outlands)", + "city1 (Unit 8 City Unit: Outer Courts)", + "city2 (Unit 8 City Unit: Lower Palace)", + "city3 (Unit 8 City Unit: Upper Palace)", + "boss1 (Unit 9 Boss Levels: Inner Chamber)", + "boss2 (Unit 9 Boss Levels: Final Showdown)", + NULL +}; + +qboolean M_Apply_SP_Cheats (union menuoption_s *op,struct menu_s *menu,int key) +{ + singleplayerinfo_t *info = menu->data; + + if (key != K_ENTER) + return false; + + switch(info->skillcombo->selectedoption) + { + case 0: + Cbuf_AddText("skill 0\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("skill 1\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("skill 2\n", RESTRICT_LOCAL); + break; + case 3: + Cbuf_AddText("skill 3\n", RESTRICT_LOCAL); + break; + } + + if ((unsigned int)info->mapcombo->selectedoption >= sizeof(maplist_q1)/sizeof(maplist_q1[0])) + Cbuf_AddText(va("map %s\n", maplist_q1[info->mapcombo->selectedoption]), RESTRICT_LOCAL); + + M_RemoveMenu(menu); + Cbuf_AddText("menu_spcheats\n", RESTRICT_LOCAL); + return true; +} + + +void M_Menu_Singleplayer_Cheats_f (void) +{ + static const char *skilloptions[] = + { + "Easy", + "Normal", + "Hard", + "Nightmare", + "None Set", + NULL + }; + + singleplayerinfo_t *info; + int cursorpositionY; + #ifndef CLIENTONLY + int currentskill; + int currentmap; + extern cvar_t sv_gravity, sv_cheats, sv_maxspeed, skill; + extern cvar_t host_mapname; + #endif + int y; + menu_t *menu = M_Options_Title(&y, sizeof(*info)); + info = menu->data; + + cursorpositionY = (y + 24); + + #ifndef CLIENTONLY + currentskill = skill.value; + if ( !currentskill ) + currentskill = 4; // no skill selected + + for (currentmap = sizeof(maplist_q1)/sizeof(maplist_q1[0]) - 1; currentmap > 0; currentmap--) + if (!strcmp(host_mapname.string, maplist_q1[currentmap])) + break; + /*anything that doesn't match will end up with 0*/ + #endif + + MC_AddRedText(menu, 16, y, " Quake Singleplayer Cheats", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", 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; + #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; + #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; + #ifndef CLIENTONLY + MC_AddSlider(menu, 16, 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; + MC_AddConsoleCommand(menu, 16, y, "No Enemy Targetting", "notarget\n"); y+=8; + #ifndef CLIENTONLY + MC_AddConsoleCommand(menu, 16, y, " Restart Map", "restart\n"); y+=8; + #else + MC_AddConsoleCommand(menu, 16, y, " Suicide", "kill\n"); y+=8; + #endif + + y+=8; + MC_AddCommand(menu, 16, y, " Apply Changes", M_Apply_SP_Cheats); y+=8; + + menu->selecteditem = (union menuoption_s *)info->skillcombo; + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 170, cursorpositionY, NULL, false); +} + +// Quake 2 + +typedef struct { +menucombo_t *skillcombo; +menucombo_t *mapcombo; +} singleplayerq2info_t; + +qboolean M_Apply_SP_Cheats_Q2 (union menuoption_s *op,struct menu_s *menu,int key) +{ + singleplayerq2info_t *info = menu->data; + + if (key != K_ENTER) + return false; + + switch(info->skillcombo->selectedoption) + { + case 0: + Cbuf_AddText("skill 0\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("skill 1\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("skill 2\n", RESTRICT_LOCAL); + break; + } + + if ((unsigned int)info->mapcombo->selectedoption >= sizeof(maplist_q2)/sizeof(maplist_q2[0])) + Cbuf_AddText(va("map %s\n", maplist_q2[info->mapcombo->selectedoption]), RESTRICT_LOCAL); + + M_RemoveMenu(menu); + Cbuf_AddText("menu_quake2_spcheats\n", RESTRICT_LOCAL); + return true; +} + + +void M_Menu_Singleplayer_Cheats_Quake2_f (void) +{ + + static const char *skilloptions[] = + { + "Easy", + "Normal", + "Hard", + "None Set", + NULL + }; + + singleplayerq2info_t *info; + int cursorpositionY; + #ifndef MINIMAL + int currentskill; + int currentmap; + extern cvar_t sv_gravity, sv_cheats, sv_maxspeed, skill; + extern cvar_t host_mapname; + #endif + int y; + menu_t *menu = M_Options_Title(&y, sizeof(*info)); + info = menu->data; + + cursorpositionY = (y + 24); + + #ifndef MINIMAL + currentskill = skill.value; + + if ( !currentskill ) + currentskill = 4; // no skill selected + + for (currentmap = sizeof(maplist_q2)/sizeof(maplist_q2[0]) - 1; currentmap > 0; currentmap--) + if (!strcmp(host_mapname.string, maplist_q2[currentmap])) + break; + /*anything that doesn't match will end up with 0*/ + #endif + + MC_AddRedText(menu, 16, y, " Quake2 Singleplayer Cheats", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", 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; + #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; + #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; + #ifndef CLIENTONLY + MC_AddSlider(menu, 16, 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; + MC_AddConsoleCommand(menu, 16, y, " Blue & Red Key", "give blue key\ngive red key\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Pyramid Key", "give pyramid key\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, "All Weapons & Items", "give all\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Data Spinner", "give data spinner\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Power Cube", "give power cube\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Data CD", "give data cd\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Ammo Pack", "give ammo pack\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Bandolier", "give bandolier\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Adrenaline", "give adrenaline\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Ancient Head", "give ancient head\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Environment Suit", "give environment suit\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Rebreather", "give rebreather\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Invulnerability", "give invulnerability\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Silencer", "give silencer\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Power Shield", "give power shield\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Commander's Head", "give commander's head\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Security Pass", "give security pass\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Airstrike Marker", "give airstrike marker\n"); y+=8; + #ifndef CLIENTONLY + MC_AddConsoleCommand(menu, 16, y, " Restart Map", va("restart\n")); y+=8; + #endif + + y+=8; + MC_AddCommand(menu, 16, y, " Apply Changes", M_Apply_SP_Cheats_Q2); y+=8; + + menu->selecteditem = (union menuoption_s *)info->skillcombo; + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 170, cursorpositionY, NULL, false); +} + +// Hexen 2 + +// Quake 2 + +typedef struct { +menucombo_t *skillcombo; +menucombo_t *mapcombo; +} singleplayerh2info_t; + +qboolean M_Apply_SP_Cheats_H2 (union menuoption_s *op,struct menu_s *menu,int key) +{ + singleplayerh2info_t *info = menu->data; + + if (key != K_ENTER) + return false; + + switch(info->skillcombo->selectedoption) + { + case 0: + Cbuf_AddText("skill 0\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("skill 1\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("skill 2\n", RESTRICT_LOCAL); + break; + case 3: + Cbuf_AddText("skill 3\n", RESTRICT_LOCAL); + break; + } + + switch(info->mapcombo->selectedoption) + { + case 0: + Cbuf_AddText("map demo1\n", RESTRICT_LOCAL); + break; + case 1: + Cbuf_AddText("map demo2\n", RESTRICT_LOCAL); + break; + case 2: + Cbuf_AddText("map demo3\n", RESTRICT_LOCAL); + break; + case 3: + Cbuf_AddText("map village1\n", RESTRICT_LOCAL); + break; + case 4: + Cbuf_AddText("map village2\n", RESTRICT_LOCAL); + break; + case 5: + Cbuf_AddText("map village3\n", RESTRICT_LOCAL); + break; + case 6: + Cbuf_AddText("map village4\n", RESTRICT_LOCAL); + break; + case 7: + Cbuf_AddText("map village5\n", RESTRICT_LOCAL); + break; + case 8: + Cbuf_AddText("map rider1a\n", RESTRICT_LOCAL); + break; + case 9: + Cbuf_AddText("map meso1\n", RESTRICT_LOCAL); + break; + case 10: + Cbuf_AddText("map meso2\n", RESTRICT_LOCAL); + break; + case 11: + Cbuf_AddText("map meso3\n", RESTRICT_LOCAL); + break; + case 12: + Cbuf_AddText("map meso4\n", RESTRICT_LOCAL); + break; + case 13: + Cbuf_AddText("map meso5\n", RESTRICT_LOCAL); + break; + case 14: + Cbuf_AddText("map meso6\n", RESTRICT_LOCAL); + break; + case 15: + Cbuf_AddText("map meso8\n", RESTRICT_LOCAL); + break; + case 16: + Cbuf_AddText("map meso9\n", RESTRICT_LOCAL); + break; + case 17: + Cbuf_AddText("map egypt1\n", RESTRICT_LOCAL); + break; + case 18: + Cbuf_AddText("map egypt2\n", RESTRICT_LOCAL); + break; + case 19: + Cbuf_AddText("map egypt3\n", RESTRICT_LOCAL); + break; + case 20: + Cbuf_AddText("map egypt4\n", RESTRICT_LOCAL); + break; + case 21: + Cbuf_AddText("map egypt5\n", RESTRICT_LOCAL); + break; + case 22: + Cbuf_AddText("map egypt6\n", RESTRICT_LOCAL); + break; + case 23: + Cbuf_AddText("map egypt7\n", RESTRICT_LOCAL); + break; + case 24: + Cbuf_AddText("map rider2c\n", RESTRICT_LOCAL); + break; + case 25: + Cbuf_AddText("map romeric1\n", RESTRICT_LOCAL); + break; + case 26: + Cbuf_AddText("map romeric2\n", RESTRICT_LOCAL); + break; + case 27: + Cbuf_AddText("map romeric3\n", RESTRICT_LOCAL); + break; + case 28: + Cbuf_AddText("map romeric4\n", RESTRICT_LOCAL); + break; + case 29: + Cbuf_AddText("map romeric5\n", RESTRICT_LOCAL); + break; + case 30: + Cbuf_AddText("map romeric6\n", RESTRICT_LOCAL); + break; + case 31: + Cbuf_AddText("map romeric7\n", RESTRICT_LOCAL); + break; + case 32: + Cbuf_AddText("map castle4\n", RESTRICT_LOCAL); + break; + case 33: + Cbuf_AddText("map castle5\n", RESTRICT_LOCAL); + break; + case 34: + Cbuf_AddText("map cath\n", RESTRICT_LOCAL); + break; + case 35: + Cbuf_AddText("map tower\n", RESTRICT_LOCAL); + break; + case 36: + Cbuf_AddText("map eidolon\n", RESTRICT_LOCAL); + break; + } + + M_RemoveMenu(menu); + Cbuf_AddText("menu_hexen2_spcheats\n", RESTRICT_LOCAL); + return true; +} + + +void M_Menu_Singleplayer_Cheats_Hexen2_f (void) +{ + + static const char *skilloptions[] = + { + "Easy", + "Normal", + "Hard", + "Nightmare", + "None Set", + NULL + }; + + static const char *mapoptions[] = + { + "demo1 (Blackmarsh: Hub 1 Blackmarsh)", + "demo2 (Barbican: Hub 1 Blackmarsh)", + "demo3 (The Mill: Hub 1 Blackmarsh)", + "village1 (King's Court: Hub 1 Blackmarsh)", + "village3 (Stables: Hub 1 Blackmarsh)", + "village2 (Inner Courtyard: Hub 1 Blackmarsh)", + "village4 (Palance Entrance: Hub 1 Blackmarsh)", + "village5 (The Forgotten Chapel: Hub 1 Blackmarsh)", + "rider1a (Famine's Domain: Hub 1 Blackmarsh)", + "meso1 (Palance of Columns: Hub 2 Mazaera)", + "meso2 (Plaza of the Sun: Hub 2 Mazaera)", + "meso3 (Square of the Stream: Hub 2 Mazaera)", + "meso4 (Tomb of the High Priest: Hub 2 Mazaera)", + "meso5 (Obelisk of the Moon: Hub 2 Mazaera)", + "meso6 (Court of 1000 Warriors: Hub 2 Mazaera)", + "meso8 (Bridge of Stars: Hub 2 Mazaera)", + "meso9 (Well of Souls: Hub 2 Mazaera)", + "egypt1 (Temple of Horus: Hub 3 Thysis)", + "egypt2 (Ancient Tempor of Nefertum: Hub 3 Thysis)", + "egypt3 (Tempor of Nefertum: Hub 3 Thysis)", + "egypt4 (Palace of the Pharaoh: Hub 3 Thysis", + "egypt5 (Pyramid of Anubus: Hub 3 Thysis)", + "egypt6 (Temple of Light: Hub 3 Thysis)", + "egypt7 (Shrine of Naos: Hub 3 Thysis)", + "rider2c (Pestilence's Lair: Hub 3 Thysis)", + "romeric1 (The Hall of Heroes: Hub 4 Septimus)", + "romeric2 (Gardens of Athena: Hub 4 Septimus)", + "romeric3 (Forum of Zeus: Hub 4 Septimus)", + "romeric4 (Baths of Demetrius: Hub 4 Septimus)", + "romeric5 (Temple of Mars: Hub 4 Septimus)", + "romeric6 (Coliseum of War: Hub 4 Septimus)", + "romeric7 (Reflecting Pool: Hub 4 Septimus)", + "castle4 (The Underhalls: Hub 5 Return to Blackmarsh)", + "castle5 (Eidolon's Ordeal: Hub 5 Return to Blackmarsh)", + "cath (Cathedral: Hub 5 Return to Blackmarsh)", + "tower (Tower of the Dark Mage: Hub 5 Return to Blackmarsh)", + "eidolon (Eidolon's Lair: Hub 5 Return to Blackmarsh)", + NULL + }; + + singleplayerh2info_t *info; + int cursorpositionY; + int currentmap; + #ifndef MINIMAL + int currentskill; + extern cvar_t sv_gravity, sv_cheats, sv_maxspeed, skill; + #endif + extern cvar_t host_mapname; + int y; + menu_t *menu = M_Options_Title(&y, sizeof(*info)); + info = menu->data; + + cursorpositionY = (y + 24); + + #ifndef MINIMAL + currentskill = skill.value; + + if ( !currentskill ) + currentskill = 4; // no skill selected + #endif + + if ( strcmp ( host_mapname.string, "" ) == 0) + currentmap = 0; + else if ( stricmp ( host_mapname.string, "demo1" ) == 0 ) + currentmap = 0; + else if ( stricmp ( host_mapname.string, "demo2" ) == 0 ) + currentmap = 1; + else if ( stricmp ( host_mapname.string, "demo3" ) == 0 ) + currentmap = 2; + else if ( stricmp ( host_mapname.string, "village1" ) == 0 ) + currentmap = 3; + else if ( stricmp ( host_mapname.string, "village2" ) == 0 ) + currentmap = 4; + else if ( stricmp ( host_mapname.string, "village3" ) == 0 ) + currentmap = 5; + else if ( stricmp ( host_mapname.string, "village4" ) == 0 ) + currentmap = 6; + else if ( stricmp ( host_mapname.string, "village5" ) == 0 ) + currentmap = 7; + else if ( stricmp ( host_mapname.string, "rider1a" ) == 0 ) + currentmap = 8; + else if ( stricmp ( host_mapname.string, "meso1" ) == 0 ) + currentmap = 9; + else if ( stricmp ( host_mapname.string, "meso2" ) == 0 ) + currentmap = 10; + else if ( stricmp ( host_mapname.string, "meso3" ) == 0 ) + currentmap = 11; + else if ( stricmp ( host_mapname.string, "meso4" ) == 0 ) + currentmap = 12; + else if ( stricmp ( host_mapname.string, "meso5" ) == 0 ) + currentmap = 13; + else if ( stricmp ( host_mapname.string, "meso6" ) == 0 ) + currentmap = 14; + else if ( stricmp ( host_mapname.string, "meso8" ) == 0 ) + currentmap = 15; + else if ( stricmp ( host_mapname.string, "meso9" ) == 0 ) + currentmap = 16; + else if ( stricmp ( host_mapname.string, "egypt1" ) == 0 ) + currentmap = 17; + else if ( stricmp ( host_mapname.string, "egypt2" ) == 0 ) + currentmap = 18; + else if ( stricmp ( host_mapname.string, "egypt3" ) == 0 ) + currentmap = 19; + else if ( stricmp ( host_mapname.string, "egypt4" ) == 0 ) + currentmap = 20; + else if ( stricmp ( host_mapname.string, "egypt5" ) == 0 ) + currentmap = 21; + else if ( stricmp ( host_mapname.string, "egypt6" ) == 0 ) + currentmap = 22; + else if ( stricmp ( host_mapname.string, "egypt7" ) == 0 ) + currentmap = 23; + else if ( stricmp ( host_mapname.string, "rider2c" ) == 0 ) + currentmap = 24; + else if ( stricmp ( host_mapname.string, "romeric1" ) == 0 ) + currentmap = 25; + else if ( stricmp ( host_mapname.string, "romeric2" ) == 0 ) + currentmap = 26; + else if ( stricmp ( host_mapname.string, "romeric3" ) == 0 ) + currentmap = 27; + else if ( stricmp ( host_mapname.string, "romeric4" ) == 0 ) + currentmap = 28; + else if ( stricmp ( host_mapname.string, "romeric5" ) == 0 ) + currentmap = 29; + else if ( stricmp ( host_mapname.string, "romeric6" ) == 0 ) + currentmap = 30; + else if ( stricmp ( host_mapname.string, "romeric7" ) == 0 ) + currentmap = 31; + else if ( stricmp ( host_mapname.string, "castle4" ) == 0 ) + currentmap = 32; + else if ( stricmp ( host_mapname.string, "castle5" ) == 0 ) + currentmap = 33; + else if ( stricmp ( host_mapname.string, "cath" ) == 0 ) + currentmap = 34; + else if ( stricmp ( host_mapname.string, "tower" ) == 0 ) + currentmap = 35; + else if ( stricmp ( host_mapname.string, "eidolon" ) == 0 ) + currentmap = 36; + else + currentmap = 0; + + MC_AddRedText(menu, 16, y, " Hexen2 Singleplayer Cheats", false); y+=8; + MC_AddWhiteText(menu, 16, y, " €‚ ", false); y+=8; + y+=8; +#ifndef MINIMAL +info->skillcombo = MC_AddCombo(menu,16, y, " Difficulty", skilloptions, currentskill); y+=8; +#endif +info->mapcombo = MC_AddCombo(menu,16, y, " Map", mapoptions, currentmap); y+=8; + #ifndef MINIMAL + MC_AddCheckBox(menu, 16, 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 MINIMAL + MC_AddSlider(menu, 16, 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; + #ifndef MINIMAL + MC_AddSlider(menu, 16, 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; + MC_AddConsoleCommand(menu, 16, y, " Change To Crusader (lvl3+)", "impulse 172\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, "Change to Necromancer (lvl3+)", "impulse 173\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Change to Assassin (lvl3+)", "impulse 174\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Remove Monsters", "impulse 35\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Freeze Monsters", "impulse 36\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Unfreeze Monsters", "impulse 37\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Increase Level By 1", "impulse 40\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Increase Experience", "impulse 41\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Display Co-ordinates", "impulse 42\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " All Weapons & Mana", "impulse 9\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " All Weapons & Mana & Items", "impulse 43\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " No Enemy Targetting", "notarget\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Enable Crosshair", "crosshair 1\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " 20 Of Each Artifact", "impulse 299\n"); y+=8; + MC_AddConsoleCommand(menu, 16, y, " Restart Map", "impulse 99\n"); y+=8; + + y+=8; + MC_AddCommand(menu, 16, y, " Apply Changes", M_Apply_SP_Cheats_H2); y+=8; + + menu->selecteditem = (union menuoption_s *)info->skillcombo; + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 250, cursorpositionY, NULL, false); } diff --git a/engine/client/menu.c b/engine/client/menu.c index aee33a5a..083c3603 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -700,6 +700,22 @@ void M_QuickConnect_f(void); void M_Menu_MediaFiles_f (void); void M_Menu_FPS_f (void); +void M_Menu_Shadow_Lighting_f (void); +void M_Menu_3D_f (void); +void M_Menu_Textures_f (void); +void M_Menu_Teamplay_f (void); +void M_Menu_Teamplay_Locations_f (void); +void M_Menu_Teamplay_Needs_f (void); +void M_Menu_Teamplay_Items_f (void); +void M_Menu_Teamplay_Items_Armor_f (void); +void M_Menu_Teamplay_Items_Weapons_f (void); +void M_Menu_Teamplay_Items_Powerups_f (void); +void M_Menu_Teamplay_Items_Ammo_Health_f (void); +void M_Menu_Teamplay_Items_Team_Fortress_f (void); +void M_Menu_Teamplay_Items_Status_Location_Misc_f (void); +void M_Menu_Singleplayer_Cheats_f (void); +void M_Menu_Singleplayer_Cheats_Quake2_f (void); +void M_Menu_Singleplayer_Cheats_Hexen2_f (void); void M_Menu_Particles_f (void); void M_Menu_ParticleSets_f (void); void M_Menu_Audio_Speakers_f (void); @@ -747,7 +763,23 @@ void M_Init_Internal (void) #ifndef __CYGWIN__ Cmd_AddRemCommand ("menu_speakers", M_Menu_Audio_Speakers_f); #endif + Cmd_AddRemCommand ("menu_spcheats", M_Menu_Singleplayer_Cheats_f); + Cmd_AddRemCommand ("menu_quake2_spcheats", M_Menu_Singleplayer_Cheats_Quake2_f); + Cmd_AddRemCommand ("menu_hexen2_spcheats", M_Menu_Singleplayer_Cheats_Hexen2_f); Cmd_AddRemCommand ("menu_fps", M_Menu_FPS_f); + Cmd_AddRemCommand ("menu_3d" , M_Menu_3D_f); + Cmd_AddRemCommand ("menu_shadow_lighting", M_Menu_Shadow_Lighting_f); + Cmd_AddRemCommand ("menu_textures", M_Menu_Textures_f); + Cmd_AddRemCommand ("menu_teamplay", M_Menu_Teamplay_f); + Cmd_AddRemCommand ("menu_teamplay_locations", M_Menu_Teamplay_Locations_f); + Cmd_AddRemCommand ("menu_teamplay_needs", M_Menu_Teamplay_Needs_f); + Cmd_AddRemCommand ("menu_teamplay_items", M_Menu_Teamplay_Items_f); + Cmd_AddRemCommand ("menu_teamplay_armor", M_Menu_Teamplay_Items_Armor_f); + Cmd_AddRemCommand ("menu_teamplay_weapons", M_Menu_Teamplay_Items_Weapons_f); + Cmd_AddRemCommand ("menu_teamplay_powerups", M_Menu_Teamplay_Items_Powerups_f); + Cmd_AddRemCommand ("menu_teamplay_ammo_health", M_Menu_Teamplay_Items_Ammo_Health_f); + Cmd_AddRemCommand ("menu_teamplay_team_fortress", M_Menu_Teamplay_Items_Team_Fortress_f); + Cmd_AddRemCommand ("menu_teamplay_status_location_misc", M_Menu_Teamplay_Items_Status_Location_Misc_f); Cmd_AddRemCommand ("menu_particles", M_Menu_Particles_f); Cmd_AddRemCommand ("menu_particlesets", M_Menu_ParticleSets_f); @@ -793,7 +825,23 @@ void M_DeInit_Internal (void) Cmd_RemoveCommand ("menu_video"); Cmd_RemoveCommand ("menu_audio"); Cmd_RemoveCommand ("menu_speakers"); + Cmd_RemoveCommand ("menu_teamplay"); + Cmd_RemoveCommand ("menu_teamplay_locations"); + Cmd_RemoveCommand ("menu_teamplay_needs"); + Cmd_RemoveCommand ("menu_teamplay_items"); + Cmd_RemoveCommand ("menu_teamplay_armor"); + Cmd_RemoveCommand ("menu_teamplay_weapons"); + Cmd_RemoveCommand ("menu_teamplay_powerups"); + Cmd_RemoveCommand ("menu_teamplay_ammo_health"); + Cmd_RemoveCommand ("menu_teamplay_team_fortress"); + Cmd_RemoveCommand ("menu_teamplay_status_location_misc"); + Cmd_RemoveCommand ("menu_spcheats"); + Cmd_RemoveCommand ("menu_hexen2_spcheats"); + Cmd_RemoveCommand ("menu_quake2_spcheats"); Cmd_RemoveCommand ("menu_fps"); + Cmd_RemoveCommand ("menu_3d"); + Cmd_RemoveCommand ("menu_shadow_lighting"); + Cmd_RemoveCommand ("menu_textures"); Cmd_RemoveCommand ("menu_particles"); Cmd_RemoveCommand ("menu_particlesets"); @@ -953,21 +1001,26 @@ void M_Keyup (int key, int unicode) // Generic function to choose which game menu to draw int M_GameType (void) { - int cached; + static int cached; + static unsigned int cachedrestarts; + + if (FS_Restarted(&cachedrestarts)) + { #if defined(Q2CLIENT) - int q1, h2, q2; + int q1, h2, q2; - q1 = COM_FDepthFile("gfx/sp_menu.lmp", true); - h2 = COM_FDepthFile("gfx/menu/title2.lmp", true); - q2 = COM_FDepthFile("pics/m_banner_game.pcx", true); + q1 = COM_FDepthFile("gfx/sp_menu.lmp", true); + h2 = COM_FDepthFile("gfx/menu/title2.lmp", true); + q2 = COM_FDepthFile("pics/m_banner_game.pcx", true); - if (q2 < h2 && q2 < q1) - cached = MGT_QUAKE2; - else if (h2 < q1) - cached = MGT_HEXEN2; - else + if (q2 < h2 && q2 < q1) + cached = MGT_QUAKE2; + else if (h2 < q1) + cached = MGT_HEXEN2; + else #endif - cached = MGT_QUAKE1; + cached = MGT_QUAKE1; + } return cached; } diff --git a/engine/client/menu.h b/engine/client/menu.h index 684ede98..82341caf 100644 --- a/engine/client/menu.h +++ b/engine/client/menu.h @@ -302,6 +302,7 @@ menuedit_t *MC_AddEditCvar(menu_t *menu, int x, int y, char *text, char *name); menucustom_t *MC_AddCustom(menu_t *menu, int x, int y, void *data); menucombo_t *MC_AddCvarCombo(menu_t *menu, int x, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values); +menu_t *M_Options_Title(int *y, int infosize); /*Create a menu with the default options titlebar*/ menu_t *M_CreateMenu (int extrasize); void M_AddMenu (menu_t *menu); void M_AddMenuFront (menu_t *menu); diff --git a/engine/client/merged.h b/engine/client/merged.h index 1b7b482f..96a23c3e 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -86,10 +86,6 @@ extern void (*R_PushDlights) (void); extern void (*R_AddStain) (vec3_t org, float red, float green, float blue, float radius); extern void (*R_LessenStains) (void); -extern void (*Media_ShowFrameBGR_24_Flip) (qbyte *framedata, int inwidth, int inheight); //input is bottom up... -extern void (*Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight); //top down -extern void (*Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, qbyte *palette); //paletted topdown (framedata is 8bit indexes into palette) - extern qboolean (*VID_Init) (rendererstate_t *info, unsigned char *palette); extern void (*VID_DeInit) (void); extern void (*VID_LockBuffer) (void); @@ -113,6 +109,17 @@ extern void SCR_SetUpToDrawConsole (void); extern void SCR_EraseCenterString (void); extern void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode); +void R_DrawTextField(int x, int y, int w, int h, char *text, unsigned int defaultmask, unsigned int fieldflags); +#define CPRINT_BALIGN (1<<0) //B +#define CPRINT_TALIGN (1<<1) //T +#define CPRINT_LALIGN (1<<2) //L +#define CPRINT_RALIGN (1<<3) //R +#define CPRINT_BACKGROUND (1<<4) //P + +#define CPRINT_OBITUARTY (1<<16) //O (show at 2/3rds from top) +#define CPRINT_PERSIST (1<<17) //P (doesn't time out) +#define CPRINT_TYPEWRITER (1<<18) // (char at a time) + #endif extern void FNC(Mod_Init) (void); @@ -188,10 +195,6 @@ typedef struct rendererinfo_s { void (*R_AddStain) (vec3_t org, float red, float green, float blue, float radius); void (*R_LessenStains) (void); - void (*Media_ShowFrameBGR_24_Flip) (qbyte *framedata, int inwidth, int inheight); //input is bottom up... - void (*Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight); //top down - void (*Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, qbyte *palette); //paletted topdown (framedata is 8bit indexes into palette) - void (*Mod_Init) (void); void (*Mod_ClearAll) (void); struct model_s *(*Mod_ForName) (char *name, qboolean crash); diff --git a/engine/client/p_classic.c b/engine/client/p_classic.c index 5516f916..145914d1 100644 --- a/engine/client/p_classic.c +++ b/engine/client/p_classic.c @@ -28,10 +28,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void D_DrawParticleTrans (vec3_t porg, float palpha, float pscale, unsigned int pcolour, blendmode_t blendmode); - -cvar_t gl_solidparticles = SCVAR("gl_solidparticles", "0"); - - typedef enum { DODGY, @@ -94,8 +90,8 @@ static union c unsigned int i; } classiccolours[BUFFERVERTS]; static vec2_t classictexcoords[BUFFERVERTS]; -index_t classicindexes[BUFFERVERTS]; -static mesh_t classicmesh; +static index_t classicindexes[BUFFERVERTS]; +mesh_t classicmesh; static shader_t *classicshader; @@ -184,7 +180,7 @@ static void PClassic_EmitSkyEffectTris(model_t *mod, msurface_t *fa) } //the one-time initialisation function, called no mater which renderer is active. -static void PClassic_InitParticles (void) +static qboolean PClassic_InitParticles (void) { int i; model_t *mod; @@ -238,6 +234,8 @@ static void PClassic_InitParticles (void) "}\n" ); classicshader->defaulttextures.base = particlecqtexture; + + return true; } static void PClassic_ShutdownParticles(void) @@ -296,7 +294,7 @@ static void PClassic_DrawParticles(void) VectorScale (vright, 1.5, right); frametime = host_frametime; - if (cl.paused) + if (cl.paused || r_secondaryview || r_refdef.recurse) frametime = 0; time3 = frametime * 15; time2 = frametime * 10; // 15; @@ -335,7 +333,7 @@ static void PClassic_DrawParticles(void) if (classicmesh.numvertexes >= BUFFERVERTS-3) { classicmesh.numindexes = classicmesh.numvertexes; - BE_DrawMeshChain(classicshader, &classicmesh, NULL, &classicshader->defaulttextures); + BE_DrawMesh_Single(classicshader, &classicmesh, NULL, &classicshader->defaulttextures); classicmesh.numvertexes = 0; } @@ -418,7 +416,7 @@ static void PClassic_DrawParticles(void) if (classicmesh.numvertexes) { classicmesh.numindexes = classicmesh.numvertexes; - BE_DrawMeshChain(classicshader, &classicmesh, NULL, &classicshader->defaulttextures); + BE_DrawMesh_Single(classicshader, &classicmesh, NULL, &classicshader->defaulttextures); classicmesh.numvertexes = 0; } diff --git a/engine/client/p_null.c b/engine/client/p_null.c index 59f138c3..8479ee40 100644 --- a/engine/client/p_null.c +++ b/engine/client/p_null.c @@ -47,7 +47,7 @@ static void PNULL_DrawParticles(void) RSpeedLocals(); RSpeedRemark(); - RQ_RenderDistAndClear(); + RQ_RenderBatchClear(); RSpeedEnd(RSPEED_PARTICLESDRAW); } diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 40775864..ec4a98d2 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -299,7 +299,6 @@ extern cvar_t r_part_sparks; extern cvar_t r_part_sparks_trifan; extern cvar_t r_part_sparks_textured; extern cvar_t r_part_beams; -extern cvar_t r_part_beams_textured; extern cvar_t r_part_contentswitch; static float particletime; @@ -1351,12 +1350,12 @@ static void P_PartInfo_f (void) R_InitParticles =============== */ -static void PScript_InitParticles (void) +static qboolean PScript_InitParticles (void) { int i; if (r_numparticles) //already inited - return; + return true; buildsintable(); @@ -1437,6 +1436,7 @@ static void PScript_InitParticles (void) pscripttmesh.st_array = pscripttexcoords; pscripttmesh.colors4f_array = pscriptcolours; pscripttmesh.indexes = pscripttriindexes; + return true; } static void PScript_Shutdown (void) @@ -3240,7 +3240,7 @@ static void GL_DrawTexturedParticle(int count, particle_t **plist, plooks_t *typ if (pscriptmesh.numvertexes >= BUFFERVERTS-4) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMeshChain(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); pscriptmesh.numvertexes = 0; } @@ -3298,7 +3298,7 @@ static void GL_DrawTexturedParticle(int count, particle_t **plist, plooks_t *typ if (pscriptmesh.numvertexes) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMeshChain(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); pscriptmesh.numvertexes = 0; } } @@ -3316,7 +3316,7 @@ static void GL_DrawTrifanParticle(int count, particle_t **plist, plooks_t *type) if (pscripttmesh.numvertexes >= BUFFERVERTS-3) { pscripttmesh.numindexes = pscripttmesh.numvertexes; - BE_DrawMeshChain(type->shader, &pscripttmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscripttmesh, NULL, &type->shader->defaulttextures); pscripttmesh.numvertexes = 0; } @@ -3352,7 +3352,7 @@ static void GL_DrawTrifanParticle(int count, particle_t **plist, plooks_t *type) if (pscripttmesh.numvertexes) { pscripttmesh.numindexes = pscripttmesh.numvertexes; - BE_DrawMeshChain(type->shader, &pscripttmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscripttmesh, NULL, &type->shader->defaulttextures); pscripttmesh.numvertexes = 0; } } @@ -3400,7 +3400,7 @@ static void GL_DrawTexturedSparkParticle(int count, particle_t **plist, plooks_t if (pscriptmesh.numvertexes >= BUFFERVERTS-4) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMeshChain(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); pscriptmesh.numvertexes = 0; } @@ -3439,7 +3439,7 @@ static void GL_DrawTexturedSparkParticle(int count, particle_t **plist, plooks_t if (pscriptmesh.numvertexes) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMeshChain(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); pscriptmesh.numvertexes = 0; } } @@ -3461,7 +3461,7 @@ static void GL_DrawParticleBeam(int count, beamseg_t **blist, plooks_t *type) if (pscriptmesh.numvertexes >= BUFFERVERTS-4) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMeshChain(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); pscriptmesh.numvertexes = 0; } @@ -3498,7 +3498,7 @@ static void GL_DrawParticleBeam(int count, beamseg_t **blist, plooks_t *type) if (pscriptmesh.numvertexes) { pscriptmesh.numindexes = pscriptmesh.numvertexes/4*6; - BE_DrawMeshChain(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); pscriptmesh.numvertexes = 0; } } @@ -3514,7 +3514,7 @@ static void GL_DrawClippedDecal(int count, clippeddecal_t **dlist, plooks_t *typ if (pscripttmesh.numvertexes >= BUFFERVERTS-3) { pscripttmesh.numindexes = pscripttmesh.numvertexes; - BE_DrawMeshChain(type->shader, &pscripttmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscripttmesh, NULL, &type->shader->defaulttextures); pscripttmesh.numvertexes = 0; } @@ -3537,15 +3537,13 @@ static void GL_DrawClippedDecal(int count, clippeddecal_t **dlist, plooks_t *typ if (pscriptmesh.numvertexes) { pscripttmesh.numindexes = pscripttmesh.numvertexes; - BE_DrawMeshChain(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); + BE_DrawMesh_Single(type->shader, &pscriptmesh, NULL, &type->shader->defaulttextures); pscripttmesh.numvertexes = 0; } } static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, particle_t **,plooks_t*), void (*sparklineparticles)(int count, particle_t **,plooks_t*), void (*sparkfanparticles)(int count, particle_t **,plooks_t*), void (*sparktexturedparticles)(int count, particle_t **,plooks_t*), void (*beamparticles)(int count, beamseg_t**,plooks_t*), void (*drawdecalparticles)(int count, clippeddecal_t**,plooks_t*)) { - RSpeedMark(); - qboolean (*tr) (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); void *pdraw, *bdraw; @@ -3565,6 +3563,7 @@ static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, part int traces=r_particle_tracelimit.ival; int rampind; + RSpeedMark(); if (r_plooksdirty) { @@ -3586,7 +3585,7 @@ static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, part } pframetime = host_frametime; - if (cl.paused || r_secondaryview) + if (cl.paused || r_secondaryview || r_refdef.recurse) pframetime = 0; VectorScale (vup, 1.5, pup); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 880b63fd..6b17650a 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -58,10 +58,10 @@ static qboolean csqc_isdarkplaces; static char csqc_printbuffer[8192]; #define CSQCPROGSGROUP "CSQC progs control" -cvar_t pr_csmaxedicts = SCVAR("pr_csmaxedicts", "3072"); //not tied to protocol nor server. -cvar_t cl_csqcdebug = SCVAR("cl_csqcdebug", "0"); //prints entity numbers which arrive (so I can tell people not to apply it to players...) -cvar_t cl_nocsqc = SCVAR("cl_nocsqc", "0"); -cvar_t pr_csqc_coreonerror = SCVAR("pr_csqc_coreonerror", "1"); +cvar_t pr_csmaxedicts = CVAR("pr_csmaxedicts", "3072"); //not tied to protocol nor server. +cvar_t cl_csqcdebug = CVAR("cl_csqcdebug", "0"); //prints entity numbers which arrive (so I can tell people not to apply it to players...) +cvar_t cl_nocsqc = CVAR("cl_nocsqc", "0"); +cvar_t pr_csqc_coreonerror = CVAR("pr_csqc_coreonerror", "1"); #define MASK_DELTA 1 @@ -153,7 +153,7 @@ typedef enum \ /*These are pointers to the csqc's globals.*/ \ globalfloat(svtime, "time"); /*float Written before entering most qc functions*/ \ - globalfloat(frametime, "frametime"); /*float Written before entering most qc functions*/ \ + globalfloat(frametime, "frametime"); /*float Written before entering most qc functions*/ \ globalfloat(cltime, "cltime"); /*float Written before entering most qc functions*/ \ globalentity(self, "self"); /*entity Written before entering most qc functions*/ \ globalentity(other, "other"); /*entity Written before entering most qc functions*/ \ @@ -777,11 +777,11 @@ static void PF_cs_makestatic (progfuncs_t *prinst, struct globalvars_s *pr_globa return; } - ent = &cl_static_entities[cl.num_statics]; + ent = &cl_static_entities[cl.num_statics].ent; if (CopyCSQCEdictToEntity(in, ent)) { + #pragma message("Link static entity") cl.num_statics++; - R_AddEfrags(ent); } PF_cs_remove(prinst, pr_globals); @@ -1352,7 +1352,7 @@ static void PF_R_GetViewFlag(progfuncs_t *prinst, struct globalvars_s *pr_global break; case VF_DRAWWORLD: - *r = !(r_refdef.flags&Q2RDF_NOWORLDMODEL);; + *r = !(r_refdef.flags&Q2RDF_NOWORLDMODEL); break; case VF_ENGINESBAR: *r = csqc_drawsbar; @@ -2373,6 +2373,11 @@ static void PF_cs_getplayerkey (progfuncs_t *prinst, struct globalvars_s *pr_glo ret = buffer; sprintf(ret, "%i", (int)cl.players[pnum].entertime); } + else if (!strcmp(keyname, "viewentity")) //compat with DP + { + ret = buffer; + sprintf(ret, "%i", pnum+1); + } else { ret = Info_ValueForKey(cl.players[pnum].userinfo, keyname); @@ -3103,7 +3108,7 @@ static void PF_cs_gecko_create (progfuncs_t *prinst, struct globalvars_s *pr_glo { char *shader = PR_GetStringOfs(prinst, OFS_PARM0); cin_t *cin; - cin = R_ShaderGetCinematic(shader); + cin = R_ShaderFindCinematic(shader); if (!cin) G_FLOAT(OFS_RETURN) = 0; @@ -3120,7 +3125,7 @@ static void PF_cs_gecko_navigate (progfuncs_t *prinst, struct globalvars_s *pr_g char *shader = PR_GetStringOfs(prinst, OFS_PARM0); char *command = PR_GetStringOfs(prinst, OFS_PARM1); cin_t *cin; - cin = R_ShaderGetCinematic(shader); + cin = R_ShaderFindCinematic(shader); if (!cin) return; @@ -3134,7 +3139,7 @@ static void PF_cs_gecko_keyevent (progfuncs_t *prinst, struct globalvars_s *pr_g int key = G_FLOAT(OFS_PARM1); int eventtype = G_FLOAT(OFS_PARM2); cin_t *cin; - cin = R_ShaderGetCinematic(shader); + cin = R_ShaderFindCinematic(shader); if (!cin) return; @@ -3147,7 +3152,7 @@ static void PF_cs_gecko_mousemove (progfuncs_t *prinst, struct globalvars_s *pr_ float posx = G_FLOAT(OFS_PARM1); float posy = G_FLOAT(OFS_PARM2); cin_t *cin; - cin = R_ShaderGetCinematic(shader); + cin = R_ShaderFindCinematic(shader); if (!cin) return; @@ -3160,7 +3165,7 @@ static void PF_cs_gecko_resize (progfuncs_t *prinst, struct globalvars_s *pr_glo float sizex = G_FLOAT(OFS_PARM1); float sizey = G_FLOAT(OFS_PARM2); cin_t *cin; - cin = R_ShaderGetCinematic(shader); + cin = R_ShaderFindCinematic(shader); if (!cin) return; Media_Send_Resize(cin, sizex, sizey); @@ -3172,7 +3177,7 @@ static void PF_cs_gecko_get_texture_extent (progfuncs_t *prinst, struct globalva float *ret = G_VECTOR(OFS_RETURN); int sx, sy; cin_t *cin; - cin = R_ShaderGetCinematic(shader); + cin = R_ShaderFindCinematic(shader); if (cin) { Media_Send_GetSize(cin, &sx, &sy); @@ -3553,7 +3558,7 @@ static void PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_globals G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1; } -//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone) skel_get_numbones (FTE_CSQC_SKELETONOBJECTS) +//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone) skel_build (FTE_CSQC_SKELETONOBJECTS) static void PF_skel_build(progfuncs_t *prinst, struct globalvars_s *pr_globals) { #define MAX_BONES 256 @@ -4845,20 +4850,20 @@ static struct { {"htos", PF_htos, 262}, {"skel_create", PF_skel_create, 263},//float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS) - {"skel_build", PF_skel_build, 264},//float(float skel, entity ent, float modlindex, float firstbone, float lastbone) skel_build = #263; // (FTE_CSQC_SKELETONOBJECTS) - {"skel_get_numbones", PF_skel_get_numbones, 265},//float(float skel) skel_get_numbones = #264; // (FTE_CSQC_SKELETONOBJECTS) - {"skel_get_bonename", PF_skel_get_bonename, 266},//string(float skel, float bonenum) skel_get_bonename = #265; // (FTE_CSQC_SKELETONOBJECTS) (returns tempstring) - {"skel_get_boneparent", PF_skel_get_boneparent, 267},//float(float skel, float bonenum) skel_get_boneparent = #266; // (FTE_CSQC_SKELETONOBJECTS) - {"skel_find_bone", PF_skel_find_bone, 268},//float(float skel, string tagname) skel_get_boneidx = #267; // (FTE_CSQC_SKELETONOBJECTS) - {"skel_get_bonerel", PF_skel_get_bonerel, 269},//vector(float skel, float bonenum) skel_get_bonerel = #268; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) - {"skel_get_boneabs", PF_skel_get_boneabs, 270},//vector(float skel, float bonenum) skel_get_boneabs = #269; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) - {"skel_set_bone", PF_skel_set_bone, 271},//void(float skel, float bonenum, vector org) skel_set_bone = #270; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_mul_bone", PF_skel_mul_bone, 272},//void(float skel, float bonenum, vector org) skel_mul_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_mul_bones", PF_skel_mul_bones, 273},//void(float skel, float startbone, float endbone, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_copybones", PF_skel_copybones, 274},//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones = #273; // (FTE_CSQC_SKELETONOBJECTS) - {"skel_delete", PF_skel_delete, 275},//void(float skel) skel_delete = #274; // (FTE_CSQC_SKELETONOBJECTS) - {"frameforname", PF_frameforname, 276},//void(float modidx, string framename) frameforname = #275 (FTE_CSQC_SKELETONOBJECTS) - {"frameduration", PF_frameduration, 277},//void(float modidx, float framenum) frameduration = #276 (FTE_CSQC_SKELETONOBJECTS) + {"skel_build", PF_skel_build, 264},//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_get_numbones", PF_skel_get_numbones, 265},//float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_get_bonename", PF_skel_get_bonename, 266},//string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) (returns tempstring) + {"skel_get_boneparent", PF_skel_get_boneparent, 267},//float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_find_bone", PF_skel_find_bone, 268},//float(float skel, string tagname) skel_get_boneidx = #268; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_get_bonerel", PF_skel_get_bonerel, 269},//vector(float skel, float bonenum) skel_get_bonerel = #269; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) + {"skel_get_boneabs", PF_skel_get_boneabs, 270},//vector(float skel, float bonenum) skel_get_boneabs = #270; // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) + {"skel_set_bone", PF_skel_set_bone, 271},//void(float skel, float bonenum, vector org) skel_set_bone = #271; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_mul_bone", PF_skel_mul_bone, 272},//void(float skel, float bonenum, vector org) skel_mul_bone = #272; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_mul_bones", PF_skel_mul_bones, 273},//void(float skel, float startbone, float endbone, vector org) skel_mul_bone = #273; // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_copybones", PF_skel_copybones, 274},//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones = #274; // (FTE_CSQC_SKELETONOBJECTS) + {"skel_delete", PF_skel_delete, 275},//void(float skel) skel_delete = #275; // (FTE_CSQC_SKELETONOBJECTS) + {"frameforname", PF_frameforname, 276},//void(float modidx, string framename) frameforname = #276 (FTE_CSQC_SKELETONOBJECTS) + {"frameduration", PF_frameduration, 277},//void(float modidx, float framenum) frameduration = #277 (FTE_CSQC_SKELETONOBJECTS) //300 {"clearscene", PF_R_ClearScene, 300}, // #300 void() clearscene (EXT_CSQC) @@ -4882,9 +4887,9 @@ static struct { // {"?", PF_Fixme, 312}, // #312 // {"?", PF_Fixme, 313}, // #313 -// {"?", PF_Fixme, 314}, // #314 //2d (immediate) operations +// {"drawtextfield", PF_CL_DrawTextField, 314}, {"drawline", PF_CL_drawline, 315}, // #315 void(float width, vector pos1, vector pos2) drawline (EXT_CSQC) {"iscachedpic", PF_CL_is_cached_pic, 316}, // #316 float(string name) iscachedpic (EXT_CSQC) {"precache_pic", PF_CL_precache_pic, 317}, // #317 string(string name, float trywad) precache_pic (EXT_CSQC) @@ -5139,8 +5144,14 @@ static struct { //DP_QC_URI_GET {"uri_get", PF_uri_get, 513}, // #513 float(string uril, float id) uri_get - {"keynumtostring", PF_cl_keynumtostring, 520}, // #520 - {"findkeysforcommand", PF_cl_findkeysforcommand, 521}, // #521 + {"tokenize_console", PF_tokenize_console, 514}, + {"argv_start_index", PF_argv_start_index, 515}, + {"argv_end_index", PF_argv_end_index, 516}, + {"buf_cvarlist", PF_buf_cvarlist, 517}, + {"cvar_description", PF_cvar_description, 518}, + + {"keynumtostring", PF_cl_keynumtostring, 520}, + {"findkeysforcommand", PF_cl_findkeysforcommand, 521}, {NULL} }; @@ -5499,14 +5510,10 @@ qboolean CSQC_Init (unsigned int checksum) csqcentsize = PR_InitEnts(csqcprogs, pr_csmaxedicts.value); ED_Alloc(csqcprogs); //we need a world entity. + //world edict becomes readonly worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0); - - worldent->readonly = true; worldent->isfree = false; - worldent->v->modelindex = 1; - worldent->v->model = PR_SetString(csqcprogs, cl.model_name[(int)worldent->v->modelindex]); - worldent->v->solid = SOLID_BSP; str = (string_t*)csqcprogs->GetEdictFieldValue(csqcprogs, (edict_t*)worldent, "message", NULL); if (str) @@ -5539,6 +5546,8 @@ qboolean CSQC_Init (unsigned int checksum) void CSQC_WorldLoaded(void) { + csqcedict_t *worldent; + if (!csqcprogs) return; if (csqcmapentitydataloaded) @@ -5551,9 +5560,16 @@ void CSQC_WorldLoaded(void) World_Physics_Start(&csqc_world); #endif + worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0); + worldent->v->modelindex = 1; + worldent->v->model = PR_SetString(csqcprogs, cl.model_name[(int)worldent->v->modelindex]); + worldent->v->solid = SOLID_BSP; + if (csqcg.worldloaded) PR_ExecuteProgram(csqcprogs, csqcg.worldloaded); csqcmapentitydata = NULL; + + worldent->readonly = true; } void CSQC_CoreDump(void) @@ -5911,16 +5927,23 @@ qboolean CSQC_ParsePrint(char *message, int printlevel) return true; } -qboolean CSQC_StuffCmd(int lplayernum, char *cmd) +qboolean CSQC_StuffCmd(int lplayernum, char *cmd, char *cmdend) { void *pr_globals; + char tmp[2]; if (!csqcprogs || !csqcg.parse_stuffcmd) return false; CSQC_ChangeLocalPlayer(lplayernum); pr_globals = PR_globals(csqcprogs, PR_CURRENT); + tmp[0] = cmdend[0]; + tmp[1] = cmdend[1]; + cmdend[0] = '\n'; + cmdend[1] = 0; (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, cmd)); + cmdend[0] = tmp[0]; + cmdend[1] = tmp[1]; PR_ExecuteProgram (csqcprogs, csqcg.parse_stuffcmd); return true; @@ -6062,7 +6085,7 @@ void CSQC_ParseEntities(void) CSQC_EntityCheck(entnum); - if (cl_csqcdebug.value) + if (cl_csqcdebug.ival) Con_Printf("Remove %i\n", entnum); ent = csqcent[entnum]; @@ -6098,13 +6121,13 @@ void CSQC_ParseEntities(void) ent->xv->entnum = entnum; G_FLOAT(OFS_PARM0) = true; - if (cl_csqcdebug.value) + if (cl_csqcdebug.ival) Con_Printf("Add %i\n", entnum); } else { G_FLOAT(OFS_PARM0) = false; - if (cl_csqcdebug.value) + if (cl_csqcdebug.ival) Con_Printf("Update %i\n", entnum); } diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index db7ef353..bc7445c2 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -328,7 +328,14 @@ void PF_CL_drawresetcliparea (progfuncs_t *prinst, struct globalvars_s *pr_globa G_FLOAT(OFS_RETURN) = 0; } - +void PF_CL_DrawTextField (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *pos = G_VECTOR(OFS_PARM0); + float *size = G_VECTOR(OFS_PARM1); + unsigned int flags = G_FLOAT(OFS_PARM2); + char *text = PR_GetStringOfs(prinst, OFS_PARM3); + R_DrawTextField(pos[0], pos[1], size[0], size[1], text, CON_WHITEMASK, flags); +} //float drawstring(vector position, string text, vector scale, float alpha, float flag) = #455; void PF_CL_drawcolouredstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -336,16 +343,29 @@ void PF_CL_drawcolouredstring (progfuncs_t *prinst, struct globalvars_s *pr_glob float *pos = G_VECTOR(OFS_PARM0); char *text = PR_GetStringOfs(prinst, OFS_PARM1); float *size = G_VECTOR(OFS_PARM2); -// float *alpha = G_FLOAT(OFS_PARM3); + float alpha = G_FLOAT(OFS_PARM3); // float flag = G_FLOAT(OFS_PARM4); + conchar_t buffer[2048], *str; + float px, py; + if (!text) { G_FLOAT(OFS_RETURN) = -1; //was null.. return; } - Draw_FunString(pos[0], pos[1], text); + COM_ParseFunString(CON_WHITEMASK, text, buffer, sizeof(buffer), false); + str = buffer; + + Font_BeginScaledString(font_conchar, pos[0], pos[1], &px, &py); + Font_ForceColour(1, 1, 1, alpha); + while(*str) + { + px = Font_DrawScaleChar(px, py, size[0], size[1], *str++); + } + Font_InvalidateColour(); + Font_EndString(font_conchar); } void PF_CL_stringwidth(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -503,7 +523,7 @@ void PF_CL_drawcharacter (progfuncs_t *prinst, struct globalvars_s *pr_globals) float alpha = G_FLOAT(OFS_PARM4); // float flag = G_FLOAT(OFS_PARM5); - int x, y; + float x, y; if (!chara) { @@ -511,10 +531,9 @@ void PF_CL_drawcharacter (progfuncs_t *prinst, struct globalvars_s *pr_globals) return; } -#pragma message("fixme: this doesn't scale") - Font_BeginString(font_conchar, pos[0], pos[1], &x, &y); + Font_BeginScaledString(font_conchar, pos[0], pos[1], &x, &y); Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha); - Font_DrawChar(x, y, CON_WHITEMASK | 0xe000|(chara&0xff)); + Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK | 0xe000|(chara&0xff)); Font_InvalidateColour(); Font_EndString(font_conchar); @@ -529,7 +548,7 @@ void PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) float *rgb = G_VECTOR(OFS_PARM3); float alpha = G_FLOAT(OFS_PARM4); // float flag = G_FLOAT(OFS_PARM5); - int x, y; + float x, y; if (!text) { @@ -537,12 +556,11 @@ void PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) return; } -#pragma message("fixme: this doesn't scale") - Font_BeginString(font_conchar, pos[0], pos[1], &x, &y); + Font_BeginScaledString(font_conchar, pos[0], pos[1], &x, &y); Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha); while(*text) { - x = Font_DrawChar(x, y, CON_WHITEMASK|0xe000|(*text++&0xff)); + x = Font_DrawScaleChar(x, y, size[0], size[1], CON_WHITEMASK|0xe000|(*text++&0xff)); } Font_InvalidateColour(); Font_EndString(font_conchar); @@ -1125,6 +1143,17 @@ void PF_M_getextresponse(progfuncs_t *prinst, struct globalvars_s *pr_globals) //this does something weird G_INT(OFS_RETURN) = 0; } + +void PF_netaddress_resolve(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *address = PR_GetStringOfs(prinst, OFS_PARM0); + netadr_t adr; + char result[256]; + if (NET_StringToAdr(address, &adr)) + RETURN_TSTRING(NET_AdrToString (result, sizeof(result), adr)); + else + RETURN_TSTRING(""); +} #else void PF_gethostcachevalue (progfuncs_t *prinst, struct globalvars_s *pr_globals){G_FLOAT(OFS_RETURN) = 0;} @@ -1595,7 +1624,7 @@ builtin_t menu_builtins[] = { //480 PF_strtolower, // #480 string(string s) VM_strtolower : DRESK - Return string as lowercase PF_strtoupper, // #481 string(string s) VM_strtoupper : DRESK - Return string as uppercase - skip1 // #482 + PF_cvar_defstring, // #482 skip1 // #483 PF_strreplace, // #484 string(string search, string replace, string subject) strreplace (DP_QC_STRREPLACE) PF_strireplace, // #485 string(string search, string replace, string subject) strireplace (DP_QC_STRREPLACE) @@ -1633,11 +1662,11 @@ builtin_t menu_builtins[] = { PF_uri_unescape, // #511 string(string in) uri_unescape = #511; PF_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT) PF_uri_get, // #513 float(string uril, float id) uri_get = #513; (DP_QC_URI_GET) - skip1 // #514 - skip1 // #515 - skip1 // #516 - skip1 // #517 - skip1 // #518 + PF_tokenize_console, // #514 + PF_argv_start_index, // #515 + PF_argv_end_index, // #516 + PF_buf_cvarlist, // #517 + PF_cvar_description, // #518 skip1 // #519 //520 @@ -1672,7 +1701,8 @@ builtin_t menu_builtins[] = { PF_M_gethostcachenumber, PF_M_gethostcacheindexforkey, PF_M_addwantedhostcachekey, - PF_M_getextresponse // #624 + PF_M_getextresponse, // #624 + PF_netaddress_resolve }; int menu_numbuiltins = sizeof(menu_builtins)/sizeof(menu_builtins[0]); diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 385ff4cb..8c0154de 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -22,8 +22,7 @@ extern cvar_t scr_conalpha; extern cvar_t gl_conback; extern cvar_t gl_font; extern cvar_t gl_contrast; - -void R2D_Conback_Callback(struct cvar_s *var, char *oldvalue); +extern cvar_t vid_conautoscale; //We need this for minor things though, so we'll just use the slow accurate method. @@ -61,6 +60,8 @@ Image loading code must be ready for use at this point. */ void R2D_Init(void) { + conback = NULL; + Shader_Init(); BE_Init(); @@ -77,13 +78,6 @@ void R2D_Init(void) #pragma message("Fixme: move conwidth handling into here") - - if (font_conchar) - Font_Free(font_conchar); - font_conchar = Font_LoadFont(8*vid.pixelheight/vid.height, gl_font.string); - if (!font_conchar && *gl_font.string) - font_conchar = Font_LoadFont(8*vid.pixelheight/vid.height, ""); - missing_texture = R_LoadTexture8("no_texture", 16, 16, (unsigned char*)r_notexture_mip + r_notexture_mip->offsets[0], IF_NOALPHA|IF_NOGAMMA, 0); draw_backtile = Draw_SafePicFromWad ("backtile"); @@ -127,7 +121,9 @@ void R2D_Init(void) "}\n" ); - Cvar_Hook(&gl_conback, R2D_Conback_Callback); + Cvar_ForceCallback(&gl_conback); + Cvar_ForceCallback(&vid_conautoscale); + Cvar_ForceCallback(&gl_font); } mpic_t *R2D_SafeCachePic (char *path) @@ -206,7 +202,7 @@ void R2D_Image(float x, float y, float w, float h, float s1, float t1, float s2, draw_mesh_st[3][0] = s1; draw_mesh_st[3][1] = t2; - BE_DrawMeshChain(pic, &draw_mesh, NULL, &pic->defaulttextures); + BE_DrawMesh_Single(pic, &draw_mesh, NULL, &pic->defaulttextures); } /*draws a block of the current colour on the screen*/ @@ -225,9 +221,9 @@ void R2D_FillBlock(int x, int y, int w, int h) draw_mesh_xyz[3][1] = y+h; if (draw_mesh_colors[0][3] != 1) - BE_DrawMeshChain(draw_fill_trans, &draw_mesh, NULL, &draw_fill_trans->defaulttextures); + BE_DrawMesh_Single(draw_fill_trans, &draw_mesh, NULL, &draw_fill_trans->defaulttextures); else - BE_DrawMeshChain(draw_fill, &draw_mesh, NULL, &draw_fill->defaulttextures); + BE_DrawMesh_Single(draw_fill, &draw_mesh, NULL, &draw_fill->defaulttextures); } void R2D_ScalePic (int x, int y, int width, int height, mpic_t *pic) @@ -261,8 +257,8 @@ void R2D_ConsoleBackground (int firstline, int lastline, qboolean forceopaque) if (!conback) return; - w = vid.conwidth; - h = vid.conheight; + w = vid.width; + h = vid.height; if (forceopaque) { @@ -284,19 +280,19 @@ void R2D_ConsoleBackground (int firstline, int lastline, qboolean forceopaque) if (a >= 1) { R2D_ImageColours(1, 1, 1, 1); - R2D_ScalePic(0, lastline-(int)vid.conheight, w, h, conback); + R2D_ScalePic(0, lastline-(int)vid.height, w, h, conback); } else { R2D_ImageColours(1, 1, 1, a); - R2D_ScalePic (0, lastline - (int)vid.conheight, w, h, conback); + R2D_ScalePic (0, lastline - (int)vid.height, w, h, conback); R2D_ImageColours(1, 1, 1, 1); } } void R2D_EditorBackground (void) { - R2D_ScalePic(0, 0, vid.conwidth, vid.conheight, conback); + R2D_ScalePic(0, 0, vid.width, vid.height, conback); } /* @@ -338,17 +334,33 @@ void R2D_TileClear (int x, int y, int w, int h) draw_mesh_st[3][0] = newsl; draw_mesh_st[3][1] = newth; - BE_DrawMeshChain(draw_backtile, &draw_mesh, NULL, NULL); + BE_DrawMesh_Single(draw_backtile, &draw_mesh, NULL, NULL); } void R2D_Conback_Callback(struct cvar_s *var, char *oldvalue) { if (*var->string) conback = R_RegisterPic(var->string); - if (!conback) + if (!conback || !conback->width) + { conback = R_RegisterCustom("console", NULL, NULL); - if (!conback) - conback = R_RegisterPic("gfx/conback.lmp"); + if (!conback) + { + if (M_GameType() == MGT_QUAKE2) + conback = R_RegisterPic("pics/conback.pcx"); + else + conback = R_RegisterPic("gfx/conback.lmp"); + } + } +} + +void R2D_Font_Callback(struct cvar_s *var, char *oldvalue) +{ + if (font_conchar) + Font_Free(font_conchar); + font_conchar = Font_LoadFont(8*vid.pixelheight/vid.height, var->string); + if (!font_conchar && *var->string) + font_conchar = Font_LoadFont(8*vid.pixelheight/vid.height, ""); } diff --git a/engine/client/r_efrag.c b/engine/client/r_efrag.c deleted file mode 100644 index 1d21ec11..00000000 --- a/engine/client/r_efrag.c +++ /dev/null @@ -1,265 +0,0 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_efrag.c - -#include "quakedef.h" - -extern int r_framecount; - -mnode_t *r_pefragtopnode; - - -//=========================================================================== - -/* -=============================================================================== - - ENTITY FRAGMENT FUNCTIONS - -=============================================================================== -*/ - -efrag_t **lastlink; - -vec3_t r_emins, r_emaxs; - -entity_t *r_addent; - - -/* -================ -R_RemoveEfrags - -Call when removing an object from the world or moving it to another position -================ -*/ -void R_RemoveEfrags (entity_t *ent) -{ - efrag_t *ef, *old, *walk, **prev; - - ef = ent->efrag; - - while (ef) - { - prev = &ef->leaf->efrags; - while (1) - { - walk = *prev; - if (!walk) - break; - if (walk == ef) - { // remove this fragment - *prev = ef->leafnext; - break; - } - else - prev = &walk->leafnext; - } - - old = ef; - ef = ef->entnext; - - // put it on the free list - old->entnext = cl.free_efrags; - cl.free_efrags = old; - } - - ent->efrag = NULL; -} - -/* -=================== -R_SplitEntityOnNode -=================== -*/ -void R_Q1Q2BSP_SplitEntityOnNode (mnode_t *node) -{ - efrag_t *ef; - mplane_t *splitplane; - mleaf_t *leaf; - int sides; - - if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3) - { - if (node->contents & Q2CONTENTS_SOLID) - { - return; - } - } - else - { - if (node->contents == Q1CONTENTS_SOLID) - { - return; - } - } - -// add an efrag if the node is a leaf - - if ( node->contents < 0) - { - if (!r_pefragtopnode) - r_pefragtopnode = node; - - leaf = (mleaf_t *)node; - -// grab an efrag off the free list - ef = cl.free_efrags; - if (!ef) - { - Con_Printf ("Too many efrags!\n"); - return; // no free fragments... - } - cl.free_efrags = cl.free_efrags->entnext; - - ef->entity = r_addent; - -// add the entity link - *lastlink = ef; - lastlink = &ef->entnext; - ef->entnext = NULL; - -// set the leaf links - ef->leaf = leaf; - ef->leafnext = leaf->efrags; - leaf->efrags = ef; - - return; - } - -// NODE_MIXED - - splitplane = node->plane; - sides = BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane); - - if (sides == 3) - { - // split on this plane - // if this is the first splitter of this bmodel, remember it - if (!r_pefragtopnode) - r_pefragtopnode = node; - } - -// recurse down the contacted sides - if (sides & 1) - R_Q1Q2BSP_SplitEntityOnNode (node->children[0]); - - if (sides & 2) - R_Q1Q2BSP_SplitEntityOnNode (node->children[1]); -} - -/* -=========== -R_AddEfrags -=========== -*/ -void R_AddEfrags (entity_t *ent) -{ - model_t *entmodel; - int i; - - if (!ent->model) - return; - - if (ent == &r_worldentity) - return; // never add the world - - r_addent = ent; - - lastlink = &ent->efrag; - r_pefragtopnode = NULL; - - entmodel = ent->model; - - for (i=0 ; i<3 ; i++) - { - r_emins[i] = ent->origin[i] + entmodel->mins[i]; - r_emaxs[i] = ent->origin[i] + entmodel->maxs[i]; - } - - if (cl.worldmodel->nodes) - R_Q1Q2BSP_SplitEntityOnNode (cl.worldmodel->nodes); - - ent->topnode = r_pefragtopnode; -} - - -/* -================ -R_StoreEfrags - -// FIXME: a lot of this goes away with edge-based -================ -*/ -void R_StoreEfrags (efrag_t **ppefrag) -{ - entity_t *pent; - model_t *clmodel; - efrag_t *pefrag; - - extern cvar_t gl_part_flame; - extern cvar_t r_drawflame; - - while ((pefrag = *ppefrag) != NULL) - { - pent = pefrag->entity; - clmodel = pent->model; - - if ((!r_drawflame.ival) && (clmodel->engineflags & MDLF_FLAME)) - break; - -// switch (clmodel->type) -// { -// case mod_alias: -// case mod_brush: -// case mod_sprite: -// pent = pefrag->entity; - - if ((pent->visframe != r_framecount) && - (cl_numvisedicts < MAX_VISEDICTS)) - { - pent->framestate.g[FS_REG].frametime[0] = cl.time; - pent->framestate.g[FS_REG].frametime[1] = cl.time; - cl_visedicts[cl_numvisedicts++] = *pent; - - // mark that we've recorded this entity for this frame - pent->visframe = r_framecount; - - // emit particles for statics (we don't need to cheat check statics) - if (clmodel->particleeffect >= 0 && gl_part_flame.ival) - { - // TODO: this is ugly.. assumes ent is in static entities, and subtracts - // pointer math to get an index to use in cl_static emit - // there needs to be a cleaner method for this - int i = (int)(pent - cl_static_entities); - P_EmitEffect(pent->origin, clmodel->particleeffect, &(cl_static_emit[i])); - } - } - - ppefrag = &pefrag->leafnext; -// break; - -// default: -// Con_Printf ("R_StoreEfrags: Bad entity type %d\n", clmodel->type); -// } - } -} - - diff --git a/engine/client/r_part.c b/engine/client/r_part.c index 45601d7f..ef17568e 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -62,12 +62,14 @@ void R_Grenadetrail_Callback(struct cvar_s *var, char *oldvalue) particleengine_t pe_null; particleengine_t pe_classic; particleengine_t pe_darkplaces; +particleengine_t pe_qmb; particleengine_t pe_script; particleengine_t *particlesystem[] = { &pe_script, &pe_darkplaces, + &pe_qmb, &pe_classic, &pe_null, NULL, @@ -100,32 +102,32 @@ void R_ParticleSystem_Callback(struct cvar_s *var, char *oldvalue) if (!pe) Sys_Error("No particle system available. Please recompile."); - pe->InitParticles(); + if (!pe->InitParticles()) + { + Con_Printf("Particlesystem %s failed to init\n", pe->name1); + pe = &pe_null; + pe->InitParticles(); + } pe->ClearParticles(); CL_RegisterParticles(); } -cvar_t r_rockettrail = SCVARFC("r_rockettrail", "1", CVAR_SEMICHEAT, R_Rockettrail_Callback); -cvar_t r_grenadetrail = SCVARFC("r_grenadetrail", "1", CVAR_SEMICHEAT, R_Grenadetrail_Callback); -#ifdef MINIMAL -//minimal builds get a different default. -cvar_t r_particlesystem = SCVARFC("r_particlesystem", "classic", CVAR_SEMICHEAT, R_ParticleSystem_Callback); -#else -cvar_t r_particlesystem = SCVARFC("r_particlesystem", "script", CVAR_SEMICHEAT, R_ParticleSystem_Callback); -#endif -cvar_t r_particlesdesc = SCVARF("r_particlesdesc", "spikeset tsshaft", CVAR_SEMICHEAT); +cvar_t r_rockettrail = CVARFC("r_rockettrail", "1", CVAR_SEMICHEAT, R_Rockettrail_Callback); +cvar_t r_grenadetrail = CVARFC("r_grenadetrail", "1", CVAR_SEMICHEAT, R_Grenadetrail_Callback); +cvar_t r_particlesystem = CVARFC("r_particlesystem", IFMINIMAL("classic", "script"), CVAR_SEMICHEAT, R_ParticleSystem_Callback); +cvar_t r_particlesdesc = CVARF("r_particlesdesc", "spikeset tsshaft", CVAR_SEMICHEAT); extern cvar_t r_bouncysparks; extern cvar_t r_part_rain; extern cvar_t r_bloodstains; extern cvar_t gl_part_flame; -cvar_t r_part_rain_quantity = SCVAR("r_part_rain_quantity", "1"); +cvar_t r_part_rain_quantity = CVAR("r_part_rain_quantity", "1"); -cvar_t r_particle_tracelimit = SCVAR("r_particle_tracelimit", "250"); -cvar_t r_part_sparks = SCVAR("r_part_sparks", "1"); -cvar_t r_part_sparks_trifan = SCVAR("r_part_sparks_trifan", "1"); -cvar_t r_part_sparks_textured = SCVAR("r_part_sparks_textured", "1"); -cvar_t r_part_beams = SCVAR("r_part_beams", "1"); -cvar_t r_part_contentswitch = SCVAR("r_part_contentswitch", "1"); +cvar_t r_particle_tracelimit = CVAR("r_particle_tracelimit", "250"); +cvar_t r_part_sparks = CVAR("r_part_sparks", "1"); +cvar_t r_part_sparks_trifan = CVAR("r_part_sparks_trifan", "1"); +cvar_t r_part_sparks_textured = CVAR("r_part_sparks_textured", "1"); +cvar_t r_part_beams = CVAR("r_part_beams", "1"); +cvar_t r_part_contentswitch = CVAR("r_part_contentswitch", "1"); particleengine_t *pe; @@ -206,7 +208,8 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) if (len < bestlen) { bestlen = len; - VectorCopy (trace.plane.normal, normal); + if (normal) + VectorCopy (trace.plane.normal, normal); VectorAdd (pe->origin, trace.endpos, impact); } @@ -215,9 +218,12 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) if (trace.startsolid) { VectorNormalize(delta); - normal[0] = -delta[0]; - normal[1] = -delta[1]; - normal[2] = -delta[2]; + if (normal) + { + normal[0] = -delta[0]; + normal[1] = -delta[1]; + normal[2] = -delta[2]; + } VectorCopy (start, impact); return true; } diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 6e0f9157..fbb3f73f 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -32,7 +32,6 @@ static vec3_t modelorg; /*set before recursively entering the visible surface static qbyte areabits[MAX_Q2MAP_AREAS/8]; model_t *currentmodel; -mesh_t nullmesh; int lightmap_bytes; // 1, 3 or 4 qboolean lightmap_bgra; @@ -1795,10 +1794,6 @@ static qbyte *R_MarkLeafSurfaces_Q1 (void) *surf->mark = surf; } - - //deal with static ents. - if (leaf->efrags) - R_StoreEfrags (&leaf->efrags); } } @@ -1820,8 +1815,7 @@ static qbyte *R_MarkLeafSurfaces_Q1 (void) Surf_RenderDynamicLightmaps (surf, shift); tex->vbo.meshlist[j] = NULL; - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; + surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh; } } } @@ -1878,10 +1872,6 @@ start: (*mark++)->visframe = r_framecount; } while (--c); } - - // deal with model fragments in this leaf - if (pleaf->efrags) - R_StoreEfrags (&pleaf->efrags); return; } @@ -1937,9 +1927,7 @@ start: continue; // wrong side Surf_RenderDynamicLightmaps (surf, shift); - // if sorting by texture, just store it out - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; + surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh; } } } @@ -2046,8 +2034,7 @@ static void Surf_RecursiveQ2WorldNode (mnode_t *node) Surf_RenderDynamicLightmaps (surf, shift); - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; + surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh; } @@ -2114,10 +2101,6 @@ static void Surf_LeafWorldNode (void) surf->visframe = r_framecount; if (surf->mark) *surf->mark = surf; - /* - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf;# - */ } } while (--i); @@ -2141,8 +2124,7 @@ static void Surf_LeafWorldNode (void) if (surf) { tex->vbo.meshlist[j] = NULL; - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; + surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh; } } } @@ -2150,26 +2132,24 @@ static void Surf_LeafWorldNode (void) } #endif -static void Surf_ClearChains(void) -{ - int i; - for (i = 0; i < cl.worldmodel->numtextures; i++) - { - if (!cl.worldmodel->textures[i]) - continue; - cl.worldmodel->textures[i]->texturechain = NULL; - cl.worldmodel->textures[i]->texturechain_tail = &cl.worldmodel->textures[i]->texturechain; - } -} - static void Surf_CleanChains(void) { - int i; model_t *model = cl.worldmodel; + batch_t *batch; - for (i=0 ; inumtextures ; i++) + if (r_refdef.recurse) { - model->textures[i]->texturechain = NULL; + for (batch = model->batches; batch; batch = batch->next) + { + batch->meshes = batch->firstmesh; + } + } + else + { + for (batch = model->batches; batch; batch = batch->next) + { + batch->meshes = batch->firstmesh; + } } } @@ -2229,7 +2209,10 @@ void Surf_SetupFrame(void) { r_oldviewleaf = r_viewleaf; r_oldviewleaf2 = r_viewleaf2; - r_viewleaf = RMod_PointInLeaf (cl.worldmodel, r_origin); + if (r_refdef.recurse) + r_viewleaf = RMod_PointInLeaf (cl.worldmodel, r_refdef.pvsorigin); + else + r_viewleaf = RMod_PointInLeaf (cl.worldmodel, r_origin); if (!r_viewleaf) { @@ -2271,29 +2254,25 @@ R_DrawWorld void Surf_DrawWorld (void) { + int tmp; qbyte *vis; RSpeedLocals(); - entity_t ent; Surf_SetupFrame(); - memset (&ent, 0, sizeof(ent)); - ent.model = cl.worldmodel; currentmodel = cl.worldmodel; + currententity = &r_worldentity; - currententity = &ent; #ifdef TERRAIN if (currentmodel->type == mod_heightmap) GL_DrawHeightmapModel(currententity); else #endif { - Surf_ClearChains(); - RSpeedRemark(); #ifdef Q2BSPS - if (ent.model->fromgame == fg_quake2 || ent.model->fromgame == fg_quake3) + if (currententity->model->fromgame == fg_quake2 || currententity->model->fromgame == fg_quake3) { int leafnum; int clientarea; @@ -2308,7 +2287,7 @@ void Surf_DrawWorld (void) CM_WriteAreaBits(cl.worldmodel, areabits, clientarea); } #ifdef Q3BSPS - if (ent.model->fromgame == fg_quake3) + if (currententity->model->fromgame == fg_quake3) { vis = R_MarkLeaves_Q3 (); Surf_LeafWorldNode (); @@ -2335,13 +2314,19 @@ void Surf_DrawWorld (void) } } + tmp = cl_numvisedicts; + CL_LinkStaticEntities(vis); + RSpeedEnd(RSPEED_WORLDNODE); TRACE(("dbg: calling BE_DrawWorld\n")); BE_DrawWorld(vis); - Surf_CleanChains(); + cl_numvisedicts = tmp; + /*FIXME: move this away*/ Surf_LessenStains(); + + Surf_CleanChains(); } } @@ -2514,6 +2499,7 @@ static int nColinElim; ================ BuildSurfaceDisplayList FIXME: this is probably misplaced +lightmaps are already built by the time this is called ================ */ void Surf_BuildSurfaceDisplayList (model_t *model, msurface_t *fa) @@ -2630,7 +2616,10 @@ static void Surf_CreateSurfaceLightmap (msurface_t *surf, int shift) if (surf->texinfo->flags & TEX_SPECIAL) surf->lightmaptexturenum = -1; if (surf->lightmaptexturenum<0) + { + surf->lightmaptexturenum = -1; return; + } smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; @@ -2691,6 +2680,7 @@ GL_BuildLightmaps Builds the lightmap texture with all the surfaces from all brush models +Groups surfaces into their respective batches (based on the lightmap number). ================== */ void Surf_BuildLightmaps (void) @@ -2698,6 +2688,9 @@ void Surf_BuildLightmaps (void) int i, j, t; model_t *m; int shift; + msurface_t *surf; + batch_t *batch, *bstop; + vec3_t sn; r_framecount = 1; // no dlightcache @@ -2735,23 +2728,70 @@ void Surf_BuildLightmaps (void) currentmodel = m; shift = Surf_LightmapShift(currentmodel); - for (t = 0; t < m->numtextures; t++) + for (t = m->numtextures-1; t >= 0; t--) { + m->textures[t]->wtexno = t; + + bstop = m->batches; + batch = NULL; for (i=0 ; inumsurfaces ; i++) {//extra texture loop so we get slightly less texture switches - if (m->surfaces[i].texinfo->texture == m->textures[t]) + surf = m->surfaces + i; + if (surf->texinfo->texture == m->textures[t]) { - P_EmitSkyEffectTris(m, &m->surfaces[i]); + P_EmitSkyEffectTris(m, surf); + Surf_CreateSurfaceLightmap (surf, shift); + + if (m->textures[t]->shader->sort == SHADER_SORT_PORTAL) + { + if (surf->flags & SURF_PLANEBACK) + VectorNegate(surf->plane->normal, sn); + else + VectorCopy(surf->plane->normal, sn); + } + else + VectorClear(sn); + if (!batch || batch->lightmap != surf->lightmaptexturenum || (m->textures[t]->shader->sort == SHADER_SORT_PORTAL && !VectorCompare(sn, batch->normal))) + { + if (m->textures[t]->shader->sort == SHADER_SORT_PORTAL) + { + for (batch = m->batches; batch != bstop; batch = batch->next) + { + if (batch->lightmap == surf->lightmaptexturenum && VectorCompare(sn, batch->normal)) + break; + } + } + else + { + for (batch = m->batches; batch != bstop; batch = batch->next) + { + if (batch->lightmap == surf->lightmaptexturenum) + break; + } + } + if (batch == bstop) + { + batch = Z_Malloc(sizeof(*batch)); + batch->lightmap = surf->lightmaptexturenum; + batch->texture = m->textures[t]; + batch->next = m->batches; + VectorCopy(sn, batch->normal); + m->batches = batch; + } + } + surf->sbatch = batch; + batch->maxmeshes++; - /*FIXME: move this into model-specific code*/ - Surf_CreateSurfaceLightmap (m->surfaces + i, shift); if (m->surfaces[i].mesh) //there are some surfaces that have a display list already (q3 ones) continue; - Surf_BuildSurfaceDisplayList (m, m->surfaces + i); + Surf_BuildSurfaceDisplayList (m, surf); } } } - + for (batch = m->batches; batch != NULL; batch = batch->next) + { + batch->mesh = BZ_Malloc(sizeof(*batch->mesh)*batch->maxmeshes*2); + } BE_GenBrushModelVBO(m); } diff --git a/engine/client/render.h b/engine/client/render.h index 0f3f4457..cd8a840b 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -38,7 +38,7 @@ typedef union { #endif } texid_t; static const texid_t r_nulltex = {0}; -#define TEXVALID(t) (t.num!=0) +#define TEXVALID(t) ((t).num!=0) #ifdef D3DQUAKE @@ -58,14 +58,6 @@ static const texid_t r_nulltex = {0}; //============================================================================= -typedef struct efrag_s -{ - struct mleaf_s *leaf; - struct efrag_s *leafnext; - struct entity_s *entity; - struct efrag_s *entnext; -} efrag_t; - typedef enum { RT_MODEL, RT_POLY, @@ -132,35 +124,17 @@ typedef struct entity_s #endif } entity_t; -// !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { vrect_t vrect; // subwindow in video for refresh // FIXME: not need vrect next field here? - vrect_t aliasvrect; // scaled Alias version - int vrectright, vrectbottom; // right & bottom screen coords - int aliasvrectright, aliasvrectbottom; // scaled Alias versions - float vrectrightedge; // rightmost right edge we care about, - // for use in edge list - float fvrectx, fvrecty; // for floating-point compares - float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping - int vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20 - int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20 - float fvrectright_adj, fvrectbottom_adj; - // right and bottom edges, for clamping - float fvrectright; // rightmost edge, for Alias clamping - float fvrectbottom; // bottommost edge, for Alias clamping - float horizontalFieldOfView; // at Z = 1.0, this many X is visible - // 2.0 = 90 degrees - float xOrigin; // should probably always be 0.5 - float yOrigin; // between be around 0.3 to 0.5 - vec3_t vieworg; + vec3_t pvsorigin; /*render the view using this point for pvs (useful for mirror views)*/ + vec3_t vieworg; /*logical view center*/ vec3_t viewangles; + vec3_t viewaxis[3]; /*forward, left, up (NOT RIGHT)*/ float fov_x, fov_y; - - int ambientlight; int flags; @@ -168,7 +142,14 @@ typedef struct float time; - qboolean useperspective; + float m_projection[16]; + float m_view[16]; + + vrect_t pxrect; /*vrect, but in pixels rather than virtual coords*/ + qboolean externalview; /*draw external models and not viewmodels*/ + qboolean recurse; /*in a mirror/portal/half way through drawing something else*/ + qboolean flipcull; /*reflected/flipped view, requires inverted culling*/ + qboolean useperspective; /*not orthographic*/ } refdef_t; extern refdef_t r_refdef; @@ -223,7 +204,7 @@ extern int lightmap_bytes; // 1, 3(, or 4) - +void R_SetSky(char *skyname); /*override all sky shaders*/ #if defined(GLQUAKE) void GLR_Init (void); @@ -232,9 +213,7 @@ void GLR_InitTextures (void); void GLR_InitEfrags (void); void GLR_RenderView (void); // must set r_refdef first // called whenever r_refdef or vid change - -void GLR_AddEfrags (entity_t *ent); -void GLR_RemoveEfrags (entity_t *ent); +void R_DrawPortal(struct batch_s *batch); void GLR_PreNewMap(void); void GLR_NewMap (void); @@ -254,10 +233,6 @@ void GLVID_Console_Resize(void); int GLR_LightPoint (vec3_t p); #endif - -void R_AddEfrags (entity_t *ent); -void R_RemoveEfrags (entity_t *ent); - enum imageflags { /*warning: many of these flags only apply the first time it is requested*/ @@ -283,7 +258,12 @@ enum uploadfmt TF_HEIGHT8PAL, /*source data is palette values rather than actual heights, generate a fallback heightmap*/ TF_H2_T7G1, /*8bit data, odd indexes give greyscale transparence*/ TF_H2_TRANS8_0, /*8bit data, 0 is transparent, not 255*/ - TF_H2_T4A4 /*8bit data, weird packing*/ + TF_H2_T4A4, /*8bit data, weird packing*/ + + /*anything below requires a palette*/ + TF_PALETTES, + TF_8PAL24, + TF_8PAL32 }; @@ -326,7 +306,7 @@ enum uploadfmt /*it seems a little excessive to have to include glquake (and windows headers), just to load some textures/shaders for the backend*/ #ifdef GLQUAKE texid_t GL_AllocNewTexture(void); -void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, int width, int height, unsigned int flags); +void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags); texid_t GL_LoadTextureFmt (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags); #endif #ifdef D3DQUAKE @@ -353,8 +333,6 @@ extern texid_t balltexture; extern texid_t beamtexture; extern texid_t ptritexture; -extern float r_projection_matrix[16]; -extern float r_view_matrix[16]; void GL_ParallelPerspective(double xmin, double xmax, double ymax, double ymin, double znear, double zfar); void GL_InfinatePerspective(double fovx, double fovy, double zNear); @@ -461,7 +439,6 @@ extern cvar_t r_xflip; #endif extern cvar_t gl_clear; -extern cvar_t gl_cull; extern cvar_t gl_poly; extern cvar_t gl_smoothmodels; extern cvar_t gl_affinemodels; @@ -518,6 +495,12 @@ int rquant[RQUANT_MAX]; #define RQuantAdd(type,quant) rquant[type] += quant; +#if defined(NDEBUG) || !defined(_WIN32) +#define RSpeedLocals() +#define RSpeedMark() +#define RSpeedRemark() +#define RSpeedEnd(spt) +#else #define RSpeedLocals() int rsp #define RSpeedMark() int rsp = r_speeds.ival?Sys_DoubleTime()*1000000:0 #define RSpeedRemark() rsp = r_speeds.ival?Sys_DoubleTime()*1000000:0 @@ -528,3 +511,4 @@ extern void (_stdcall *qglFinish) (void); #else #define RSpeedEnd(spt) rspeeds[spt] += r_speeds.value?Sys_DoubleTime()*1000000 - rsp:0 #endif +#endif \ No newline at end of file diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 873ce326..cc4325dc 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -1,6 +1,8 @@ #include "quakedef.h" #include "winquake.h" #include "pr_common.h" +#include "gl_draw.h" +#include refdef_t r_refdef; @@ -38,59 +40,56 @@ void GL_Texturemode2d_Callback (struct cvar_s *var, char *oldvalue); void GL_Texture_Anisotropic_Filtering_Callback (struct cvar_s *var, char *oldvalue); #endif -cvar_t _vid_wait_override = FCVAR ("vid_wait", "_vid_wait_override", "", - CVAR_ARCHIVE); +cvar_t _vid_wait_override = CVARAF ("vid_wait", "", + "_vid_wait_override", CVAR_ARCHIVE); -cvar_t _windowed_mouse = SCVARF ("_windowed_mouse","1", CVAR_ARCHIVE); +cvar_t _windowed_mouse = CVARF ("_windowed_mouse","1", + CVAR_ARCHIVE); -cvar_t con_ocranaleds = SCVAR ("con_ocranaleds", "2"); +cvar_t con_ocranaleds = CVAR ("con_ocranaleds", "2"); -cvar_t d_palconvwrite = SCVAR ("d_palconvwrite", "1"); -cvar_t d_palremapsize = SCVARF ("d_palremapsize", "64", - CVAR_RENDERERLATCH); +cvar_t d_palconvwrite = CVAR ("d_palconvwrite", "1"); +cvar_t d_palremapsize = CVARF ("d_palremapsize", "64", + CVAR_RENDERERLATCH); -cvar_t cl_cursor = SCVAR ("cl_cursor", ""); -cvar_t cl_cursorsize = SCVAR ("cl_cursorsize", "32"); -cvar_t cl_cursorbias = SCVAR ("cl_cursorbias", "4"); +cvar_t cl_cursor = CVAR ("cl_cursor", ""); +cvar_t cl_cursorsize = CVAR ("cl_cursorsize", "32"); +cvar_t cl_cursorbias = CVAR ("cl_cursorbias", "4"); -cvar_t gl_nocolors = SCVAR ("gl_nocolors", "0"); -cvar_t gl_part_flame = SCVAR ("gl_part_flame", "1"); +cvar_t gl_nocolors = CVAR ("gl_nocolors", "0"); +cvar_t gl_part_flame = CVAR ("gl_part_flame", "1"); //opengl library, blank means try default. -static cvar_t gl_driver = SCVARF ("gl_driver", "", - CVAR_ARCHIVE | CVAR_RENDERERLATCH); -cvar_t gl_shadeq1_name = SCVAR ("gl_shadeq1_name", "*"); +static cvar_t gl_driver = CVARF ("gl_driver", "", + CVAR_ARCHIVE | CVAR_RENDERERLATCH); +cvar_t gl_shadeq1_name = CVAR ("gl_shadeq1_name", "*"); extern cvar_t r_vertexlight; -cvar_t mod_md3flags = SCVAR ("mod_md3flags", "1"); +cvar_t mod_md3flags = CVAR ("mod_md3flags", "1"); -cvar_t r_ambient = SCVARF ("r_ambient", "0", +cvar_t r_ambient = CVARF ("r_ambient", "0", CVAR_CHEAT); -cvar_t r_bloodstains = SCVAR ("r_bloodstains", "1"); -cvar_t r_bouncysparks = SCVARF ("r_bouncysparks", "0", +cvar_t r_bloodstains = CVAR ("r_bloodstains", "1"); +cvar_t r_bouncysparks = CVARF ("r_bouncysparks", "0", CVAR_ARCHIVE); -cvar_t r_drawdisk = SCVAR ("r_drawdisk", "1"); -cvar_t r_drawentities = SCVAR ("r_drawentities", "1"); -cvar_t r_drawflat = SCVARF ("r_drawflat", "0", +cvar_t r_drawentities = CVAR ("r_drawentities", "1"); +cvar_t r_drawflat = CVARF ("r_drawflat", "0", CVAR_SEMICHEAT | CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM); -cvar_t gl_miptexLevel = SCVAR ("gl_miptexLevel", "0"); -cvar_t r_drawviewmodel = SCVAR ("r_drawviewmodel", "1"); -cvar_t r_drawviewmodelinvis = SCVAR ("r_drawviewmodelinvis", "0"); -#ifdef MINIMAL -cvar_t r_dynamic = SCVARF ("r_dynamic", "0", +cvar_t gl_miptexLevel = CVAR ("gl_miptexLevel", "0"); +cvar_t r_drawviewmodel = CVAR ("r_drawviewmodel", "1"); +cvar_t r_drawviewmodelinvis = CVAR ("r_drawviewmodelinvis", "0"); +cvar_t r_dynamic = CVARF ("r_dynamic", IFMINIMAL("0","1"), CVAR_ARCHIVE); -#else -cvar_t r_dynamic = SCVARF ("r_dynamic", "1", - CVAR_ARCHIVE); -#endif -cvar_t r_fastsky = SCVARF ("r_fastsky", "0", +cvar_t r_fastturb = CVARF ("r_fastturb", "0", CVAR_SHADERSYSTEM); -cvar_t r_fastskycolour = SCVARF ("r_fastskycolour", "0", +cvar_t r_fastsky = CVARF ("r_fastsky", "0", + CVAR_SHADERSYSTEM); +cvar_t r_fastskycolour = CVARF ("r_fastskycolour", "0", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM); -cvar_t r_fb_bmodels = SCVARF("gl_fb_bmodels", "1", - CVAR_SEMICHEAT|CVAR_RENDERERLATCH); -cvar_t r_fb_models = FCVAR ("r_fb_models", "gl_fb_models", "1", +cvar_t r_fb_bmodels = CVARF("gl_fb_bmodels", "1", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); +cvar_t r_fb_models = CVARAF ("r_fb_models", "1", + "gl_fb_models", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); cvar_t r_skin_overlays = SCVARF ("r_skin_overlays", "1", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); cvar_t r_flashblend = SCVARF ("gl_flashblend", "0", @@ -115,39 +114,38 @@ cvar_t r_nolightdir = SCVAR ("r_nolightdir", "0"); cvar_t r_novis = SCVAR ("r_novis", "0"); cvar_t r_part_rain = SCVARF ("r_part_rain", "0", CVAR_ARCHIVE); -//whack in a value of 2 and you get easily visible players. cvar_t r_skyboxname = SCVARF ("r_skybox", "", CVAR_RENDERERCALLBACK | CVAR_SHADERSYSTEM); cvar_t r_speeds = SCVAR ("r_speeds", "0"); cvar_t r_stainfadeammount = SCVAR ("r_stainfadeammount", "1"); cvar_t r_stainfadetime = SCVAR ("r_stainfadetime", "1"); -cvar_t r_stains = SCVARFC("r_stains", "0.75", +cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"), CVAR_ARCHIVE, Cvar_Limiter_ZeroToOne_Callback); -cvar_t r_wallcolour = SCVARF ("r_wallcolour", "255 255 255", +cvar_t r_wallcolour = CVARF ("r_wallcolour", "255 255 255", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);//FIXME: broken -cvar_t r_walltexture = SCVARF ("r_walltexture", "", +cvar_t r_walltexture = CVARF ("r_walltexture", "", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM); //FIXME: broken -cvar_t r_wateralpha = SCVARF ("r_wateralpha", "1", +cvar_t r_wateralpha = CVARF ("r_wateralpha", "1", CVAR_SHADERSYSTEM); -cvar_t r_waterwarp = SCVARF ("r_waterwarp", "1", +cvar_t r_waterwarp = CVARF ("r_waterwarp", "1", CVAR_ARCHIVE); -cvar_t r_replacemodels = SCVARF ("r_replacemodels", "md3 md2", +cvar_t r_replacemodels = CVARF ("r_replacemodels", IFMINIMAL("","md3 md2"), CVAR_ARCHIVE); //otherwise it would defeat the point. -cvar_t scr_allowsnap = SCVARF ("scr_allowsnap", "1", +cvar_t scr_allowsnap = CVARF ("scr_allowsnap", "1", CVAR_NOTFROMSERVER); -cvar_t scr_centersbar = SCVAR ("scr_centersbar", "0"); -cvar_t scr_centertime = SCVAR ("scr_centertime", "2"); -cvar_t scr_chatmodecvar = SCVAR ("scr_chatmode", "0"); -cvar_t scr_conalpha = SCVARC ("scr_conalpha", "0.7", +cvar_t scr_centersbar = CVAR ("scr_centersbar", "0"); +cvar_t scr_centertime = CVAR ("scr_centertime", "2"); +cvar_t scr_chatmodecvar = CVAR ("scr_chatmode", "0"); +cvar_t scr_conalpha = CVARC ("scr_conalpha", "0.7", Cvar_Limiter_ZeroToOne_Callback); -cvar_t scr_consize = SCVAR ("scr_consize", "0.5"); -cvar_t scr_conspeed = SCVAR ("scr_conspeed", "300"); +cvar_t scr_consize = CVAR ("scr_consize", "0.5"); +cvar_t scr_conspeed = CVAR ("scr_conspeed", "300"); // 10 - 170 -cvar_t scr_fov = SCVARFC("fov", "90", +cvar_t scr_fov = CVARFC("fov", "90", CVAR_ARCHIVE, SCR_Fov_Callback); cvar_t scr_printspeed = SCVAR ("scr_printspeed", "8"); @@ -156,44 +154,44 @@ cvar_t scr_showturtle = SCVAR ("showturtle", "0"); cvar_t scr_turtlefps = SCVAR ("scr_turtlefps", "10"); cvar_t scr_sshot_compression = SCVAR ("scr_sshot_compression", "75"); cvar_t scr_sshot_type = SCVAR ("scr_sshot_type", "jpg"); -cvar_t scr_viewsize = SCVARFC("viewsize", "100", +cvar_t scr_viewsize = CVARFC("viewsize", "100", CVAR_ARCHIVE, SCR_Viewsize_Callback); -cvar_t vid_conautoscale = SCVARF ("vid_conautoscale", "0", +cvar_t vid_conautoscale = CVARF ("vid_conautoscale", "0", CVAR_ARCHIVE | CVAR_RENDERERCALLBACK); -cvar_t vid_conheight = SCVARF ("vid_conheight", "0", +cvar_t vid_conheight = CVARF ("vid_conheight", "0", CVAR_ARCHIVE); -cvar_t vid_conwidth = SCVARF ("vid_conwidth", "0", +cvar_t vid_conwidth = CVARF ("vid_conwidth", "0", CVAR_ARCHIVE | CVAR_RENDERERCALLBACK); //see R_RestartRenderer_f for the effective default 'if (newr.renderer == -1)'. -cvar_t vid_renderer = SCVARF ("vid_renderer", "", +cvar_t vid_renderer = CVARF ("vid_renderer", "", CVAR_ARCHIVE | CVAR_RENDERERLATCH); -static cvar_t vid_allow_modex = SCVARF ("vid_allow_modex", "1", +static cvar_t vid_allow_modex = CVARF ("vid_allow_modex", "1", CVAR_ARCHIVE | CVAR_RENDERERLATCH); //FIXME: remove -static cvar_t vid_bpp = SCVARF ("vid_bpp", "32", +static cvar_t vid_bpp = CVARF ("vid_bpp", "32", CVAR_ARCHIVE | CVAR_RENDERERLATCH); -static cvar_t vid_desktopsettings = SCVARF ("vid_desktopsettings", "0", +static cvar_t vid_desktopsettings = CVARF ("vid_desktopsettings", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); #ifdef NPQTV -static cvar_t vid_fullscreen_npqtv = SCVARF ("vid_fullscreen", "1", +static cvar_t vid_fullscreen_npqtv = CVARF ("vid_fullscreen", "1", CVAR_ARCHIVE | CVAR_RENDERERLATCH); -cvar_t vid_fullscreen = SCVARF ("vid_fullscreen_embedded", "0", +cvar_t vid_fullscreen = CVARF ("vid_fullscreen_embedded", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); #else -static cvar_t vid_fullscreen = SCVARF ("vid_fullscreen", "1", +static cvar_t vid_fullscreen = CVARF ("vid_fullscreen", "1", CVAR_ARCHIVE | CVAR_RENDERERLATCH); #endif -cvar_t vid_height = SCVARF ("vid_height", "0", +cvar_t vid_height = CVARF ("vid_height", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); -static cvar_t vid_multisample = SCVARF ("vid_multisample", "0", +cvar_t vid_multisample = CVARF ("vid_multisample", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); -static cvar_t vid_refreshrate = SCVARF ("vid_displayfrequency", "0", +static cvar_t vid_refreshrate = CVARF ("vid_displayfrequency", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); -cvar_t vid_wndalpha = SCVAR ("vid_wndalpha", "1"); +cvar_t vid_wndalpha = CVAR ("vid_wndalpha", "1"); //more readable defaults to match conwidth/conheight. -cvar_t vid_width = SCVARF ("vid_width", "0", +cvar_t vid_width = CVARF ("vid_width", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); extern cvar_t bul_backcol; @@ -223,7 +221,6 @@ extern cvar_t r_mirroralpha; extern cvar_t r_netgraph; extern cvar_t r_norefresh; extern cvar_t r_novis; -extern cvar_t r_shadows; extern cvar_t r_speeds; extern cvar_t r_waterwarp; @@ -251,15 +248,14 @@ cvar_t gl_bump = SCVARF ("gl_bump", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); cvar_t gl_compress = SCVARF ("gl_compress", "0", CVAR_ARCHIVE); -cvar_t gl_conback = SCVARF ("gl_conback", "", - CVAR_RENDERERCALLBACK); +cvar_t gl_conback = CVARFC ("gl_conback", "", + CVAR_RENDERERCALLBACK, R2D_Conback_Callback); cvar_t gl_contrast = SCVAR ("gl_contrast", "1"); cvar_t gl_detail = SCVARF ("gl_detail", "0", CVAR_ARCHIVE); cvar_t gl_detailscale = SCVAR ("gl_detailscale", "5"); cvar_t gl_font = SCVARF ("gl_font", "", CVAR_RENDERERCALLBACK); -cvar_t gl_fontinwardstep = SCVAR ("gl_fontinwardstep", "0"); cvar_t gl_lateswap = SCVAR ("gl_lateswap", "0"); cvar_t gl_lerpimages = SCVAR ("gl_lerpimages", "1"); cvar_t gl_lightmap_shift = SCVARF ("gl_lightmap_shift", "0", @@ -269,7 +265,7 @@ cvar_t gl_lightmap_shift = SCVARF ("gl_lightmap_shift", "0", cvar_t gl_load24bit = SCVARF ("gl_load24bit", "1", CVAR_ARCHIVE); -cvar_t gl_max_size = SCVAR ("gl_max_size", "1024"); +cvar_t gl_max_size = SCVARF ("gl_max_size", "1024", CVAR_RENDERERLATCH); cvar_t gl_maxshadowlights = SCVARF ("gl_maxshadowlights", "2", CVAR_ARCHIVE); cvar_t gl_menutint_shader = SCVAR ("gl_menutint_shader", "1"); @@ -281,8 +277,6 @@ cvar_t gl_mindist = SCVARF ("gl_mindist", "4", cvar_t gl_motionblur = SCVARF ("gl_motionblur", "0", CVAR_ARCHIVE); cvar_t gl_motionblurscale = SCVAR ("gl_motionblurscale", "1"); -cvar_t gl_mylumassuck = SCVAR ("gl_mylumassuck", "0"); -cvar_t gl_nobind = SCVAR ("gl_nobind", "0"); cvar_t gl_overbright = SCVARF ("gl_overbright", "0", CVAR_ARCHIVE); cvar_t gl_overbright_all = SCVARF ("gl_overbright_all", "0", @@ -295,23 +289,19 @@ cvar_t gl_schematics = SCVAR ("gl_schematics", "0"); cvar_t gl_skyboxdist = SCVAR ("gl_skyboxdist", "0"); //0 = guess. cvar_t gl_smoothcrosshair = SCVAR ("gl_smoothcrosshair", "1"); -//gl blends. Set this to 1 to stop the outside of your conchars from being visible -cvar_t gl_smoothfont = SCVARF ("gl_smoothfont", "1", - CVAR_RENDERERCALLBACK); - #ifdef SPECULAR cvar_t gl_specular = SCVAR ("gl_specular", "0"); #endif // The callbacks are not in D3D yet (also ugly way of seperating this) #ifdef GLQUAKE -cvar_t gl_texture_anisotropic_filtering = SCVARFC("gl_texture_anisotropic_filtering", "0", +cvar_t gl_texture_anisotropic_filtering = CVARFC("gl_texture_anisotropic_filtering", "0", CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, GL_Texture_Anisotropic_Filtering_Callback); -cvar_t gl_texturemode = SCVARFC("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", +cvar_t gl_texturemode = CVARFC("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, GL_Texturemode_Callback); -cvar_t gl_texturemode2d = SCVARFC("gl_texturemode2d", "GL_LINEAR", +cvar_t gl_texturemode2d = CVARFC("gl_texturemode2d", "GL_LINEAR", CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, GL_Texturemode2d_Callback); #endif @@ -320,6 +310,7 @@ cvar_t gl_triplebuffer = SCVARF ("gl_triplebuffer", "1", CVAR_ARCHIVE); cvar_t gl_ztrick = SCVAR ("gl_ztrick", "0"); +cvar_t r_noportals = SCVAR ("r_noportals", "0"); cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE); @@ -335,7 +326,6 @@ cvar_t r_shadow_realtime_world_shadows = SCVARF ("r_shadow_realtime_world_shado cvar_t r_shadow_realtime_dlight = SCVARF ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_dlight_shadows = SCVARF ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_world_lightmaps = SCVARF ("r_shadow_realtime_world_lightmaps", "0.8", 0); -cvar_t r_shadows = SCVARF ("r_shadows", "0", CVAR_ARCHIVE | CVAR_RENDERERLATCH); cvar_t r_vertexdlights = SCVAR ("r_vertexdlights", "0"); @@ -383,7 +373,6 @@ void GLRenderer_Init(void) Cvar_Register (&gl_clear, GLRENDEREROPTIONS); - Cvar_Register (&gl_cull, GLRENDEREROPTIONS); Cvar_Register (&gl_smoothmodels, GRAPHICALNICETIES); Cvar_Register (&gl_affinemodels, GLRENDEREROPTIONS); Cvar_Register (&gl_nohwblend, GLRENDEREROPTIONS); @@ -394,7 +383,7 @@ void GLRenderer_Init(void) Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS); Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS); - Cvar_Register (&r_shadows, GLRENDEREROPTIONS); + Cvar_Register (&r_noportals, GLRENDEREROPTIONS); Cvar_Register (&r_noaliasshadows, GLRENDEREROPTIONS); Cvar_Register (&gl_maxshadowlights, GLRENDEREROPTIONS); Cvar_Register (&r_shadow_bumpscale_basetexture, GLRENDEREROPTIONS); @@ -416,8 +405,6 @@ void GLRenderer_Init(void) Cvar_Register (&gl_maxdist, GLRENDEREROPTIONS); Cvar_Register (&vid_multisample, GLRENDEREROPTIONS); - Cvar_Register (&gl_fontinwardstep, GRAPHICALNICETIES); - Cvar_Register (&gl_smoothfont, GRAPHICALNICETIES); Cvar_Register (&gl_smoothcrosshair, GRAPHICALNICETIES); Cvar_Register (&gl_bump, GRAPHICALNICETIES); @@ -440,10 +427,8 @@ void GLRenderer_Init(void) Cvar_Register (&r_polygonoffset_submodel_factor, GLRENDEREROPTIONS); Cvar_Register (&r_polygonoffset_submodel_offset, GLRENDEREROPTIONS); - Cvar_Register (&gl_nobind, GLRENDEREROPTIONS); Cvar_Register (&gl_picmip, GLRENDEREROPTIONS); Cvar_Register (&gl_picmip2d, GLRENDEREROPTIONS); - Cvar_Register (&r_drawdisk, GLRENDEREROPTIONS); Cvar_Register (&gl_texturemode, GLRENDEREROPTIONS); Cvar_Register (&gl_texturemode2d, GLRENDEREROPTIONS); @@ -480,8 +465,6 @@ void GLRenderer_Init(void) Cvar_Register (&gl_blendsprites, GLRENDEREROPTIONS); - Cvar_Register (&gl_mylumassuck, GLRENDEREROPTIONS); - Cvar_Register (&gl_lightmap_shift, GLRENDEREROPTIONS); Cvar_Register (&gl_menutint_shader, GLRENDEREROPTIONS); @@ -625,6 +608,7 @@ void Renderer_Init(void) Cvar_Register (&r_nolerp, GRAPHICALNICETIES); Cvar_Register (&r_nolightdir, GRAPHICALNICETIES); + Cvar_Register (&r_fastturb, GRAPHICALNICETIES); Cvar_Register (&r_fastsky, GRAPHICALNICETIES); Cvar_Register (&r_fastskycolour, GRAPHICALNICETIES); Cvar_Register (&r_wateralpha, GRAPHICALNICETIES); @@ -733,10 +717,6 @@ void (*R_PushDlights) (void); void (*R_AddStain) (vec3_t org, float red, float green, float blue, float radius); void (*R_LessenStains) (void); -void (*Media_ShowFrameBGR_24_Flip) (qbyte *framedata, int inwidth, int inheight); //input is bottom up... -void (*Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight); //top down -void (*Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, qbyte *palette); //paletted topdown (framedata is 8bit indexes into palette) - void (*Mod_Init) (void); void (*Mod_ClearAll) (void); struct model_s *(*Mod_ForName) (char *name, qboolean crash); @@ -818,10 +798,6 @@ rendererinfo_t dedicatedrendererinfo = { NULL, //R_AddStain; NULL, //R_LessenStains; - NULL, //Media_ShowFrameBGR_24_Flip; - NULL, //Media_ShowFrameRGBA_32; - NULL, //Media_ShowFrame8bit; - #if defined(GLQUAKE) || defined(D3DQUAKE) RMod_Init, RMod_ClearAll, @@ -951,7 +927,7 @@ typedef struct { menucombo_t *conscalecombo; menucombo_t *bppcombo; menucombo_t *refreshratecombo; - menucombo_t *texturefiltercombo; + menucombo_t *vsynccombo; menuedit_t *customwidth; menuedit_t *customheight; } videomenuinfo_t; @@ -1023,19 +999,20 @@ qboolean M_VideoApply (union menuoption_s *op,struct menu_s *menu,int key) break; } - switch(info->texturefiltercombo->selectedoption) + switch(info->vsynccombo->selectedoption) { case 0: - Cbuf_AddText("gl_texturemode gl_nearest_mipmap_nearest\n", RESTRICT_LOCAL); + Cbuf_AddText(va("vid_wait %i\n", 0), RESTRICT_LOCAL); break; case 1: - Cbuf_AddText("gl_texturemode gl_linear_mipmap_nearest\n", RESTRICT_LOCAL); + Cbuf_AddText(va("vid_wait %i\n", 1), RESTRICT_LOCAL); break; case 2: - Cbuf_AddText("gl_texturemode gl_linear_mipmap_linear\n", RESTRICT_LOCAL); + Cbuf_AddText(va("vid_wait %i\n", 2), RESTRICT_LOCAL); break; } + Cbuf_AddText(va("vid_bpp %i\n", selectedbpp), RESTRICT_LOCAL); switch(info->refreshratecombo->selectedoption) @@ -1085,11 +1062,9 @@ qboolean M_VideoApply (union menuoption_s *op,struct menu_s *menu,int key) } void M_Menu_Video_f (void) { - extern cvar_t r_stains, v_contrast; + extern cvar_t v_contrast; #if defined(GLQUAKE) - extern cvar_t r_bloom; #endif - extern cvar_t r_bouncysparks; static const char *modenames[128] = {"Custom"}; static const char *rendererops[] = { #ifdef GLQUAKE @@ -1114,6 +1089,7 @@ void M_Menu_Video_f (void) "Trilinear", NULL }; + static const char *refreshrates[] = { "0Hz (OS Driver refresh rate)", @@ -1127,17 +1103,38 @@ void M_Menu_Video_f (void) NULL }; + static const char *vsyncoptions[] = + { + "Off", + "Wait for Vertical Sync", + "Wait for Display Enable", + NULL + }; + videomenuinfo_t *info; - menu_t *menu; int prefabmode; int prefab2dmode; int currentbpp; int currentrefreshrate; -#ifdef GLQUAKE - int currenttexturefilter; -#endif + int currentvsync; + int aspectratio3d; + int aspectratio2d; + char *aspectratio23d; + char *aspectratio22d; + char *rendererstring; + static char current3dres[10]; // enough to fit 1920x1200 + static char current2dres[10]; // same as above + static char currenthz[6]; // enough to fit 120hz + static char currentcolordepth[6]; + + extern cvar_t _vid_wait_override; + float vidwidth = vid.pixelwidth; + float vidheight = vid.pixelheight; int i, y; + menu_t *menu = M_Options_Title(&y, sizeof(videomenuinfo_t)); + info = menu->data; + prefabmode = -1; prefab2dmode = -1; for (i = 0; i < sizeof(vid_modes)/sizeof(vidmode_t); i++) @@ -1150,13 +1147,7 @@ void M_Menu_Video_f (void) } modenames[i+1] = NULL; - key_dest = key_menu; - m_state = m_complex; - - menu = M_CreateMenu(sizeof(videomenuinfo_t)); - info = menu->data; - -#if defined(GLQUAKE) && defined(USE_D3D) +#if defined(GLQUAKE) && defined(D3DQUAKE) if (!strcmp(vid_renderer.string, "d3d9")) i = 1; else @@ -1164,9 +1155,15 @@ void M_Menu_Video_f (void) i = 0; if (vid_bpp.value >= 32) + { currentbpp = 2; + strcpy(currentcolordepth, va("%sbit (16.7m colors)",vid_bpp.string) ); + } else if (vid_bpp.value >= 16) + { currentbpp = 1; + strcpy(currentcolordepth, va("%sbit (65.5k colors)",vid_bpp.string) ); + } else currentbpp = 0; @@ -1189,50 +1186,119 @@ void M_Menu_Video_f (void) else currentrefreshrate = 0; -#ifdef GLQUAKE - if (!Q_strcasecmp(gl_texturemode.string, "gl_nearest_mipmap_nearest")) - currenttexturefilter = 0; - else if (!Q_strcasecmp(gl_texturemode.string, "gl_linear_mipmap_linear")) - currenttexturefilter = 2; - else if (!Q_strcasecmp(gl_texturemode.string, "gl_linear_mipmap_nearest")) - currenttexturefilter = 1; + strcpy(currenthz, va("%sHz",vid_refreshrate.string) ); + + aspectratio3d = (vidwidth / vidheight * 100); // times by 100 so don't have to deal with floats + + if (aspectratio3d == 125) // 1.25 + aspectratio23d = "5:4"; + else if (aspectratio3d == 160) // 1.6 + aspectratio23d = "16:10"; + else if (aspectratio3d == 133) // 1.333333 + aspectratio23d = "4:3"; + else if (aspectratio3d == 177) // 1.777778 + aspectratio23d = "16:9"; else - currenttexturefilter = 1; -#endif + { + aspectratio23d = "Non-standard Ratio"; + Con_Printf("Ratio: %i, width: %i, height: %i\n", aspectratio3d, vid.pixelwidth, vid.pixelheight); + } + aspectratio2d = (vid_conwidth.value / vid_conheight.value * 100); // times by 100 so don't have to deal with floats - MC_AddCenterPicture(menu, 4, 24, "vidmodes"); + if (aspectratio2d == 125) // 1.25 + aspectratio22d = "5:4"; + else if (aspectratio2d == 160) // 1.6 + aspectratio22d = "16:10"; + else if (aspectratio2d == 133) // 1.333333 + aspectratio22d = "4:3"; + else if (aspectratio2d == 177) // 1.777778 + aspectratio22d = "16:9"; + else + aspectratio22d = "Non-standard Ratio"; - y = 32; - info->renderer = MC_AddCombo(menu, 16, y, " Renderer ", rendererops, i); y+=8; - info->bppcombo = MC_AddCombo(menu, 16, y, " Color Depth ", bppnames, currentbpp); y+=8; - info->refreshratecombo = MC_AddCombo(menu, 16, y, " Refresh Rate ", refreshrates, currentrefreshrate); y+=8; - info->modecombo = MC_AddCombo(menu, 16, y, " Video Size ", modenames, prefabmode+1); y+=8; - info->conscalecombo = MC_AddCombo(menu, 16, y, " 2d Size ", modenames, prefab2dmode+1); y+=8; - MC_AddCheckBox(menu, 16, y, " Fullscreen ", &vid_fullscreen,0); y+=8; - y+=4;info->customwidth = MC_AddEdit(menu, 16, y, " Custom width ", vid_width.string); y+=8; - y+=4;info->customheight = MC_AddEdit(menu, 16, y, " Custom height", vid_height.string); y+=12; + currentvsync = _vid_wait_override.value; + + if ( stricmp(vid_renderer.string,"gl" ) == 0 ) + rendererstring = "OpenGL"; + else if ( stricmp(vid_renderer.string,"d3d7") == 0 ) + rendererstring = "DirectX 7"; + else if ( stricmp(vid_renderer.string,"d3d9") == 0 ) + rendererstring = "DirectX 9"; + else if ( stricmp(vid_renderer.string,"d3d") == 0) + rendererstring = "DirectX"; + else if ( stricmp(vid_renderer.string,"sw") == 0) + rendererstring = "Software"; + else + rendererstring = "Unknown Renderer?"; + + strcpy(current3dres, va("%ix%i", vid.pixelwidth, vid.pixelheight) ); + strcpy(current2dres, va("%sx%s", vid_conwidth.string, vid_conheight.string) ); + + y += 40; + MC_AddRedText(menu, 0, y, " Current Renderer", false); + MC_AddRedText(menu, 225, y, rendererstring, false); y+=8; + MC_AddRedText(menu, 0, y, " Current Color Depth", false); + MC_AddRedText(menu, 225, y, currentcolordepth, false); y+=8; + if ( ( vidwidth == 0) || ( vidheight == 0) ) + y+=16; + else + { + MC_AddRedText(menu, 0, y, " Current 3D Res", false); + MC_AddRedText(menu, 225, y, current3dres, false); y+=8; + MC_AddRedText(menu, 0, y, " Current 3D A/R", false); + MC_AddRedText(menu, 225, y, aspectratio23d, false); y+=8; + } + + if ( ( vid_conwidth.value == 0) || ( vid_conheight.value == 0) ) // same as 3d resolution + { + MC_AddRedText(menu, 0, y, " Current 2D Res", false); + MC_AddRedText(menu, 225, y, current3dres, false); y+=8; + MC_AddRedText(menu, 0, y, " Current 2D A/R", false); + MC_AddRedText(menu, 225, y, aspectratio23d, false); y+=8; + } + else + { + MC_AddRedText(menu, 0, y, " Current 2D Res", false); + MC_AddRedText(menu, 225, y, current2dres, false); y+=8; + MC_AddRedText(menu, 0, y, " Current 2D A/R", false); + MC_AddRedText(menu, 225, y, aspectratio22d, false); y+=8; + } + + MC_AddRedText(menu, 0, y, " Current Refresh Rate", false); + MC_AddRedText(menu, 225, y, currenthz, false); y+=8; + y+=8; + MC_AddRedText(menu, 0, y, " €‚ ", false); y+=8; y+=8; - MC_AddCommand(menu, 16, y, " Apply", M_VideoApply); y+=8; + info->renderer = MC_AddCombo(menu, 16, y, " Renderer", rendererops, i); y+=8; + info->bppcombo = MC_AddCombo(menu, 16, y, " Color Depth", bppnames, currentbpp); y+=8; + info->refreshratecombo = MC_AddCombo(menu, 16, y, " Refresh Rate", refreshrates, currentrefreshrate); y+=8; + info->modecombo = MC_AddCombo(menu, 16, y, " Video Size", modenames, prefabmode+1); y+=8; + MC_AddWhiteText(menu, 16, y, " 3D Aspect Ratio", false); y+=8; + info->conscalecombo = MC_AddCombo(menu, 16, y, " 2D Size", modenames, prefab2dmode+1); y+=8; + MC_AddWhiteText(menu, 16, y, " 2D Aspect Ratio", false); y+=8; + MC_AddCheckBox(menu, 16, y, " Fullscreen", &vid_fullscreen,0); y+=8; + y+=4;info->customwidth = MC_AddEdit(menu, 16, y, " Custom width", vid_width.string); y+=8; + y+=4;info->customheight = MC_AddEdit(menu, 16, y, " Custom height", vid_height.string); y+=12; + info->vsynccombo = MC_AddCombo(menu, 16, y, " VSync", vsyncoptions, currentvsync); y+=8; + //MC_AddCheckBox(menu, 16, y, " Override VSync", &_vid_wait_override,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Desktop Settings", &vid_desktopsettings,0); y+=8; y+=8; - MC_AddCheckBox(menu, 16, y, " Stain maps", &r_stains,0); y+=8; - MC_AddCheckBox(menu, 16, y, " Bouncy sparks", &r_bouncysparks,0); y+=8; - MC_AddCheckBox(menu, 16, y, " Rain", &r_part_rain,0); y+=8; -#ifdef GLQUAKE - MC_AddCheckBox(menu, 16, y, " GL Bumpmapping", &gl_bump,0); y+=8; - MC_AddCheckBox(menu, 16, y, " Bloom", &r_bloom,0); y+=8; -#endif - MC_AddCheckBox(menu, 16, y, " Dynamic lights", &r_dynamic,0); y+=8; - MC_AddSlider(menu, 16, y, " Screen size", &scr_viewsize, 30, 120, 0.1);y+=8; - MC_AddSlider(menu, 16, y, " Gamma", &v_gamma, 0.3, 1, 0.05); y+=8; - MC_AddSlider(menu, 16, y, " Contrast", &v_contrast, 1, 3, 0.05); y+=8; -#ifdef GLQUAKE - info->texturefiltercombo = MC_AddCombo(menu, 16, y, " Texture Filter ", texturefilternames, currenttexturefilter); y+=8; - MC_AddSlider(menu, 16, y, "Anisotropy Level", &gl_texture_anisotropic_filtering, 1, 16, 1); y+=8; //urm, this shouldn't really be a slider, but should be a combo instead -#endif + MC_AddCommand(menu, 16, y, "= Apply Changes =", M_VideoApply); y+=8; + y+=8; + MC_AddSlider(menu, 16, y, " Screen size", &scr_viewsize, 30, 120, 1);y+=8; + MC_AddSlider(menu, 16, y, "Console Autoscale",&vid_conautoscale, 0, 6, 0.25); y+=8; + MC_AddSlider(menu, 16, y, " Gamma", &v_gamma, 0.3, 1, 0.05); y+=8; + MC_AddCheckBox(menu, 16, y, " Desktop Gamma", &vid_desktopgamma,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Hardware Gamma", &vid_hardwaregamma,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Preserve Gamma", &vid_preservegamma,0); y+=8; + MC_AddSlider(menu, 16, y, " Contrast", &v_contrast, 1, 3, 0.05); y+=8; + y+=8; + MC_AddCheckBox(menu, 16, y, " Allow ModeX", &vid_allow_modex,0); y+=8; + MC_AddCheckBox(menu, 16, y, " Windowed Mouse", &_windowed_mouse,0); y+=8; - menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 152, 32, NULL, false); menu->selecteditem = (union menuoption_s *)info->renderer; + menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 152, menu->selecteditem->common.posy, NULL, false); menu->event = CheckCustomMode; } @@ -1289,10 +1355,6 @@ void R_SetRenderer(rendererinfo_t *ri) VID_GetRGBInfo = ri->VID_GetRGBInfo; VID_SetWindowCaption = ri->VID_SetWindowCaption; - Media_ShowFrame8bit = ri->Media_ShowFrame8bit; - Media_ShowFrameRGBA_32 = ri->Media_ShowFrameRGBA_32; - Media_ShowFrameBGR_24_Flip = ri->Media_ShowFrameBGR_24_Flip; - Mod_Init = ri->Mod_Init; Mod_Think = ri->Mod_Think; Mod_ClearAll = ri->Mod_ClearAll; @@ -1612,7 +1674,7 @@ TRACE(("dbg: R_ApplyRenderer: starting on client state\n")); { staticmodelindex[i] = 0; for (j = 1; j < MAX_MODELS; j++) - if (cl_static_entities[i].model == cl.model_precache[j]) + if (cl_static_entities[i].ent.model == cl.model_precache[j]) { staticmodelindex[i] = j; break; @@ -1701,11 +1763,10 @@ TRACE(("dbg: R_ApplyRenderer: R_NewMap\n")); TRACE(("dbg: R_ApplyRenderer: efrags\n")); for (i = 0; i < cl.num_statics; i++) //make the static entities reappear. { - cl_static_entities[i].model = cl.model_precache[staticmodelindex[i]]; - if (staticmodelindex[i]) //make sure it's worthwhile. - { - R_AddEfrags(&cl_static_entities[i]); - } + cl_static_entities[i].ent.model = cl.model_precache[staticmodelindex[i]]; + if (cl_static_entities[i].ent.model) + cl.worldmodel->funcs.FindTouchedLeafs(cl.worldmodel, &cl_static_entities[i].pvscache, NULL, NULL); +#pragma message("STATIC ENTITITES --- relink") } } #ifdef VM_UI @@ -2031,43 +2092,10 @@ mspriteframe_t *R_GetSpriteFrame (entity_t *currententity) return pspriteframe; } - - -float r_projection_matrix[16]; -float r_view_matrix[16]; - +/* void MYgluPerspective(double fovx, double fovy, double zNear, double zFar) { - Matrix4_Projection_Far(r_projection_matrix, fovx, fovy, zNear, zFar); - /* - double xmin, xmax, ymin, ymax; - - ymax = zNear * tan( fovy * M_PI / 360.0 ); - ymin = -ymax; - - xmax = zNear * tan( fovx * M_PI / 360.0 ); - xmin = -xmax; - - r_projection_matrix[0] = (2*zNear) / (xmax - xmin); - r_projection_matrix[4] = 0; - r_projection_matrix[8] = (xmax + xmin) / (xmax - xmin); - r_projection_matrix[12] = 0; - - r_projection_matrix[1] = 0; - r_projection_matrix[5] = (2*zNear) / (ymax - ymin); - r_projection_matrix[9] = (ymax + ymin) / (ymax - ymin); - r_projection_matrix[13] = 0; - - r_projection_matrix[2] = 0; - r_projection_matrix[6] = 0; - r_projection_matrix[10] = - (zFar+zNear)/(zFar-zNear); - r_projection_matrix[14] = - (2.0f*zFar*zNear)/(zFar-zNear); - - r_projection_matrix[3] = 0; - r_projection_matrix[7] = 0; - r_projection_matrix[11] = -1; - r_projection_matrix[15] = 0; - */ + Matrix4_Projection_Far(r_refdef.m_projection, fovx, fovy, zNear, zFar); } void GL_InfinatePerspective(double fovx, double fovy, @@ -2128,7 +2156,7 @@ void GL_ParallelPerspective(double xmin, double xmax, double ymax, double ymin, r_projection_matrix[11] = 0; r_projection_matrix[15] = 1; } - +*/ /* @@ -2350,9 +2378,6 @@ qbyte *R_MarkLeaves_Q1 (void) if (((r_oldviewleaf == r_viewleaf && r_oldviewleaf2 == r_viewleaf2) && !r_novis.ival) || r_novis.ival & 2) return vis; -// if (mirror) -// return; - r_visframecount++; r_oldviewleaf = r_viewleaf; @@ -2714,5 +2739,7 @@ void R_InitParticleTexture (void) } } ptritexture = R_LoadTexture32("", PARTICLETEXTURESIZE, PARTICLETEXTURESIZE, data, IF_NOMIPMAP|IF_NOPICMIP); + + Cvar_ForceCallback(&r_particlesystem); } diff --git a/engine/client/renderque.c b/engine/client/renderque.c index fb981f6e..41112904 100644 --- a/engine/client/renderque.c +++ b/engine/client/renderque.c @@ -14,11 +14,16 @@ static renderque_t *distrque[NUMGRADUATIONS]; int rqmaxgrad, rqmingrad; int rquesize = 0x2000; +float rquepivot; + +void RQ_BeginFrame(void) +{ + rquepivot = DotProduct(r_refdef.vieworg, vpn); +} void RQ_AddDistReorder(void (*render) (int count, void **objects, void *objtype), void *object, void *objtype, float *pos) { int dist; - vec3_t delta; renderque_t *rq; if (!freerque) { @@ -26,8 +31,7 @@ void RQ_AddDistReorder(void (*render) (int count, void **objects, void *objtype) return; } - VectorSubtract(pos, r_refdef.vieworg, delta); - dist = Length(delta)/4; + dist = DotProduct(pos, vpn)-rquepivot; if (dist > rqmaxgrad) { @@ -38,7 +42,8 @@ void RQ_AddDistReorder(void (*render) (int count, void **objects, void *objtype) if (dist < rqmingrad) { if (dist < 0) //hmm... value wrapped? shouldn't happen - dist = 0; + return; +// dist = 0; rqmingrad = dist; } @@ -56,7 +61,7 @@ void RQ_AddDistReorder(void (*render) (int count, void **objects, void *objtype) if (!distrque[dist]) distrque[dist] = rq; } - +/* void RQ_RenderDistAndClear(void) { int i; @@ -79,6 +84,7 @@ void RQ_RenderDistAndClear(void) rqmaxgrad=0; rqmingrad = NUMGRADUATIONS-1; } +*/ void RQ_RenderBatchClear(void) { #define SLOTS 512 diff --git a/engine/client/renderque.h b/engine/client/renderque.h index 866eabda..83cece1e 100644 --- a/engine/client/renderque.h +++ b/engine/client/renderque.h @@ -1,9 +1,9 @@ #ifndef RENDERQUE_H #define RENDERQUE_H +void RQ_BeginFrame(void); void RQ_AddDistReorder(void (*render) (int count, void **objects, void *objtype), void *object, void *objtype, float *pos); -FTE_DEPRECATED void RQ_RenderDistAndClear(void); void RQ_RenderBatchClear(void); typedef struct renderque_s diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 0725da8e..f2bdb3eb 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -27,6 +27,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern cvar_t hud_tracking_show; +extern cvar_t com_parseutf8; +#define CON_ALTMASK (com_parseutf8.ival?(COLOR_MAGENTA<= Q2CS_SOUNDS && i < Q2CS_SOUNDS + Q2MAX_SOUNDS) return cl.model_name [i-Q2CS_SOUNDS]; + if (i == Q2CS_AIRACCEL) + return "4"; //#define Q2CS_LIGHTS (Q2CS_IMAGES +Q2MAX_IMAGES) //#define Q2CS_ITEMS (Q2CS_LIGHTS +Q2MAX_LIGHTSTYLES) //#define Q2CS_PLAYERSKINS (Q2CS_ITEMS +Q2MAX_ITEMS) @@ -491,7 +460,7 @@ void Sbar_ExecuteLayoutString (char *s) s = COM_Parse (s); // SCR_AddDirtyPoint (x, y); // SCR_AddDirtyPoint (x+23, y+23); - p = Draw_SafeCachePic(com_token); + p = Sbar_Q2CachePic(com_token); if (p) Draw_ScalePic (x, y, p->width, p->height, p); continue; @@ -522,7 +491,7 @@ void Sbar_ExecuteLayoutString (char *s) if (cl.q2frame.playerstate.stats[Q2STAT_FLASHES] & 1) { - p = Draw_SafeCachePic("field_3"); + p = Sbar_Q2CachePic("field_3"); if (p) Draw_ScalePic (x, y, p->width, p->height, p); } @@ -546,7 +515,7 @@ void Sbar_ExecuteLayoutString (char *s) if (cl.q2frame.playerstate.stats[Q2STAT_FLASHES] & 4) { - p = Draw_SafeCachePic("field_3"); + p = Sbar_Q2CachePic("field_3"); if (p) Draw_ScalePic (x, y, p->width, p->height, p); } @@ -590,7 +559,7 @@ void Sbar_ExecuteLayoutString (char *s) if (!strcmp(com_token, "cstring")) { s = COM_Parse (s); - DrawHUDString (com_token, x, y, 320, 0); + DrawHUDString (com_token, x, y, 320, false); continue; } @@ -604,7 +573,7 @@ void Sbar_ExecuteLayoutString (char *s) if (!strcmp(com_token, "cstring2")) { s = COM_Parse (s); - DrawHUDString (com_token, x, y, 320,0x80); + DrawHUDString (com_token, x, y, 320, true); continue; } @@ -2155,7 +2124,7 @@ void Sbar_Draw (void) if (cls.protocol == CP_QUAKE2) { SCR_VRectForPlayer(&sbar_rect, 0); - + Draw_ImageColours(1, 1, 1, 1); if (*cl.q2statusbar) Sbar_ExecuteLayoutString(cl.q2statusbar); if (*cl.q2layout) diff --git a/engine/client/screen.h b/engine/client/screen.h index f0e9a436..55921a42 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -102,12 +102,15 @@ void Font_Shutdown(void); struct font_s *Font_LoadFont(int height, char *fontfilename); void Font_Free(struct font_s *f); void Font_BeginString(struct font_s *font, int vx, int vy, int *px, int *py); +void Font_BeginScaledString(struct font_s *font, float vx, float vy, float *px, float *py); /*avoid using*/ int Font_CharHeight(void); int Font_CharWidth(unsigned int charcode); +int Font_CharEndCoord(int x, unsigned int charcode); int Font_DrawChar(int px, int py, unsigned int charcode); +float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int charcode); /*avoid using*/ +void Font_EndString(struct font_s *font); void Font_ForceColour(float r, float g, float b, float a); //This colour will be applied while the char mask remains WHITE. If you print char by char, make sure to include the mask. void Font_InvalidateColour(void); -void Font_EndString(struct font_s *font); /*these three functions deal with formatted blocks of text (including tabs and new lines)*/ int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends); int Font_LineWidth(conchar_t *start, conchar_t *end); diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index f6332850..3450aa2c 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -61,32 +61,51 @@ int desired_bits = 16; int sound_started=0; -cvar_t bgmvolume = SCVARF("musicvolume", "0", CVAR_ARCHIVE); -cvar_t volume = SCVARF("volume", "0.7", CVAR_ARCHIVE); +cvar_t bgmvolume = CVARF( "musicvolume", "0", CVAR_ARCHIVE); +cvar_t volume = CVARF( "volume", "0.7", CVAR_ARCHIVE); -cvar_t nosound = SCVAR("nosound", "0"); -cvar_t precache = FCVAR("s_precache", "precache", "1", 0); -cvar_t loadas8bit = FCVAR("s_loadas8bit", "loadas8bit", "0", 0); -cvar_t bgmbuffer = SCVAR("bgmbuffer", "4096"); -cvar_t ambient_level = FCVAR("s_ambientlevel", "ambient_level", "0.3", 0); -cvar_t ambient_fade = FCVAR("s_ambientfade", "ambient_fade", "100", 0); -cvar_t snd_noextraupdate = FCVAR("s_noextraupdate", "snd_noextraupdate", "0", 0); -cvar_t snd_show = FCVAR("s_show", "snd_show", "0", 0); -cvar_t snd_khz = FCVAR("s_khz", "snd_khz", "11", CVAR_ARCHIVE); -cvar_t snd_inactive = FCVAR("s_inactive", "snd_inactive", "0", 0); //set if you want sound even when tabbed out. -cvar_t _snd_mixahead = FCVAR("s_mixahead", "_snd_mixahead", "0.2", CVAR_ARCHIVE); -cvar_t snd_leftisright = FCVAR("s_swapstereo", "snd_leftisright", "0", CVAR_ARCHIVE); -cvar_t snd_eax = FCVAR("s_eax", "snd_eax", "0", 0); -cvar_t snd_speakers = FCVAR("s_numspeakers", "snd_numspeakers", "2", 0); -cvar_t snd_buffersize = FCVAR("s_buffersize", "snd_buffersize", "0", 0); -cvar_t snd_samplebits = FCVAR("s_bits", "snd_samplebits", "16", CVAR_ARCHIVE); -cvar_t snd_playersoundvolume = FCVAR("s_localvolume", "snd_localvolume", "1", 0); //sugested by crunch +cvar_t nosound = CVAR( "nosound", "0"); +cvar_t precache = CVARAF( "s_precache", "1", + "precache", 0); +cvar_t loadas8bit = CVARAF( "s_loadas8bit", "0", + "loadas8bit", 0); +cvar_t bgmbuffer = CVAR( "bgmbuffer", "4096"); +cvar_t ambient_level = CVARAF( "s_ambientlevel", "0.3", + "ambient_level", 0); +cvar_t ambient_fade = CVARAF( "s_ambientfade", "100", + "ambient_fade", 0); +cvar_t snd_noextraupdate = CVARAF( "s_noextraupdate", "0", + "snd_noextraupdate", 0); +cvar_t snd_show = CVARAF( "s_show", "0", + "snd_show", 0); +cvar_t snd_khz = CVARAF( "s_khz", "11", + "snd_khz", CVAR_ARCHIVE); +cvar_t snd_inactive = CVARAF( "s_inactive", "0", + "snd_inactive", 0); //set if you want sound even when tabbed out. +cvar_t _snd_mixahead = CVARAF( "s_mixahead", "0.2", + "_snd_mixahead", CVAR_ARCHIVE); +cvar_t snd_leftisright = CVARAF( "s_swapstereo", "0", + "snd_leftisright", CVAR_ARCHIVE); +cvar_t snd_eax = CVARAF( "s_eax", "0", + "snd_eax", 0); +cvar_t snd_speakers = CVARAF( "s_numspeakers", "2", + "snd_numspeakers", 0); +cvar_t snd_buffersize = CVARAF( "s_buffersize", "0", + "snd_buffersize", 0); +cvar_t snd_samplebits = CVARAF( "s_bits", "16", + "snd_samplebits", CVAR_ARCHIVE); +cvar_t snd_playersoundvolume = CVARAF( "s_localvolume", "1", + "snd_localvolume", 0); //sugested by crunch -cvar_t snd_capture = FCVAR("s_capture", "snd_capture", "0", 0); -cvar_t snd_linearresample = FCVAR("s_linearresample", "snd_linearresample", "1", 0); -cvar_t snd_linearresample_stream = FCVAR("s_linearresample_stream", "snd_linearresample_stream", "0", 0); +cvar_t snd_capture = CVARAF( "s_capture", "0", + "snd_capture", 0); +cvar_t snd_linearresample = CVARAF( "s_linearresample", "1", + "snd_linearresample", 0); +cvar_t snd_linearresample_stream = CVARAF( "s_linearresample_stream", "0", + "snd_linearresample_stream", 0); -cvar_t snd_usemultipledevices = FCVAR("s_multipledevices", "snd_multipledevices", "0", 0); +cvar_t snd_usemultipledevices = CVARAF( "s_multipledevices", "0", + "snd_multipledevices", 0); extern vfsfile_t *rawwritefile; diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 0ee0c0a5..e7bc9a02 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include +#include #ifndef __CYGWIN__ #include #include @@ -244,13 +245,13 @@ int Sys_DebugLog(char *file, char *fmt, ...) int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm) { -#include - DIR *dir, *dir2; + DIR *dir; char apath[MAX_OSPATH]; char file[MAX_OSPATH]; char truepath[MAX_OSPATH]; char *s; struct dirent *ent; + struct stat st; //printf("path = %s\n", gpath); //printf("match = %s\n", match); @@ -291,29 +292,25 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const if (!ent) break; if (*ent->d_name != '.') + { if (wildcmp(match, ent->d_name)) { - Q_snprintfz(file, sizeof(file), "%s/%s", gpath, ent->d_name); -//would use stat, but it breaks on fat32. + Q_snprintfz(file, sizeof(file), "%s/%s", truepath, ent->d_name); - if ((dir2 = opendir(file))) + if (stat(file, &st) == 0) { - closedir(dir2); - Q_snprintfz(file, sizeof(file), "%s%s/", apath, ent->d_name); -//printf("is directory = %s\n", file); + Q_snprintfz(file, sizeof(file), "%s%s%s", apath, ent->d_name, S_ISDIR(st.st_mode)?"/":""); + + if (!func(file, st.st_size, parm)) + { + closedir(dir); + return false; + } } else - { - Q_snprintfz(file, sizeof(file), "%s%s", apath, ent->d_name); -//printf("file = %s\n", file); - } - - if (!func(file, -2, parm)) - { - closedir(dir); - return false; - } + printf("Stat failed for \"%s\"\n", file); } + } } while(1); closedir(dir); diff --git a/engine/client/vid.h b/engine/client/vid.h index 65db8b22..a405583f 100644 --- a/engine/client/vid.h +++ b/engine/client/vid.h @@ -56,11 +56,6 @@ typedef struct int numpages; int recalc_refdef; // if true, recalc vid-based stuff -FTE_DEPRECATED pixel_t *conbuffer; -FTE_DEPRECATED int conrowbytes; -FTE_DEPRECATED unsigned conwidth; -FTE_DEPRECATED unsigned conheight; - unsigned pixelwidth; unsigned pixelheight; } viddef_t; diff --git a/engine/client/view.c b/engine/client/view.c index 8deb03bd..39c6be62 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1363,7 +1363,7 @@ void V_RenderPlayerViews(int plnum) r_refdef.viewangles[2]=e->angles[2];//*s+(1-s)*e->msg_angles[1][2]; r_refdef.viewangles[PITCH] *= -1; - r_secondaryview = 3; //show the player + r_refdef.externalview = true; //show the player R_RenderView (); // r_framecount = old_framecount; @@ -1390,7 +1390,7 @@ void V_RenderPlayerViews(int plnum) vid.recalc_refdef=true; } #endif - r_secondaryview = 0; + r_refdef.externalview = false; } void V_RenderView (void) diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 98ec4f0f..cd7cb331 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -163,8 +163,8 @@ void TP_SkinCvar_Callback(struct cvar_s *var, char *oldvalue); TP_CVAR(loc_name_suit, "suit") //create the globals for all the TP cvars. -#define TP_CVAR(name,def) cvar_t name = SCVAR(#name, def) -#define TP_CVARC(name,def,call) cvar_t name = SCVARC(#name, def, call) +#define TP_CVAR(name,def) cvar_t name = CVAR(#name, def) +#define TP_CVARC(name,def,call) cvar_t name = CVARC(#name, def, call) TP_CVARS; #undef TP_CVAR #undef TP_CVARC diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 8883aaf8..e5445f0a 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -125,7 +125,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PSET_CLASSIC - #define CSQC_DAT //support for csqc + //#define CSQC_DAT //support for csqc #ifndef SERVERONLY //don't be stupid, stupid. #ifndef CLIENTONLY @@ -298,6 +298,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PROTOCOLEXTENSIONS +#ifdef MINIMAL + #define IFMINIMAL(x,y) x +#else + #define IFMINIMAL(x,y) y +#endif + //#define PRE_SAYONE 2.487 //FIXME: remove. // defs common to client and server @@ -361,6 +367,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MSVCDISABLEWARNINGS #if _MSC_VER >= 1300 #define FTE_DEPRECATED __declspec(deprecated) + #define _CRT_SECURE_NO_WARNINGS + #define _CRT_NONSTDC_NO_WARNINGS #endif #define NORETURN __declspec(noreturn) #endif diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index f53ef3b0..76c778bb 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -768,3 +768,15 @@ typedef struct int patchwidth; int patchheight; } rbspface_t; + +#define MAX_ENT_LEAFS 16 +typedef struct pvscache_s +{ + int num_leafs; + short leafnums[MAX_ENT_LEAFS]; +#ifdef Q2BSPS + int areanum; //q2bsp + int areanum2; //q2bsp + int headnode; //q2bsp +#endif +} pvscache_t; diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 92f3f9cb..6201ed51 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" -cvar_t com_fs_cache = SCVARF("fs_cache", "1", CVAR_ARCHIVE); +cvar_t com_fs_cache = SCVARF("fs_cache", IFMINIMAL("2","1"), CVAR_ARCHIVE); cvar_t rcon_level = SCVAR("rcon_level", "20"); cvar_t cmd_maxbuffersize = SCVAR("cmd_maxbuffersize", "65536"); int Cmd_ExecLevel; @@ -2607,7 +2607,7 @@ void Cmd_set_f(void) else docalc = false; - var = Cvar_Get (Cmd_Argv(1), "0", 0, "Custom variables"); + var = Cvar_Get (Cmd_Argv(1), "", 0, "Custom variables"); if (Cmd_FromGamecode()) //AAHHHH!!! Q2 set command is different { diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index a5d92af9..bf772b48 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1380,7 +1380,7 @@ void Mod_CompileTriangleNeighbours(galiasinfo_t *galias) #ifdef GLQUAKE if (qrenderer != QR_OPENGL) return; - if (r_shadow_realtime_dlight_shadows.value || r_shadow_realtime_world_shadows.value) + if (r_shadow_realtime_dlight_shadows.ival || r_shadow_realtime_world_shadows.ival) { int *neighbours; neighbours = Hunk_Alloc(sizeof(int)*galias->numindexes/3*3); @@ -2612,7 +2612,7 @@ qboolean Mod_LoadQ2Model (model_t *mod, void *buffer) { pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vecV_t)*numverts #ifndef SERVERONLY - + sizeof(vec3_t)*numverts + + 3*sizeof(vec3_t)*numverts #endif ); poutframe->poseofs = (char *)pose - (char *)poutframe; @@ -2624,6 +2624,9 @@ qboolean Mod_LoadQ2Model (model_t *mod, void *buffer) #ifndef SERVERONLY normals = (vec3_t*)&verts[galias->numverts]; pose->ofsnormals = (char *)normals - (char *)pose; + + pose->ofssvector = (char *)&normals[galias->numverts] - (char *)pose; + pose->ofstvector = (char *)&normals[galias->numverts*2] - (char *)pose; #endif diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index e303725f..e4df89b3 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -38,7 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //#define ODE_DYNAMIC 1 //#endif -cvar_t physics_ode_enable = SCVAR("physics_ode_enable", "1"); +cvar_t physics_ode_enable = CVARD("physics_ode_enable", IFMINIMAL("0", "1"), "Enables the use of ODE physics, but only if the mod supports it."); cvar_t physics_ode_quadtree_depth = CVARDP4(0, "physics_ode_quadtree_depth","5", "desired subdivision level of quadtree culling space"); cvar_t physics_ode_contactsurfacelayer = CVARDP4(0, "physics_ode_contactsurfacelayer","0", "allows objects to overlap this many units to reduce jitter"); cvar_t physics_ode_worldquickstep = CVARDP4(0, "physics_ode_worldquickstep","1", "use dWorldQuickStep rather than dWorldStep"); diff --git a/engine/common/common.c b/engine/common/common.c index 5b65efd2..313a2f6d 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -44,11 +44,11 @@ static char *argvdummy = " "; static char *safeargvs[NUM_SAFE_ARGVS] = {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse"}; -cvar_t registered = SCVAR("registered","0"); -cvar_t gameversion = SCVARF("gameversion","", CVAR_SERVERINFO); -cvar_t com_gamename = SCVAR("com_gamename", ""); -cvar_t com_modname = SCVAR("com_modname", ""); -cvar_t com_parseutf8 = SCVAR("com_parseutf8", "0"); //1 parse. 2 parse, but stop parsing that string if a char was malformed. +cvar_t registered = CVARD("registered","0","Set if quake's pak1.pak is available"); +cvar_t gameversion = CVARFD("gameversion","", CVAR_SERVERINFO, "gamecode version for server browsers"); +cvar_t com_gamename = CVARD("com_gamename", "", "The game name used for dpmaster queries"); +cvar_t com_modname = CVARD("com_modname", "", "dpmaster information"); +cvar_t com_parseutf8 = CVARD("com_parseutf8", "0", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts."); //1 parse. 2 parse, but stop parsing that string if a char was malformed. qboolean com_modified; // set true if using non-id files @@ -2003,7 +2003,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t ext = extstack[extstackdepth]; } } - else if (str[1] == 'U') //restore from stack (it's great for names) + else if (str[1] == 'U') //unicode (16bit) char ^Uxxxx { if (!keepmarkup) { diff --git a/engine/common/common.h b/engine/common/common.h index 038a50b8..00fd3b88 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -378,6 +378,7 @@ char *COM_GetPathInfo (int i, int *crc); char *COM_NextPath (char *prevpath); void COM_FlushFSCache(void); //a file was written using fopen void COM_RefreshFSCache_f(void); +qboolean FS_Restarted(unsigned int *since); void COM_InitFilesystem (void); void FS_Shutdown(void); @@ -402,7 +403,7 @@ char *COM_Effectinfo_ForNumber(unsigned int efnum); unsigned int COM_RemapMapChecksum(unsigned int checksum); -#define MAX_INFO_KEY 64 +#define MAX_INFO_KEY 256 char *Info_ValueForKey (char *s, const char *key); void Info_RemoveKey (char *s, const char *key); char *Info_KeyForNumber (char *s, int num); diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 8cba6eda..0efba7b1 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -24,6 +24,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. cvar_group_t *cvar_groups; +hashtable_t cvar_hash; +bucket_t *cvar_buckets[1024]; + //cvar_t *cvar_vars; static char *cvar_null_string = ""; static char *cvar_zero_string = "0"; @@ -65,6 +68,8 @@ Cvar_FindVar */ cvar_t *Cvar_FindVar (const char *var_name) { + return Hash_GetInsensative(&cvar_hash, var_name); +/* cvar_group_t *grp; cvar_t *var; @@ -76,7 +81,7 @@ cvar_t *Cvar_FindVar (const char *var_name) if (var->name2 && !Q_strcasecmp (var_name, var->name2)) return var; } - +*/ return NULL; } @@ -885,6 +890,9 @@ unlinked: Cvar_DefaultFree(tbf->defaultstr); if (tbf->latched_string) Z_Free(tbf->latched_string); + Hash_RemoveData(&cvar_hash, tbf->name, tbf); + if (tbf->name2) + Hash_RemoveData(&cvar_hash, tbf->name2, tbf); Z_Free(tbf); } @@ -939,6 +947,11 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname) Cvar_SetCore (variable, old->string, true); Cvar_Free(old); + + Hash_AddInsensative(&cvar_hash, variable->name, variable, &variable->hbn1); + if (variable->name2) + Hash_AddInsensative(&cvar_hash, variable->name2, variable, &variable->hbn2); + return false; } @@ -960,6 +973,10 @@ qboolean Cvar_Register (cvar_t *variable, const char *groupname) variable->restriction = 0; //exe registered vars group->cvars = variable; + Hash_AddInsensative(&cvar_hash, variable->name, variable, &variable->hbn1); + if (variable->name2) + Hash_AddInsensative(&cvar_hash, variable->name2, variable, &variable->hbn2); + variable->string = (char*)Z_Malloc (1); if (variable->flags & CVAR_FREEDEFAULT) @@ -1209,6 +1226,12 @@ void Cvar_Limiter_ZeroToOne_Callback(struct cvar_s *var, char *oldvalue) } } +void Cvar_Init(void) +{ + memset(cvar_buckets, 0, sizeof(cvar_buckets)); + Hash_InitTable(&cvar_hash, sizeof(cvar_buckets)/Hash_BytesForBuckets(1), cvar_buckets); +} + void Cvar_Shutdown(void) { cvar_t *var; diff --git a/engine/common/cvar.h b/engine/common/cvar.h index 992a4a9e..bc876202 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -53,6 +53,8 @@ Cvars are restricted from having the same names as commands to keep this interface from being ambiguous. */ +#include "hash.h" + typedef struct cvar_s { //must match q2's definition @@ -68,6 +70,7 @@ typedef struct cvar_s char *name2; void (*callback) (struct cvar_s *var, char *oldvalue); + char *description; int ival; @@ -78,15 +81,23 @@ typedef struct cvar_s #ifdef HLSERVER struct hlcvar_s *hlcvar; #endif + bucket_t hbn1, hbn2; } cvar_t; -#define FCVARC(ConsoleName,ConsoleName2,Value,Flags,Callback) {ConsoleName, Value, NULL, Flags, 0, 0, 0, ConsoleName2, Callback} -#define FCVAR(ConsoleName,ConsoleName2,Value,Flags) FCVARC(ConsoleName, ConsoleName2, Value, Flags, NULL) -#define SCVARFC(ConsoleName, Value, Flags, Callback) FCVARC(ConsoleName, NULL, Value, Flags, Callback) -#define SCVARF(ConsoleName,Value, Flags) FCVAR(ConsoleName, NULL, Value, Flags) -#define SCVARC(ConsoleName,Value,Callback) FCVARC(ConsoleName, NULL, Value, 0, Callback) -#define SCVAR(ConsoleName,Value) FCVAR(ConsoleName, NULL, Value, 0) -#define CVARDP4(Flags,ConsoleName,Value,Description) FCVAR(ConsoleName, NULL, Value, Flags) +#define CVARAFDC(ConsoleName,Value,ConsoleName2,Flags,Description,Callback) {ConsoleName, Value, NULL, Flags, 0, 0, 0, ConsoleName2, Callback, Description} +#define CVARAFC(ConsoleName,Value,ConsoleName2,Flags,Callback) CVARAFC(ConsoleName, Value, ConsoleName2, Flags, NULL, Callback) +#define CVARAFD(ConsoleName,Value,ConsoleName2,Flags,Description)CVARAFDC(ConsoleName, Value, ConsoleName2, Flags, Description, NULL) +#define CVARAF(ConsoleName,Value,ConsoleName2,Flags) CVARAFDC(ConsoleName, Value, ConsoleName2, Flags, NULL, NULL) +#define CVARFC(ConsoleName,Value,Flags,Callback) CVARAFDC(ConsoleName, Value, NULL, Flags, NULL, Callback) +#define CVARFD(ConsoleName,Value,Flags,Description) CVARAFDC(ConsoleName, Value, NULL, Flags, Description, NULL) +#define CVARF(ConsoleName,Value,Flags) CVARFC(ConsoleName, Value, Flags, NULL) +#define CVARC(ConsoleName,Value,Callback) CVARFC(ConsoleName, Value, 0, Callback) +#define CVARD(ConsoleName,Value,Description) CVARAFDC(ConsoleName, Value, NULL, 0, Description, NULL) +#define CVAR(ConsoleName,Value) CVARD(ConsoleName, Value, NULL) + +#define SCVAR(ConsoleName,Value) CVAR(ConsoleName,Value) +#define SCVARF(ConsoleName,Value,Flags) CVARF(ConsoleName,Value,Flags) +#define CVARDP4(Flags,ConsoleName,Value,Description) CVARFD(ConsoleName, Value, Flags,Description) typedef struct cvar_group_s { @@ -182,6 +193,7 @@ void Cvar_WriteVariables (vfsfile_t *f, qboolean all); cvar_t *Cvar_FindVar (const char *var_name); +void Cvar_Init(void); void Cvar_Shutdown(void); void Cvar_ForceCheatVars(qboolean semicheats, qboolean absolutecheats); //locks/unlocks cheat cvars depending on weather we are allowed them. diff --git a/engine/common/fs.c b/engine/common/fs.c index 514f7a54..2ca34796 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -19,6 +19,7 @@ hashtable_t filesystemhash; qboolean com_fschanged = true; +static unsigned int fs_restarts; extern cvar_t com_fs_cache; int active_fs_cachetype; @@ -491,7 +492,7 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation goto fail; } - if (com_fs_cache.value) + if (com_fs_cache.ival) { if (com_fschanged) FS_RebuildFSHash(); @@ -987,9 +988,11 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r if (strcmp(mode, "rb")) - if (strcmp(mode, "wb")) - if (strcmp(mode, "ab")) - return NULL; //urm, unable to write/append + if (strcmp(mode, "r+b")) + if (strcmp(mode, "wb")) + if (strcmp(mode, "w+b")) + if (strcmp(mode, "ab")) + return NULL; //urm, unable to write/append //if there can only be one file (eg: write access) find out where it is. switch (relativeto) @@ -1527,9 +1530,21 @@ void COM_RefreshFSCache_f(void) void COM_FlushFSCache(void) { - if (com_fs_cache.value != 2) + if (com_fs_cache.ival != 2) com_fschanged=true; } + +/*since should start as 0, otherwise this can be used to poll*/ +qboolean FS_Restarted(unsigned int *since) +{ + if (*since < fs_restarts) + { + *since = fs_restarts; + return true; + } + return false; +} + /* ================ FS_AddGameDirectory @@ -1544,6 +1559,8 @@ void FS_AddGameDirectory (const char *puredir, const char *dir, unsigned int loa char *p; + fs_restarts++; + if ((p = strrchr(dir, '/')) != NULL) strcpy(gamedirfile, ++p); else @@ -2164,8 +2181,6 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base } #if !defined(NPQTV) && !defined(SERVERONLY) //this is *really* unfortunate, but doing this crashes the browser - //I assume its because the client - if (poshname) { char resultpath[MAX_PATH]; diff --git a/engine/common/fs_win32.c b/engine/common/fs_win32.c index 3b10185e..21a4af02 100644 --- a/engine/common/fs_win32.c +++ b/engine/common/fs_win32.c @@ -112,6 +112,8 @@ vfsfile_t *VFSW32_Open(const char *osname, const char *mode) qboolean append = !!strchr(mode, 'a'); qboolean text = !!strchr(mode, 't'); write |= append; + if (strchr(mode, '+')) + read = write = true; if (write && read) h = CreateFileA(osname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index fc620c0c..04271705 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -32,12 +32,6 @@ qboolean RMod_LoadMarksurfaces (lump_t *l); qboolean RMod_LoadSurfedges (lump_t *l); void RMod_LoadLighting (lump_t *l); -qboolean SWMod_LoadVertexes (lump_t *l); -qboolean SWMod_LoadEdges (lump_t *l); -qboolean SWMod_LoadMarksurfaces (lump_t *l); -qboolean SWMod_LoadSurfedges (lump_t *l); -void SWMod_LoadLighting (lump_t *l); - void Q2BSP_SetHullFuncs(hull_t *hull); qboolean CM_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace); @@ -131,6 +125,28 @@ void ClearBounds (vec3_t mins, vec3_t maxs) } +void Mod_SortShaders(void) +{ + texture_t *textemp; + int i, j; + + //sort loadmodel->textures + for (i = 0; i < loadmodel->numtextures; i++) + { + for (j = i+1; j < loadmodel->numtextures; j++) + { + if ((loadmodel->textures[i]->shader && loadmodel->textures[j]->shader) && (loadmodel->textures[j]->shader->sort < loadmodel->textures[i]->shader->sort)) + { + textemp = loadmodel->textures[j]; + loadmodel->textures[j] = loadmodel->textures[i]; + loadmodel->textures[i] = textemp; + } + } + } +} + + + #ifdef Q2BSPS qbyte *ReadPCXPalette(qbyte *buf, int len, qbyte *out); @@ -256,15 +272,13 @@ typedef struct int patch_cp[2]; } q3cface_t; +/*used to trace*/ int checkcount; -//FIXME: Unlimit these. -char map_name[MAX_QPATH]; - int numbrushsides; q2cbrushside_t map_brushsides[MAX_Q2MAP_BRUSHSIDES]; -int numtexinfo; +int numtexinfo; q2mapsurface_t *map_surfaces; int numplanes; @@ -363,10 +377,6 @@ int numleaffaces; - - - - int PlaneTypeForNormal ( vec3_t normal ) { vec_t ax, ay, az; @@ -624,7 +634,6 @@ static void SnapPlane( vec3_t normal, vec_t *dist ) =============================================================================== */ -#if 1 #define MAX_FACET_PLANES 32 #define cm_subdivlevel 15 @@ -810,7 +819,7 @@ static void CM_CreatePatch( q3cpatch_t *patch, q2mapsurface_t *shaderref, const data = BZ_Malloc( size[0] * size[1] * sizeof( vecV_t ) + ( size[0]-1 ) * ( size[1]-1 ) * 2 * ( sizeof( q2cbrush_t ) + 32 * sizeof( mplane_t ) ) ); - points = ( vec3_t * )data; data += size[0] * size[1] * sizeof( vecV_t ); + points = ( vecV_t * )data; data += size[0] * size[1] * sizeof( vecV_t ); facets = ( q2cbrush_t * )data; data += ( size[0]-1 ) * ( size[1]-1 ) * 2 * sizeof( q2cbrush_t ); brushplanes = ( mplane_t * )data; data += ( size[0]-1 ) * ( size[1]-1 ) * 2 * MAX_FACET_PLANES * sizeof( mplane_t ); @@ -899,218 +908,6 @@ static void CM_CreatePatch( q3cpatch_t *patch, q2mapsurface_t *shaderref, const BZ_Free( points ); } -#else - -#define cm_subdivlevel 15 - -qboolean CM_CreateBrush ( q2cbrush_t *brush, vec3_t *verts, q2mapsurface_t *surface ) -{ - int i, j, k, sign; - vec3_t v1, v2; - vec3_t absmins, absmaxs; - q2cbrushside_t *side; - mplane_t *plane; - static mplane_t mainplane, patchplanes[20]; - qboolean skip[20]; - int numpatchplanes = 0; - - // calc absmins & absmaxs - ClearBounds ( absmins, absmaxs ); - for (i = 0; i < 3; i++) - AddPointToBounds ( verts[i], absmins, absmaxs ); - - PlaneFromPoints ( verts, &mainplane ); - - // front plane - plane = &patchplanes[numpatchplanes++]; - *plane = mainplane; - - // back plane - plane = &patchplanes[numpatchplanes++]; - VectorNegate (mainplane.normal, plane->normal); - plane->dist = -mainplane.dist; - - // axial planes - for ( i = 0; i < 3; i++ ) - { - for (sign = -1; sign <= 1; sign += 2) - { - plane = &patchplanes[numpatchplanes++]; - if (numpatchplanes > 20) - return false; - VectorClear ( plane->normal ); - plane->normal[i] = sign; - plane->dist = sign > 0 ? absmaxs[i] : -absmins[i]; - } - } - - // edge planes - for ( i = 0; i < 3; i++ ) - { - vec3_t normal; - - VectorCopy (verts[i], v1); - VectorCopy (verts[(i + 1) % 3], v2); - - for ( k = 0; k < 3; k++ ) - { - normal[k] = 0; - normal[(k+1)%3] = v1[(k+2)%3] - v2[(k+2)%3]; - normal[(k+2)%3] = -(v1[(k+1)%3] - v2[(k+1)%3]); - - if (VectorEquals (normal, vec3_origin)) - continue; - - plane = &patchplanes[numpatchplanes++]; - if (numpatchplanes > 20) - return false; - - VectorNormalize ( normal ); - VectorCopy ( normal, plane->normal ); - plane->dist = DotProduct (plane->normal, v1); - - if ( DotProduct(verts[(i + 2) % 3], normal) - plane->dist > 0 ) - { // invert - VectorInverse ( plane->normal ); - plane->dist = -plane->dist; - } - } - } - - // set plane->type and mark duplicate planes for removal - for (i = 0; i < numpatchplanes; i++) - { - CategorizePlane ( &patchplanes[i] ); - skip[i] = false; - - for (j = i + 1; j < numpatchplanes; j++) - if ( patchplanes[j].dist == patchplanes[i].dist - && VectorEquals (patchplanes[j].normal, patchplanes[i].normal) ) - { - skip[i] = true; - break; - } - } - - brush->numsides = 0; - brush->brushside = Hunk_Alloc((sizeof(*plane) + sizeof(*side))*numpatchplanes); - plane = (mplane_t*)(brush->brushside+numpatchplanes); - - for (k = 0; k < 2; k++) - { - for (i = 0; i < numpatchplanes; i++) - { - if (skip[i]) - continue; - - // first, store all axially aligned planes - // then store everything else - // does it give a noticeable speedup? - if (!k && patchplanes[i].type >= 3) - continue; - - skip[i] = true; - - side = brush->brushside + brush->numsides; - side->plane = plane+brush->numsides; - plane[brush->numsides] = patchplanes[i]; - brush->numsides++; - - if (DotProduct(plane->normal, mainplane.normal) >= 0) - side->surface = surface; - else - side->surface = NULL; // don't clip against this side - } - } - - return true; -} - -qboolean CM_CreatePatch ( q3cpatch_t *patch, int numverts, const vec_t *verts, int *patch_cp ) -{ - int step[2], size[2], flat[2], i, u, v; - vec4_t points[MAX_CM_PATCH_VERTS], pointss[MAX_CM_PATCH_VERTS]; - vec3_t tverts[4], tverts2[4]; - q2cbrush_t *brush; - mplane_t mainplane; - -// find the degree of subdivision in the u and v directions - Patch_GetFlatness ( cm_subdivlevel, verts, patch_cp, flat ); - - step[0] = (1 << flat[0]); - step[1] = (1 << flat[1]); - size[0] = (patch_cp[0] / 2) * step[0] + 1; - size[1] = (patch_cp[1] / 2) * step[1] + 1; - - if ( size[0] * size[1] > MAX_CM_PATCH_VERTS ) - { - return true; - Con_Printf (CON_ERROR "CM_CreatePatch: patch has too many vertices\n"); - return false; - } - - for (i = 0; i < numverts; i++) - VectorCopy(verts[i], pointss[i]); -// fill in -//gcc warns without this cast - Patch_Evaluate ( (const vec4_t *)pointss, patch_cp, step, points ); -/* - for (i = 0; i < numverts; i++) - { - points[i][0] = (int)(points[i][0]*20)/20.0f; - points[i][1] = (int)(points[i][1]*20)/20.0f; - points[i][2] = (int)(points[i][2]*20)/20.0f; - } -*/ - patch->brushes = brush = map_brushes + numbrushes; - patch->numbrushes = 0; - - ClearBounds (patch->absmins, patch->absmaxs); - -// create a set of brushes - for (v = 0; v < size[1]-1; v++) - { - for (u = 0; u < size[0]-1; u++) - { - if (numbrushes >= MAX_CM_BRUSHES) - { - Con_Printf (CON_ERROR "CM_CreatePatch: too many patch brushes\n"); - return false; - } - - i = v * size[0] + u; - VectorCopy (points[i], tverts[0]); - VectorCopy (points[i + size[0]], tverts[1]); - VectorCopy (points[i + 1], tverts[2]); - VectorCopy (points[i + size[0] + 1], tverts[3]); - - for (i = 0; i < 4; i++) - AddPointToBounds (tverts[i], patch->absmins, patch->absmaxs); - - PlaneFromPoints (tverts, &mainplane); - - // create two brushes - if (!CM_CreateBrush (brush, tverts, patch->surface)) - return false; - - brush->contents = patch->surface->c.value; - brush++; numbrushes++; patch->numbrushes++; - - VectorCopy (tverts[2], tverts2[0]); - VectorCopy (tverts[1], tverts2[1]); - VectorCopy (tverts[3], tverts2[2]); - if (!CM_CreateBrush (brush, tverts2, patch->surface)) - return false; - - brush->contents = patch->surface->c.value; - brush++; numbrushes++; patch->numbrushes++; - } - } - - return true; -} -#endif - //====================================================== /* @@ -1154,7 +951,7 @@ qboolean CM_CreatePatchesForLeafs (void) continue; if (face->patch_cp[0] <= 0 || face->patch_cp[1] <= 0) continue; - if (face->shadernum < 0 || face->shadernum >= numtexinfo) + if (face->shadernum < 0 || face->shadernum >= loadmodel->numtextures) continue; surf = &map_surfaces[face->shadernum]; @@ -1186,7 +983,7 @@ qboolean CM_CreatePatchesForLeafs (void) checkout[k] = numpatches++; //gcc warns without this cast - CM_CreatePatch ( patch, surf, (const vec_t *)map_verts + face->firstvert, face->patch_cp ); + CM_CreatePatch ( patch, surf, (const vec_t *)(map_verts + face->firstvert), face->patch_cp ); } leaf->contents |= patch->surface->c.value; @@ -1302,13 +1099,7 @@ qboolean CMod_LoadSurfaces (lump_t *l) return true; } #ifndef SERVERONLY -qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height); -qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, int asgrey); - - -qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, int asgrey); -qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height); -texture_t *Mod_LoadWall(char *name) +texture_t *Mod_LoadWall(char *name, char *sname) { qbyte *in, *oin; texture_t *tex; @@ -1363,7 +1154,7 @@ texture_t *Mod_LoadWall(char *name) BZ_Free(wal); - tex->shader = R_RegisterShader_Lightmap(name); + tex->shader = R_RegisterCustom (sname, Shader_DefaultBSPQ2, NULL); R_BuildDefaultTexnums(&tn, tex->shader); return tex; @@ -1375,6 +1166,7 @@ qboolean CMod_LoadTexInfo (lump_t *l) //yes I know these load from the same plac mtexinfo_t *out; int i, j, count; char name[MAX_QPATH], *lwr; + char sname[MAX_QPATH]; float len1, len2; int texcount; @@ -1411,10 +1203,17 @@ qboolean CMod_LoadTexInfo (lump_t *l) //yes I know these load from the same plac else out->mipadjust = 1; - //damn q2... compact the textures. + if (out->flags & TI_SKY) + snprintf(sname, sizeof(sname), "sky/%s", in->texture); + else if (out->flags & (TI_WARP|TI_TRANS33|TI_TRANS66)) + snprintf(sname, sizeof(sname), "%s%s/%s", ((out->flags&TI_WARP)?"warp":"trans"), ((out->flags&TI_TRANS66)?"66":(out->flags&TI_TRANS33?"33":"")), in->texture); + else + snprintf(sname, sizeof(sname), "wall/%s", in->texture); + + //compact the textures. for (j=0; j < texcount; j++) { - if (!strcmp(in->texture, loadmodel->textures[j]->name)) + if (!strcmp(sname, loadmodel->textures[j]->name)) { out->texture = loadmodel->textures[j]; break; @@ -1429,24 +1228,24 @@ qboolean CMod_LoadTexInfo (lump_t *l) //yes I know these load from the same plac } snprintf (name, sizeof(name), "textures/%s.wal", in->texture); - out->texture = Mod_LoadWall (name); + out->texture = Mod_LoadWall (name, sname); if (!out->texture || !out->texture->width || !out->texture->height) { out->texture = Hunk_Alloc(sizeof(texture_t) + 16*16+8*8+4*4+2*2); Con_Printf (CON_WARNING "Couldn't load %s\n", name); memcpy(out->texture, r_notexture_mip, sizeof(texture_t) + 16*16+8*8+4*4+2*2); - // out->texture = r_notexture_mip; // texture not found - // out->flags = 0; } - Q_strncpyz(out->texture->name, in->texture, sizeof(out->texture->name)); + Q_strncpyz(out->texture->name, sname, sizeof(out->texture->name)); loadmodel->textures[texcount++] = out->texture; } } loadmodel->numtextures = texcount; + + Mod_SortShaders(); return true; } #endif @@ -2660,28 +2459,6 @@ mesh_t *GL_CreateMeshForPatch (model_t *mod, int patchwidth, int patchheight, in return mesh; } - -void CModQ3_SortShaders(void) -{ - texture_t *textemp; - int i, j; - - //sort loadmodel->textures - for (i = 0; i < numtexinfo; i++) - { - for (j = i+1; j < numtexinfo; j++) - { - if ((loadmodel->textures[i]->shader && loadmodel->textures[j]->shader) && (loadmodel->textures[j]->shader->sort < loadmodel->textures[i]->shader->sort)) - { - textemp = loadmodel->textures[j]; - loadmodel->textures[j] = loadmodel->textures[i]; - loadmodel->textures[i] = textemp; - } - } - } -} - -mesh_t nullmesh; qboolean CModQ3_LoadRFaces (lump_t *l) { q3dface_t *in; @@ -2834,7 +2611,7 @@ qboolean CModQ3_LoadRFaces (lump_t *l) Mod_NormaliseTextureVectors(map_normals_array, map_svector_array, map_tvector_array, numvertexes); - CModQ3_SortShaders(); + Mod_SortShaders(); return true; } @@ -2977,7 +2754,7 @@ qboolean CModRBSP_LoadRFaces (lump_t *l) */ } } - CModQ3_SortShaders(); + Mod_SortShaders(); return true; } @@ -3786,7 +3563,6 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned numvisibility = 0; numentitychars = 0; map_entitystring = NULL; - map_name[0] = 0; loadmodel->type = mod_brush; @@ -3940,7 +3716,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned #ifndef CLIENTONLY loadmodel->funcs.FatPVS = Q2BSP_FatPVS; loadmodel->funcs.EdictInFatPVS = Q2BSP_EdictInFatPVS; - loadmodel->funcs.FindTouchedLeafs_Q1 = Q2BSP_FindTouchedLeafs; + loadmodel->funcs.FindTouchedLeafs = Q2BSP_FindTouchedLeafs; #endif loadmodel->funcs.LeafPVS = CM_LeafnumPVS; loadmodel->funcs.LeafnumForPoint = CM_PointLeafnum; @@ -4040,7 +3816,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned #ifndef CLIENTONLY loadmodel->funcs.FatPVS = Q2BSP_FatPVS; loadmodel->funcs.EdictInFatPVS = Q2BSP_EdictInFatPVS; - loadmodel->funcs.FindTouchedLeafs_Q1 = Q2BSP_FindTouchedLeafs; + loadmodel->funcs.FindTouchedLeafs = Q2BSP_FindTouchedLeafs; #endif loadmodel->funcs.LightPointValues = NULL; loadmodel->funcs.StainNode = NULL; @@ -4090,7 +3866,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned #ifndef CLIENTONLY loadmodel->funcs.FatPVS = Q2BSP_FatPVS; loadmodel->funcs.EdictInFatPVS = Q2BSP_EdictInFatPVS; - loadmodel->funcs.FindTouchedLeafs_Q1 = Q2BSP_FindTouchedLeafs; + loadmodel->funcs.FindTouchedLeafs = Q2BSP_FindTouchedLeafs; #endif loadmodel->funcs.LightPointValues = GLQ2BSP_LightPointValues; loadmodel->funcs.StainNode = GLR_Q2BSP_StainNode; @@ -4122,10 +3898,6 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned memset (portalopen, 0, sizeof(portalopen)); //make them start closed. FloodAreaConnections (); - strcpy (map_name, name); - - - loadmodel->checksum = loadmodel->checksum2 = *checksum; @@ -4278,7 +4050,7 @@ void CM_InitBoxHull (void) #ifndef CLIENTONLY box_model.funcs.FatPVS = Q2BSP_FatPVS; box_model.funcs.EdictInFatPVS = Q2BSP_EdictInFatPVS; - box_model.funcs.FindTouchedLeafs_Q1 = Q2BSP_FindTouchedLeafs; + box_model.funcs.FindTouchedLeafs = Q2BSP_FindTouchedLeafs; #endif #ifndef SERVERONLY diff --git a/engine/common/log.c b/engine/common/log.c index f5fa7c1e..2a2b10d3 100644 --- a/engine/common/log.c +++ b/engine/common/log.c @@ -8,16 +8,16 @@ void Log_Name_Callback (struct cvar_s *var, char *oldvalue); // cvars #define CONLOGGROUP "Console logging" -cvar_t log_enable[LOG_TYPES] = { SCVARF("log_enable", "0", CVAR_NOTFROMSERVER), - SCVARF("log_enable_players", "0", CVAR_NOTFROMSERVER)}; -cvar_t log_name[LOG_TYPES] = { SCVARFC("log_name", "", CVAR_NOTFROMSERVER, Log_Name_Callback), - SCVARFC("log_name_players", "", CVAR_NOTFROMSERVER, Log_Name_Callback)}; -cvar_t log_dir = SCVARFC("log_dir", "", CVAR_NOTFROMSERVER, Log_Dir_Callback); -cvar_t log_readable = SCVARF("log_readable", "0", CVAR_NOTFROMSERVER); -cvar_t log_developer = SCVARF("log_developer", "0", CVAR_NOTFROMSERVER); -cvar_t log_rotate_files = SCVARF("log_rotate_files", "0", CVAR_NOTFROMSERVER); -cvar_t log_rotate_size = SCVARF("log_rotate_size", "131072", CVAR_NOTFROMSERVER); -cvar_t log_dosformat = SCVARF("log_dosformat", "0", CVAR_NOTFROMSERVER); +cvar_t log_enable[LOG_TYPES] = { CVARF("log_enable", "0", CVAR_NOTFROMSERVER), + CVARF("log_enable_players", "0", CVAR_NOTFROMSERVER)}; +cvar_t log_name[LOG_TYPES] = { CVARFC("log_name", "", CVAR_NOTFROMSERVER, Log_Name_Callback), + CVARFC("log_name_players", "", CVAR_NOTFROMSERVER, Log_Name_Callback)}; +cvar_t log_dir = CVARFC("log_dir", "", CVAR_NOTFROMSERVER, Log_Dir_Callback); +cvar_t log_readable = CVARF("log_readable", "0", CVAR_NOTFROMSERVER); +cvar_t log_developer = CVARF("log_developer", "0", CVAR_NOTFROMSERVER); +cvar_t log_rotate_files = CVARF("log_rotate_files", "0", CVAR_NOTFROMSERVER); +cvar_t log_rotate_size = CVARF("log_rotate_size", "131072", CVAR_NOTFROMSERVER); +cvar_t log_dosformat = CVARF("log_dosformat", "0", CVAR_NOTFROMSERVER); // externals extern char gamedirfile[]; diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 556c6701..9d2276c6 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -167,6 +167,7 @@ void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]); void R_ConcatRotationsPad (float in1[3][4], float in2[3][4], float out[3][4]); void R_ConcatTransforms (matrix3x4 in1, matrix3x4 in2, matrix3x4 out); void RotatePointAroundVector (vec3_t dst, const vec3_t dir, const vec3_t point, float degrees); +void RotateLightVector(const vec3_t *axis, const vec3_t origin, const vec3_t lightpoint, vec3_t result); int VectorCompare (const vec3_t v1, const vec3_t v2); void VectorInverse (vec3_t v); void _VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t vecc); diff --git a/engine/common/particles.h b/engine/common/particles.h index 6a8643a1..9da8b815 100644 --- a/engine/common/particles.h +++ b/engine/common/particles.h @@ -89,6 +89,7 @@ typedef enum { BM_BLEND, BM_BLENDCOLOUR, BM_ADD, BM_SUBTRACT } blendmode_t; // used for callback extern cvar_t r_particlesdesc; +extern cvar_t r_particlesystem; struct model_s; struct msurface_s; @@ -137,7 +138,7 @@ typedef struct { void (*ParticleTrailIndex) (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk); void (*EmitSkyEffectTris) (struct model_s *mod, struct msurface_s *fa); - void (*InitParticles) (void); + qboolean (*InitParticles) (void); void (*ShutdownParticles) (void); void (*DelinkTrailstate) (trailstate_t **tsk); void (*ClearParticles) (void); diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index aba166bc..ccf1fd9b 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -385,6 +385,14 @@ void PF_cvar_defstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_CSTRING(cv->defaultstr); } +//string(string cvarname) cvar_description +void PF_cvar_description (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str = PR_GetStringOfs(prinst, OFS_PARM0); + cvar_t *cv = Cvar_Get(str, "", 0, "QC variables"); + RETURN_CSTRING(cv->description); +} + //float(string name) cvar_type void PF_cvar_type (progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -1510,6 +1518,65 @@ void PF_instr (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_SSTRING(sub); //last as long as the original string } +void PF_strreplace (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char resultbuf[4096]; + char *result = resultbuf; + char *search = PR_GetStringOfs(prinst, OFS_PARM0); + char *replace = PR_GetStringOfs(prinst, OFS_PARM1); + char *subject = PR_GetStringOfs(prinst, OFS_PARM2); + int searchlen = strlen(search); + int replacelen = strlen(replace); + + if (searchlen) + { + while (*subject && result < resultbuf + sizeof(resultbuf) - replacelen - 2) + { + if (!strncmp(subject, search, searchlen)) + { + subject += searchlen; + memcpy(result, replace, replacelen); + result += replacelen; + } + else + *result++ = *subject++; + } + *result = 0; + RETURN_TSTRING(resultbuf); + } + else + RETURN_TSTRING(subject); +} +void PF_strireplace (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char resultbuf[4096]; + char *result = resultbuf; + char *search = PR_GetStringOfs(prinst, OFS_PARM0); + char *replace = PR_GetStringOfs(prinst, OFS_PARM1); + char *subject = PR_GetStringOfs(prinst, OFS_PARM2); + int searchlen = strlen(search); + int replacelen = strlen(replace); + + if (searchlen) + { + while (*subject && result < resultbuf + sizeof(resultbuf) - replacelen - 2) + { + if (!strnicmp(subject, search, searchlen)) + { + subject += searchlen; + memcpy(result, replace, replacelen); + result += replacelen; + } + else + *result++ = *subject++; + } + *result = 0; + RETURN_TSTRING(resultbuf); + } + else + RETURN_TSTRING(subject); +} + //string(entity ent) etos = #65 void PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -1668,7 +1735,7 @@ void PF_buf_copy (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (strbuflist[bufto].prinst != prinst) return; - //codeme + Con_Printf("PF_buf_copy: stub\n"); } // #444 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS) void PF_buf_sort (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1682,7 +1749,7 @@ void PF_buf_sort (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (strbuflist[bufno].prinst != prinst) return; - //codeme + Con_Printf("PF_buf_sort: stub\n"); } // #445 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS) void PF_buf_implode (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1695,7 +1762,7 @@ void PF_buf_implode (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (strbuflist[bufno].prinst != prinst) return; - //codeme + Con_Printf("PF_buf_implode: stub\n"); RETURN_TSTRING(""); } @@ -1762,7 +1829,7 @@ void PF_bufstr_add (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (strbuflist[bufno].prinst != prinst) return; - //codeme + Con_Printf("PF_bufstr_add: stub\n"); G_FLOAT(OFS_RETURN) = 0; } @@ -1777,7 +1844,21 @@ void PF_bufstr_free (progfuncs_t *prinst, struct globalvars_s *pr_globals) if (strbuflist[bufno].prinst != prinst) return; - //codeme + Con_Printf("PF_bufstr_free: stub\n"); +} + +void PF_buf_cvarlist (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int bufno = G_FLOAT(OFS_PARM0)-1; + char *pattern = PR_GetStringOfs(prinst, OFS_PARM1); + char *antipattern = PR_GetStringOfs(prinst, OFS_PARM2); + + if ((unsigned int)bufno >= NUMSTRINGBUFS) + return; + if (strbuflist[bufno].prinst != prinst) + return; + + Con_Printf("PF_buf_cvarlist: stub\n"); } //515's String functions @@ -1826,9 +1907,10 @@ void PF_uri_escape (progfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_uri_unescape (progfuncs_t *prinst, struct globalvars_s *pr_globals) { unsigned char *s = (unsigned char*)PR_GetStringOfs(prinst, OFS_PARM0); + unsigned char resultbuf[8192]; unsigned char *i, *o; unsigned char hex; - i = s; o = s; + i = s; o = resultbuf; while (*i) { if (*i == '%') @@ -1860,43 +1942,180 @@ void PF_uri_unescape (progfuncs_t *prinst, struct globalvars_s *pr_globals) *o++ = hex; i += 3; } - *o++ = *i++; + else + *o++ = *i++; } *o = 0; - RETURN_TSTRING(s); + RETURN_TSTRING(resultbuf); } //////////////////////////////////////////////////// //Console functions +#define MAXQCTOKENS 64 +static struct { + char *token; + unsigned int start; + unsigned int end; +} qctoken[MAXQCTOKENS]; +unsigned int qctoken_count; + void PF_ArgC (progfuncs_t *prinst, struct globalvars_s *pr_globals) //85 //float() argc; { - G_FLOAT(OFS_RETURN) = Cmd_Argc(); + G_FLOAT(OFS_RETURN) = qctoken_count; } -//KRIMZON_SV_PARSECLIENTCOMMAND added these two. +int tokenizeqc(char *str, qboolean dpfuckage) +{ + char *start = str; + while(qctoken_count > 0) + { + qctoken_count--; + free(qctoken[qctoken_count].token); + } + qctoken_count = 0; + while (qctoken_count < MAXQCTOKENS) + { + /*skip whitespace here so the token's start is accurate*/ + while (*str && *(unsigned char*)str <= ' ') + str++; + + if (!*str) + break; + + qctoken[qctoken_count].start = str - start; + str = COM_StringParse (str, false, dpfuckage); + if (!str) + break; + + qctoken[qctoken_count].token = strdup(com_token); + + qctoken[qctoken_count].end = str - start; + qctoken_count++; + } + return qctoken_count; +} + +/*KRIMZON_SV_PARSECLIENTCOMMAND added these two - note that for compatibility with DP, this tokenize builtin is veeery vauge and doesn't match the console*/ void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals) //84 //void(string str) tokanize; { - Cmd_TokenizeString(PR_GetStringOfs(prinst, OFS_PARM0), false, true); - G_FLOAT(OFS_RETURN) = Cmd_Argc(); + G_FLOAT(OFS_RETURN) = tokenizeqc(PR_GetStringOfs(prinst, OFS_PARM0), true); +} + +void PF_tokenize_console (progfuncs_t *prinst, struct globalvars_s *pr_globals) //84 //void(string str) tokanize; +{ + G_FLOAT(OFS_RETURN) = tokenizeqc(PR_GetStringOfs(prinst, OFS_PARM0), false); } void PF_tokenizebyseparator (progfuncs_t *prinst, struct globalvars_s *pr_globals) { - Cmd_TokenizePunctation(PR_GetStringOfs(prinst, OFS_PARM0), PR_GetStringOfs(prinst, OFS_PARM1)); - G_FLOAT(OFS_RETURN) = Cmd_Argc(); + char *str = PR_GetStringOfs(prinst, OFS_PARM0); + char *sep[7]; + int seplen[7]; + int seps = 0, s; + char *start = str; + int tlen; + qboolean found = true; + + while (seps < *prinst->callargc - 1 && seps < 7) + { + sep[seps] = PR_GetStringOfs(prinst, OFS_PARM1 + seps*3); + seplen[seps] = strlen(sep[seps]); + seps++; + } + + /*flush the old lot*/ + while(qctoken_count > 0) + { + qctoken_count--; + free(qctoken[qctoken_count].token); + } + qctoken_count = 0; + + qctoken[qctoken_count].start = 0; + if (*str) + for(;;) + { + found = false; + /*see if its a separator*/ + if (!*str) + { + qctoken[qctoken_count].end = str - start; + found = true; + } + else + { + for (s = 0; s < seps; s++) + { + if (!strncmp(str, sep[s], seplen[s])) + { + qctoken[qctoken_count].end = str - start; + str += seplen[s]; + found = true; + break; + } + } + } + /*it was, split it out*/ + if (found) + { + tlen = qctoken[qctoken_count].end - qctoken[qctoken_count].start; + qctoken[qctoken_count].token = malloc(tlen + 1); + memcpy(qctoken[qctoken_count].token, start + qctoken[qctoken_count].start, tlen); + qctoken[qctoken_count].token[tlen] = 0; + + qctoken_count++; + + if (*str && qctoken_count < MAXQCTOKENS) + qctoken[qctoken_count].start = str - start; + else + break; + } + str++; + } + G_FLOAT(OFS_RETURN) = qctoken_count; +} + +void PF_argv_start_index (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int idx = G_FLOAT(OFS_PARM0); + + /*negative indexes are relative to the end*/ + if (idx < 0) + idx += qctoken_count; + + if ((unsigned int)idx >= qctoken_count) + G_FLOAT(OFS_RETURN) = -1; + else + G_FLOAT(OFS_RETURN) = qctoken[idx].start; +} + +void PF_argv_end_index (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int idx = G_FLOAT(OFS_PARM0); + + /*negative indexes are relative to the end*/ + if (idx < 0) + idx += qctoken_count; + + if ((unsigned int)idx >= qctoken_count) + G_FLOAT(OFS_RETURN) = -1; + else + G_FLOAT(OFS_RETURN) = qctoken[idx].end; } void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals) //86 //string(float num) argv; { - int i = G_FLOAT(OFS_PARM0); - if (i < 0) - { - PR_BIError(prinst, "pr_argv with i < 0"); + int idx = G_FLOAT(OFS_PARM0); + + /*negative indexes are relative to the end*/ + if (idx < 0) + idx += qctoken_count; + + if ((unsigned int)idx >= qctoken_count) G_INT(OFS_RETURN) = 0; - return; - } - RETURN_TSTRING(Cmd_Argv(i)); + else + RETURN_TSTRING(qctoken[idx].token); } //Console functions diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index def17be5..61577680 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -29,13 +29,8 @@ struct wedict_s #endif /*the above is shared with qclib*/ link_t area; - int num_leafs; - short leafnums[MAX_ENT_LEAFS]; -#ifdef Q2BSPS - int areanum; //q2bsp - int areanum2; //q2bsp - int headnode; //q2bsp -#endif + pvscache_t pvsinfo; + #ifdef USEODE entityode_t ode; #endif @@ -51,8 +46,6 @@ struct wedict_s #define PF_drawline PF_Fixme #define PF_drawcolorcodedstring PF_Fixme #define PF_uri_get PF_Fixme -#define PF_strreplace PF_Fixme -#define PF_strireplace PF_Fixme #define PF_gecko_create PF_Fixme #define PF_gecko_destroy PF_Fixme #define PF_gecko_navigate PF_Fixme @@ -115,7 +108,10 @@ void PF_floor (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_ceil (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_tokenizebyseparator (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_tokenize_console (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_argv_start_index (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_argv_end_index (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_nextent (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -219,6 +215,8 @@ void PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_stof (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_mod (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strreplace (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strireplace (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_stov (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_dupstring(progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_forgetstring(progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -277,6 +275,7 @@ void PF_strpad (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_edict_for_num (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_num_for_edict (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_cvar_defstring (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_cvar_description (progfuncs_t *prinst, struct globalvars_s *pr_globals); //these functions are from pr_menu.dat void PF_CL_is_cached_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -315,6 +314,7 @@ void PF_bufstr_get (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_bufstr_set (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_bufstr_add (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_bufstr_free (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_buf_cvarlist (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_whichpack (progfuncs_t *prinst, struct globalvars_s *pr_globals); diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 08e32c15..2ca41dec 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -679,17 +679,18 @@ typedef struct entity_state_s unsigned short modelindex2; //q2 #endif unsigned short frame; + unsigned int skinnum; /*q2 needs 32 bits, which is quite impressive*/ unsigned short colormap; - unsigned short skinnum; - + //pad 2 bytes qbyte glowsize; qbyte glowcolour; qbyte scale; - char fatness; + qbyte hexen2flags; qbyte abslight; qbyte dpflags; + //pad qbyte colormod[3];//multiply this by 8 to read as 0 to 1... qbyte trans; diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 440097bf..e31e1e5a 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -549,6 +549,7 @@ void Fragment_ClipTriangle(fragmentdecal_t *dec, float *a, float *b, float *c) #define MAXFRAGMENTVERTS 360 int Fragment_ClipPolyToPlane(float *inverts, float *outverts, int incount, float *plane, float planedist) { +#define C 4 float dotv[MAXFRAGMENTVERTS+1]; char keep[MAXFRAGMENTVERTS+1]; #define KEEP_KILL 0 @@ -562,7 +563,7 @@ int Fragment_ClipPolyToPlane(float *inverts, float *outverts, int incount, float for (i = 0; i < incount; i++) { - dotv[i] = DotProduct((inverts+i*3), plane) - planedist; + dotv[i] = DotProduct((inverts+i*C), plane) - planedist; if (dotv[i]<-FRAG_EPSILON) { keep[i] = KEEP_KILL; @@ -580,32 +581,33 @@ int Fragment_ClipPolyToPlane(float *inverts, float *outverts, int incount, float return 0; //all were clipped if (clippedcount == 0) { //none were clipped - memcpy(outverts, inverts, sizeof(float)*3*incount); + for (i = 0; i < incount; i++) + VectorCopy((inverts+i*C), (outverts+i*C)); return incount; } for (i = 0; i < incount; i++) { - p1 = inverts+i*3; + p1 = inverts+i*C; if (keep[i] == KEEP_BORDER) { - out = outverts+outcount++*3; + out = outverts+outcount++*C; VectorCopy(p1, out); continue; } if (keep[i] == KEEP_KEEP) { - out = outverts+outcount++*3; + out = outverts+outcount++*C; VectorCopy(p1, out); } if (keep[i+1] == KEEP_BORDER || keep[i] == keep[i+1]) continue; - p2 = inverts+((i+1)%incount)*3; + p2 = inverts+((i+1)%incount)*C; d = dotv[i] - dotv[i+1]; if (d) d = dotv[i] / d; - out = outverts+outcount++*3; + out = outverts+outcount++*C; VectorInterpolate(p1, d, p2, out); } return outcount; @@ -615,8 +617,8 @@ void Fragment_ClipPoly(fragmentdecal_t *dec, int numverts, float *inverts) { //emit the triangle, and clip it's fragments. int p; - float verts[MAXFRAGMENTVERTS*3]; - float verts2[MAXFRAGMENTVERTS*3]; + float verts[MAXFRAGMENTVERTS*C]; + float verts2[MAXFRAGMENTVERTS*C]; float *cverts; int flip; @@ -656,9 +658,9 @@ void Fragment_ClipPoly(fragmentdecal_t *dec, int numverts, float *inverts) numverts--; - VectorCopy((cverts+3*0), decalfragmentverts[dec->numtris*3+0]); - VectorCopy((cverts+3*(numverts-1)), decalfragmentverts[dec->numtris*3+1]); - VectorCopy((cverts+3*numverts), decalfragmentverts[dec->numtris*3+2]); + VectorCopy((cverts+C*0), decalfragmentverts[dec->numtris*3+0]); + VectorCopy((cverts+C*(numverts-1)), decalfragmentverts[dec->numtris*3+1]); + VectorCopy((cverts+C*numverts), decalfragmentverts[dec->numtris*3+2]); dec->numtris++; } } @@ -670,7 +672,7 @@ void Fragment_Mesh (fragmentdecal_t *dec, mesh_t *mesh) { int i; - vec3_t verts[3]; + vecV_t verts[3]; /*if its a triangle fan/poly/quad then we can just submit the entire thing without generating extra fragments*/ if (mesh->istrifan) @@ -975,7 +977,7 @@ unsigned int Q1BSP_FatPVS (model_t *mod, vec3_t org, qbyte *pvsbuffer, unsigned return fatbytes; } -qboolean Q1BSP_EdictInFatPVS(model_t *mod, wedict_t *ent, qbyte *pvs) +qboolean Q1BSP_EdictInFatPVS(model_t *mod, struct pvscache_s *ent, qbyte *pvs) { int i; @@ -996,7 +998,7 @@ SV_FindTouchedLeafs Links the edict to the right leafs so we can get it's potential visability. =============== */ -void Q1BSP_RFindTouchedLeafs (world_t *w, wedict_t *ent, mnode_t *node, float *mins, float *maxs) +void Q1BSP_RFindTouchedLeafs (model_t *wm, struct pvscache_s *ent, mnode_t *node, float *mins, float *maxs) { mplane_t *splitplane; mleaf_t *leaf; @@ -1017,7 +1019,7 @@ void Q1BSP_RFindTouchedLeafs (world_t *w, wedict_t *ent, mnode_t *node, float *m } leaf = (mleaf_t *)node; - leafnum = leaf - w->worldmodel->leafs - 1; + leafnum = leaf - wm->leafs - 1; ent->leafnums[ent->num_leafs] = leafnum; ent->num_leafs++; @@ -1031,16 +1033,16 @@ void Q1BSP_RFindTouchedLeafs (world_t *w, wedict_t *ent, mnode_t *node, float *m // recurse down the contacted sides if (sides & 1) - Q1BSP_RFindTouchedLeafs (w, ent, node->children[0], mins, maxs); + Q1BSP_RFindTouchedLeafs (wm, ent, node->children[0], mins, maxs); if (sides & 2) - Q1BSP_RFindTouchedLeafs (w, ent, node->children[1], mins, maxs); + Q1BSP_RFindTouchedLeafs (wm, ent, node->children[1], mins, maxs); } -void Q1BSP_FindTouchedLeafs(world_t *w, model_t *mod, wedict_t *ent, float *mins, float *maxs) +void Q1BSP_FindTouchedLeafs(model_t *mod, struct pvscache_s *ent, float *mins, float *maxs) { ent->num_leafs = 0; - if (ent->v->modelindex) - Q1BSP_RFindTouchedLeafs (w, ent, mod->nodes, mins, maxs); + if (mins && maxs) + Q1BSP_RFindTouchedLeafs (mod, ent, mod->nodes, mins, maxs); } #endif @@ -1186,7 +1188,7 @@ void Q1BSP_SetModelFuncs(model_t *mod) #ifndef CLIENTONLY mod->funcs.FatPVS = Q1BSP_FatPVS; mod->funcs.EdictInFatPVS = Q1BSP_EdictInFatPVS; - mod->funcs.FindTouchedLeafs_Q1 = Q1BSP_FindTouchedLeafs; + mod->funcs.FindTouchedLeafs = Q1BSP_FindTouchedLeafs; #endif mod->funcs.LightPointValues = NULL; mod->funcs.StainNode = NULL; diff --git a/engine/common/world.h b/engine/common/world.h index 690c0b46..5a4e9e36 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -115,16 +115,16 @@ typedef struct vec3_t laggedpos; } laggedentinfo_t; -struct world_s { +struct world_s +{ void (*Event_Touch)(struct world_s *w, wedict_t *s, wedict_t *o); model_t *(*GetCModel)(struct world_s *w, int modelindex); + int *global_self; unsigned int max_edicts; //limiting factor... 1024 fields*4*MAX_EDICTS == a heck of a lot. unsigned int num_edicts; // increases towards MAX_EDICTS -FTE_DEPRECATED unsigned int edict_size; - wedict_t *edicts; // can NOT be array indexed, because - // edict_t is variable sized, but can - // be used to reference the world ent +FTE_DEPRECATED unsigned int edict_size; //still used in copyentity + wedict_t *edicts; // can NOT be array indexed. struct progfuncs_s *progs; model_t *worldmodel; areanode_t areanodes[AREA_NODES]; @@ -203,8 +203,8 @@ int VARGS WorldQ2_AreaEdicts (world_t *w, vec3_t mins, vec3_t maxs, q2edict_t ** trace_t WorldQ2_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, q2edict_t *passedict); unsigned int Q2BSP_FatPVS (model_t *mod, vec3_t org, qbyte *buffer, unsigned int buffersize, qboolean add); -qboolean Q2BSP_EdictInFatPVS(model_t *mod, wedict_t *ent, qbyte *pvs); -void Q2BSP_FindTouchedLeafs(world_t *w, model_t *mod, wedict_t *ent, float *mins, float *maxs); +qboolean Q2BSP_EdictInFatPVS(model_t *mod, struct pvscache_s *ent, qbyte *pvs); +void Q2BSP_FindTouchedLeafs(model_t *mod, struct pvscache_s *ent, float *mins, float *maxs); #endif diff --git a/engine/d3d9/d3d9quake.h b/engine/d3d9/d3d9quake.h index a6a85578..43506578 100644 --- a/engine/d3d9/d3d9quake.h +++ b/engine/d3d9/d3d9quake.h @@ -123,7 +123,6 @@ int D3D9_R_LightPoint (vec3_t point); void D3D9_R_NewMap (void); void D3D9_R_PreNewMap (void); void D3D9_R_PushDlights (void); -void D3D9_R_SetSky (char *name, float rotate, vec3_t axis); void D3D9_SCR_UpdateScreen (void); void D3D9_Set2D (void); void D3D9_VID_DeInit (void); diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index 7bf1b4e2..82a34117 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -201,6 +201,6 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - AMDCaProjectFile = C:\Games\Quake\ftesrc\engine\dotnet2005\CodeAnalyst\ftequake.caw + AMDCaProjectFile = C:\Games\Quake\wip\engine\dotnet2005\CodeAnalyst\ftequake.caw EndGlobalSection EndGlobal diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index a15dad26..d7ec1507 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -430,6 +430,7 @@ UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" CharacterSet="2" + WholeProgramOptimization="1" > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/engine/dotnet2008/ftequake.sln b/engine/dotnet2008/ftequake.sln new file mode 100644 index 00000000..09d6cc39 --- /dev/null +++ b/engine/dotnet2008/ftequake.sln @@ -0,0 +1,144 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}" + ProjectSection(ProjectDependencies) = postProject + {382E6790-D1CA-48F5-8E53-D114635EB61D} = {382E6790-D1CA-48F5-8E53-D114635EB61D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gas2masm", "gas2masm.vcproj", "{382E6790-D1CA-48F5-8E53-D114635EB61D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npqtv", "npqtv.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}" + ProjectSection(ProjectDependencies) = postProject + {382E6790-D1CA-48F5-8E53-D114635EB61D} = {382E6790-D1CA-48F5-8E53-D114635EB61D} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + D3DDebug|Win32 = D3DDebug|Win32 + D3DDebug|x64 = D3DDebug|x64 + Debug Dedicated Server|Win32 = Debug Dedicated Server|Win32 + Debug Dedicated Server|x64 = Debug Dedicated Server|x64 + GLDebug|Win32 = GLDebug|Win32 + GLDebug|x64 = GLDebug|x64 + GLRelease|Win32 = GLRelease|Win32 + GLRelease|x64 = GLRelease|x64 + MDebug|Win32 = MDebug|Win32 + MDebug|x64 = MDebug|x64 + MinGLDebug|Win32 = MinGLDebug|Win32 + MinGLDebug|x64 = MinGLDebug|x64 + MinGLRelease|Win32 = MinGLRelease|Win32 + MinGLRelease|x64 = MinGLRelease|x64 + MRelease|Win32 = MRelease|Win32 + MRelease|x64 = MRelease|x64 + Release Dedicated Server|Win32 = Release Dedicated Server|Win32 + Release Dedicated Server|x64 = Release Dedicated Server|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.ActiveCfg = D3DDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.Build.0 = D3DDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.ActiveCfg = D3DDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.Build.0 = D3DDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|Win32.ActiveCfg = MRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|Win32.Build.0 = MRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|x64.ActiveCfg = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|x64.Build.0 = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|Win32.ActiveCfg = GLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|Win32.Build.0 = GLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.ActiveCfg = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.Build.0 = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.ActiveCfg = GLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.Build.0 = GLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.Build.0 = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|Win32.ActiveCfg = MDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|Win32.Build.0 = MDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|x64.Build.0 = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|Win32.ActiveCfg = MinGLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|Win32.Build.0 = MinGLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|x64.ActiveCfg = MinGLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|x64.Build.0 = MinGLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|Win32.ActiveCfg = MinGLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|Win32.Build.0 = MinGLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|x64.ActiveCfg = MinGLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|x64.Build.0 = MinGLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|Win32.ActiveCfg = MRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|Win32.Build.0 = MRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|x64.ActiveCfg = MRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|x64.Build.0 = MRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|Win32.ActiveCfg = Release Dedicated Server|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|Win32.Build.0 = Release Dedicated Server|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|x64.ActiveCfg = Release Dedicated Server|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|x64.Build.0 = Release Dedicated Server|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.D3DDebug|Win32.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.D3DDebug|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.D3DDebug|x64.ActiveCfg = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.D3DDebug|x64.Build.0 = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLDebug|Win32.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLDebug|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLDebug|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLDebug|x64.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLRelease|Win32.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLRelease|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLRelease|x64.ActiveCfg = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLRelease|x64.Build.0 = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MDebug|Win32.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MDebug|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MDebug|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MDebug|x64.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLDebug|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLDebug|x64.ActiveCfg = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLDebug|x64.Build.0 = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLRelease|Win32.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLRelease|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLRelease|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLRelease|x64.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MRelease|Win32.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MRelease|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MRelease|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MRelease|x64.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release Dedicated Server|Win32.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release Dedicated Server|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release Dedicated Server|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release Dedicated Server|x64.Build.0 = Debug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|Win32.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|x64.Build.0 = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug Dedicated Server|Win32.ActiveCfg = GLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug Dedicated Server|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug Dedicated Server|x64.Build.0 = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|Win32.ActiveCfg = GLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|Win32.Build.0 = GLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|x64.ActiveCfg = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|x64.Build.0 = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|Win32.ActiveCfg = GLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|Win32.Build.0 = GLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|x64.Build.0 = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MDebug|Win32.ActiveCfg = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MDebug|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MDebug|x64.Build.0 = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|Win32.ActiveCfg = GLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|Win32.Build.0 = GLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|x64.ActiveCfg = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|x64.Build.0 = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|Win32.ActiveCfg = GLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|Win32.Build.0 = GLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|x64.Build.0 = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MRelease|Win32.ActiveCfg = GLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MRelease|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MRelease|x64.Build.0 = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release Dedicated Server|Win32.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release Dedicated Server|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release Dedicated Server|x64.Build.0 = GLRelease|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/engine/dotnet2008/ftequake.vcproj b/engine/dotnet2008/ftequake.vcproj new file mode 100644 index 00000000..4e63e7fb --- /dev/null +++ b/engine/dotnet2008/ftequake.vcproj @@ -0,0 +1,33081 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/dotnet2008/gas2masm.vcproj b/engine/dotnet2008/gas2masm.vcproj new file mode 100644 index 00000000..8c678098 --- /dev/null +++ b/engine/dotnet2008/gas2masm.vcproj @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/dotnet2008/npqtv.vcproj b/engine/dotnet2008/npqtv.vcproj new file mode 100644 index 00000000..43a071d2 --- /dev/null +++ b/engine/dotnet2008/npqtv.vcproj @@ -0,0 +1,43499 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/dotnet2008/resource.h b/engine/dotnet2008/resource.h new file mode 100644 index 00000000..c6f7916b --- /dev/null +++ b/engine/dotnet2008/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by npqtv.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index 6334a2df..7087cc17 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -639,69 +639,6 @@ SOURCE=..\server\svq3_game.c !ENDIF -# End Source File -# Begin Source File - -SOURCE=..\server\world.c - -!IF "$(CFG)" == "ftequake - Win32 Release" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" - -# ADD CPP /Yu"quakedef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" - -# ADD CPP /Yu"qwsvdef.h" - -!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" - -# ADD CPP /Yu"qwsvdef.h" - -!ENDIF - # End Source File # End Group # Begin Group "client" @@ -2180,6 +2117,10 @@ SOURCE=..\client\p_null.c # End Source File # Begin Source File +SOURCE=..\client\p_qmb.c +# End Source File +# Begin Source File + SOURCE=..\client\p_script.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -2355,50 +2296,6 @@ SOURCE=..\client\r_bulleten.c # End Source File # Begin Source File -SOURCE=..\client\r_efrag.c - -!IF "$(CFG)" == "ftequake - Win32 Release" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" - -# PROP BASE Exclude_From_Build 1 -# PROP Exclude_From_Build 1 -# ADD CPP /G6 /O1 - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" - -# PROP BASE Exclude_From_Build 1 -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" - -!ENDIF - -# End Source File -# Begin Source File - SOURCE=..\client\r_part.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -3803,52 +3700,6 @@ SOURCE=..\gl\gl_ngraph.c # End Source File # Begin Source File -SOURCE=..\gl\gl_ppl.c - -!IF "$(CFG)" == "ftequake - Win32 Release" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" - -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" - -# PROP BASE Exclude_From_Build 1 -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" - -# PROP BASE Exclude_From_Build 1 -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" - -!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" - -# PROP BASE Exclude_From_Build 1 -# PROP Exclude_From_Build 1 - -!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" - -!ENDIF - -# End Source File -# Begin Source File - SOURCE=..\common\gl_q2bsp.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -4391,6 +4242,14 @@ SOURCE=..\gl\LTFACE.C # End Source File # Begin Source File +SOURCE=..\client\r_2d.c +# End Source File +# Begin Source File + +SOURCE=..\client\r_surf.c +# End Source File +# Begin Source File + SOURCE=..\gl\shader.h # End Source File # End Group @@ -4544,6 +4403,69 @@ SOURCE=..\common\translate.c # End Source File # Begin Source File +SOURCE=..\server\world.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# ADD CPP /Yu"quakedef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +# ADD CPP /Yu"quekdef.h" + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +# ADD CPP /Yu"quekdef.h" + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\common\zone.c # End Source File # End Group diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 3e6b079d..26fe3c96 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -223,12 +223,12 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, unsigned int tc, bc; qboolean forced; - if ((e->model->engineflags & MDLF_NOTREPLACEMENTS) && !ruleset_allow_sensative_texture_replacements.value) + if ((e->model->engineflags & MDLF_NOTREPLACEMENTS) && !ruleset_allow_sensative_texture_replacements.ival) forced = true; else forced = false; - if (!gl_nocolors.value || forced) + if (!gl_nocolors.ival || forced) { if (e->scoreboard) { @@ -517,7 +517,7 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, } } texnums->base = R_AllocNewTexture(scaled_width, scaled_height); - R_Upload(texnums->base, "", TF_RGBX32, pixels, scaled_width, scaled_height, IF_NOMIPMAP); + R_Upload(texnums->base, "", TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); //now do the fullbrights. out = pixels; @@ -534,7 +534,7 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, } } texnums->fullbright = R_AllocNewTexture(scaled_width, scaled_height); - R_Upload(texnums->fullbright, "", TF_RGBA32, pixels, scaled_width, scaled_height, IF_NOMIPMAP); + R_Upload(texnums->fullbright, "", TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); } else { @@ -905,7 +905,7 @@ void R_DrawGAliasModel (entity_t *e, unsigned int rmode) // if (e->flags & Q2RF_VIEWERMODEL && e->keynum == cl.playernum[r_refdef.currentplayernum]+1) // return; - if (r_secondaryview && e->flags & Q2RF_WEAPONMODEL) + if (r_refdef.externalview && e->flags & Q2RF_WEAPONMODEL) return; { @@ -1139,7 +1139,7 @@ void R_DrawGAliasModel (entity_t *e, unsigned int rmode) } } - BE_DrawMeshChain(shader, &mesh, NULL, skin); + BE_DrawMesh_Single(shader, &mesh, NULL, skin); } if (e->flags & Q2RF_WEAPONMODEL) @@ -1160,7 +1160,7 @@ void R_DrawGAliasModel (entity_t *e, unsigned int rmode) #endif } -//returns result in the form of the result vector +//returns the rotated offset of the two points in result void RotateLightVector(const vec3_t *axis, const vec3_t origin, const vec3_t lightpoint, vec3_t result) { vec3_t offs; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index c895fa04..be8850e5 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -15,7 +15,7 @@ varying vec3 lightvector;\n\ varying vec3 eyevector;\n\ #endif\n\ #ifdef PCF\n\ -varying vec4 shadowcoord;\n\ +varying vec4 vshadowcoord;\n\ uniform mat4 entmatrix;\n\ #endif\n\ " @@ -47,7 +47,7 @@ void main (void)\n\ eyevector.z = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n\ #endif\n\ #if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n\ - shadowcoord = gl_TextureMatrix[7] * (entmatrix*gl_Vertex);\n\ + vshadowcoord = gl_TextureMatrix[7] * (entmatrix*gl_Vertex);\n\ #endif\n\ }\n\ #endif\n\ @@ -56,8 +56,8 @@ void main (void)\n\ /*this is full 4*4 PCF, with an added attempt at prenumbra*/ /*the offset consts are 1/(imagesize*2) */ #define PCF16P(f) "\ - float xPixelOffset = (1.0+shadowcoord.b/lightradius)/512.0;\ - float yPixelOffset = (1.0+shadowcoord.b/lightradius)/512.0;\ + float xPixelOffset = (1.0+shadowcoord.b/lightradius)/texx;\ + float yPixelOffset = (1.0+shadowcoord.b/lightradius)/texy;\ float s = 0.0;\n\ s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ @@ -85,8 +85,8 @@ void main (void)\n\ /*this is pcf 3*3*/ /*the offset consts are 1/(imagesize*2) */ #define PCF9(f) "\ - const float xPixelOffset = 1.0/512.0;\ - const float yPixelOffset = 1.0/512.0;\ + const float xPixelOffset = 1.0/texx;\ + const float yPixelOffset = 1.0/texy;\ float s = 0.0;\n\ s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ @@ -105,8 +105,8 @@ void main (void)\n\ /*this is a lazy form of pcf. take 5 samples in an x*/ /*the offset consts are 1/(imagesize*2) */ #define PCF5(f) "\ - float xPixelOffset = 1.0/512.0;\ - float yPixelOffset = 1.0/512.0;\ + float xPixelOffset = 1.0/texx;\ + float yPixelOffset = 1.0/texy;\ float s = 0.0;\n\ s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ @@ -187,8 +187,19 @@ void main (void)\n\ diff += pow(dv, 8.0) * specs;\n\ diff.g = pow(dv, 8.0);\n\ #endif\n\ -\n\ +""\n\ #ifdef PCF\n\ +#if defined(SPOT)\n\ +const float texx = 512.0;\n\ +const float texy = 512.0;\n\ +vec4 shadowcoord = vshadowcoord;\n\ +#else\n\ +const float texx = 512.0;\n\ +const float texy = 512.0;\n\ +vec4 shadowcoord;\n\ +shadowcoord.zw = vshadowcoord.zw;\n\ +shadowcoord.xy = vshadowcoord.xy;\n\ +#endif\n\ #ifdef CUBE\n\ "PCF9("shadowCube") /*valid are 1,5,9*/"\n\ #else\n\ @@ -254,9 +265,8 @@ static const char PCFPASS_SHADER[] = "\ program\n\ {\n\ //#define CUBE\n\ - #define SPOT\n\ #define PCF\n\ - %s%s\n\ + %s%s%s\n\ }\n\ \ //incoming fragment\n\ @@ -297,7 +307,7 @@ static const char PCFPASS_SHADER[] = "\ }"; -extern cvar_t r_shadow_glsl_offsetmapping; +extern cvar_t r_shadow_glsl_offsetmapping, r_noportals; #if 0//def _DEBUG #define checkerror() if (qglGetError()) Con_Printf("Error detected at line %s:%i\n", __FILE__, __LINE__) @@ -306,18 +316,10 @@ extern cvar_t r_shadow_glsl_offsetmapping; #endif static void BE_SendPassBlendAndDepth(unsigned int sbits); +static void BE_SubmitBatch(batch_t *batch); void PPL_CreateShaderObjects(void){} void PPL_BaseBModelTextures(entity_t *e){} -void R_DrawBeam( entity_t *e ){} -qboolean PPL_ShouldDraw(void) -{ - if (currententity->flags & Q2RF_EXTERNALMODEL && r_secondaryview != 3) - return false; - if (!Cam_DrawPlayer(r_refdef.currentplayernum, currententity->keynum-1)) - return false; - return true; -} enum{ PERMUTATION_GENERIC = 0, @@ -353,6 +355,17 @@ static char *pcfpassname[PERMUTATIONS] = "lightpass_pcf_offset_spec", "lightpass_pcf_offset_bump_spec" }; +static char *spotpassname[PERMUTATIONS] = +{ + "lightpass_spot", + "lightpass_spot_bump", + "lightpass_spot_spec", + "lightpass_spot_bump_spec", + "lightpass_spot_offset", + "lightpass_spot_offset_bump", + "lightpass_spot_offset_spec", + "lightpass_spot_offset_bump_spec" +}; static char *permutationdefines[PERMUTATIONS] = { "", "#define BUMP\n", @@ -376,6 +389,8 @@ struct { const shader_t *lightpassshader[PERMUTATIONS]; qboolean initedpcfpasses; const shader_t *pcfpassshader[PERMUTATIONS]; + qboolean initedspotpasses; + const shader_t *spotpassshader[PERMUTATIONS]; qboolean force2d; int currenttmu; @@ -388,11 +403,13 @@ struct { unsigned int shaderbits; - mesh_t *pushedmeshes; vbo_t dummyvbo; int currentvbo; int currentebo; + mesh_t **meshes; + unsigned int meshcount; + int pendingvertexvbo; void *pendingvertexpointer; int curvertexvbo; @@ -549,12 +566,12 @@ void GL_CullFace(unsigned int sflags) if (shaderstate.curcull & SHADER_CULL_FRONT) { qglEnable(GL_CULL_FACE); - qglCullFace(GL_FRONT); + qglCullFace(r_refdef.flipcull?GL_BACK:GL_FRONT); } else if (shaderstate.curcull & SHADER_CULL_BACK) { qglEnable(GL_CULL_FACE); - qglCullFace(GL_BACK); + qglCullFace(r_refdef.flipcull?GL_FRONT:GL_BACK); } else { @@ -662,12 +679,6 @@ void R_IBrokeTheArrays(void) RevertToKnownState(); } -void R_UnlockArrays(void) -{ -} -void R_ClearArrays(void) -{ -} void GL_FlushBackEnd(void) { memset(&shaderstate, 0, sizeof(shaderstate)); @@ -698,6 +709,8 @@ void BE_SetupForShadowMap(void) qglDepthMask(GL_TRUE); shaderstate.shaderbits |= SBITS_MISC_DEPTHWRITE; // qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + BE_SelectMode(BEM_DEPTHONLY, 0); } #endif @@ -850,7 +863,13 @@ void Shader_LightPass_Std(char *shortname, shader_t *s, const void *args) void Shader_LightPass_PCF(char *shortname, shader_t *s, const void *args) { char shadertext[8192*2]; - sprintf(shadertext, PCFPASS_SHADER, args, LIGHTPASS_GLSL_SHARED LIGHTPASS_GLSL_VERTEX LIGHTPASS_GLSL_FRAGMENT); + sprintf(shadertext, PCFPASS_SHADER, args, "", LIGHTPASS_GLSL_SHARED LIGHTPASS_GLSL_VERTEX LIGHTPASS_GLSL_FRAGMENT); + Shader_DefaultScript(shortname, s, shadertext); +} +void Shader_LightPass_Spot(char *shortname, shader_t *s, const void *args) +{ + char shadertext[8192*2]; + sprintf(shadertext, PCFPASS_SHADER, args, "#define SPOT\n", LIGHTPASS_GLSL_SHARED LIGHTPASS_GLSL_VERTEX LIGHTPASS_GLSL_FRAGMENT); Shader_DefaultScript(shortname, s, shadertext); } @@ -886,7 +905,7 @@ void BE_Init(void) shaderstate.identitylighting = 1; /*normally we load these lazily, but if they're probably going to be used anyway, load them now to avoid stalls.*/ - if (r_shadow_realtime_dlight.ival && !shaderstate.initedlightpasses) + if (r_shadow_realtime_dlight.ival && !shaderstate.initedlightpasses && gl_config.arb_shader_objects) { int i; shaderstate.initedlightpasses = true; @@ -899,6 +918,8 @@ void BE_Init(void) shaderstate.shaderbits = ~0; BE_SendPassBlendAndDepth(0); qglEnableClientState(GL_VERTEX_ARRAY); + + currententity = &r_worldentity; } //end tables @@ -1059,28 +1080,31 @@ static void tcmod(const tcmod_t *tcmod, int cnt, const float *src, float *dst, c } } -static void GenerateTCMods(const shaderpass_t *pass, int passnum, const mesh_t *meshlist) +static void GenerateTCMods(const shaderpass_t *pass, int passnum) { #if 1 - for (; meshlist; meshlist = meshlist->next) + int i, m; + float *src; + mesh_t *mesh; + for (m = 0; m < shaderstate.meshcount; m++) { - int i; - float *src; - src = tcgen(pass, meshlist->numvertexes, texcoordarray[passnum]+meshlist->vbofirstvert*2, meshlist); + mesh = shaderstate.meshes[m]; + + src = tcgen(pass, mesh->numvertexes, texcoordarray[passnum]+mesh->vbofirstvert*2, mesh); //tcgen might return unmodified info if (pass->numtcmods) { - tcmod(&pass->tcmods[0], meshlist->numvertexes, src, texcoordarray[passnum]+meshlist->vbofirstvert*2, meshlist); + tcmod(&pass->tcmods[0], mesh->numvertexes, src, texcoordarray[passnum]+mesh->vbofirstvert*2, mesh); for (i = 1; i < pass->numtcmods; i++) { - tcmod(&pass->tcmods[i], meshlist->numvertexes, texcoordarray[passnum]+meshlist->vbofirstvert*2, texcoordarray[passnum]+meshlist->vbofirstvert*2, meshlist); + tcmod(&pass->tcmods[i], mesh->numvertexes, texcoordarray[passnum]+mesh->vbofirstvert*2, texcoordarray[passnum]+mesh->vbofirstvert*2, mesh); } - src = texcoordarray[passnum]+meshlist->vbofirstvert*2; + src = texcoordarray[passnum]+mesh->vbofirstvert*2; } - else if (src != texcoordarray[passnum]+meshlist->vbofirstvert*2) + else if (src != texcoordarray[passnum]+mesh->vbofirstvert*2) { //this shouldn't actually ever be true - memcpy(texcoordarray[passnum]+meshlist->vbofirstvert*2, src, 8*meshlist->numvertexes); + memcpy(texcoordarray[passnum]+mesh->vbofirstvert*2, src, 8*mesh->numvertexes); } } GL_SelectVBO(0); @@ -1231,15 +1255,36 @@ static void colourgen(const shaderpass_t *pass, int cnt, const avec4_t *src, ave break; case RGB_GEN_TOPCOLOR: - case RGB_GEN_BOTTOMCOLOR: -#pragma message("fix 24bit player colours") - while((cnt)--) + if (cnt) { - dst[cnt][0] = 1; - dst[cnt][1] = 1; - dst[cnt][2] = 1; + int r, g, b; + R_FetchTopColour(&r, &g, &b); + dst[0][0] = r/255.0f; + dst[0][1] = g/255.0f; + dst[0][2] = b/255.0f; + while((cnt)--) + { + dst[cnt][0] = dst[0][0]; + dst[cnt][1] = dst[0][1]; + dst[cnt][2] = dst[0][2]; + } + } + break; + case RGB_GEN_BOTTOMCOLOR: + if (cnt) + { + int r, g, b; + R_FetchBottomColour(&r, &g, &b); + dst[0][0] = r/255.0f; + dst[0][1] = g/255.0f; + dst[0][2] = b/255.0f; + while((cnt)--) + { + dst[cnt][0] = dst[0][0]; + dst[cnt][1] = dst[0][1]; + dst[cnt][2] = dst[0][2]; + } } - // Con_Printf("RGB_GEN %i not supported\n", pass->rgbgen); break; } } @@ -1339,9 +1384,9 @@ static void deformgen(const deformv_t *deformv, int cnt, const vecV_t *src, vecV for (k = 0; k < 4; k++) { - dst[k][0] = mid[0] + radius*((mesh->st_array[k][0]-0.5)*r_view_matrix[0+0]+(mesh->st_array[k][1]-0.5)*r_view_matrix[0+1]); - dst[k][1] = mid[1] + radius*((mesh->st_array[k][0]-0.5)*r_view_matrix[4+0]+(mesh->st_array[k][1]-0.5)*r_view_matrix[4+1]); - dst[k][2] = mid[2] + radius*((mesh->st_array[k][0]-0.5)*r_view_matrix[8+0]+(mesh->st_array[k][1]-0.5)*r_view_matrix[8+1]); + dst[k][0] = mid[0] + radius*((mesh->st_array[k][0]-0.5)*r_refdef.m_view[0+0]-(mesh->st_array[k][1]-0.5)*r_refdef.m_view[0+1]); + dst[k][1] = mid[1] + radius*((mesh->st_array[k][0]-0.5)*r_refdef.m_view[4+0]-(mesh->st_array[k][1]-0.5)*r_refdef.m_view[4+1]); + dst[k][2] = mid[2] + radius*((mesh->st_array[k][0]-0.5)*r_refdef.m_view[8+0]-(mesh->st_array[k][1]-0.5)*r_refdef.m_view[8+1]); } } break; @@ -1482,11 +1527,14 @@ static void deformgen(const deformv_t *deformv, int cnt, const vecV_t *src, vecV } } -static void GenerateVertexDeforms(const shader_t *shader, const mesh_t *meshlist) +static void GenerateVertexDeforms(const shader_t *shader) { - int i; - for (; meshlist; meshlist = meshlist->next) + int i, m; + mesh_t *meshlist; + for (m = 0; m < shaderstate.meshcount; m++) { + meshlist = shaderstate.meshes[m]; + deformgen(&shader->deforms[0], meshlist->numvertexes, meshlist->xyz_array, vertexarray+meshlist->vbofirstvert, meshlist); for (i = 1; i < shader->numdeforms; i++) { @@ -1512,8 +1560,16 @@ static void alphagen(const shaderpass_t *pass, int cnt, const avec4_t *src, avec { default: case ALPHA_GEN_IDENTITY: - while(cnt--) - dst[cnt][3] = 1; + if (shaderstate.flags & BEF_FORCETRANSPARENT) + { + while(cnt--) + dst[cnt][3] = shaderstate.curentity->shaderRGBAf[3]; + } + else + { + while(cnt--) + dst[cnt][3] = 1; + } break; case ALPHA_GEN_CONST: @@ -1533,10 +1589,15 @@ static void alphagen(const shaderpass_t *pass, int cnt, const avec4_t *src, avec case ALPHA_GEN_PORTAL: //FIXME: should this be per-vert? - VectorAdd(mesh->xyz_array[0], shaderstate.curentity->origin, v1); - VectorSubtract(r_origin, v1, v2); - f = VectorLength(v2) * (1.0 / 255.0); - f = bound(0.0f, f, 1.0f); + if (r_refdef.recurse) + f = 1; + else + { + VectorAdd(mesh->xyz_array[0], shaderstate.curentity->origin, v1); + VectorSubtract(r_origin, v1, v2); + f = VectorLength(v2) * (1.0 / shaderstate.curshader->portaldist); + f = bound(0.0f, f, 1.0f); + } while(cnt--) dst[cnt][3] = f; @@ -1568,14 +1629,14 @@ static void alphagen(const shaderpass_t *pass, int cnt, const avec4_t *src, avec case ALPHA_GEN_SPECULAR: - { + { mat3_t axis; AngleVectors(shaderstate.curentity->angles, axis[0], axis[1], axis[2]); VectorSubtract(r_origin, shaderstate.curentity->origin, v1); if (!Matrix3_Compare(axis, axisDefault)) { - Matrix3_Multiply_Vec3(axis, v2, v2); + Matrix3_Multiply_Vec3(axis, v1, v2); } else { @@ -1594,15 +1655,19 @@ static void alphagen(const shaderpass_t *pass, int cnt, const avec4_t *src, avec } } -static void GenerateColourMods(const shaderpass_t *pass, const mesh_t *meshlist) +static void GenerateColourMods(const shaderpass_t *pass) { + unsigned int m; + mesh_t *meshlist; + meshlist = shaderstate.meshes[0]; + if (meshlist->colors4b_array) { //hack... GL_SelectVBO(0); qglColorPointer(4, GL_UNSIGNED_BYTE, 0, meshlist->colors4b_array); qglEnableClientState(GL_COLOR_ARRAY); - qglShadeModel(GL_FLAT); + qglShadeModel(GL_SMOOTH); return; } if (pass->flags & SHADER_PASS_NOCOLORARRAY) @@ -1643,8 +1708,10 @@ static void GenerateColourMods(const shaderpass_t *pass, const mesh_t *meshlist) return; } - for (; meshlist; meshlist = meshlist->next) + for (m = 0; m < shaderstate.meshcount; m++) { + meshlist = shaderstate.meshes[m]; + colourgen(pass, meshlist->numvertexes, meshlist->colors4f_array, coloursarray + meshlist->vbofirstvert, meshlist); alphagen(pass, meshlist->numvertexes, meshlist->colors4f_array, coloursarray + meshlist->vbofirstvert, meshlist); } @@ -1654,7 +1721,7 @@ static void GenerateColourMods(const shaderpass_t *pass, const mesh_t *meshlist) } } -static void BE_GeneratePassTC(const shaderpass_t *pass, int passno, const mesh_t *meshlist) +static void BE_GeneratePassTC(const shaderpass_t *pass, int passno) { pass += passno; if (!pass->numtcmods) @@ -1688,12 +1755,12 @@ static void BE_GeneratePassTC(const shaderpass_t *pass, int passno, const mesh_t else { //specular highlights and reflections have no fixed data, and must be generated. - GenerateTCMods(pass, passno, meshlist); + GenerateTCMods(pass, passno); } } else { - GenerateTCMods(pass, passno, meshlist); + GenerateTCMods(pass, passno); } } @@ -1708,7 +1775,7 @@ static void BE_SendPassBlendAndDepth(unsigned int sbits) sbits &= ~(SBITS_MISC_DEPTHWRITE|SBITS_MISC_DEPTHEQUALONLY); sbits |= SBITS_MISC_NODEPTHTEST; } - if (shaderstate.flags) + if (shaderstate.flags & ~BEF_PUSHDEPTH) { if (!(sbits & SBITS_BLEND_BITS)) { /*only force blend bits if its not already blended*/ @@ -1836,24 +1903,30 @@ static void BE_SendPassBlendAndDepth(unsigned int sbits) } } -static void BE_SubmitMeshChain(const mesh_t *meshlist) +static void BE_SubmitMeshChain(void) { int startv, starti, endv, endi; - while (meshlist) - { - startv = meshlist->vbofirstvert; - starti = meshlist->vbofirstelement; + int m; + mesh_t *mesh; - endv = startv+meshlist->numvertexes; - endi = starti+meshlist->numindexes; + mesh = shaderstate.meshes[0]; + + for (m = 0; m < shaderstate.meshcount; ) + { + startv = mesh->vbofirstvert; + starti = mesh->vbofirstelement; + + endv = startv+mesh->numvertexes; + endi = starti+mesh->numindexes; //find consecutive surfaces - for (meshlist = meshlist->next; meshlist; meshlist = meshlist->next) + for (++m; m < shaderstate.meshcount; m++) { - if (endi == meshlist->vbofirstelement) + mesh = shaderstate.meshes[m]; + if (endi == mesh->vbofirstelement) { - endv = meshlist->vbofirstvert+meshlist->numvertexes; - endi = meshlist->vbofirstelement+meshlist->numindexes; + endv = mesh->vbofirstvert+mesh->numvertexes; + endi = mesh->vbofirstelement+mesh->numindexes; } else { @@ -1865,7 +1938,7 @@ static void BE_SubmitMeshChain(const mesh_t *meshlist) } } -static void DrawPass(const shaderpass_t *pass, const mesh_t *meshlist) +static void DrawPass(const shaderpass_t *pass) { int i; int tmu; @@ -1886,7 +1959,7 @@ static void DrawPass(const shaderpass_t *pass, const mesh_t *meshlist) checkerror(); BE_SendPassBlendAndDepth(pass[i].shaderbits); - GenerateColourMods(pass+i, meshlist); + GenerateColourMods(pass+i); checkerror(); tmu = 0; for (; i < lastpass; i++) @@ -1900,7 +1973,7 @@ static void DrawPass(const shaderpass_t *pass, const mesh_t *meshlist) GL_MBind(tmu, Shader_TextureForPass(pass+i)); checkerror(); - BE_GeneratePassTC(pass, i, meshlist); + BE_GeneratePassTC(pass, i); checkerror(); if (tmu >= shaderstate.lastpasstmus) @@ -1948,12 +2021,12 @@ static void DrawPass(const shaderpass_t *pass, const mesh_t *meshlist) shaderstate.lastpasstmus = tmu; GL_ApplyVertexPointer(); - BE_SubmitMeshChain(meshlist); + BE_SubmitMeshChain(); checkerror(); } -static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pass, const mesh_t *meshlist) +static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pass) { const shader_t *s = shader; int i; @@ -1962,7 +2035,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas int r, g, b; BE_SendPassBlendAndDepth(pass->shaderbits); - GenerateColourMods(pass, meshlist); + GenerateColourMods(pass); for ( i = 0; i < pass->numMergedPasses; i++) { @@ -1972,7 +2045,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas qglEnable(GL_TEXTURE_2D); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); } - BE_GeneratePassTC(pass, i, meshlist); + BE_GeneratePassTC(pass, i); } for (; i < shaderstate.lastpasstmus; i++) { @@ -2062,7 +2135,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas } } GL_ApplyVertexPointer(); - BE_SubmitMeshChain(meshlist); + BE_SubmitMeshChain(); GLSlang_UseProgram(0); } @@ -2102,22 +2175,13 @@ void BE_SelectMode(backendmode_t mode, unsigned int flags) { extern int gldepthfunc; -#ifdef RTLIGHTS if (mode != shaderstate.mode) { -qglDisable(GL_POLYGON_OFFSET_FILL); -shaderstate.curpolyoffset.factor = 0; -shaderstate.curpolyoffset.unit = 0; - +#ifdef RTLIGHTS if (mode == BEM_STENCIL) { qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); -shaderstate.curpolyoffset.factor = 0; -shaderstate.curpolyoffset.unit = 0; -qglEnable(GL_POLYGON_OFFSET_FILL); -qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); - /*BEM_STENCIL doesn't support mesh writing*/ qglDisableClientState(GL_COLOR_ARRAY); //disable all tmus @@ -2138,6 +2202,7 @@ qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.uni //don't actually change stencil stuff - caller needs to be //aware of how many times stuff is drawn, so they can do that themselves. } +#endif if (mode == BEM_DEPTHONLY) { qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -2155,12 +2220,13 @@ qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.uni BE_SendPassBlendAndDepth(SBITS_MISC_DEPTHWRITE); GL_TexEnv(GL_REPLACE); - qglCullFace(GL_FRONT); + GL_CullFace(SHADER_CULL_FRONT); } if (shaderstate.mode == BEM_STENCIL || shaderstate.mode == BEM_DEPTHONLY) + { qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - + } +#ifdef RTLIGHTS if (mode == BEM_SMAPLIGHT) { if (!shaderstate.initedpcfpasses) @@ -2173,6 +2239,18 @@ qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.uni } } } + if (mode == BEM_SMAPLIGHTSPOT) + { + if (!shaderstate.initedspotpasses) + { + int i; + shaderstate.initedspotpasses = true; + for (i = 0; i < PERMUTATIONS; i++) + { + shaderstate.spotpassshader[i] = R_RegisterCustom(spotpassname[i], Shader_LightPass_Spot, permutationdefines[i]); + } + } + } if (mode == BEM_LIGHT) { if (!shaderstate.initedlightpasses) @@ -2185,8 +2263,8 @@ qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.uni } } } - } #endif + } shaderstate.mode = mode; shaderstate.flags = flags; } @@ -2201,44 +2279,52 @@ void BE_SelectDLight(dlight_t *dl, vec3_t colour) } #endif -static void DrawMeshChain(const mesh_t *meshlist) +void BE_PushOffsetShadow(qboolean pushdepth) { - const shaderpass_t *p; - int passno,perm; - passno = 0; - - GL_SelectEBO(shaderstate.sourcevbo->vboe); - if (shaderstate.curshader->numdeforms) - GenerateVertexDeforms(shaderstate.curshader, meshlist); - else + if (pushdepth) { - shaderstate.pendingvertexpointer = shaderstate.sourcevbo->coord; - shaderstate.pendingvertexvbo = shaderstate.sourcevbo->vbocoord; - } + /*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc + we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/ + extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor; + polyoffset_t po; + po.factor = r_polygonoffset_submodel_factor.value; + po.unit = r_polygonoffset_submodel_offset.value; #ifndef FORCESTATE - if (shaderstate.curcull != (shaderstate.curshader->flags & (SHADER_CULL_FRONT|SHADER_CULL_BACK))) + if (((int*)&shaderstate.curpolyoffset)[0] != ((int*)&po)[0] || ((int*)&shaderstate.curpolyoffset)[1] != ((int*)&po)[1]) #endif - { - shaderstate.curcull = (shaderstate.curshader->flags & (SHADER_CULL_FRONT|SHADER_CULL_BACK)); - - if (shaderstate.curcull & SHADER_CULL_FRONT) { - qglEnable(GL_CULL_FACE); - qglCullFace(GL_FRONT); - } - else if (shaderstate.curcull & SHADER_CULL_BACK) - { - qglEnable(GL_CULL_FACE); - qglCullFace(GL_BACK); - } - else - { - qglDisable(GL_CULL_FACE); + shaderstate.curpolyoffset = po; + if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) + { + qglEnable(GL_POLYGON_OFFSET_FILL); + qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); + } + else + qglDisable(GL_POLYGON_OFFSET_FILL); } } + else + { +#ifndef FORCESTATE + if (*(int*)&shaderstate.curpolyoffset != 0 || *(int*)&shaderstate.curpolyoffset != 0) +#endif + { + shaderstate.curpolyoffset = shaderstate.curshader->polyoffset; + if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) + { + qglEnable(GL_POLYGON_OFFSET_FILL); + qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); + } + else + qglDisable(GL_POLYGON_OFFSET_FILL); + } + } +} - if (shaderstate.flags & BEF_PUSHDEPTH) +void BE_PolyOffset(qboolean pushdepth) +{ + if (pushdepth) { /*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/ @@ -2277,12 +2363,63 @@ static void DrawMeshChain(const mesh_t *meshlist) qglDisable(GL_POLYGON_OFFSET_FILL); } } +} + +static void DrawMeshes(void) +{ + const shaderpass_t *p; + int passno,perm; + passno = 0; + + GL_SelectEBO(shaderstate.sourcevbo->vboe); + if (shaderstate.curshader->numdeforms) + GenerateVertexDeforms(shaderstate.curshader); + else + { + shaderstate.pendingvertexpointer = shaderstate.sourcevbo->coord; + shaderstate.pendingvertexvbo = shaderstate.sourcevbo->vbocoord; + } + +#ifndef FORCESTATE + if (shaderstate.curcull != (shaderstate.curshader->flags & (SHADER_CULL_FRONT|SHADER_CULL_BACK))) +#endif + { + shaderstate.curcull = (shaderstate.curshader->flags & (SHADER_CULL_FRONT|SHADER_CULL_BACK)); + + if (shaderstate.curcull & SHADER_CULL_FRONT) + { + qglEnable(GL_CULL_FACE); + qglCullFace(r_refdef.flipcull?GL_BACK:GL_FRONT); + } + else if (shaderstate.curcull & SHADER_CULL_BACK) + { + qglEnable(GL_CULL_FACE); + qglCullFace(r_refdef.flipcull?GL_FRONT:GL_BACK); + } + else + { + qglDisable(GL_CULL_FACE); + } + } + + BE_PolyOffset(shaderstate.flags & BEF_PUSHDEPTH); switch(shaderstate.mode) { case BEM_STENCIL: Host_Error("Shader system is not meant to accept stencil meshes\n"); break; +#ifdef RTLIGHTS + case BEM_SMAPLIGHTSPOT: + perm = 0; + if (TEXVALID(shaderstate.curtexnums->bump) && shaderstate.spotpassshader[perm|PERMUTATION_BUMPMAP]) + perm |= PERMUTATION_BUMPMAP; + if (TEXVALID(shaderstate.curtexnums->specular) && shaderstate.spotpassshader[perm|PERMUTATION_SPECULAR]) + perm |= PERMUTATION_SPECULAR; + if (r_shadow_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.spotpassshader[perm|PERMUTATION_OFFSET]) + perm |= PERMUTATION_OFFSET; + BE_RenderMeshProgram(shaderstate.spotpassshader[perm], shaderstate.spotpassshader[perm]->passes); + break; case BEM_SMAPLIGHT: perm = 0; if (TEXVALID(shaderstate.curtexnums->bump) && shaderstate.pcfpassshader[perm|PERMUTATION_BUMPMAP]) @@ -2291,7 +2428,7 @@ static void DrawMeshChain(const mesh_t *meshlist) perm |= PERMUTATION_SPECULAR; if (r_shadow_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.pcfpassshader[perm|PERMUTATION_OFFSET]) perm |= PERMUTATION_OFFSET; - BE_RenderMeshProgram(shaderstate.pcfpassshader[perm], shaderstate.pcfpassshader[perm]->passes, meshlist); + BE_RenderMeshProgram(shaderstate.pcfpassshader[perm], shaderstate.pcfpassshader[perm]->passes); break; case BEM_LIGHT: perm = 0; @@ -2301,13 +2438,13 @@ static void DrawMeshChain(const mesh_t *meshlist) perm |= PERMUTATION_SPECULAR; if (r_shadow_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.lightpassshader[perm|PERMUTATION_OFFSET]) perm |= PERMUTATION_OFFSET; - BE_RenderMeshProgram(shaderstate.lightpassshader[perm], shaderstate.lightpassshader[perm]->passes, meshlist); + BE_RenderMeshProgram(shaderstate.lightpassshader[perm], shaderstate.lightpassshader[perm]->passes); break; - +#endif case BEM_DEPTHONLY: #pragma message("fixme: support alpha test") GL_ApplyVertexPointer(); - BE_SubmitMeshChain(meshlist); + BE_SubmitMeshChain(); break; case BEM_DEPTHDARK: @@ -2325,14 +2462,14 @@ static void DrawMeshChain(const mesh_t *meshlist) BE_SendPassBlendAndDepth(shaderstate.curshader->passes[0].shaderbits); GL_ApplyVertexPointer(); - BE_SubmitMeshChain(meshlist); + BE_SubmitMeshChain(); break; } //fallthrough case BEM_STANDARD: default: if (shaderstate.curshader->programhandle.glsl) - BE_RenderMeshProgram(shaderstate.curshader, shaderstate.curshader->passes, meshlist); + BE_RenderMeshProgram(shaderstate.curshader, shaderstate.curshader->passes); else { while (passno < shaderstate.curshader->numpasses) @@ -2342,14 +2479,14 @@ static void DrawMeshChain(const mesh_t *meshlist) // if (p->flags & SHADER_PASS_DETAIL) // continue; - DrawPass(p, meshlist); + DrawPass(p); } } break; } } -void BE_DrawMeshChain(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums) +void BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t *vbo, texnums_t *texnums) { if (!vbo) { @@ -2360,12 +2497,11 @@ void BE_DrawMeshChain(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t shaderstate.curtexnums = texnums; shaderstate.curlightmap = r_nulltex; shaderstate.curdeluxmap = r_nulltex; - shaderstate.curtime = realtime; + shaderstate.curtime = cl.servertime - currententity->shaderTime; - while (meshchain) + while (nummeshes--) { - m = meshchain; - meshchain = meshchain->next; + m = *meshlist++; shaderstate.dummyvbo.coord = m->xyz_array; shaderstate.dummyvbo.texcoord = m->st_array; @@ -2375,9 +2511,9 @@ void BE_DrawMeshChain(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t shaderstate.dummyvbo.tvector = m->tnormals_array; shaderstate.dummyvbo.colours4f = m->colors4f_array; - m->next = NULL; - DrawMeshChain(m); - m->next = meshchain; + shaderstate.meshcount = 1; + shaderstate.meshes = &m; + DrawMeshes(); } } else @@ -2390,154 +2526,15 @@ void BE_DrawMeshChain(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t shaderstate.curdeluxmap = r_nulltex; shaderstate.curtime = realtime; - DrawMeshChain(meshchain); + shaderstate.meshcount = nummeshes; + shaderstate.meshes = meshlist; + DrawMeshes(); } } - -//FIXME: Legacy code -void R_RenderMeshBuffer(meshbuffer_t *mb, qboolean shadowpass) +void BE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, vbo_t *vbo, texnums_t *texnums) { - mesh_t *m; - if (!shaderstate.pushedmeshes) - return; - - BE_SelectMode(BEM_STANDARD, 0); - shaderstate.sourcevbo = &shaderstate.dummyvbo; - shaderstate.curshader = mb->shader; - shaderstate.curentity = mb->entity; - shaderstate.curtexnums = NULL; - shaderstate.curlightmap = r_nulltex; - shaderstate.curdeluxmap = r_nulltex; - if (shaderstate.force2d || !shaderstate.curentity) - shaderstate.curtime = realtime; - else - shaderstate.curtime = r_refdef.time - shaderstate.curentity->shaderTime; - - while (shaderstate.pushedmeshes) - { - m = shaderstate.pushedmeshes; - shaderstate.pushedmeshes = m->next; - m->next = NULL; - shaderstate.dummyvbo.coord = m->xyz_array; - shaderstate.dummyvbo.texcoord = m->st_array; - shaderstate.dummyvbo.indicies = m->indexes; - shaderstate.dummyvbo.normals = m->normals_array; - shaderstate.dummyvbo.svector = m->snormals_array; - shaderstate.dummyvbo.tvector = m->tnormals_array; - shaderstate.dummyvbo.colours4f = m->colors4f_array; - if (m->vbofirstvert || m->vbofirstelement) - return; - DrawMeshChain(m); - } -} -void R_PushMesh(mesh_t *mesh, int features) -{ - mesh->next = shaderstate.pushedmeshes; - shaderstate.pushedmeshes = mesh; -} - -static void DrawSurfaceChain(msurface_t *s, shader_t *shader, vbo_t *vbo) -{ //doesn't merge surfaces, but tells gl to do each vertex arrayed surface individually, which means no vertex copying. - int i; - mesh_t *ml, *m; - - if (!vbo) - return; - - ml = NULL; - for (; s ; s=s->texturechain) - { - m = s->mesh; - if (!m) //urm. - continue; - if (m->numvertexes <= 1) - continue; - - if (s->lightmaptexturenum < 0) - { - m->next = ml; - ml = m; - } - else - { - m->next = lightmap[s->lightmaptexturenum]->meshchain; - lightmap[s->lightmaptexturenum]->meshchain = m; - } - } - - shaderstate.sourcevbo = vbo; - shaderstate.curshader = shader; - shaderstate.curentity = currententity; - shaderstate.curtime = realtime; - - if (ml) - { - shaderstate.curlightmap = r_nulltex; - shaderstate.curdeluxmap = r_nulltex; - DrawMeshChain(ml); - } - checkerror(); - for (i = 0; i < numlightmaps; i++) - { - if (!lightmap[i] || !lightmap[i]->meshchain) - continue; - - if (lightmap[i]->modified) - { - glRect_t *theRect; - lightmap[i]->modified = false; - theRect = &lightmap[i]->rectchange; - GL_Bind(lightmap_textures[i]); - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, ((lightmap_bytes==3)?GL_RGB:GL_LUMINANCE), GL_UNSIGNED_BYTE, - lightmap[i]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*lightmap_bytes); - theRect->l = LMBLOCK_WIDTH; - theRect->t = LMBLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; - checkerror(); - - if (lightmap[i]->deluxmodified) - { - lightmap[i]->deluxmodified = false; - theRect = &lightmap[i]->deluxrectchange; - GL_Bind(deluxmap_textures[i]); - qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE, - lightmap[i]->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); - theRect->l = LMBLOCK_WIDTH; - theRect->t = LMBLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; - checkerror(); - } - } - - shaderstate.curlightmap = lightmap_textures[i]; - shaderstate.curdeluxmap = deluxmap_textures[i]; - DrawMeshChain(lightmap[i]->meshchain); - lightmap[i]->meshchain = NULL; - } -} - - -static void BE_BaseTextureChain(msurface_t *first) -{ - texture_t *t, *tex; - shader_t *shader; - t = first->texinfo->texture; - tex = R_TextureAnimation (t); - - //TEMP: use shader as an input parameter, not tex. - shader = tex->shader; - if (!shader) - { - shader = R_RegisterShader_Lightmap(tex->name); - tex->shader = shader; - } - - shaderstate.curtexnums = &shader->defaulttextures; - DrawSurfaceChain(first, shader, &t->vbo); + shader->next = NULL; + BE_DrawMesh_List(shader, 1, &mesh, NULL, texnums); } static void BaseBrushTextures(entity_t *ent) @@ -2546,6 +2543,9 @@ static void BaseBrushTextures(entity_t *ent) msurface_t *s, *chain; model_t *model; + batch_t batch; + mesh_t *batchmeshes[64]; + #ifdef RTLIGHTS if (BE_LightCullModel(ent->origin, ent->model)) return; @@ -2554,11 +2554,6 @@ static void BaseBrushTextures(entity_t *ent) qglPushMatrix(); R_RotateForEntity(ent); - ent->shaderRGBAf[0] = 1; - ent->shaderRGBAf[1] = 1; - ent->shaderRGBAf[2] = 1; - ent->shaderRGBAf[3] = 1; - model = ent->model; chain = NULL; @@ -2590,20 +2585,26 @@ static void BaseBrushTextures(entity_t *ent) Surf_RenderDynamicLightmaps (s, shift); } + memset(&batch, 0, sizeof(batch)); + batch.maxmeshes = sizeof(batchmeshes)/sizeof(batchmeshes[0]); + batch.mesh = batchmeshes; + batch.lightmap = -1; + batch.texture = NULL; for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) { - if (chain && s->texinfo->texture != chain->texinfo->texture) //last surface or not the same as the next + if (batch.meshes == batch.maxmeshes || batch.lightmap != s->lightmaptexturenum || batch.texture != s->texinfo->texture) { - BE_BaseTextureChain(chain); - chain = NULL; + if (batch.texture) + BE_SubmitBatch(&batch); + batch.texture = s->texinfo->texture; + batch.shader = R_TextureAnimation (batch.texture)->shader; + batch.lightmap = s->lightmaptexturenum; + batch.meshes = 0; } - - s->texturechain = chain; - chain = s; + batch.mesh[batch.meshes++] = s->mesh; } - - if (chain) - BE_BaseTextureChain(chain); + if (batch.texture) + BE_SubmitBatch(&batch); qglPopMatrix(); } @@ -2657,7 +2658,7 @@ void BE_BaseEntTextures(void) continue; if (currententity->model->needload) continue; - if (!PPL_ShouldDraw()) + if (!R_ShouldDraw(currententity)) continue; switch(currententity->model->type) { @@ -2699,40 +2700,147 @@ void BE_DrawPolys(qboolean decalsset) m.indexes = cl_strisidx + cl_stris[i].firstidx; m.numindexes = cl_stris[i].numidx; m.numvertexes = cl_stris[i].numvert; - BE_DrawMeshChain(cl_stris[i].shader, &m, NULL, &cl_stris[i].shader->defaulttextures); + BE_DrawMesh_Single(cl_stris[i].shader, &m, NULL, &cl_stris[i].shader->defaulttextures); + } +} +static void BE_SubmitBatch(batch_t *batch) +{ + model_t *model = cl.worldmodel; + int lm; + + lm = batch->lightmap; + if (lm < 0) + { + shaderstate.curlightmap = r_nulltex; + shaderstate.curdeluxmap = r_nulltex; + } + else + { + if (lightmap[lm]->modified) + { + glRect_t *theRect; + lightmap[lm]->modified = false; + theRect = &lightmap[lm]->rectchange; + GL_Bind(lightmap_textures[lm]); + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, + LMBLOCK_WIDTH, theRect->h, ((lightmap_bytes==3)?GL_RGB:GL_LUMINANCE), GL_UNSIGNED_BYTE, + lightmap[lm]->lightmaps+(theRect->t) *LMBLOCK_WIDTH*lightmap_bytes); + theRect->l = LMBLOCK_WIDTH; + theRect->t = LMBLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + checkerror(); + + if (lightmap[lm]->deluxmodified) + { + lightmap[lm]->deluxmodified = false; + theRect = &lightmap[lm]->deluxrectchange; + GL_Bind(deluxmap_textures[lm]); + qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, + LMBLOCK_WIDTH, theRect->h, GL_RGB, GL_UNSIGNED_BYTE, + lightmap[lm]->deluxmaps+(theRect->t) *LMBLOCK_WIDTH*3); + theRect->l = LMBLOCK_WIDTH; + theRect->t = LMBLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; + checkerror(); + } + } + + shaderstate.curlightmap = lightmap_textures[lm]; + shaderstate.curdeluxmap = deluxmap_textures[lm]; + } + + shaderstate.sourcevbo = &batch->texture->vbo; + shaderstate.curshader = batch->shader; + shaderstate.curentity = currententity; + shaderstate.curtime = realtime; + + shaderstate.curtexnums = &shaderstate.curshader->defaulttextures; + + if (0) + { + int i; + for (i = batch->firstmesh; i < batch->meshes; i++) + { + shaderstate.meshcount = 1; + shaderstate.meshes = &batch->mesh[i]; + DrawMeshes(); + } + } + else + { + shaderstate.meshcount = batch->meshes - batch->firstmesh; + shaderstate.meshes = batch->mesh+batch->firstmesh; + DrawMeshes(); } } void BE_SubmitMeshes (void) { - texture_t *t; - msurface_t *s; - int i; model_t *model = cl.worldmodel; - unsigned int fl; + batch_t *batch, *old; currententity = &r_worldentity; - for (i=0 ; inumtextures ; i++) + /*find all the portal shaders and try to draw them*/ + if (!r_noportals.ival && !r_refdef.recurse) { - t = model->textures[i]; - if (!t) - continue; - s = t->texturechain; - if (!s) + if (shaderstate.mode == BEM_STANDARD) + { + for (batch = model->batches; batch; batch = batch->next) + { + batch->shader = R_TextureAnimation (batch->texture)->shader; + if (batch->shader->sort > SHADER_SORT_PORTAL) + break; + + if (batch->meshes == batch->firstmesh) + continue; + + BE_SelectMode(BEM_DEPTHONLY, 0); + for (old = model->batches; old != batch; old = old->next) + { + if (old->meshes == old->firstmesh) + continue; + BE_SubmitBatch(old); + } + BE_SelectMode(BEM_STANDARD, 0); + + + R_DrawPortal(batch); + + /*clear depth again*/ + GL_ForceDepthWritable(); + qglClear(GL_DEPTH_BUFFER_BIT); + currententity = &r_worldentity; + } + } + } + + for (batch = model->batches; batch; batch = batch->next) + { + if (batch->meshes == batch->firstmesh) continue; - fl = s->texinfo->texture->shader->flags; - if (fl & SHADER_NODLIGHT) + batch->shader = R_TextureAnimation (batch->texture)->shader; + + if (batch->shader->sort == SHADER_SORT_PORTAL) + { + if (shaderstate.mode != BEM_STANDARD) + continue; + } + + if (batch->shader->flags & SHADER_NODLIGHT) if (shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_SMAPLIGHT) continue; - if (fl & SHADER_SKY) + if (batch->shader->flags & SHADER_SKY) { if (shaderstate.mode == BEM_STANDARD) - R_DrawSkyChain (s); + R_DrawSkyChain (batch); + continue; } - else - BE_BaseTextureChain(s); + + BE_SubmitBatch(batch); } if (shaderstate.mode == BEM_STANDARD) @@ -2741,6 +2849,7 @@ void BE_SubmitMeshes (void) checkerror(); BE_BaseEntTextures(); checkerror(); + currententity = &r_worldentity; } void BE_DrawWorld (qbyte *vis) @@ -2758,9 +2867,11 @@ void BE_DrawWorld (qbyte *vis) r_worldentity.axis[1][1] = 1; r_worldentity.axis[2][2] = 1; +#ifdef RTLIGHTS if (r_shadow_realtime_world.value) shaderstate.identitylighting = r_shadow_realtime_world_lightmaps.value; else +#endif shaderstate.identitylighting = 1; if (shaderstate.identitylighting == 0) diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index 9e866703..34df4571 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -27,47 +27,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef GLQUAKE #include "glquake.h" -extern vrect_t gl_truescreenrect; +/* +============================================================================== -/* -============================================================================== - LIGHT BLOOMS - -============================================================================== -*/ -static float Diamond8x[8][8] = { - {0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f}, - {0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f}, - {0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f}, - {0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f}, - {0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f}, - {0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f}, - {0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f} }; +============================================================================== +*/ -static float Diamond6x[6][6] = { - {0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f}, - {0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f}, - {0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f}, - {0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f}, - {0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f}, - {0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f} }; - -static float Diamond4x[4][4] = { - {0.3f, 0.4f, 0.4f, 0.3f}, - {0.4f, 0.9f, 0.9f, 0.4f}, - {0.4f, 0.9f, 0.9f, 0.4f}, - {0.3f, 0.4f, 0.4f, 0.3f} }; - - cvar_t r_bloom = FCVAR("r_bloom", "gl_bloom", "0", CVAR_ARCHIVE); -static cvar_t r_bloom_alpha = SCVAR("r_bloom_alpha", "0.5"); -static cvar_t r_bloom_diamond_size = SCVAR("r_bloom_diamond_size", "8"); -static cvar_t r_bloom_intensity = SCVAR("r_bloom_intensity", "1"); -static cvar_t r_bloom_darken = SCVAR("r_bloom_darken", "3"); -static cvar_t r_bloom_sample_size = SCVARF("r_bloom_sample_size", "256", CVAR_RENDERERLATCH); -static cvar_t r_bloom_fast_sample = SCVARF("r_bloom_fast_sample", "0", CVAR_RENDERERLATCH); +cvar_t r_bloom = CVARAFD("r_bloom", "0", "gl_bloom", CVAR_ARCHIVE, "Enables bloom (light bleeding from bright objects)"); +cvar_t r_bloom_alpha = CVAR("r_bloom_alpha", "0.5"); +cvar_t r_bloom_diamond_size = CVAR("r_bloom_diamond_size", "8"); +cvar_t r_bloom_intensity = CVAR("r_bloom_intensity", "1"); +cvar_t r_bloom_darken = CVAR("r_bloom_darken", "3"); +cvar_t r_bloom_sample_size = CVARF("r_bloom_sample_size", "256", CVAR_RENDERERLATCH); +cvar_t r_bloom_fast_sample = CVARF("r_bloom_fast_sample", "0", CVAR_RENDERERLATCH); typedef struct { //texture numbers @@ -139,12 +113,12 @@ R_Bloom_InitBackUpTexture void R_Bloom_InitBackUpTexture(int widthheight) { qbyte *data; - + data = Z_Malloc(widthheight * widthheight * 4); bs.size_backup = widthheight; bs.tx_backup = GL_LoadTexture32("***bs.tx_backup***", bs.size_backup, bs.size_backup, (unsigned int*)data, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA); - + Z_Free (data); } @@ -157,12 +131,12 @@ void R_Bloom_InitEffectTexture(void) { qbyte *data; float bloomsizecheck; - + if (r_bloom_sample_size.value < 32) Cvar_SetValue (&r_bloom_sample_size, 32); //make sure bloom size is a power of 2 - bs.size_sample = r_bloom_sample_size.value; + bs.size_sample = min(r_bloom_sample_size.value, gl_max_size.value); bloomsizecheck = (float)bs.size_sample; while (bloomsizecheck > 1.0f) bloomsizecheck /= 2.0f; if (bloomsizecheck != 1.0f) @@ -183,7 +157,7 @@ void R_Bloom_InitEffectTexture(void) data = Z_Malloc(bs.size_sample * bs.size_sample * 4); bs.tx_effect = GL_LoadTexture32("***bs.tx_effect***", bs.size_sample, bs.size_sample, (unsigned int*)data, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA); - + Z_Free (data); } @@ -198,7 +172,7 @@ void R_Bloom_InitTextures(void) int size; int maxtexsize; - //find closer power of 2 to screen size + //find closer power of 2 to screen size for (bs.scr_w = 1;bs.scr_w < vid.pixelwidth;bs.scr_w *= 2); for (bs.scr_h = 1;bs.scr_h < vid.pixelheight;bs.scr_h *= 2); @@ -286,7 +260,7 @@ void R_Bloom_DrawEffect(void) qglBlendFunc(GL_ONE, GL_ONE); qglColor4f(r_bloom_alpha.value, r_bloom_alpha.value, r_bloom_alpha.value, 1.0f); GL_TexEnv(GL_MODULATE); - qglBegin(GL_QUADS); + qglBegin(GL_QUADS); qglTexCoord2f (0, bs.smp_t); qglVertex2f (bs.vp_x, bs.vp_y); qglTexCoord2f (0, 0); @@ -296,7 +270,7 @@ void R_Bloom_DrawEffect(void) qglTexCoord2f (bs.smp_s, bs.smp_t); qglVertex2f (bs.vp_x + bs.vp_w, bs.vp_y); qglEnd(); - + qglDisable(GL_BLEND); } @@ -337,7 +311,7 @@ void R_Bloom_GeneratexCross(void) { qglBlendFunc(GL_DST_COLOR, GL_ZERO); GL_TexEnv(GL_MODULATE); - + for(i=0; iinteger ;i++) { R_Bloom_SamplePass( 0, 0 ); } @@ -346,7 +320,7 @@ void R_Bloom_GeneratexCross(void) //bluring passes if( BLOOM_BLUR_RADIUS ) { - + qglBlendFunc(GL_ONE, GL_ONE); range = (float)BLOOM_BLUR_RADIUS; @@ -381,7 +355,7 @@ void R_Bloom_GeneratexCross(void) qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bs.smp_w, bs.smp_h); } - + //restore full screen workspace qglViewport( 0, 0, glState.width, glState.height ); qglMatrixMode( GL_PROJECTION ); @@ -424,7 +398,7 @@ void R_Bloom_GeneratexDiamonds(void) { qglBlendFunc(GL_DST_COLOR, GL_ZERO); GL_TexEnv(GL_MODULATE); - + for (i=0; i 7 || r_bloom_diamond_size.value <= 3) - { - if (r_bloom_diamond_size.value != 8) - Cvar_SetValue(&r_bloom_diamond_size, 8); - for (i=0; i 5) - { - if (r_bloom_diamond_size.value != 6) - Cvar_SetValue(&r_bloom_diamond_size, 6); - for(i=0; i 3) - { - if (r_bloom_diamond_size.value != 4) - Cvar_SetValue(&r_bloom_diamond_size, 4); - - for (i=0; i bs.vp_w) @@ -606,9 +547,9 @@ void R_BloomBlend (void)//refdef_t *fd, meshlist_t *meshlist ) bs.smp_s = (float)bs.smp_w/bs.size_sample; bs.smp_t = (float)bs.smp_h/bs.size_sample; - buw = bs.size_downsample * bs.smp_s; - buh = bs.size_downsample * bs.smp_t; - + buw = bs.size_backup * bs.smp_s; + buh = bs.size_backup * bs.smp_t; + //copy the screen space we'll use to work into the backup texture GL_Bind(bs.tx_backup); qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, buw, buh); @@ -623,7 +564,7 @@ void R_BloomBlend (void)//refdef_t *fd, meshlist_t *meshlist ) qglDisable(GL_BLEND); GL_Bind(bs.tx_backup); qglColor4f(1, 1, 1, 1); - R_Bloom_Quad(0, + R_Bloom_Quad(0, vid.pixelheight - (buh), buw, buh, diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 68fad4e2..e1f0f44a 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -37,8 +37,9 @@ static void GL_Upload32 (char *name, unsigned *data, int width, int height, unsi static void GL_Upload32_BGRA (char *name, unsigned *data, int width, int height, unsigned int flags); static void GL_Upload24BGR_Flip (char *name, qbyte *framedata, int inwidth, int inheight, unsigned int flags); static void GL_Upload8 (char *name, qbyte *data, int width, int height, unsigned int flags, unsigned int alpha); +static void GL_Upload8Pal32 (qbyte *data, qbyte *pal, int width, int height, unsigned int flags); -void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, int width, int height, unsigned int flags) +void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags) { GL_Bind(tex); switch(fmt) @@ -72,6 +73,13 @@ void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, int w GL_Upload8(name, data, width, height, flags, 1); break; + case TF_8PAL24: + GL_Upload8Pal24(data, palette, width, height, flags); + break; + case TF_8PAL32: + GL_Upload8Pal32(data, palette, width, height, flags); + break; + #ifdef _MSC_VER default: Sys_Error("Unsupported image format type\n"); @@ -79,6 +87,7 @@ void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, int w #endif } } + texid_t GL_LoadTextureFmt (char *name, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags) { extern cvar_t r_shadow_bumpscale_basetexture; @@ -122,40 +131,30 @@ static index_t r_quad_indexes[6] = {0, 1, 2, 0, 2, 3}; extern qbyte gammatable[256]; +#ifdef GL_USE8BITTEX unsigned char *d_15to8table; qboolean inited15to8; +#endif extern cvar_t crosshair, crosshairimage, crosshairalpha, cl_crossx, cl_crossy, crosshaircolor, crosshairsize; static texid_t filmtexture; -extern cvar_t gl_nobind; extern cvar_t gl_max_size; extern cvar_t gl_picmip; extern cvar_t gl_lerpimages; extern cvar_t gl_picmip2d; -extern cvar_t r_drawdisk; extern cvar_t gl_compress; -extern cvar_t gl_smoothfont, gl_smoothcrosshair, gl_fontinwardstep; +extern cvar_t gl_smoothcrosshair; extern cvar_t gl_texturemode, gl_texture_anisotropic_filtering; -extern cvar_t cl_noblink; extern cvar_t gl_savecompressedtex; -extern cvar_t gl_load24bit; - -extern cvar_t con_ocranaleds; -extern cvar_t gl_blend2d; -extern cvar_t scr_conalpha; - texid_t translate_texture; texid_t missing_texture; //texture used when one is missing. texid_t cs_texture; // crosshair texture shader_t *crosshair_shader; -float custom_char_instep, default_char_instep; //to avoid blending issues -float char_instep; - static unsigned cs_data[16*16]; static texid_t externalhair; int gl_anisotropy_factor; @@ -172,8 +171,6 @@ int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST; int gl_filter_max = GL_LINEAR; int gl_filter_max_2d = GL_LINEAR; -int texels; - typedef struct gltexture_s { texid_t texnum; @@ -407,7 +404,9 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); TRACE(("dbg: GLDraw_ReInit: Draw_SafePicFromWad\n")); draw_disc = Draw_SafePicFromWad ("disc"); +#ifdef GL_USE8BITTEX inited15to8 = false; +#endif qglClearColor (1,0,0,0); @@ -449,6 +448,9 @@ void GLDraw_DeInit (void) sizeofuploadmemorybuffer = 0; //and give a nice safe sys_error if we try using it. sizeofuploadmemorybufferintermediate = 0; +#ifdef RTLIGHTS + Sh_Shutdown(); +#endif Shader_Shutdown(); } @@ -490,7 +492,7 @@ void GLCrosshair_Callback(struct cvar_s *var, char *oldvalue) } #undef Pix - R_Upload(cs_texture, NULL, TF_RGBA32, cs_data, 16, 16, IF_NOMIPMAP|IF_NOGAMMA); + R_Upload(cs_texture, NULL, TF_RGBA32, cs_data, NULL, 16, 16, IF_NOMIPMAP|IF_NOGAMMA); if (gl_smoothcrosshair.ival) { @@ -744,7 +746,7 @@ void GLDraw_FadeScreen (void) if (!faderender) return; - +#pragma message("Warning: This doesn't use the backend") if (scenepp_mt_program && gl_menutint_shader.ival) { float vwidth = 1, vheight = 1; @@ -858,8 +860,6 @@ Call before beginning any disc IO. */ void GLDraw_BeginDisc (void) { - if (!draw_disc || !r_drawdisk.value) - return; } @@ -902,7 +902,7 @@ void GL_Set2D (void) - +#if 0 void MediaGL_ShowFrame8bit(qbyte *framedata, int inwidth, int inheight, qbyte *palette) //bottom up { if (!TEXVALID(filmtexture)) @@ -1079,7 +1079,7 @@ void MediaGL_ShowFrameBGR_24_Flip(qbyte *framedata, int inwidth, int inheight) if (scr_con_current) SCR_DrawConsole (false); } - +#endif //==================================================================== @@ -1289,7 +1289,7 @@ void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, unsigned *inrow; unsigned frac, fracstep; - if (gl_lerpimages.value) + if (gl_lerpimages.ival) { Image_Resample32Lerp(in, inwidth, inheight, out, outwidth, outheight); return; @@ -1611,8 +1611,6 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne if (gl_config.arb_texture_compression && gl_compress.value && name && !(flags&IF_NOMIPMAP)) samples = (flags&IF_NOALPHA) ? GL_COMPRESSED_RGB_ARB : GL_COMPRESSED_RGBA_ARB; -texels += scaled_width * scaled_height; - if (gl_config.sgis_generate_mipmap && !(flags&IF_NOMIPMAP)) { TRACE(("dbg: GL_Upload32: GL_SGIS_generate_mipmap\n")); @@ -1900,8 +1898,6 @@ void GL_Upload8Grey (unsigned char*data, int width, int height, unsigned int fla samples = 1;//alpha ? gl_alpha_format : gl_solid_format; -texels += scaled_width * scaled_height; - if (scaled_width == width && scaled_height == height) { if (flags&IF_NOMIPMAP) @@ -2185,8 +2181,6 @@ void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qbool samples = 1; // alpha ? gl_alpha_format : gl_solid_format; - texels += scaled_width * scaled_height; - if (scaled_width == width && scaled_height == height) { if (!mipmap) @@ -2457,7 +2451,7 @@ void GL_Upload8Pal24 (qbyte *data, qbyte *pal, int width, int height, unsigned i } GL_Upload32 (NULL, (unsigned*)trans, width, height, flags); } -void GL_Upload8Pal32 (qbyte *data, qbyte *pal, int width, int height, unsigned int flags) +static void GL_Upload8Pal32 (qbyte *data, qbyte *pal, int width, int height, unsigned int flags) { qbyte *trans = uploadmemorybufferintermediate; int i, s; diff --git a/engine/gl/gl_draw.h b/engine/gl/gl_draw.h index 6a1ef5c6..3754f501 100644 --- a/engine/gl/gl_draw.h +++ b/engine/gl/gl_draw.h @@ -49,3 +49,5 @@ void R2D_Shutdown(void); void R2D_PolyBlend (void); void R2D_BrightenScreen (void); + +void R2D_Conback_Callback(struct cvar_s *var, char *oldvalue); diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 8c343809..1264a1de 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -12,10 +12,12 @@ void Font_Shutdown(void); struct font_s *Font_LoadFont(int height, char *fontfilename); void Font_Free(struct font_s *f); void Font_BeginString(struct font_s *font, int vx, int vy, int *px, int *py); +void Font_BeginScaledString(struct font_s *font, float vx, float vy, float *px, float *py); /*avoid using*/ int Font_CharHeight(void); int Font_CharWidth(unsigned int charcode); int Font_CharEndCoord(int x, unsigned int charcode); int Font_DrawChar(int px, int py, unsigned int charcode); +float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int charcode); /*avoid using*/ void Font_EndString(struct font_s *font); int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends); struct font_s *font_conchar; @@ -157,7 +159,6 @@ static const char *imgs[] = #define GEN_CONCHAR_GLYPHS 0 //set to 0 or 1 to define whether to generate glyphs from conchars too, or if it should just draw them as glquake always used to extern cvar_t cl_noblink; -extern cvar_t gl_smoothfont; extern cvar_t con_ocranaleds; typedef struct font_s @@ -278,7 +279,7 @@ static void Font_Flush(void) if (fontplanes.planechanged) { - R_Upload(fontplanes.texnum[fontplanes.activeplane], NULL, TF_RGBA32, (void*)fontplanes.plane, PLANEWIDTH, PLANEHEIGHT, IF_NOPICMIP|IF_NOMIPMAP|IF_NOGAMMA); + R_Upload(fontplanes.texnum[fontplanes.activeplane], NULL, TF_RGBA32, (void*)fontplanes.plane, NULL, PLANEWIDTH, PLANEHEIGHT, IF_NOPICMIP|IF_NOMIPMAP|IF_NOGAMMA); fontplanes.planechanged = false; } @@ -286,15 +287,15 @@ static void Font_Flush(void) if (font_colourmask & CON_NONCLEARBG) { fontplanes.backshader->defaulttextures.base = r_nulltex; - BE_DrawMeshChain(fontplanes.backshader, &font_mesh, NULL, &fontplanes.backshader->defaulttextures); + BE_DrawMesh_Single(fontplanes.backshader, &font_mesh, NULL, &fontplanes.backshader->defaulttextures); fontplanes.shader->defaulttextures.base = font_texture; - BE_DrawMeshChain(fontplanes.shader, &font_mesh, NULL, &fontplanes.shader->defaulttextures); + BE_DrawMesh_Single(fontplanes.shader, &font_mesh, NULL, &fontplanes.shader->defaulttextures); } else { fontplanes.shader->defaulttextures.base = font_texture; - BE_DrawMeshChain(fontplanes.shader, &font_mesh, NULL, &fontplanes.shader->defaulttextures); + BE_DrawMesh_Single(fontplanes.shader, &font_mesh, NULL, &fontplanes.shader->defaulttextures); } font_mesh.numindexes = 0; @@ -448,13 +449,14 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx) struct charcache_s *c; #if GEN_CONCHAR_GLYPHS != 0 - if (charidx >= 0xe000 && charidx <= 0xe0ff && draw_chars) + if (charidx >= 0xe000 && charidx <= 0xe0ff) { int cpos = charidx & 0xff; unsigned int img[64*64], *d; unsigned char *s; int scale; int x,y, ys; + qbyte *draw_chars = W_GetLumpName("conchars"); if (draw_chars) { d = img; @@ -881,6 +883,12 @@ void Font_BeginString(struct font_s *font, int vx, int vy, int *px, int *py) *px = (vx*vid.pixelwidth) / (float)vid.width; *py = (vy*vid.pixelheight) / (float)vid.height; } +void Font_BeginScaledString(struct font_s *font, float vx, float vy, float *px, float *py) +{ + curfont = font; + *px = (vx*vid.pixelwidth) / (float)vid.width; + *py = (vy*vid.pixelheight) / (float)vid.height; +} void Font_EndString(struct font_s *font) { @@ -1098,8 +1106,8 @@ int Font_DrawChar(int px, int py, unsigned int charcode) { sx = ((px+c->left)*(int)vid.width) / (float)vid.pixelwidth; sy = ((py+c->top)*(int)vid.height) / (float)vid.pixelheight; - sw = ((c->bmw+1)*vid.width) / (float)vid.pixelwidth; - sh = ((c->bmh+1)*vid.height) / (float)vid.pixelheight; + sw = ((c->bmw)*vid.width) / (float)vid.pixelwidth; + sh = ((c->bmh)*vid.height) / (float)vid.pixelheight; v = Font_BeginChar(fontplanes.texnum[c->texplane]); } @@ -1123,4 +1131,107 @@ int Font_DrawChar(int px, int py, unsigned int charcode) return nextx; } + +/*there is no sane way to make this pixel-correct*/ +float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int charcode) +{ + struct charcache_s *c; + float s0, s1; + float t0, t1; + float nextx; + float sx, sy, sw, sh; + int col; + int v; + + cw /= curfont->charheight; + ch /= curfont->charheight; + + + //crash if there is no current font. + c = Font_GetChar(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK)); + if (!c) + { + c = Font_TryLoadGlyph(curfont, (CHARIDXTYPE)(charcode&CON_CHARMASK)); + if (!c) + return px; + } + + nextx = px + c->advance*cw; + + if ((charcode & CON_CHARMASK) == ' ') + return nextx; + + if (charcode & CON_BLINKTEXT) + { + if (!cl_noblink.ival) + if ((int)(realtime*3) & 1) + return nextx; + } + + col = charcode & (CON_NONCLEARBG|CON_BGMASK|CON_FGMASK|CON_HALFALPHA); + if (col != font_colourmask) + { + Font_Flush(); + font_colourmask = col; + + col = (charcode&CON_FGMASK)>>CON_FGSHIFT; + fontplanes.shader->passes[0].rgbgen_func.args[0] = consolecolours[col].fr; + fontplanes.shader->passes[0].rgbgen_func.args[1] = consolecolours[col].fg; + fontplanes.shader->passes[0].rgbgen_func.args[2] = consolecolours[col].fb; + fontplanes.shader->passes[0].alphagen_func.args[0] = (charcode & CON_HALFALPHA)?0.5:1; + + col = (charcode&CON_BGMASK)>>CON_BGSHIFT; + fontplanes.backshader->passes[0].rgbgen_func.args[0] = consolecolours[col].fr; + fontplanes.backshader->passes[0].rgbgen_func.args[1] = consolecolours[col].fg; + fontplanes.backshader->passes[0].rgbgen_func.args[2] = consolecolours[col].fb; + fontplanes.backshader->passes[0].alphagen_func.args[0] = (charcode & CON_NONCLEARBG)?0.5:0; + } + + s0 = (float)c->bmx/PLANEWIDTH; + t0 = (float)c->bmy/PLANEWIDTH; + s1 = (float)(c->bmx+c->bmw)/PLANEWIDTH; + t1 = (float)(c->bmy+c->bmh)/PLANEWIDTH; + + if (c->texplane >= DEFAULTPLANE) + { + sx = ((px+c->left)*(int)vid.width) / (float)vid.pixelwidth; + sy = ((py+c->top)*(int)vid.height) / (float)vid.pixelheight; + sw = ((curfont->charheight*cw)*vid.width) / (float)vid.pixelwidth; + sh = ((curfont->charheight*ch)*vid.height) / (float)vid.pixelheight; + + if (c->texplane == DEFAULTPLANE) + v = Font_BeginChar(fontplanes.defaultfont); + else + v = Font_BeginChar(curfont->singletexture); + } + else + { + sx = ((px+c->left)*(int)vid.width) / (float)vid.pixelwidth; + sy = ((py+c->top)*(int)vid.height) / (float)vid.pixelheight; + sw = ((c->bmw*cw)*vid.width) / (float)vid.pixelwidth; + sh = ((c->bmh*ch)*vid.height) / (float)vid.pixelheight; + v = Font_BeginChar(fontplanes.texnum[c->texplane]); + } + + font_texcoord[v+0][0] = s0; + font_texcoord[v+0][1] = t0; + font_texcoord[v+1][0] = s1; + font_texcoord[v+1][1] = t0; + font_texcoord[v+2][0] = s1; + font_texcoord[v+2][1] = t1; + font_texcoord[v+3][0] = s0; + font_texcoord[v+3][1] = t1; + + font_coord[v+0][0] = sx; + font_coord[v+0][1] = sy; + font_coord[v+1][0] = sx+sw; + font_coord[v+1][1] = sy; + font_coord[v+2][0] = sx+sw; + font_coord[v+2][1] = sy+sh; + font_coord[v+3][0] = sx; + font_coord[v+3][1] = sy+sh; + + return nextx; +} + #endif //!SERVERONLY diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 8ea086f9..50163f1d 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -587,12 +587,12 @@ unsigned int Heightmap_FatPVS (model_t *mod, vec3_t org, qbyte *pvsbuffer, unsi } #ifndef CLIENTONLY -qboolean Heightmap_EdictInFatPVS (model_t *mod, wedict_t *edict, qbyte *pvsdata) +qboolean Heightmap_EdictInFatPVS (model_t *mod, struct pvscache_s *edict, qbyte *pvsdata) { return true; } -void Heightmap_FindTouchedLeafs (world_t *w, model_t *mod, wedict_t *ent, float *mins, float *maxs) +void Heightmap_FindTouchedLeafs (model_t *mod, pvscache_t *ent, float *mins, float *maxs) { } #endif @@ -790,7 +790,7 @@ qboolean GL_LoadHeightmapModel (model_t *mod, void *buffer) mod->funcs.LeafPVS = Heightmap_LeafnumPVS; #ifndef CLIENTONLY - mod->funcs.FindTouchedLeafs_Q1 = Heightmap_FindTouchedLeafs; + mod->funcs.FindTouchedLeafs = Heightmap_FindTouchedLeafs; mod->funcs.EdictInFatPVS = Heightmap_EdictInFatPVS; mod->funcs.FatPVS = Heightmap_FatPVS; #endif diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index a6b45524..a7e68ea5 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -67,7 +67,8 @@ extern cvar_t r_loadlits; extern cvar_t gl_specular; #endif extern cvar_t r_fb_bmodels; - +mesh_t nullmesh; +void Mod_SortShaders(void); #ifdef RUNTIMELIGHTING model_t *lightmodel; @@ -152,7 +153,7 @@ void RMod_BlockTextureColour_f (void) { memset(&tn, 0, sizeof(tn)); tn.base = R_LoadTexture32(texname, 8, 8, colour, IF_NOALPHA|IF_NOGAMMA); - s = R_RegisterCustom (texname, Shader_DefaultBSP, NULL); + s = R_RegisterCustom (texname, Shader_DefaultBSPQ1, NULL); } for (i = 0; i < sizeof(colour)/sizeof(colour[0]); i++) @@ -923,16 +924,16 @@ void Mod_FinishTexture(texture_t *tx, texnums_t tn) char *star; //find the * if (!*gl_shadeq1_name.string || !strcmp(gl_shadeq1_name.string, "*")) - tx->shader = R_RegisterShader_Lightmap(tx->name); //just load the regular name. + tx->shader = R_RegisterCustom (tx->name, Shader_DefaultBSPQ1, NULL); //just load the regular name. else if (!(star = strchr(gl_shadeq1_name.string, '*')) || (strlen(gl_shadeq1_name.string)+strlen(tx->name)+1>=sizeof(altname))) //it's got to fit. - tx->shader = R_RegisterShader_Lightmap(gl_shadeq1_name.string); + tx->shader = R_RegisterCustom (gl_shadeq1_name.string, Shader_DefaultBSPQ1, NULL); else { strncpy(altname, gl_shadeq1_name.string, star-gl_shadeq1_name.string); //copy the left altname[star-gl_shadeq1_name.string] = '\0'; strcat(altname, tx->name); //insert the * strcat(altname, star+1); //add any final text. - tx->shader = R_RegisterShader_Lightmap(altname); + tx->shader = R_RegisterCustom (altname, Shader_DefaultBSPQ1, NULL); } R_BuildDefaultTexnums(&tn, tx->shader); @@ -1996,7 +1997,6 @@ qboolean RMod_LoadFaces (lump_t *l) }*/ if (!Q_strncmp(out->texinfo->texture->name,"{",1)) // alpha { - out->texinfo->flags |= TI_ALPHATEST; out->flags |= (SURF_DRAWALPHA); continue; } @@ -2124,7 +2124,6 @@ qboolean RMod_LoadLeafs (lump_t *l) out->compressed_vis = NULL; else out->compressed_vis = loadmodel->visdata + p; - out->efrags = NULL; for (j=0 ; j<4 ; j++) out->ambient_sound_level[j] = in->ambient_level[j]; @@ -2915,6 +2914,9 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) RMod_MakeHull0 (); } + if (!isDedicated && noerrors) + Mod_SortShaders(); + if (crouchhullfile) { FS_FreeFile(crouchhullfile); diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 4f5cc324..b3385832 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -49,8 +49,8 @@ typedef struct { unsigned int (*NativeContents)(struct model_s *model, int hulloverride, int frame, vec3_t p, vec3_t mins, vec3_t maxs); unsigned int (*FatPVS) (struct model_s *model, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean merge); - qboolean (*EdictInFatPVS) (struct model_s *model, struct wedict_s *edict, qbyte *pvsbuffer); - void (*FindTouchedLeafs_Q1) (struct world_s *w, struct model_s *model, struct wedict_s *ent, vec3_t cullmins, vec3_t cullmaxs); //edict system as opposed to q2 game dll system. + qboolean (*EdictInFatPVS) (struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer); + void (*FindTouchedLeafs) (struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs); //edict system as opposed to q2 game dll system. void (*LightPointValues) (struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void (*StainNode) (struct mnode_s *node, float *parms); @@ -62,41 +62,49 @@ typedef struct { typedef struct mesh_s { + int numvertexes; + int numindexes; + + /*position within its vbo*/ unsigned int vbofirstvert; unsigned int vbofirstelement; - - int numvertexes; + /*arrays used for rendering*/ vecV_t *xyz_array; - vec3_t *normals_array; - vec3_t *snormals_array; - vec3_t *tnormals_array; - vec2_t *st_array; - vec2_t *lmst_array; - avec4_t *colors4f_array; - byte_vec4_t *colors4b_array; + vec3_t *normals_array; /*required for lighting*/ + vec3_t *snormals_array;/*required for rtlighting*/ + vec3_t *tnormals_array;/*required for rtlighting*/ + vec2_t *st_array; /*texture coords*/ + vec2_t *lmst_array; /*second texturecoord set (merely dubbed lightmap)*/ + avec4_t *colors4f_array;/*floating point colours array*/ + byte_vec4_t *colors4b_array;/*byte colours array*/ - int numindexes; index_t *indexes; + + //required for shadow volumes int *trneighbors; vec3_t *trnormals; - vec3_t mins, maxs; - float radius; - - qboolean istrifan; /*if its a fan/poly/single quad*/ - - struct mesh_s *next; + qboolean istrifan; /*if its a fan/poly/single quad (permits optimisations)*/ } mesh_t; -FTE_DEPRECATED struct meshbuffer_s; - -void FTE_DEPRECATED R_PushMesh ( mesh_t *mesh, int features ); -void FTE_DEPRECATED R_RenderMeshBuffer ( struct meshbuffer_s *mb, qboolean shadowpass ); -qboolean FTE_DEPRECATED R_MeshWillExceed(mesh_t *mesh); +extern mesh_t nullmesh; extern int gl_canbumpmap; +typedef struct batch_s +{ + mesh_t **mesh; /*list must be long enough for all surfaces that will form part of this batch times two, for mirrors/portals*/ + unsigned int firstmesh; + unsigned int meshes; + struct batch_s *next; + shader_t *shader; + struct texture_s *texture; + struct vbo_s *vbo; + int lightmap; + unsigned int maxmeshes; + vec3_t normal; +} batch_t; /* d*_t structures are on-disk representations @@ -166,8 +174,11 @@ typedef struct { struct shader_s *shader; //fixme: remove... } texnums_t; -typedef struct +typedef struct vbo_s { + int numvisible; + struct msurface_s **vislist; + int meshcount; struct msurface_s **meshlist; @@ -205,11 +216,10 @@ typedef struct texture_s int parttype; struct shader_s *shader; + int wtexno; vbo_t vbo; - struct msurface_s *texturechain; // for gl_texsort drawing - struct msurface_s **texturechain_tail; //so we can link them in depth order int anim_total; // total tenths in sequence ( 0 = no) int anim_min, anim_max; // time for this frame min <=time< max struct texture_s *anim_next; // in the animation sequence @@ -295,8 +305,6 @@ typedef struct msurface_s int firstedge; // look up in model->surfedges[], negative numbers int numedges; // are backwards edges - struct msurface_s *nextalphasurface; - short texturemins[2]; short extents[2]; @@ -306,7 +314,7 @@ typedef struct msurface_s mesh_t *mesh; entity_t *ownerent; - struct msurface_s *texturechain; + batch_t *sbatch; mtexinfo_t *texinfo; struct msurface_s **mark; int visframe; // should be drawn when node is crossed @@ -369,7 +377,6 @@ typedef struct mleaf_s // leaf specific qbyte *compressed_vis; - struct efrag_s *efrags; msurface_t **firstmarksurface; int nummarksurfaces; @@ -429,12 +436,11 @@ int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangen qboolean Q1BSP_Trace(struct model_s *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, struct trace_s *trace); qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace); unsigned int Q1BSP_FatPVS (struct model_s *mod, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean add); -qboolean Q1BSP_EdictInFatPVS(struct model_s *mod, struct wedict_s *ent, qbyte *pvs); -void Q1BSP_FindTouchedLeafs(struct world_s *w, struct model_s *mod, struct wedict_s *ent, float *mins, float *maxs); +qboolean Q1BSP_EdictInFatPVS(struct model_s *mod, struct pvscache_s *ent, qbyte *pvs); +void Q1BSP_FindTouchedLeafs(struct model_s *mod, struct pvscache_s *ent, float *mins, float *maxs); qbyte *Q1BSP_LeafPVS (struct model_s *model, mleaf_t *leaf, qbyte *buffer, unsigned int buffersize); - -FTE_DEPRECATED texnums_t R_InitSky (struct texture_s *mt); +texnums_t R_InitSky (struct texture_s *mt); /* ============================================================================== @@ -830,6 +836,7 @@ typedef struct model_s char *entities; void *terrain; + batch_t *batches; unsigned checksum; unsigned checksum2; diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 2c8d053c..6c755819 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -166,6 +166,7 @@ void R_RenderDlight (dlight_t *light) bub_sin = bubble_sintable; bub_cos = bubble_costable; rad = light->radius * 0.35; + rad = 16; VectorCopy(light->color, colour); @@ -202,7 +203,7 @@ void R_RenderDlight (dlight_t *light) bub_cos++; } - BE_DrawMeshChain(flashblend_shader, &flashblend_mesh, NULL, &flashblend_shader->defaulttextures); + BE_DrawMesh_Single(flashblend_shader, &flashblend_mesh, NULL, &flashblend_shader->defaulttextures); } /* diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index dcaeb480..30fb1129 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -34,8 +34,6 @@ void R_RenderBrushPoly (msurface_t *fa); extern int gl_canstencil; -vrect_t gl_truescreenrect; - FTEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB; FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB; @@ -55,14 +53,6 @@ float r_wateralphaval; //allowed or not... int c_brush_polys, c_alias_polys; -qboolean envmap; // true during envmap command capture - -int mirrortexturenum; // quake texturenum, not gltexturenum -qboolean mirror; -mplane_t *mirror_plane; -msurface_t *r_mirror_chain; -qboolean r_inmirror; //or out-of-body - // // view origin // @@ -71,9 +61,6 @@ vec3_t vpn; vec3_t vright; vec3_t r_origin; -extern float r_projection_matrix[16]; -extern float r_view_matrix[16]; - // // screen size info // @@ -85,22 +72,13 @@ int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; texture_t *r_notexture_mip; -//void R_MarkLeaves (void); - cvar_t r_norefresh = SCVAR("r_norefresh","0"); -//cvar_t r_drawentities = SCVAR("r_drawentities","1"); -//cvar_t r_drawviewmodel = SCVAR("r_drawviewmodel","1"); -//cvar_t r_speeds = SCVAR("r_speeds","0"); -//cvar_t r_fullbright = SCVAR("r_fullbright","0"); cvar_t r_mirroralpha = SCVARF("r_mirroralpha","1", CVAR_CHEAT); -//cvar_t r_waterwarp = SCVAR("r_waterwarp", "0"); -//cvar_t r_novis = SCVAR("r_novis","0"); -//cvar_t r_netgraph = SCVAR("r_netgraph","0"); extern cvar_t gl_part_flame; +extern cvar_t r_bloom; cvar_t gl_clear = SCVAR("gl_clear","0"); -cvar_t gl_cull = SCVAR("gl_cull","1"); cvar_t gl_smoothmodels = SCVAR("gl_smoothmodels","1"); cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0"); cvar_t gl_playermip = SCVAR("gl_playermip","0"); @@ -110,7 +88,6 @@ cvar_t gl_finish = SCVAR("gl_finish","0"); cvar_t gl_dither = SCVAR("gl_dither", "1"); cvar_t gl_maxdist = SCVAR("gl_maxdist", "8192"); -#pragma message("r_polygonoffset_submodel_offset: not implemented at the mo") cvar_t r_polygonoffset_submodel_factor = SCVAR("r_polygonoffset_submodel_factor", "0.05"); cvar_t r_polygonoffset_submodel_offset = SCVAR("r_polygonoffset_submodel_offset", "25"); @@ -134,6 +111,8 @@ cvar_t r_xflip = SCVAR("leftisright", "0"); extern cvar_t gl_ztrick; extern cvar_t scr_fov; +shader_t *scenepp_waterwarp; + // post processing stuff texid_t sceneblur_texture; texid_t scenepp_texture; @@ -162,6 +141,85 @@ int scenepp_panorama_parm_fov; // processing shaders void GL_InitSceneProcessingShaders_WaterWarp (void) { +#if 1 + /* + inputs: + texcoords: edge points + coords: vertex coords (duh) + time + ampscale (cvar = r_waterwarp) + + use ifs instead of an edge map? + */ + if (gl_config.arb_shader_objects) + { + scenepp_waterwarp = R_RegisterShader("waterwarp", + "{\n" + "glslprogram\n" + "{\n" + "#ifdef VERTEX_SHADER\n" + "\ + varying vec2 v_stc;\ + varying vec2 v_warp;\ + varying vec2 v_edge;\ + uniform float time;\ + void main (void)\ + {\ + gl_Position = ftransform();\ + v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;\ + v_warp.s = "/*FIXME: Multiply by screen matricies*/"time * 0.25 + gl_MultiTexCoord0.s;\ + v_warp.t = time * 0.25 + gl_MultiTexCoord0.t;\ + v_edge = gl_MultiTexCoord0.xy;\ + }\ + \n" + "#endif\n" + "#ifdef FRAGMENT_SHADER\n" + "\ + varying vec2 v_stc;\ + varying vec2 v_warp;\ + varying vec2 v_edge;\ + uniform sampler2D texScreen;\ + uniform sampler2D texWarp;\ + uniform sampler2D texEdge;\ + uniform float ampscale;\ + void main (void)\ + {\ + float amptemp;\ + vec3 edge;\ + edge = texture2D( texEdge, v_edge ).rgb;\ + amptemp = (0.010 / 0.625) * ampscale * edge.x;\ + vec3 offset;\ + offset = texture2D( texWarp, v_warp ).rgb;\ + offset.x = (offset.x - 0.5) * 2.0;\ + offset.y = (offset.y - 0.5) * 2.0;\ + vec2 temp;\ + temp.x = v_stc.x + offset.x * amptemp;\ + temp.y = v_stc.y + offset.y * amptemp;\ + gl_FragColor = texture2D( texScreen, temp );\ + }\ + \n" + "#endif\n" + "}\n" + "param cvarf r_waterwarp ampscale\n" + "param texture 0 texScreen\n" + "param texture 1 texWarp\n" + "param texture 2 texEdge\n" + "param time time\n" + "{\n" + "map $currentrender\n" + "}\n" + "{\n" + "map $upperoverlay\n" + "}\n" + "{\n" + "map $loweroverlay\n" + "}\n" + "}\n" + ); + scenepp_waterwarp->defaulttextures.upperoverlay = scenepp_texture_warp; + scenepp_waterwarp->defaulttextures.loweroverlay = scenepp_texture_edge; + } +#else char *genericvert = "\ varying vec2 v_texCoord0;\ varying vec2 v_texCoord1;\ @@ -224,6 +282,7 @@ void GL_InitSceneProcessingShaders_WaterWarp (void) if (qglGetError()) Con_Printf(CON_ERROR "GL Error initing shader object\n"); +#endif } void GL_InitFisheyeFov(void) @@ -508,7 +567,7 @@ void R_DrawSpriteModel (entity_t *e) unsigned int fl; unsigned int sprtype; - static vec2_t texcoords[4]={{0, 1},{0,0},{1,0},{1,1}}; + static vec2_t texcoords[4]={{0, 0},{0,1},{1,1},{1,0}}; static index_t indexes[6] = {0, 1, 2, 0, 2, 3}; vecV_t vertcoords[4]; avec4_t colours[4]; @@ -622,7 +681,7 @@ void R_DrawSpriteModel (entity_t *e) mesh.numvertexes = 4; mesh.st_array = texcoords; mesh.istrifan = true; - BE_DrawMeshChain(frame->shader, &mesh, NULL, &frame->shader->defaulttextures); + BE_DrawMesh_Single(frame->shader, &mesh, NULL, &frame->shader->defaulttextures); } //================================================================================== @@ -651,7 +710,7 @@ void R_DrawLightning(entity_t *e) vecV_t points[4]; vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; - index_t indexarray[6] = {0, 1, 2, 0, 2, 3}; + static index_t indexarray[6] = {0, 1, 2, 0, 2, 3}; mesh_t mesh; @@ -694,7 +753,7 @@ void R_DrawLightning(entity_t *e) mesh.normals_array = NULL; mesh.numvertexes = 4; mesh.st_array = texcoords; - BE_DrawMeshChain(e->forcedshader, &mesh, NULL, NULL); + BE_DrawMesh_Single(e->forcedshader, &mesh, NULL, NULL); } //q3 railgun beam void R_DrawRailCore(entity_t *e) @@ -707,7 +766,7 @@ void R_DrawRailCore(entity_t *e) mesh_t mesh; vecV_t points[4]; vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; - index_t indexarray[6] = {0, 1, 2, 0, 2, 3}; + static index_t indexarray[6] = {0, 1, 2, 0, 2, 3}; vec4_t colors[4]; if (!e->forcedshader) @@ -755,10 +814,105 @@ void R_DrawRailCore(entity_t *e) mesh.numvertexes = 4; mesh.st_array = texcoords; - BE_DrawMeshChain(e->forcedshader, &mesh, NULL, NULL); + BE_DrawMesh_Single(e->forcedshader, &mesh, NULL, NULL); } #endif +/*quick test: map bunk1 ware1 */ +void R_DrawBeam(entity_t *e) +{ + float r, g, b; + + vec3_t dir, v, cr; + vecV_t points[4]; + float length, scale; + static byte_vec4_t colours[4]; + static vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; + static index_t indexarray[6] = {0, 1, 2, 0, 2, 3}; + mesh_t mesh; + +shader_t *beamshader; + beamshader = R_RegisterShader("q2beam", + "{\n" + "{\n" + "map $whiteimage\n" + "rgbgen vertex\n" + "alphagen vertex\n" + "blendfunc blend\n" + "}\n" + "}\n" + ); + + VectorSubtract(e->origin, e->oldorigin, dir); + length = Length(dir); + + scale = e->scale; + if (!scale) + scale = 1; + scale *= e->framestate.g[FS_REG].frame[0]; + if (!scale) + scale = 6; + + scale/= 2; + + VectorSubtract(r_refdef.vieworg, e->origin, v); + CrossProduct(v, dir, cr); + VectorNormalize(cr); + VectorMA(e->origin, scale, cr, points[0]); + VectorMA(e->origin, -scale, cr, points[1]); + + VectorSubtract(r_refdef.vieworg, e->oldorigin, v); + CrossProduct(v, dir, cr); + VectorNormalize(cr); + VectorMA(e->oldorigin, -scale, cr, points[2]); + VectorMA(e->oldorigin, scale, cr, points[3]); + + r = ( d_8to24rgbtable[e->skinnum & 0xFF] ) & 0xFF; + g = ( d_8to24rgbtable[e->skinnum & 0xFF] >> 8 ) & 0xFF; + b = ( d_8to24rgbtable[e->skinnum & 0xFF] >> 16 ) & 0xFF; + + r *= e->shaderRGBAf[0]; + g *= e->shaderRGBAf[1]; + b *= e->shaderRGBAf[2]; + + colours[0][0] = r; + colours[0][1] = g; + colours[0][2] = b; + colours[0][3] = 255*0.666; + *(int*)colours[1] = *(int*)colours[0]; + *(int*)colours[2] = *(int*)colours[0]; + *(int*)colours[3] = *(int*)colours[0]; + + memset(&mesh, 0, sizeof(mesh)); + mesh.vbofirstelement = 0; + mesh.vbofirstvert = 0; + mesh.xyz_array = points; + mesh.indexes = indexarray; + mesh.numindexes = sizeof(indexarray)/sizeof(indexarray[0]); + mesh.colors4b_array = colours; + mesh.lmst_array = NULL; + mesh.normals_array = NULL; + mesh.numvertexes = sizeof(points)/sizeof(points[0]); + mesh.st_array = texcoords; + BE_DrawMesh_Single(beamshader, &mesh, NULL, &beamshader->defaulttextures); +} + +/* +============= +R_ShouldDraw +Ents are added to the list regardless. +This is where they're filtered (based on which view is currently being drawn). +============= +*/ +qboolean R_ShouldDraw(entity_t *e) +{ + if (e->flags & Q2RF_EXTERNALMODEL && !r_refdef.externalview) + return false; + if (!Cam_DrawPlayer(r_refdef.currentplayernum, e->keynum-1)) + return false; + return true; +} + /* ============= R_DrawEntitiesOnList @@ -776,7 +930,7 @@ void GLR_DrawEntitiesOnList (void) { currententity = &cl_visedicts[i]; - if (!PPL_ShouldDraw()) + if (!R_ShouldDraw(currententity)) continue; @@ -863,119 +1017,6 @@ void GLR_DrawEntitiesOnList (void) } } -/* -=============== -R_SetupFrame -=============== -*/ -static void GLR_SetupFrame (void) -{ -// don't allow cheats in multiplayer - r_wateralphaval = r_wateralpha.value; - if (!cls.allow_watervis) - r_wateralphaval = 1; - - if (!mirror) - { - R_AnimateLight (); - - // build the transformation matrix for the given view angles - - AngleVectors (r_refdef.viewangles, vpn, vright, vup); - - r_framecount++; - } - VectorCopy (r_refdef.vieworg, r_origin); - -// current viewleaf - if (r_refdef.flags & Q2RDF_NOWORLDMODEL) - { - } -#ifdef Q2BSPS - else if (cl.worldmodel && (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)) - { - static mleaf_t fakeleaf; - mleaf_t *leaf; - - r_viewleaf = &fakeleaf; //so we can use quake1 rendering routines for q2 bsps. - r_viewleaf->contents = Q1CONTENTS_EMPTY; - r_viewleaf2 = NULL; - - r_oldviewcluster = r_viewcluster; - r_oldviewcluster2 = r_viewcluster2; - leaf = RMod_PointInLeaf (cl.worldmodel, r_origin); - r_viewcluster = r_viewcluster2 = leaf->cluster; - - // check above and below so crossing solid water doesn't draw wrong - if (!leaf->contents) - { // look down a bit - vec3_t temp; - - VectorCopy (r_origin, temp); - temp[2] -= 16; - leaf = RMod_PointInLeaf (cl.worldmodel, temp); - if ( !(leaf->contents & Q2CONTENTS_SOLID) && - (leaf->cluster != r_viewcluster2) ) - r_viewcluster2 = leaf->cluster; - } - else - { // look up a bit - vec3_t temp; - - VectorCopy (r_origin, temp); - temp[2] += 16; - leaf = RMod_PointInLeaf (cl.worldmodel, temp); - if ( !(leaf->contents & Q2CONTENTS_SOLID) && - (leaf->cluster != r_viewcluster2) ) - r_viewcluster2 = leaf->cluster; - } - } -#endif - else - { - mleaf_t *leaf; - vec3_t temp; - - r_oldviewleaf = r_viewleaf; - r_oldviewleaf2 = r_viewleaf2; - r_viewleaf = RMod_PointInLeaf (cl.worldmodel, r_origin); - - if (!r_viewleaf) - { - } - else if (r_viewleaf->contents == Q1CONTENTS_EMPTY) - { //look down a bit - VectorCopy (r_origin, temp); - temp[2] -= 16; - leaf = RMod_PointInLeaf (cl.worldmodel, temp); - if (leaf->contents <= Q1CONTENTS_WATER && leaf->contents >= Q1CONTENTS_LAVA) - r_viewleaf2 = leaf; - else - r_viewleaf2 = NULL; - } - else if (r_viewleaf->contents <= Q1CONTENTS_WATER && r_viewleaf->contents >= Q1CONTENTS_LAVA) - { //in water, look up a bit. - - VectorCopy (r_origin, temp); - temp[2] += 16; - leaf = RMod_PointInLeaf (cl.worldmodel, temp); - if (leaf->contents == Q1CONTENTS_EMPTY) - r_viewleaf2 = leaf; - else - r_viewleaf2 = NULL; - } - else - r_viewleaf2 = NULL; - - if (r_viewleaf) - V_SetContentsColor (r_viewleaf->contents); - } - - c_brush_polys = 0; - c_alias_polys = 0; - -} - /* ============= R_SetupGL @@ -988,93 +1029,89 @@ void R_SetupGL (void) float fov_x, fov_y; - AngleVectors (r_refdef.viewangles, vpn, vright, vup); - VectorCopy (r_refdef.vieworg, r_origin); - - // - // set up viewpoint - // - x = r_refdef.vrect.x * vid.pixelwidth/(int)vid.width; - x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * vid.pixelwidth/(int)vid.width; - y = (vid.height-r_refdef.vrect.y) * vid.pixelheight/(int)vid.height; - y2 = ((int)vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * vid.pixelheight/(int)vid.height; - - // fudge around because of frac screen scale - if (x > 0) - x--; - if (x2 < vid.pixelwidth) - x2++; - if (y2 < 0) - y2--; - if (y < vid.pixelheight) - y++; - - w = x2 - x; - h = y - y2; - - if (envmap) + if (!r_refdef.recurse) { - x = y2 = 0; - w = h = 256; + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + VectorCopy (r_refdef.vieworg, r_origin); + + // + // set up viewpoint + // + x = r_refdef.vrect.x * vid.pixelwidth/(int)vid.width; + x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * vid.pixelwidth/(int)vid.width; + y = (vid.height-r_refdef.vrect.y) * vid.pixelheight/(int)vid.height; + y2 = ((int)vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * vid.pixelheight/(int)vid.height; + + // fudge around because of frac screen scale + if (x > 0) + x--; + if (x2 < vid.pixelwidth) + x2++; + if (y2 < 0) + y2--; + if (y < vid.pixelheight) + y++; + + w = x2 - x; + h = y - y2; + + r_refdef.pxrect.x = x; + r_refdef.pxrect.y = y; + r_refdef.pxrect.width = w; + r_refdef.pxrect.height = h; + + qglViewport (x, y2, w, h); + + fov_x = r_refdef.fov_x;//+sin(cl.time)*5; + fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5; + + if (r_waterwarp.value<0 && r_viewleaf && r_viewleaf->contents <= Q1CONTENTS_WATER) + { + fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); + fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); + } + + screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; + if (r_refdef.useperspective) + { + int stencilshadows = 0; + #ifdef RTLIGHTS + stencilshadows |= r_shadow_realtime_dlight.ival && r_shadow_realtime_dlight_shadows.ival; + stencilshadows |= r_shadow_realtime_world.ival && r_shadow_realtime_world_shadows.ival; + #endif + + if ((!stencilshadows || !gl_canstencil) && gl_maxdist.value>=100)//gl_nv_range_clamp) + { + // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; + // yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect; + // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI; + // MYgluPerspective (yfov, screenaspect, 4, 4096); + + Matrix4_Projection_Far(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value, gl_maxdist.value); + } + else + { + Matrix4_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value); + } + } + else + { + if (gl_maxdist.value>=1) + Matrix4_Orthographic(r_refdef.m_projection, -fov_x/2, fov_x/2, fov_y/2, -fov_y/2, -gl_maxdist.value, gl_maxdist.value); + else + Matrix4_Orthographic(r_refdef.m_projection, 0, r_refdef.vrect.width, 0, r_refdef.vrect.height, -9999, 9999); + } + + Matrix4_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg); } - gl_truescreenrect.x = x; - gl_truescreenrect.y = y; - gl_truescreenrect.width = w; - gl_truescreenrect.height = h; - - qglViewport (x, y2, w, h); - qglMatrixMode(GL_PROJECTION); - - fov_x = r_refdef.fov_x;//+sin(cl.time)*5; - fov_y = r_refdef.fov_y;//-sin(cl.time+1)*5; - - if (r_waterwarp.value<0 && r_viewleaf && r_viewleaf->contents <= Q1CONTENTS_WATER) - { - fov_x *= 1 + (((sin(cl.time * 4.7) + 1) * 0.015) * r_waterwarp.value); - fov_y *= 1 + (((sin(cl.time * 3.0) + 1) * 0.015) * r_waterwarp.value); - } - - screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; - if (r_refdef.useperspective) - { - int stencilshadows = 0; -#ifdef RTLIGHTS - stencilshadows |= r_shadow_realtime_dlight.value && r_shadow_realtime_dlight_shadows.value; - stencilshadows |= r_shadow_realtime_world.value && r_shadow_realtime_world_shadows.value; -#endif - - if ((!stencilshadows || !gl_canstencil) && gl_maxdist.value>=100)//gl_nv_range_clamp) - { - // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; - // yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect; - // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI; - // MYgluPerspective (yfov, screenaspect, 4, 4096); - - Matrix4_Projection_Far(r_projection_matrix, fov_x, fov_y, gl_mindist.value, gl_maxdist.value); - } - else - { - Matrix4_Projection_Inf(r_projection_matrix, fov_x, fov_y, gl_mindist.value); - } - } - else - { - if (gl_maxdist.value>=1) - GL_ParallelPerspective(-fov_x/2, fov_x/2, fov_y/2, -fov_y/2, -gl_maxdist.value, gl_maxdist.value); - else - GL_ParallelPerspective(0, r_refdef.vrect.width, 0, r_refdef.vrect.height, -9999, 9999); - } - qglLoadMatrixf(r_projection_matrix); + qglLoadMatrixf(r_refdef.m_projection); qglMatrixMode(GL_MODELVIEW); + qglLoadMatrixf(r_refdef.m_view); - - Matrix4_ModelViewMatrixFromAxis(r_view_matrix, vpn, vright, vup, r_refdef.vieworg); - qglLoadMatrixf(r_view_matrix); - - if (gl_dither.value) + if (gl_dither.ival) { qglEnable(GL_DITHER); } @@ -1098,16 +1135,11 @@ void R_RenderScene (void) if (!cl.worldmodel || (!cl.worldmodel->nodes && cl.worldmodel->type != mod_heightmap)) r_refdef.flags |= Q2RDF_NOWORLDMODEL; -#ifdef RTLIGHTS - if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) - Sh_GenShadowMaps(); -#endif - TRACE(("dbg: calling R_SetupGL\n")); R_SetupGL (); TRACE(("dbg: calling R_SetFrustrum\n")); - R_SetFrustum (r_projection_matrix, r_view_matrix); + R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { @@ -1122,6 +1154,8 @@ void R_RenderScene (void) S_ExtraUpdate (); // don't let sound get messed up if going slow + RQ_BeginFrame(); + TRACE(("dbg: calling GLR_DrawEntitiesOnList\n")); GLR_DrawEntitiesOnList (); @@ -1137,6 +1171,247 @@ void R_RenderScene (void) } RQ_RenderBatchClear(); } +/*generates a new modelview matrix, as well as vpn vectors*/ +static void R_MirrorMatrix(plane_t *plane) +{ + float mirror[16]; + float view[16]; + float result[16]; + + vec3_t pnorm; + VectorNegate(plane->normal, pnorm); + + mirror[0] = 1-2*pnorm[0]*pnorm[0]; + mirror[1] = -2*pnorm[0]*pnorm[1]; + mirror[2] = -2*pnorm[0]*pnorm[2]; + mirror[3] = 0; + + mirror[4] = -2*pnorm[1]*pnorm[0]; + mirror[5] = 1-2*pnorm[1]*pnorm[1]; + mirror[6] = -2*pnorm[1]*pnorm[2] ; + mirror[7] = 0; + + mirror[8] = -2*pnorm[2]*pnorm[0]; + mirror[9] = -2*pnorm[2]*pnorm[1]; + mirror[10] = 1-2*pnorm[2]*pnorm[2]; + mirror[11] = 0; + + mirror[12] = -2*pnorm[0]*plane->dist; + mirror[13] = -2*pnorm[1]*plane->dist; + mirror[14] = -2*pnorm[2]*plane->dist; + mirror[15] = 1; + + view[0] = vpn[0]; + view[1] = vpn[1]; + view[2] = vpn[2]; + view[3] = 0; + + view[4] = -vright[0]; + view[5] = -vright[1]; + view[6] = -vright[2]; + view[7] = 0; + + view[8] = vup[0]; + view[9] = vup[1]; + view[10] = vup[2]; + view[11] = 0; + + view[12] = r_refdef.vieworg[0]; + view[13] = r_refdef.vieworg[1]; + view[14] = r_refdef.vieworg[2]; + view[15] = 1; + + VectorMA(r_refdef.vieworg, 0.25, plane->normal, r_refdef.pvsorigin); + + Matrix4_Multiply(mirror, view, result); + + vpn[0] = result[0]; + vpn[1] = result[1]; + vpn[2] = result[2]; + + vright[0] = -result[4]; + vright[1] = -result[5]; + vright[2] = -result[6]; + + vup[0] = result[8]; + vup[1] = result[9]; + vup[2] = result[10]; + + r_refdef.vieworg[0] = result[12]; + r_refdef.vieworg[1] = result[13]; + r_refdef.vieworg[2] = result[14]; +} +static entity_t *R_NearestPortal(plane_t *plane) +{ + int i; + entity_t *best = NULL; + float dist, bestd = 0; + for (i = 0; i < cl_numvisedicts; i++) + { + if (cl_visedicts[i].rtype == RT_PORTALSURFACE) + { + dist = DotProduct(cl_visedicts[i].origin, plane->normal)-plane->dist; + dist = fabs(dist); + if (dist < 64 && (!best || dist < bestd)) + best = &cl_visedicts[i]; + } + } + return best; +} + +static void TransformCoord(vec3_t in, vec3_t planea[3], vec3_t planeo, vec3_t viewa[3], vec3_t viewo, vec3_t result) +{ + int i; + vec3_t local; + vec3_t transformed; + float d; + + local[0] = in[0] - planeo[0]; + local[1] = in[1] - planeo[1]; + local[2] = in[2] - planeo[2]; + + VectorClear(transformed); + for ( i = 0 ; i < 3 ; i++ ) + { + d = DotProduct(local, planea[i]); + VectorMA(transformed, d, viewa[i], transformed); + } + + result[0] = transformed[0] + viewo[0]; + result[1] = transformed[1] + viewo[1]; + result[2] = transformed[2] + viewo[2]; +} +static void TransformDir(vec3_t in, vec3_t planea[3], vec3_t viewa[3], vec3_t result) +{ + int i; + float d; + vec3_t tmp; + + VectorCopy(in, tmp); + + VectorClear(result); + for ( i = 0 ; i < 3 ; i++ ) + { + d = DotProduct(tmp, planea[i]); + VectorMA(result, d, viewa[i], result); + } +} +void R_DrawPortal(batch_t *batch) +{ + entity_t *view; + GLdouble glplane[4]; + plane_t plane; + refdef_t oldrefdef; + mesh_t *mesh = batch->mesh[batch->firstmesh]; + + if (r_refdef.recurse) + return; + + VectorCopy(mesh->normals_array[0], plane.normal); + plane.dist = DotProduct(mesh->xyz_array[0], plane.normal); + + //if we're too far away from the surface, don't draw anything + if (batch->shader->flags & SHADER_AGEN_PORTAL) + { + /*there's a portal alpha blend on that surface, that fades out after this distance*/ + if (DotProduct(r_refdef.vieworg, plane.normal)-plane.dist > batch->shader->portaldist) + return; + } + //if we're behind it, then also don't draw anything. + if (DotProduct(r_refdef.vieworg, plane.normal)-plane.dist < 0) + return; + + view = R_NearestPortal(&plane); + //if (!view) + // return; + + oldrefdef = r_refdef; + r_refdef.recurse = true; + + r_refdef.externalview = true; + + if (!view || VectorCompare(view->origin, view->oldorigin)) + { + r_refdef.flipcull ^= true; + R_MirrorMatrix(&plane); + } + else + { + float d; + vec3_t paxis[3], porigin, vaxis[3], vorg; + void PerpendicularVector( vec3_t dst, const vec3_t src ); + + /*calculate where the surface is meant to be*/ + VectorCopy(mesh->normals_array[0], paxis[0]); + PerpendicularVector(paxis[1], paxis[1]); + CrossProduct(paxis[0], paxis[1], paxis[2]); + d = DotProduct(view->origin, plane.normal) - plane.dist; + VectorMA(view->origin, -d, paxis[0], porigin); + + /*grab the camera origin*/ + VectorNegate(view->axis[0], vaxis[0]); + VectorNegate(view->axis[1], vaxis[1]); + VectorCopy(view->axis[2], vaxis[2]); + VectorCopy(view->oldorigin, vorg); + + VectorCopy(vorg, r_refdef.pvsorigin); + + /*rotate it a bit*/ + RotatePointAroundVector(vaxis[1], vaxis[0], view->axis[1], sin(realtime)*4); + CrossProduct(vaxis[0], vaxis[1], vaxis[2]); + + TransformCoord(oldrefdef.vieworg, paxis, porigin, vaxis, vorg, r_refdef.vieworg); + TransformDir(vpn, paxis, vaxis, vpn); + TransformDir(vright, paxis, vaxis, vright); + TransformDir(vup, paxis, vaxis, vup); + } + Matrix4_ModelViewMatrixFromAxis(r_refdef.m_view, vpn, vright, vup, r_refdef.vieworg); + VectorAngles(vpn, vup, r_refdef.viewangles); + VectorCopy(r_refdef.vieworg, r_origin); + +/*FIXME: the batch stuff should be done in renderscene*/ + + /*fixup the first mesh index*/ + for (batch = cl.worldmodel->batches; batch; batch = batch->next) + { + batch->firstmesh = batch->meshes; + } + + GL_CullFace(0); + + /*FIXME: can we get away with stenciling the screen?*/ + /*Add to frustum culling instead of clip planes?*/ + glplane[0] = -plane.normal[0]; + glplane[1] = -plane.normal[1]; + glplane[2] = -plane.normal[2]; + glplane[3] = plane.dist; + qglClipPlane(GL_CLIP_PLANE0, glplane); + qglEnable(GL_CLIP_PLANE0); + R_RenderScene(); + qglDisable(GL_CLIP_PLANE0); + + for (batch = cl.worldmodel->batches; batch; batch = batch->next) + { + batch->firstmesh = 0; + } + r_refdef = oldrefdef; + + /*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); + + /*put GL back the way it was*/ + qglMatrixMode(GL_PROJECTION); + qglLoadMatrixf(r_refdef.m_projection); + + qglMatrixMode(GL_MODELVIEW); + qglLoadMatrixf(r_refdef.m_view); + + GL_CullFace(0); + +#pragma message("warning: there's a bug with rtlights in portals, culling is broken or something. May also be loading the wrong matrix") +} /* @@ -1149,20 +1424,10 @@ void R_Clear (void) { /*tbh, this entire function should be in the backend*/ GL_ForceDepthWritable(); - if (r_mirroralpha.value != 1.0) - { - if (gl_clear.value && !r_secondaryview) - qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - qglClear (GL_DEPTH_BUFFER_BIT); - gldepthmin = 0; - gldepthmax = 0.5; - gldepthfunc=GL_LEQUAL; - } #ifdef SIDEVIEWS - else if (gl_ztrick.value && !gl_ztrickdisabled) + if (gl_ztrick.value && !gl_ztrickdisabled) #else - else if (gl_ztrick.value) + if (gl_ztrick.value) #endif { static int trickframe; @@ -1197,265 +1462,6 @@ void R_Clear (void) qglDepthRange (gldepthmin, gldepthmax); } -void R_Mirror (void) -{ - msurface_t *s, *prevs, *prevr, *rejects; -// entity_t *ent; - mplane_t *mirror_plane; - - vec3_t oldangles, oldorg, oldvpn, oldvright, oldvup; //cache - for rear view mirror and stuff. - float base_view_matrix[16]; - - if (!mirror) - { - r_inmirror = false; - return; - } - -#pragma message("backend fixme") - Con_Printf("mirrors are not updated for the backend\n"); - - r_inmirror = true; - - memcpy(oldangles, r_refdef.viewangles, sizeof(vec3_t)); - memcpy(oldorg, r_refdef.vieworg, sizeof(vec3_t)); - memcpy(oldvpn, vpn, sizeof(vec3_t)); - memcpy(oldvright, vright, sizeof(vec3_t)); - memcpy(oldvup, vup, sizeof(vec3_t)); - memcpy (base_view_matrix, r_view_matrix, sizeof(base_view_matrix)); - - s = r_mirror_chain; - while(s) //okay, so this is a hack - { - s->nextalphasurface = s->texturechain; - s = s->nextalphasurface; - } - cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL; - - while(r_mirror_chain) - { - s = r_mirror_chain; - r_mirror_chain = r_mirror_chain->nextalphasurface; -#if 0 - s->nextalphasurface = NULL; - -#else - //this loop figures out all surfaces with the same plane. - //yes, this can mean that the list is reversed a few times, but we do have depth testing to solve that anyway. - for(prevs = s,prevr=NULL,rejects=NULL;r_mirror_chain;r_mirror_chain=r_mirror_chain->nextalphasurface) - { - if (s->plane->dist != r_mirror_chain->plane->dist || s->plane->signbits != r_mirror_chain->plane->signbits - || s->plane->normal[0] != r_mirror_chain->plane->normal[0] || s->plane->normal[1] != r_mirror_chain->plane->normal[1] || s->plane->normal[2] != r_mirror_chain->plane->normal[2]) - { //reject - if (prevr) - prevr->nextalphasurface = r_mirror_chain; - else - rejects = r_mirror_chain; - prevr = r_mirror_chain; - } - else - { //matches - prevs->nextalphasurface = r_mirror_chain; - prevs = r_mirror_chain; - } - } - prevs->nextalphasurface = NULL; - if (prevr) - prevr->nextalphasurface = NULL; - - r_mirror_chain = rejects; -#endif - mirror_plane = s->plane; - - //enable stencil writing - qglClearStencil(0); - qglClear(GL_STENCIL_BUFFER_BIT); - qglDisable(GL_ALPHA_TEST); - qglDisable(GL_STENCIL_TEST); - qglEnable(GL_STENCIL_TEST); - qglStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); //replace where it passes - qglStencilFunc( GL_ALWAYS, 1, ~0 ); //always pass (where z passes set to 1) - qglDisable(GL_TEXTURE_2D); - qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); - qglDepthMask( GL_FALSE ); - - qglEnableClientState( GL_VERTEX_ARRAY ); - for (prevs = s; s; s=s->nextalphasurface) //write the polys to the stencil buffer. - { - qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), s->mesh->xyz_array); - qglDrawElements(GL_TRIANGLES, s->mesh->numindexes, GL_INDEX_TYPE, s->mesh->indexes); - } - - - qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - qglStencilFunc( GL_EQUAL, 1, ~0 ); //pass if equal to 1 - -//now clear the depth buffer where the stencil passed -//we achieve this by changing the projection matrix underneath. -//the stencil only shows where the final surface will appear, and only where not obscured -//we rewrite the depth with the blending pass after. - qglEnable(GL_DEPTH_TEST); //use only the stencil test - qglDepthRange(1, 1); - qglDepthFunc (GL_ALWAYS); - qglDepthMask( GL_TRUE ); - qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); - - qglMatrixMode(GL_PROJECTION); - qglLoadIdentity(); - qglOrtho (0, 1, 1, 0, -99999, 99999); - qglMatrixMode(GL_MODELVIEW); - qglLoadIdentity (); - - qglBegin(GL_QUADS); - qglVertex3f(0, 0, -99999); - qglVertex3f(1, 0, -99999); - qglVertex3f(1, 1, -99999); - qglVertex3f(0, 1, -99999); - qglEnd(); - - qglEnable(GL_DEPTH_TEST); //use only the stencil test - qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); -/* -Thus the final mirror matrix for any given plane p*+k=0 is: - -| 1-2*nx*nx -2*nx*ny -2*nx*nz -2*nx*k | - -| -2*ny*nx 1-2*ny*ny -2*ny*nz -2*ny*k | - -| -2*nz*nx -2*nz*ny 1-2*nz*nz -2*nz*k | - -| 0 0 0 1 | -*/ - { - float mirror[16]; - float view[16]; - float result[16]; - float nx = mirror_plane->normal[0]; - float ny = mirror_plane->normal[1]; - float nz = mirror_plane->normal[2]; - float k = -mirror_plane->dist; - - mirror[0] = 1-2*nx*nx; - mirror[1] = -2*nx*ny; - mirror[2] = -2*nx*nz; - mirror[3] = 0; - - mirror[4] = -2*ny*nx; - mirror[5] = 1-2*ny*ny; - mirror[6] = -2*ny*nz; - mirror[7] = 0; - - mirror[8] = -2*nz*nx; - mirror[9] = -2*nz*ny; - mirror[10] = 1-2*nz*nz; - mirror[11] = 0; - - mirror[12] = -2*nx*k; - mirror[13] = -2*ny*k; - mirror[14] = -2*nz*k; - mirror[15] = 1; - - view[0] = oldvpn[0]; - view[1] = oldvpn[1]; - view[2] = oldvpn[2]; - view[3] = 0; - - view[4] = -oldvright[0]; - view[5] = -oldvright[1]; - view[6] = -oldvright[2]; - view[7] = 0; - - view[8] = oldvup[0]; - view[9] = oldvup[1]; - view[10] = oldvup[2]; - view[11] = 0; - - view[12] = oldorg[0]; - view[13] = oldorg[1]; - view[14] = oldorg[2]; - view[15] = 1; - - Matrix4_Multiply(mirror, view, result); - - vpn[0] = result[0]; - vpn[1] = result[1]; - vpn[2] = result[2]; - - vright[0] = -result[4]; - vright[1] = -result[5]; - vright[2] = -result[6]; - - vup[0] = result[8]; - vup[1] = result[9]; - vup[2] = result[10]; - - r_refdef.vieworg[0] = result[12]; - r_refdef.vieworg[1] = result[13]; - r_refdef.vieworg[2] = result[14]; - } - - r_refdef.viewangles[0] = 0; - r_refdef.viewangles[1] = 0; - r_refdef.viewangles[2] = 0; - - - gldepthmin = 0.5; - gldepthmax = 1; - qglDepthRange (gldepthmin, gldepthmax); - qglDepthFunc (gldepthfunc); - - R_RenderScene (); - -// GLR_DrawWaterSurfaces (); - - - gldepthmin = 0; - gldepthmax = 0.5; - qglDepthRange (gldepthmin, gldepthmax); - qglDepthFunc (gldepthfunc); - - - memcpy(r_refdef.viewangles, oldangles, sizeof(vec3_t)); - memcpy(r_refdef.vieworg, oldorg, sizeof(vec3_t)); - - qglCullFace(GL_FRONT); - qglMatrixMode(GL_MODELVIEW); - - qglLoadMatrixf (base_view_matrix); - - qglDisable(GL_STENCIL_TEST); - - // blend on top - qglDisable(GL_ALPHA_TEST); - qglEnable (GL_BLEND); - qglEnable(GL_TEXTURE_2D); - qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - qglColor4f (1,1,1,r_mirroralpha.value); -qglDisable(GL_STENCIL_TEST); -qglPolygonOffset(1, 0); -qglEnable(GL_POLYGON_OFFSET_FILL); - for (s=prevs ; s ; s=s->nextalphasurface) - { - qglEnable (GL_BLEND); - //R_RenderBrushPoly (s); - } -qglDisable(GL_POLYGON_OFFSET_FILL); -qglPolygonOffset(0, 0); - qglEnable(GL_TEXTURE_2D); - qglDisable (GL_BLEND); - qglColor4f (1,1,1,1); - } - qglDisable(GL_STENCIL_TEST); - - memcpy(r_refdef.viewangles, oldangles, sizeof(vec3_t)); - memcpy(r_refdef.vieworg, oldorg, sizeof(vec3_t)); - - AngleVectors (r_refdef.viewangles, vpn, vright, vup); - - r_inmirror = false; -} -//#endif - #if 0 void GLR_SetupFog (void) { @@ -1845,8 +1851,6 @@ qboolean R_RenderScene_Fish(void) ang[5][0] = -saveang[0]*2; for (i = 0; i < numsides; i++) { - mirror = false; - r_refdef.fov_x = 90; r_refdef.fov_y = 90; r_refdef.viewangles[0] = saveang[0]+ang[order[i]][0]; @@ -1862,9 +1866,6 @@ qboolean R_RenderScene_Fish(void) // render normal view R_RenderScene (); - // render mirror view - R_Mirror (); - qglDisable(GL_TEXTURE_2D); qglEnable(GL_TEXTURE_CUBE_MAP_ARB); GL_BindType(GL_TEXTURE_CUBE_MAP_ARB, scenepp_fisheye_texture); @@ -1997,8 +1998,6 @@ void GLR_RenderView (void) else #endif { - mirror = false; - GL_SetShaderState2D(false); R_Clear (); @@ -2007,12 +2006,10 @@ void GLR_RenderView (void) // render normal view R_RenderScene (); - - // render mirror view - R_Mirror (); } - R_BloomBlend(); + if (r_bloom.ival) + R_BloomBlend(); // qglDisable(GL_FOG); @@ -2036,9 +2033,14 @@ void GLR_RenderView (void) // SCENE POST PROCESSING // we check if we need to use any shaders - currently it's just waterwarp - if (scenepp_ww_program) if ((r_waterwarp.value>0 && r_viewleaf && r_viewleaf->contents <= Q1CONTENTS_WATER)) - R_RenderWaterWarp(); + { + GL_Set2D(); + if (scenepp_waterwarp) + R2D_ScalePic(0, 0, vid.width, vid.height, scenepp_waterwarp); + else if (scenepp_ww_program) + R_RenderWaterWarp(); + } diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 65c26b72..c2713a67 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -67,74 +67,6 @@ void GLR_InitTextures (void) } }*/ -/* -=============== -R_Envmap_f - -Grab six views for environment mapping tests -=============== -*/ -void R_Envmap_f (void) -{ - qbyte buffer[256*256*4]; - - qglDrawBuffer (GL_FRONT); - qglReadBuffer (GL_FRONT); - envmap = true; - - r_refdef.vrect.x = 0; - r_refdef.vrect.y = 0; - r_refdef.vrect.width = 256; - r_refdef.vrect.height = 256; - - r_refdef.viewangles[0] = 0; - r_refdef.viewangles[1] = 0; - r_refdef.viewangles[2] = 0; - GL_BeginRendering (); - R_RenderView (); - qglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env0.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[1] = 90; - GL_BeginRendering (); - R_RenderView (); - qglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env1.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[1] = 180; - GL_BeginRendering (); - R_RenderView (); - qglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env2.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[1] = 270; - GL_BeginRendering (); - R_RenderView (); - qglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env3.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[0] = -90; - r_refdef.viewangles[1] = 0; - GL_BeginRendering (); - R_RenderView (); - qglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env4.rgb", buffer, sizeof(buffer)); - - r_refdef.viewangles[0] = 90; - r_refdef.viewangles[1] = 0; - GL_BeginRendering (); - R_RenderView (); - qglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - COM_WriteFile ("env5.rgb", buffer, sizeof(buffer)); - - envmap = false; - qglDrawBuffer (GL_BACK); - qglReadBuffer (GL_BACK); - GL_EndRendering (); - GL_DoSwap(); -} - - @@ -522,7 +454,7 @@ extern cvar_t gl_bump, v_contrast, r_drawflat; extern cvar_t r_stains, r_stainfadetime, r_stainfadeammount; // callback defines -extern cvar_t gl_conback, gl_font, gl_smoothfont, gl_fontinwardstep, r_menutint; +extern cvar_t gl_font, r_menutint; extern cvar_t vid_conautoscale, vid_conheight, vid_conwidth; extern cvar_t crosshair, crosshairimage, crosshaircolor, r_skyboxname; extern cvar_t r_floorcolour, r_wallcolour, r_floortexture, r_walltexture; @@ -531,10 +463,6 @@ void GLCrosshairimage_Callback(struct cvar_s *var, char *oldvalue); void GLCrosshair_Callback(struct cvar_s *var, char *oldvalue); void GLCrosshaircolor_Callback(struct cvar_s *var, char *oldvalue); void GLR_Menutint_Callback (struct cvar_s *var, char *oldvalue); -void GL_Conback_Callback (struct cvar_s *var, char *oldvalue); -void GL_Font_Callback (struct cvar_s *var, char *oldvalue); -void GL_Smoothfont_Callback (struct cvar_s *var, char *oldvalue); -void GL_Fontinwardstep_Callback (struct cvar_s *var, char *oldvalue); void GLVID_Conwidth_Callback(struct cvar_s *var, char *oldvalue); void GLVID_Conautoscale_Callback(struct cvar_s *var, char *oldvalue); void GLVID_Conheight_Callback(struct cvar_s *var, char *oldvalue); @@ -554,10 +482,7 @@ void GLR_DeInit (void) Cvar_Unhook(&crosshaircolor); Cvar_Unhook(&r_skyboxname); Cvar_Unhook(&r_menutint); - Cvar_Unhook(&gl_conback); Cvar_Unhook(&gl_font); - Cvar_Unhook(&gl_smoothfont); - Cvar_Unhook(&gl_fontinwardstep); Cvar_Unhook(&vid_conautoscale); Cvar_Unhook(&vid_conheight); Cvar_Unhook(&vid_conwidth); @@ -578,7 +503,6 @@ void GLR_DeInit (void) void GLR_Init (void) { Cmd_AddRemCommand ("timerefresh", GLR_TimeRefresh_f); - Cmd_AddRemCommand ("envmap", R_Envmap_f); #ifdef RTLIGHTS Cmd_AddRemCommand ("r_editlights_reload", R_ReloadRTLights_f); Cmd_AddRemCommand ("r_editlights_save", R_SaveRTLights_f); @@ -590,11 +514,6 @@ void GLR_Init (void) Cvar_Hook(&crosshairimage, GLCrosshairimage_Callback); Cvar_Hook(&crosshaircolor, GLCrosshaircolor_Callback); Cvar_Hook(&r_menutint, GLR_Menutint_Callback); - Cvar_ForceCallback(&gl_conback); - Cvar_Hook(&gl_conback, GL_Conback_Callback); - Cvar_Hook(&gl_font, GL_Font_Callback); - Cvar_Hook(&gl_smoothfont, GL_Smoothfont_Callback); - Cvar_Hook(&gl_fontinwardstep, GL_Fontinwardstep_Callback); Cvar_Hook(&vid_conautoscale, GLVID_Conautoscale_Callback); Cvar_Hook(&vid_conheight, GLVID_Conheight_Callback); Cvar_Hook(&vid_conwidth, GLVID_Conwidth_Callback); @@ -840,6 +759,7 @@ static void R_LoadRTLights(void) { dlight_t *dl; char fname[MAX_QPATH]; + char cubename[MAX_QPATH]; char *file; char *end; int style; @@ -876,11 +796,6 @@ static void R_LoadRTLights(void) flags = LFLAG_NOSHADOWS; file++; } - else if (*file == '#') - { - flags = LFLAG_SHADOWMAP; - file++; - } else flags = 0; @@ -906,6 +821,7 @@ static void R_LoadRTLights(void) file = COM_Parse(file); //cubemap + Q_strncpyz(cubename, com_token, sizeof(cubename)); file = COM_Parse(file); //corona @@ -946,6 +862,11 @@ static void R_LoadRTLights(void) VectorCopy(rgb, dl->color); dl->die = 0; dl->flags = flags|LFLAG_ALLOW_PPL; + if (*cubename) + { + dl->fov = 90; + dl->flags |= LFLAG_SHADOWMAP; + } AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]); dl->style = style+1; @@ -1029,19 +950,6 @@ void GLR_NewMap (void) char namebuf[MAX_QPATH]; extern cvar_t host_mapname, r_shadow_realtime_dlight, r_shadow_realtime_world; int i; - -/* - if (cl.worldmodel->fromgame == fg_quake3 && cls.netchan.remote_address.type != NA_LOOPBACK) - { - if (!cls.allow_cheats) - { - CL_Disconnect(); - Host_EndGame("\n\nThe quake3 map implementation is still experimental and contains many bugs that could be considered cheats. Therefore, the engine is handicapped to quake3 maps only when hosting - it's single player only.\n\nYou can allow it on the server by activating cheats, at which point this check will be ignored\n"); - return; - } -// Cbuf_AddText("disconnect\n", RESTRICT_LOCAL); - } -*/ for (i=0 ; i<256 ; i++) d_lightstylevalue[i] = 264; // normal light value @@ -1055,11 +963,6 @@ void GLR_NewMap (void) COM_StripExtension(COM_SkipPath(cl.worldmodel->name), namebuf, sizeof(namebuf)); Cvar_Set(&host_mapname, namebuf); -// clear out efrags in case the level hasn't been reloaded -// FIXME: is this one short? - for (i=0 ; inumleafs ; i++) - cl.worldmodel->leafs[i].efrags = NULL; - Surf_DeInit(); r_viewleaf = NULL; @@ -1072,20 +975,6 @@ TRACE(("dbg: GLR_NewMap: wiping them stains (getting the cloth out)\n")); Surf_WipeStains(); TRACE(("dbg: GLR_NewMap: building lightmaps\n")); Surf_BuildLightmaps (); -TRACE(("dbg: GLR_NewMap: figuring out skys and mirrors\n")); - // identify sky texture - if (cl.worldmodel->fromgame != fg_quake2 && cl.worldmodel->fromgame != fg_quake3) - { - mirrortexturenum = -1; - } - for (i=0 ; inumtextures ; i++) - { - if (!cl.worldmodel->textures[i]) - continue; - if (!Q_strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) ) - mirrortexturenum = i; - cl.worldmodel->textures[i]->texturechain = NULL; - } TRACE(("dbg: GLR_NewMap: ui\n")); #ifdef VM_UI @@ -1093,9 +982,10 @@ TRACE(("dbg: GLR_NewMap: ui\n")); #endif TRACE(("dbg: GLR_NewMap: tp\n")); TP_NewMap(); + R_SetSky(cl.skyname); #ifdef RTLIGHTS - if (r_shadow_realtime_dlight.value || r_shadow_realtime_world.value) + if (r_shadow_realtime_dlight.ival || r_shadow_realtime_world.ival) { R_LoadRTLights(); if (rtlights_first == rtlights_max) diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 1b58e4c4..7cc5ec75 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -266,11 +266,11 @@ void BE_GenBrushModelVBO(model_t *mod) BZ_Free(vboedata); } } - for (i=0 ; inumsurfaces ; i++) +/* for (i=0 ; inumsurfaces ; i++) { if (!mod->surfaces[i].mark) Host_EndGame("Surfaces with bad textures detected\n"); - } + }*/ } void BE_UploadAllLightmaps(void) @@ -294,8 +294,8 @@ void BE_UploadAllLightmaps(void) qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes - , LMBLOCK_WIDTH, LMBLOCK_HEIGHT, 0, - ((lightmap_bytes==3)?GL_RGB:GL_LUMINANCE), GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); + , LMBLOCK_WIDTH, LMBLOCK_HEIGHT, 0, + ((lightmap_bytes==3)?GL_RGB:GL_LUMINANCE), GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); if (gl_bump.ival) { @@ -308,8 +308,8 @@ void BE_UploadAllLightmaps(void) qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexImage2D (GL_TEXTURE_2D, 0, 3 - , LMBLOCK_WIDTH, LMBLOCK_HEIGHT, 0, - GL_RGB, GL_UNSIGNED_BYTE, lightmap[i]->deluxmaps); + , LMBLOCK_WIDTH, LMBLOCK_HEIGHT, 0, + GL_RGB, GL_UNSIGNED_BYTE, lightmap[i]->deluxmaps); } } } diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index f35ac074..cf7ceb42 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -94,8 +94,8 @@ void GLVID_Console_Resize(void) if (cheight < 200) cheight = 200; - vid.width = vid.conwidth = cwidth; - vid.height = vid.conheight = cheight; + vid.width = cwidth; + vid.height = cheight; vid.recalc_refdef = true; diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index b8d744c4..25352262 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // r_shader.c - based on code by Stephen C. Taylor +// Ported to FTE from qfusion, there are numerous changes since then. #include "quakedef.h" @@ -37,10 +38,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern texid_t missing_texture; static qboolean shader_reload_needed; +static qboolean shader_rescan_needed; //cvars that affect shader generation cvar_t r_vertexlight = SCVAR("r_vertexlight", "0"); -extern cvar_t r_fastsky, r_skyboxname; +extern cvar_t r_fastturb, r_fastsky, r_skyboxname; extern cvar_t r_drawflat; //backend fills this in to say the max pass count @@ -191,6 +193,8 @@ static char shaderbuf[MAX_QPATH * 256]; int shaderbuflen; shader_t *r_shaders; +static hashtable_t shader_active_hash; +void *shader_active_hash_mem; //static char r_skyboxname[MAX_QPATH]; //static float r_skyheight; @@ -222,6 +226,22 @@ static char *Shader_ParseString ( char **ptr ) return token; } +static char *Shader_ParseSensString ( char **ptr ) +{ + char *token; + + if ( !ptr || !(*ptr) ) { + return ""; + } + if ( !**ptr || **ptr == '}' ) { + return ""; + } + + token = COM_ParseExt ( ptr, false ); + + return token; +} + static float Shader_ParseFloat ( char **ptr ) { if ( !ptr || !(*ptr) ) { @@ -254,6 +274,8 @@ static void Shader_ParseVector ( char **ptr, vec3_t v ) } ptr = &scratch; scratch = var->string; + + token = Shader_ParseString ( ptr ); } if ( !Q_stricmp (token, "(") ) { bracket = true; @@ -287,10 +309,10 @@ static void Shader_ParseVector ( char **ptr, vec3_t v ) } } -static void Shader_ParseSkySides ( shader_t *shader, char **ptr, texid_t *images ) +qboolean Shader_ParseSkySides (char *shadername, char *texturename, texid_t *images) { + qboolean allokay = true; int i, ss, sp; - char *token; char path[MAX_QPATH]; static char *skyname_suffix[][6] = { @@ -309,24 +331,29 @@ static void Shader_ParseSkySides ( shader_t *shader, char **ptr, texid_t *images "gfx/env/%s%s" }; - token = Shader_ParseString ( ptr ); - if (*token == '$') + if (*texturename == '$') { cvar_t *v; - v = Cvar_FindVar(token+1); + v = Cvar_FindVar(texturename+1); if (v) - token = v->string; + texturename = v->string; } + if (!*texturename) + texturename = "-"; + for ( i = 0; i < 6; i++ ) { - if ( token[0] == '-' ) { + if ( texturename[0] == '-' ) + { images[i] = r_nulltex; - } else { + } + else + { for (sp = 0; sp < sizeof(skyname_pattern)/sizeof(skyname_pattern[0]); sp++) { for (ss = 0; ss < sizeof(skyname_suffix)/sizeof(skyname_suffix[0]); ss++) { - Com_sprintf ( path, sizeof(path), skyname_pattern[sp], token, skyname_suffix[ss][i] ); + Com_sprintf ( path, sizeof(path), skyname_pattern[sp], texturename, skyname_suffix[ss][i] ); images[i] = R_LoadHiResTexture ( path, NULL, IF_NOALPHA); if (TEXVALID(images[i])) break; @@ -336,11 +363,13 @@ static void Shader_ParseSkySides ( shader_t *shader, char **ptr, texid_t *images } if (!TEXVALID(images[i])) { - Con_Printf("Shader \"%s\" missing texture: %s\n", shader->name, path); + Con_Printf("Sky \"%s\" missing texture: %s\n", shadername, path); images[i] = missing_texture; + allokay = false; } } } + return allokay; } static void Shader_ParseFunc ( char **ptr, shaderfunc_t *func ) @@ -472,34 +501,39 @@ static void Shader_DeformVertexes ( shader_t *shader, shaderpass_t *pass, char * } -static void Shader_SkyParms ( shader_t *shader, shaderpass_t *pass, char **ptr ) +static void Shader_SkyParms(shader_t *shader, shaderpass_t *pass, char **ptr) { int i; skydome_t *skydome; float skyheight; + char *boxname; if (shader->skydome) { - for ( i = 0; i < 5; i++ ) { - Z_Free ( shader->skydome->meshes[i].xyz_array ); - Z_Free ( shader->skydome->meshes[i].normals_array ); - Z_Free ( shader->skydome->meshes[i].st_array ); + for (i = 0; i < 5; i++) + { + Z_Free(shader->skydome->meshes[i].xyz_array); + Z_Free(shader->skydome->meshes[i].normals_array); + Z_Free(shader->skydome->meshes[i].st_array); } - Z_Free ( shader->skydome ); + Z_Free(shader->skydome); } - skydome = (skydome_t *)Z_Malloc ( sizeof(skydome_t) ); + skydome = (skydome_t *)Z_Malloc(sizeof(skydome_t)); shader->skydome = skydome; - Shader_ParseSkySides ( shader, ptr, skydome->farbox_textures ); + boxname = Shader_ParseString(ptr); + Shader_ParseSkySides(shader->name, boxname, skydome->farbox_textures); - skyheight = Shader_ParseFloat ( ptr ); - if ( !skyheight ) { + skyheight = Shader_ParseFloat(ptr); + if (!skyheight) + { skyheight = 512.0f; } - Shader_ParseSkySides ( shader, ptr, skydome->nearbox_textures ); + boxname = Shader_ParseString(ptr); + Shader_ParseSkySides(shader->name, boxname, skydome->nearbox_textures); shader->flags |= SHADER_SKY; shader->sort = SHADER_SORT_SKY; @@ -553,12 +587,16 @@ static void Shader_Sort ( shader_t *shader, shaderpass_t *pass, char **ptr ) shader->sort = SHADER_SORT_SKY; } else if( !Q_stricmp( token, "opaque" ) ) { shader->sort = SHADER_SORT_OPAQUE; + } else if( !Q_stricmp( token, "decal" ) ) { + shader->sort = SHADER_SORT_DECAL; + } else if( !Q_stricmp( token, "seethrough" ) ) { + shader->sort = SHADER_SORT_SEETHROUGH; } else if( !Q_stricmp( token, "banner" ) ) { shader->sort = SHADER_SORT_BANNER; - } else if( !Q_stricmp( token, "underwater" ) ) { - shader->sort = SHADER_SORT_UNDERWATER; } else if( !Q_stricmp( token, "additive" ) ) { shader->sort = SHADER_SORT_ADDITIVE; + } else if( !Q_stricmp( token, "underwater" ) ) { + shader->sort = SHADER_SORT_UNDERWATER; } else if( !Q_stricmp( token, "nearest" ) ) { shader->sort = SHADER_SORT_NEAREST; } else { @@ -586,6 +624,16 @@ static void Shader_EntityMergable ( shader_t *shader, shaderpass_t *pass, char * 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 vert frag + on one line. + */ void *vert, *frag; char *token; if (shader->programhandle.glsl) @@ -701,7 +749,7 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p } else if (!Q_stricmp(token, "cvari")) { - token = Shader_ParseString(ptr); + token = Shader_ParseSensString(ptr); cv = Cvar_Get(token, "", 0, "GLSL Shader parameters"); if (cv) { //Cvar_Get returns null if the cvar is the name of a command @@ -712,7 +760,7 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p } else if (!Q_stricmp(token, "cvarf")) { - token = Shader_ParseString(ptr); + token = Shader_ParseSensString(ptr); cv = Cvar_Get(token, "", 0, "GLSL Shader parameters"); if (cv) { //Cvar_Get returns null if the cvar is the name of a command @@ -742,7 +790,7 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p else Con_Printf("shader %s: parameter type \"%s\" not known\n", shader->name, token); - token = Shader_ParseString(ptr); + token = Shader_ParseSensString(ptr); #ifdef GLQUAKE if (qrenderer == QR_OPENGL) @@ -1027,6 +1075,9 @@ static void Shaderpass_AlphaGen (shader_t *shader, shaderpass_t *pass, char **pt if (!Q_stricmp (token, "portal")) { pass->alphagen = ALPHA_GEN_PORTAL; + shader->portaldist = Shader_ParseFloat(ptr); + if (!shader->portaldist) + shader->portaldist = 256; shader->flags |= SHADER_AGEN_PORTAL; } else if (!Q_stricmp (token, "vertex")) @@ -1432,12 +1483,11 @@ qboolean Shader_Init (void) shader_hash = calloc (HASH_SIZE, sizeof(*shader_hash)); - Con_Printf ( "Initializing Shaders.\n" ); - - COM_EnumerateFiles("shaders/*.shader", Shader_InitCallback, NULL); - COM_EnumerateFiles("scripts/*.shader", Shader_InitCallback, NULL); -// COM_EnumerateFiles("scripts/*.rscript", Shader_InitCallback, NULL); + shader_active_hash_mem = malloc(Hash_BytesForBuckets(1024)); + memset(shader_active_hash_mem, 0, Hash_BytesForBuckets(1024)); + Hash_InitTable(&shader_active_hash, 1024, shader_active_hash_mem); + shader_rescan_needed = true; Shader_NeedReload(); Shader_DoReload(); return true; @@ -1474,7 +1524,7 @@ static void Shader_MakeCache ( char *path ) t = NULL; Shader_GetPathAndOffset ( token, &t, &i ); - if ( t ) + if (t) { ptr = Shader_Skip ( ptr ); continue; @@ -1567,6 +1617,8 @@ void Shader_Free (shader_t *shader) int i; shaderpass_t *pass; + Hash_RemoveData(&shader_active_hash, shader->name, shader); + #ifdef GLQUAKE if (qrenderer == QR_OPENGL) if (shader->programhandle.glsl) @@ -1594,6 +1646,7 @@ void Shader_Free (shader_t *shader) { Shader_FreePass (pass); } + shader->numpasses = 0; } void Shader_Shutdown (void) @@ -1605,7 +1658,7 @@ void Shader_Shutdown (void) shader = r_shaders; for (i = 0; i < MAX_SHADERS; i++, shader++) { - if ( !shader->registration_sequence ) + if ( !shader->uses ) continue; Shader_Free ( shader ); @@ -1623,10 +1676,12 @@ void Shader_Shutdown (void) } } - Z_Free(r_shaders); + free(r_shaders); r_shaders = NULL; - Z_Free(shader_hash); + free(shader_hash); shader_hash = NULL; + free(shader_active_hash_mem); + shader_active_hash_mem = NULL; shader_reload_needed = false; } @@ -1703,7 +1758,7 @@ void Shader_Readpass (shader_t *shader, char **ptr) pass->numtcmods = 0; pass->numMergedPasses = 1; - while ( ptr ) + while ( *ptr ) { token = COM_ParseExt (ptr, true); @@ -2013,7 +2068,7 @@ void Shader_Finish (shader_t *s) "{\n" "{\n" "map $whiteimage\n" - "rgbgen $r_fastskycolour\n" + "rgbgen const $r_fastskycolour\n" "}\n" "}\n" ); @@ -2161,7 +2216,7 @@ done:; pass = s->passes; for (i = 0; i < s->numpasses; i++, pass++ ) { - if ((pass->shaderbits&SBITS_BLEND_BITS) == (SBITS_SRCBLEND_DST_COLOR|SBITS_DSTBLEND_ZERO)) + if (pass->shaderbits & SBITS_ATEST_BITS) { opaque = i; } @@ -2180,11 +2235,9 @@ done:; if (!(s->flags & SHADER_SKY ) && !s->sort) { if (opaque == -1) - s->sort = SHADER_SORT_ADDITIVE; - else if (s->passes[opaque].shaderbits & SBITS_ATEST_BITS) - s->sort = SHADER_SORT_OPAQUE + 1; + s->sort = SHADER_SORT_BLEND; else - s->sort = SHADER_SORT_OPAQUE; + s->sort = SHADER_SORT_SEETHROUGH; } } else @@ -2206,7 +2259,7 @@ done:; if (!s->sort) { if (pass->shaderbits & SBITS_ATEST_BITS) - s->sort = SHADER_SORT_OPAQUE + 1; + s->sort = SHADER_SORT_SEETHROUGH; } if (!( s->flags & SHADER_DEPTHWRITE) && @@ -2314,6 +2367,11 @@ void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader) if (!TEXVALID(tn->bump) && gl_bump.ival) tn->bump = R_LoadHiResTexture(va("normalmaps/%s", shader->name), NULL, IF_NOALPHA); + if (!TEXVALID(tn->loweroverlay)) + tn->loweroverlay = R_LoadHiResTexture(va("%s_pants", shader->name), NULL, 0); /*how rude*/ + if (!TEXVALID(tn->upperoverlay)) + tn->upperoverlay = R_LoadHiResTexture(va("%s_shirt", shader->name), NULL, 0); + shader->defaulttextures = *tn; } @@ -2331,24 +2389,211 @@ void Shader_DefaultScript(char *shortname, shader_t *s, const void *args) } }; -void Shader_DefaultBSP(char *shortname, shader_t *s, const void *args) +void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) { char *builtin = NULL; + if (!builtin && r_drawflat.value) + builtin = ( + "{\n" + "{\n" + "map $lightmap\n" + "tcgen lightmap\n" + "rgbgen const $r_floorcolour\n" + "}\n" + "}\n" + ); + + if (!builtin) + builtin = ( + "{\n" + "if $deluxmap\n" + "[\n" + "{\n" + "map $normalmap\n" + "tcgen base\n" + "}\n" + "{\n" + "map $deluxmap\n" + "tcgen lightmap\n" + "}\n" + "]\n" + "{\n" + "map $diffuse\n" + "tcgen base\n" + "}\n" + "if $lightmap\n" + "[\n" + "{\n" + "map $lightmap\n" + "blendfunc gl_dst_color gl_zero\n" + "}\n" + "]\n" + "{\n" + "map $fullbright\n" + "blendfunc add\n" + "depthfunc equal\n" + "}\n" + "}\n" + ); + + Shader_DefaultScript(shortname, s, builtin); +} + +void Shader_DefaultCinematic(char *shortname, shader_t *s, const void *args) +{ + Shader_DefaultScript(shortname, s, + va( + "{\n" + "{\n" + "videomap %s\n" + "}\n" + "}\n" + , args) + ); +} + +/*shortname should begin with 'skybox_'*/ +void Shader_DefaultSkybox(char *shortname, shader_t *s, const void *args) +{ + Shader_DefaultScript(shortname, s, + va( + "{\n" + "skyparms %s - -\n" + "}\n" + , shortname+7) + ); +} + +void Shader_DefaultBSPQ2(char *shortname, shader_t *s, const void *args) +{ + if (!strncmp(shortname, "sky/", 4)) + { + Shader_DefaultScript(shortname, s, + "{\n" + "skyparms - - -\n" + "}\n" + ); + } + else if (!strncmp(shortname, "warp/", 7)) + { + Shader_DefaultScript(shortname, s, + "{\n" + "{\n" + "map $diffuse\n" + "tcmod turb 0 0.01 0.5 0\n" + "}\n" + "}\n" + ); + } + else if (!strncmp(shortname, "warp33/", 7)) + { + Shader_DefaultScript(shortname, s, + "{\n" + "{\n" + "map $diffuse\n" + "tcmod turb 0 0.01 0.5 0\n" + "alphagen const 0.333\n" + "blendfunc blend\n" + "}\n" + "}\n" + ); + } + else if (!strncmp(shortname, "warp66/", 7)) + { + Shader_DefaultScript(shortname, s, + "{\n" + "{\n" + "map $diffuse\n" + "tcmod turb 0 0.01 0.5 0\n" + "alphagen const 0.666\n" + "blendfunc blend\n" + "}\n" + "}\n" + ); + } + else if (!strncmp(shortname, "trans/", 7)) + Shader_DefaultScript(shortname, s, + "{\n" + "{\n" + "map $diffuse\n" + "alphagen const 1\n" + "blendfunc blend\n" + "}\n" + "}\n" + ); + else if (!strncmp(shortname, "trans33/", 7)) + Shader_DefaultScript(shortname, s, + "{\n" + "{\n" + "map $diffuse\n" + "alphagen const 0.333\n" + "blendfunc blend\n" + "}\n" + "}\n" + ); + else if (!strncmp(shortname, "trans66/", 7)) + Shader_DefaultScript(shortname, s, + "{\n" + "{\n" + "map $diffuse\n" + "alphagen const 0.666\n" + "blendfunc blend\n" + "}\n" + "}\n" + ); + else + Shader_DefaultBSPLM(shortname, s, args); +} + +void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) +{ + char *builtin = NULL; + if (r_mirroralpha.value < 1 && !strcmp(shortname, "window02_1")) + { + if (r_mirroralpha.value < 0) + { + builtin = "{\n" + "portal\n" + "{\n" + "map $diffuse\n" + "blendfunc blend\n" + "alphagen portal 512\n" + "depthwrite\n" + "}\n" + "}\n"; + } + else + { + builtin = "{\n" + "portal\n" + "{\n" + "map $diffuse\n" + "blendfunc blend\n" + "alphagen const $r_mirroralpha\n" + "depthwrite\n" + "}\n" + "}\n"; + } + + } + if (!builtin && (*shortname == '*')) { //q1 water - /* if (r_fastturb.value) + if (r_fastturb.ival) { - builtin = ( + builtin = ( + "{\n" "{\n" - "{\n" - "map $whiteimage\n" - "rgbgen $r_fastturbcolour\n" - "}\n" + "map $whiteimage\n" + "rgbgen $r_fastturbcolour\n" "}\n" - ); + "}\n" + ); } - else*/ +#ifdef GLQUAKE + else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects) + { builtin = ( "{\n" "program\n" @@ -2388,6 +2633,19 @@ void Shader_DefaultBSP(char *shortname, shader_t *s, const void *args) "}\n" "}\n" ); + } +#endif + else + { + builtin = ( + "{\n" + "{\n" + "map $diffuse\n" + "tcmod turb 0 0.01 0.5 0\n" + "}\n" + "}\n" + ); + } } if (!builtin && !strncmp(shortname, "sky", 3)) { @@ -2397,7 +2655,7 @@ void Shader_DefaultBSP(char *shortname, shader_t *s, const void *args) "{\n" "{\n" "map $whiteimage\n" - "rgbgen $r_fastskycolour\n" + "rgbgen const $r_fastskycolour\n" "}\n" "}\n" ); @@ -2407,7 +2665,8 @@ void Shader_DefaultBSP(char *shortname, shader_t *s, const void *args) "skyparms $r_skybox - -\n" "}\n" ); - else +#ifdef GLQUAKE + else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects) builtin = ( "{\n" "program\n" @@ -2464,6 +2723,25 @@ void Shader_DefaultBSP(char *shortname, shader_t *s, const void *args) "}\n" "}\n" ); +#endif + else + builtin = ( + "{\n" + "skyparms - 512 -\n" + /*WARNING: these values are not authentic quake, only close aproximations*/ + "{\n" + "map $diffuse\n" + "tcmod scale 10 10\n" + "tcmod scroll 0.04 0.04\n" + "}\n" + "{\n" + "map $fullbright\n" + "blendfunc blend\n" + "tcmod scale 10 10\n" + "tcmod scroll 0.02 0.02\n" + "}\n" + "}\n" + ); } if (!builtin && *shortname == '{') { @@ -2504,7 +2782,7 @@ void Shader_DefaultBSP(char *shortname, shader_t *s, const void *args) } /*Hack: note that halflife would normally expect you to use rendermode/renderampt*/ - if (!builtin && (!strncmp(shortname, "glass", 5) || !strncmp(shortname, "window", 6))) + if (!builtin && (!strncmp(shortname, "glass", 5)/* || !strncmp(shortname, "window", 6)*/)) { /*alpha bended*/ builtin = ( @@ -2518,51 +2796,10 @@ void Shader_DefaultBSP(char *shortname, shader_t *s, const void *args) ); } - if (!builtin && r_drawflat.value) - builtin = ( - "{\n" - "{\n" - "map $lightmap\n" - "tcgen lightmap\n" - "rgbgen const $r_floorcolour\n" - "}\n" - "}\n" - ); - - if (!builtin) - builtin = ( - "{\n" - "if $deluxmap\n" - "[\n" - "{\n" - "map $normalmap\n" - "tcgen base\n" - "}\n" - "{\n" - "map $deluxmap\n" - "tcgen lightmap\n" - "}\n" - "]\n" - "{\n" - "map $diffuse\n" - "tcgen base\n" - "}\n" - "if $lightmap\n" - "[\n" - "{\n" - "map $lightmap\n" - "blendfunc gl_dst_color gl_zero\n" - "}\n" - "]\n" - "{\n" - "map $fullbright\n" - "blendfunc add\n" - "depthfunc equal\n" - "}\n" - "}\n" - ); - - Shader_DefaultScript(shortname, s, builtin); + if (builtin) + Shader_DefaultScript(shortname, s, builtin); + else + Shader_DefaultBSPLM(shortname, s, args); } void Shader_DefaultBSPVertex(char *shortname, shader_t *s, const void *args) @@ -2588,7 +2825,7 @@ void Shader_DefaultBSPVertex(char *shortname, shader_t *s, const void *args) s->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT; s->features = MF_STCOORDS|MF_COLORS; s->sort = SHADER_SORT_OPAQUE; - s->registration_sequence = 1;//fizme: registration_sequence; + s->uses = 1; } void Shader_DefaultBSPFlare(char *shortname, shader_t *s, const void *args) { @@ -2615,7 +2852,7 @@ void Shader_DefaultBSPFlare(char *shortname, shader_t *s, const void *args) s->flags = SHADER_FLARE; s->features = MF_STCOORDS|MF_COLORS; s->sort = SHADER_SORT_ADDITIVE; - s->registration_sequence = 1;//fizme: registration_sequence; + s->uses = 1; } void Shader_DefaultSkin(char *shortname, shader_t *s, const void *args) { @@ -2628,10 +2865,12 @@ void Shader_DefaultSkin(char *shortname, shader_t *s, const void *args) "{\n" "map $loweroverlay\n" "rgbgen bottomcolor\n" + "blendfunc gl_src_alpha gl_one\n" "}\n" "{\n" "map $upperoverlay\n" - "rgbgen uppercolor\n" + "rgbgen topcolor\n" + "blendfunc gl_src_alpha gl_one\n" "}\n" "{\n" "map $fullbright\n" @@ -2668,7 +2907,7 @@ void Shader_DefaultSkinShell(char *shortname, shader_t *s, const void *args) s->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT; s->features = MF_STCOORDS|MF_NORMALS; s->sort = SHADER_SORT_OPAQUE; - s->registration_sequence = 1;//fizme: registration_sequence; + s->uses = 1; } void Shader_Default2D(char *shortname, shader_t *s, const void *genargs) { @@ -2698,7 +2937,7 @@ void Shader_Default2D(char *shortname, shader_t *s, const void *genargs) s->flags = SHADER_NOPICMIP|SHADER_NOMIPMAPS|SHADER_BLEND; s->features = MF_STCOORDS|MF_COLORS; s->sort = SHADER_SORT_ADDITIVE; - s->registration_sequence = 1;//fizme: registration_sequence; + s->uses = 1; } //loads a shader string into an existing shader object, and finalises it and stuff @@ -2708,7 +2947,7 @@ static void Shader_ReadShader(shader_t *s, char *shadersource) // set defaults s->flags = SHADER_CULL_FRONT; - s->registration_sequence = 1;//fizme: registration_sequence; + s->uses = 1; while (shadersource) { @@ -2747,7 +2986,7 @@ static void Shader_ReadShader(shader_t *s, char *shadersource) Shader_Finish ( s ); } -qboolean Shader_ParseShader(char *shortname, char *usename, shader_t *s) +static qboolean Shader_ParseShader(char *shortname, char *usename, shader_t *s) { unsigned int offset = 0, length; char path[MAX_QPATH]; @@ -2780,6 +3019,7 @@ qboolean Shader_ParseShader(char *shortname, char *usename, shader_t *s) Shader_Free(s); memset ( s, 0, sizeof( shader_t ) ); Com_sprintf ( s->name, MAX_QPATH, usename ); + Hash_Add(&shader_active_hash, s->name, s, &s->bucket); Shader_ReadShader(s, file); @@ -2792,8 +3032,12 @@ qboolean Shader_ParseShader(char *shortname, char *usename, shader_t *s) return false; } - -int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *genargs) +void R_UnloadShader(shader_t *shader) +{ + if (shader->uses-- == 1) + Shader_Free(shader); +} +static int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *genargs) { int i, f = -1; char shortname[MAX_QPATH]; @@ -2803,20 +3047,25 @@ int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *genargs) COM_CleanUpPath(shortname); - // test if already loaded + // check the hash first + s = Hash_Get(&shader_active_hash, shortname); + if (s) + { + i = s - r_shaders; + r_shaders[i].uses++; + return i; + } + + // not loaded, find a free slot for (i = 0; i < MAX_SHADERS; i++) { - if (!r_shaders[i].generator) + if (!r_shaders[i].uses) { if ( f == -1 ) // free shader + { f = i; - continue; - } - - if (!Q_stricmp (shortname, r_shaders[i].name) ) - { - r_shaders[i].registration_sequence = 1;//fizme: registration_sequence; - return i; + break; + } } } @@ -2857,6 +3106,7 @@ int R_LoadShader ( char *name, shader_gen_t *defaultgen, const char *genargs) s->generator = defaultgen; s->genargs = genargs; Com_sprintf ( s->name, MAX_QPATH, shortname ); + Hash_Add(&shader_active_hash, s->name, s, &s->bucket); defaultgen(shortname, s, genargs); return f; @@ -2873,6 +3123,18 @@ void Shader_DoReload(void) const char *genargs; texnums_t oldtn; + if (shader_rescan_needed && ruleset_allow_shaders.ival) + { + Con_Printf ( "Initializing Shaders.\n" ); + + COM_EnumerateFiles("shaders/*.shader", Shader_InitCallback, NULL); + COM_EnumerateFiles("scripts/*.shader", Shader_InitCallback, NULL); + //COM_EnumerateFiles("scripts/*.rscript", Shader_InitCallback, NULL); + + shader_reload_needed = true; + shader_rescan_needed = false; + } + if (!shader_reload_needed) return; shader_reload_needed = false; @@ -2881,7 +3143,7 @@ void Shader_DoReload(void) for (s = r_shaders, i = 0; i < MAX_SHADERS; i++, s++) { - if (!s->generator) + if (!s->uses) continue; defaultgen = s->generator; @@ -2918,6 +3180,7 @@ void Shader_DoReload(void) s->generator = defaultgen; s->genargs = genargs; Com_sprintf ( s->name, MAX_QPATH, shortname ); + Hash_Add(&shader_active_hash, s->name, s, &s->bucket); s->generator(shortname, s, s->genargs); R_BuildDefaultTexnums(&oldtn, s); } @@ -2929,14 +3192,27 @@ void Shader_NeedReload(void) shader_reload_needed = true; } -cin_t *R_ShaderGetCinematic(char *name) +cin_t *R_ShaderGetCinematic(shader_t *s) +{ +#ifndef NOMEDIA + int j; + if (!s) + return NULL; + for (j = 0; j < s->numpasses; j++) + if (s->passes[j].cin) + return s->passes[j].cin; +#endif + /*no cinematic in this shader!*/ + return NULL; +} + +cin_t *R_ShaderFindCinematic(char *name) { #ifdef NOMEDIA return NULL; #else - int i, j; - char shortname[MAX_QPATH]; - shader_t *s; + int i; + char shortname[MAX_QPATH]; COM_StripExtension ( name, shortname, sizeof(shortname)); @@ -2945,7 +3221,7 @@ cin_t *R_ShaderGetCinematic(char *name) //try and find it for (i = 0; i < MAX_SHADERS; i++) { - if (!r_shaders[i].registration_sequence) + if (!r_shaders[i].uses) continue; if (!Q_stricmp (shortname, r_shaders[i].name) ) @@ -2954,14 +3230,8 @@ cin_t *R_ShaderGetCinematic(char *name) if (i == MAX_SHADERS) return NULL; - //we have a currently-loaded shader. - s = &r_shaders[i]; - for (j = 0; j < s->numpasses; j++) - if (s->passes[j].cin) - return s->passes[j].cin; - - //but it has no cinematic passes. - return NULL; + //found the named shader. + return R_ShaderGetCinematic(&r_shaders[i]); #endif } @@ -2977,7 +3247,7 @@ shader_t *R_RegisterShader (char *name, const char *shaderscript) shader_t *R_RegisterShader_Lightmap (char *name) { - return &r_shaders[R_LoadShader (name, Shader_DefaultBSP, NULL)]; + return &r_shaders[R_LoadShader (name, Shader_DefaultBSPLM, NULL)]; } shader_t *R_RegisterShader_Vertex (char *name) diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 194e255b..eba44db3 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -6,15 +6,18 @@ #include "glquake.h" #include "shader.h" -#define lradius l->radius +#define SHADOWMAP_SIZE 512 + #define nearplane (16) -#if 0//def _DEBUG +#if 1//def _DEBUG #define checkerror() if (qglGetError()) Con_Printf("Error detected at line %s:%i\n", __FILE__, __LINE__) #else #define checkerror() #endif +static int shadow_fbo_id; + static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour); @@ -37,7 +40,7 @@ struct { typedef struct { unsigned int count; unsigned int max; - msurface_t **s; + mesh_t **s; } shadowmeshsurfs_t; typedef struct shadowmesh_s { unsigned int numindicies; @@ -185,21 +188,17 @@ static void SHM_Shadow_Cache_Surface(msurface_t *surf) { int i; -#pragma message("Remove this loop ffs!") - for (i = 0; i < cl.worldmodel->numtextures; i++) + i = surf->texinfo->texture->wtexno; + if (i < 0) + return; + + if (sh_shmesh->litsurfs[i].count == sh_shmesh->litsurfs[i].max) { - if (surf->texinfo->texture == cl.worldmodel->textures[i]) - { - if (sh_shmesh->litsurfs[i].count == sh_shmesh->litsurfs[i].max) - { - sh_shmesh->litsurfs[i].max += 64; - sh_shmesh->litsurfs[i].s = BZ_Realloc(sh_shmesh->litsurfs[i].s, sizeof(void*)*(sh_shmesh->litsurfs[i].max)); - } - sh_shmesh->litsurfs[i].s[sh_shmesh->litsurfs[i].count] = surf; - sh_shmesh->litsurfs[i].count++; - break; - } + sh_shmesh->litsurfs[i].max += 64; + sh_shmesh->litsurfs[i].s = BZ_Realloc(sh_shmesh->litsurfs[i].s, sizeof(void*)*(sh_shmesh->litsurfs[i].max)); } + sh_shmesh->litsurfs[i].s[sh_shmesh->litsurfs[i].count] = surf->mesh; + sh_shmesh->litsurfs[i].count++; } static void SHM_Shadow_Cache_Leaf(mleaf_t *leaf) @@ -862,7 +861,7 @@ static SHM_ComposeVolume_BruteForce(dlight_t *dl) continue; for (sno = 0; sno < sms->count; sno++) { - sm = sms->s[sno]->mesh; + sm = sms->s[sno]; if (sm->istrifan) { @@ -1259,19 +1258,17 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture) { - static int fboid; - - if (qglGenRenderbuffersEXT) + if (gl_config.ext_framebuffer_objects) { - if (!fboid) + if (!shadow_fbo_id) { - qglGenRenderbuffersEXT(1, &fboid); - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboid); + qglGenRenderbuffersEXT(1, &shadow_fbo_id); + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id); qglDrawBuffer(GL_NONE); qglReadBuffer(GL_NONE); } else - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboid); + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id); if (TEXVALID(depthtexture)) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depthtexture.num, 0); @@ -1279,7 +1276,7 @@ void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture) } void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize) { - if (qglGenRenderbuffersEXT) + if (gl_config.ext_framebuffer_objects) { qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } @@ -1290,43 +1287,66 @@ void GL_EndRenderBuffer_DepthOnly(texid_t depthtexture, int texsize) } } -static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face) +static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float proj[16]) { - float mvm[16], proj[16]; + float mvm[16]; + vec3_t t1,t2; - int smsize = 512; - int tno, sno; - mesh_t *m, *sm; + int smsize = SHADOWMAP_SIZE; + int tno; + mesh_t *m; texture_t *tex; // qglDepthRange(0, 1); - BE_SetupForShadowMap(); checkerror(); - if (1) - { + if (l->fov) qglViewport (0, 0, smsize, smsize); + else + qglViewport (((face/2)*smsize)/3, ((face&1)*smsize)/2, smsize/3, smsize/2); - if (!l->fov) - l->fov = 90; - - Matrix4_Projection_Far(proj, l->fov, l->fov, nearplane, lradius); + switch(face) + { + case 0: + //forward Matrix4_ModelViewMatrixFromAxis(mvm, l->axis[0], l->axis[1], l->axis[2], l->origin); - - qglMatrixMode(GL_PROJECTION); - qglLoadMatrixf(proj); - qglMatrixMode(GL_MODELVIEW); - qglLoadMatrixf(mvm); - - R_SetFrustum(proj, mvm); + break; + case 1: + //back + VectorNegate(l->axis[0], t1); + VectorNegate(l->axis[1], t2); + Matrix4_ModelViewMatrixFromAxis(mvm, t1, t2, l->axis[2], l->origin); + break; + case 2: + //left + VectorNegate(l->axis[1], t1); + VectorNegate(l->axis[0], t2); + Matrix4_ModelViewMatrixFromAxis(mvm, l->axis[1], t2, l->axis[2], l->origin); + break; + case 3: + //right + VectorNegate(l->axis[1], t1); + Matrix4_ModelViewMatrixFromAxis(mvm, t1, l->axis[0], l->axis[2], l->origin); + break; + case 4: + //up + VectorNegate(l->axis[0], t2); + Matrix4_ModelViewMatrixFromAxis(mvm, l->axis[2], l->axis[1], t2, l->origin); + break; + case 5: + //down + VectorNegate(l->axis[2], t1); + Matrix4_ModelViewMatrixFromAxis(mvm, t1, l->axis[1], l->axis[0], l->origin); + break; } -checkerror(); - BE_SelectMode(BEM_DEPTHONLY, 0); + qglMatrixMode(GL_MODELVIEW); + qglLoadMatrixf(mvm); - GL_BeginRenderBuffer_DepthOnly(l->stexture); - qglClear (GL_DEPTH_BUFFER_BIT); + R_SetFrustum(proj, mvm); + + checkerror(); if (smesh) for (tno = 0; tno < smesh->numsurftextures; tno++) @@ -1334,30 +1354,19 @@ checkerror(); m = NULL; if (!smesh->litsurfs[tno].count) continue; - tex = smesh->litsurfs[tno].s[0]->texinfo->texture; - for (sno = 0; sno < smesh->litsurfs[tno].count; sno++) - { - sm = smesh->litsurfs[tno].s[sno]->mesh; - if (!sm) - continue; - sm->next = m; - m = sm; - } - if (m) - BE_DrawMeshChain(tex->shader, m, &tex->vbo, &tex->shader->defaulttextures); + tex = cl.worldmodel->textures[tno]; + BE_DrawMesh_List(tex->shader, smesh->litsurfs[tno].count, smesh->litsurfs[tno].s, &tex->vbo, &tex->shader->defaulttextures); } BE_BaseEntShadowDepth(); - GL_EndRenderBuffer_DepthOnly(l->stexture, smsize); - if (0) { int i; - static float depth[512*512]; + static float depth[SHADOWMAP_SIZE*SHADOWMAP_SIZE]; qglReadPixels(0, 0, smsize, smsize, GL_DEPTH_COMPONENT, GL_FLOAT, depth); - for (i = 512*512; i --> 0; ) + for (i = SHADOWMAP_SIZE*SHADOWMAP_SIZE; i --> 0; ) { if (depth[i] == 1) *((unsigned int*)depth+i) = 0; @@ -1377,69 +1386,96 @@ checkerror(); checkerror(); } -void Sh_GenShadowMaps (void) +void Sh_Shutdown(void) +{ + if (shadow_fbo_id) + { + qglDeleteRenderbuffersEXT(1, &shadow_fbo_id); + shadow_fbo_id = 0; + } +} + +void Sh_GenShadowMap (dlight_t *l) { - dlight_t *l; - int i; int f; - int smsize = 512; + int smsize = SHADOWMAP_SIZE; + float proj[16]; shadowmesh_t *smesh; - //FIXME: push dynamic shadow volume generation to another thread. - //FIXME: cull lights here. - - for (l = cl_dlights+rtlights_first, i=rtlights_first; istexture)) { - if (!(l->flags & LFLAG_SHADOWMAP)) - continue; - if (!l->radius || l->flags & LFLAG_NOSHADOWS) - continue; - if (l->color[0]<0) - continue; //quick check for darklight + l->stexture = GL_AllocNewTexture(); + + checkerror(); - if (!TEXVALID(l->stexture)) - { - l->stexture = GL_AllocNewTexture(); - - checkerror(); + GL_Bind(l->stexture); + checkerror(); + qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); + // qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize, smsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + checkerror(); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - GL_Bind(l->stexture); - checkerror(); - qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); - // qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, smsize, smsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - checkerror(); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - - checkerror(); - } - else if (l->refresh-->0) - continue; //FIXME: need to optimise GenShadowFace first - l->refresh = 0; - - if (l->worldshadowmesh) - smesh = l->worldshadowmesh; - else - { - unsigned int leaf; - qbyte lvisb[MAX_MAP_LEAFS/8]; - qbyte *lvis; - leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, l->origin); - lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); - smesh = SHM_BuildShadowVolumeMesh(l, lvis, NULL); - } - - qglEnable(GL_POLYGON_OFFSET_FILL); - qglPolygonOffset(5, 25); - for (f = 0; f < 1; f++) - { - Sh_GenShadowFace(l, smesh, f); - } - qglDisable(GL_POLYGON_OFFSET_FILL); + checkerror(); } + + if (l->worldshadowmesh) + smesh = l->worldshadowmesh; + else + { + unsigned int leaf; + qbyte lvisb[MAX_MAP_LEAFS/8]; + qbyte *lvis; + leaf = cl.worldmodel->funcs.LeafnumForPoint(cl.worldmodel, l->origin); + lvis = cl.worldmodel->funcs.LeafPVS(cl.worldmodel, leaf, lvisb, sizeof(lvisb)); + smesh = SHM_BuildShadowVolumeMesh(l, lvis, NULL); + } + + /*polygon offsets. urgh.*/ + qglEnable(GL_POLYGON_OFFSET_FILL); + qglPolygonOffset(5, 25); + BE_SetupForShadowMap(); + + /*set framebuffer*/ + GL_BeginRenderBuffer_DepthOnly(l->stexture); + qglClear (GL_DEPTH_BUFFER_BIT); + + if (l->fov) + { + Matrix4_Projection_Far(proj, l->fov, l->fov, nearplane, l->radius); + qglMatrixMode(GL_PROJECTION); + qglLoadMatrixf(proj); + + /*single face*/ + Sh_GenShadowFace(l, smesh, 0, proj); + } + else + { + Matrix4_Projection_Far(proj, 90, 90, nearplane, l->radius); + qglMatrixMode(GL_PROJECTION); + qglLoadMatrixf(proj); + + /*generate faces*/ + for (f = 0; f < 6; f++) + { + Sh_GenShadowFace(l, smesh, f, proj); + } + } + /*end framebuffer*/ + GL_EndRenderBuffer_DepthOnly(l->stexture, smsize); + + qglDisable(GL_POLYGON_OFFSET_FILL); + + qglMatrixMode(GL_PROJECTION); + qglLoadMatrixf(r_refdef.m_projection); + + qglMatrixMode(GL_MODELVIEW); + qglLoadMatrixf(r_refdef.m_view); + + qglViewport(r_refdef.pxrect.x, vid.pixelheight - r_refdef.pxrect.y, r_refdef.pxrect.width, r_refdef.pxrect.height); } static float shadowprojectionbias[16] = @@ -1450,15 +1486,41 @@ static float shadowprojectionbias[16] = 0.5f, 0.5f, 0.4993f, 1.0f }; -static void Sh_DrawLameSpotLightShadowMap(dlight_t *l, vec3_t colour) +static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour) { float t[16]; float bp[16]; float proj[16], view[16]; vec3_t biasorg; int ve; + vec3_t mins, maxs; - Matrix4_Projection_Far(proj, l->fov, l->fov, nearplane, lradius); + if (R_CullSphere(l->origin, l->radius)) + { + bench.numfrustumculled++; + return; //this should be the more common case + } + + mins[0] = l->origin[0] - l->radius; + mins[1] = l->origin[1] - l->radius; + mins[2] = l->origin[2] - l->radius; + + maxs[0] = l->origin[0] + l->radius; + maxs[1] = l->origin[1] + l->radius; + maxs[2] = l->origin[2] + l->radius; + + if (Sh_ScissorForBox(mins, maxs)) + { + bench.numscissorculled++; + return; + } + + Sh_GenShadowMap(l); + + if (l->fov) + Matrix4_Projection_Far(proj, l->fov, l->fov, nearplane, l->radius); + else + Matrix4_Projection_Far(proj, 90, 90, nearplane, l->radius); VectorMA(l->origin, 0, l->axis[0], biasorg); Matrix4_ModelViewMatrixFromAxis(view, l->axis[0], l->axis[1], l->axis[2], l->origin); @@ -1486,7 +1548,6 @@ checkerror(); bench.numlights++; -#if 1 qglMatrixMode(GL_TEXTURE); GL_MBind(7, l->stexture); // qglEnable(GL_TEXTURE_2D); @@ -1495,7 +1556,6 @@ checkerror(); qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); qglLoadMatrixf(bp); qglMatrixMode(GL_MODELVIEW); - PPL_RevertToKnownState(); GL_SelectTexture(0); @@ -1503,7 +1563,7 @@ checkerror(); ve = 0; BE_SelectDLight(l, colour); - BE_SelectMode(BEM_SMAPLIGHT, 0); + BE_SelectMode(l->fov?BEM_SMAPLIGHTSPOT:BEM_SMAPLIGHT, 0); Sh_DrawEntLighting(l, colour); GL_SelectTexture(7); @@ -1511,118 +1571,9 @@ checkerror(); qglMatrixMode(GL_TEXTURE); qglLoadIdentity(); qglMatrixMode(GL_MODELVIEW); -// PPL_RevertToKnownState(); + checkerror(); -#else -GL_MBind(0, l->stexture); -qglEnable(GL_TEXTURE_2D); - //Set up texture coordinate generation. - qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - qglTexGenfv(GL_S, GL_EYE_PLANE, &t[0]); - qglEnable(GL_TEXTURE_GEN_S); - - qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - qglTexGenfv(GL_T, GL_EYE_PLANE, &t[4]); - qglEnable(GL_TEXTURE_GEN_T); - - qglTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - qglTexGenfv(GL_R, GL_EYE_PLANE, &t[8]); - qglEnable(GL_TEXTURE_GEN_R); - - qglTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - qglTexGenfv(GL_Q, GL_EYE_PLANE, &t[12]); - qglEnable(GL_TEXTURE_GEN_Q); -checkerror(); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); - qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); -checkerror(); - - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - -if (1) -{ - GL_MBind(1, balltexture); - qglEnable(GL_TEXTURE_2D); - - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - - - qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - qglTexGenfv(GL_S, GL_EYE_PLANE, &t[0]); - qglEnable(GL_TEXTURE_GEN_S); - - qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - qglTexGenfv(GL_T, GL_EYE_PLANE, &t[4]); - qglEnable(GL_TEXTURE_GEN_T); - - qglTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - qglTexGenfv(GL_R, GL_EYE_PLANE, &t[8]); - qglEnable(GL_TEXTURE_GEN_R); - - qglTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - qglTexGenfv(GL_Q, GL_EYE_PLANE, &t[12]); - qglEnable(GL_TEXTURE_GEN_Q); -} -else -{ - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); - qglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); -} - - qglEnable(GL_BLEND); - qglBlendFunc (GL_SRC_ALPHA, GL_ONE); - qglDisable(GL_ALPHA_TEST); - qglColor3f(colour[0], colour[1], colour[2]); - qglEnableClientState(GL_VERTEX_ARRAY); - qglDisableClientState(GL_COLOR_ARRAY); -checkerror(); - qglDepthMask(0); - GL_TexEnv(GL_MODULATE); - ve = 0; - - //qglEnable(GL_POLYGON_OFFSET_FILL); - qglPolygonOffset(-0.5, -25); - - for (i = 0; i < cl.worldmodel->numsurfaces; i++) - { - s = &cl.worldmodel->surfaces[i]; -// if(s->visframe != r_framecount) -// continue; - - if (ve != s->texinfo->texture->vbo.vboe) - { - ve = s->texinfo->texture->vbo.vboe; - - GL_SelectVBO(s->texinfo->texture->vbo.vbocoord); - GL_SelectEBO(s->texinfo->texture->vbo.vboe); - qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), s->texinfo->texture->vbo.coord); - } - qglDrawRangeElements(GL_TRIANGLES, s->mesh->vbofirstvert, s->mesh->numvertexes, s->mesh->numindexes, GL_INDEX_TYPE, (index_t*)(s->mesh->vbofirstelement*sizeof(index_t))); - } - checkerror(); - - qglDisable(GL_POLYGON_OFFSET_FILL); - - GL_SelectVBO(0); - GL_SelectEBO(0); - - GL_MBind(1, 0); - qglDisable(GL_TEXTURE_2D); - qglDisable(GL_TEXTURE_GEN_S); - qglDisable(GL_TEXTURE_GEN_T); - qglDisable(GL_TEXTURE_GEN_R); - qglDisable(GL_TEXTURE_GEN_Q); - GL_MBind(0, 0); - qglDisable(GL_TEXTURE_GEN_S); - qglDisable(GL_TEXTURE_GEN_T); - qglDisable(GL_TEXTURE_GEN_R); - qglDisable(GL_TEXTURE_GEN_Q); - checkerror(); -#endif } @@ -1655,21 +1606,13 @@ static void Sh_WorldLightingPass(void) } } - - - -#pragma message("move to header") -void BE_BaseEntTextures(void); - /* draws faces facing the light Note: Backend mode must have been selected in advance, as must the light to light from */ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) { - mesh_t *meshchain, *surfmesh; - int tno, sno; - msurface_t *surf; + int tno; texture_t *tex; shadowmesh_t *sm; @@ -1681,21 +1624,8 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) { if (!sm->litsurfs[tno].count) continue; - meshchain = NULL; - tex = sm->litsurfs[tno].s[0]->texinfo->texture; - for (sno = 0; sno < sm->litsurfs[tno].count; sno++) - { - surf = sm->litsurfs[tno].s[sno]; -// if (surf->visframe == r_visframecount) - { - /*was visible this frame*/ - surfmesh = surf->mesh; - surfmesh->next = meshchain; - meshchain = surfmesh; - } - } - if (meshchain) - BE_DrawMeshChain(tex->shader, meshchain, &tex->vbo, &tex->shader->defaulttextures); + tex = cl.worldmodel->textures[tno]; + BE_DrawMesh_List(tex->shader, sm->litsurfs[tno].count, sm->litsurfs[tno].s, &tex->vbo, &tex->shader->defaulttextures); } BE_BaseEntTextures(); @@ -1709,8 +1639,8 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) - - +#pragma message "move to header" +void BE_PushOffsetShadow(qboolean foobar); #define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff @@ -1739,6 +1669,8 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) qglEnableClientState(GL_VERTEX_ARRAY); qglEnable(GL_VERTEX_ARRAY); + BE_PushOffsetShadow(true); + model = e->model; surf = model->surfaces+model->firstmodelsurface; for (i = 0; i < model->nummodelsurfaces; i++, surf++) @@ -1807,6 +1739,8 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) qglEnd(); } qglPopMatrix(); + + BE_PushOffsetShadow(false); } @@ -1819,6 +1753,8 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q int i; struct shadowmesh_s *sm; + BE_PushOffsetShadow(false); + sm = SHM_BuildShadowVolumeMesh(dl, lvis, vvis); if (!sm) Sh_DrawBrushModelShadow(dl, &r_worldentity); @@ -1848,19 +1784,13 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q { currententity = &cl_visedicts[i]; - if (currententity->flags & RF_NOSHADOW) + if (currententity->flags & (RF_NOSHADOW|Q2RF_BEAM)) continue; { if (currententity->keynum == dl->key && currententity->keynum) continue; } - - if (currententity->flags & Q2RF_BEAM) - { - R_DrawBeam(currententity); - continue; - } if (!currententity->model) continue; @@ -2065,7 +1995,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) } else if (qglActiveStencilFaceEXT) { - /*personally I prefer the ATI way*/ + /*personally I prefer the ATI way (nvidia method)*/ qglClearStencil(0); qglClear(GL_STENCIL_BUFFER_BIT); GL_CullFace(0); @@ -2089,7 +2019,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) qglActiveStencilFaceEXT(GL_FRONT); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglStencilFunc( GL_EQUAL, 0, ~0 ); -#pragma message("fixme: does this work properly on ati cards? cull front, but leave front as equals?") + qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); GL_CullFace(SHADER_CULL_FRONT); @@ -2150,27 +2080,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) qglDisable(GL_STENCIL_TEST); qglStencilFunc( GL_ALWAYS, 0, ~0 ); -/* - if (developer.ival) - { - PPL_RevertToKnownState(); - qglEnable(GL_BLEND); - qglBlendFunc(GL_ONE, GL_ONE); - qglDisable(GL_DEPTH_TEST); - qglDepthMask(0); - qglShadeModel (GL_SMOOTH); - qglDepthMask (0); - qglDisable (GL_TEXTURE_2D); - qglShadeModel (GL_SMOOTH); - qglEnable (GL_BLEND); - qglBlendFunc (GL_ONE, GL_ONE); - R_RenderDlight (dl); - qglEnable(GL_DEPTH_TEST); - qglShadeModel (GL_FLAT); - PPL_RevertToKnownState(); - } -*/ checkerror(); return true; } @@ -2231,7 +2141,10 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) //sets up the gl scissor (and culls to view) if (Sh_ScissorForBox(mins, maxs)) + { + bench.numscissorculled++; return; //was culled. + } bench.numlights++; @@ -2296,13 +2209,13 @@ void Sh_DrawLights(qbyte *vis) if (colour[0] < 0.001 && colour[1] < 0.001 && colour[2] < 0.001) continue; //just switch these off. - if (((!dl->die)?!r_shadow_realtime_world_shadows.value:!r_shadow_realtime_dlight_shadows.value) || dl->flags & LFLAG_NOSHADOWS) + if (((!dl->die)?!r_shadow_realtime_world_shadows.ival:!r_shadow_realtime_dlight_shadows.ival) || dl->flags & LFLAG_NOSHADOWS) { Sh_DrawShadowlessLight(dl, colour, vis); } else if (dl->flags & LFLAG_SHADOWMAP) { - Sh_DrawLameSpotLightShadowMap(dl, colour); + Sh_DrawShadowMapLight(dl, colour); } else { @@ -2313,9 +2226,9 @@ void Sh_DrawLights(qbyte *vis) qglDisable(GL_SCISSOR_TEST); BE_SelectMode(BEM_STANDARD, 0); - if (developer.value) - Con_Printf("%i lights drawn, %i frustum culled, %i pvs culled, %i scissor culled\n", bench.numlights, bench.numfrustumculled, bench.numpvsculled, bench.numscissorculled); - memset(&bench, 0, sizeof(bench)); +// if (developer.value) +// Con_Printf("%i lights drawn, %i frustum culled, %i pvs culled, %i scissor culled\n", bench.numlights, bench.numfrustumculled, bench.numpvsculled, bench.numscissorculled); +// memset(&bench, 0, sizeof(bench)); } #endif #endif diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 1be92763..592b4cb3 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -12,6 +12,7 @@ void (APIENTRY *qglClear) (GLbitfield mask); void (APIENTRY *qglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); void (APIENTRY *qglClearDepth) (GLclampd depth); void (APIENTRY *qglClearStencil) (GLint s); +void (APIENTRY *qglClipPlane) (GLenum plane, const GLdouble *equation); void (APIENTRY *qglColor3f) (GLfloat red, GLfloat green, GLfloat blue); void (APIENTRY *qglColor3ub) (GLubyte red, GLubyte green, GLubyte blue); void (APIENTRY *qglColor4f) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); @@ -200,6 +201,10 @@ static unsigned int gl_num_extensions; qboolean GL_CheckExtension(char *extname) { int i; + cvar_t *v = Cvar_Get(va("gl_ext_%s", extname), "1", 0, "GL Extensions"); + if (v && !v->ival) + return false; + if (gl_num_extensions && qglGetStringi) { for (i = 0; i < gl_num_extensions; i++) @@ -290,6 +295,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) gl_config.arb_texture_cube_map = false; gl_config.arb_shader_objects = false; + gl_config.ext_framebuffer_objects = false; gl_config.ext_texture_filter_anisotropic = 0; @@ -389,17 +395,19 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglUnlockArraysEXT = (void *)getglext("glUnlockArraysEXT"); } + /*various combiner features*/ gl_config.tex_env_combine = GL_CheckExtension("GL_EXT_texture_env_combine"); gl_config.env_add = GL_CheckExtension("GL_EXT_texture_env_add"); gl_config.nv_tex_env_combine4 = GL_CheckExtension("GL_NV_texture_env_combine4"); - gl_config.arb_texture_env_combine = GL_CheckExtension("GL_ARB_texture_env_combine"); gl_config.arb_texture_env_dot3 = GL_CheckExtension("GL_ARB_texture_env_dot3"); + gl_config.arb_texture_cube_map = GL_CheckExtension("GL_ARB_texture_cube_map"); if (gl_mtexarbable && gl_config.arb_texture_cube_map && gl_config.arb_texture_env_combine && gl_config.arb_texture_env_dot3 && !COM_CheckParm("-nobump") && gl_bump.value) gl_bumpmappingpossible = true; + /*vbos*/ if (GL_CheckExtension("GL_ARB_vertex_buffer_object")) { qglGenBuffersARB = (void *)getglext("glGenBuffersARB"); @@ -425,9 +433,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) // glslang //the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects. //but our code kinda requires both for clean workings. - if (GL_CheckExtension("GL_ARB_fragment_shader")) - if (GL_CheckExtension("GL_ARB_vertex_shader")) - if (GL_CheckExtension("GL_ARB_shader_objects")) + if (GL_CheckExtension("GL_ARB_fragment_shader") + && GL_CheckExtension("GL_ARB_vertex_shader") + && GL_CheckExtension("GL_ARB_shader_objects")) { gl_config.arb_shader_objects = true; qglCreateProgramObjectARB = (void *)getglext("glCreateProgramObjectARB"); @@ -450,8 +458,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglUniform1fARB = (void *)getglext("glUniform1fARB"); } - if (GL_CheckExtension("GL_ARB_fragment_shader")) + if (GL_CheckExtension("GL_EXT_framebuffer_object")) { + gl_config.ext_framebuffer_objects = true; qglGenFramebuffersEXT = (void *)getglext("glGenFramebuffersEXT"); qglDeleteFramebuffersEXT = (void *)getglext("glDeleteFramebuffersEXT"); qglBindFramebufferEXT = (void *)getglext("glBindFramebufferEXT"); @@ -603,6 +612,7 @@ void GL_Init(void *(*getglfunction) (char *name)) qglClearColor = (void *)getglcore("glClearColor"); qglClearDepth = (void *)getglcore("glClearDepth"); qglClearStencil = (void *)getglcore("glClearStencil"); + qglClipPlane = (void *)getglcore("glClipPlane"); qglColor3f = (void *)getglcore("glColor3f"); qglColor3ub = (void *)getglcore("glColor3ub"); qglColor4f = (void *)getglcore("glColor4f"); @@ -818,11 +828,6 @@ rendererinfo_t openglrendererinfo = { Surf_AddStain, Surf_LessenStains, - MediaGL_ShowFrameBGR_24_Flip, - MediaGL_ShowFrameRGBA_32, - MediaGL_ShowFrame8bit, - - RMod_Init, RMod_ClearAll, RMod_ForName, diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index f8413534..21f9a6b2 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -132,8 +132,6 @@ unsigned char vid_curpal[256*3]; HGLRC baseRC; HDC maindc; -glvert_t glv; - HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); @@ -199,6 +197,7 @@ void *getwglfunc(char *name) { FARPROC proc; TRACE(("dbg: getwglfunc: %s: getting\n", name)); + proc = GetProcAddress(hInstGL, name); if (!proc) { @@ -267,9 +266,12 @@ qboolean GLInitialise (char *renderer) if (!hInstGL) { + unsigned int emode; strcpy(opengldllname, "opengl32"); Con_DPrintf ("Loading renderer dll \"%s\"", opengldllname); + emode = SetErrorMode(SEM_FAILCRITICALERRORS); /*no annoying errors if they use glide*/ hInstGL = LoadLibrary(opengldllname); + SetErrorMode(emode); if (hInstGL) Con_DPrintf (" Success\n"); @@ -476,31 +478,29 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) if ((i = COM_CheckParm("-conwidth")) != 0) - vid.conwidth = Q_atoi(com_argv[i+1]); + vid.width = Q_atoi(com_argv[i+1]); else { - vid.conwidth = 640; + vid.width = 640; } - vid.conwidth &= 0xfff8; // make it a multiple of eight + vid.width &= 0xfff8; // make it a multiple of eight - if (vid.conwidth < 320) - vid.conwidth = 320; + if (vid.width < 320) + vid.width = 320; // pick a conheight that matches with correct aspect - vid.conheight = vid.conwidth*3 / 4; + vid.height = vid.width*3 / 4; if ((i = COM_CheckParm("-conheight")) != 0) - vid.conheight = Q_atoi(com_argv[i+1]); - if (vid.conheight < 200) - vid.conheight = 200; + vid.height = Q_atoi(com_argv[i+1]); + if (vid.height < 200) + vid.height = 200; - if (vid.conheight > info->height) - vid.conheight = info->height; - if (vid.conwidth > info->width) - vid.conwidth = info->width; - vid.width = vid.conwidth; - vid.height = vid.conheight; + if (vid.height > info->height) + vid.height = info->height; + if (vid.width > info->width) + vid.width = info->width; vid.numpages = 2; @@ -601,29 +601,27 @@ qboolean VID_SetFullDIBMode (rendererstate_t *info) if ((i = COM_CheckParm("-conwidth")) != 0) - vid.conwidth = Q_atoi(com_argv[i+1]); + vid.width = Q_atoi(com_argv[i+1]); else - vid.conwidth = 640; + vid.width = 640; - vid.conwidth &= 0xfff8; // make it a multiple of eight + vid.width &= 0xfff8; // make it a multiple of eight - if (vid.conwidth < 320) - vid.conwidth = 320; + if (vid.width < 320) + vid.width = 320; // pick a conheight that matches with correct aspect - vid.conheight = vid.conwidth*3 / 4; + vid.height = vid.width*3 / 4; if ((i = COM_CheckParm("-conheight")) != 0) - vid.conheight = Q_atoi(com_argv[i+1]); - if (vid.conheight < 200) - vid.conheight = 200; + vid.height = Q_atoi(com_argv[i+1]); + if (vid.height < 200) + vid.height = 200; - if (vid.conheight > info->height) - vid.conheight = info->height; - if (vid.conwidth > info->width) - vid.conwidth = info->width; - vid.width = vid.conwidth; - vid.height = vid.conheight; + if (vid.height > info->height) + vid.height = info->height; + if (vid.width > info->width) + vid.width = info->width; vid.numpages = 2; @@ -1781,21 +1779,24 @@ qboolean GLVID_Is8bit(void) { return is8bit; } -#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB void VID_Init8bitPalette(void) { +#ifdef GL_USE8BITTEX +#ifdef GL_EXT_paletted_texture +#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB + // Check for 8bit Extensions and initialize them. int i; char thePalette[256*3]; char *oldPalette, *newPalette; qglColorTableEXT = (void *)qwglGetProcAddress("glColorTableEXT"); - if (!qglColorTableEXT || !GL_CheckExtension("GL_EXT_shared_texture_palette") || COM_CheckParm("-no8bit")) + if (!qglColorTableEXT || !GL_CheckExtension("GL_EXT_shared_texture_palette") || COM_CheckParm("-no8bit")) return; Con_SafePrintf("8-bit GL extensions enabled.\n"); - qglEnable(GL_SHARED_TEXTURE_PALETTE_EXT); + qglEnable(GL_SHARED_TEXTURE_PALETTE_EXT); oldPalette = (char *) d_8to24rgbtable; //d_8to24table3dfx; newPalette = thePalette; for (i=0;i<256;i++) @@ -1808,6 +1809,9 @@ void VID_Init8bitPalette(void) qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette); is8bit = TRUE; + +#endif +#endif } void GLVID_DeInit (void) diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 353e35e3..c516595e 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -25,44 +25,40 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "shader.h" #include -static void R_CalcSkyChainBounds (msurface_t *s); +static void R_CalcSkyChainBounds (batch_t *s); static void GL_DrawSkyGrid (texture_t *tex); -static void GL_DrawSkySphere (msurface_t *fa); -static void GL_SkyForceDepth(msurface_t *fa); -static void GL_DrawSkyBox (texid_t *texnums, msurface_t *s); - -//static int skytexturenum; +static void GL_DrawSkySphere (batch_t *fa, shader_t *shader); +static void GL_SkyForceDepth(batch_t *fa); +static void GL_DrawSkyBox (texid_t *texnums, batch_t *s); static float speedscale; // for top sky and bottom sky -//static float skyrotate; -//static vec3_t skyaxis; - -//static qboolean usingskybox; - -//static msurface_t *warpface; - -//extern cvar_t r_skyboxname; extern cvar_t gl_skyboxdist; extern cvar_t r_fastsky; extern cvar_t r_fastskycolour; -//static char defaultskybox[MAX_QPATH]; -//static int skyprogram; -//static int skyprogram_time; -//static int skyprogram_eyepos; - -//static int waterprogram; -//static int waterprogram_time; - -static qboolean overrideskybox; -static texid_t overrideskyboxtex[6]; -//static vec3_t glskycolor; +static shader_t *forcedskyshader; +static shader_t *skyboxface; //========================================================= +void R_SetSky(char *skyname) +{ + if (*skyname) + forcedskyshader = R_RegisterCustom(va("skybox_%s", skyname), Shader_DefaultSkybox, NULL); + else + forcedskyshader = NULL; + + skyboxface = R_RegisterShader("skyboxface", + "{\n" + "{\n" + "map $diffuse\n" + "}\n" + "}\n" + ); +} /* ================= @@ -70,36 +66,45 @@ GL_DrawSkyChain ================= */ #ifdef GLQUAKE -static void R_DrawSkyBoxChain (msurface_t *s); -void R_DrawSkyChain (msurface_t *s) +void R_DrawSkyChain (batch_t *batch) { + shader_t *skyshader; texid_t *skyboxtex; - skyboxtex = s->texinfo->texture->shader->skydome->farbox_textures; + if (forcedskyshader) + skyshader = forcedskyshader; + else + skyshader = batch->shader; - R_CalcSkyChainBounds(s); + if (skyshader->skydome) + skyboxtex = skyshader->skydome->farbox_textures; + else + skyboxtex = NULL; -#ifdef GLQUAKE - if (qrenderer == QR_OPENGL) + if (qrenderer == QR_OPENGL && skyboxtex && TEXVALID(*skyboxtex)) { - GL_DrawSkyBox (skyboxtex, s); - GL_SkyForceDepth(s); + R_CalcSkyChainBounds(batch); + GL_DrawSkyBox (skyboxtex, batch); + + GL_SkyForceDepth(batch); return; } -#endif if (*r_fastsky.string) { - GL_DrawSkyGrid(s->texinfo->texture); - GL_SkyForceDepth(s); + R_CalcSkyChainBounds(batch); + + R_IBrokeTheArrays(); + GL_DrawSkyGrid(batch->texture); + R_IBrokeTheArrays(); + + GL_SkyForceDepth(batch); } else { - GL_DrawSkySphere(s); - GL_SkyForceDepth(s); + GL_DrawSkySphere(batch, skyshader); + GL_SkyForceDepth(batch); } - - R_IBrokeTheArrays(); } #endif @@ -119,7 +124,6 @@ static vec3_t skyclip[6] = { {1,0,1}, {-1,0,1} }; -static int c_sky; // 1 = s, 2 = t, 3 = 2048 static int st_to_vec[6][3] = @@ -163,8 +167,6 @@ static void DrawSkyPolygon (int nump, vec3_t vecs) int axis; float *vp; - c_sky++; - // decide which face it maps to VectorClear (v); for (i=0, vp=vecs ; itexturechain) + for (m = batch->firstmesh; m < batch->meshes; m++) { + mesh = batch->mesh[m]; //triangulate - for (i=2 ; imesh->numvertexes ; i++) + for (i=2 ; inumvertexes ; i++) { - VectorSubtract (fa->mesh->xyz_array[0], r_origin, verts[0]); - VectorSubtract (fa->mesh->xyz_array[i-1], r_origin, verts[1]); - VectorSubtract (fa->mesh->xyz_array[i], r_origin, verts[2]); + VectorSubtract (mesh->xyz_array[0], r_origin, verts[0]); + VectorSubtract (mesh->xyz_array[i-1], r_origin, verts[1]); + VectorSubtract (mesh->xyz_array[i], r_origin, verts[2]); ClipSkyPolygon (3, verts[0], 0); } } @@ -370,92 +370,6 @@ static int skymade; static index_t skysphere_element3i[skysphere_numtriangles * 3]; static float skysphere_texcoord2f[skysphere_numverts * 2]; -#ifdef D3DQUAKE -static float skysphere_d3dvertex[skysphere_numverts * 5]; -static d3d_animateskysphere(float time) -{ - int i; - float *d3dvert, *texcoord2f; - - d3dvert = skysphere_d3dvertex; - texcoord2f = skysphere_texcoord2f; - for (i = 0; i < skysphere_numverts; i++) - { - d3dvert[3] = time+*texcoord2f++; - d3dvert[4] = time+*texcoord2f++; - - d3dvert+=5; - } -} -static void d3d_skyspherecalc(int skytype) -{ //yes, this is basically stolen from DarkPlaces - int i, j; - index_t *e; - float a, b, x, ax, ay, v[3], length, *d3dvert, *texcoord2f; - float dx, dy, dz; - - float texscale; - - if (skymade == skytype+500) - return; - - skymade = skytype+500; - - if (skytype == 2) - texscale = 1/16.0f; - else - texscale = 1/1.5f; - - texscale*=3; - - dx = 16; - dy = 16; - dz = 16 / 3; - - d3dvert = skysphere_d3dvertex; - texcoord2f = skysphere_texcoord2f; - - for (j = 0;j <= skygridy;j++) - { - a = j * skygridyrecip; - ax = cos(a * M_PI * 2); - ay = -sin(a * M_PI * 2); - for (i = 0;i <= skygridx;i++) - { - b = i * skygridxrecip; - x = cos((b + 0.5) * M_PI); - v[0] = ax*x * dx; - v[1] = ay*x * dy; - v[2] = -sin((b + 0.5) * M_PI) * dz; - length = texscale / sqrt(v[0]*v[0]+v[1]*v[1]+(v[2]*v[2]*9)); - - *d3dvert++ = v[0]*1000; - *d3dvert++ = v[1]*1000; - *d3dvert++ = v[2]*1000; - - d3dvert+=2; - - *texcoord2f++ = v[0] * length; - *texcoord2f++ = v[1] * length; - } - } - e = skysphere_element3i; - for (j = 0;j < skygridy;j++) - { - for (i = 0;i < skygridx;i++) - { - *e++ = j * skygridx1 + i; - *e++ = j * skygridx1 + i + 1; - *e++ = (j + 1) * skygridx1 + i; - - *e++ = j * skygridx1 + i + 1; - *e++ = (j + 1) * skygridx1 + i + 1; - *e++ = (j + 1) * skygridx1 + i; - } - } -} -#endif - #ifdef GLQUAKE static vecV_t skysphere_vertex3f[skysphere_numverts]; static mesh_t skymesh; @@ -533,53 +447,17 @@ static void gl_skyspherecalc(int skytype) } } -static void GL_SkyForceDepth(msurface_t *fa) +static void GL_SkyForceDepth(batch_t *batch) { - vbo_t *v; - mesh_t *m; - if (!cls.allow_skyboxes) //allow a little extra fps. - {//Draw the texture chain to only the depth buffer. - v = &fa->texinfo->texture->vbo; - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, v->vboe); - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, v->vbocoord); - qglVertexPointer(3, GL_FLOAT, 0, v->coord); - qglDisable(GL_TEXTURE_2D); - - if (qglColorMask) - qglColorMask(0,0,0,0); - for (; fa; fa = fa->texturechain) - { - m = fa->mesh; - qglDrawRangeElements(GL_TRIANGLES, m->vbofirstvert, m->vbofirstvert+m->numvertexes, m->numindexes, GL_INDEX_TYPE, v->indicies+m->vbofirstelement); - } - if (qglColorMask) - qglColorMask(1,1,1,1); - - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - - R_IBrokeTheArrays(); + { + BE_SelectMode(BEM_DEPTHONLY, 0); + BE_DrawMesh_List(batch->shader, batch->meshes-batch->firstmesh, batch->mesh+batch->firstmesh, &batch->texture->vbo, &batch->shader->defaulttextures); + BE_SelectMode(BEM_STANDARD, 0); /*skys only render in standard mode anyway, so this is safe*/ } } -static void FTE_DEPRECATED GL_DrawAliasMesh (mesh_t *mesh, texid_t texnum) -{ - shader_t shader; - memset(&shader, 0, sizeof(shader)); - shader.numpasses = 1; - shader.passes[0].numMergedPasses = 1; - shader.passes[0].anim_frames[0] = texnum; - shader.passes[0].rgbgen = RGB_GEN_IDENTITY; - shader.passes[0].alphagen = ALPHA_GEN_IDENTITY; - shader.passes[0].shaderbits |= SBITS_MISC_DEPTHWRITE; - shader.passes[0].blendmode = GL_MODULATE; - shader.passes[0].texgen = T_GEN_SINGLEMAP; - - BE_DrawMeshChain(&shader, mesh, NULL, NULL); -} - -static void GL_DrawSkySphere (msurface_t *fa) +static void GL_DrawSkySphere (batch_t *batch, shader_t *shader) { extern cvar_t gl_maxdist; float time = cl.gametime+realtime-cl.gametimemark; @@ -594,36 +472,9 @@ static void GL_DrawSkySphere (msurface_t *fa) qglTranslatef(r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2]); qglScalef(skydist, skydist, skydist); -//draw in bulk? this is eeevil //FIXME: We should use the skybox clipping code and split the sphere into 6 sides. - if (fa->texinfo->texture->shader) - { //the shader route. - meshbuffer_t mb; - gl_skyspherecalc(2); - mb.infokey = -1; - mb.dlightbits = 0; - mb.entity = &r_worldentity; - mb.shader = fa->texinfo->texture->shader; - mb.fog = NULL; - mb.mesh = &skymesh; - R_PushMesh(mb.mesh, mb.shader->features); - R_RenderMeshBuffer(&mb, false); - } - else - { //the boring route. - gl_skyspherecalc(1); - qglMatrixMode(GL_TEXTURE); - qglPushMatrix(); - qglTranslatef(time*8/128, time*8/128, 0); - GL_DrawAliasMesh(&skymesh, fa->texinfo->texture->shader->defaulttextures.base); - qglColor4f(1,1,1,0.5); - qglEnable(GL_BLEND); - qglTranslatef(time*8/128, time*8/128, 0); - GL_DrawAliasMesh(&skymesh, fa->texinfo->texture->shader->defaulttextures.fullbright); - qglDisable(GL_BLEND); - qglPopMatrix(); - qglMatrixMode(GL_MODELVIEW); - } + gl_skyspherecalc(2); + BE_DrawMesh_Single(shader, &skymesh, NULL, &batch->shader->defaulttextures); qglPopMatrix(); } #endif @@ -631,19 +482,16 @@ static void GL_DrawSkySphere (msurface_t *fa) #ifdef GLQUAKE -static void GL_MakeSkyVec (float s, float t, int axis) +static void GL_MakeSkyVec (float s, float t, int axis, float *vc, float *tc) { - vec3_t v, b; + vec3_t b; int j, k; float skydist = gl_skyboxdist.value; extern cvar_t gl_maxdist; if (!skydist) { -// if (r_shadows.value || !gl_maxdist.value) -// skydist = 1000000; //inifite distance -// else - skydist = gl_maxdist.value * 0.577; + skydist = gl_maxdist.value * 0.577; } b[0] = s*skydist; @@ -654,9 +502,9 @@ static void GL_MakeSkyVec (float s, float t, int axis) { k = st_to_vec[axis][j]; if (k < 0) - v[j] = -b[-k - 1]; + vc[j] = -b[-k - 1]; else - v[j] = b[k - 1]; + vc[j] = b[k - 1]; } // avoid bilerp seam @@ -672,9 +520,8 @@ static void GL_MakeSkyVec (float s, float t, int axis) else if (t > 511.0/512) t = 511.0/512; - t = 1.0 - t; - qglTexCoord2f (s, t); - qglVertex3fv (v); + tc[0] = s; + tc[1] = 1.0 - t; } @@ -714,10 +561,7 @@ static void MakeSkyGridVec2 (float s, float t, int axis, vec3_t v) if (!skydist) { -// if (r_shadows.value || !gl_maxdist.value) -// skydist = 1000000; //inifite distance -// else - skydist = gl_maxdist.value * 0.577; + skydist = gl_maxdist.value * 0.577; } b[0] = s*skydist; @@ -819,10 +663,15 @@ R_DrawSkyBox */ static int skytexorder[6] = {0,2,1,3,4,5}; #ifdef GLQUAKE -static void GL_DrawSkyBox (texid_t *texnums, msurface_t *s) +static void GL_DrawSkyBox (texid_t *texnums, batch_t *s) { int i; + vecV_t skyface_vertex[4]; + vec2_t skyface_texcoord[4]; + index_t skyface_index[6] = {0, 1, 2, 0, 2, 3}; + mesh_t skyfacemesh = {0}; + if (cl.skyrotate) { for (i=0 ; i<6 ; i++) @@ -852,20 +701,25 @@ static void GL_DrawSkyBox (texid_t *texnums, msurface_t *s) if (cl.skyrotate) qglRotatef (cl.time * cl.skyrotate, cl.skyaxis[0], cl.skyaxis[1], cl.skyaxis[2]); + skyfacemesh.indexes = skyface_index; + skyfacemesh.st_array = skyface_texcoord; + skyfacemesh.xyz_array = skyface_vertex; + skyfacemesh.numindexes = 6; + skyfacemesh.numvertexes = 4; + for (i=0 ; i<6 ; i++) { if (skymins[0][i] >= skymaxs[0][i] || skymins[1][i] >= skymaxs[1][i]) continue; - GL_Bind (texnums[skytexorder[i]]); + GL_MakeSkyVec (skymins[0][i], skymins[1][i], i, skyface_vertex[0], skyface_texcoord[0]); + GL_MakeSkyVec (skymins[0][i], skymaxs[1][i], i, skyface_vertex[1], skyface_texcoord[1]); + GL_MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i, skyface_vertex[2], skyface_texcoord[2]); + GL_MakeSkyVec (skymaxs[0][i], skymins[1][i], i, skyface_vertex[3], skyface_texcoord[3]); - qglBegin (GL_QUADS); - GL_MakeSkyVec (skymins[0][i], skymins[1][i], i); - GL_MakeSkyVec (skymins[0][i], skymaxs[1][i], i); - GL_MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); - GL_MakeSkyVec (skymaxs[0][i], skymins[1][i], i); - qglEnd (); + skyboxface->defaulttextures.base = texnums[skytexorder[i]]; + BE_DrawMesh_Single(skyboxface, &skyfacemesh, NULL, &skyboxface->defaulttextures); } qglPopMatrix (); diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index a41305a6..4fc155d3 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -129,6 +129,7 @@ typedef struct { qboolean arb_texture_compression; // qboolean arb_fragment_program; qboolean arb_shader_objects; + qboolean ext_framebuffer_objects; qboolean ext_stencil_wrap; int ext_texture_filter_anisotropic; int maxtmus; //max texture units @@ -158,7 +159,7 @@ texid_t GL_FindTexture (char *identifier); texid_t GL_LoadTextureFB (char *identifier, int width, int height, qbyte *data, unsigned int flags); void GL_Upload8Pal24 (qbyte *data, qbyte *pal, int width, int height, unsigned int flags); - +/* typedef struct { float x, y, z; @@ -167,7 +168,7 @@ typedef struct } glvert_t; FTE_DEPRECATED extern glvert_t glv; - +*/ #endif // r_local.h -- private refresh defs @@ -187,7 +188,6 @@ FTE_DEPRECATED extern glvert_t glv; void R_TimeRefresh_f (void); -FTE_DEPRECATED texture_t *SWR_TextureAnimation (texture_t *base); #include "particles.h" @@ -220,7 +220,6 @@ extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; extern texture_t *r_notexture_mip; extern int d_lightstylevalue[256]; // 8.8 fraction of base light value -FTE_DEPRECATED extern qboolean envmap; extern texid_t netgraphtexture; // netgraph texture extern int gl_lightmap_format; @@ -293,24 +292,13 @@ void FTE_DEPRECATED R_BackendInit(void); void FTE_DEPRECATED R_IBrokeTheArrays(void); #endif -void R_DrawSkyChain (msurface_t *s); -texnums_t R_InitSky (texture_t *mt); + // // gl_warp.c // -#ifdef GLQUAKE -void FTE_DEPRECATED GL_SubdivideSurface (msurface_t *fa, float dividesize); -void FTE_DEPRECATED GL_EmitBothSkyLayers (msurface_t *fa); - -void R_DrawSkyBox (msurface_t *s); -void R_ForceSkyBox (void); -void R_AddSkySurface (msurface_t *fa); -#endif -#ifdef D3DQUAKE -void D3D7_DrawSkyChain (msurface_t *s); -void D3D9_DrawSkyChain (msurface_t *s); -#endif +void R_DrawSkyChain (batch_t *batch); /*called from the backend, and calls back into it*/ +texnums_t R_InitSky (texture_t *mt); /*generate q1 sky texnums*/ // // gl_draw.c @@ -323,6 +311,7 @@ void GL_Set2D (void); // // gl_rmain.c // +qboolean R_ShouldDraw(entity_t *e); qboolean R_CullBox (vec3_t mins, vec3_t maxs); #ifdef GLQUAKE qboolean R_CullSphere (vec3_t origin, float radius); @@ -378,23 +367,10 @@ void R_InitBloomTextures(void); // gl_rsurf.c // #ifdef GLQUAKE -FTE_DEPRECATED void R_DrawBrushModel (entity_t *e); - void GL_LoadShaders(void); #endif -//gl_ppl.c -FTE_DEPRECATED void PPL_DrawWorld (qbyte *viewvis); -FTE_DEPRECATED qboolean PPL_ShouldDraw(void); -FTE_DEPRECATED void RotateLightVector(const vec3_t *angles, const vec3_t origin, const vec3_t lightpoint, vec3_t result); - -// -// gl_refrag.c -// -void R_StoreEfrags (efrag_t **ppefrag); - - // // gl_ngraph.c // diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 9f9a60fc..8653f332 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -20,12 +20,14 @@ typedef enum { typedef enum { SHADER_SORT_NONE, - SHADER_SORT_SKY, SHADER_SORT_PORTAL, + SHADER_SORT_SKY, SHADER_SORT_OPAQUE, + SHADER_SORT_DECAL, + SHADER_SORT_SEETHROUGH, SHADER_SORT_BANNER, SHADER_SORT_UNDERWATER, - SHADER_SORT_DECAL, + SHADER_SORT_BLEND, SHADER_SORT_ADDITIVE, SHADER_SORT_NEAREST } shadersort_t; @@ -56,17 +58,6 @@ typedef struct float args[4]; // offset, amplitude, phase_offset, rate } shaderfunc_t; -typedef struct meshbuffer_s -{ - int infokey; // lightmap number or mesh number - unsigned int dlightbits; - entity_t *entity; - struct shader_s *shader; - mesh_t *mesh; - struct mfog_s *fog; -} meshbuffer_t; - - //tecture coordinate manipulation typedef struct { @@ -282,6 +273,7 @@ typedef struct { } polyoffset_t; struct shader_s { + int uses; int width; int height; int numpasses; @@ -292,6 +284,7 @@ struct shader_s byte_vec4_t fog_color; float fog_dist; + float portaldist; int numdeforms; deformv_t deforms[SHADER_DEFORM_MAX]; @@ -334,14 +327,14 @@ struct shader_s const char *genargs; meshfeatures_t features; - - int registration_sequence; + bucket_t bucket; }; extern shader_t *r_shaders; extern int be_maxpasses; +void R_UnloadShader(shader_t *shader); shader_t *R_RegisterPic (char *name); shader_t *R_RegisterShader (char *name, const char *shaderscript); shader_t *R_RegisterShader_Lightmap (char *name); @@ -351,10 +344,15 @@ shader_t *R_RegisterSkin (char *name); shader_t *R_RegisterCustom (char *name, shader_gen_t *defaultgen, const void *args); void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader); -cin_t *R_ShaderGetCinematic(char *name); +cin_t *R_ShaderGetCinematic(shader_t *s); +cin_t *R_ShaderFindCinematic(char *name); void Shader_DefaultSkinShell(char *shortname, shader_t *s, const void *args); -void Shader_DefaultBSP(char *shortname, shader_t *s, const void *args); +void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args); +void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args); +void Shader_DefaultBSPQ2(char *shortname, shader_t *s, const void *args); +void Shader_DefaultSkybox(char *shortname, shader_t *s, const void *args); +void Shader_DefaultCinematic(char *shortname, shader_t *s, const void *args); void Shader_DefaultScript(char *shortname, shader_t *s, const void *args); void Shader_DoReload(void); @@ -373,6 +371,7 @@ typedef enum BEM_STENCIL, //used for drawing shadow volumes to the stencil buffer. BEM_DEPTHDARK, //a quick depth pass. textures used only for alpha test. additive textures still shown as normal. BEM_LIGHT, //we have a valid light + BEM_SMAPLIGHTSPOT, //we have a spot light using a shadowmap BEM_SMAPLIGHT //we have a light using a shadowmap } backendmode_t; @@ -386,8 +385,10 @@ typedef enum //Select the current render mode and modifier flags void BE_SelectMode(backendmode_t mode, unsigned int flags); -//Draws an entire mesh chain from a VBO. vbo can be null, in which case the chain may be drawn without batching. -void BE_DrawMeshChain(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums); +/*Draws an entire mesh list from a VBO. vbo can be null, in which case the chain may be drawn without batching. + Rules for using a list: Every mesh must be part of the same VBO, shader, lightmap, and must have the same pointers set*/ +void BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums); +void BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums); //Asks the backend to invoke DrawMeshChain for each surface, and to upload lightmaps as required void BE_DrawWorld (qbyte *vis); @@ -407,10 +408,11 @@ void BE_UploadAllLightmaps(void); void BE_SubmitMeshes (void); //sets up gl for depth-only FIXME void BE_SetupForShadowMap(void); -//Generates shadow maps (called before anything is drawn in case it needs to clobber the normal view) -void Sh_GenShadowMaps (void); +//Called from shadowmapping code into backend +void BE_BaseEntTextures(void); //Draws lights, called from the backend void Sh_DrawLights(qbyte *vis); +void Sh_Shutdown(void); //Draws the depth of ents in the world near the current light void BE_BaseEntShadowDepth(void); //Sets the given light+colour to be the current one that everything is to be lit/culled by. diff --git a/engine/http/httpclient.c b/engine/http/httpclient.c index 975de52e..2a83c54b 100644 --- a/engine/http/httpclient.c +++ b/engine/http/httpclient.c @@ -225,7 +225,7 @@ static qboolean HTTP_DL_Work(struct dl_download *dl) if (*dl->localname) { FS_CreatePath(dl->localname, FS_GAME); - dl->file = FS_OpenVFS(dl->localname, "wb", FS_GAME); + dl->file = FS_OpenVFS(dl->localname, "w+b", FS_GAME); } else dl->file = FS_OpenTemp(); diff --git a/engine/qclib/hash.h b/engine/qclib/hash.h index 778e67a5..3eda7f6e 100644 --- a/engine/qclib/hash.h +++ b/engine/qclib/hash.h @@ -5,7 +5,7 @@ #ifndef HASH_H__ #define HASH_H__ -#define Hash_BytesForBuckets(b) (sizeof(bucket_t)*b) +#define Hash_BytesForBuckets(b) (sizeof(bucket_t*)*b) #define STRCMP(s1,s2) (((*s1)!=(*s2)) || strcmp(s1+1,s2+1)) //saves about 2-6 out of 120 - expansion of idea from fastqcc typedef struct bucket_s { diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 868e3310..966de4d8 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -500,7 +500,10 @@ char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) sprintf (line, "%s", PR_StringToNative(progfuncs, val->string)); break; case ev_entity: - sprintf (line, "entity %i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict)) ); +// if (val->edict >= maxedicts) + sprintf (line, "entity %i", val->edict); +// else +// sprintf (line, "entity %i", NUM_FOR_EDICT(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, val->edict)) ); break; case ev_function: if (!val->function) @@ -511,8 +514,13 @@ char *PR_ValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) sprintf (line, "Bad function"); else { - f = pr_progstate[(val->function & 0xff000000)>>24].functions + (val->function & ~0xff000000); - sprintf (line, "%i:%s()", (val->function & 0xff000000)>>24, f->s_name+progfuncs->stringtable); + if ((val->function &~0xff000000) >= pr_progs->numfunctions) + sprintf(line, "bad function %i:%i\n", (val->function & 0xff000000)>>24, val->function & ~0xff000000); + else + { + f = pr_progstate[(val->function & 0xff000000)>>24].functions + (val->function & ~0xff000000); + sprintf (line, "%i:%s()", (val->function & 0xff000000)>>24, f->s_name+progfuncs->stringtable); + } } } break; @@ -1166,7 +1174,7 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) break; if (!data) { - printf ("ED_ParseEntity: EOF without closing brace"); + printf ("ED_ParseEntity: EOF without closing brace\n"); return NULL; } @@ -1191,7 +1199,7 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) if (qcc_token[0] == '}') { - printf ("ED_ParseEntity: closing brace without data"); + printf ("ED_ParseEntity: closing brace without data\n"); return NULL; } @@ -2827,8 +2835,12 @@ retry: if (st16[i].op >= OP_CALL1 && st16[i].op <= OP_CALL8) { if (st16[i].b) + { hexencalling = true; - +#ifdef NOENDIAN + break; +#endif + } } } if (hexencalling) diff --git a/engine/qclib/pr_multi.c b/engine/qclib/pr_multi.c index 5a1ade75..7a47d3ce 100644 --- a/engine/qclib/pr_multi.c +++ b/engine/qclib/pr_multi.c @@ -231,7 +231,7 @@ int QC_RegisterFieldVar(progfuncs_t *progfuncs, unsigned int type, char *name, i { if (field[i].type != type) { - printf("Field type mismatch on \"%s\"\n", name); + printf("Field type mismatch on \"%s\". %i != %i\n", name, field[i].type, type); continue; } if (!progfuncs->fieldadjust && engineofs>=0) diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index 39c316e5..60e38e5a 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -1,5 +1,6 @@ #ifdef _WIN32 - + #define _CRT_SECURE_NO_WARNINGS + #define _CRT_NONSTDC_NO_WARNINGS #ifndef AVAIL_ZLIB #ifdef _MSC_VER //#define AVAIL_ZLIB diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 5656c842..cba08da5 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -742,7 +742,7 @@ pbool QCC_WriteData (int crc) // numfunctions++; } - else if (def->type->type == ev_field)// && !def->constant) + else if (def->type->type == ev_field && def->constant) { dd = &fields[numfielddefs]; numfielddefs++; diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 7423e406..abc93f73 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -479,7 +479,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) default: protocollen = sizeof(buffer); - Con_Printf("NQWriteByte: bad tempentity\n"); + Con_Printf("NQWriteByte: bad tempentity %i\n", data); PR_StackTrace(svprogfuncs); break; } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index fb642d21..55ec2017 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -520,7 +520,7 @@ void PR_LoadGlabalStruct(void) #define globalstring(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); #define globalvec(need,name) ((nqglobalvars_t*)pr_globals)->V_##name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->V_##name) SV_Error("Could not find export \""#name"\" in progs\n"); #define globalvec_(need,name) ((nqglobalvars_t*)pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); -#define globalfunc(need,name) ((nqglobalvars_t*)pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); +#define globalfunc(need,name) ((nqglobalvars_t*)pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0); if (need && !((nqglobalvars_t*)pr_globals)->name) {static func_t strippedout; strippedout = PR_FindFunction(svprogfuncs, #name, 0); if (strippedout) ((nqglobalvars_t*)pr_globals)->name = &strippedout; else SV_Error("Could not find function \""#name"\" in progs\n"); } // globalint(pad); globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about. globalint (true, other); @@ -624,7 +624,7 @@ void PR_LoadGlabalStruct(void) gfuncs.ClassChangeWeapon = PR_FindFunction(svprogfuncs, "ClassChangeWeapon", PR_ANY); gfuncs.RunClientCommand = PR_FindFunction(svprogfuncs, "SV_RunClientCommand", PR_ANY); - if (pr_no_playerphysics.value) + if (pr_no_playerphysics.ival) SV_PlayerPhysicsQC = 0; else SV_PlayerPhysicsQC = PR_FindFunction(svprogfuncs, "SV_PlayerPhysics", PR_ANY); @@ -3145,6 +3145,8 @@ static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) char *def = ""; if (!strcmp(str, "sv_maxairspeed")) def = "30"; + else if (!strcmp(str, "sv_jumpvelocity")) + def = "270"; else def = ""; @@ -8926,7 +8928,7 @@ void PF_checkpvs(progfuncs_t *prinst, struct globalvars_s *pr_globals) //and yeah, this is overkill what with the whole fat thing and all. sv.world.worldmodel->funcs.FatPVS(sv.world.worldmodel, viewpos, qcpvs, sizeof(qcpvs), false); - G_FLOAT(OFS_RETURN) = sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, (wedict_t*)ent, qcpvs); + G_FLOAT(OFS_RETURN) = sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &((wedict_t*)ent)->pvsinfo, qcpvs); } //entity(string match [, float matchnum]) matchclient = #241; @@ -9508,6 +9510,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs //DP_QC_WHICHPACK {"whichpack", PF_whichpack, 0, 0, 0, 503}, // #503 string(string filename) whichpack + //no 504 //DP_QC_URI_ESCAPE {"uri_escape", PF_uri_escape, 0, 0, 0, 510}, // #510 string(string in) uri_escape @@ -9519,7 +9522,11 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs //DP_QC_URI_GET {"uri_get", PF_uri_get, 0, 0, 0, 513}, // #513 float(string uril, float id) uri_get - //no 504 + {"tokenize_console",PF_tokenize_console,0, 0, 0, 514}, + {"argv_start_index",PF_argv_start_index,0, 0, 0, 515}, + {"argv_end_index", PF_argv_end_index, 0, 0, 0, 516}, + {"buf_cvarlist", PF_buf_cvarlist, 0, 0, 0, 517}, + {"cvar_description",PF_cvar_description,0, 0, 0, 518}, //end dp extras {"precache_vwep_model",PF_precache_vwep_model,0,0, 0, 532}, // #532 float(string mname) precache_vwep_model diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index 568a451b..c9ce1809 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -324,12 +324,12 @@ comextqcfields } comentvars_t; #endif -#define MAX_ENT_LEAFS 16 - -#if defined(ODE_STATIC) || defined(ODE_DYNAMIC) -#define USEODE 1 +#if defined(CSQC_DAT) || !defined(CLIENTONLY) + #if defined(ODE_STATIC) || defined(ODE_DYNAMIC) + #define USEODE 1 + #endif #endif #ifdef USEODE diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index d0332880..b2ab2b0c 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -53,9 +53,9 @@ void deleetstring(char *match, char *leet) *s = *s - 18 + '0'; else if (*s >= 'A' && *s <= 'Z') *s = *s - 'A' + 'a'; - else if (*s<' ' || *s == '~') + else if (*s == ' ' || *s == '~') continue; - s++; + s++; } *s = '\0'; @@ -891,6 +891,17 @@ void SV_FilterIP_f (void) return; } + nb = svs.bannedips; + while (nb) + { + if (NET_CompareAdr(nb->adr, banadr) && NET_CompareAdr(nb->adrmask, banmask)) + { + Con_Printf("%s is already banned\n", Cmd_Argv(1)); + break; + } + nb = nb->next; + } + // loop through clients and kick the ones that match for (i = 0, cl = svs.clients; i < sv.allocated_client_slots; i++, cl++) { diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 9fbeb197..1ee27b15 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -2126,7 +2126,7 @@ unsigned int Q2BSP_FatPVS(model_t *mod, vec3_t org, qbyte *buffer, unsigned int return SV_Q2BSP_FatPVS (mod, org, buffer, buffersize, add); } -qboolean Q2BSP_EdictInFatPVS(model_t *mod, wedict_t *ent, qbyte *pvs) +qboolean Q2BSP_EdictInFatPVS(model_t *mod, pvscache_t *ent, qbyte *pvs) { int i,l; if (!CM_AreasConnected (mod, clientarea, ent->areanum)) @@ -2446,13 +2446,18 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, continue; } - if (ent == clent) + if (ent->xv->viewmodelforclient) + { + if (ent->xv->viewmodelforclient != EDICT_TO_PROG(svprogfuncs, host_client->edict)) + continue; + pvsflags = PVSF_IGNOREPVS; + } + else if (ent == clent) { pvsflags = PVSF_IGNOREPVS; } else { - // ignore ents without visible models if (!ent->xv->SendEntity && (!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && !((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC)) continue; @@ -2483,11 +2488,7 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, else if ((pvsflags & PVSF_MODE_MASK) < PVSF_USEPHS) { //branch out to the pvs testing. - if (ent->xv->viewmodelforclient == EDICT_TO_PROG(svprogfuncs, clent)) - { - //unconditional - } - else if (ent->xv->tag_entity) + if (ent->xv->tag_entity) { edict_t *p = ent; int c = 10; @@ -2495,12 +2496,12 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, { p = EDICT_NUM(svprogfuncs, p->xv->tag_entity); } - if (!sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, (wedict_t*)p, pvs)) + if (!sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &((wedict_t*)p)->pvsinfo, pvs)) continue; } else { - if (!sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, (wedict_t*)ent, pvs)) + if (!sv.world.worldmodel->funcs.EdictInFatPVS(sv.world.worldmodel, &((wedict_t*)ent)->pvsinfo, pvs)) continue; } } @@ -2523,16 +2524,10 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, } } - - //fte's gib filters //DP_SV_NODRAWONLYTOCLIENT if (ent->xv->nodrawtoclient) //DP extension. if (ent->xv->nodrawtoclient == EDICT_TO_PROG(svprogfuncs, client->edict)) continue; - //DP_ENT_VIEWMODEL - if (ent->xv->viewmodelforclient) //only the one set sees it - if (ent->xv->viewmodelforclient != EDICT_TO_PROG(svprogfuncs, client->edict)) - continue; //DP_SV_DRAWONLYTOCLIENT if (ent->xv->drawonlytoclient) if (ent->xv->drawonlytoclient != EDICT_TO_PROG(svprogfuncs, client->edict)) @@ -2682,7 +2677,7 @@ void SV_Snapshot_Clear(packet_entities_t *pack) csqcnuments = 0; numnails = 0; } - + /* ============= SVQ3Q1_BuildEntityPacket diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 62ef0b01..d89a3e77 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -64,25 +64,25 @@ typedef struct { netadr_t adr; } sv_masterlist_t; sv_masterlist_t sv_masterlist[] = { - {MP_QUAKEWORLD, SCVARC("sv_master1", "", SV_Masterlist_Callback)}, - {MP_QUAKEWORLD, SCVARC("sv_master2", "", SV_Masterlist_Callback)}, - {MP_QUAKEWORLD, SCVARC("sv_master3", "", SV_Masterlist_Callback)}, - {MP_QUAKEWORLD, SCVARC("sv_master4", "", SV_Masterlist_Callback)}, - {MP_QUAKEWORLD, SCVARC("sv_master5", "", SV_Masterlist_Callback)}, - {MP_QUAKEWORLD, SCVARC("sv_master6", "", SV_Masterlist_Callback)}, - {MP_QUAKEWORLD, SCVARC("sv_master7", "", SV_Masterlist_Callback)}, - {MP_QUAKEWORLD, SCVARC("sv_master8", "", SV_Masterlist_Callback)}, + {MP_QUAKEWORLD, CVARC("sv_master1", "", SV_Masterlist_Callback)}, + {MP_QUAKEWORLD, CVARC("sv_master2", "", SV_Masterlist_Callback)}, + {MP_QUAKEWORLD, CVARC("sv_master3", "", SV_Masterlist_Callback)}, + {MP_QUAKEWORLD, CVARC("sv_master4", "", SV_Masterlist_Callback)}, + {MP_QUAKEWORLD, CVARC("sv_master5", "", SV_Masterlist_Callback)}, + {MP_QUAKEWORLD, CVARC("sv_master6", "", SV_Masterlist_Callback)}, + {MP_QUAKEWORLD, CVARC("sv_master7", "", SV_Masterlist_Callback)}, + {MP_QUAKEWORLD, CVARC("sv_master8", "", SV_Masterlist_Callback)}, - {MP_QUAKEWORLD, SCVARC("sv_qwmasterextra1", "qwmaster.ocrana.de:27000", SV_Masterlist_Callback)}, //german. admin unknown - {MP_QUAKEWORLD, SCVARC("sv_qwmasterextra2", "masterserver.exhale.de:27000", SV_Masterlist_Callback)}, //german. admin unknown - {MP_QUAKEWORLD, SCVARC("sv_qwmasterextra3", "kubus.rulez.pl:27000", SV_Masterlist_Callback)}, //poland. admin unknown - {MP_QUAKEWORLD, SCVARC("sv_qwmasterextra4", "master.quakeservers.net:27000", SV_Masterlist_Callback)}, //european. admin: raz0? - //{MP_QUAKEWORLD, SCVARC("sv_qwmasterextra5", "asgaard.morphos-team.net:27000", SV_Masterlist_Callback)}, //admin bigfoot + {MP_QUAKEWORLD, CVARC("sv_qwmasterextra1", "qwmaster.ocrana.de:27000", SV_Masterlist_Callback)}, //german. admin unknown + {MP_QUAKEWORLD, CVARC("sv_qwmasterextra2", "masterserver.exhale.de:27000", SV_Masterlist_Callback)}, //german. admin unknown + {MP_QUAKEWORLD, CVARC("sv_qwmasterextra3", "kubus.rulez.pl:27000", SV_Masterlist_Callback)}, //poland. admin unknown + {MP_QUAKEWORLD, CVARC("sv_qwmasterextra4", "master.quakeservers.net:27000", SV_Masterlist_Callback)}, //european. admin: raz0? + //{MP_QUAKEWORLD, CVARC("sv_qwmasterextra5", "asgaard.morphos-team.net:27000", SV_Masterlist_Callback)}, //admin bigfoot - {MP_DARKPLACES, SCVARC("sv_masterextra1", "ghdigital.com:27950", SV_Masterlist_Callback)}, //69.59.212.88 (admin: LordHavoc) - {MP_DARKPLACES, SCVARC("sv_masterextra2", "dpmaster.deathmask.net:27950", SV_Masterlist_Callback)}, //209.164.24.243 (admin: Willis) - {MP_DARKPLACES, SCVARC("sv_masterextra3", "dpmaster.tchr.no:27950", SV_Masterlist_Callback)}, // (admin: tChr) - {MP_NONE, SCVAR(NULL, NULL)} + {MP_DARKPLACES, CVARC("sv_masterextra1", "ghdigital.com:27950", SV_Masterlist_Callback)}, //69.59.212.88 (admin: LordHavoc) + {MP_DARKPLACES, CVARC("sv_masterextra2", "dpmaster.deathmask.net:27950", SV_Masterlist_Callback)}, //209.164.24.243 (admin: Willis) + {MP_DARKPLACES, CVARC("sv_masterextra3", "dpmaster.tchr.no:27950", SV_Masterlist_Callback)}, // (admin: tChr) + {MP_NONE, CVAR(NULL, NULL)} }; client_t *host_client; // current client @@ -112,102 +112,104 @@ extern cvar_t developer; extern cvar_t rcon_password; extern cvar_t password; #endif -cvar_t spectator_password = SCVARF("spectator_password", "", CVAR_NOUNSAFEEXPAND); // password for entering as a sepctator +cvar_t spectator_password = CVARF("spectator_password", "", CVAR_NOUNSAFEEXPAND); // password for entering as a sepctator -cvar_t allow_download = SCVAR("allow_download", "1"); -cvar_t allow_download_skins = SCVAR("allow_download_skins", "1"); -cvar_t allow_download_models = SCVAR("allow_download_models", "1"); -cvar_t allow_download_sounds = SCVAR("allow_download_sounds", "1"); -cvar_t allow_download_demos = SCVAR("allow_download_demos", "1"); -cvar_t allow_download_maps = SCVAR("allow_download_maps", "1"); -cvar_t allow_download_anymap = SCVAR("allow_download_pakmaps", "0"); -cvar_t allow_download_pakcontents = SCVAR("allow_download_pakcontents", "1"); -cvar_t allow_download_root = SCVAR("allow_download_root", "0"); -cvar_t allow_download_textures = SCVAR("allow_download_textures", "1"); -cvar_t allow_download_pk3s = SCVAR("allow_download_pk3s", "1"); -cvar_t allow_download_wads = SCVAR("allow_download_wads", "1"); -cvar_t allow_download_configs = SCVAR("allow_download_configs", "0"); +cvar_t allow_download = CVAR("allow_download", "1"); +cvar_t allow_download_skins = CVAR("allow_download_skins", "1"); +cvar_t allow_download_models = CVAR("allow_download_models", "1"); +cvar_t allow_download_sounds = CVAR("allow_download_sounds", "1"); +cvar_t allow_download_demos = CVAR("allow_download_demos", "1"); +cvar_t allow_download_maps = CVAR("allow_download_maps", "1"); +cvar_t allow_download_anymap = CVAR("allow_download_pakmaps", "0"); +cvar_t allow_download_pakcontents = CVAR("allow_download_pakcontents", "1"); +cvar_t allow_download_root = CVAR("allow_download_root", "0"); +cvar_t allow_download_textures = CVAR("allow_download_textures", "1"); +cvar_t allow_download_pk3s = CVAR("allow_download_pk3s", "1"); +cvar_t allow_download_wads = CVAR("allow_download_wads", "1"); +cvar_t allow_download_configs = CVAR("allow_download_configs", "0"); -cvar_t sv_public = SCVAR("sv_public", "0"); -cvar_t sv_listen_qw = FCVAR("sv_listen_qw", "sv_listen", "1", 0); -cvar_t sv_listen_nq = SCVAR("sv_listen_nq", "0"); -cvar_t sv_listen_dp = SCVAR("sv_listen_dp", "1"); -cvar_t sv_listen_q3 = SCVAR("sv_listen_q3", "0"); -cvar_t sv_reportheartbeats = SCVAR("sv_reportheartbeats", "1"); -cvar_t sv_highchars = SCVAR("sv_highchars", "1"); -cvar_t sv_loadentfiles = SCVAR("sv_loadentfiles", "1"); -cvar_t sv_maxrate = SCVAR("sv_maxrate", "10000"); -cvar_t sv_maxdrate = FCVAR("sv_maxdrate", "sv_maxdownloadrate", "10000", 0); -cvar_t sv_minping = SCVARF("sv_minping", "0", CVAR_SERVERINFO); +cvar_t sv_public = CVAR("sv_public", "0"); +cvar_t sv_listen_qw = CVARAF("sv_listen_qw", "1", "sv_listen", 0); +cvar_t sv_listen_nq = CVAR("sv_listen_nq", "0"); +cvar_t sv_listen_dp = CVAR("sv_listen_dp", "1"); +cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0"); +cvar_t sv_reportheartbeats = CVAR("sv_reportheartbeats", "1"); +cvar_t sv_highchars = CVAR("sv_highchars", "1"); +cvar_t sv_loadentfiles = CVAR("sv_loadentfiles", "1"); +cvar_t sv_maxrate = CVAR("sv_maxrate", "10000"); +cvar_t sv_maxdrate = CVARAF("sv_maxdrate", "10000", + "sv_maxdownloadrate", 0); +cvar_t sv_minping = CVARF("sv_minping", "0", CVAR_SERVERINFO); -cvar_t sv_bigcoords = SCVARF("sv_bigcoords", "", CVAR_SERVERINFO); +cvar_t sv_bigcoords = CVARF("sv_bigcoords", "", CVAR_SERVERINFO); -cvar_t sv_cullplayers_trace = SCVARF("sv_cullplayers_trace", "", CVAR_SERVERINFO); -cvar_t sv_cullentities_trace = SCVARF("sv_cullentities_trace", "", CVAR_SERVERINFO); -cvar_t sv_phs = SCVAR("sv_phs", "1"); -cvar_t sv_resetparms = SCVAR("sv_resetparms", "0"); +cvar_t sv_cullplayers_trace = CVARF("sv_cullplayers_trace", "", CVAR_SERVERINFO); +cvar_t sv_cullentities_trace = CVARF("sv_cullentities_trace", "", CVAR_SERVERINFO); +cvar_t sv_phs = CVAR("sv_phs", "1"); +cvar_t sv_resetparms = CVAR("sv_resetparms", "0"); -cvar_t sv_master = SCVAR("sv_master", "0"); -cvar_t sv_masterport = SCVAR("sv_masterport", "0"); +cvar_t sv_master = CVAR("sv_master", "0"); +cvar_t sv_masterport = CVAR("sv_masterport", "0"); -cvar_t sv_voicechat = SCVAR("sv_voicechat", "0"); //still development. -cvar_t sv_gamespeed = SCVAR("sv_gamespeed", "1"); -cvar_t sv_csqcdebug = SCVAR("sv_csqcdebug", "0"); -cvar_t sv_csqc_progname = SCVAR("sv_csqc_progname", "csprogs.dat"); +cvar_t sv_voicechat = CVAR("sv_voicechat", "0"); //still development. +cvar_t sv_gamespeed = CVAR("sv_gamespeed", "1"); +cvar_t sv_csqcdebug = CVAR("sv_csqcdebug", "0"); +cvar_t sv_csqc_progname = CVAR("sv_csqc_progname", "csprogs.dat"); #ifdef TCPCONNECT -cvar_t sv_port_tcp = SCVARC("sv_port_tcp", "", SV_Tcpport_Callback); +cvar_t sv_port_tcp = CVARC("sv_port_tcp", "", SV_Tcpport_Callback); #ifdef IPPROTO_IPV6 -cvar_t sv_port_tcp6 = SCVARC("sv_port_tcp6", "", SV_Tcpport6_Callback); +cvar_t sv_port_tcp6 = CVARC("sv_port_tcp6", "", SV_Tcpport6_Callback); #endif #endif -cvar_t sv_port = SCVARC("sv_port", "27500", SV_Port_Callback); +cvar_t sv_port = CVARC("sv_port", "27500", SV_Port_Callback); #ifdef IPPROTO_IPV6 -cvar_t sv_port_ipv6 = SCVARC("sv_port_ipv6", "27500", SV_PortIPv6_Callback); +cvar_t sv_port_ipv6 = CVARC("sv_port_ipv6", "27500", SV_PortIPv6_Callback); #endif #ifdef USEIPX -cvar_t sv_port_ipx = SCVARC("sv_port_ipx", "27500", SV_PortIPX_Callback); +cvar_t sv_port_ipx = CVARC("sv_port_ipx", "27500", SV_PortIPX_Callback); #endif -cvar_t pausable = SCVAR("pausable", "1"); +cvar_t pausable = CVAR("pausable", "1"); // // game rules mirrored in svs.info // -cvar_t fraglimit = SCVARF("fraglimit", "" , CVAR_SERVERINFO); -cvar_t timelimit = SCVARF("timelimit", "" , CVAR_SERVERINFO); -cvar_t teamplay = SCVARF("teamplay", "" , CVAR_SERVERINFO); -cvar_t samelevel = SCVARF("samelevel", "" , CVAR_SERVERINFO); -cvar_t maxclients = FCVAR("maxclients","sv_maxclients","8",CVAR_SERVERINFO); -cvar_t maxspectators = SCVARF("maxspectators", "8", CVAR_SERVERINFO); +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 maxclients = CVARAF("maxclients", "8", + "sv_maxclients", CVAR_SERVERINFO); +cvar_t maxspectators = CVARF("maxspectators", "8", CVAR_SERVERINFO); #ifdef SERVERONLY -cvar_t deathmatch = SCVARF("deathmatch", "1", CVAR_SERVERINFO); // 0, 1, or 2 +cvar_t deathmatch = CVARF("deathmatch", "1", CVAR_SERVERINFO); // 0, 1, or 2 #else -cvar_t deathmatch = SCVARF("deathmatch", "0", CVAR_SERVERINFO); // 0, 1, or 2 +cvar_t deathmatch = CVARF("deathmatch", "0", CVAR_SERVERINFO); // 0, 1, or 2 #endif -cvar_t coop = SCVARF("coop", "" , CVAR_SERVERINFO); -cvar_t skill = SCVARF("skill", "" , CVAR_SERVERINFO); // 0, 1, 2 or 3 -cvar_t spawn = SCVARF("spawn", "" , CVAR_SERVERINFO); -cvar_t watervis = SCVARF("watervis", "" , CVAR_SERVERINFO); -cvar_t rearview = SCVARF("rearview", "" , CVAR_SERVERINFO); -cvar_t allow_fish = SCVARF("allow_fish", "0", CVAR_SERVERINFO); -cvar_t allow_luma = SCVARF("allow_luma", "1", CVAR_SERVERINFO); -cvar_t allow_bump = SCVARF("allow_bump", "1", CVAR_SERVERINFO); -cvar_t allow_skybox = SCVARF("allow_skybox", "", CVAR_SERVERINFO); -cvar_t sv_allow_splitscreen = SCVARF("allow_splitscreen","",CVAR_SERVERINFO); -cvar_t fbskins = SCVARF("fbskins", "1", CVAR_SERVERINFO); //to get rid of lame fuhquake fbskins -cvar_t mirrors = SCVARF("mirrors", "" , CVAR_SERVERINFO); +cvar_t coop = CVARF("coop", "" , CVAR_SERVERINFO); +cvar_t skill = CVARF("skill", "" , CVAR_SERVERINFO); // 0, 1, 2 or 3 +cvar_t spawn = CVARF("spawn", "" , CVAR_SERVERINFO); +cvar_t watervis = CVARF("watervis", "" , CVAR_SERVERINFO); +cvar_t rearview = CVARF("rearview", "" , CVAR_SERVERINFO); +cvar_t allow_fish = CVARF("allow_fish", "0", CVAR_SERVERINFO); +cvar_t allow_luma = CVARF("allow_luma", "1", CVAR_SERVERINFO); +cvar_t allow_bump = CVARF("allow_bump", "1", CVAR_SERVERINFO); +cvar_t allow_skybox = CVARF("allow_skybox", "", CVAR_SERVERINFO); +cvar_t sv_allow_splitscreen = CVARF("allow_splitscreen","",CVAR_SERVERINFO); +cvar_t fbskins = CVARF("fbskins", "1", CVAR_SERVERINFO); //to get rid of lame fuhquake fbskins +cvar_t mirrors = CVARF("mirrors", "" , CVAR_SERVERINFO); -cvar_t sv_motd[] ={ SCVAR("sv_motd1", ""), - SCVAR("sv_motd2", ""), - SCVAR("sv_motd3", ""), - SCVAR("sv_motd4", "") }; +cvar_t sv_motd[] ={ CVAR("sv_motd1", ""), + CVAR("sv_motd2", ""), + CVAR("sv_motd3", ""), + CVAR("sv_motd4", "") }; -cvar_t sv_compatiblehulls = SCVAR("sv_compatiblehulls", "1"); +cvar_t sv_compatiblehulls = CVAR("sv_compatiblehulls", "1"); -cvar_t hostname = SCVARF("hostname","unnamed", CVAR_SERVERINFO); +cvar_t hostname = CVARF("hostname","unnamed", CVAR_SERVERINFO); -cvar_t secure = SCVARF("secure", "", CVAR_SERVERINFO); +cvar_t secure = CVARF("secure", "", CVAR_SERVERINFO); extern cvar_t sv_nomsec; @@ -1811,7 +1813,7 @@ client_t *SVC_DirectConnect(void) else maxpacketentities = MAX_STANDARD_PACKET_ENTITIES; - if (!sv_allow_splitscreen.value) + if (!sv_allow_splitscreen.ival) numssclients = 1; if (!(protextsupported & PEXT_SPLITSCREEN)) @@ -2012,14 +2014,14 @@ client_t *SVC_DirectConnect(void) if (!newcl) //client has no slot. It's possible to bipass this if server is loading a game. (or a duplicated qsocket) { // if at server limits, refuse connection - if ( maxclients.value > MAX_CLIENTS ) + if ( maxclients.ival > MAX_CLIENTS ) Cvar_SetValue (&maxclients, MAX_CLIENTS); - if (maxspectators.value > MAX_CLIENTS) + if (maxspectators.ival > MAX_CLIENTS) Cvar_SetValue (&maxspectators, MAX_CLIENTS); -// if (maxspectators.value + maxclients.value > MAX_CLIENTS) //maybe a server wishes to allow this sort of thing? -// Cvar_SetValue ("maxspectators", MAX_CLIENTS - maxspectators.value + maxclients.value); - if (svprogfuncs && ((spectator && spectators >= (int)maxspectators.value) - || (!spectator && clients >= (int)maxclients.value) +// if (maxspectators.ival + maxclients.value > MAX_CLIENTS) //maybe a server wishes to allow this sort of thing? +// Cvar_SetValue ("maxspectators", MAX_CLIENTS - maxspectators.ival + maxclients.ival); + if (svprogfuncs && ((spectator && spectators >= maxspectators.ival) + || (!spectator && clients >= maxclients.ival) || (clients + spectators >= sv.allocated_client_slots) )) { Con_Printf ("%s:full connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); @@ -4360,6 +4362,8 @@ void SV_Init (quakeparms_t *parms) // if (parms->memsize < MINIMUM_MEMORY) // SV_Error ("Only %4.1f megs of memory reported, can't execute game", parms->memsize / (float)0x100000); + Cvar_Init(); + Memory_Init (parms->membase, parms->memsize); Sys_Init(); diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 80dd9e92..40736aaf 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -681,7 +681,7 @@ dir_t *Sys_listdir (char *path, char *ext, qboolean usesorting) dir->files = (file_t*)(dir+1); dir->maxfiles = maxfiles; - Q_strncpyz(searchterm, va("%s/*.%s", path, ext), sizeof(searchterm)); + Q_strncpyz(searchterm, va("%s/*%s", path, ext), sizeof(searchterm)); COM_EnumerateFiles(searchterm, Sys_listdirFound, dir); return dir; @@ -706,23 +706,25 @@ void Sys_freedir(dir_t *dir) static void SV_DemoDir_Callback(struct cvar_s *var, char *oldvalue); -cvar_t sv_demoUseCache = SCVAR("sv_demoUseCache", ""); -cvar_t sv_demoCacheSize = SCVAR("sv_demoCacheSize", ""); -cvar_t sv_demoMaxDirSize = SCVAR("sv_demoMaxDirSize", "102400"); //so ktpro autorecords. -cvar_t sv_demoDir = SCVARC("sv_demoDir", "demos", SV_DemoDir_Callback); -cvar_t sv_demofps = SCVAR("sv_demofps", ""); -cvar_t sv_demoPings = SCVAR("sv_demoPings", ""); -cvar_t sv_demoNoVis = SCVAR("sv_demoNoVis", ""); -cvar_t sv_demoMaxSize = SCVAR("sv_demoMaxSize", ""); -cvar_t sv_demoExtraNames = SCVAR("sv_demoExtraNames", ""); +cvar_t sv_demoUseCache = CVAR("sv_demoUseCache", ""); +cvar_t sv_demoCacheSize = CVAR("sv_demoCacheSize", ""); +cvar_t sv_demoMaxDirSize = CVAR("sv_demoMaxDirSize", "102400"); //so ktpro autorecords. +cvar_t sv_demoDir = CVARC("sv_demoDir", "demos", SV_DemoDir_Callback); +cvar_t sv_demofps = CVAR("sv_demofps", ""); +cvar_t sv_demoPings = CVAR("sv_demoPings", ""); +cvar_t sv_demoNoVis = CVAR("sv_demoNoVis", ""); +cvar_t sv_demoMaxSize = CVAR("sv_demoMaxSize", ""); +cvar_t sv_demoExtraNames = CVAR("sv_demoExtraNames", ""); -cvar_t qtv_password = SCVAR("qtv_password", ""); -cvar_t qtv_streamport = FCVAR("qtv_streamport", "mvd_streamport", "0", 0); -cvar_t qtv_maxstreams = FCVAR("qtv_maxstreams", "mvd_maxstreams", "1", 0); +cvar_t qtv_password = CVAR( "qtv_password", ""); +cvar_t qtv_streamport = CVARAF( "qtv_streamport", "0", + "mvd_streamport", 0); +cvar_t qtv_maxstreams = CVARAF( "qtv_maxstreams", "1", + "mvd_maxstreams", 0); -cvar_t sv_demoPrefix = SCVAR("sv_demoPrefix", ""); -cvar_t sv_demoSuffix = SCVAR("sv_demoSuffix", ""); -cvar_t sv_demotxt = SCVAR("sv_demotxt", "1"); +cvar_t sv_demoPrefix = CVAR("sv_demoPrefix", ""); +cvar_t sv_demoSuffix = CVAR("sv_demoSuffix", ""); +cvar_t sv_demotxt = CVAR("sv_demotxt", "1"); void SV_WriteMVDMessage (sizebuf_t *msg, int type, int to, float time); @@ -2444,12 +2446,12 @@ void SV_UserCmdMVDList_f (void) float f; int i,j,show; - Con_Printf("available demos\n"); + SV_ClientPrintf(host_client, PRINT_HIGH, "available demos:\n"); dir = Sys_listdir(sv_demoDir.string, ".mvd", SORT_BY_DATE); list = dir->files; if (!list->name[0]) { - Con_Printf("no demos\n"); + SV_ClientPrintf(host_client, PRINT_HIGH, "no demos\n"); } for (i = 1; i <= dir->numfiles; i++, list++) @@ -2464,23 +2466,23 @@ void SV_UserCmdMVDList_f (void) for (d = demo.dest; d; d = d->nextdest) { if (!strcmp(list->name, d->name)) - Con_Printf("*%d: %s %dk\n", i, list->name, d->totalsize/1024); + SV_ClientPrintf(host_client, PRINT_HIGH, "*%d: %s %dk\n", i, list->name, d->totalsize/1024); } if (!d) - Con_Printf("%d: %s %dk\n", i, list->name, list->size/1024); + SV_ClientPrintf(host_client, PRINT_HIGH, "%d: %s %dk\n", i, list->name, list->size/1024); } } for (d = demo.dest; d; d = d->nextdest) dir->size += d->totalsize; - Con_Printf("\ndirectory size: %.1fMB\n",(float)dir->size/(1024*1024)); + SV_ClientPrintf(host_client, PRINT_HIGH, "\ndirectory size: %.1fMB\n",(float)dir->size/(1024*1024)); if (sv_demoMaxDirSize.value) { f = (sv_demoMaxDirSize.value*1024 - dir->size)/(1024*1024); if ( f < 0) f = 0; - Con_Printf("space available: %.1fMB\n", f); + SV_ClientPrintf(host_client, PRINT_HIGH, "space available: %.1fMB\n", f); } Sys_freedir(dir); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index d93af124..b462e80b 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -62,7 +62,8 @@ cvar_t pm_slidefix = SCVARF("pm_slidefix", "0", CVAR_SERVERINFO); cvar_t pm_slidyslopes = SCVARF("pm_slidyslopes", "0", CVAR_SERVERINFO); cvar_t pm_airstep = SCVARF("pm_airstep", "0", CVAR_SERVERINFO); cvar_t pm_walljump = SCVARF("pm_walljump", "0", CVAR_SERVERINFO); -cvar_t pm_stepheight = FCVAR("pm_stepheight", "sv_stepheight", "18", CVAR_SERVERINFO); +cvar_t pm_stepheight = CVARAF("pm_stepheight", "18", + "sv_stepheight", CVAR_SERVERINFO); extern cvar_t sv_nomsec; @@ -145,7 +146,7 @@ qboolean SV_RunThink (edict_t *ent) { float thinktime; - if (sv_nomsec.value>=2) //try and imitate nq as closeley as possible + if (sv_nomsec.ival>=2) //try and imitate nq as closeley as possible { thinktime = ent->v->nextthink; if (thinktime <= 0 || thinktime > sv.world.physicstime + host_frametime) @@ -745,13 +746,6 @@ qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) || check->v->movetype == MOVETYPE_NOCLIP) continue; - oldsolid = pusher->v->solid; - pusher->v->solid = SOLID_NOT; - block = (edict_t*)World_TestEntityPosition (&sv.world, (wedict_t*)check); - pusher->v->solid = oldsolid; - if (block) - continue; - // if the entity is standing on the pusher, it will definately be moved if ( ! ( ((int)check->v->flags & FL_ONGROUND) && @@ -770,6 +764,13 @@ qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) continue; } + oldsolid = pusher->v->solid; + pusher->v->solid = SOLID_NOT; + block = (edict_t*)World_TestEntityPosition (&sv.world, (wedict_t*)check); + pusher->v->solid = oldsolid; + if (block) + continue; + VectorCopy (check->v->origin, moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; @@ -1913,7 +1914,7 @@ void SV_RunNewmis (void) if (!realpr_nqglobal_struct.newmis) //newmis variable is not exported. return; - if (sv_nomsec.value >= 2) + if (sv_nomsec.ival >= 2) return; if (!pr_global_struct->newmis) diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index e46d7fe9..5924ae14 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1824,7 +1824,7 @@ void SV_UpdateToReliableMessages (void) if (progstype != PROG_QW) { if (!curgrav) - curgrav = 1; + curgrav = sv_gravity.value; if (!curspeed) curspeed = sv_maxspeed.value; } diff --git a/engine/server/sv_sys_unix.c b/engine/server/sv_sys_unix.c index cc2a89a8..eb714ee3 100644 --- a/engine/server/sv_sys_unix.c +++ b/engine/server/sv_sys_unix.c @@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include +#include #ifdef MULTITHREAD #include @@ -697,13 +698,13 @@ int main(int argc, char *argv[]) int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const char *, int, void *), void *parm) { -#include - DIR *dir, *dir2; + DIR *dir; char apath[MAX_OSPATH]; char file[MAX_OSPATH]; char truepath[MAX_OSPATH]; char *s; struct dirent *ent; + struct stat st; //printf("path = %s\n", gpath); //printf("match = %s\n", match); @@ -744,29 +745,25 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const if (!ent) break; if (*ent->d_name != '.') + { if (wildcmp(match, ent->d_name)) { - Q_snprintfz(file, sizeof(file), "%s/%s", gpath, ent->d_name); -//would use stat, but it breaks on fat32. + Q_snprintfz(file, sizeof(file), "%s/%s", truepath, ent->d_name); - if ((dir2 = opendir(file))) + if (stat(file, &st) == 0) { - closedir(dir2); - Q_snprintfz(file, sizeof(file), "%s%s/", apath, ent->d_name); -//printf("is directory = %s\n", file); + Q_snprintfz(file, sizeof(file), "%s%s%s", apath, ent->d_name, S_ISDIR(st.st_mode)?"/":""); + + if (!func(file, st.st_size, parm)) + { + closedir(dir); + return false; + } } else - { - Q_snprintfz(file, sizeof(file), "%s%s", apath, ent->d_name); -//printf("file = %s\n", file); - } - - if (!func(file, -2, parm)) - { - closedir(dir); - return false; - } + printf("Stat failed for \"%s\"\n", file); } + } } while(1); closedir(dir); diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 715eadc1..88774005 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -40,38 +40,40 @@ cvar_t cl_rollangle = SCVAR("cl_rollangle", "2.0"); extern cvar_t cl_rollspeed; extern cvar_t cl_rollangle; #endif -cvar_t sv_spectalk = SCVAR("sv_spectalk", "1"); +cvar_t sv_spectalk = SCVAR("sv_spectalk", "1"); cvar_t sv_mapcheck = SCVAR("sv_mapcheck", "1"); -cvar_t sv_antilag = SCVARF("sv_antilag", "0", CVAR_SERVERINFO); -cvar_t sv_antilag_frac = SCVARF("sv_antilag_frac", "1", CVAR_SERVERINFO); -cvar_t sv_cheatpc = SCVAR("sv_cheatpc", "125"); -cvar_t sv_cheatspeedchecktime = SCVAR("sv_cheatspeedchecktime", "30"); -cvar_t sv_playermodelchecks = SCVAR("sv_playermodelchecks", "1"); +cvar_t sv_antilag = SCVARF("sv_antilag", "0", CVAR_SERVERINFO); +cvar_t sv_antilag_frac = SCVARF("sv_antilag_frac", "1", CVAR_SERVERINFO); +cvar_t sv_cheatpc = SCVAR("sv_cheatpc", "125"); +cvar_t sv_cheatspeedchecktime = SCVAR("sv_cheatspeedchecktime", "30"); +cvar_t sv_playermodelchecks = SCVAR("sv_playermodelchecks", "1"); -cvar_t sv_cmdlikercon = SCVAR("sv_cmdlikercon", "0"); //set to 1 to allow a password of username:password instead of the correct rcon password. -cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server. -cvar_t cmd_gamecodelevel = SCVAR("cmd_gamecodelevel", "50"); //execution level which gamecode is told about (for unrecognised commands) +cvar_t sv_cmdlikercon = SCVAR("sv_cmdlikercon", "0"); //set to 1 to allow a password of username:password instead of the correct rcon password. +cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server. +cvar_t cmd_gamecodelevel = SCVAR("cmd_gamecodelevel", "50"); //execution level which gamecode is told about (for unrecognised commands) -cvar_t sv_nomsec = SCVAR("sv_nomsec", "0"); -cvar_t sv_edgefriction = FCVAR("sv_edgefriction", "edgefriction", "2", 0); +cvar_t sv_nomsec = SCVAR("sv_nomsec", "0"); +cvar_t sv_edgefriction = CVARAF("sv_edgefriction", "2", + "edgefriction", 0); -cvar_t sv_brokenmovetypes = SCVAR("sv_brokenmovetypes", "0"); +cvar_t sv_brokenmovetypes = SCVAR("sv_brokenmovetypes", "0"); -cvar_t sv_chatfilter = SCVAR("sv_chatfilter", "0"); +cvar_t sv_chatfilter = CVAR("sv_chatfilter", "0"); -cvar_t sv_floodprotect = SCVAR("sv_floodprotect", "1"); -cvar_t sv_floodprotect_messages = SCVAR("sv_floodprotect_messages", "4"); -cvar_t sv_floodprotect_interval = SCVAR("sv_floodprotect_interval", "4"); -cvar_t sv_floodprotect_silencetime = SCVAR("sv_floodprotect_silencetime", "10"); -cvar_t sv_floodprotect_suicide = SCVAR("sv_floodprotect_suicide", "1"); -cvar_t sv_floodprotect_sendmessage = FCVAR("sv_floodprotect_sendmessage", "floodprotmsg", "", 0); +cvar_t sv_floodprotect = CVAR("sv_floodprotect", "1"); +cvar_t sv_floodprotect_messages = CVAR("sv_floodprotect_messages", "4"); +cvar_t sv_floodprotect_interval = CVAR("sv_floodprotect_interval", "4"); +cvar_t sv_floodprotect_silencetime = CVAR("sv_floodprotect_silencetime", "10"); +cvar_t sv_floodprotect_suicide = CVAR("sv_floodprotect_suicide", "1"); +cvar_t sv_floodprotect_sendmessage = CVARAF("sv_floodprotect_sendmessage", "", + "floodprotmsg", 0); cvar_t votelevel = SCVAR("votelevel", "0"); cvar_t voteminimum = SCVAR("voteminimum", "4"); -cvar_t votepercent = SCVAR("votepercent", "-1"); -cvar_t votetime = SCVAR("votetime", "10"); +cvar_t votepercent = SCVAR("votepercent", "-1"); +cvar_t votetime = SCVAR("votetime", "10"); cvar_t pr_allowbutton1 = SCVARF("pr_allowbutton1", "1", CVAR_LATCH); extern cvar_t sv_minping; @@ -3572,7 +3574,6 @@ void Cmd_SetPos_f(void) World_LinkEdict (&sv.world, (wedict_t*)sv_player, false); } -void ED_ClearEdict (progfuncs_t *progfuncs, edict_t *e); void SV_SetUpClientEdict (client_t *cl, edict_t *ent) { extern int pr_teamfield; @@ -3879,6 +3880,7 @@ void SV_DisableClientsCSQC(void) #endif } +void SV_UserCmdMVDList_f (void); void SV_STFU_f(void) { char *msg; @@ -3954,7 +3956,7 @@ ucmd_t ucmds[] = {"setpos", Cmd_SetPos_f}, {"stopdownload", SV_StopDownload_f}, - {"demolist", SV_MVDList_f}, + {"demolist", SV_UserCmdMVDList_f}, {"demoinfo", SV_MVDInfo_f}, {NULL, NULL} @@ -4163,7 +4165,7 @@ void SVNQ_Spawn_f (void) } else { - memset (ent->v, 0, sv.world.edict_size); + ED_Clear(svprogfuncs, ent); ED_Spawned(ent, false); ent->v->colormap = NUM_FOR_EDICT(svprogfuncs, ent); @@ -5684,7 +5686,7 @@ haveannothergo: #endif if (!sv.paused) { - if (sv_nomsec.value) + if (sv_nomsec.ival) { cl->isindependant = false; if (!sv_player->v->fixangle) diff --git a/engine/server/svq2_game.c b/engine/server/svq2_game.c index d2ec50d1..93b6bcc6 100644 --- a/engine/server/svq2_game.c +++ b/engine/server/svq2_game.c @@ -629,6 +629,19 @@ static int VARGS SVQ2_AreaEdicts (vec3_t mins, vec3_t maxs, q2edict_t **list, in return WorldQ2_AreaEdicts(&sv.world, mins, maxs, list, maxcount, areatype); } +static model_t *SVQ2_GetCModel(world_t *w, int modelindex) +{ + if ((unsigned int)modelindex < MAX_MODELS) + return sv.models[modelindex]; + else + return NULL; +} + +void SVQ2_InitWorld(void) +{ + sv.world.GetCModel = SVQ2_GetCModel; +} + qboolean SVQ2_InitGameProgs(void) { volatile static game_import_t import; //volatile because msvc sucks @@ -646,7 +659,10 @@ qboolean SVQ2_InitGameProgs(void) } if (ge) + { + SVQ2_InitWorld(); return true; + } // calc the imports. import.multicast = SV_Multicast; @@ -732,6 +748,7 @@ qboolean SVQ2_InitGameProgs(void) return false; } + SVQ2_InitWorld(); ge->Init (); return true; diff --git a/engine/server/world.c b/engine/server/world.c index 6e619132..25d42dad 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -292,7 +292,7 @@ void World_TouchLinks (world_t *w, wedict_t *ent, areanode_t *node) } #ifdef Q2BSPS -void Q2BSP_FindTouchedLeafs(world_t *w, model_t *model, wedict_t *ent, float *mins, float *maxs) +void Q2BSP_FindTouchedLeafs(model_t *model, struct pvscache_s *ent, float *mins, float *maxs) { #define MAX_TOTAL_ENT_LEAFS 128 int leafs[MAX_TOTAL_ENT_LEAFS]; @@ -307,6 +307,9 @@ void Q2BSP_FindTouchedLeafs(world_t *w, model_t *model, wedict_t *ent, float *mi ent->areanum = 0; ent->areanum2 = 0; + if (!mins || !maxs) + return; + //get all leafs, including solids num_leafs = CM_BoxLeafnums (model, mins, maxs, leafs, MAX_TOTAL_ENT_LEAFS, &topnode); @@ -468,19 +471,12 @@ void World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers) // link to PVS leafs if (w->worldmodel) - w->worldmodel->funcs.FindTouchedLeafs_Q1(w, w->worldmodel, ent, ent->v->absmin, ent->v->absmax); -/* -#ifdef Q2BSPS - if (w->worldmodel->fromgame == fg_quake2 || w->worldmodel->fromgame == fg_quake3) - Q2BSP_FindTouchedLeafs(ent); - else -#endif - if (w->worldmodel->fromgame == fg_doom) { + if (ent->v->modelindex) + w->worldmodel->funcs.FindTouchedLeafs(w->worldmodel, &ent->pvsinfo, ent->v->absmin, ent->v->absmax); + else + w->worldmodel->funcs.FindTouchedLeafs(w->worldmodel, &ent->pvsinfo, NULL, NULL); } - else - Q1BSP_FindTouchedLeafs(ent); -*/ if (ent->v->solid == SOLID_NOT) return; @@ -1614,7 +1610,10 @@ static void World_ClipToLinks (world_t *w, areanode_t *node, moveclip_t *clip) if (touch == clip->passedict) continue; if (touch->v->solid == SOLID_TRIGGER || touch->v->solid == SOLID_LADDER) - Host_Error ("Trigger (%s) in clipping list", PR_GetString(w->progs, touch->v->classname)); + { + Con_Printf ("Trigger (%s) in clipping list\n", PR_GetString(w->progs, touch->v->classname)); + continue; + } if (clip->type & MOVE_LAGGED) { diff --git a/specs/browser.txt b/specs/browser.txt new file mode 100644 index 00000000..48b663aa --- /dev/null +++ b/specs/browser.txt @@ -0,0 +1,67 @@ + + + + + + Insert your 'no-plugin' text here. Be sure to include links to download a copy of one. + + + + + + + +Two objects. Yes, I know. Evil. But yeah. Firefox will ignore any objects with a classid, and internet exploder won't have a clue what it is if it doesn't have a classid. bah. +Yes, you need to specify the params twice. +You probably want to name them too. + +Any supported param is also supported as a field usable from javascript. There's no distinction between them. + +Supported fields/params. +bool running: true if active. false if its not running. setting this field will start up quake or shut it down. + +string startserver: the server that will be used when the engine starts up. +string server: the current server. if not running, maps to startserver instead. (server=foo; running = true; will result in the plugin going to that server in all cases) +string playername: the name cvar. requires running. +string skin: the string cvar. requires running. +string team: the team cvar. requires running. +string topcolor: the topcolor cvar. requires running +string bottomcolor: the topcolor cvar. requires running +string password: the password cvar. requires running +not supported. string spectator: the spectator cvar. requires running + +string mapsrc: the cl_download_mapsrc cvar. Should be empty or a url like: http://bigfoot.morphos-team.net/misc/quakemaps/ + if set, its a url that contains a load of bsp files that can be downloaded via http instead of grabbing them off the server. + +string fullscreen: vid_fullscreen. + +string datadownload: specifies a url to obtain mod data from. + Can contain multiple space-separated entries. + Each entry must have a pak or pk3 file name, followed by a colon, followed by a url that contains a zip file. + Each file should be moddir/pakname.pak for instance. +string game: specifies the actual game+mod to use. + The first entry can be: + quake/q1/qw: quake1 + quake2/q2: quake2 + quake3/q3: quake3 + halflife/hl: half-life (not really supported, but you may have a TC mod that just wants halflife maps) + hexen2/h2: hexen2 + nexuiz: nexuiz... moving target. sorry. + Any of the above will tell the plugin to hunt for the given game on the user's hard drive, and to then use that as a base dir, with the relevent game's basedir(s) loaded. + Any other option will be taken as only that base gamedir in an obscure place in the user's profile. + Additional gamedirs can be named, separated by spaces. These are additional mod dirs which will always be loaded despite the user's/server's choice of gamedir. + +string curver: read only. Returns the current version of the plugin. +string availver: Tells the plugin what the most recent version of the plugin is. Basically it will cause the plugin to show a warning whenever its not running. + +string splash: This is a url to a jpeg/png image to be shown when the plugin is not active. + +string stream: when set, (including via stream="foo";running=true;) this will direct the plugin to begin playing a qtv stream. +string map: when set and running, the plugin will change map and use its own server. overrides startserver when not running. + + + +stuff that may be supported at some point +connType: describes how the plugin should connect. join/qtv/observe/map + +join: server? gah diff --git a/specs/particles.txt b/specs/particles.txt new file mode 100644 index 00000000..8e76cae7 --- /dev/null +++ b/specs/particles.txt @@ -0,0 +1,273 @@ +Example: +r_part blah +{ + texture textures/particles/myimage.tga + tcoords 0 0 64 64 64 + die 2 + scalefactor 1 + scale 20 + alpha 0.5 + rgb 255 0 0 + rgbdelta 0 128 128 + spawnmode ball + spawnorg 32 +} + +will give transparent (0.5) red particles that will fade to fully white when they go fully transparent 2 seconds later. +they will spawn within a ball of 32 units radius. + + + + +texture + specifies to use an image named TEXTURENAME for this effect. + +tcoords [tscale] [rsmax] [rsstep] + specifies to use a subsection of the image. + if tscale is set, all units are divided by this. it is the virtual size of your texture. So a value of 1 means that your texture coords must be between 0 and 1. But if it properly matches your texture's size, the coords are in pixels. + if rsmax is present, each particle will use a random image. These images must be on a single row in your particle font. + rsstep specifies the stride (gap from one to the next) in your particle font, and is only needed if rsmax is present and greater than 1. + +rotationstart [max] + the particle will start with a rotation rotated between min and max. + if max is missing, the particle will always start with the min value. + +beamtexstep + only valid if the effect is a beam. + specifies the number of quake units per beam texture repitition. + +beamtexspeed + only valid if the effect is a beam. + controls how fast the texture scrolls on the beam. + +scale [max] + particles will start with a diameter of this many quake units. + actual scale will be randomly chosen between min and max (max defaults to equal min is missing) + +scalerand + obsolete + overrides the scale max value + actual scale will be now be randomly chosen between min and min+extra + +scalefactor + controls how the particle scales with distance. + 1 makes the particle scale the same as anything else + 0 makes the particle not change size no matter how far it is + +scaledelta + controls how the particle scales over time + specifies the change in the particle scale per second. + +step + trails/beams only + specifies the distance between each particle in the trail (or beam). + +count + point/box effects only (not trails or beams) + specifies how many particles are spawned per effect (some classic effects contain an extra scaler which is multiplied by the resulting value) + +alpha + specifies the initial alpha value of the effect + +alphadelta + specifies how much the alpha value of the effect changes per second (subtracted) + +die + specifies the maximum age of the particle + +diesubrand + specifies the maximum starting age of the particle. + basically the particle will live up to this much less time. the alpha value will also be aged by the amount chosen by this value + +randomvel [vert] + controls how fast the particle moves when it spawns. This works regardless of any requested velocities. + if vert is not specified, horiz is used instead. + +veladd + controls how much of the effect's spawn velocity is used, can be greater than 1, or negative. + +orgadd + biases how much to add to the starting origin relative to the requested velocity. + +friction <1> <2> <3> + FIXME + +gravity + amount that the particle's velocity changes per second, in quake units. + +clipbounce + how much of the particle's velocity to use if the particle is clipped. See cliptype. + Defaults to 0.8 + +cliptype + Specifies which new effect to spawn when the particle hits something. + The origin and velocity of the particle are used to spawn the new effect. + The clipbounce value is used as a scaler for the reflected velocity. + If the effect named is the effect itself, the particle will merely bounce, instead of spawning a new effect. + FIXME: make default to bounce if clipbounce is set without cliptype. + +clipcount + The scaler to use for the number of particles to spawn upon a clip event. + Only valid in conjunction with cliptype. + +assoc + Specifies another effect to spawn at the same time that this effect is spawned. + Thus allowing two sets of particles from one effect. + +inwater + Specifies a replacement effect to use when this one is spawned underwater. + assoc used is the replacement effect. the assoc value from the replaced effect is ignored. + +colorindex [rand] + Specifies a palette index to spawn the particle with. + The index used is between index and index+rand. + overrides the normal starting colours. + +colorrand + obsolete. + replaces the [rand] part of the colorindex setting. + +citracer + only valid if colorindex is set. + adds a palette index between 0 and 3, based on the particle index in the effect or trail. + +red +green +blue +rgb +rgb + Specifies the initial red, green, and/or blue values for each particle. + Fully opaque is 255 or above. + Values above 255 are valid, but will remain opaque until the value drops below 255 from the colour deltas. + +redrand +greenrand +bluerand +rgbrand +rgbrand + Specifies how much extra red, green, and/or blue there may be for particles. + The initial colour will be multiplied by this amount before addition. + Each componant is separately randomized. EG, red might add nothing, while the full green is added, and only half the blue. + Fully opaque is 255 or above. + +redrandsync +greenrandsync +bluerandsync +rgbrandsync +rgbrandsync + Specifies how much extra red, green, and/or blue there may be for particles. + The initial colour will be multiplied by this amount before addition. + Componants are syncronised. EG, if the full amount of red is added, the full amount of green and blue will also be added. + Fully opaque is 255 or above. + +reddelta +greendelta +bluedelta +rgbdelta +rgbdelta + Specifies how much the red, green, and/or blue values of each particle change over time. + The value 255 is the value required to go from opaque to invisible in 1 second. + +rgbdeltatime + Specifies for how long the particle may change colours for. After this many seconds, the particle may no longer change colours (delta becomes 0). + +rampmode + mode may be one of: + none: uses rgb+rand+sync+delta+scale+scaledelta values. + absolute: the ramp overrides all colour+scale values. The effect moves from one absolute ramp index to the next. + delta: uses rgb+rand+sync+scale, but not delta values. All delta values come from the colour ramp instead. + + if not none, the ramp index used is based upon the particle's age, its lifetime, and how many ramp elements there are. + +rampindexlist [ [idx3 ...]] + Scale used is the currently set scale value. + Specifies a set of palette index values to use for the effect as part of the effect's colour ramp. + +rampindex + Specifies an individual palette index value and particle scale to use for the effect as part of the effect's colour ramp + +ramp [alpha] [scale] + Specifies a ramp index in rgb terms, regardless of palette. + +stains + How much the effect discolours the wall upon impact. + The stained colour is based upon the colour of the particle upon impact. + +blend + mode may be one of: add, subtract, blendcolour/blendcolor, blend + if the texture used is actually a shader, this is ignored. + +spawnmode [arg1] [arg2] + This affects how particles are positioned when they first spawn, and their initial velocities. + for point effects, mode may be one of: + circle: particles spawn within a ball with uniform distance from the center + ball: particles spawn randomly within a ball. + telebox: matches quake's telebox + lavasplash: like chthon's lava splash + uniformcircle: particles are spawned in a circle with uniform distance between and from the center. z=0. + syncfield: particles spawn at predictable locations based upon time within a rough sphere. Only useful for effects that are regenerated+replaced every frame. + distball: + *default*: regular box. particles are spawned inside an axially aligned box. + + for trail effects, mode may be one of: + spiral: particles are given velocities perpendicular to the direction based on the distance moved. + tracer: particles spawn with alternating horizontal velocities (a wake effect). + *default*: particles spawn as a regular trail. + +spawnparam1 + obsolete + +spawnparam2 + obsolete + +up + the particle's origin is moved upwards by this amount + +type + How the particles look. + mode may be: + beam: valid only for trails. Particles form a single textured beam acting as nodes along it. + spark: particles are lines, their length depending upon their speed. + sparkfan: particles are non-planar triangle fans, their length depending upon their speed. + texturedspark: textured particles are aligned along their direction of movement, their length depending upon their speed. + decal: particles are spawned only upon bsp geometry. They are clipped by it. + *default*: Particles are regular, rotating, 2d images. + +isbeam + obsolete. + please use 'type beam' instead. + +spawntime +spawnchance + + +emit + Specifies the effect to periodically emit. + +emitinterval + Particles will not emit additional effects for this duration after emitting one. + +emitintervalrand + FIXME: fold into emitinterval + + +emitstart + Prevents the particle from emitting anything for this duration when it first spawns. + +spawnorg [vert] +spawnvel [vert] + +perframe + apply inverse frametime to count (causes emits to be per frame) + +averageout + average trail points from start to end, useful with t_lightning, etc + +nostate + Causes the particle system to ignore all state information. + +nospreadfirst + don't randomize org/vel for first generated particle + +nospreadlast + don't randomize org/vel for last generated particle