/** * @brief * @sa FinalLightFace */ void BuildFacelights (unsigned int facenum) { dBspSurface_t* face; dBspPlane_t* plane; dBspTexinfo_t* tex; float* center; float* sdir, *tdir; vec3_t normal, binormal; vec4_t tangent; lightinfo_t li; float scale; int i, j, numsamples; facelight_t* fl; int* headhints; const int grid_type = config.soft ? 1 : 0; if (facenum >= MAX_MAP_FACES) { Com_Printf("MAX_MAP_FACES hit\n"); return; } face = &curTile->faces[facenum]; plane = &curTile->planes[face->planenum]; tex = &curTile->texinfo[face->texinfo]; if (tex->surfaceFlags & SURF_WARP) return; /* non-lit texture */ sdir = tex->vecs[0]; tdir = tex->vecs[1]; /* lighting -extra antialiasing */ if (config.extrasamples) numsamples = config.soft ? SOFT_SAMPLES : MAX_SAMPLES; else numsamples = 1; OBJZERO(li); scale = 1.0 / numsamples; /* each sample contributes this much */ li.face = face; li.facedist = plane->dist; VectorCopy(plane->normal, li.facenormal); /* negate the normal and dist */ if (face->side) { VectorNegate(li.facenormal, li.facenormal); li.facedist = -li.facedist; } /* get the origin offset for rotating bmodels */ VectorCopy(face_offset[facenum], li.modelorg); /* calculate lightmap texture mins and maxs */ CalcLightinfoExtents(&li); /* and the lightmap texture vectors */ CalcLightinfoVectors(&li); /* now generate all of the sample points */ CalcPoints(&li, 0, 0); fl = &facelight[config.compile_for_day][facenum]; fl->numsamples = li.numsurfpt; fl->samples = Mem_AllocTypeN(vec3_t, fl->numsamples); fl->directions = Mem_AllocTypeN(vec3_t, fl->numsamples); center = face_extents[facenum].center; /* center of the face */ /* Also setup the hints. Each hint is specific to each light source, including sunlight. */ headhints = Mem_AllocTypeN(int, (numlights[config.compile_for_day] + 1)); /* calculate light for each sample */ for (i = 0; i < fl->numsamples; i++) { float* const sample = fl->samples[i]; /* accumulate lighting here */ float* const direction = fl->directions[i]; /* accumulate direction here */ if (tex->surfaceFlags & SURF_PHONG) /* interpolated normal */ SampleNormal(&li, li.surfpt[i], normal); else /* or just plane normal */ VectorCopy(li.facenormal, normal); for (j = 0; j < numsamples; j++) { /* with antialiasing */ vec3_t pos; /* add offset for supersampling */ VectorMA(li.surfpt[i], sampleofs[grid_type][j][0] * li.step, li.textoworld[0], pos); VectorMA(pos, sampleofs[grid_type][j][1] * li.step, li.textoworld[1], pos); NudgeSamplePosition(pos, normal, center, pos); GatherSampleLight(pos, normal, sample, direction, scale, headhints); } if (VectorNotEmpty(direction)) { vec3_t dir; /* normalize it */ VectorNormalize(direction); /* finalize the lighting direction for the sample */ TangentVectors(normal, sdir, tdir, tangent, binormal); dir[0] = DotProduct(direction, tangent); dir[1] = DotProduct(direction, binormal); dir[2] = DotProduct(direction, normal); VectorCopy(dir, direction); } } /* Free the hints. */ Mem_Free(headhints); for (i = 0; i < fl->numsamples; i++) { /* pad them */ float* const direction = fl->directions[i]; if (VectorEmpty(direction)) VectorSet(direction, 0.0, 0.0, 1.0); } /* free the sample positions for the face */ Mem_Free(li.surfpt); }
void uiWindowNode::clone (const uiNode_t* source, uiNode_t* clone) { /* clean up index */ EXTRADATA(clone).index = nullptr; OBJZERO(EXTRADATA(clone).index_hash); }
/** * @sa S_Shutdown * @sa S_Restart_f */ void S_Init (void) { SDL_version version; char drivername[MAX_VAR]; Com_Printf("\n------- sound initialization -------\n"); OBJZERO(s_env); snd_init = Cvar_Get("snd_init", "1", CVAR_ARCHIVE, "Should the sound renderer get initialized"); snd_init->modified = false; /* don't restart right away */ Cmd_AddCommand("snd_restart", S_Restart_f, "Restart the sound renderer"); if (!snd_init->integer) { Com_Printf("not initializing.\n"); Cmd_AddCommand("music_change", Cmd_Dummy_f, "Dummy command if sound is disabled"); Cvar_Get("snd_music", "PsymongN3", 0, "Background music track"); return; } cl_soundSysPool = Mem_CreatePool("Client: Sound system"); snd_distance_scale = Cvar_Get("snd_distance_scale", "0.1", 0, "Sound distance scale"); snd_volume = Cvar_Get("snd_volume", "0.7", CVAR_ARCHIVE, "Sound volume - default is 0.7"); snd_rate = Cvar_Get("snd_rate", "44100", CVAR_ARCHIVE, "Hz value for sound renderer - default is 44100"); snd_chunkbufsize = Cvar_Get("snd_chunkbufsize", "1024", CVAR_ARCHIVE, "The sound buffer chunk size"); /* set volumes to be changed so they are applied again for next sound/music playing */ /** @todo implement the volume change for already loaded sample chunks */ snd_volume->modified = true; Cmd_AddCommand("snd_play", S_Play_f, "Plays a sound fx file. Pass path relative to base/sound without file extension"); Cmd_AddParamCompleteFunction("snd_play", S_CompleteSounds); if (SDL_WasInit(SDL_INIT_AUDIO) == 0) { if (SDL_Init(SDL_INIT_AUDIO) < 0) { Com_Printf("S_Init: %s.\n", SDL_GetError()); return; } } MIX_VERSION(&version) Com_Printf("SDL_mixer version: %d.%d.%d\n", version.major, version.minor, version.patch); Com_Printf("... requested audio rate: %i\n", snd_rate->integer); if (Mix_OpenAudio(snd_rate->integer, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, snd_chunkbufsize->integer) == -1) { Com_Printf("S_Init: %s\n", Mix_GetError()); return; } if (Mix_QuerySpec(&s_env.rate, &s_env.format, &s_env.numChannels) == 0) { Com_Printf("S_Init: %s\n", Mix_GetError()); return; } if (SDL_AudioDriverName(drivername, sizeof(drivername)) == NULL) Q_strncpyz(drivername, "(UNKNOWN)", sizeof(drivername)); Com_Printf("... driver: '%s'\n", drivername); if (Mix_AllocateChannels(MAX_CHANNELS) != MAX_CHANNELS) { Com_Printf("S_Init: %s\n", Mix_GetError()); return; } Mix_ChannelFinished(S_FreeChannel); Com_Printf("... audio rate: %i\n", s_env.rate); Com_Printf("... audio channels: %i\n", s_env.numChannels); #if COMPARE_VERSION(1, 2, 10) if (!(Mix_Init(MIX_INIT_OGG) & MIX_INIT_OGG)) Com_Printf("... could not load ogg vorbis support\n"); else Com_Printf("... loaded ogg vorbis support\n"); #endif s_env.initialized = true; M_Init(); }
/** * @brief Creates a server's entity / program execution context * by parsing textual entity definitions out of an ent file. * @sa CM_EntityString * @sa SV_SpawnServer */ void G_SpawnEntities (const char *mapname, bool day, const char *entities) { int entnum; G_FreeTags(TAG_LEVEL); OBJZERO(level); level.pathingMap = (pathing_t *)G_TagMalloc(sizeof(*level.pathingMap), TAG_LEVEL); G_EdictsReset(); /* initialize reactionFire data */ G_ReactionFireTargetsInit(); Q_strncpyz(level.mapname, mapname, sizeof(level.mapname)); level.day = day; G_ResetClientData(); level.activeTeam = TEAM_NO_ACTIVE; level.actualRound = 1; level.hurtAliens = sv_hurtaliens->integer; ai_waypointList = NULL; /* parse ents */ entnum = 0; while (1) { edict_t *ent; /* parse the opening brace */ const char *token = Com_Parse(&entities); if (!entities) break; if (token[0] != '{') gi.Error("ED_LoadFromFile: found %s when expecting {", token); ent = G_Spawn(); entities = ED_ParseEdict(entities, ent); ent->mapNum = entnum++; /* Set the position of the entity */ VecToPos(ent->origin, ent->pos); /* Call this entity's specific initializer (sets ent->type) */ ED_CallSpawn(ent); /* if this entity is an bbox (e.g. actor), then center its origin based on its position */ if (ent->solid == SOLID_BBOX) G_EdictCalcOrigin(ent); } /* spawn ai players, if needed */ if (level.num_spawnpoints[TEAM_CIVILIAN]) { if (AI_CreatePlayer(TEAM_CIVILIAN) == NULL) gi.DPrintf("Could not create civilian\n"); } if ((sv_maxclients->integer == 1 || ai_numactors->integer) && level.num_spawnpoints[TEAM_ALIEN]) { if (AI_CreatePlayer(TEAM_ALIEN) == NULL) gi.DPrintf("Could not create alien\n"); } Com_Printf("Used inventory slots after ai spawn: %i\n", game.i.GetUsedSlots(&game.i)); G_FindEdictGroups(); }
static void testCharacterAnimationFiles (void) { const char *pattern = "models/**.anm"; const char *filename; mAliasModel_t mod; const char* bloodspider[] = { "death1", "death2", "death3", "dead1", "dead2", "dead3", "stand0", "stand1", "stand2", "stand3", "walk0", "walk1", "walk2", "walk3", "cstand0", "cstand1", "cstand2", "cstand3", "cwalk0", "cwalk1", "cwalk2", "cwalk3", "stand_menu", "panic0", NULL }; const char* hovernet[] = { "death1", "dead1", "death2","dead2", "death3", "dead3", "stand0", "walk0", "cstand0", "cwalk0", "stand1", "walk1", "cstand1", "cwalk1", "stand2", "walk2", "cstand2", "cwalk2", "stand3", "walk3", "cstand3", "cwalk3", "move_rifle", "shoot_rifle", "cmove_rifle", "cshoot_rifle", "stand_menu", "panic0", NULL }; const char* soldiers[] = { "death1", "death2", "death3", "dead1", "dead2", "dead3", "stand0", "stand1", "stand2", "stand3", "walk0", "walk1", "walk2", "walk3", "cstand0", "cstand1", "cstand2", "cstand3", "cwalk0", "cwalk1", "cwalk2", "cwalk3", "stand_menu", "panic0", "move_rifle", "shoot_rifle", "cmove_rifle", "cshoot_rifle", "move_biggun", "shoot_biggun", "cmove_biggun", "cshoot_biggun", "move_melee", "shoot_melee", "cmove_melee", "cshoot_melee", "stand_still", "move_pistol", "shoot_pistol", "cmove_pistol", "cshoot_pistol", "move_pistol_d", "shoot_pistol_d", "cmove_pistol_d", "cshoot_pistol_d", "move_grenade", "shoot_grenade", "cmove_grenade", "cshoot_grenade", "move_item", "shoot_item", "cmove_item", "cshoot_item", "move_rpg", "shoot_rpg", "cmove_rpg", "cshoot_rpg", NULL }; const char* civilians[] = { "death1", "dead1", "death2", "dead2", "death3", "dead3", "stand0", "walk0", "panic0", "stand1", "stand2", "stand_menu", "stand_still", NULL }; FS_BuildFileList(pattern); vid_modelPool = Mem_CreatePool("Vid Model Pool"); while ((filename = FS_NextFileFromFileList(pattern)) != NULL) { const char **animList; if (Q_strstart(filename, "models/soldiers/")) animList = soldiers; else if (Q_strstart(filename, "models/civilians/")) animList = civilians; else if (Q_strstart(filename, "models/aliens/bloodspider")) animList = bloodspider; else if (Q_strstart(filename, "models/aliens/hovernet")) animList = hovernet; else if (Q_strstart(filename, "models/aliens/")) animList = soldiers; else animList = NULL; /** @todo remove this hack - but ugvs are just not ready yet */ if (Q_strstart(filename, "models/soldiers/ugv_")) continue; /** @todo remove this hack - alientank is just not ready yet */ if (Q_strstart(filename, "models/aliens/alientank/")) continue; if (animList != NULL) { OBJZERO(mod); /* set a very high value to work around the error check in the loading function */ mod.num_frames = 100000; Com_Printf("load character anim file: %s\n", filename); R_ModLoadAnims(&mod, filename); while (*animList != NULL) { int i; for (i = 0; i < mod.num_anims; i++) { const mAliasAnim_t *a = &mod.animdata[i]; if (Q_streq(a->name, *animList)) break; } if (i == mod.num_anims) UFO_CU_ASSERT_MSG(va("anm file %s does not contain the needed animation definition %s", filename, *animList)); animList++; } } } Mem_DeletePool(vid_modelPool); FS_NextFileFromFileList(NULL); }
ReactionFireTargetList () { OBJZERO(targets); init(); }
/** * @brief This is a savegame function which stores the game in xml-Format. * @param[in] filename The Filename to save to (without extension) * @param[in] comment Description of the savegame * @param[out] error On failure an errormessage may be set. */ static bool SAV_GameSave (const char* filename, const char* comment, char** error) { if (!CP_IsRunning()) { *error = _("No campaign active."); Com_Printf("Error: No campaign active.\n"); return false; } if (!B_AtLeastOneExists()) { *error = _("Nothing to save yet."); Com_Printf("Error: Nothing to save yet.\n"); return false; } char savegame[MAX_OSPATH]; dateLong_t date; char message[30]; char timeStampBuffer[32]; Com_MakeTimestamp(timeStampBuffer, sizeof(timeStampBuffer)); cgi->GetRelativeSavePath(savegame, sizeof(savegame)); Q_strcat(savegame, sizeof(savegame), "%s.%s", filename, SAVEGAME_EXTENSION); xmlNode_t* topNode = mxmlNewXML("1.0"); xmlNode_t* node = cgi->XML_AddNode(topNode, SAVE_ROOTNODE); /* writing Header */ cgi->XML_AddInt(node, SAVE_SAVEVERSION, SAVE_FILE_VERSION); cgi->XML_AddString(node, SAVE_COMMENT, comment); cgi->XML_AddString(node, SAVE_UFOVERSION, UFO_VERSION); cgi->XML_AddString(node, SAVE_REALDATE, timeStampBuffer); CP_DateConvertLong(&ccs.date, &date); Com_sprintf(message, sizeof(message), _("%i %s %02i"), date.year, Date_GetMonthName(date.month - 1), date.day); cgi->XML_AddString(node, SAVE_GAMEDATE, message); /* working through all subsystems. perhaps we should redesign it, order is not important anymore */ Com_Printf("Calling subsystems\n"); for (int i = 0; i < saveSubsystemsAmount; i++) { if (!saveSubsystems[i].save) continue; if (!saveSubsystems[i].save(node)) Com_Printf("...subsystem '%s' failed to save the data\n", saveSubsystems[i].name); else Com_Printf("...subsystem '%s' - saved\n", saveSubsystems[i].name); } /* calculate the needed buffer size */ saveFileHeader_t header; OBJZERO(header); header.compressed = LittleLong(save_compressed->integer); header.version = LittleLong(SAVE_FILE_VERSION); header.subsystems = LittleLong(saveSubsystemsAmount); Q_strncpyz(header.name, comment, sizeof(header.name)); Q_strncpyz(header.gameVersion, UFO_VERSION, sizeof(header.gameVersion)); CP_DateConvertLong(&ccs.date, &date); Com_sprintf(header.gameDate, sizeof(header.gameDate), _("%i %s %02i"), date.year, Date_GetMonthName(date.month - 1), date.day); Q_strncpyz(header.realDate, timeStampBuffer, sizeof(header.realDate)); char dummy[2]; int requiredBufferLength = mxmlSaveString(topNode, dummy, 2, MXML_NO_CALLBACK); header.xmlSize = LittleLong(requiredBufferLength); byte* const buf = Mem_PoolAllocTypeN(byte, requiredBufferLength + 1, cp_campaignPool); if (!buf) { mxmlDelete(topNode); *error = _("Could not allocate enough memory to save this game"); Com_Printf("Error: Could not allocate enough memory to save this game\n"); return false; } int res = mxmlSaveString(topNode, (char*)buf, requiredBufferLength + 1, MXML_NO_CALLBACK); mxmlDelete(topNode); Com_Printf("XML Written to buffer (%d Bytes)\n", res); uLongf bufLen; if (header.compressed) bufLen = compressBound(requiredBufferLength); else bufLen = requiredBufferLength; byte* const fbuf = Mem_PoolAllocTypeN(byte, bufLen + sizeof(header), cp_campaignPool); memcpy(fbuf, &header, sizeof(header)); if (header.compressed) { res = compress(fbuf + sizeof(header), &bufLen, buf, requiredBufferLength); cgi->Free(buf); if (res != Z_OK) { cgi->Free(fbuf); *error = _("Memory error compressing save-game data - set save_compressed cvar to 0"); Com_Printf("Memory error compressing save-game data (%s) (Error: %i)!\n", comment, res); return false; } } else { memcpy(fbuf + sizeof(header), buf, requiredBufferLength); cgi->Free(buf); } /* last step - write data */ cgi->FS_WriteFile(fbuf, bufLen + sizeof(header), savegame); cgi->Free(fbuf); return true; }
/** * @brief Update xviInfection value for each nation, using the XVI overlay. * @note should be executed after all daily event that could change XVI overlay */ void CP_UpdateNationXVIInfection (void) { /* No need to update XVI levels if the overlay didn't change */ if (!xviNationInfectionNeedsUpdate) return; /* width in pixel of the XVI overlay */ int width; /* height in pixel of the XVI overlay */ int height; CP_GetXVIMapDimensions(&width, &height); const float heightPerDegree = height / 180.0f; const float widthPerDegree = width / 360.0f; /* parameter used to normalize nation XVI level. * decrease this factor to increase XVI level per nation */ const float AREA_FACTOR = 650.0f; /* area used to normalized XVI infection level for each nation. * depend on overlay size so that if we change resolution of * overlay it doesn't impact nation XIInfection */ const float normalizingArea = width * height / AREA_FACTOR; /* temporary array to store the XVI levels */ float xviInfection[MAX_NATIONS]; /* Initialize array */ OBJZERO(xviInfection); for (int y = 0; y < height; y++) { int sum[MAX_NATIONS]; const byte* previousNationColor; const nation_t* nation; /* current position (in latitude / longitude) */ vec2_t currentPos; OBJZERO(sum); Vector2Set(currentPos, 180.0f, 90.0f - y / heightPerDegree); previousNationColor = GEO_GetColor(currentPos, MAPTYPE_NATIONS, nullptr); nation = GEO_GetNation(currentPos); for (int x = 0; x < width; x++) { const byte* nationColor; currentPos[0] = 180.0f - x / widthPerDegree; nationColor = GEO_GetColor(currentPos, MAPTYPE_NATIONS, nullptr); if (!VectorCompare(nationColor, previousNationColor)) { previousNationColor = nationColor; nation = GEO_GetNation(currentPos); } if (nation) { const int xviLevel = CP_GetXVILevel(x, y); if (xviLevel > 0) sum[nation->idx] += xviLevel; } } /* divide the total XVI infection by the area of a pixel * because pixel are smaller as you go closer from the pole */ for (int nationIdx = 0; nationIdx < ccs.numNations; nationIdx++) xviInfection[nationIdx] += ((float) sum[nationIdx]) / (cos(torad * currentPos[1]) * normalizingArea); } /* copy the new values of XVI infection level into nation array */ for (int nationIdx = 0; nationIdx < ccs.numNations; nationIdx++) { nation_t* nation = NAT_GetNationByIDX(nationIdx); nation->stats[0].xviInfection = ceil(xviInfection[nation->idx]); } xviNationInfectionNeedsUpdate = false; }
/** * @brief Copies an entry from the building description file into the list of building types. * @note Parses one "building" entry in the basemanagement.ufo file and writes * it into the next free entry in bmBuildings[0], which is the list of buildings * in the first base (building_t). * @param[in] name Unique script id of a building. This is parsed from "building xxx" -> id=xxx. * @param[in] text the whole following text that is part of the "building" item definition in .ufo. * @param[in] link Bool value that decides whether to link the tech pointer in or not * @sa CL_ParseScriptFirst (link is false here) * @sa CL_ParseScriptSecond (link it true here) */ void B_ParseBuildings (const char* name, const char** text, bool link) { building_t* building; technology_t* techLink; const char* errhead = "B_ParseBuildings: unexpected end of file (names "; const char* token; /* get id list body */ token = Com_Parse(text); if (!*text || *token != '{') { cgi->Com_Printf("B_ParseBuildings: building \"%s\" without body ignored\n", name); return; } if (ccs.numBuildingTemplates >= MAX_BUILDINGS) cgi->Com_Error(ERR_DROP, "B_ParseBuildings: too many buildings"); if (!link) { for (int i = 0; i < ccs.numBuildingTemplates; i++) { if (Q_streq(ccs.buildingTemplates[i].id, name)) { cgi->Com_Printf("B_ParseBuildings: Second building with same name found (%s) - second ignored\n", name); return; } } /* new entry */ building = &ccs.buildingTemplates[ccs.numBuildingTemplates]; OBJZERO(*building); building->id = cgi->PoolStrDup(name, cp_campaignPool, 0); cgi->Com_DPrintf(DEBUG_CLIENT, "...found building %s\n", building->id); /* set standard values */ building->tpl = building; /* Self-link just in case ... this way we can check if it is a template or not. */ building->idx = -1; /* No entry in buildings list (yet). */ building->base = nullptr; building->buildingType = MAX_BUILDING_TYPE; building->dependsBuilding = nullptr; building->maxCount = -1; /* Default: no limit */ building->size[0] = 1; building->size[1] = 1; ccs.numBuildingTemplates++; do { /* get the name type */ token = cgi->Com_EParse(text, errhead, name); if (!*text) break; if (*token == '}') break; /* get values */ if (Q_streq(token, "type")) { token = cgi->Com_EParse(text, errhead, name); if (!*text) return; building->buildingType = B_GetBuildingTypeByBuildingID(token); if (building->buildingType >= MAX_BUILDING_TYPE) cgi->Com_Printf("didn't find buildingType '%s'\n", token); } else { /* no linking yet */ if (Q_streq(token, "depends")) { cgi->Com_EParse(text, errhead, name); if (!*text) return; } else { if (!cgi->Com_ParseBlockToken(name, text, building, valid_building_vars, cp_campaignPool, token)) cgi->Com_Printf("B_ParseBuildings: unknown token \"%s\" ignored (building %s)\n", token, name); } } } while (*text); if (building->size[0] < 1 || building->size[1] < 1 || building->size[0] >= BASE_SIZE || building->size[1] >= BASE_SIZE) { cgi->Com_Printf("B_ParseBuildings: Invalid size for building %s (%i, %i)\n", building->id, (int)building->size[0], (int)building->size[1]); ccs.numBuildingTemplates--; } } else { building = B_GetBuildingTemplate(name); if (!building) cgi->Com_Error(ERR_DROP, "B_ParseBuildings: Could not find building with id %s\n", name); techLink = RS_GetTechByProvided(name); if (techLink) building->tech = techLink; do { /* get the name type */ token = cgi->Com_EParse(text, errhead, name); if (!*text) break; if (*token == '}') break; /* get values */ if (Q_streq(token, "depends")) { const building_t* dependsBuilding = B_GetBuildingTemplate(cgi->Com_EParse(text, errhead, name)); if (!dependsBuilding) cgi->Com_Error(ERR_DROP, "Could not find building depend of %s\n", building->id); building->dependsBuilding = dependsBuilding; if (!*text) return; } } while (*text); } }
/** * @brief Writes the brush list to the bsp */ void EmitBrushes (void) { curTile->numbrushsides = 0; curTile->numbrushes = nummapbrushes; /* Clear out curTile->brushes */ OBJZERO(curTile->brushes); for (int bnum = 0; bnum < nummapbrushes; bnum++) { const mapbrush_t* b = &mapbrushes[bnum]; dBspBrush_t* db = &curTile->dbrushes[bnum]; cBspBrush_t* cb = &curTile->brushes[bnum]; db->brushContentFlags = b->contentFlags; db->firstbrushside = curTile->numbrushsides; db->numsides = b->numsides; cb->brushContentFlags = b->contentFlags; cb->firstbrushside = curTile->numbrushsides; cb->numsides = b->numsides; cb->checkcount = 0; for (int j = 0; j < b->numsides; j++) { if (curTile->numbrushsides == MAX_MAP_BRUSHSIDES) { Sys_Error("MAX_MAP_BRUSHSIDES (%i)", curTile->numbrushsides); } else { dBspBrushSide_t* cp = &curTile->brushsides[curTile->numbrushsides]; curTile->numbrushsides++; cp->planenum = b->original_sides[j].planenum; cp->texinfo = b->original_sides[j].texinfo; } } /* add any axis planes not contained in the brush to bevel off corners */ for (int x = 0; x < 3; x++) for (int s = -1; s <= 1; s += 2) { /* add the plane */ vec3_t normal; VectorCopy(vec3_origin, normal); normal[x] = (float)s; vec_t dist; if (s == -1) dist = -b->mbBox.mins[x]; else dist = b->mbBox.maxs[x]; int planenum = FindOrCreateFloatPlane(normal, dist); int i; for (i = 0; i < b->numsides; i++) if (b->original_sides[i].planenum == planenum) break; if (i == b->numsides) { if (curTile->numbrushsides >= MAX_MAP_BRUSHSIDES) Sys_Error("MAX_MAP_BRUSHSIDES (%i)", curTile->numbrushsides); curTile->brushsides[curTile->numbrushsides].planenum = planenum; curTile->brushsides[curTile->numbrushsides].texinfo = curTile->brushsides[curTile->numbrushsides - 1].texinfo; curTile->numbrushsides++; db->numsides++; cb->numsides++; } } } }
void Cvar_Shutdown (void) { cvarVars = NULL; OBJZERO(cvarVarsHash); }
/** * @todo need to merge UI model case, and the common case (look to be a copy-pasted code) */ void UI_DrawModelNode (uiNode_t *node, const char *source) { modelInfo_t mi; uiModel_t *model; vec3_t nodeorigin; vec3_t autoScale; vec3_t autoCenter; assert(UI_NodeInstanceOf(node, "model")); /**< We use model extradata */ if (source[0] == '\0') return; model = UI_GetUIModel(source); /* direct model name - no UI model definition */ if (!model) { /* prevent the searching for a model def in the next frame */ mi.model = R_FindModel(source); mi.name = source; if (!mi.model) { Com_Printf("Could not find model '%s'\n", source); return; } } /* compute the absolute origin ('origin' property is relative to the node center) */ UI_GetNodeAbsPos(node, nodeorigin); R_CleanupDepthBuffer(nodeorigin[0], nodeorigin[1], node->size[0], node->size[1]); if (EXTRADATA(node).clipOverflow) R_PushClipRect(nodeorigin[0], nodeorigin[1], node->size[0], node->size[1]); nodeorigin[0] += node->size[0] / 2 + EXTRADATA(node).origin[0]; nodeorigin[1] += node->size[1] / 2 + EXTRADATA(node).origin[1]; nodeorigin[2] = EXTRADATA(node).origin[2]; VectorMA(EXTRADATA(node).angles, cls.frametime, EXTRADATA(node).omega, EXTRADATA(node).angles); mi.origin = nodeorigin; mi.angles = EXTRADATA(node).angles; mi.scale = EXTRADATA(node).scale; mi.center = nullVector; mi.color = node->color; mi.mesh = 0; /* special case to draw models with UI model */ if (model) { UI_DrawModelNodeWithUIModel(node, source, &mi, model); if (EXTRADATA(node).clipOverflow) R_PopClipRect(); return; } /* if the node is linked to a parent, the parent will display it */ if (EXTRADATA(node).tag) { if (EXTRADATA(node).clipOverflow) R_PopClipRect(); return; } /* autoscale? */ if (EXTRADATA(node).autoscale) { const vec2_t size = {node->size[0] - node->padding, node->size[1] - node->padding}; R_ModelAutoScale(size, &mi, autoScale, autoCenter); } /* no animation */ mi.frame = 0; mi.oldframe = 0; mi.backlerp = 0; /* get skin */ if (EXTRADATA(node).skin && *EXTRADATA(node).skin) mi.skin = atoi(UI_GetReferenceString(node, EXTRADATA(node).skin)); else mi.skin = 0; /* do animations */ if (EXTRADATA(node).animation && *EXTRADATA(node).animation) { animState_t *as; const char *ref; ref = UI_GetReferenceString(node, EXTRADATA(node).animation); /* check whether the cvar value changed */ if (strncmp(EXTRADATA(node).oldRefValue, source, MAX_OLDREFVALUE)) { Q_strncpyz(EXTRADATA(node).oldRefValue, source, MAX_OLDREFVALUE); /* model has changed but mem is already reserved in pool */ if (EXTRADATA(node).animationState) { Mem_Free(EXTRADATA(node).animationState); EXTRADATA(node).animationState = NULL; } } if (!EXTRADATA(node).animationState) { as = (animState_t *) Mem_PoolAlloc(sizeof(*as), cl_genericPool, 0); if (!as) Com_Error(ERR_DROP, "Model %s should have animState_t for animation %s - but doesn't\n", mi.name, ref); R_AnimChange(as, mi.model, ref); EXTRADATA(node).animationState = as; } else { const char *anim; /* change anim if needed */ as = EXTRADATA(node).animationState; if (!as) Com_Error(ERR_DROP, "Model %s should have animState_t for animation %s - but doesn't\n", mi.name, ref); anim = R_AnimGetName(as, mi.model); if (anim && !Q_streq(anim, ref)) R_AnimChange(as, mi.model, ref); R_AnimRun(as, mi.model, cls.frametime * 1000); } mi.frame = as->frame; mi.oldframe = as->oldframe; mi.backlerp = as->backlerp; } /* draw the main model on the node */ R_DrawModelDirect(&mi, NULL, NULL); /* draw all children */ if (node->firstChild) { uiNode_t *child; modelInfo_t pmi = mi; for (child = node->firstChild; child; child = child->next) { const char *tag; char childSource[MAX_VAR]; const char* childRef; /* skip non "model" nodes */ if (child->behaviour != node->behaviour) continue; /* skip invisible child */ if (child->invis || !UI_CheckVisibility(child)) continue; OBJZERO(mi); mi.angles = EXTRADATA(child).angles; mi.scale = EXTRADATA(child).scale; mi.center = nullVector; mi.origin = EXTRADATA(child).origin; mi.color = pmi.color; /* get the anchor name to link the model into the parent */ tag = EXTRADATA(child).tag; /* init model name */ childRef = UI_GetReferenceString(child, EXTRADATA(child).model); if (Q_strnull(childRef)) childSource[0] = '\0'; else Q_strncpyz(childSource, childRef, sizeof(childSource)); mi.model = R_FindModel(childSource); mi.name = childSource; /* init skin */ if (EXTRADATA(child).skin && *EXTRADATA(child).skin) mi.skin = atoi(UI_GetReferenceString(child, EXTRADATA(child).skin)); else mi.skin = 0; R_DrawModelDirect(&mi, &pmi, tag); } } if (EXTRADATA(node).clipOverflow) R_PopClipRect(); }
/** * @brief Start Base Attack. * @note Base attack mission -- Stage 2 */ void CP_BaseAttackStartMission (mission_t *mission) { base_t *base = mission->data.base; linkedList_t *hiredSoldiersInBase = NULL; int soldiers; assert(base); mission->stage = STAGE_BASE_ATTACK; CP_MissionDisableTimeLimit(mission); if (mission->ufo) { /* ufo becomes invisible on geoscape, but don't remove it from ufo global array (may reappear)*/ CP_UFORemoveFromGeoscape(mission, qfalse); } /* we always need at least one command centre in the base - because the * phalanx soldiers have their starting positions here. * There should also always be an entrance - the aliens start there * but we don't need to check that as entrance can't be destroyed */ if (!B_GetNumberOfBuildingsInBaseByBuildingType(base, B_COMMAND)) { /** @todo handle command centre properly */ Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no Command Center: it can't defend itself. Destroy base.\n", base->name); CP_BaseAttackMissionDestroyBase(mission); return; } MSO_CheckAddNewMessage(NT_BASE_ATTACK, _("Base attack"), va(_("Base '%s' is under attack!"), base->name), qfalse, MSG_BASEATTACK, NULL); base->baseStatus = BASE_UNDER_ATTACK; ccs.campaignStats.basesAttacked++; MAP_SelectMission(mission); mission->active = qtrue; ccs.mapAction = MA_BASEATTACK; Com_DPrintf(DEBUG_CLIENT, "Base attack: %s at %.0f:%.0f\n", mission->id, mission->pos[0], mission->pos[1]); /** @todo EMPL_ROBOT */ E_GetHiredEmployees(base, EMPL_SOLDIER, &hiredSoldiersInBase); /* Fill the fake aircraft */ LIST_Delete(&baseAttackFakeAircraft.acTeam); OBJZERO(baseAttackFakeAircraft); baseAttackFakeAircraft.homebase = base; /* needed for transfer of alien corpses */ VectorCopy(base->pos, baseAttackFakeAircraft.pos); #if 0 /** @todo active this once more than 8 soldiers are working */ /* needed to spawn soldiers on map */ baseAttackFakeAircraft.maxTeamSize = LIST_Count(hiredSoldiersInBase); #else baseAttackFakeAircraft.maxTeamSize = MAX_ACTIVETEAM; #endif if (!hiredSoldiersInBase) { Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no soldiers: it can't defend itself. Destroy base.\n", base->name); CP_BaseAttackMissionDestroyBase(mission); return; } UI_ExecuteConfunc("soldierlist_clear"); soldiers = 0; LIST_Foreach(hiredSoldiersInBase, employee_t, employee) { const rank_t *rank = CL_GetRankByIdx(employee->chr.score.rank); if (E_IsAwayFromBase(employee)) continue; UI_ExecuteConfunc("soldierlist_add %d \"%s %s\"", employee->chr.ucn, (rank) ? _(rank->shortname) : "", employee->chr.name); if (soldiers < 1) UI_ExecuteConfunc("team_select_ucn %d", employee->chr.ucn); soldiers++; } if (soldiers == 0) { Com_DPrintf(DEBUG_CLIENT, "CP_BaseAttackStartMission: Base '%s' has no soldiers at home: it can't defend itself. Destroy base.\n", base->name); CP_BaseAttackMissionDestroyBase(mission); return; } #if 0 /** @todo active this once more than 8 soldiers are working */ /* all soldiers in the base should get used */ baseAttackFakeAircraft.maxTeamSize = AIR_GetTeamSize(&baseAttackFakeAircraft); #endif LIST_Delete(&hiredSoldiersInBase); base->aircraftCurrent = &baseAttackFakeAircraft; MAP_SetMissionAircraft(&baseAttackFakeAircraft); /** @todo remove me - this is not needed because we are using the base->aircraftCurrent * pointer for resolving the aircraft - only CP_GameAutoGo needs this */ MAP_SetInterceptorAircraft(&baseAttackFakeAircraft); /* needed for updating soldier stats sa CP_UpdateCharacterStats*/ B_SetCurrentSelectedBase(base); /* needed for equipment menu */ Com_sprintf(popupText, sizeof(popupText), _("Base '%s' is under attack! What to do ?"), base->name); UI_RegisterText(TEXT_POPUP, popupText); CP_GameTimeStop(); UI_PushWindow("popup_baseattack", NULL, NULL); }
/** * @sa CL_ParseClientData */ static void CP_ParseCampaign (const char *name, const char **text) { const char *errhead = "CP_ParseCampaign: unexpected end of file (campaign "; campaign_t *cp; const char *token; int i; salary_t *s; bool drop = false; /* search for campaigns with same name */ for (i = 0; i < ccs.numCampaigns; i++) if (Q_streq(name, ccs.campaigns[i].id)) break; if (i < ccs.numCampaigns) { Com_Printf("CP_ParseCampaign: campaign def \"%s\" with same name found, second ignored\n", name); return; } if (ccs.numCampaigns >= MAX_CAMPAIGNS) { Com_Printf("CP_ParseCampaign: Max campaigns reached (%i)\n", MAX_CAMPAIGNS); return; } /* initialize the campaign */ cp = &ccs.campaigns[ccs.numCampaigns++]; OBJZERO(*cp); cp->idx = ccs.numCampaigns - 1; Q_strncpyz(cp->id, name, sizeof(cp->id)); /* some default values */ cp->team = TEAM_PHALANX; Q_strncpyz(cp->researched, "researched_human", sizeof(cp->researched)); cp->researchRate = 0.8f; cp->produceRate = 1.0f; cp->healingRate = 1.0f; cp->ufoReductionRate = NON_OCCURRENCE_PROBABILITY; cp->initialInterest = INITIAL_OVERALL_INTEREST; /* get it's body */ token = Com_Parse(text); if (!*text || *token != '{') { Com_Printf("CP_ParseCampaign: campaign def \"%s\" without body ignored\n", name); ccs.numCampaigns--; return; } /* set undefined markers */ s = &cp->salaries; for (i = 0; i < MAX_EMPL; i++) { s->base[i] = -1; s->rankBonus[i] = -1; s->admin[i] = -1; } s->aircraftFactor = -1; s->aircraftDivisor = -1; s->baseUpkeep = -1; s->adminInitial = -1; s->debtInterest = -1; do { token = cgi->Com_EParse(text, errhead, name); if (!*text) break; if (*token == '}') break; /* check for some standard values */ if (Com_ParseBlockToken(name, text, cp, campaign_vals, NULL, token)) { continue; } else if (Q_streq(token, "salary")) { CP_ParseSalary(token, text, s); } else if (Q_streq(token, "events")) { token = cgi->Com_EParse(text, errhead, name); if (!*text) return; cp->events = CP_GetEventsByID(token); } else { Com_Printf("CP_ParseCampaign: unknown token \"%s\" ignored (campaign %s)\n", token, name); cgi->Com_EParse(text, errhead, name); } } while (*text); if (cp->difficulty < -4) cp->difficulty = -4; else if (cp->difficulty > 4) cp->difficulty = 4; /* checking for undefined values */ for (i = 0; i < MAX_EMPL; i++) { if (s->base[i] == -1 || s->rankBonus[i] == -1 || s->admin[i] == -1) { drop = true; break; } } if (drop || s->aircraftFactor == -1 || s->aircraftDivisor == -1 || s->baseUpkeep == -1 || s->adminInitial == -1 || s->debtInterest == -1) { Com_Printf("CP_ParseCampaign: check salary definition. Campaign def \"%s\" ignored\n", name); ccs.numCampaigns--; return; } }
/** * @brief Register all save-subsystems and init some cvars and commands * @sa SAV_GameSave * @sa SAV_GameLoad */ void SAV_Init (void) { static saveSubsystems_t cp_subsystemXML = {"campaign", CP_SaveXML, CP_LoadXML}; static saveSubsystems_t rs_subsystemXML = {"research", RS_SaveXML, RS_LoadXML}; static saveSubsystems_t b_subsystemXML = {"base", B_SaveXML, B_LoadXML}; static saveSubsystems_t hos_subsystemXML = {"hospital", HOS_SaveXML, HOS_LoadXML}; static saveSubsystems_t bs_subsystemXML = {"market", BS_SaveXML, BS_LoadXML}; static saveSubsystems_t e_subsystemXML = {"employee", E_SaveXML, E_LoadXML}; static saveSubsystems_t ac_subsystemXML = {"aliencont", nullptr, AC_LoadXML}; static saveSubsystems_t pr_subsystemXML = {"production", PR_SaveXML, PR_LoadXML}; static saveSubsystems_t air_subsystemXML = {"aircraft", AIR_SaveXML, AIR_LoadXML}; static saveSubsystems_t ab_subsystemXML = {"alien base", AB_SaveXML, AB_LoadXML}; static saveSubsystems_t int_subsystemXML = {"interest", INT_SaveXML, INT_LoadXML}; static saveSubsystems_t mis_subsystemXML = {"mission", MIS_SaveXML, MIS_LoadXML}; static saveSubsystems_t ms_subsystemXML = {"messagesystem", MS_SaveXML, MS_LoadXML}; static saveSubsystems_t stats_subsystemXML = {"stats", STATS_SaveXML, STATS_LoadXML}; static saveSubsystems_t na_subsystemXML = {"nations", NAT_SaveXML, NAT_LoadXML}; static saveSubsystems_t trans_subsystemXML = {"transfer", TR_SaveXML, TR_LoadXML}; static saveSubsystems_t xvi_subsystemXML = {"xvirate", XVI_SaveXML, XVI_LoadXML}; static saveSubsystems_t ins_subsystemXML = {"installation", INS_SaveXML, INS_LoadXML}; static saveSubsystems_t mso_subsystemXML = {"messageoptions", MSO_SaveXML, MSO_LoadXML}; static saveSubsystems_t event_subsystemXML = {"triggerevents", CP_TriggerEventSaveXML, CP_TriggerEventLoadXML}; static saveSubsystems_t us_subsystemXML = {"ufostores", US_SaveXML, US_LoadXML}; saveSubsystemsAmount = 0; OBJZERO(saveSubsystems); Com_Printf("\n--- save subsystem initialization --\n"); /* don't mess with the order */ SAV_AddSubsystem(&cp_subsystemXML); SAV_AddSubsystem(&rs_subsystemXML); SAV_AddSubsystem(&b_subsystemXML); SAV_AddSubsystem(&hos_subsystemXML); SAV_AddSubsystem(&bs_subsystemXML); SAV_AddSubsystem(&e_subsystemXML); SAV_AddSubsystem(&ac_subsystemXML); SAV_AddSubsystem(&air_subsystemXML); SAV_AddSubsystem(&ab_subsystemXML); SAV_AddSubsystem(&int_subsystemXML); SAV_AddSubsystem(&ins_subsystemXML); SAV_AddSubsystem(&mis_subsystemXML); SAV_AddSubsystem(&us_subsystemXML); SAV_AddSubsystem(&pr_subsystemXML); SAV_AddSubsystem(&ms_subsystemXML); SAV_AddSubsystem(&stats_subsystemXML); SAV_AddSubsystem(&na_subsystemXML); SAV_AddSubsystem(&trans_subsystemXML); SAV_AddSubsystem(&xvi_subsystemXML); SAV_AddSubsystem(&mso_subsystemXML); SAV_AddSubsystem(&event_subsystemXML); /* Check whether there is a quicksave at all */ cgi->Cmd_AddCommand("game_quickloadinit", SAV_GameQuickLoadInit_f, "Load the game from the quick save slot."); cgi->Cmd_AddCommand("game_quicksave", SAV_GameQuickSave_f, "Save to the quick save slot."); cgi->Cmd_AddCommand("game_quickload", SAV_GameQuickLoad_f, "Load the game from the quick save slot."); cgi->Cmd_AddCommand("game_save", SAV_GameSave_f, "Saves to a given filename"); cgi->Cmd_AddCommand("game_load", SAV_GameLoad_f, "Loads a given filename"); cgi->Cmd_AddCommand("game_delete", SAV_GameDelete_f, "Deletes a given filename"); cgi->Cmd_AddCommand("game_comments", SAV_GameReadGameComments_f, "Loads the savegame names"); cgi->Cmd_AddCommand("game_continue", SAV_GameContinue_f, "Continue with the last saved game"); save_compressed = cgi->Cvar_Get("save_compressed", "1", CVAR_ARCHIVE, "Save the savefiles compressed if set to 1"); cl_lastsave = cgi->Cvar_Get("cl_lastsave", "", CVAR_ARCHIVE, "Last saved slot - use for the continue-campaign function"); }
/** * @brief Parses one "components" entry in a .ufo file and writes it into the next free entry in xxxxxxxx (components_t). * @param[in] name The unique id of a components_t array entry. * @param[in] text the whole following text after the "components" definition. * @sa CP_ParseScriptFirst */ static void CP_ParseComponents (const char *name, const char **text) { components_t *comp; const char *errhead = "CP_ParseComponents: unexpected end of file."; const char *token; /* get body */ token = Com_Parse(text); if (!*text || *token != '{') { Com_Printf("CP_ParseComponents: \"%s\" components def without body ignored.\n", name); return; } if (ccs.numComponents >= MAX_ASSEMBLIES) { Com_Printf("CP_ParseComponents: too many technology entries. limit is %i.\n", MAX_ASSEMBLIES); return; } /* New components-entry (next free entry in global comp-list) */ comp = &ccs.components[ccs.numComponents]; ccs.numComponents++; OBJZERO(*comp); /* name is not used */ do { /* get the name type */ token = cgi->Com_EParse(text, errhead, name); if (!*text) break; if (*token == '}') break; /* get values */ if (Q_streq(token, "aircraft")) { token = cgi->Com_EParse(text, errhead, name); if (!*text) break; /* set standard values */ Q_strncpyz(comp->assemblyId, token, sizeof(comp->assemblyId)); comp->assemblyItem = INVSH_GetItemByIDSilent(comp->assemblyId); if (comp->assemblyItem) Com_DPrintf(DEBUG_CLIENT, "CP_ParseComponents: linked item: %s with components: %s\n", token, comp->assemblyId); } else if (Q_streq(token, "item")) { /* Defines what items need to be collected for this item to be researchable. */ if (comp->numItemtypes < MAX_COMP) { /* Parse block */ component_type_data_t itemTokens; OBJZERO(itemTokens); if (Com_ParseBlock ("item", text, &itemTokens, components_type_vals, NULL)) { if (itemTokens.id[0] == '\0') cgi->Com_Error(ERR_DROP, "CP_ParseComponents: \"item\" token id is missing.\n"); if (itemTokens.amount[0] == '\0') cgi->Com_Error(ERR_DROP, "CP_ParseComponents: \"amount\" token id is missing.\n"); if (itemTokens.numbercrash[0] == '\0') cgi->Com_Error(ERR_DROP, "CP_ParseComponents: \"numbercrash\" token id is missing.\n"); comp->items[comp->numItemtypes] = INVSH_GetItemByID(itemTokens.id); /* item id -> item pointer */ /* Parse number of items. */ comp->itemAmount[comp->numItemtypes] = atoi(itemTokens.amount); /* If itemcount needs to be scaled */ if (itemTokens.numbercrash[0] == '%') comp->itemAmount2[comp->numItemtypes] = COMP_ITEMCOUNT_SCALED; else comp->itemAmount2[comp->numItemtypes] = atoi(itemTokens.numbercrash); /** @todo Set item links to NONE if needed */ /* comp->item_idx[comp->numItemtypes] = xxx */ comp->numItemtypes++; } } else { Com_Printf("CP_ParseComponents: \"%s\" Too many 'items' defined. Limit is %i - ignored.\n", name, MAX_COMP); } } else if (Q_streq(token, "time")) { /* Defines how long disassembly lasts. */ token = Com_Parse(text); comp->time = atoi(token); } else { Com_Printf("CP_ParseComponents: Error in \"%s\" - unknown token: \"%s\".\n", name, token); } } while (*text); if (comp->assemblyId[0] == '\0') { cgi->Com_Error(ERR_DROP, "CP_ParseComponents: component \"%s\" is not applied to any aircraft.\n", name); } }
void CIN_InitCinematic (cinematic_t* cin) { OBJZERO(*cin); }
/** * @brief Reset all characters in the static character array * @sa GAME_GetCharacterArraySize * @sa GAME_GetCharacter */ void GAME_ResetCharacters (void) { OBJZERO(characters); chrDisplayList.num = 0; }
/** * @brief Parse medals and ranks defined in the medals.ufo file. * @sa CL_ParseScriptFirst */ void CL_ParseRanks (const char* name, const char** text) { rank_t* rank; const char* errhead = "CL_ParseRanks: unexpected end of file (medal/rank "; const char* token; /* get name list body body */ token = Com_Parse(text); if (!*text || *token != '{') { Com_Printf("CL_ParseRanks: rank/medal \"%s\" without body ignored\n", name); return; } for (int i = 0; i < ccs.numRanks; i++) { if (Q_streq(name, ccs.ranks[i].name)) { Com_Printf("CL_ParseRanks: Rank with same name '%s' already loaded.\n", name); return; } } /* parse ranks */ if (ccs.numRanks >= MAX_RANKS) { Com_Printf("CL_ParseRanks: Too many rank descriptions, '%s' ignored.\n", name); ccs.numRanks = MAX_RANKS; return; } rank = &ccs.ranks[ccs.numRanks++]; OBJZERO(*rank); rank->id = cgi->PoolStrDup(name, cp_campaignPool, 0); rank->level = -1; do { /* get the name type */ token = cgi->Com_EParse(text, errhead, name); if (!*text) break; if (*token == '}') break; if (cgi->Com_ParseBlockToken(name, text, rank, rankValues, cp_campaignPool, token)) { continue; } else if (Q_streq(token, "type")) { /* employeeType_t */ token = cgi->Com_EParse(text, errhead, name); if (!*text) return; /* error check is performed in E_GetEmployeeType function */ rank->type = E_GetEmployeeType(token); } else Com_Printf("CL_ParseRanks: unknown token \"%s\" ignored (medal/rank %s)\n", token, name); } while (*text); if (rank->image == nullptr || !strlen(rank->image)) cgi->Com_Error(ERR_DROP, "CL_ParseRanks: image is missing for rank %s", rank->id); if (rank->name == nullptr || !strlen(rank->name)) cgi->Com_Error(ERR_DROP, "CL_ParseRanks: name is missing for rank %s", rank->id); if (rank->shortname == nullptr || !strlen(rank->shortname)) rank->shortname = rank->name; if (rank->level == -1) cgi->Com_Error(ERR_DROP, "CL_ParseRanks: level is missing for rank %s", rank->id); }
/** * @brief create a new framebuffer object * @param[in] width The width of the framebuffer * @param[in] height The height of the framebuffer * @param[in] ntextures The amount of textures for this framebuffer. See also the filters array. * @param[in] depth Also generate a depth buffer * @param[in] halfFloat Use half float pixel format * @param[in] filters Filters for the textures. Must have @c ntextures entries */ r_framebuffer_t * R_CreateFramebuffer (int width, int height, int ntextures, qboolean depth, qboolean halfFloat, unsigned int *filters) { r_framebuffer_t *buf; int i; if (!r_state.frameBufferObjectsInitialized) { Com_Printf("Warning: framebuffer creation failed; framebuffers not initialized!\n"); return NULL; } if (frameBufferObjectCount >= lengthof(frameBufferObjects)) { Com_Printf("Warning: framebuffer creation failed; already created too many framebuffers!\n"); return NULL; } buf = &frameBufferObjects[frameBufferObjectCount++]; OBJZERO(*buf); if (ntextures > r_config.maxDrawBuffers) { Com_Printf("Couldn't allocate requested number of drawBuffers in R_SetupFramebuffer!\n"); ntextures = r_config.maxDrawBuffers; } Vector4Clear(buf->clearColor); buf->width = width; buf->height = height; R_SetupViewport(buf, 0, 0, width, height); buf->nTextures = ntextures; buf->textures = (unsigned int *)Mem_Alloc(sizeof(unsigned int) * ntextures); buf->pixelFormat = halfFloat ? GL_RGBA16F_ARB : GL_RGBA8; buf->byteFormat = halfFloat ? GL_HALF_FLOAT_ARB : GL_UNSIGNED_BYTE; /* Presence of depth buffer indicates render target that could use antialiasing*/ if (depth) { /** @todo also check if we are running on older (SM2.0) hardware, which doesn't support antialiased MRT */ if (qglRenderbufferStorageMultisampleEXT && qglBlitFramebuffer) { int samples = min(4, max(0, r_multisample->integer)); if (samples>1) buf->samples = samples; } } for (i = 0; i < buf->nTextures; i++) { buf->textures[i] = R_GetFreeFBOTexture(); glBindTexture(GL_TEXTURE_2D, buf->textures[i]); glTexImage2D(GL_TEXTURE_2D, 0, buf->pixelFormat, buf->width, buf->height, 0, GL_RGBA, buf->byteFormat, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filters[i]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); qglGenerateMipmapEXT(GL_TEXTURE_2D); if (r_config.anisotropic) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_config.maxAnisotropic); R_CheckError(); } glBindTexture(GL_TEXTURE_2D, 0); /* create FBO itself */ qglGenFramebuffersEXT(1, &buf->fbo); R_CheckError(); qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buf->fbo); /* create&attach depth renderbuffer */ if (depth) { qglGenRenderbuffersEXT(1, &buf->depth); qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, buf->depth); if (buf->samples) qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, buf->samples, GL_DEPTH_COMPONENT, buf->width, buf->height); else qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, buf->width, buf->height); qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, buf->depth); } else { buf->depth = 0; } /* create multisample color buffers if needed */ if (buf->samples) { /* generate color buffers */ for (i = 0; i < buf->nTextures; i++) { unsigned colorbuffer; qglGenRenderbuffersEXT(1, &colorbuffer); qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorbuffer); qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, buf->samples, buf->pixelFormat, buf->width, buf->height); qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, colorAttachments[i], GL_RENDERBUFFER_EXT, colorbuffer); R_CheckError(); } /* proxy framebuffer object for resolving MSAA */ qglGenFramebuffersEXT(1, &buf->proxyFBO); R_CheckError(); qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, buf->proxyFBO); } /* Whether multisampling was enabled or not, current FBO should be populated with render-to-texture bindings */ for (i = 0; i < buf->nTextures; i++) { qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, colorAttachments[i], GL_TEXTURE_2D, buf->textures[i], 0); R_CheckError(); } R_CheckError(); /* unbind the framebuffer and return to default state */ qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); return buf; }
/** * @brief Copies an entry from the installation description file into the list of installation templates. * @note Parses one "installation" entry in the installation.ufo file and writes * it into the next free entry in installationTemplates. * @param[in] name Unique test-id of a installationTemplate_t. * @param[in] text the rest of the script file that is tokenized here */ void INS_ParseInstallations (const char *name, const char **text) { installationTemplate_t *installation; const char *errhead = "INS_ParseInstallations: unexpected end of file (names "; const char *token; int i; /* get id list body */ token = Com_Parse(text); if (!*text || *token != '{') { Com_Printf("INS_ParseInstallations: installation \"%s\" without body ignored\n", name); return; } if (!name) { Com_Printf("INS_ParseInstallations: installation name not specified.\n"); return; } if (ccs.numInstallationTemplates >= MAX_INSTALLATION_TEMPLATES) { Com_Printf("INS_ParseInstallations: too many installation templates\n"); ccs.numInstallationTemplates = MAX_INSTALLATION_TEMPLATES; /* just in case it's bigger. */ return; } for (i = 0; i < ccs.numInstallationTemplates; i++) { if (Q_streq(ccs.installationTemplates[i].name, name)) { Com_Printf("INS_ParseInstallations: Second installation with same name found (%s) - second ignored\n", name); return; } } /* new entry */ installation = &ccs.installationTemplates[ccs.numInstallationTemplates]; OBJZERO(*installation); installation->id = Mem_PoolStrDup(name, cp_campaignPool, 0); Com_DPrintf(DEBUG_CLIENT, "...found installation %s\n", installation->id); ccs.numInstallationTemplates++; do { /* get the name type */ token = Com_EParse(text, errhead, name); if (!*text) break; if (*token == '}') break; /* check for some standard values */ if (!Com_ParseBlockToken(name, text, installation, installation_vals, cp_campaignPool, token)) { /* other values */ if (Q_streq(token, "cost")) { char cvarname[MAX_VAR] = "mn_installation_"; Q_strcat(cvarname, installation->id, sizeof(cvarname)); Q_strcat(cvarname, "_cost", sizeof(cvarname)); token = Com_EParse(text, errhead, name); if (!*text) return; installation->cost = atoi(token); Cvar_Set(cvarname, va(_("%d c"), atoi(token))); } else if (Q_streq(token, "buildtime")) { char cvarname[MAX_VAR]; token = Com_EParse(text, errhead, name); if (!*text) return; installation->buildTime = atoi(token); Com_sprintf(cvarname, sizeof(cvarname), "mn_installation_%s_buildtime", installation->id); Cvar_Set(cvarname, va(ngettext("%d day", "%d days", atoi(token)), atoi(token))); } } } while (*text); }
void SetUp() { OBJZERO(*sv); }
void IN_JoystickMove (void) { bool joy_pressed[lengthof(joy_keys)]; unsigned int axes = 0; unsigned int hats = 0; int total = 0; int i = 0; /* check whether a user has changed the joystick number */ if (in_joystickNo->modified) IN_StartupJoystick(); /* check whether joysticks are disabled */ if (!in_joystick->integer) return; if (!stick) return; SDL_JoystickUpdate(); OBJZERO(joy_pressed); /* update the ball state */ total = SDL_JoystickNumBalls(stick); if (total > 0) { int balldx = 0; int balldy = 0; for (i = 0; i < total; i++) { int dx = 0; int dy = 0; SDL_JoystickGetBall(stick, i, &dx, &dy); balldx += dx; balldy += dy; } if (balldx || balldy) { mousePosX = balldx / viddef.rx; mousePosY = balldy / viddef.ry; } } /* now query the stick buttons... */ total = SDL_JoystickNumButtons(stick); if (total > 0) { if (total > lengthof(stick_state.buttons)) total = lengthof(stick_state.buttons); for (i = 0; i < total; i++) { const bool pressed = (SDL_JoystickGetButton(stick, i) != 0); if (pressed != stick_state.buttons[i]) { IN_EventEnqueue(K_JOY1 + i, 0, pressed); stick_state.buttons[i] = pressed; } } } /* look at the hats... */ total = SDL_JoystickNumHats(stick); if (total > 0) { if (total > 4) total = 4; for (i = 0; i < total; i++) ((Uint8 *)&hats)[i] = SDL_JoystickGetHat(stick, i); } /* update hat state */ if (hats != stick_state.oldhats) { for (i = 0; i < 4; i++) { if (((Uint8 *)&hats)[i] != ((Uint8 *)&stick_state.oldhats)[i]) { /* release event */ switch (((Uint8 *)&stick_state.oldhats)[i]) { case SDL_HAT_UP: IN_EventEnqueue(hat_keys[4 * i + 0], 0, false); break; case SDL_HAT_RIGHT: IN_EventEnqueue(hat_keys[4 * i + 1], 0, false); break; case SDL_HAT_DOWN: IN_EventEnqueue(hat_keys[4 * i + 2], 0, false); break; case SDL_HAT_LEFT: IN_EventEnqueue(hat_keys[4 * i + 3], 0, false); break; case SDL_HAT_RIGHTUP: IN_EventEnqueue(hat_keys[4 * i + 0], 0, false); IN_EventEnqueue(hat_keys[4 * i + 1], 0, false); break; case SDL_HAT_RIGHTDOWN: IN_EventEnqueue(hat_keys[4 * i + 2], 0, false); IN_EventEnqueue(hat_keys[4 * i + 1], 0, false); break; case SDL_HAT_LEFTUP: IN_EventEnqueue(hat_keys[4 * i + 0], 0, false); IN_EventEnqueue(hat_keys[4 * i + 3], 0, false); break; case SDL_HAT_LEFTDOWN: IN_EventEnqueue(hat_keys[4 * i + 2], 0, false); IN_EventEnqueue(hat_keys[4 * i + 3], 0, false); break; default: break; } /* press event */ switch (((Uint8 *)&hats)[i]) { case SDL_HAT_UP: IN_EventEnqueue(hat_keys[4 * i + 0], 0, true); break; case SDL_HAT_RIGHT: IN_EventEnqueue(hat_keys[4 * i + 1], 0, true); break; case SDL_HAT_DOWN: IN_EventEnqueue(hat_keys[4 * i + 2], 0, true); break; case SDL_HAT_LEFT: IN_EventEnqueue(hat_keys[4 * i + 3], 0, true); break; case SDL_HAT_RIGHTUP: IN_EventEnqueue(hat_keys[4 * i + 0], 0, true); IN_EventEnqueue(hat_keys[4 * i + 1], 0, true); break; case SDL_HAT_RIGHTDOWN: IN_EventEnqueue(hat_keys[4 * i + 2], 0, true); IN_EventEnqueue(hat_keys[4 * i + 1], 0, true); break; case SDL_HAT_LEFTUP: IN_EventEnqueue(hat_keys[4 * i + 0], 0, true); IN_EventEnqueue(hat_keys[4 * i + 3], 0, true); break; case SDL_HAT_LEFTDOWN: IN_EventEnqueue(hat_keys[4 * i + 2], 0, true); IN_EventEnqueue(hat_keys[4 * i + 3], 0, true); break; default: break; } } } } /* save hat state */ stick_state.oldhats = hats; /* finally, look at the axes... */ total = SDL_JoystickNumAxes(stick); if (total >= 2) { /* the first two axes are used for the cursor movement */ for (i = 0; i < 2; i++) { const Sint16 axis = SDL_JoystickGetAxis(stick, i); const float velocity = ((float) axis) / 32767.0f; if (velocity > -in_joystickThreshold->value && velocity < in_joystickThreshold->value) continue; if (i & 1) { mousePosY += in_joystickSpeed->value * velocity; if (mousePosY > (int)viddef.context.height) mousePosY = (int)viddef.context.height; else if (mousePosY < 0) mousePosY = 0; } else { mousePosX += in_joystickSpeed->value * velocity; if (mousePosX > (int)viddef.context.width) mousePosX = (int)viddef.context.width; else if (mousePosX < 0) mousePosX = 0; } } } if (total > 2) { if (total > 16) total = 16; /* every axis except the first two can be normally bound to an action */ for (i = 2; i < total; i++) { const Sint16 axis = SDL_JoystickGetAxis(stick, i); const float f = ((float) axis) / 32767.0f; if (f < -in_joystickThreshold->value) { axes |= (1 << (i * 2)); } else if (f > in_joystickThreshold->value) { axes |= (1 << ((i * 2) + 1)); } } } /* Time to update axes state based on old vs. new. */ if (axes != stick_state.oldaxes) { for (i = 2; i < 16; i++) { if ((axes & (1 << i)) && !(stick_state.oldaxes & (1 << i))) IN_EventEnqueue(joy_keys[i], 0, true); if (!(axes & (1 << i)) && (stick_state.oldaxes & (1 << i))) IN_EventEnqueue(joy_keys[i], 0, false); } } /* Save for future generations. */ stick_state.oldaxes = axes; }
/** * @brief Called after every player has joined */ void G_ResetClientData (void) { scoreMissionNum = 0; OBJZERO(scoreMission); }
/** * @brief A connection request that did not come from the master * @sa CL_ConnectionlessPacket */ static void SVC_DirectConnect (struct net_stream *stream) { char userinfo[MAX_INFO_STRING]; client_t *cl; player_t *player; int playernum; int version; qboolean connected; char buf[256]; const char *peername = NET_StreamPeerToName(stream, buf, sizeof(buf), qfalse); Com_DPrintf(DEBUG_SERVER, "SVC_DirectConnect()\n"); if (sv->started) { Com_Printf("rejected connect because match is already running\n"); NET_OOB_Printf(stream, "print\nGame has started already.\n"); return; } version = atoi(Cmd_Argv(1)); if (version != PROTOCOL_VERSION) { Com_Printf("rejected connect from version %i - %s\n", version, peername); NET_OOB_Printf(stream, "print\nServer is version %s.\n", UFO_VERSION); return; } Q_strncpyz(userinfo, Cmd_Argv(2), sizeof(userinfo)); if (userinfo[0] == '\0') { /* catch empty userinfo */ Com_Printf("Empty userinfo from %s\n", peername); NET_OOB_Printf(stream, "print\nConnection refused.\n"); return; } if (strchr(userinfo, '\xFF')) { /* catch end of message in string exploit */ Com_Printf("Illegal userinfo contained xFF from %s\n", peername); NET_OOB_Printf(stream, "print\nConnection refused.\n"); return; } if (strlen(Info_ValueForKey(userinfo, "ip"))) { /* catch spoofed ips */ Com_Printf("Illegal userinfo contained ip from %s\n", peername); NET_OOB_Printf(stream, "print\nConnection refused.\n"); return; } /* force the IP key/value pair so the game can filter based on ip */ Info_SetValueForKey(userinfo, sizeof(userinfo), "ip", peername); /* find a client slot */ cl = NULL; while ((cl = SV_GetNextClient(cl)) != NULL) if (cl->state == cs_free) break; if (cl == NULL) { NET_OOB_Printf(stream, "print\nServer is full.\n"); Com_Printf("Rejected a connection - server is full.\n"); return; } /* build a new connection - accept the new client * this is the only place a client_t is ever initialized */ OBJZERO(*cl); playernum = cl - SV_GetClient(0); player = PLAYER_NUM(playernum); cl->player = player; cl->player->num = playernum; TH_MutexLock(svs.serverMutex); connected = svs.ge->ClientConnect(player, userinfo, sizeof(userinfo)); TH_MutexUnlock(svs.serverMutex); /* get the game a chance to reject this connection or modify the userinfo */ if (!connected) { const char *rejmsg = Info_ValueForKey(userinfo, "rejmsg"); if (rejmsg[0] != '\0') { NET_OOB_Printf(stream, "print\n%s\nConnection refused.\n", rejmsg); Com_Printf("Game rejected a connection from %s. Reason: %s\n", peername, rejmsg); } else { NET_OOB_Printf(stream, "print\nConnection refused.\n"); Com_Printf("Game rejected a connection from %s.\n", peername); } return; } /* new player */ cl->player->inuse = qtrue; /* parse some info from the info strings */ strncpy(cl->userinfo, userinfo, sizeof(cl->userinfo) - 1); SV_UserinfoChanged(cl); /* send the connect packet to the client */ if (sv_http_downloadserver->string[0]) NET_OOB_Printf(stream, "client_connect dlserver=%s", sv_http_downloadserver->string); else NET_OOB_Printf(stream, "client_connect"); SV_SetClientState(cl, cs_connected); cl->lastconnect = svs.realtime; Q_strncpyz(cl->peername, peername, sizeof(cl->peername)); cl->stream = stream; NET_StreamSetData(stream, cl); }