/** * @brief Allows switching boolean cvars between zero and not-zero from console */ static void Cvar_Switch_f (void) { const int c = Cmd_Argc(); if (c != 2 && c != 3) { Com_Printf("Usage: %s <variable> [u / s / a]\n", Cmd_Argv(0)); return; } if (c == 3) { const char* arg = Cmd_Argv(2); int flags = 0; while (arg[0] != '\0') { switch (arg[0]) { case 'u': flags |= CVAR_USERINFO; break; case 's': flags |= CVAR_SERVERINFO; break; case 'a': flags |= CVAR_ARCHIVE; break; default: Com_Printf("invalid flags %c given\n", arg[0]); break; } arg++; } Cvar_FullSet(Cmd_Argv(1), va("%i", !Cvar_GetInteger(Cmd_Argv(1))), flags); } else { Com_Printf("val: %i\n", Cvar_GetInteger(Cmd_Argv(1))); Cvar_Set(Cmd_Argv(1), "%i", !Cvar_GetInteger(Cmd_Argv(1))); } }
/** * @brief Reset cheat cvar values to default * @sa CL_SendCommand */ void Cvar_FixCheatVars (void) { if (!(Com_ServerState() && !Cvar_GetInteger("sv_cheats"))) return; for (cvar_t* var = cvarVars; var; var = var->next) { if (!(var->flags & CVAR_CHEAT)) continue; if (!var->defaultString) { Com_Printf("Cheat cvars: Cvar %s has no default value\n", var->name); continue; } if (Q_streq(var->string, var->defaultString)) continue; /* also remove the oldString value here */ Mem_Free(var->oldString); var->oldString = nullptr; Mem_Free(var->string); var->string = Mem_PoolStrDup(var->defaultString, com_cvarSysPool, 0); var->value = atof(var->string); var->integer = atoi(var->string); Com_Printf("'%s' is a cheat cvar - activate sv_cheats to use it.\n", var->name); } }
/** * @brief Starts a new skirmish game */ static void GAME_SK_Start_f (void) { char map[MAX_VAR]; mapDef_t *md; if (!chrDisplayList.num) { unsigned int i; /** @todo make the teamdef configurable */ const char *ugvTeamDefID = "phalanx_ugv_phoenix"; const char *name = Cvar_GetString("cl_equip"); const equipDef_t *ed = INV_GetEquipmentDefinitionByID(name); const size_t size = GAME_GetCharacterArraySize(); uint32_t maxSoldiers = Cvar_GetInteger("sv_maxsoldiersperplayer"); uint32_t ugvs = Cvar_GetInteger("cl_ugvs"); if (maxSoldiers <= 0) maxSoldiers = size; ugvs = min(ugvs, size - maxSoldiers); Com_Printf("Starting skirmish with %i soldiers and %i ugvs\n", maxSoldiers, ugvs); GAME_AutoTeam(name, maxSoldiers); for (i = 0; i < ugvs; i++) GAME_AppendTeamMember(i + maxSoldiers, ugvTeamDefID, ed); } else { Com_Printf("Using already loaded team with %i members\n", chrDisplayList.num); } assert(cls.currentSelectedMap >= 0); assert(cls.currentSelectedMap < MAX_MAPDEFS); md = Com_GetMapDefByIDX(cls.currentSelectedMap); if (!md) return; GAME_SK_SetMissionParameters(md); assert(md->map); Com_sprintf(map, sizeof(map), "map %s %s %s;", Cvar_GetInteger("mn_serverday") ? "day" : "night", md->map, md->param ? md->param : ""); /* prepare */ UI_InitStack(NULL, "singleplayermission", qtrue, qfalse); Cbuf_AddText(map); }
/** * @brief Use current skin for all team members onboard. */ static void CL_ChangeSkinForWholeTeam_f (void) { /* Get selected skin and fall back to default skin if it is not valid. */ const int newSkin = CL_FixActorSkinIDX(Cvar_GetInteger("mn_body_skin")); /* Apply new skin to all (shown/displayed) team-members. */ /** @todo What happens if a model of a team member does not have the selected skin? */ LIST_Foreach(chrDisplayList, character_t, chr) { /** @todo Get the skin id from the model by using the actorskin id */ /** @todo Or remove skins from models and convert character_t->skin to string */ chr->bodySkin = newSkin; } }
/** * @brief Change the skin of the selected actor. */ static void CL_ChangeSkin_f (void) { const int sel = cl_selected->integer; character_t* chr = (character_t*)LIST_GetByIdx(chrDisplayList, sel); if (chr == nullptr) { return; } const int newSkin = CL_FixActorSkinIDX(Cvar_GetInteger("mn_body_skin")); Cvar_SetValue("mn_body_skin", newSkin); /** @todo Get the skin id from the model by using the actorskin id */ /** @todo Or remove skins from models and convert character_t->skin to string */ chr->bodySkin = newSkin; }
/** * @sa AIR_IsAircraftOnGeoscape */ aircraft_t *UFO_GetNextOnGeoscape (aircraft_t *lastUFO) { aircraft_t* ufo = lastUFO; while ((ufo = UFO_GetNext(ufo)) != NULL) { if (UFO_IsUFOSeenOnGeoscape(ufo) #ifdef DEBUG || Cvar_GetInteger("debug_showufos") #endif ) return ufo; } return NULL; }
/** * @brief Take a screen shot of the map with the position of the radar * * We add 1 pixel into the border to easy check the result: * the screen shot must have a border of 1 black pixel */ static void CL_BattlescapeRadarGenerate_f (void) { const int border = 0; const char* mapName = Cvar_GetString("sv_mapname"); const int level = Cvar_GetInteger("cl_worldlevel"); const char* filename = nullptr; int x, y, width, height; CL_BattlescapeRadarMapInFrameBuffer(&x, &y, &width, &height); if (mapName) filename = va("%s_%i", mapName, level + 1); R_ScreenShot(x - border, y - border, width + border * 2, height + border * 2, filename, nullptr); }
/** * @brief Use current skin for all team members onboard. */ static void CL_ChangeSkinForWholeTeam_f (void) { int newSkin, i; /* Get selected skin and fall back to default skin if it is not valid. */ newSkin = Cvar_GetInteger("mn_body_skin"); newSkin = CL_FixActorSkinIDX(newSkin); /* Apply new skin to all (shown/displayed) team-members. */ /** @todo What happens if a model of a team member does not have the selected skin? */ for (i = 0; i < chrDisplayList.num; i++) { character_t *chr = chrDisplayList.chr[i]; assert(chr); /** @todo Get the skin id from the model by using the actorskin id */ /** @todo Or remove skins from models and convert character_t->skin to string */ chr->bodySkin = newSkin; } }
/** * @brief Change the skin of the selected actor. */ static void CL_ChangeSkin_f (void) { const int sel = cl_selected->integer; if (sel >= 0 && sel < chrDisplayList.num) { int newSkin = Cvar_GetInteger("mn_body_skin"); character_t *chr = chrDisplayList.chr[sel]; newSkin = CL_FixActorSkinIDX(newSkin); if (chr) { /** @todo Get the skin id from the model by using the actorskin id */ /** @todo Or remove skins from models and convert character_t->skin to string */ chr->bodySkin = newSkin; Cvar_SetValue("mn_body_skin", newSkin); Cvar_Set("mn_skinname", CL_GetTeamSkinName(newSkin)); } } }
static void Com_DeveloperSet_f (void) { int oldValue = Cvar_GetInteger("developer"); int newValue = oldValue; int i = 0; if (Cmd_Argc() == 2) { const char* debugLevel = Cmd_Argv(1); while (debugLevels[i].str) { if (Q_streq(debugLevel, debugLevels[i].str)) { if (oldValue & debugLevels[i].debugLevel) /* if it's already set... */ newValue &= ~debugLevels[i].debugLevel; /* ...reset it. */ else newValue |= debugLevels[i].debugLevel; break; } i++; } if (!debugLevels[i].str) { Com_Printf("No valid debug mode parameter\n"); return; } Cvar_SetValue("developer", newValue); Com_Printf("Currently selected debug print levels\n"); i = 0; while (debugLevels[i].str) { if (newValue & debugLevels[i].debugLevel) Com_Printf("* %s\n", debugLevels[i].str); i++; } } else { Com_Printf("Usage: %s <debug_level>\n", Cmd_Argv(0)); Com_Printf(" valid debug_levels are:\n"); while (debugLevels[i].str) { Com_Printf(" * %s\n", debugLevels[i].str); i++; } } }
void GL_RenderScene(camera_t *camera, vec3_t userpos, unsigned int sceneRenderFlags) { if (!world.cl_loaded || !gfx_render.integer) { //GL_2dMode(); return; } static float lasttime=0; camera_t sunCam; Pass basePass; worldLight_t rimLight; float lerp; float ambBoost = (vid_realbright.integer && gfx_GLSLQuality.integer<=1) ? vid_realbrightMult.value : 1.0f; basePass.setViewer(camera); scene_cam = camera; sunLight.origin[0] = -wr_sun_x.value; sunLight.origin[1] = -wr_sun_y.value; sunLight.origin[2] = -wr_sun_z.value; memset(&rimLight, 0, sizeof(worldLight_t)); M_MultVec3(sunLight.origin, -1, rimLight.origin); rimLight.type = LIGHT_DIRECTIONAL; //// SHADOW MAP RENDER //// //shadow pass, render to texture if(gfx_shadow.integer && gfx_shadowQuality.integer >= 1 && gfx_GLSLQuality.integer>1) { vec3_t wmin, wmax, sunLook; World_GetBounds(wmin, wmax); //SET_VEC3(sunLook, (wmax[0]-wmin[0])*.5f, (wmax[1]-wmin[1])*.5f, 0 * .5f); M_MultVec3(camera->viewaxis[AXIS_FORWARD], camera->farclip*0.05, sunLook); M_AddVec2(sunLook, camera->origin, sunLook); Cam_DefaultCamera(&sunCam, gfx_shadowSize.integer, gfx_shadowSize.integer, 2, 8192); if(wr_sun_z.value < 0) { SET_VEC3(sunCam.origin, -wr_sun_x.value, -wr_sun_y.value, -wr_sun_z.value); } else { SET_VEC3(sunCam.origin, wr_sun_x.value, wr_sun_y.value, wr_sun_z.value); } M_Normalize(sunCam.origin); M_MultVec3(sunCam.origin, wmax[0], sunCam.origin); sunCam.origin[0]+=sunLook[0]; sunCam.origin[1]+=sunLook[1]; M_SubVec3(sunLook, sunCam.origin, sunCam.viewaxis[AXIS_FORWARD]); M_GetAxisFromForwardVec(sunCam.viewaxis[AXIS_FORWARD], sunCam.viewaxis); sunCam.fovy = 50; sunCam.time = camera->time; sunCam.fog_far=100000; sunCam.fog_near=99999; sunCam.flags |= CAM_NO_SKY; //CSM setup if(gfx_shadowQuality.integer >= 2) { shadowSplit=0; for(int i=0;i<gfx_shadowQuality.integer;i++) { cascadedPass[i].setViewer(&sunCam); renderer.addPass(&cascadedPass[i]); } } else { shadowPass.setViewer(&sunCam); renderer.addPass(&shadowPass); } } else if( gfx_GLSLQuality.integer > 1 ) { renderer.addPass(&shadowPass); } if(gfx_postProcEnabled.integer && gfx_GLSLQuality.integer>1 && (gfx_depthNormalPass.integer || gfx_postSSAO.integer)) { zPass->setViewer(camera); renderer.addPass(zPass); } basePass.setDepthFunc(GL_LEQUAL); basePass.setDepthMask(true); basePass.clearDepth(true); if(gfx_GLSLQuality.integer>1 && gfx_postProcessing.integer) basePass.setTarget(screenPostTarget); else basePass.setTarget(glScreen); renderer.addPass(&basePass); //// BUILD RENDER LIST //// // sun/moon if(wr_sun_z.value < 0) { lerp = CLAMP(fabs(-1 - cos(wr_sun_phi.value)), 0, 1); //Console_Printf("phi %f lerp %f\n", wr_sun_phi.value, lerp); //setup sun light color and ambient sunLight.ambient[0] = obj_ambient_r.value*ambBoost; sunLight.ambient[1] = obj_ambient_g.value*ambBoost; sunLight.ambient[2] = obj_ambient_b.value*ambBoost; sunLight.color[0] = obj_light0_r.value*.9; sunLight.color[1] = obj_light0_g.value*.9; sunLight.color[2] = obj_light0_b.value*.98; rimLight.ambient[0] = 0; rimLight.ambient[1] = 0; rimLight.ambient[2] = 0; rimLight.color[0] = lerp*obj_light1_r.value*.9; rimLight.color[1] = lerp*obj_light1_g.value*.9; rimLight.color[2] = lerp*obj_light1_b.value*.98; } else { if(wr_sun_phi.value < 5.23f && wr_sun_phi.value > 1.0472f) lerp = CLAMP(fabs(1-cos(3*(M_PI-wr_sun_phi.value))), 0, 1); else lerp = 0; //Console_Printf("phi %f lerp %f cos %f\n", wr_sun_phi.value, lerp, cos(3*(M_PI-wr_sun_phi.value))); //the lights need to flip M_MultVec3(sunLight.origin, -1, sunLight.origin); M_MultVec3(rimLight.origin, -1, rimLight.origin); //setup moon light color and ambient sunLight.ambient[0] = obj_ambient_r.value*ambBoost; sunLight.ambient[1] = obj_ambient_g.value*ambBoost; sunLight.ambient[2] = obj_ambient_b.value*ambBoost; sunLight.color[0] = obj_light1_r.value*.9; sunLight.color[1] = obj_light1_g.value*.9; sunLight.color[2] = obj_light1_b.value*.98; rimLight.ambient[0] = 0; rimLight.ambient[1] = 0; rimLight.ambient[2] = 0; rimLight.color[0] = lerp*obj_light0_r.value*.9; rimLight.color[1] = lerp*obj_light0_g.value*.9; rimLight.color[2] = lerp*obj_light0_b.value*.98; } renderer.addLight(&sunLight, NULL, 0); renderer.addLight(&rimLight, NULL, 0); // The deal here is rather than changing the code in scene.cpp to support the // new renderer, we just "import" all the scene data //// SCENE DATA //// lightCount = 0; //objects scenelist_t *list; for (list = scenelist; list; list = list->next) { //if(list->cull) // continue; switch (list->obj.objtype) { case OBJTYPE_MODEL: GL_AddModelToLists(&list->obj); break; case OBJTYPE_LIGHT: GL_AddLight(0, &list->obj); break; default: break; } } //polys scenefacelist_t *flist; for (flist = scenefacelist; flist; flist = flist->next) { renderer.addPoly(flist, NULL, flist->shader); } //decals for (flist = scenefacelist_decals; flist; flist = flist->next) { renderer.addPoly(flist, NULL, flist->shader); } //lights scenelightlist_t *llist; for (llist = scenelightlist; llist; llist = llist->next) { worldLight_t *l = &worldlights[lightCount++]; M_CopyVec3(llist->light.color, l->color); M_CopyVec3(llist->light.pos, l->origin); renderer.addLight(l, NULL, 0); } //// END SCENE DATA //// //// ENVIRO //// if(!(camera->flags & CAM_NO_WORLD)) { //terrain if (!(scene_cam->flags & CAM_NO_TERRAIN)) renderer.addCustomListItem(&terrainItem, false); //sprites for (std::list<scenelist_t*>::iterator itr = spritelist.begin(); itr != spritelist.end(); itr++) { scenelist_t *sprite = *itr; renderer.addSprite(sprite, &sprite->obj, sprite->obj.shader); } //clouds (at the back) if(gfx_sky.integer) { renderer.addCustomListItem(&cloudsItem, false); } if(gfx_water.integer) { waterItem.set(NULL,NULL,0); renderer.addCustomListItem(&waterItem, false); } //sky if (gfx_sky.integer) { if(Cvar_GetInteger("tl_suntod") <= 1440) sky.setTimeofDay(Cvar_GetValue("tl_suntod")/1440.0f); else sky.setTimeofDay((Cvar_GetValue("tod_sunminute"))/1440.0f); //renderer.addListItem(&clouds, false); renderer.addCustomListItem(&sky, false); } //// FX LAYER //// //polys for (flist = scenefxfacelist; flist; flist = flist->next) { renderer.addPolyFX(flist, NULL, flist->shader); } //decals for (flist = scenefxfacelist_decals; flist; flist = flist->next) { renderer.addPolyFX(flist, NULL, flist->shader); } //sprites for (std::list<scenelist_t*>::iterator itr = spritefxlist.begin(); itr != spritefxlist.end(); itr++) { scenelist_t *sprite = *itr; renderer.addSpriteFX(sprite, &sprite->obj, sprite->obj.shader); } } //// RENDER //// renderer.render(camera->time-lasttime); lasttime = camera->time; }
/** * @brief Draws weather effects */ void Weather::render (void) { /* Don't play the weather particles if the user doesn't want them */ if (!Cvar_GetInteger("cl_particleweather")) { return; } GLfloat prtPos[3 * 4 * Weather::MAX_PARTICLES]; GLfloat prtTexcoord[2 * 4 * Weather::MAX_PARTICLES]; GLushort prtIndex[3 * 2 * Weather::MAX_PARTICLES]; size_t prtCount = 0; //const float splashTimeScale = 0.001f / splashTime; /* from msec to 1/sec units, so division is done only once per frame */ /** @todo shadowcasting at least for the sunlight */ #if 0 // disabled because of bizarre colors vec4_t prtColor = {color[0] * (refdef.ambientColor[0] + refdef.sunDiffuseColor[0]), color[1] * (refdef.ambientColor[1] + refdef.sunDiffuseColor[1]), color[2] * (refdef.ambientColor[2] + refdef.sunDiffuseColor[2]), color[3]}; #else vec_t prtBrightness = VectorLength(refdef.ambientColor) + VectorLength(refdef.sunDiffuseColor); /** @todo proper color to brightness mapping */ vec4_t prtColor = {color[0] * prtBrightness, color[1] * prtBrightness, color[2] * prtBrightness, color[3]}; /* alpha is not to be scaled */ #endif for (size_t i = 0; i < Weather::MAX_PARTICLES; i++) { Weather::particle &prt = particles[i]; if (prt.ttl < 0) continue; /* if particle is alive, construct a camera-facing quad */ GLfloat x, y, z; GLfloat dx, dy, dz; GLfloat thisParticleSize = particleSize; if (prt.vz == 0 && splashTime > 0) { /* splash particle, do zoom and other things */ /** @todo alpha decay */ const float splashFactor = prt.ttl / 500.0f;//1.0f - prt.ttl * splashTimeScale; thisParticleSize *= (splashSize - 1.0f) * splashFactor + 1.0f; dx = dy = thisParticleSize; } else { dx = i & 1 ? thisParticleSize* 2 : thisParticleSize; dy = i & 1 ? thisParticleSize : thisParticleSize * 2 ; /** @todo make a proper projection instead of this hack */ } x = prt.x; y = prt.y; z = prt.z; dz = smearLength * prt.vz * 0.5; /** @todo should use proper velocity vector ... or maybe not */ /* construct a particle geometry; */ GLfloat *pos = &prtPos[3 * 4 * prtCount]; GLfloat *texcoord = &prtTexcoord[2 * 4 * prtCount]; GLushort *idx = &prtIndex[3 * 2 * prtCount]; /** @todo actually rotate billboard in the correct position */ pos[0] = x - dx; pos[1] = y - dy; pos[2] = z + dz * 2; pos[3] = x + dx; pos[4] = y - dy; pos[5] = z + dz *2; pos[6] = x + dx; pos[7] = y + dy; pos[8] = z; pos[9] = x - dx; pos[10] = y + dy; pos[11] = z; texcoord[0] = 0; texcoord[1] = 0; /* upper left vertex */ texcoord[2] = 1.0f; texcoord[3] = 0; /* upper right vertex */ texcoord[4] = 1.0f; texcoord[5] = 1.0f; /* bottom right vertex */ texcoord[6] = 0; texcoord[7] = 1.0f; /* bottom left vertex */ idx[0] = 4 * prtCount; idx[1] = 4 * prtCount + 1; idx[2] = 4 * prtCount + 2; idx[3] = 4 * prtCount + 2; idx[4] = 4 * prtCount + 3; idx[5] = 4 * prtCount; prtCount++; } if (prtCount < 1) return; /* draw the generated array */ R_Color(prtColor); glBindTexture(GL_TEXTURE_2D, wpTexture()); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, prtPos); R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, prtTexcoord); R_EnableBlend(true); glDrawElements(GL_TRIANGLES, prtCount * 3 * 2, GL_UNSIGNED_SHORT, prtIndex); R_EnableBlend(false); R_ResetArrayState(); R_Color(nullptr); refdef.batchCount++; }
/** * @brief Updates weather for the time passed; handles particle creation/removal automatically */ void Weather::update (int milliseconds) { /* Don't play the weather particles if the user doesn't want them */ if (!Cvar_GetInteger("cl_particleweather")) { /* This makes weather look very weird if it is enabled mid-battle */ /* clearParticles(); */ return; } size_t dead = 0; /* physics: check for ttl and move live particles */ for (size_t i = 0; i < Weather::MAX_PARTICLES; i++) { Weather::particle &prt = particles[i]; if (prt.ttl < 0) { dead++; continue; } else { /** @todo creates vanishing-before-impact particles at low framerates -- should improve that somehow */ int restOfLife = prt.ttl -= milliseconds; if (restOfLife < 0) { if (fabs(prt.vz) < 0.001f || splashTime < 1) { /* either no splash or is a splash particle dying */ dead++; continue; } /* convert it into splash particle */ /* technically, we should complete the last frame of movement, but with current particle types it looks good even without it */ prt.vz = 0; prt.vx = 0; prt.vy = 0; prt.ttl += splashTime; } } /* if we got so far, particle is alive and probably needs a physics update */ const int timeAfterUpdate = prt.timeout -= milliseconds; const float moveDuration = milliseconds * 0.001f; prt.x += prt.vx * moveDuration; prt.y += prt.vy * moveDuration; prt.z += prt.vz * moveDuration; if (timeAfterUpdate > 0) { /* just move linearly */ continue; } /* alter motion vector */ /** @todo */ } /* create new ones in place of dead */ if (dead) { const float windX = cos(windDirection) * (windStrength + crand() * windTurbulence); const float windY = sin(windDirection) * (windStrength + crand() * windTurbulence); AABB weatherZone; /** < extents of zone in which weather particles will be rendered */ weatherZone = cl.mapData->mapBox; weatherZone.expandXY(256); weatherZone.maxs[2] += 512; Line prtPath; if (dead > 200) dead = 200; /* avoid creating too much particles in the single frame, it could kill the low-end hardware */ int debugCreated = 0; for (size_t i = 0; dead && i < Weather::MAX_PARTICLES && i < weatherStrength * Weather::MAX_PARTICLES; i++) { Weather::particle &prt = particles[i]; if (prt.ttl >= 0) continue; prt.x = (frand() * (weatherZone.getMaxX() - weatherZone.getMinX())) + weatherZone.getMinX(); prt.y = (frand() * (weatherZone.getMaxY() - weatherZone.getMinY())) + weatherZone.getMinY(); prt.z = weatherZone.getMaxZ(); prt.vx = windX; prt.vy = windY; prt.vz = -fallingSpeed * (frand() * 0.2f + 0.9f); float lifeTime = (weatherZone.getMaxZ() - weatherZone.getMinZ()) / -prt.vz; /* default */ VectorSet(prtPath.start, prt.x, prt.y, prt.z); VectorSet(prtPath.stop, prt.x + prt.vx * lifeTime, prt.y + prt.vy * lifeTime, prt.z + prt.vz * lifeTime); trace_t trace = CL_Trace(prtPath, AABB::EMPTY, nullptr, nullptr, MASK_SOLID, cl.mapMaxLevel - 1); /* find the collision point */ lifeTime *= trace.fraction; prt.ttl = 1000 * lifeTime; /* convert to milliseconds */ prt.timeout = prt.ttl + 1000000; /** @todo proper code for physics */ debugCreated++; dead--; } } #if 0 if (debugCreated) Com_Printf("created %i weather particles\n", debugCreated); #endif }