/** * @return @c true if are a compatible client and nothing else must be downloaded or no downloads are still running, * @c false if the start of the match must get a little bit postponed (running downloads). * @note throws ERR_DISCONNECT if we are not compatible to the server */ static bool CL_CanMultiplayerStart (void) { const int day = CL_GetConfigStringInteger(CS_LIGHTMAP); const char* serverVersion = CL_GetConfigString(CS_VERSION); /* checksum doesn't match with the one the server gave us via configstring */ if (!Q_streq(UFO_VERSION, serverVersion)) { Com_sprintf(popupText, sizeof(popupText), _("Local game version (%s) differs from the server version (%s)"), UFO_VERSION, serverVersion); UI_Popup(_("Error"), popupText); Com_Error(ERR_DISCONNECT, "Local game version (%s) differs from the server version (%s)", UFO_VERSION, serverVersion); /* amount of objects from script files doesn't match */ } else if (csi.numODs != CL_GetConfigStringInteger(CS_OBJECTAMOUNT)) { UI_Popup(_("Error"), _("Script files are not the same")); Com_Error(ERR_DISCONNECT, "Script files are not the same"); } /* activate the map loading screen for multiplayer, too */ SCR_BeginLoadingPlaque(); /* check download */ if (cls.downloadMaps) { /* confirm map */ if (CL_DownloadMap(CL_GetConfigString(CS_NAME))) return false; cls.downloadMaps = false; } /* map might still be downloading? */ if (CL_PendingHTTPDownloads()) return false; if (Com_GetScriptChecksum() != CL_GetConfigStringInteger(CS_UFOCHECKSUM)) Com_Printf("You are using modified ufo script files - might produce problems\n"); CM_LoadMap(CL_GetConfigString(CS_TILES), day, CL_GetConfigString(CS_POSITIONS), CL_GetConfigString(CS_ENTITYSTRING), cl.mapData, cl.mapTiles); #if 0 if (cl.mapData->mapChecksum != CL_GetConfigStringInteger(CS_MAPCHECKSUM)) { UI_Popup(_("Error"), _("Local map version differs from server")); Com_Error(ERR_DISCONNECT, "Local map version differs from server: %u != '%i'", cl.mapData->mapChecksum, CL_GetConfigStringInteger(CS_MAPCHECKSUM)); } #endif return true; }
/** * @param entData The structure that holds the data we parsed from the script */ static void SP_light (const localEntityParse_t* entData) { if (entData->light < 1.0) return; const int dayLightmap = CL_GetConfigStringInteger(CS_LIGHTMAP); if (!(dayLightmap && (entData->spawnflags & (1 << SPAWNFLAG_NO_DAY)))) { R_AddStaticLight(entData->origin, entData->light, entData->color); } }
static void SP_worldspawn (const localEntityParse_t *entData) { const int dayLightmap = CL_GetConfigStringInteger(CS_LIGHTMAP); int i; /* maximum level */ cl.mapMaxLevel = entData->maxLevel; if (GAME_IsMultiplayer()) { if (cl_teamnum->integer > entData->maxMultiplayerTeams || cl_teamnum->integer <= TEAM_CIVILIAN) { Com_Printf("The selected team is not usable. " "The map doesn't support %i teams but only %i teams\n", cl_teamnum->integer, entData->maxMultiplayerTeams); Cvar_SetValue("cl_teamnum", TEAM_DEFAULT); Com_Printf("Set teamnum to %i\n", cl_teamnum->integer); } } /** @todo - make sun position/color vary based on local time at location? */ if (dayLightmap) VectorCopy(entData->ambientDayColor, sun.ambientColor); else VectorCopy(entData->ambientNightColor, sun.ambientColor); /* clamp it */ for (i = 0; i < 3; i++) if (sun.ambientColor[i] < MIN_AMBIENT_COMPONENT) sun.ambientColor[i] = MIN_AMBIENT_COMPONENT; /* scale it into a reasonable range, the clamp above ensures this will work */ while (VectorSum(sun.ambientColor) < MIN_AMBIENT_SUM) VectorScale(sun.ambientColor, 1.25, sun.ambientColor); /* set up "global" (ie. directional) light sources */ Vector4Set(sun.loc, 0, 0, -1, 0.0); sun.constantAttenuation = 1.0; sun.linearAttenuation = 0.0; sun.quadraticAttenuation = 0.0; sun.enabled = qtrue; if (dayLightmap) { /* sunlight color */ Vector4Set(sun.diffuseColor, 0.8, 0.8, 0.8, 1); Vector4Set(sun.specularColor, 1.0, 1.0, 0.9, 1); } else { /* moonlight color */ Vector4Set(sun.diffuseColor, 0.2, 0.2, 0.3, 1); Vector4Set(sun.specularColor, 0.5, 0.5, 0.7, 1); } /** @todo Parse fog from worldspawn config */ refdef.weather = WEATHER_NONE; refdef.fogColor[3] = 1.0; VectorSet(refdef.fogColor, 0.75, 0.75, 0.75); }
static void SP_misc_sound (const localEntityParse_t *entData) { const int dayLightmap = CL_GetConfigStringInteger(CS_LIGHTMAP); if (!(dayLightmap && (entData->spawnflags & (1 << SPAWNFLAG_NO_DAY)))) LE_AddAmbientSound(entData->noise, entData->origin, (entData->spawnflags & 0xFF), entData->volume, entData->attenuation); }
static void SP_misc_particle (const localEntityParse_t *entData) { const int dayLightmap = CL_GetConfigStringInteger(CS_LIGHTMAP); if (!(dayLightmap && (entData->spawnflags & (1 << SPAWNFLAG_NO_DAY)))) CL_AddMapParticle(entData->particle, entData->origin, entData->wait, entData->entStringPos, (entData->spawnflags & 0xFF)); }
/** * @brief Call before entering a new level, or after vid_restart */ void CL_ViewLoadMedia (void) { le_t* le; int i, max; float loadingPercent; CL_ViewUpdateRenderData(); if (CL_GetConfigString(CS_TILES)[0] == '\0') return; /* no map loaded */ GAME_InitMissionBriefing(_(CL_GetConfigString(CS_MAPTITLE))); loadingPercent = 0; /* register models, pics, and skins */ SCR_DrawLoading(loadingPercent); R_ModBeginLoading(CL_GetConfigString(CS_TILES), CL_GetConfigStringInteger(CS_LIGHTMAP), CL_GetConfigString(CS_POSITIONS), CL_GetConfigString(CS_NAME), CL_GetConfigString(CS_MAPZONE)); CL_SpawnParseEntitystring(); loadingPercent += 10.0f; SCR_DrawLoading(loadingPercent); LM_Register(); CL_ParticleRegisterArt(); for (i = 1, max = 0; i < MAX_MODELS && CL_GetConfigString(CS_MODELS + i)[0] != '\0'; i++) max++; max += csi.numODs; for (i = 1; i < MAX_MODELS; i++) { const char* name = CL_GetConfigString(CS_MODELS + i); if (name[0] == '\0') break; SCR_DrawLoading(loadingPercent); cl.model_draw[i] = R_FindModel(name); if (!cl.model_draw[i]) { Cmd_ExecuteString("fs_info"); Com_Error(ERR_DROP, "Could not load model '%s'\n", name); } /* initialize clipping for bmodels */ if (name[0] == '*') cl.model_clip[i] = CM_InlineModel(cl.mapTiles, name); else cl.model_clip[i] = nullptr; loadingPercent += 100.0f / (float)max; } /* update le model references */ le = nullptr; while ((le = LE_GetNextInUse(le))) { if (le->modelnum1 > 0) le->model1 = LE_GetDrawModel(le->modelnum1); if (le->modelnum2 > 0) le->model2 = LE_GetDrawModel(le->modelnum2); } refdef.ready = true; /* waiting for EV_START */ SCR_EndLoadingPlaque(); }
/** @note Defaults should match those of ufo2map, or lighting will be inconsistent between world and models */ static void SP_worldspawn (const localEntityParse_t* entData) { /* maximum level */ cl.mapMaxLevel = entData->maxLevel; if (GAME_IsMultiplayer()) { if (cl_teamnum->integer > entData->maxMultiplayerTeams || cl_teamnum->integer <= TEAM_CIVILIAN) { Com_Printf("The selected team is not usable. " "The map doesn't support %i teams but only %i teams\n", cl_teamnum->integer, entData->maxMultiplayerTeams); Cvar_SetValue("cl_teamnum", TEAM_DEFAULT); Com_Printf("Set teamnum to %i\n", cl_teamnum->integer); } } /** @todo - make sun position/color vary based on local time at location? */ const int dayLightmap = CL_GetConfigStringInteger(CS_LIGHTMAP); /** @note Some vectors have exra elements to comply with mathlib and/or OpenGL conventions, but handled as shorter ones */ vec3_t sunAngles; vec4_t sunColor; vec_t sunIntensity; if (dayLightmap) { /* set defaults for daylight */ Vector4Set(refdef.ambientColor, 0.26, 0.26, 0.26, 1.0); sunIntensity = 280; VectorSet(sunAngles, -75, 100, 0); Vector4Set(sunColor, 0.90, 0.75, 0.65, 1.0); /* override defaults with data from worldspawn entity, if any */ if (VectorNotEmpty(entData->ambientDayColor)) VectorCopy(entData->ambientDayColor, refdef.ambientColor); if (entData->dayLight) sunIntensity = entData->dayLight; if (Vector2NotEmpty(entData->daySunAngles)) Vector2Copy(entData->daySunAngles, sunAngles); if (VectorNotEmpty(entData->daySunColor)) VectorCopy(entData->daySunColor, sunColor); Vector4Set(refdef.sunSpecularColor, 1.0, 1.0, 0.9, 1); } else { /* set defaults for night light */ Vector4Set(refdef.ambientColor, 0.16, 0.16, 0.17, 1.0); sunIntensity = 15; VectorSet(sunAngles, -80, 220, 0); Vector4Set(sunColor, 0.25, 0.25, 0.35, 1.0); /* override defaults with data from worldspawn entity, if any */ if (VectorNotEmpty(entData->ambientNightColor)) VectorCopy(entData->ambientNightColor, refdef.ambientColor); if (entData->nightLight) sunIntensity = entData->nightLight; if (Vector2NotEmpty(entData->nightSunAngles)) Vector2Copy(entData->nightSunAngles, sunAngles); if (VectorNotEmpty(entData->nightSunColor)) VectorCopy(entData->nightSunColor, sunColor); Vector4Set(refdef.sunSpecularColor, 0.5, 0.5, 0.7, 1); } ColorNormalize(sunColor, sunColor); VectorScale(sunColor, sunIntensity/255.0, sunColor); Vector4Copy(sunColor, refdef.sunDiffuseColor); /* clamp ambient for models */ Vector4Copy(refdef.ambientColor, refdef.modelAmbientColor); for (int i = 0; i < 3; i++) if (refdef.modelAmbientColor[i] < MIN_AMBIENT_COMPONENT) refdef.modelAmbientColor[i] = MIN_AMBIENT_COMPONENT; /* scale it into a reasonable range, the clamp above ensures this will work */ while (VectorSum(refdef.modelAmbientColor) < MIN_AMBIENT_SUM) VectorScale(refdef.modelAmbientColor, 1.25, refdef.modelAmbientColor); AngleVectors(sunAngles, refdef.sunVector, nullptr, nullptr); refdef.sunVector[3] = 0.0; /* to use as directional light source in OpenGL */ /** @todo Parse fog from worldspawn config */ refdef.weather = WEATHER_NONE; refdef.fogColor[3] = 1.0; VectorSet(refdef.fogColor, 0.75, 0.75, 0.75); }