/* * Directory listing. */ void FS_Dir_f(void) { char **dirnames; /* File list. */ char findname[1024]; /* File search path and pattern. */ char *path = NULL; /* Search path. */ char wildcard[1024] = "*.*"; /* File pattern. */ int i; /* Loop counter. */ int ndirs; /* Number of files in list. */ /* Check for pattern in arguments. */ if (Cmd_Argc() != 1) { Q_strlcpy(wildcard, Cmd_Argv(1), sizeof(wildcard)); } /* Scan search paths and list files. */ while ((path = FS_NextPath(path)) != NULL) { Com_sprintf(findname, sizeof(findname), "%s/%s", path, wildcard); Com_Printf("Directory of '%s'.\n", findname); Com_Printf("----\n"); if ((dirnames = FS_ListFiles(findname, &ndirs, 0, 0)) != 0) { for (i = 0; i < ndirs - 1; i++) { if (strrchr(dirnames[i], '/')) { Com_Printf("%s\n", strrchr(dirnames[i], '/') + 1); } else { Com_Printf("%s\n", dirnames[i]); } } FS_FreeList(dirnames, ndirs); } Com_Printf("\n"); } }
/* * origname: the filename to be opened, might be without extension * type: extension of the type we wanna open ("jpg", "png" or "tga") * pic: pointer RGBA pixel data will be assigned to */ qboolean LoadSTB(const char *origname, const char* type, byte **pic, int *width, int *height) { char filename[256]; Q_strlcpy(filename, origname, sizeof(filename)); /* Add the extension */ if (strcmp(COM_FileExtension(filename), type) != 0) { Q_strlcat(filename, ".", sizeof(filename)); Q_strlcat(filename, type, sizeof(filename)); } *pic = NULL; byte* rawdata = NULL; int rawsize = FS_LoadFile(filename, (void **)&rawdata); if (rawdata == NULL) { return false; } int w, h, bytesPerPixel; byte* data = NULL; data = stbi_load_from_memory(rawdata, rawsize, &w, &h, &bytesPerPixel, STBI_rgb_alpha); if (data == NULL) { VID_Printf(PRINT_ALL, "stb_image couldn't load data from %s: %s!\n", filename, stbi_failure_reason()); FS_FreeFile(rawdata); return false; } FS_FreeFile(rawdata); VID_Printf(PRINT_DEVELOPER, "LoadSTB() loaded: %s\n", filename); *pic = data; *width = w; *height = h; return true; }
void CPointBaseCommand::KeyValue(KeyValueData *pkvd) { // add this field to the command list if (m_uiCommandsCount < MAX_POINT_CMDS) { char command[128]; if (pkvd->szValue[0] != '\0' && Q_strcmp(pkvd->szValue, "-") != 0) { Q_snprintf(command, sizeof(command), "%s \"%s\"", pkvd->szKeyName, pkvd->szValue); } else { Q_strlcpy(command, pkvd->szKeyName); } m_iszCommands[m_uiCommandsCount++] = ALLOC_STRING(command); pkvd->fHandled = TRUE; return; } CPointEntity::KeyValue(pkvd); }
/* This fixes some problems with wrong tagged models and skins */ void CL_FixUpGender(void) { char *p; char sk[80]; if (gender_auto->value) { if (gender->modified) { /* was set directly, don't override the user */ gender->modified = false; return; } Q_strlcpy(sk, skin->string, sizeof(sk)); if ((p = strchr(sk, '/')) != NULL) { *p = 0; } if ((Q_stricmp(sk, "male") == 0) || (Q_stricmp(sk, "cyborg") == 0)) { Cvar_Set("gender", "male"); } else if ((Q_stricmp(sk, "female") == 0) || (Q_stricmp(sk, "crackhor") == 0)) { Cvar_Set("gender", "female"); } else { Cvar_Set("gender", "none"); } gender->modified = false; } }
/* * Resend a connect message if the last one has timed out */ void CL_CheckForResend(void) { netadr_t adr; /* if the local server is running and we aren't just connect */ if ((cls.state == ca_disconnected) && Com_ServerState()) { cls.state = ca_connecting; Q_strlcpy(cls.servername, "localhost", sizeof(cls.servername)); /* we don't need a challenge on the localhost */ CL_SendConnectPacket(); return; } /* resend if we haven't gotten a reply yet */ if (cls.state != ca_connecting) { return; } if (cls.realtime - cls.connect_time < 3000) { return; } if (!NET_StringToAdr(cls.servername, &adr)) { Com_Printf("Bad server address\n"); cls.state = ca_disconnected; return; } if (adr.port == 0) { adr.port = BigShort(PORT_SERVER); } cls.connect_time = cls.realtime; Com_Printf("Connecting to %s...\n", cls.servername); Netchan_OutOfBandPrint(NS_CLIENT, adr, "getchallenge\n"); }
/* * Finds the file in the search path. Returns filesize and an open FILE *. Used * for streaming data out of either a pak file or a seperate file. */ int FS_FOpenFile(const char *name, fileHandle_t *f, fsMode_t mode) { int size = 0; fsHandle_t *handle; handle = FS_HandleForFile(name, f); Q_strlcpy(handle->name, name, sizeof(handle->name)); handle->mode = mode; switch (mode) { case FS_READ: size = FS_FOpenFileRead(handle); break; case FS_WRITE: size = FS_FOpenFileWrite(handle); break; case FS_APPEND: size = FS_FOpenFileAppend(handle); break; default: Com_Error(ERR_FATAL, "FS_FOpenFile: bad mode (%i)", mode); break; } if (size != -1) { return size; } /* Couldn't open, so free the handle. */ memset(handle, 0, sizeof(*handle)); *f = 0; return -1; }
bool SystemWrapper::RegisterCommand(char *name, ISystemModule *module, int commandID) { command_t *cmd = (command_t *)m_Commands.GetFirst(); while (cmd) { if (Q_stricmp(cmd->name, name) == 0) { Printf("WARNING! System::RegisterCommand: command \"%s\" already exists.\n", name); return false; } cmd = (command_t *)m_Commands.GetNext(); } cmd = (command_t *)Mem_ZeroMalloc(sizeof(command_t)); Q_strlcpy(cmd->name, name); cmd->module = module; cmd->commandID = commandID; m_Commands.Add(cmd); Cmd_AddWrapperCommand(cmd->name, SystemWrapper_CommandForwarder); return true; }
/* * Takes an explicit (not game tree related) path to a pack file. * * Loads the header and directory, adding the files at the beginning of the list * so they override previous pack files. */ fsPack_t * FS_LoadPK3(const char *packPath) { char fileName[MAX_QPATH]; /* File name. */ int i = 0; /* Loop counter. */ int numFiles; /* Number of files in PK3. */ int status; /* Error indicator. */ fsPackFile_t *files; /* List of files in PK3. */ fsPack_t *pack; /* PK3 file. */ unzFile *handle; /* Zip file handle. */ unz_file_info info; /* Zip file info. */ unz_global_info global; /* Zip file global info. */ handle = unzOpen(packPath); if (handle == NULL) { return NULL; } if (unzGetGlobalInfo(handle, &global) != UNZ_OK) { unzClose(handle); Com_Error(ERR_FATAL, "FS_LoadPK3: '%s' is not a pack file", packPath); } numFiles = global.number_entry; if ((numFiles > MAX_FILES_IN_PACK) || (numFiles == 0)) { unzClose(handle); Com_Error(ERR_FATAL, "FS_LoadPK3: '%s' has %i files", packPath, numFiles); } files = Z_Malloc(numFiles * sizeof(fsPackFile_t)); /* Parse the directory. */ status = unzGoToFirstFile(handle); while (status == UNZ_OK) { fileName[0] = '\0'; unzGetCurrentFileInfo(handle, &info, fileName, MAX_QPATH, NULL, 0, NULL, 0); Q_strlcpy(files[i].name, fileName, sizeof(files[i].name)); files[i].offset = -1; /* Not used in ZIP files */ files[i].size = info.uncompressed_size; i++; status = unzGoToNextFile(handle); } pack = Z_Malloc(sizeof(fsPack_t)); Q_strlcpy(pack->name, packPath, sizeof(pack->name)); pack->pak = NULL; pack->pk3 = handle; pack->numFiles = numFiles; pack->files = files; Com_Printf("Added packfile '%s' (%i files).\n", pack, numFiles); return pack; }
/* * Takes an explicit (not game tree related) path to a pak file. * * Loads the header and directory, adding the files at the beginning of the * list so they override previous pack files. */ fsPack_t * FS_LoadPAK(const char *packPath) { int i; /* Loop counter. */ int numFiles; /* Number of files in PAK. */ FILE *handle; /* File handle. */ fsPackFile_t *files; /* List of files in PAK. */ fsPack_t *pack; /* PAK file. */ dpackheader_t header; /* PAK file header. */ dpackfile_t info[MAX_FILES_IN_PACK]; /* PAK info. */ handle = fopen(packPath, "rb"); if (handle == NULL) { return NULL; } fread(&header, 1, sizeof(dpackheader_t), handle); if (LittleLong(header.ident) != IDPAKHEADER) { fclose(handle); Com_Error(ERR_FATAL, "FS_LoadPAK: '%s' is not a pack file", packPath); } header.dirofs = LittleLong(header.dirofs); header.dirlen = LittleLong(header.dirlen); numFiles = header.dirlen / sizeof(dpackfile_t); if ((numFiles > MAX_FILES_IN_PACK) || (numFiles == 0)) { fclose(handle); Com_Error(ERR_FATAL, "FS_LoadPAK: '%s' has %i files", packPath, numFiles); } files = Z_Malloc(numFiles * sizeof(fsPackFile_t)); fseek(handle, header.dirofs, SEEK_SET); fread(info, 1, header.dirlen, handle); /* Parse the directory. */ for (i = 0; i < numFiles; i++) { Q_strlcpy(files[i].name, info[i].name, sizeof(files[i].name)); files[i].offset = LittleLong(info[i].filepos); files[i].size = LittleLong(info[i].filelen); } pack = Z_Malloc(sizeof(fsPack_t)); Q_strlcpy(pack->name, packPath, sizeof(pack->name)); pack->pak = handle; #ifdef ZIP pack->pk3 = NULL; #endif pack->numFiles = numFiles; pack->files = files; Com_Printf("Added packfile '%s' (%i files).\n", pack, numFiles); return pack; }
/* ================ SV_SpawnServer Change the server to a new map, taking all connected clients along with it. ================ */ void SV_SpawnServer( cm_t *cm, const char *server, const char *spawnpoint ) { int i; client_t *client; #if USE_CLIENT SCR_BeginLoadingPlaque(); // for local system #endif Com_Printf( "------- Server Initialization -------\n" ); Com_Printf( "SpawnServer: %s\n", server ); // everyone needs to reconnect FOR_EACH_CLIENT( client ) { SV_ClientReset( client ); } SV_BroadcastCommand( "changing map=%s\n", server ); SV_SendClientMessages(); SV_SendAsyncPackets(); // free current level CM_FreeMap( &sv.cm ); SV_FreeFile( sv.entitystring ); // wipe the entire per-level structure memset( &sv, 0, sizeof( sv ) ); sv.spawncount = ( rand() | ( rand() << 16 ) ) ^ Sys_Milliseconds(); sv.spawncount &= 0x7FFFFFFF; // set legacy spawncounts FOR_EACH_CLIENT( client ) { client->spawncount = sv.spawncount; } // reset entity counter svs.next_entity = 0; #if USE_FPS // set framerate parameters set_frame_time(); #endif // save name for levels that don't set message Q_strlcpy( sv.configstrings[CS_NAME], server, MAX_QPATH ); Q_strlcpy( sv.name, server, sizeof( sv.name ) ); if( Cvar_VariableInteger( "deathmatch" ) ) { sprintf( sv.configstrings[CS_AIRACCEL], "%d", sv_airaccelerate->integer ); } else { strcpy( sv.configstrings[CS_AIRACCEL], "0" ); } #if !USE_CLIENT resolve_masters(); #endif override_entity_string( server ); sv.cm = *cm; sprintf( sv.configstrings[CS_MAPCHECKSUM], "%d", ( int )cm->cache->checksum ); // set inline model names Q_concat( sv.configstrings[CS_MODELS + 1], MAX_QPATH, "maps/", server, ".bsp", NULL ); for( i = 1; i < cm->cache->nummodels; i++ ) { sprintf( sv.configstrings[ CS_MODELS + 1 + i ], "*%d", i ); } // // clear physics interaction links // SV_ClearWorld(); // // spawn the rest of the entities on the map // // precache and static commands can be issued during // map initialization sv.state = ss_loading; X86_PUSH_FPCW; X86_SINGLE_FPCW; // load and spawn all other entities ge->SpawnEntities ( sv.name, sv.entitystring ? sv.entitystring : cm->cache->entitystring, spawnpoint ); // run two frames to allow everything to settle ge->RunFrame (); sv.framenum++; ge->RunFrame (); sv.framenum++; X86_POP_FPCW; // make sure maxclients string is correct sprintf( sv.configstrings[CS_MAXCLIENTS], "%d", sv_maxclients->integer ); // all precaches are complete sv.state = ss_game; #if USE_MVD_SERVER // respawn dummy MVD client, set base states, etc SV_MvdMapChanged(); #endif // set serverinfo variable SV_InfoSet( "mapname", sv.name ); SV_InfoSet( "port", net_port->string ); Cvar_SetInteger( sv_running, ss_game, FROM_CODE ); Cvar_Set( "sv_paused", "0" ); Cvar_Set( "timedemo", "0" ); EXEC_TRIGGER( sv_changemapcmd ); #if USE_SYSCON SV_SetConsoleTitle(); #endif SV_BroadcastCommand( "reconnect\n" ); Com_Printf ("-------------------------------------\n"); }
/* * A connection request that did not come from the master */ void SVC_DirectConnect(void) { char userinfo[MAX_INFO_STRING]; netadr_t adr; int i; client_t *cl, *newcl; client_t temp; edict_t *ent; int edictnum; int version; int qport; int challenge; adr = net_from; Com_DPrintf("SVC_DirectConnect ()\n"); version = (int)strtol(Cmd_Argv(1), (char **)NULL, 10); if (version != PROTOCOL_VERSION) { Netchan_OutOfBandPrint(NS_SERVER, adr, "print\nServer is version %s.\n", YQ2VERSION); Com_DPrintf(" rejected connect from version %i\n", version); return; } qport = (int)strtol(Cmd_Argv(2), (char **)NULL, 10); challenge = (int)strtol(Cmd_Argv(3), (char **)NULL, 10); Q_strlcpy(userinfo, Cmd_Argv(4), sizeof(userinfo)); /* force the IP key/value pair so the game can filter based on ip */ Info_SetValueForKey(userinfo, "ip", NET_AdrToString(net_from)); /* attractloop servers are ONLY for local clients */ if (sv.attractloop) { if (!NET_IsLocalAddress(adr)) { Com_Printf("Remote connect in attract loop. Ignored.\n"); Netchan_OutOfBandPrint(NS_SERVER, adr, "print\nConnection refused.\n"); return; } } /* see if the challenge is valid */ if (!NET_IsLocalAddress(adr)) { for (i = 0; i < MAX_CHALLENGES; i++) { if (NET_CompareBaseAdr(net_from, svs.challenges[i].adr)) { if (challenge == svs.challenges[i].challenge) { break; /* good */ } Netchan_OutOfBandPrint(NS_SERVER, adr, "print\nBad challenge.\n"); return; } } if (i == MAX_CHALLENGES) { Netchan_OutOfBandPrint(NS_SERVER, adr, "print\nNo challenge for address.\n"); return; } } newcl = &temp; memset(newcl, 0, sizeof(client_t)); /* if there is already a slot for this ip, reuse it */ for (i = 0, cl = svs.clients; i < maxclients->value; i++, cl++) { if (cl->state < cs_connected) { continue; } if (NET_CompareBaseAdr(adr, cl->netchan.remote_address) && ((cl->netchan.qport == qport) || (adr.port == cl->netchan.remote_address.port))) { if (!NET_IsLocalAddress(adr)) { Com_DPrintf("%s:reconnect rejected : too soon\n", NET_AdrToString(adr)); return; } Com_Printf("%s:reconnect\n", NET_AdrToString(adr)); newcl = cl; goto gotnewcl; } } /* find a client slot */ newcl = NULL; for (i = 0, cl = svs.clients; i < maxclients->value; i++, cl++) { if (cl->state == cs_free) { newcl = cl; break; } } if (!newcl) { Netchan_OutOfBandPrint(NS_SERVER, adr, "print\nServer is full.\n"); Com_DPrintf("Rejected a connection.\n"); return; } gotnewcl: /* build a new connection accept the new client this is the only place a client_t is ever initialized */ *newcl = temp; sv_client = newcl; edictnum = (newcl - svs.clients) + 1; ent = EDICT_NUM(edictnum); newcl->edict = ent; newcl->challenge = challenge; /* save challenge for checksumming */ /* get the game a chance to reject this connection or modify the userinfo */ if (!(ge->ClientConnect(ent, userinfo))) { if (*Info_ValueForKey(userinfo, "rejmsg")) { Netchan_OutOfBandPrint(NS_SERVER, adr, "print\n%s\nConnection refused.\n", Info_ValueForKey(userinfo, "rejmsg")); } else { Netchan_OutOfBandPrint(NS_SERVER, adr, "print\nConnection refused.\n"); } Com_DPrintf("Game rejected a connection.\n"); return; } /* parse some info from the info strings */ Q_strlcpy(newcl->userinfo, userinfo, sizeof(newcl->userinfo)); SV_UserinfoChanged(newcl); /* send the connect packet to the client */ Netchan_OutOfBandPrint(NS_SERVER, adr, "client_connect"); Netchan_Setup(NS_SERVER, &newcl->netchan, adr, qport); newcl->state = cs_connected; SZ_Init(&newcl->datagram, newcl->datagram_buf, sizeof(newcl->datagram_buf)); newcl->datagram.allowoverflow = true; newcl->lastmessage = svs.realtime; /* don't timeout */ newcl->lastconnect = svs.realtime; }
void PlayerModel_Load(void) { char scratch[MAX_QPATH]; size_t len; int ndirs = 0; char *dirnames[MAX_PLAYERMODELS]; int i, j; char **list; char *s, *p; int numFiles; playerModelInfo_t *pmi; uis.numPlayerModels = 0; // get a list of directories if (!(list = (char **)FS_ListFiles(NULL, "players/*/tris.md2", FS_SEARCH_BYFILTER | FS_SEARCH_SAVEPATH, &numFiles))) { return; } for (i = 0; i < numFiles; i++) { len = Q_strlcpy(scratch, list[i], sizeof(scratch)); if (len >= sizeof(scratch)) continue; // make short name for the model if (!(s = strchr(scratch, '/'))) continue; s++; if (!(p = strchr(s, '/'))) continue; *p = 0; for (j = 0; j < ndirs; j++) { if (!strcmp(dirnames[j], s)) { break; } } if (j != ndirs) { continue; } dirnames[ndirs++] = UI_CopyString(s); if (ndirs == MAX_PLAYERMODELS) { break; } } FS_FreeList((void **)list); if (!ndirs) { return; } // go through the subdirectories for (i = 0; i < ndirs; i++) { int k, s; char **pcxnames; char **skinnames; int npcxfiles; int nskins = 0; // verify the existence of tris.md2 Q_concat(scratch, sizeof(scratch), "players/", dirnames[i], "/tris.md2", NULL); if (!FS_FileExists(scratch)) { goto skip; } // verify the existence of at least one pcx skin Q_concat(scratch, sizeof(scratch), "players/", dirnames[i], NULL); pcxnames = (char **)FS_ListFiles(scratch, ".pcx", 0, &npcxfiles); if (!pcxnames) { goto skip; } // count valid skins, which consist of a skin with a matching "_i" icon for (k = 0; k < npcxfiles; k++) { if (!strstr(pcxnames[k], "_i.pcx")) { if (IconOfSkinExists(pcxnames[k], pcxnames, npcxfiles)) { nskins++; } } } if (!nskins) { FS_FreeList((void **)pcxnames); goto skip; } skinnames = UI_Malloc(sizeof(char *) * (nskins + 1)); skinnames[nskins] = NULL; // copy the valid skins for (s = 0, k = 0; k < npcxfiles; k++) { if (!strstr(pcxnames[k], "_i.pcx")) { if (IconOfSkinExists(pcxnames[k], pcxnames, npcxfiles)) { COM_StripExtension(scratch, pcxnames[k], sizeof(scratch)); skinnames[s++] = UI_CopyString(scratch); } } } FS_FreeList((void **)pcxnames); // at this point we have a valid player model pmi = &uis.pmi[uis.numPlayerModels++]; pmi->nskins = nskins; pmi->skindisplaynames = skinnames; pmi->directory = dirnames[i]; continue; skip: Z_Free(dirnames[i]); } qsort(uis.pmi, uis.numPlayerModels, sizeof(uis.pmi[0]), pmicmpfnc); }
/* ================== CON_ConsoleInput ================== */ char *CON_ConsoleInput (void) { INPUT_RECORD buff[MAXCMDLINE]; DWORD count = 0, events = 0; WORD key = 0; int i; int newlinepos = -1; if (!GetNumberOfConsoleInputEvents(qconsole_hin, &events)) return NULL; if (events < 1) return NULL; // if we have overflowed, start dropping oldest input events if (events >= MAXCMDLINE) { ReadConsoleInput(qconsole_hin, buff, 1, &events); return NULL; } if (!ReadConsoleInput(qconsole_hin, buff, events, &count)) return NULL; FlushConsoleInputBuffer(qconsole_hin); for (i = 0; i < count; i++) { if (buff[i].EventType != KEY_EVENT) continue; if (!buff[i].Event.KeyEvent.bKeyDown) continue; key = buff[i].Event.KeyEvent.wVirtualKeyCode; if (key == VK_RETURN) { newlinepos = i; break; } else if (key == VK_UP) { CON_HistPrev(); break; } else if (key == VK_DOWN) { CON_HistNext(); break; } else if (key == VK_TAB) { // command completion field_t f; Field_Clear(&f); Q_strlcpy(f.buffer, qconsole_line, sizeof(f.buffer)); Field_AutoComplete(&f); Q_strlcpy(qconsole_line, f.buffer, sizeof(qconsole_line)); qconsole_linelen = strlen(qconsole_line); break; } if (qconsole_linelen < sizeof(qconsole_line) - 1) { char c = buff[i].Event.KeyEvent.uChar.AsciiChar; if (key == VK_BACK) { int pos = (qconsole_linelen > 0) ? qconsole_linelen - 1 : 0; qconsole_line[pos] = '\0'; qconsole_linelen = pos; } else if (c) { qconsole_line[qconsole_linelen++] = c; qconsole_line[qconsole_linelen] = '\0'; } } } if (newlinepos < 0) { CON_Show(); return NULL; } if (!qconsole_linelen) { CON_Show(); Com_Printf("\n"); return NULL; } qconsole_linelen = 0; CON_Show(); CON_HistAdd(); Com_Printf("%s\n", qconsole_line); return qconsole_line; }
/* * Creates a server's entity / program execution context by * parsing textual entity definitions out of an ent file. */ void SpawnEntities(const char *mapname, char *entities, const char *spawnpoint) { edict_t *ent; int inhibit; const char *com_token; int i; float skill_level; if (!mapname || !entities || !spawnpoint) { return; } skill_level = floor(skill->value); if (skill_level < 0) { skill_level = 0; } if (skill_level > 3) { skill_level = 3; } if (skill->value != skill_level) { Cvar_ForceSet("skill", va("%f", skill_level)); } SaveClientData(); Z_FreeTags(TAG_LEVEL); memset(&level, 0, sizeof(level)); memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); Q_strlcpy(level.mapname, mapname, sizeof(level.mapname)); Q_strlcpy(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)); /* set client fields on player ents */ for (i = 0; i < game.maxclients; i++) { g_edicts[i + 1].client = game.clients + i; } ent = NULL; inhibit = 0; /* parse ents */ while (1) { /* parse the opening brace */ com_token = COM_Parse(&entities); if (!entities) { break; } if (com_token[0] != '{') { PF_error("ED_LoadFromFile: found %s when expecting {", com_token); } if (!ent) { ent = g_edicts; } else { ent = G_Spawn(); } entities = ED_ParseEdict(entities, ent); /* remove things (except the world) from different skill levels or deathmatch */ if (ent != g_edicts) { if (deathmatch->value) { if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) { G_FreeEdict(ent); inhibit++; continue; } } else { if (((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD))) { G_FreeEdict(ent); inhibit++; continue; } } ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH); } ED_CallSpawn(ent); } PF_dprintf("%i entities inhibited.\n", inhibit); G_FindTeams(); PlayerTrail_Init(); }
/* * Adds the directory to the head of the path, then loads and adds pak1.pak * pak2.pak ... * * Extended all functionality to include Quake III .pk3 */ void FS_AddGameDirectory(const char *dir) { char **list; /* File list. */ char path[MAX_OSPATH]; /* Path to PAK / PK3. */ int i, j; /* Loop counters. */ int nfiles; /* Number of files in list. */ fsSearchPath_t *search; /* Search path. */ fsPack_t *pack; /* PAK / PK3 file. */ pack = NULL; /* Set game directory. */ Q_strlcpy(fs_gamedir, dir, sizeof(fs_gamedir)); /* Create directory if it does not exist. */ FS_CreatePath(fs_gamedir); /* Add the directory to the search path. */ search = Z_Malloc(sizeof(fsSearchPath_t)); Q_strlcpy(search->path, dir, sizeof(search->path)); search->next = fs_searchPaths; fs_searchPaths = search; /* Add numbered pack files in sequence. */ for (i = 0; i < sizeof(fs_packtypes) / sizeof(fs_packtypes[0]); i++) { for (j = 0; j < MAX_PAKS; j++) { Com_sprintf(path, sizeof(path), "%s/pak%d.%s", dir, j, fs_packtypes[i].suffix); switch (fs_packtypes[i].format) { case PAK: pack = FS_LoadPAK(path); break; #ifdef ZIP case PK3: pack = FS_LoadPK3(path); break; #endif } if (pack == NULL) { continue; } search = Z_Malloc(sizeof(fsSearchPath_t)); search->pack = pack; search->next = fs_searchPaths; fs_searchPaths = search; } } /* Add not numbered pack files. */ for (i = 0; i < sizeof(fs_packtypes) / sizeof(fs_packtypes[0]); i++) { Com_sprintf(path, sizeof(path), "%s/*.%s", dir, fs_packtypes[i].suffix); if ((list = FS_ListFiles(path, &nfiles, 0, SFF_SUBDIR)) == NULL) { continue; } Com_sprintf(path, sizeof(path), "%s/pak*.%s", dir, fs_packtypes[i].suffix); for (j = 0; j < nfiles - 1; j++) { /* Skip numbered packs. */ if (glob_match(path, list[j])) { continue; } switch (fs_packtypes[i].format) { case PAK: pack = FS_LoadPAK(list[j]); break; #ifdef ZIP case PK3: pack = FS_LoadPK3(list[j]); break; #endif } if (pack == NULL) { continue; } search = Z_Malloc(sizeof(fsSearchPath_t)); search->pack = pack; search->next = fs_searchPaths; fs_searchPaths = search; } FS_FreeList(list, nfiles); } }
/* ============== SpawnEntities Creates a server's entity / program execution context by parsing textual entity definitions out of an ent file. ============== */ void G_SpawnEntities(const char *mapname, const char *entities, const char *spawnpoint) { edict_t *ent; gclient_t *client; int i; client_persistant_t pers; char *token; char playerskin[MAX_QPATH]; #if USE_SQLITE G_OpenDatabase(); G_LogClients(); #endif gi.FreeTags(TAG_LEVEL); memset(&level, 0, sizeof(level)); memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); Q_strlcpy(level.mapname, mapname, sizeof(level.mapname)); G_LoadScores(); // set client fields on player ents for (i = 0; i < game.maxclients; i++) { ent = &g_edicts[i + 1]; client = &game.clients[i]; ent->client = client; ent->inuse = qfalse; if (!client->pers.connected) { continue; } // clear everything but the persistant data pers = client->pers; memset(client, 0, sizeof(*client)); client->pers = pers; client->edict = ent; client->clientNum = i; client->pers.connected = CONN_CONNECTED; // combine name and skin into a configstring Q_concat(playerskin, sizeof(playerskin), client->pers.netname, "\\", client->pers.skin, NULL); gi.configstring(CS_PLAYERSKINS + i, playerskin); gi.configstring(CS_PLAYERNAMES + i, client->pers.netname); } // parse worldspawn token = COM_Parse(&entities); if (!entities) gi.error("%s: empty entity string", __func__); if (token[0] != '{') gi.error("%s: found %s when expecting {", __func__, token); ent = g_edicts; ED_ParseEdict(&entities, ent); ED_CallSpawn(ent); level.entstring = entities; G_ParseString(); G_FindTeams(); //G_UpdateItemBans(); // find spawnpoints ent = NULL; while ((ent = G_Find(ent, FOFS(classname), "info_player_deathmatch")) != NULL) { level.spawns[level.numspawns++] = ent; if (level.numspawns == MAX_SPAWNS) { break; } } gi.dprintf("%d spawn points\n", level.numspawns); }
/* * Saves the state of the map just being exited and goes to a new map. * * If the initial character of the map string is '*', the next map is * in a new unit, so the current savegame directory is cleared of * map files. * * Example: * inter.cin+jail * * Clears the archived maps, plays the inter.cin cinematic, then * goes to map jail.bsp. */ void SV_GameMap_f(void) { char *map; int i; client_t *cl; qboolean *savedInuse; if (Cmd_Argc() != 2) { Com_Printf("USAGE: gamemap <map>\n"); return; } Com_DPrintf("SV_GameMap(%s)\n", Cmd_Argv(1)); FS_CreatePath(va("%s/save/current/", FS_Gamedir())); /* check for clearing the current savegame */ map = Cmd_Argv(1); if (map[0] == '*') { /* wipe all the *.sav files */ SV_WipeSavegame("current"); } else { /* save the map just exited */ if (sv.state == ss_game) { /* clear all the client inuse flags before saving so that when the level is re-entered, the clients will spawn at spawn points instead of occupying body shells */ savedInuse = malloc(maxclients->value * sizeof(qboolean)); for (i = 0, cl = svs.clients; i < maxclients->value; i++, cl++) { savedInuse[i] = cl->edict->inuse; cl->edict->inuse = false; } SV_WriteLevelFile(); /* we must restore these for clients to transfer over correctly */ for (i = 0, cl = svs.clients; i < maxclients->value; i++, cl++) { cl->edict->inuse = savedInuse[i]; } free(savedInuse); } } /* start up the next map */ SV_Map(false, Cmd_Argv(1), false); /* archive server state */ Q_strlcpy(svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)); /* copy off the level to the autosave slot */ if (!dedicated->value) { SV_WriteServerFile(true); SV_CopySaveGame("current", "save0"); } }
/* * Windows main function. Containts the * initialization code and the main loop */ int main(int argc, char **argv) { // Setup FPU if necessary. Sys_SetupFPU(); // Force DPI awareness. Sys_SetHighDPIMode(); // crappy argument parser can't parse. for (int i = 0; i < argc; i++) { // Are we portable? if (strcmp(argv[i], "-portable") == 0) { is_portable = true; } // Inject a custom data dir. if (strcmp(argv[i], "-datadir") == 0) { // Mkay, did the user give us an argument? if (i != (argc - 1)) { DWORD attrib; WCHAR wpath[MAX_OSPATH]; MultiByteToWideChar(CP_UTF8, 0, argv[i + 1], -1, wpath, MAX_OSPATH); attrib = GetFileAttributesW(wpath); if (attrib != INVALID_FILE_ATTRIBUTES) { if (!(attrib & FILE_ATTRIBUTE_DIRECTORY)) { printf("-datadir %s is not a directory\n", argv[i + 1]); return 1; } Q_strlcpy(datadir, argv[i + 1], MAX_OSPATH); } else { printf("-datadir %s could not be found\n", argv[i + 1]); return 1; } } else { printf("-datadir needs an argument\n"); return 1; } } } // Need to redirect stdout before anything happens. #ifndef DEDICATED_ONLY Sys_RedirectStdout(); #endif // Call the initialization code. // Never returns. Qcommon_Init(argc, argv); return 0; }
void LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height) { byte *raw; pcx_t *pcx; int x, y; int len, full_size; int pcx_width, pcx_height; qboolean image_issues = false; int dataByte, runLength; byte *out, *pix; char filename[256]; Q_strlcpy(filename, origname, sizeof(filename)); /* Add the extension */ if (strcmp(COM_FileExtension(filename), "pcx")) { Q_strlcat(filename, ".pcx", sizeof(filename)); } *pic = NULL; if (palette) { *palette = NULL; } /* load the file */ len = FS_LoadFile(filename, (void **) &raw); if (!raw || len < sizeof(pcx_t)) { R_Printf(PRINT_DEVELOPER, "Bad pcx file %s\n", filename); return; } /* parse the PCX file */ pcx = (pcx_t *) raw; pcx->xmin = LittleShort(pcx->xmin); pcx->ymin = LittleShort(pcx->ymin); pcx->xmax = LittleShort(pcx->xmax); pcx->ymax = LittleShort(pcx->ymax); pcx->hres = LittleShort(pcx->hres); pcx->vres = LittleShort(pcx->vres); pcx->bytes_per_line = LittleShort(pcx->bytes_per_line); pcx->palette_type = LittleShort(pcx->palette_type); raw = &pcx->data; pcx_width = pcx->xmax - pcx->xmin; pcx_height = pcx->ymax - pcx->ymin; if ((pcx->manufacturer != 0x0a) || (pcx->version != 5) || (pcx->encoding != 1) || (pcx->bits_per_pixel != 8) || (pcx_width >= 4096) || (pcx_height >= 4096)) { R_Printf(PRINT_ALL, "Bad pcx file %s\n", filename); FS_FreeFile(pcx); return; } full_size = (pcx_height + 1) * (pcx_width + 1); out = malloc(full_size); if (!out) { R_Printf(PRINT_ALL, "Can't allocate\n"); FS_FreeFile(pcx); return; } *pic = out; pix = out; if (palette) { *palette = malloc(768); if (!(*palette)) { R_Printf(PRINT_ALL, "Can't allocate\n"); free(out); FS_FreeFile(pcx); return; } if (len > 768) { memcpy(*palette, (byte *) pcx + len - 768, 768); } else { image_issues = true; } } if (width) { *width = pcx_width + 1; } if (height) { *height = pcx_height + 1; } for (y = 0; y <= pcx_height; y++, pix += pcx_width + 1) { for (x = 0; x <= pcx_width;) { if (raw - (byte *) pcx > len) { // no place for read image_issues = true; x = pcx_width; break; } dataByte = *raw++; if ((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; if (raw - (byte *) pcx > len) { // no place for read image_issues = true; x = pcx_width; break; } dataByte = *raw++; } else { runLength = 1; } while (runLength-- > 0) { if ((*pic + full_size) <= (pix + x)) { // no place for write image_issues = true; x += runLength; runLength = 0; } else { pix[x++] = dataByte; } } } } if (raw - (byte *) pcx > len) { R_Printf(PRINT_DEVELOPER, "PCX file %s was malformed", filename); free(*pic); *pic = NULL; } if (image_issues) { R_Printf(PRINT_ALL, "PCX file %s has possible size issues.\n", filename); } FS_FreeFile(pcx); }
/*QUAKED worldspawn (0 0 0) ? * * Only used for the world. * "sky" environment map name * "skyaxis" vector axis for rotating sky * "skyrotate" speed of rotation in degrees/second * "sounds" music cd track number * "gravity" 800 is default gravity * "message" text to print at user logon */ void SP_worldspawn(edict_t *ent) { if (!ent) { return; } ent->movetype = MOVETYPE_PUSH; ent->solid = SOLID_BSP; ent->inuse = true; /* since the world doesn't use G_Spawn() */ ent->s.modelindex = 1; /* world model is always index 1 */ /* --------------- */ /* reserve some spots for dead player bodies for coop / deathmatch */ InitBodyQue(); /* set configstrings for items */ SetItemNames(); if (st.nextmap) { strcpy(level.nextmap, st.nextmap); } /* make some data visible to the server */ if (ent->message && ent->message[0]) { PF_Configstring(CS_NAME, ent->message); Q_strlcpy(level.level_name, ent->message, sizeof(level.level_name)); } else { Q_strlcpy(level.level_name, level.mapname, sizeof(level.level_name)); } if (st.sky && st.sky[0]) { PF_Configstring(CS_SKY, st.sky); } else { PF_Configstring(CS_SKY, "unit1_"); } PF_Configstring(CS_SKYROTATE, va("%f", st.skyrotate)); PF_Configstring(CS_SKYAXIS, va("%f %f %f", st.skyaxis[0], st.skyaxis[1], st.skyaxis[2])); PF_Configstring(CS_CDTRACK, va("%i", ent->sounds)); PF_Configstring(CS_MAXCLIENTS, va("%i", (int) (maxclients->value))); /* status bar program */ if (deathmatch->value) { PF_Configstring(CS_STATUSBAR, deathmatch_statusbar); } else { PF_Configstring(CS_STATUSBAR, singleplayer_statusbar); } /* --------------- */ level.pic_health = SV_ImageIndex("icon_health"); SV_ImageIndex("stat_flash"); if (!st.gravity) { Cvar_Set("sv_gravity", "800"); } else { Cvar_Set("sv_gravity", st.gravity); } snd_fry = SV_SoundIndex("player/fry.wav"); /* standing in lava / slime */ PrecacheItem(FindItem("Blaster")); SV_SoundIndex("player/lava1.wav"); SV_SoundIndex("player/lava2.wav"); SV_SoundIndex("misc/pc_up.wav"); SV_SoundIndex("misc/talk1.wav"); SV_SoundIndex("misc/udeath.wav"); /* gibs */ SV_SoundIndex("items/respawn1.wav"); /* sexed sounds */ SV_SoundIndex("*death1.wav"); SV_SoundIndex("*death2.wav"); SV_SoundIndex("*death3.wav"); SV_SoundIndex("*death4.wav"); SV_SoundIndex("*fall1.wav"); SV_SoundIndex("*fall2.wav"); SV_SoundIndex("*gurp1.wav"); /* drowning damage */ SV_SoundIndex("*gurp2.wav"); SV_SoundIndex("*jump1.wav"); /* player jump */ SV_SoundIndex("*pain25_1.wav"); SV_SoundIndex("*pain25_2.wav"); SV_SoundIndex("*pain50_1.wav"); SV_SoundIndex("*pain50_2.wav"); SV_SoundIndex("*pain75_1.wav"); SV_SoundIndex("*pain75_2.wav"); SV_SoundIndex("*pain100_1.wav"); SV_SoundIndex("*pain100_2.wav"); /* sexed models: THIS ORDER MUST MATCH THE DEFINES IN g_local.h you can add more, max 19 (pete change)these models are only loaded in coop or deathmatch. not singleplayer. */ if (coop->value || deathmatch->value) { SV_ModelIndex("#w_blaster.md2"); SV_ModelIndex("#w_shotgun.md2"); SV_ModelIndex("#w_sshotgun.md2"); SV_ModelIndex("#w_machinegun.md2"); SV_ModelIndex("#w_chaingun.md2"); SV_ModelIndex("#a_grenades.md2"); SV_ModelIndex("#w_glauncher.md2"); SV_ModelIndex("#w_rlauncher.md2"); SV_ModelIndex("#w_hyperblaster.md2"); SV_ModelIndex("#w_railgun.md2"); } /* ------------------- */ SV_SoundIndex("player/gasp1.wav"); /* gasping for air */ SV_SoundIndex("player/gasp2.wav"); /* head breaking surface, not gasping */ SV_SoundIndex("player/watr_in.wav"); /* feet hitting water */ SV_SoundIndex("player/watr_out.wav"); /* feet leaving water */ SV_SoundIndex("player/watr_un.wav"); /* head going underwater */ SV_SoundIndex("player/u_breath1.wav"); SV_SoundIndex("player/u_breath2.wav"); SV_SoundIndex("items/pkup.wav"); /* bonus item pickup */ SV_SoundIndex("world/land.wav"); /* landing thud */ SV_SoundIndex("misc/h2ohit1.wav"); /* landing splash */ SV_SoundIndex("items/damage.wav"); SV_SoundIndex("items/protect.wav"); SV_SoundIndex("items/protect4.wav"); SV_SoundIndex("weapons/noammo.wav"); SV_SoundIndex("infantry/inflies1.wav"); sm_meat_index = SV_ModelIndex("models/objects/gibs/sm_meat/tris.md2"); SV_ModelIndex("models/objects/gibs/arm/tris.md2"); SV_ModelIndex("models/objects/gibs/bone/tris.md2"); SV_ModelIndex("models/objects/gibs/bone2/tris.md2"); SV_ModelIndex("models/objects/gibs/chest/tris.md2"); SV_ModelIndex("models/objects/gibs/skull/tris.md2"); SV_ModelIndex("models/objects/gibs/head2/tris.md2"); /* Setup light animation tables. 'a' is total darkness, 'z' is doublebright. */ /* 0 normal */ PF_Configstring(CS_LIGHTS + 0, "m"); /* 1 FLICKER (first variety) */ PF_Configstring(CS_LIGHTS + 1, "mmnmmommommnonmmonqnmmo"); /* 2 SLOW STRONG PULSE */ PF_Configstring(CS_LIGHTS + 2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba"); /* 3 CANDLE (first variety) */ PF_Configstring(CS_LIGHTS + 3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg"); /* 4 FAST STROBE */ PF_Configstring(CS_LIGHTS + 4, "mamamamamama"); /* 5 GENTLE PULSE 1 */ PF_Configstring(CS_LIGHTS + 5, "jklmnopqrstuvwxyzyxwvutsrqponmlkj"); /* 6 FLICKER (second variety) */ PF_Configstring(CS_LIGHTS + 6, "nmonqnmomnmomomno"); /* 7 CANDLE (second variety) */ PF_Configstring(CS_LIGHTS + 7, "mmmaaaabcdefgmmmmaaaammmaamm"); /* 8 CANDLE (third variety) */ PF_Configstring(CS_LIGHTS + 8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"); /* 9 SLOW STROBE (fourth variety) */ PF_Configstring(CS_LIGHTS + 9, "aaaaaaaazzzzzzzz"); /* 10 FLUORESCENT FLICKER */ PF_Configstring(CS_LIGHTS + 10, "mmamammmmammamamaaamammma"); /* 11 SLOW PULSE NOT FADE TO BLACK */ PF_Configstring(CS_LIGHTS + 11, "abcdefghijklmnopqrrqponmlkjihgfedcba"); /* styles 32-62 are assigned by the light program for switchable lights */ /* 63 testing */ PF_Configstring(CS_LIGHTS + 63, "a"); }
void FS_Startup(void) { int i; fsSearchPath_t *next; fsPack_t *pack; if (strstr(fs_gamedirvar->string, "..") || strstr(fs_gamedirvar->string, ".") || strstr(fs_gamedirvar->string, "/") || (fs_gamedirvar->string[0] == '\0')) { Com_Printf("Invalid game directory.\n"); Cvar_ForceSet("fs_game", BASEDIRNAME); } /* Check for game override. */ if (strcasecmp(fs_gamedirvar->string, fs_currentGame) != 0) { /* Free up any current game dir info. */ while (fs_searchPaths != fs_baseSearchPaths) { if (fs_searchPaths->pack != NULL) { pack = fs_searchPaths->pack; if (pack->pak != NULL) { fclose(pack->pak); } #ifdef ZIP if (pack->pk3 != NULL) { unzClose(pack->pk3); } #endif Z_Free(pack->files); Z_Free(pack); } next = fs_searchPaths->next; Z_Free(fs_searchPaths); fs_searchPaths = next; } /* Close open files for game dir. */ for (i = 0; i < MAX_HANDLES; i++) { if (strstr(fs_handles[i].name, fs_currentGame) && ((fs_handles[i].file != NULL) #ifdef ZIP || (fs_handles[i].zip != NULL) #endif )) { FS_FCloseFile(i); } } /* Don't add baseq2 again. */ if (Q_stricmp(fs_gamedirvar->string, BASEDIRNAME) == 0) { Q_strlcpy(fs_gamedir, fs_basedir->string, sizeof(fs_gamedir)); } else { /* Add the directories. */ FS_AddGameDirectory(va("%s/%s", fs_homepath->string, fs_gamedirvar->string)); } } Q_strlcpy(fs_currentGame, fs_gamedirvar->string, sizeof(fs_currentGame)); FS_Path_f(); }
void CL_ParseConfigString(void) { int i, length; char *s; char olds[MAX_QPATH]; i = MSG_ReadShort(&net_message); if ((i < 0) || (i >= MAX_CONFIGSTRINGS)) { Com_Error(ERR_DROP, "configstring > MAX_CONFIGSTRINGS"); } s = MSG_ReadString(&net_message); Q_strlcpy(olds, cl.configstrings[i], sizeof(olds)); length = strlen(s); if (length > sizeof(cl.configstrings) - sizeof(cl.configstrings[0])*i - 1) { Com_Error(ERR_DROP, "CL_ParseConfigString: oversize configstring"); } strcpy(cl.configstrings[i], s); /* do something apropriate */ if ((i >= CS_LIGHTS) && (i < CS_LIGHTS + MAX_LIGHTSTYLES)) { CL_SetLightstyle(i - CS_LIGHTS); } else if (i == CS_CDTRACK) { if (cl.refresh_prepped) { #ifdef CDA CDAudio_Play((int)strtol(cl.configstrings[CS_CDTRACK], (char **)NULL, 10), true); #endif #ifdef OGG /* OGG/Vorbis */ if ((int)strtol(cl.configstrings[CS_CDTRACK], (char **)NULL, 10) < 10) { char tmp[3] = "0"; OGG_ParseCmd(strcat(tmp, cl.configstrings[CS_CDTRACK])); } else { OGG_ParseCmd(cl.configstrings[CS_CDTRACK]); } #endif } } else if ((i >= CS_MODELS) && (i < CS_MODELS + MAX_MODELS)) { if (cl.refresh_prepped) { cl.model_draw[i - CS_MODELS] = R_RegisterModel(cl.configstrings[i]); if (cl.configstrings[i][0] == '*') { cl.model_clip[i - CS_MODELS] = CM_InlineModel(cl.configstrings[i]); } else { cl.model_clip[i - CS_MODELS] = NULL; } } } else if ((i >= CS_SOUNDS) && (i < CS_SOUNDS + MAX_MODELS)) { if (cl.refresh_prepped) { cl.sound_precache[i - CS_SOUNDS] = S_RegisterSound(cl.configstrings[i]); } } else if ((i >= CS_IMAGES) && (i < CS_IMAGES + MAX_MODELS)) { if (cl.refresh_prepped) { cl.image_precache[i - CS_IMAGES] = Draw_FindPic(cl.configstrings[i]); } } else if ((i >= CS_PLAYERSKINS) && (i < CS_PLAYERSKINS + MAX_CLIENTS)) { if (cl.refresh_prepped && strcmp(olds, s)) { CL_ParseClientinfo(i - CS_PLAYERSKINS); } } }
/* * Returns file size or -1 if not found. Can open separate files as well as * files inside pack files (both PAK and PK3). */ int FS_FOpenFileRead(fsHandle_t *handle) { char path[MAX_OSPATH]; int i; fsSearchPath_t *search; fsPack_t *pack; file_from_pak = 0; #ifdef ZIP file_from_pk3 = 0; #endif /* Search through the path, one element at a time. */ for (search = fs_searchPaths; search; search = search->next) { /* Search inside a pack file. */ if (search->pack) { pack = search->pack; for (i = 0; i < pack->numFiles; i++) { if (Q_stricmp(pack->files[i].name, handle->name) == 0) { /* Found it! */ Com_FilePath(pack->name, fs_fileInPath, sizeof(fs_fileInPath)); fs_fileInPack = true; if (fs_debug->value) { Com_Printf("FS_FOpenFileRead: '%s' (found in '%s').\n", handle->name, pack->name); } if (pack->pak) { /* PAK */ file_from_pak = 1; handle->file = fopen(pack->name, "rb"); if (handle->file) { fseek(handle->file, pack->files[i].offset, SEEK_SET); return pack->files[i].size; } } #ifdef ZIP else if (pack->pk3) { /* PK3 */ file_from_pk3 = 1; Q_strlcpy(file_from_pk3_name, strrchr(pack->name, '/') + 1, sizeof(file_from_pk3_name)); handle->zip = unzOpen(pack->name); if (handle->zip) { if (unzLocateFile(handle->zip, handle->name, 2) == UNZ_OK) { if (unzOpenCurrentFile(handle->zip) == UNZ_OK) { return pack->files[i].size; } } unzClose(handle->zip); } } #endif Com_Error(ERR_FATAL, "Couldn't reopen '%s'", pack->name); } } } else { /* Search in a directory tree. */ Com_sprintf(path, sizeof(path), "%s/%s", search->path, handle->name); handle->file = fopen(path, "rb"); if (!handle->file) { Q_strlwr(path); handle->file = fopen(path, "rb"); } if (!handle->file) { continue; } if (handle->file) { /* Found it! */ Q_strlcpy(fs_fileInPath, search->path, sizeof(fs_fileInPath)); fs_fileInPack = false; if (fs_debug->value) { Com_Printf("FS_FOpenFileRead: '%s' (found in '%s').\n", handle->name, search->path); } return FS_FileLength(handle->file); } } } /* Not found! */ fs_fileInPath[0] = 0; fs_fileInPack = false; if (fs_debug->value) { Com_Printf("FS_FOpenFileRead: couldn't find '%s'.\n", handle->name); } return -1; }
void CL_ParseServerData(void) { extern cvar_t *fs_gamedirvar; char *str; int i; Com_DPrintf("Serverdata packet received.\n"); /* wipe the client_state_t struct */ CL_ClearState(); cls.state = ca_connected; /* parse protocol version number */ i = MSG_ReadLong(&net_message); cls.serverProtocol = i; /* another demo hack */ if (Com_ServerState() && (PROTOCOL_VERSION == 34)) { } else if (i != PROTOCOL_VERSION) { Com_Error(ERR_DROP, "Server returned version %i, not %i", i, PROTOCOL_VERSION); } cl.servercount = MSG_ReadLong(&net_message); cl.attractloop = MSG_ReadByte(&net_message); /* game directory */ str = MSG_ReadString(&net_message); Q_strlcpy(cl.gamedir, str, sizeof(cl.gamedir)); /* set gamedir */ if ((*str && (!fs_gamedirvar->string || !*fs_gamedirvar->string || strcmp(fs_gamedirvar->string, str))) || (!*str && (fs_gamedirvar->string || *fs_gamedirvar->string))) { Cvar_Set("game", str); } /* parse player entity number */ cl.playernum = MSG_ReadShort(&net_message); /* get the full level name */ str = MSG_ReadString(&net_message); if (cl.playernum == -1) { /* playing a cinematic or showing a pic, not a level */ SCR_PlayCinematic(str); } else { /* seperate the printfs so the server * message can have a color */ Com_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n"); Com_Printf("%c%s\n", 2, str); /* need to prep refresh at next oportunity */ cl.refresh_prepped = false; } }
void CL_LoadClientinfo(clientinfo_t *ci, char *s) { int i; char *t; char model_name[MAX_QPATH]; char skin_name[MAX_QPATH]; char model_filename[MAX_QPATH]; char skin_filename[MAX_QPATH]; char weapon_filename[MAX_QPATH]; Q_strlcpy(ci->cinfo, s, sizeof(ci->cinfo)); s = ci->cinfo; /* isolate the player's name */ Q_strlcpy(ci->name, s, sizeof(ci->name)); t = strstr(s, "\\"); if (t) { ci->name[t - s] = 0; s = t + 1; } if (cl_noskins->value || (*s == 0)) { strcpy(model_filename, "players/male/tris.md2"); strcpy(weapon_filename, "players/male/weapon.md2"); strcpy(skin_filename, "players/male/grunt.pcx"); strcpy(ci->iconname, "/players/male/grunt_i.pcx"); ci->model = R_RegisterModel(model_filename); memset(ci->weaponmodel, 0, sizeof(ci->weaponmodel)); ci->weaponmodel[0] = R_RegisterModel(weapon_filename); ci->skin = R_RegisterSkin(skin_filename); ci->icon = Draw_FindPic(ci->iconname); } else { /* isolate the model name */ strcpy(model_name, s); t = strstr(model_name, "/"); if (!t) { t = strstr(model_name, "\\"); } if (!t) { t = model_name; } *t = 0; /* isolate the skin name */ strcpy(skin_name, s + strlen(model_name) + 1); /* model file */ Com_sprintf(model_filename, sizeof(model_filename), "players/%s/tris.md2", model_name); ci->model = R_RegisterModel(model_filename); if (!ci->model) { strcpy(model_name, "male"); Com_sprintf(model_filename, sizeof(model_filename), "players/male/tris.md2"); ci->model = R_RegisterModel(model_filename); } /* skin file */ Com_sprintf(skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = R_RegisterSkin(skin_filename); /* if we don't have the skin and the model wasn't male, * see if the male has it (this is for CTF's skins) */ if (!ci->skin && Q_stricmp(model_name, "male")) { /* change model to male */ strcpy(model_name, "male"); Com_sprintf(model_filename, sizeof(model_filename), "players/male/tris.md2"); ci->model = R_RegisterModel(model_filename); /* see if the skin exists for the male model */ Com_sprintf(skin_filename, sizeof(skin_filename), "players/%s/%s.pcx", model_name, skin_name); ci->skin = R_RegisterSkin(skin_filename); } /* if we still don't have a skin, it means that the male model didn't have * it, so default to grunt */ if (!ci->skin) { /* see if the skin exists for the male model */ Com_sprintf(skin_filename, sizeof(skin_filename), "players/%s/grunt.pcx", model_name); ci->skin = R_RegisterSkin(skin_filename); } /* weapon file */ for (i = 0; i < num_cl_weaponmodels; i++) { Com_sprintf(weapon_filename, sizeof(weapon_filename), "players/%s/%s", model_name, cl_weaponmodels[i]); ci->weaponmodel[i] = R_RegisterModel(weapon_filename); if (!ci->weaponmodel[i] && (strcmp(model_name, "cyborg") == 0)) { /* try male */ Com_sprintf(weapon_filename, sizeof(weapon_filename), "players/male/%s", cl_weaponmodels[i]); ci->weaponmodel[i] = R_RegisterModel(weapon_filename); } if (!cl_vwep->value) { break; /* only one when vwep is off */ } } /* icon file */ Com_sprintf(ci->iconname, sizeof(ci->iconname), "/players/%s/%s_i.pcx", model_name, skin_name); ci->icon = Draw_FindPic(ci->iconname); } /* must have loaded all data types to be valid */ if (!ci->skin || !ci->icon || !ci->model || !ci->weaponmodel[0]) { ci->skin = NULL; ci->icon = NULL; ci->model = NULL; ci->weaponmodel[0] = NULL; return; } }
/* * The current net_message is parsed for the given client */ void SV_ExecuteClientMessage(client_t *cl) { int c; char *s; usercmd_t nullcmd; usercmd_t oldest, oldcmd, newcmd; int net_drop; int stringCmdCount; int checksum, calculatedChecksum; int checksumIndex; qboolean move_issued; int lastframe; sv_client = cl; sv_player = sv_client->edict; /* only allow one move command */ move_issued = false; stringCmdCount = 0; while (1) { if (net_message.readcount > net_message.cursize) { Com_Printf("SV_ReadClientMessage: badread\n"); SV_DropClient(cl); return; } c = MSG_ReadByte(&net_message); if (c == -1) { break; } switch (c) { default: Com_Printf("SV_ReadClientMessage: unknown command char\n"); SV_DropClient(cl); return; case clc_nop: break; case clc_userinfo: Q_strlcpy(cl->userinfo, MSG_ReadString(&net_message), sizeof(cl->userinfo)); SV_UserinfoChanged(cl); break; case clc_move: if (move_issued) { return; /* someone is trying to cheat... */ } move_issued = true; checksumIndex = net_message.readcount; checksum = MSG_ReadByte(&net_message); lastframe = MSG_ReadLong(&net_message); if (lastframe != cl->lastframe) { cl->lastframe = lastframe; if (cl->lastframe > 0) { cl->frame_latency[cl->lastframe & (LATENCY_COUNTS - 1)] = svs.realtime - cl->frames[cl->lastframe & UPDATE_MASK].senttime; } } memset(&nullcmd, 0, sizeof(nullcmd)); MSG_ReadDeltaUsercmd(&net_message, &nullcmd, &oldest); MSG_ReadDeltaUsercmd(&net_message, &oldest, &oldcmd); MSG_ReadDeltaUsercmd(&net_message, &oldcmd, &newcmd); if (cl->state != cs_spawned) { cl->lastframe = -1; break; } /* if the checksum fails, ignore the rest of the packet */ calculatedChecksum = COM_BlockSequenceCRCByte( net_message.data + checksumIndex + 1, net_message.readcount - checksumIndex - 1, cl->netchan.incoming_sequence); if (calculatedChecksum != checksum) { Com_DPrintf("Failed command checksum for %s (%d != %d)/%d\n", cl->name, calculatedChecksum, checksum, cl->netchan.incoming_sequence); return; } if (!sv_paused->value) { net_drop = cl->netchan.dropped; if (net_drop < 20) { while (net_drop > 2) { SV_ClientThink(cl, &cl->lastcmd); net_drop--; } if (net_drop > 1) { SV_ClientThink(cl, &oldest); } if (net_drop > 0) { SV_ClientThink(cl, &oldcmd); } } SV_ClientThink(cl, &newcmd); } cl->lastcmd = newcmd; break; case clc_stringcmd: s = MSG_ReadString(&net_message); /* malicious users may try using too many string commands */ if (++stringCmdCount < MAX_STRINGCMDS) { SV_ExecuteUserCommand(s); } if (cl->state == cs_zombie) { return; /* disconnect command */ } break; } } }
BOOL CTrcsMgr::RequestTransac( Transac &sTransac ) { Transac* pTrsc = g_TransacPool().Alloc(); if( !pTrsc ) return FALSE; pTrsc->m_TrscID = _GetCurrentTrscID(); pTrsc->m_OptID = sTransac.m_OptID; pTrsc->m_pTrscCallFn = sTransac.m_pTrscCallFn; pTrsc->m_pTrscFailedCallFn = sTransac.m_pTrscFailedCallFn; pTrsc->m_ServiceID = sTransac.m_ServiceID; pTrsc->m_Trsc_CBParam.m_Money = sTransac.m_Trsc_CBParam.m_Money; pTrsc->m_Trsc_CBParam.m_nNum = sTransac.m_Trsc_CBParam.m_nNum; pTrsc->m_Trsc_CBParam.m_nDay = sTransac.m_Trsc_CBParam.m_nDay; pTrsc->m_Trsc_CBParam.m_Buyer = sTransac.m_Trsc_CBParam.m_Buyer; pTrsc->m_Trsc_CBParam.m_Seller = sTransac.m_Trsc_CBParam.m_Seller; pTrsc->m_Trsc_CBParam.m_Ext1 = sTransac.m_Trsc_CBParam.m_Ext1; pTrsc->m_Trsc_CBParam.m_Ext2 = sTransac.m_Trsc_CBParam.m_Ext2; pTrsc->m_Trsc_CBParam.m_Ext3 = sTransac.m_Trsc_CBParam.m_Ext3; pTrsc->m_Trsc_CBParam.m_Ext4 = sTransac.m_Trsc_CBParam.m_Ext4; pTrsc->m_Trsc_CBParam.m_Ext5 = sTransac.m_Trsc_CBParam.m_Ext5; pTrsc->m_Trsc_CBParam.m_Ext6 = sTransac.m_Trsc_CBParam.m_Ext6; pTrsc->m_Trsc_CBParam.m_Ext7 = sTransac.m_Trsc_CBParam.m_Ext7; pTrsc->m_Trsc_CBParam.m_Ext8 = sTransac.m_Trsc_CBParam.m_Ext8; pTrsc->m_Trsc_CBParam.m_Ext9 = sTransac.m_Trsc_CBParam.m_Ext9; pTrsc->m_Trsc_CBParam.m_Ext10 = sTransac.m_Trsc_CBParam.m_Ext10; pTrsc->m_Trsc_CBParam.m_Ext11 = sTransac.m_Trsc_CBParam.m_Ext11; pTrsc->m_Trsc_CBParam.m_Ext12 = sTransac.m_Trsc_CBParam.m_Ext12; pTrsc->m_Trsc_CBParam.m_IsSetMoney = sTransac.m_Trsc_CBParam.m_IsSetMoney; if(sTransac.m_strExtParam != NULL) Q_strlcpy(pTrsc->m_strExtParam,sizeof(pTrsc->m_strExtParam),sTransac.m_strExtParam); //strcpy(pTrsc->m_strExtParam,sTransac.m_strExtParam); if (sTransac.m_Trsc_CBParam.m_ExpStr1 && strlen(sTransac.m_Trsc_CBParam.m_ExpStr1) < PAYSYSTEM_EXPSTR1_LEN) { //strcpy(pTrsc->m_Trsc_CBParam.m_ExpStr1, sTransac.m_Trsc_CBParam.m_ExpStr1); Q_strlcpy(pTrsc->m_Trsc_CBParam.m_ExpStr1,sizeof(pTrsc->m_Trsc_CBParam.m_ExpStr1), sTransac.m_Trsc_CBParam.m_ExpStr1); } if (sTransac.m_Trsc_CBParam.m_ExtStr2 && strlen(sTransac.m_Trsc_CBParam.m_ExtStr2) < PAYSYSTEM_EXPSTR1_LEN) { //strcpy(pTrsc->m_Trsc_CBParam.m_ExtStr2, sTransac.m_Trsc_CBParam.m_ExtStr2); Q_strlcpy(pTrsc->m_Trsc_CBParam.m_ExtStr2,sizeof(pTrsc->m_Trsc_CBParam.m_ExtStr2), sTransac.m_Trsc_CBParam.m_ExtStr2); } if (sTransac.m_Trsc_CBParam.m_UserName && strlen(sTransac.m_Trsc_CBParam.m_UserName) < PAYSYSTEM_EXPSTR1_LEN) { //strcpy(pTrsc->m_Trsc_CBParam.m_UserName, sTransac.m_Trsc_CBParam.m_UserName); Q_strlcpy(pTrsc->m_Trsc_CBParam.m_UserName,sizeof(pTrsc->m_Trsc_CBParam.m_UserName), sTransac.m_Trsc_CBParam.m_UserName); } if (sTransac.m_Trsc_CBParam.m_ExpStr3 && strlen(sTransac.m_Trsc_CBParam.m_ExpStr3) < PAYSYSTEM_EXPSTR2_LEN) { //strcpy(pTrsc->m_Trsc_CBParam.m_ExpStr3, sTransac.m_Trsc_CBParam.m_ExpStr3); Q_strlcpy(pTrsc->m_Trsc_CBParam.m_ExpStr3,sizeof(pTrsc->m_Trsc_CBParam.m_ExpStr3), sTransac.m_Trsc_CBParam.m_ExpStr3); } if (sTransac.m_Trsc_CBParam.m_ExpStr4 && strlen(sTransac.m_Trsc_CBParam.m_ExpStr4) < PAYSYSTEM_EXPSTR2_LEN) { //strcpy(pTrsc->m_Trsc_CBParam.m_ExpStr4, sTransac.m_Trsc_CBParam.m_ExpStr4); Q_strlcpy(pTrsc->m_Trsc_CBParam.m_ExpStr4,sizeof(pTrsc->m_Trsc_CBParam.m_ExpStr4), sTransac.m_Trsc_CBParam.m_ExpStr4); } if (sTransac.m_Trsc_CBParam.m_ExpStr5 && strlen(sTransac.m_Trsc_CBParam.m_ExpStr5) < PAYSYSTEM_EXPSTR3_LEN) { //strcpy(pTrsc->m_Trsc_CBParam.m_ExpStr5, sTransac.m_Trsc_CBParam.m_ExpStr5); Q_strlcpy(pTrsc->m_Trsc_CBParam.m_ExpStr5,sizeof(pTrsc->m_Trsc_CBParam.m_ExpStr5), sTransac.m_Trsc_CBParam.m_ExpStr5); } if (sTransac.m_Trsc_CBParam.m_ExpStr6 && strlen(sTransac.m_Trsc_CBParam.m_ExpStr6) < PAYSYSTEM_EXPSTR2_LEN) { //strcpy(pTrsc->m_Trsc_CBParam.m_ExpStr6, sTransac.m_Trsc_CBParam.m_ExpStr6); Q_strlcpy(pTrsc->m_Trsc_CBParam.m_ExpStr6,sizeof(pTrsc->m_Trsc_CBParam.m_ExpStr6), sTransac.m_Trsc_CBParam.m_ExpStr6); } int index = m_TrscContainer.Find( pTrsc->m_TrscID ); if( m_TrscContainer.IsValidIndex( index ) ) { Log("创建金钱交易时出现严重错误:流水号重复!"); return FALSE; } CPlayer* pPlayer = PlayerMgr().GetPlayerByPID( pTrsc->m_Trsc_CBParam.m_Buyer ); if( pPlayer ) { pTrsc->m_Money = pPlayer->GetMoney(Currency_Silver); //Log("支付请求 账号: %s , 玩家: %s,操作:%d, 请求金币:%s , 剩余金币: %d",pPlayer->GetUserName(), pPlayer->GetName(),pTrsc->m_OptID,pTrsc->m_Trsc_CBParam.m_Money,pTrsc->m_Money ); } else { CPlayer* pSellPlayer = PlayerMgr().GetPlayerByPID( pTrsc->m_Trsc_CBParam.m_Seller ); if( pSellPlayer ) { pTrsc->m_Money = pSellPlayer->GetMoney(Currency_Silver); //Log("支付请求 账号: %s , 玩家: %s,操作:%d, 请求金币:%s , 剩余金币: %d",pSellPlayer->GetUserName(), pSellPlayer->GetName(),pTrsc->m_OptID,pTrsc->m_Trsc_CBParam.m_Money,pTrsc->m_Money ); } } pTrsc->m_TrscTime = Time().GetCurrentTime(); //Log("\n 支付系统 支付单号: %I64d, 初始化时间 %I64d\n", pTrsc->m_TrscID,pTrsc->m_TrscTime); m_TrscContainer.Insert( pTrsc->m_TrscID, pTrsc ); //这里发给DB让其存流水号 PACKET_COMMAND pack; pack.SetParam( DBSERVER_SET_PAYID,GetCmdFormat(DBSERVER_SET_PAYID),pTrsc->m_TrscID); DataServerMgr().SendDBMsg(&pack); return _ProcGameRequest(pTrsc); }
static void BuildName( const file_info_t *info, char **cache ) { char buffer[MAX_OSPATH]; char date[MAX_QPATH]; demoInfo_t demo; demoEntry_t *e; struct tm *tm; size_t len; memset( &demo, 0, sizeof( demo ) ); strcpy( demo.map, "???" ); strcpy( demo.pov, "???" ); if( cache ) { char *s = *cache; char *p = strchr( s, '\\' ); if( p ) { *p = 0; Q_strlcpy( demo.map, s, sizeof( demo.map ) ); s = p + 1; p = strchr( s, '\\' ); if( p ) { *p = 0; Q_strlcpy( demo.pov, s, sizeof( demo.pov ) ); s = p + 1; } } *cache = s; } else { Q_concat( buffer, sizeof( buffer ), m_demos.browse, "/", info->name, NULL ); CL_GetDemoInfo( buffer, &demo ); if( demo.mvd ) { strcpy( demo.pov, DEMO_MVD_POV ); } } // resize columns len = strlen( demo.map ); if( len > 8 ) { len = 8; } if( len > m_demos.widest_map ) { m_demos.widest_map = len; } len = strlen( demo.pov ); if( len > m_demos.widest_pov ) { m_demos.widest_pov = len; } // format date if( ( tm = localtime( &info->mtime ) ) != NULL ) { if( tm->tm_year == m_demos.year ) { strftime( date, sizeof( date ), "%b %d %H:%M", tm ); } else { strftime( date, sizeof( date ), "%b %d %Y", tm ); } } else { strcpy( date, "???" ); } Com_FormatSize( buffer, sizeof( buffer ), info->size ); e = UI_FormatColumns( DEMO_EXTRASIZE, info->name, date, buffer, demo.map, demo.pov, NULL ); e->type = ENTRY_DEMO; e->size = info->size; e->mtime = info->mtime; m_demos.total_bytes += info->size; m_demos.list.items[m_demos.list.numItems++] = e; }
/* * Called for important messages that should stay * in the center of the screen for a few moments */ void SCR_CenterPrint(char *str) { char *s; char line[64]; int i, j, l; Q_strlcpy(scr_centerstring, str, sizeof(scr_centerstring)); scr_centertime_off = scr_centertime->value; scr_centertime_start = cl.time; /* count the number of lines for centering */ scr_center_lines = 1; s = str; while (*s) { if (*s == '\n') { scr_center_lines++; } s++; } /* echo it to the console */ Com_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n"); s = str; do { /* scan the width of the line */ for (l = 0; l < 40; l++) { if ((s[l] == '\n') || !s[l]) { break; } } for (i = 0; i < (40 - l) / 2; i++) { line[i] = ' '; } for (j = 0; j < l; j++) { line[i++] = s[j]; } line[i] = '\n'; line[i + 1] = 0; Com_Printf("%s", line); while (*s && *s != '\n') { s++; } if (!*s) { break; } s++; /* skip the \n */ } while (1); Com_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n"); Con_ClearNotify(); }
/* * Creates a server's entity / program execution context by * parsing textual entity definitions out of an ent file. */ void SpawnEntities(const char *mapname, char *entities, const char *spawnpoint) { edict_t *ent; int inhibit; const char *com_token; int i; float skill_level; static qboolean monster_count_city3 = false; if (!mapname || !entities || !spawnpoint) { return; } skill_level = floor(skill->value); if (skill_level < 0) { skill_level = 0; } if (skill_level > 3) { skill_level = 3; } if (skill->value != skill_level) { gi.cvar_forceset("skill", va("%f", skill_level)); } SaveClientData(); gi.FreeTags(TAG_LEVEL); memset(&level, 0, sizeof(level)); memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); Q_strlcpy(level.mapname, mapname, sizeof(level.mapname)); Q_strlcpy(game.spawnpoint, spawnpoint, sizeof(game.spawnpoint)); /* set client fields on player ents */ for (i = 0; i < game.maxclients; i++) { g_edicts[i + 1].client = game.clients + i; } ent = NULL; inhibit = 0; /* parse ents */ while (1) { /* parse the opening brace */ com_token = COM_Parse(&entities); if (!entities) { break; } if (com_token[0] != '{') { gi.error("ED_LoadFromFile: found %s when expecting {", com_token); } if (!ent) { ent = g_edicts; } else { ent = G_Spawn(); } entities = ED_ParseEdict(entities, ent); /* yet another map hack */ if (!Q_stricmp(level.mapname, "command") && !Q_stricmp(ent->classname, "trigger_once") && !Q_stricmp(ent->model, "*27")) { ent->spawnflags &= ~SPAWNFLAG_NOT_HARD; } /* * The 'monsters' count in city3.bsp is wrong. * There're two monsters triggered in a hidden * and unreachable room next to the security * pass. * * We need to make sure that this hack is only * applied once! */ if(!Q_stricmp(level.mapname, "city3") && !monster_count_city3) { level.total_monsters = level.total_monsters - 2; monster_count_city3 = true; } /* remove things (except the world) from different skill levels or deathmatch */ if (ent != g_edicts) { if (deathmatch->value) { if (ent->spawnflags & SPAWNFLAG_NOT_DEATHMATCH) { G_FreeEdict(ent); inhibit++; continue; } } else { if (((skill->value == 0) && (ent->spawnflags & SPAWNFLAG_NOT_EASY)) || ((skill->value == 1) && (ent->spawnflags & SPAWNFLAG_NOT_MEDIUM)) || (((skill->value == 2) || (skill->value == 3)) && (ent->spawnflags & SPAWNFLAG_NOT_HARD)) ) { G_FreeEdict(ent); inhibit++; continue; } } ent->spawnflags &= ~(SPAWNFLAG_NOT_EASY | SPAWNFLAG_NOT_MEDIUM | SPAWNFLAG_NOT_HARD | SPAWNFLAG_NOT_COOP | SPAWNFLAG_NOT_DEATHMATCH); } ED_CallSpawn(ent); } gi.dprintf("%i entities inhibited.\n", inhibit); G_FindTeams(); PlayerTrail_Init(); }