/* ================ Con_Init ================ */ void Con_Init (void) { #define MAXGAMEDIRLEN 1000 char temp[MAXGAMEDIRLEN+1]; char *ch; // JPG - added this int fd, n; // JPG - added these time_t ltime; // JPG - for console log file con_debuglog = COM_CheckParm("-condebug"); if (con_debuglog) { // JPG - check for different file name if ((con_debuglog < com_argc - 1) && (*com_argv[con_debuglog+1] != '-') && (*com_argv[con_debuglog+1] != '+')) { if ((ch = strchr(com_argv[con_debuglog+1], '%')) && (ch[1] == 'd')) { n = 0; do { n = n + 1; dpsnprintf(logfilename, sizeof(logfilename), com_argv[con_debuglog+1], n); strcat(logfilename, ".log"); dpsnprintf(temp, sizeof(temp), "%s/%s", com_gamedir, logfilename); fd = open(temp, O_CREAT | O_EXCL | O_WRONLY, 0666); } while (fd == -1); close(fd); } else dpsnprintf(logfilename, sizeof(logfilename), "%s.log", com_argv[con_debuglog+1]); } else strcpy(logfilename, "qconsole.log"); // JPG - changed t2 to logfilename if (strlen (com_gamedir) < (MAXGAMEDIRLEN - strlen (logfilename))) { dpsnprintf (temp, sizeof(temp), "%s/%s", com_gamedir, logfilename); // JPG - added the '/' unlink (temp); } // JPG - print initial message Con_Printf("Log file initialized.\n"); Con_Printf("%s/%s\n", com_gamedir, logfilename); time( <ime ); Con_Printf( "%s\n", ctime( <ime ) ); } // used by some mods con_text = Hunk_AllocName (CON_TEXTSIZE, "context"); memset (con_text, ' ', CON_TEXTSIZE); Con_Printf ("Console initialized.\n"); // register our commands Cmd_AddCommand ("clear", Con_Clear_f); }
static int R_LoadSkyBox(void) { int i, j, success; int indices[4] = {0,1,2,3}; char name[MAX_INPUTLINE]; unsigned char *image_buffer; unsigned char *temp; char vabuf[1024]; R_UnloadSkyBox(); if (!skyname[0]) return true; for (j=0; j<3; j++) { success = 0; for (i=0; i<6; i++) { if (dpsnprintf(name, sizeof(name), "%s_%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, false, NULL))) { if (dpsnprintf(name, sizeof(name), "%s%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, false, NULL))) { if (dpsnprintf(name, sizeof(name), "env/%s%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, false, NULL))) { if (dpsnprintf(name, sizeof(name), "gfx/env/%s%s", skyname, suffix[j][i].suffix) < 0 || !(image_buffer = loadimagepixelsbgra(name, false, false, false, NULL))) continue; } } } temp = (unsigned char *)Mem_Alloc(tempmempool, image_width*image_height*4); Image_CopyMux (temp, image_buffer, image_width, image_height, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, indices); skyboxskinframe[i] = R_SkinFrame_LoadInternalBGRA(va(vabuf, sizeof(vabuf), "skyboxside%d", i), TEXF_CLAMP | (gl_texturecompression_sky.integer ? TEXF_COMPRESS : 0), temp, image_width, image_height, vid.sRGB3D); Mem_Free(image_buffer); Mem_Free(temp); success++; } if (success) break; } if (j == 3) return false; if (developer_loading.integer) Con_Printf("loading skybox \"%s\"\n", name); return true; }
const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength) { #ifndef NOSUPPORTIPV6 lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress; if (address && address->addresstype == LHNETADDRESSTYPE_INET6) { #ifndef _WIN32 if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname) return ifname; #else // The Win32 API doesn't have if_indextoname() until Windows Vista, // but luckily it just uses the interface ID as the interface name if (dpsnprintf(ifname, ifnamelength, "%lu", address->addr.in6.sin6_scope_id) > 0) return ifname; #endif } #endif return NULL; }
/* ============ Cvar_SetValue ============ */ void Cvar_SetValue (char *var_name, float value) { char val[32]; dpsnprintf (val, sizeof(val), "%f",value); Cvar_Set (var_name, val); }
void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize) { mfunction_t *f; int i; char vabuf[1024]; if(prog) { dpsnprintf(buf, bufsize, "(%s) ", prog->name); } else { strlcpy(buf, "<NO PROG>", bufsize); return; } prog->stack[prog->depth].s = prog->xstatement; prog->stack[prog->depth].f = prog->xfunction; for (i = prog->depth; i > 0; i--) { f = prog->stack[i].f; if(strlcat(buf, f ? va(vabuf, sizeof(vabuf), "%s:%s(%i) ", PRVM_GetString(prog, f->s_file), PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement) : "<NULL> ", bufsize ) >= bufsize) break; } }
void CDAudio_Play (int track, qboolean looping) { char buf[20]; if (music_playlist_index.integer >= 0) return; dpsnprintf(buf, sizeof(buf), "%d", (int) track); CDAudio_Play_byName(buf, looping, true, 0); }
// operating system specific code static void adddirentry(stringlist_t *list, const char *path, const char *name) { if (strcmp(name, ".") && strcmp(name, "..")) { char temp[MAX_OSPATH]; dpsnprintf( temp, sizeof( temp ), "%s%s", path, name ); stringlistappend(list, temp); } }
static void cl_gecko_destroy_f( void ) { char name[MAX_QPATH]; if (Cmd_Argc() != 2) { Con_Print("usage: gecko_destroy <name>\ndestroys a browser\n"); return; } dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1)); CL_Gecko_DestroyBrowser( CL_Gecko_FindBrowser( name ) ); }
static void cl_gecko_create_f( void ) { char name[MAX_QPATH]; if (Cmd_Argc() != 2) { Con_Print("usage: gecko_create <name>\npcreates a browser (full texture path " CLGECKOPREFIX "<name>)\n"); return; } dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1)); CL_Gecko_CreateBrowser( name, -1 ); }
void listdirectory(stringlist_t *list, const char *basepath, const char *path) { char fullpath[MAX_OSPATH]; DIR *dir; struct dirent *ent; dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, *path ? path : "./"); dir = opendir(fullpath); if (!dir) return; while ((ent = readdir(dir))) adddirentry(list, path, ent->d_name); closedir(dir); }
void listdirectory(stringlist_t *list, const char *basepath, const char *path) { char fullpath[MAX_OSPATH]; DIR *dir; struct dirent *ent; dpsnprintf(fullpath, sizeof(fullpath), "%s%s", basepath, path); #ifdef __ANDROID__ // SDL currently does not support listing assets, so we have to emulate // it. We're using relative paths for assets, so that will do. if (basepath[0] != '/') { char listpath[MAX_OSPATH]; qfile_t *listfile; dpsnprintf(listpath, sizeof(listpath), "%sls.txt", fullpath); char *buf = (char *) FS_SysLoadFile(listpath, tempmempool, true, NULL); if (!buf) return; char *p = buf; for (;;) { char *q = strchr(p, '\n'); if (q == NULL) break; *q = 0; adddirentry(list, path, p); p = q + 1; } Mem_Free(buf); return; } #endif dir = opendir(fullpath); if (!dir) return; while ((ent = readdir(dir))) adddirentry(list, path, ent->d_name); closedir(dir); }
static void cl_gecko_navigate_f( void ) { char name[MAX_QPATH]; const char *URI; if (Cmd_Argc() != 3) { Con_Print("usage: gecko_navigate <name> <URI>\nnavigates to a certain URI\n"); return; } dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1)); URI = Cmd_Argv( 2 ); CL_Gecko_NavigateToURI( CL_Gecko_FindBrowser( name ), URI ); }
static void gl_gecko_movecursor_f( void ) { char name[MAX_QPATH]; float x, y; if (Cmd_Argc() != 4) { Con_Print("usage: gecko_movecursor <name> <x> <y>\nmove the cursor to a certain position\n"); return; } dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1)); x = atof( Cmd_Argv( 2 ) ); y = atof( Cmd_Argv( 3 ) ); CL_Gecko_Event_CursorMove( CL_Gecko_FindBrowser( name ), x, y ); }
static void cl_gecko_injecttext_f( void ) { char name[MAX_QPATH]; const char *text; clgecko_t *instance; const char *p; if (Cmd_Argc() < 3) { Con_Print("usage: gecko_injecttext <name> <text>\ninjects a certain text into the browser\n"); return; } dpsnprintf(name, sizeof(name), CLGECKOPREFIX "%s", Cmd_Argv(1)); instance = CL_Gecko_FindBrowser( name ); if( !instance ) { Con_Printf( "cl_gecko_injecttext_f: gecko instance '%s' couldn't be found!\n", name ); return; } text = Cmd_Argv( 2 ); for( p = text ; *p ; p++ ) { unsigned key = *p; switch( key ) { case ' ': key = K_SPACE; break; case '\\': key = *++p; switch( key ) { case 'n': key = K_ENTER; break; case '\0': --p; key = '\\'; break; } break; } CL_Gecko_Event_Key( instance, (keynum_t) key, CLG_BET_PRESS ); } }
static int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port) { char port_buff [16]; struct addrinfo hints; struct addrinfo* addrinf; int err; dpsnprintf (port_buff, sizeof (port_buff), "%d", port); port_buff[sizeof (port_buff) - 1] = '\0'; memset(&hints, 0, sizeof (hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; //hints.ai_flags = AI_PASSIVE; err = getaddrinfo(name, port_buff, &hints, &addrinf); if (err != 0 || addrinf == NULL) return 0; if (addrinf->ai_addr->sa_family != AF_INET6 && addrinf->ai_addr->sa_family != AF_INET) { freeaddrinfo (addrinf); return 0; } // great it worked if (addrinf->ai_addr->sa_family == AF_INET6) { address->addresstype = LHNETADDRESSTYPE_INET6; memcpy(&address->addr.in6, addrinf->ai_addr, sizeof(address->addr.in6)); } else { address->addresstype = LHNETADDRESSTYPE_INET4; memcpy(&address->addr.in, addrinf->ai_addr, sizeof(address->addr.in)); } address->port = port; freeaddrinfo (addrinf); return 1; }
static qboolean CL_Gecko_Embedding_Init (void) { char profile_path [MAX_OSPATH]; OSGK_GeckoResult grc; OSGK_EmbeddingOptions *options; OSGK_ScriptObjectTemplate* dpGlobalTemplate; if (!osgk_dll) return false; if( cl_geckoembedding != NULL ) return true; Con_DPrintf( "CL_Gecko_Embedding_Init: setting up gecko embedding\n" ); options = osgk_embedding_options_create(); #ifdef XULRUNNER_DIR_SUFFIX osgk_embedding_options_add_search_path( options, "./xulrunner-" XULRUNNER_DIR_SUFFIX "/" ); #endif osgk_embedding_options_add_search_path( options, "./xulrunner/" ); dpsnprintf (profile_path, sizeof (profile_path), "%s/xulrunner_profile/", fs_gamedir); osgk_embedding_options_set_profile_dir( options, profile_path, 0 ); cl_geckoembedding = osgk_embedding_create_with_options( options, &grc ); osgk_release( options ); if( cl_geckoembedding == NULL ) { Con_Printf( "CL_Gecko_Embedding_Init: Couldn't retrieve gecko embedding object (%.8x)!\n", grc ); return false; } Con_DPrintf( "CL_Gecko_Embedding_Init: Embedding set up correctly\n" ); dpGlobalTemplate = osgk_sot_create( cl_geckoembedding, dpGlobal_create, NULL, NULL ); osgk_sot_add_function (dpGlobalTemplate, "query", 0, dpGlobal_query); osgk_sot_register (dpGlobalTemplate, cl_geckoembedding, "Darkplaces", 0); osgk_release( dpGlobalTemplate ); return true; }
/* ===================== CL_NextDemo Called to play the next demo in the demo loop ===================== */ void CL_NextDemo (void) { char str[MAX_INPUTLINE]; if (cls.demonum == -1) return; // don't play demos if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) { cls.demonum = 0; if (!cls.demos[cls.demonum][0]) { Con_Print("No demos listed with startdemos\n"); cls.demonum = -1; return; } } dpsnprintf (str, sizeof(str), "playdemo %s\n", cls.demos[cls.demonum]); Cbuf_InsertText (str); cls.demonum++; }
/* ==================== CleanURL Returns a "cleaned up" URL for display (to strip login data) ==================== */ static const char *CleanURL(const char *url, char *urlbuf, size_t urlbuflength) { const char *p, *q, *r; // if URL is of form anything://foo-without-slash@rest, replace by anything://rest p = strstr(url, "://"); if(p) { q = strchr(p + 3, '@'); if(q) { r = strchr(p + 3, '/'); if(!r || q < r) { dpsnprintf(urlbuf, urlbuflength, "%.*s%s", (int)(p - url + 3), url, q + 1); return urlbuf; } } } return url; }
/* ==================== Curl_SendRequirements Makes the current host_clients download all files he needs. This is done by sending him the following console commands: curl --clear_autodownload curl --pak --for maps/pushmoddm1.bsp --forthismap http://where/this/darn/map/is/pushmoddm1.pk3 curl --finish_autodownload ==================== */ static qboolean Curl_SendRequirement(const char *filename, qboolean foundone, char *sendbuffer, size_t sendbuffer_len) { const char *p; const char *thispack = FS_WhichPack(filename); const char *packurl; if(!thispack) return false; p = strrchr(thispack, '/'); if(p) thispack = p + 1; packurl = Curl_FindPackURL(thispack); if(packurl && *packurl && strcmp(packurl, "-")) { if(!foundone) strlcat(sendbuffer, "curl --clear_autodownload\n", sendbuffer_len); strlcat(sendbuffer, "curl --pak --forthismap --as ", sendbuffer_len); strlcat(sendbuffer, thispack, sendbuffer_len); if(sv_curl_maxspeed.value > 0) dpsnprintf(sendbuffer + strlen(sendbuffer), sendbuffer_len - strlen(sendbuffer), " --maxspeed=%.1f", sv_curl_maxspeed.value); strlcat(sendbuffer, " --for ", sendbuffer_len); strlcat(sendbuffer, filename, sendbuffer_len); strlcat(sendbuffer, " ", sendbuffer_len); strlcat(sendbuffer, packurl, sendbuffer_len); strlcat(sendbuffer, thispack, sendbuffer_len); strlcat(sendbuffer, "\n", sendbuffer_len); return true; } return false; }
/* ==================== Curl_Begin Starts a download of a given URL to the file name portion of this URL (or name if given) in the "dlcache/" folder. ==================== */ static qboolean Curl_Begin(const char *URL, const char *extraheaders, double maxspeed, const char *name, qboolean ispak, qboolean forthismap, const char *post_content_type, const unsigned char *postbuf, size_t postbufsize, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata) { if(!curl_dll) { return false; } else { char fn[MAX_OSPATH]; char urlbuf[1024]; const char *p, *q; size_t length; downloadinfo *di; // if URL is protocol:///* or protocol://:port/*, insert the IP of the current server p = strchr(URL, ':'); if(p) { if(!strncmp(p, ":///", 4) || !strncmp(p, "://:", 4)) { char addressstring[128]; *addressstring = 0; InfoString_GetValue(cls.userinfo, "*ip", addressstring, sizeof(addressstring)); q = strchr(addressstring, ':'); if(!q) q = addressstring + strlen(addressstring); if(*addressstring) { dpsnprintf(urlbuf, sizeof(urlbuf), "%.*s://%.*s%s", (int) (p - URL), URL, (int) (q - addressstring), addressstring, URL + (p - URL) + 3); URL = urlbuf; } } } // Note: This extraction of the file name portion is NOT entirely correct. // // It does the following: // // http://host/some/script.cgi/SomeFile.pk3?uid=ABCDE -> SomeFile.pk3 // http://host/some/script.php?uid=ABCDE&file=/SomeFile.pk3 -> SomeFile.pk3 // http://host/some/script.php?uid=ABCDE&file=SomeFile.pk3 -> script.php // // However, I'd like to keep this "buggy" behavior so that PHP script // authors can write download scripts without having to enable // AcceptPathInfo on Apache. They just have to ensure that their script // can be called with such a "fake" path name like // http://host/some/script.php?uid=ABCDE&file=/SomeFile.pk3 // // By the way, such PHP scripts should either send the file or a // "Location:" redirect; PHP code example: // // header("Location: http://www.example.com/"); // // By the way, this will set User-Agent to something like // "Nexuiz build 22:27:55 Mar 17 2006" (engineversion) and Referer to // dp://serverhost:serverport/ so you can filter on this; an example // httpd log file line might be: // // 141.2.16.3 - - [17/Mar/2006:22:32:43 +0100] "GET /maps/tznex07.pk3 HTTP/1.1" 200 1077455 "dp://141.2.16.7:26000/" "Nexuiz Linux 22:07:43 Mar 17 2006" if(!name) name = CleanURL(URL); if(!buf) { p = strrchr(name, '/'); p = p ? (p+1) : name; q = strchr(p, '?'); length = q ? (size_t)(q - p) : strlen(p); dpsnprintf(fn, sizeof(fn), "dlcache/%.*s", (int)length, p); name = fn; // make it point back // already downloading the file? { downloadinfo *di = Curl_Find(fn); if(di) { Con_Printf("Can't download %s, already getting it from %s!\n", fn, CleanURL(di->url)); // however, if it was not for this map yet... if(forthismap && !di->forthismap) { di->forthismap = true; // this "fakes" a download attempt so the client will wait for // the download to finish and then reconnect ++numdownloads_added; } return false; } } if(ispak && FS_FileExists(fn)) { qboolean already_loaded; if(FS_AddPack(fn, &already_loaded, true)) { Con_DPrintf("%s already exists, not downloading!\n", fn); if(already_loaded) Con_DPrintf("(pak was already loaded)\n"); else { if(forthismap) { ++numdownloads_added; ++numdownloads_success; } } return false; } else { qfile_t *f = FS_OpenRealFile(fn, "rb", false); if(f) { char buf[4] = {0}; FS_Read(f, buf, sizeof(buf)); // no "-1", I will use memcmp if(memcmp(buf, "PK\x03\x04", 4) && memcmp(buf, "PACK", 4)) { Con_DPrintf("Detected non-PAK %s, clearing and NOT resuming.\n", fn); FS_Close(f); f = FS_OpenRealFile(fn, "wb", false); if(f) FS_Close(f); } else { // OK FS_Close(f); } } } } } // if we get here, we actually want to download... so first verify the // URL scheme (so one can't read local files using file://) if(strncmp(URL, "http://", 7) && strncmp(URL, "ftp://", 6) && strncmp(URL, "https://", 8)) { Con_Printf("Curl_Begin(\"%s\"): nasty URL scheme rejected\n", URL); return false; } if(forthismap) ++numdownloads_added; di = (downloadinfo *) Z_Malloc(sizeof(*di)); strlcpy(di->filename, name, sizeof(di->filename)); strlcpy(di->url, URL, sizeof(di->url)); dpsnprintf(di->referer, sizeof(di->referer), "dp://%s/", cls.netcon ? cls.netcon->address : "notconnected.invalid"); di->forthismap = forthismap; di->stream = NULL; di->startpos = 0; di->curle = NULL; di->started = false; di->ispak = (ispak && !buf); di->maxspeed = maxspeed; di->bytes_received = 0; di->bytes_received_curl = 0; di->bytes_sent_curl = 0; di->extraheaders = extraheaders; di->next = downloads; di->prev = NULL; if(di->next) di->next->prev = di; di->buffer = buf; di->buffersize = bufsize; if(callback == NULL) { di->callback = curl_default_callback; di->callback_data = di; } else { di->callback = callback; di->callback_data = cbdata; } if(post_content_type) { di->post_content_type = post_content_type; di->postbuf = postbuf; di->postbufsize = postbufsize; } else { di->post_content_type = NULL; di->postbuf = NULL; di->postbufsize = 0; } downloads = di; return true; } }
/* ==================== Curl_Curl_f implements the "curl" console command curl --info curl --cancel curl --cancel filename curl url For internal use: curl [--pak] [--forthismap] [--for filename filename...] url --pak: after downloading, load the package into the virtual file system --for filename...: only download of at least one of the named files is missing --forthismap: don't reconnect on failure curl --clear_autodownload clears the download success/failure counters curl --finish_autodownload if at least one download has been started, disconnect and drop to the menu once the last download completes successfully, reconnect to the current server ==================== */ void Curl_Curl_f(void) { double maxspeed = 0; int i; int end; qboolean pak = false; qboolean forthismap = false; const char *url; const char *name = 0; if(!curl_dll) { Con_Print("libcurl DLL not found, this command is inactive.\n"); return; } if(!cl_curl_enabled.integer) { Con_Print("curl support not enabled. Set cl_curl_enabled to 1 to enable.\n"); return; } if(Cmd_Argc() < 2) { Con_Print("usage:\ncurl --info, curl --cancel [filename], curl url\n"); return; } url = Cmd_Argv(Cmd_Argc() - 1); end = Cmd_Argc(); for(i = 1; i != end; ++i) { const char *a = Cmd_Argv(i); if(!strcmp(a, "--info")) { Curl_Info_f(); return; } else if(!strcmp(a, "--cancel")) { if(i == end - 1) // last argument Curl_CancelAll(); else { downloadinfo *di = Curl_Find(url); if(di) Curl_EndDownload(di, CURL_DOWNLOAD_ABORTED, CURLE_OK); else Con_Print("download not found\n"); } return; } else if(!strcmp(a, "--pak")) { pak = true; } else if(!strcmp(a, "--for")) // must be last option { for(i = i + 1; i != end - 1; ++i) { if(!FS_FileExists(Cmd_Argv(i))) goto needthefile; // why can't I have a "double break"? } // if we get here, we have all the files... return; } else if(!strcmp(a, "--forthismap")) { forthismap = true; } else if(!strcmp(a, "--as")) { if(i < end - 1) { ++i; name = Cmd_Argv(i); } } else if(!strcmp(a, "--clear_autodownload")) { // mark all running downloads as "not for this map", so if they // fail, it does not matter Curl_Clear_forthismap(); return; } else if(!strcmp(a, "--finish_autodownload")) { if(numdownloads_added) { char donecommand[256]; if(cls.netcon) { if(cl.loadbegun) // curling won't inhibit loading the map any more when at this stage, so bail out and force a reconnect { dpsnprintf(donecommand, sizeof(donecommand), "connect %s", cls.netcon->address); Curl_CommandWhenDone(donecommand); noclear = TRUE; CL_Disconnect(); noclear = FALSE; Curl_CheckCommandWhenDone(); } else Curl_Register_predownload(); } } return; } else if(!strncmp(a, "--maxspeed=", 11)) { maxspeed = atof(a + 11); } else if(*a == '-') { Con_Printf("curl: invalid option %s\n", a); // but we ignore the option } } needthefile: Curl_Begin_ToFile(url, maxspeed, name, pak, forthismap); }
/* ==================== Curl_GetDownloadInfo returns an array of Curl_downloadinfo_t structs for usage by GUIs. The number of elements in the array is returned in int *nDownloads. const char **additional_info may be set to a string of additional user information, or to NULL if no such display shall occur. The returned array must be freed later using Z_Free. ==================== */ Curl_downloadinfo_t *Curl_GetDownloadInfo(int *nDownloads, const char **additional_info) { int i; downloadinfo *di; Curl_downloadinfo_t *downinfo; static char addinfo[128]; if(!curl_dll) { *nDownloads = 0; if(additional_info) *additional_info = NULL; return NULL; } i = 0; for(di = downloads; di; di = di->next) ++i; downinfo = (Curl_downloadinfo_t *) Z_Malloc(sizeof(*downinfo) * i); i = 0; for(di = downloads; di; di = di->next) { // do not show infobars for background downloads if(developer.integer <= 0) if(di->buffer) continue; strlcpy(downinfo[i].filename, di->filename, sizeof(downinfo[i].filename)); if(di->curle) { downinfo[i].progress = Curl_GetDownloadAmount(di); downinfo[i].speed = Curl_GetDownloadSpeed(di); downinfo[i].queued = false; } else { downinfo[i].queued = true; } ++i; } if(additional_info) { // TODO: can I clear command_when_done as soon as the first download fails? if(*command_when_done && !numdownloads_fail && numdownloads_added) { if(!strncmp(command_when_done, "connect ", 8)) dpsnprintf(addinfo, sizeof(addinfo), "(will join %s when done)", command_when_done + 8); else if(!strcmp(command_when_done, "cl_begindownloads")) dpsnprintf(addinfo, sizeof(addinfo), "(will enter the game when done)"); else dpsnprintf(addinfo, sizeof(addinfo), "(will do '%s' when done)", command_when_done); *additional_info = addinfo; } else *additional_info = NULL; } *nDownloads = i; return downinfo; }
/* ==================== Host_Init ==================== */ static void Host_Init (void) { int i; const char* os; char vabuf[1024]; if (COM_CheckParm("-profilegameonly")) Sys_AllowProfiling(false); // LordHavoc: quake never seeded the random number generator before... heh if (COM_CheckParm("-benchmark")) srand(0); // predictable random sequence for -benchmark else srand((unsigned int)time(NULL)); // FIXME: this is evil, but possibly temporary // LordHavoc: doesn't seem very temporary... // LordHavoc: made this a saved cvar // COMMANDLINEOPTION: Console: -developer enables warnings and other notices (RECOMMENDED for mod developers) if (COM_CheckParm("-developer")) { developer.value = developer.integer = 1; developer.string = "1"; } if (COM_CheckParm("-developer2") || COM_CheckParm("-developer3")) { developer.value = developer.integer = 1; developer.string = "1"; developer_extra.value = developer_extra.integer = 1; developer_extra.string = "1"; developer_insane.value = developer_insane.integer = 1; developer_insane.string = "1"; developer_memory.value = developer_memory.integer = 1; developer_memory.string = "1"; developer_memorydebug.value = developer_memorydebug.integer = 1; developer_memorydebug.string = "1"; } if (COM_CheckParm("-developer3")) { gl_paranoid.integer = 1;gl_paranoid.string = "1"; gl_printcheckerror.integer = 1;gl_printcheckerror.string = "1"; } // COMMANDLINEOPTION: Console: -nostdout disables text output to the terminal the game was launched from if (COM_CheckParm("-nostdout")) sys_nostdout = 1; // used by everything Memory_Init(); // initialize console command/cvar/alias/command execution systems Cmd_Init(); // initialize memory subsystem cvars/commands Memory_Init_Commands(); // initialize console and logging and its cvars/commands Con_Init(); // initialize various cvars that could not be initialized earlier u8_Init(); Curl_Init_Commands(); Cmd_Init_Commands(); Sys_Init_Commands(); COM_Init_Commands(); FS_Init_Commands(); // initialize console window (only used by sys_win.c) Sys_InitConsole(); // initialize the self-pack (must be before COM_InitGameType as it may add command line options) FS_Init_SelfPack(); // detect gamemode from commandline options or executable name COM_InitGameType(); // construct a version string for the corner of the console os = DP_OS_NAME; dpsnprintf (engineversion, sizeof (engineversion), "%s %s %s", gamename, os, buildstring); Con_Printf("%s\n", engineversion); // initialize process nice level Sys_InitProcessNice(); // initialize ixtable Mathlib_Init(); // initialize filesystem (including fs_basedir, fs_gamedir, -game, scr_screenshot_name) FS_Init(); // register the cvars for session locking Host_InitSession(); // must be after FS_Init Crypto_Init(); Crypto_Init_Commands(); NetConn_Init(); Curl_Init(); //PR_Init(); //PR_Cmd_Init(); PRVM_Init(); Mod_Init(); World_Init(); SV_Init(); V_Init(); // some cvars needed by server player physics (cl_rollangle etc) Host_InitCommands(); Host_InitLocal(); Host_ServerOptions(); Thread_Init(); if (cls.state == ca_dedicated) Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server (or disconnect all clients if running a server)"); else { Con_DPrintf("Initializing client\n"); R_Modules_Init(); Palette_Init(); #ifdef CONFIG_MENU MR_Init_Commands(); #endif VID_Shared_Init(); VID_Init(); Render_Init(); S_Init(); CDAudio_Init(); Key_Init(); CL_Init(); } // save off current state of aliases, commands and cvars for later restore if FS_GameDir_f is called // NOTE: menu commands are freed by Cmd_RestoreInitState Cmd_SaveInitState(); // FIXME: put this into some neat design, but the menu should be allowed to crash // without crashing the whole game, so this should just be a short-time solution // here comes the not so critical stuff if (setjmp(host_abortframe)) { return; } Host_AddConfigText(); Cbuf_Execute(); // if stuffcmds wasn't run, then quake.rc is probably missing, use default if (!host_stuffcmdsrun) { Cbuf_AddText("exec default.cfg\nexec " CONFIGFILENAME "\nexec autoexec.cfg\nstuffcmds\n"); Cbuf_Execute(); } // put up the loading image so the user doesn't stare at a black screen... SCR_BeginLoadingPlaque(true); #ifdef CONFIG_MENU if (cls.state != ca_dedicated) { MR_Init(); } #endif // check for special benchmark mode // COMMANDLINEOPTION: Client: -benchmark <demoname> runs a timedemo and quits, results of any timedemo can be found in gamedir/benchmark.log (for example id1/benchmark.log) i = COM_CheckParm("-benchmark"); if (i && i + 1 < com_argc) if (!sv.active && !cls.demoplayback && !cls.connect_trying) { Cbuf_AddText(va(vabuf, sizeof(vabuf), "timedemo %s\n", com_argv[i + 1])); Cbuf_Execute(); } // check for special demo mode // COMMANDLINEOPTION: Client: -demo <demoname> runs a playdemo and quits i = COM_CheckParm("-demo"); if (i && i + 1 < com_argc) if (!sv.active && !cls.demoplayback && !cls.connect_trying) { Cbuf_AddText(va(vabuf, sizeof(vabuf), "playdemo %s\n", com_argv[i + 1])); Cbuf_Execute(); } // COMMANDLINEOPTION: Client: -capturedemo <demoname> captures a playdemo and quits i = COM_CheckParm("-capturedemo"); if (i && i + 1 < com_argc) if (!sv.active && !cls.demoplayback && !cls.connect_trying) { Cbuf_AddText(va(vabuf, sizeof(vabuf), "playdemo %s\ncl_capturevideo 1\n", com_argv[i + 1])); Cbuf_Execute(); } if (cls.state == ca_dedicated || COM_CheckParm("-listen")) if (!sv.active && !cls.demoplayback && !cls.connect_trying) { Cbuf_AddText("startmap_dm\n"); Cbuf_Execute(); } if (!sv.active && !cls.demoplayback && !cls.connect_trying) { #ifdef CONFIG_MENU Cbuf_AddText("togglemenu 1\n"); #endif Cbuf_Execute(); } Con_DPrint("========Initialized=========\n"); //Host_StartVideo(); if (cls.state != ca_dedicated) SV_StartThread(); }
int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport) { lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress; const unsigned char *a; if (!address || !string || stringbuffersize < 1) return 0; *string = 0; switch(address->addresstype) { default: break; case LHNETADDRESSTYPE_LOOP: if (includeport) { if (stringbuffersize >= 12) { dpsnprintf(string, stringbuffersize, "local:%d", address->port); return 1; } } else { if (stringbuffersize >= 6) { memcpy(string, "local", 6); return 1; } } break; case LHNETADDRESSTYPE_INET4: a = (const unsigned char *)(&address->addr.in.sin_addr); if (includeport) { if (stringbuffersize >= 22) { dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port); return 1; } } else { if (stringbuffersize >= 16) { dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); return 1; } } break; #ifndef NOSUPPORTIPV6 case LHNETADDRESSTYPE_INET6: a = (const unsigned char *)(&address->addr.in6.sin6_addr); if (includeport) { if (stringbuffersize >= 88) { dpsnprintf(string, stringbuffersize, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15], address->port); return 1; } } else { if (stringbuffersize >= 80) { dpsnprintf(string, stringbuffersize, "%x:%x:%x:%x:%x:%x:%x:%x", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15]); return 1; } } break; #endif } return 0; }
void CDAudio_Play_byName (const char *trackname, qboolean looping, qboolean tryreal, float startposition) { unsigned int track; sfx_t* sfx; char filename[MAX_QPATH]; Host_StartVideo(); if (!enabled) return; if(tryreal && strspn(trackname, "0123456789") == strlen(trackname)) { track = (unsigned char) atoi(trackname); #ifdef MAXTRACKS if(track > 0 && track < MAXTRACKS) if(*remap[track]) { if(strspn(remap[track], "0123456789") == strlen(remap[track])) { trackname = remap[track]; } else { // ignore remappings to fake tracks if we're going to play a real track switch(cdaudio.integer) { case 0: // we never access CD case 1: // we have a replacement trackname = remap[track]; break; case 2: // we only use fake track replacement if CD track is invalid CDAudio_GetAudioDiskInfo(); if(!cdValid || track > maxTrack) trackname = remap[track]; break; case 3: // we always play from CD - ignore this remapping then case 4: // we randomize anyway break; } } } #endif } if(tryreal && strspn(trackname, "0123456789") == strlen(trackname)) { track = (unsigned char) atoi(trackname); if (track < 1) { Con_DPrintf("CDAudio: Bad track number %u.\n", track); return; } } else track = 0; // div0: I assume this code was intentionally there. Maybe turn it into a cvar? if (cdPlaying && cdPlayTrack == track && faketrack == -1) return; CDAudio_Stop (); if(track >= 1) { if(cdaudio.integer == 3) // only play real CD tracks at all { if(CDAudio_Play_real(track, looping, true)) goto success; return; } if(cdaudio.integer == 2) // prefer real CD track over fake { if(CDAudio_Play_real(track, looping, false)) goto success; } } if(cdaudio.integer == 4) // only play real CD tracks, EVEN instead of fake tracks! { if(CDAudio_Play_real(track, looping, false)) goto success; if(cdValid && maxTrack > 0) { track = 1 + (rand() % maxTrack); if(CDAudio_Play_real(track, looping, true)) goto success; } else { Con_DPrint ("No CD in player.\n"); } return; } // Try playing a fake track (sound file) first if(track >= 1) { dpsnprintf(filename, sizeof(filename), "sound/cdtracks/track%03u.wav", track); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/track%03u.ogg", track); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/track%03u.ogg", track);// added by motorsep if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/cdtracks/track%03u.ogg", track);// added by motorsep if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/track%02u.wav", track); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/track%02u.ogg", track); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/track%02u.ogg", track);// added by motorsep if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/cdtracks/track%02u.ogg", track);// added by motorsep } else { dpsnprintf(filename, sizeof(filename), "%s", trackname); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "%s.wav", trackname); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "%s.ogg", trackname); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/%s", trackname); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/%s.wav", trackname); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/%s.ogg", trackname); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/%s", trackname); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/%s.wav", trackname); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "sound/cdtracks/%s.ogg", trackname); if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/%s.ogg", trackname); // added by motorsep if (!FS_FileExists(filename)) dpsnprintf(filename, sizeof(filename), "music/cdtracks/%s.ogg", trackname); // added by motorsep } if (FS_FileExists(filename) && (sfx = S_PrecacheSound (filename, false, true))) { faketrack = S_StartSound_StartPosition (-1, 0, sfx, vec3_origin, cdvolume, 0, startposition); if (faketrack != -1) { if (looping) S_SetChannelFlag (faketrack, CHANNELFLAG_FORCELOOP, true); S_SetChannelFlag (faketrack, CHANNELFLAG_FULLVOLUME, true); S_SetChannelFlag (faketrack, CHANNELFLAG_LOCALSOUND, true); // not pausable if(track >= 1) { if(cdaudio.integer != 0) // we don't need these messages if only fake tracks can be played anyway Con_DPrintf ("Fake CD track %u playing...\n", track); } else Con_DPrintf ("BGM track %s playing...\n", trackname); } } // If we can't play a fake CD track, try the real one if (faketrack == -1) { if(cdaudio.integer == 0 || track < 1) { Con_Print("Could not load BGM track.\n"); return; } else { if(!CDAudio_Play_real(track, looping, true)) return; } } success: cdPlayLooping = looping; cdPlayTrack = track; cdPlaying = true; if (cdvolume == 0.0 || bgmvolume.value == 0) CDAudio_Pause (); }
static void Mod_Sprite_SharedSetup(const unsigned char *datapointer, int version, const unsigned int *palette, qboolean additive) { int i, j, groupframes, realframes, x, y, origin[2], width, height; qboolean fullbright; dspriteframetype_t *pinframetype; dspriteframe_t *pinframe; dspritegroup_t *pingroup; dspriteinterval_t *pinintervals; skinframe_t *skinframe; float modelradius, interval; char name[MAX_QPATH], fogname[MAX_QPATH]; const void *startframes; int texflags = (r_mipsprites.integer ? TEXF_MIPMAP : 0) | ((gl_texturecompression.integer && gl_texturecompression_sprites.integer) ? TEXF_COMPRESS : 0) | TEXF_ISSPRITE | TEXF_PICMIP | TEXF_ALPHA | TEXF_CLAMP; modelradius = 0; if (loadmodel->numframes < 1) Host_Error ("Mod_Sprite_SharedSetup: Invalid # of frames: %d", loadmodel->numframes); // LordHavoc: hack to allow sprites to be non-fullbright fullbright = true; for (i = 0;i < MAX_QPATH && loadmodel->name[i];i++) if (loadmodel->name[i] == '!') fullbright = false; // // load the frames // startframes = datapointer; realframes = 0; for (i = 0;i < loadmodel->numframes;i++) { pinframetype = (dspriteframetype_t *)datapointer; datapointer += sizeof(dspriteframetype_t); if (LittleLong (pinframetype->type) == SPR_SINGLE) groupframes = 1; else { pingroup = (dspritegroup_t *)datapointer; datapointer += sizeof(dspritegroup_t); groupframes = LittleLong(pingroup->numframes); datapointer += sizeof(dspriteinterval_t) * groupframes; } for (j = 0;j < groupframes;j++) { pinframe = (dspriteframe_t *)datapointer; if (version == SPRITE32_VERSION) datapointer += sizeof(dspriteframe_t) + LittleLong(pinframe->width) * LittleLong(pinframe->height) * 4; else //if (version == SPRITE_VERSION || version == SPRITEHL_VERSION) datapointer += sizeof(dspriteframe_t) + LittleLong(pinframe->width) * LittleLong(pinframe->height); } realframes += groupframes; } loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes); loadmodel->sprite.sprdata_frames = (mspriteframe_t *)Mem_Alloc(loadmodel->mempool, sizeof(mspriteframe_t) * realframes); loadmodel->num_textures = realframes; loadmodel->num_texturesperskin = 1; loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, sizeof(texture_t) * loadmodel->num_textures); datapointer = (unsigned char *)startframes; realframes = 0; for (i = 0;i < loadmodel->numframes;i++) { pinframetype = (dspriteframetype_t *)datapointer; datapointer += sizeof(dspriteframetype_t); if (LittleLong (pinframetype->type) == SPR_SINGLE) { groupframes = 1; interval = 0.1f; } else { pingroup = (dspritegroup_t *)datapointer; datapointer += sizeof(dspritegroup_t); groupframes = LittleLong(pingroup->numframes); pinintervals = (dspriteinterval_t *)datapointer; datapointer += sizeof(dspriteinterval_t) * groupframes; interval = LittleFloat(pinintervals[0].interval); if (interval < 0.01f) Host_Error("Mod_Sprite_SharedSetup: invalid interval"); } dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "frame %i", i); loadmodel->animscenes[i].firstframe = realframes; loadmodel->animscenes[i].framecount = groupframes; loadmodel->animscenes[i].framerate = 1.0f / interval; loadmodel->animscenes[i].loop = true; for (j = 0;j < groupframes;j++) { pinframe = (dspriteframe_t *)datapointer; datapointer += sizeof(dspriteframe_t); origin[0] = LittleLong (pinframe->origin[0]); origin[1] = LittleLong (pinframe->origin[1]); width = LittleLong (pinframe->width); height = LittleLong (pinframe->height); loadmodel->sprite.sprdata_frames[realframes].left = origin[0]; loadmodel->sprite.sprdata_frames[realframes].right = origin[0] + width; loadmodel->sprite.sprdata_frames[realframes].up = origin[1]; loadmodel->sprite.sprdata_frames[realframes].down = origin[1] - height; x = (int)max(loadmodel->sprite.sprdata_frames[realframes].left * loadmodel->sprite.sprdata_frames[realframes].left, loadmodel->sprite.sprdata_frames[realframes].right * loadmodel->sprite.sprdata_frames[realframes].right); y = (int)max(loadmodel->sprite.sprdata_frames[realframes].up * loadmodel->sprite.sprdata_frames[realframes].up, loadmodel->sprite.sprdata_frames[realframes].down * loadmodel->sprite.sprdata_frames[realframes].down); if (modelradius < x + y) modelradius = x + y; if (cls.state != ca_dedicated) { skinframe = NULL; // note: Nehahra's null.spr has width == 0 and height == 0 if (width > 0 && height > 0) { if (groupframes > 1) { dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j); dpsnprintf (fogname, sizeof(fogname), "%s_%i_%ifog", loadmodel->name, i, j); } else { dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i); dpsnprintf (fogname, sizeof(fogname), "%s_%ifog", loadmodel->name, i); } if (!(skinframe = R_SkinFrame_LoadExternal(name, texflags | TEXF_COMPRESS, false))) { unsigned char *pixels = (unsigned char *) Mem_Alloc(loadmodel->mempool, width*height*4); if (version == SPRITE32_VERSION) { for (x = 0;x < width*height;x++) { pixels[x*4+2] = datapointer[x*4+0]; pixels[x*4+1] = datapointer[x*4+1]; pixels[x*4+0] = datapointer[x*4+2]; pixels[x*4+3] = datapointer[x*4+3]; } } else //if (version == SPRITEHL_VERSION || version == SPRITE_VERSION) Image_Copy8bitBGRA(datapointer, pixels, width*height, palette ? palette : palette_bgra_transparent); skinframe = R_SkinFrame_LoadInternalBGRA(name, texflags, pixels, width, height, false); // texflags |= TEXF_COMPRESS; Mem_Free(pixels); } } if (skinframe == NULL) skinframe = R_SkinFrame_LoadMissing(); Mod_SpriteSetupTexture(&loadmodel->data_textures[realframes], skinframe, fullbright, additive); } if (version == SPRITE32_VERSION) datapointer += width * height * 4; else //if (version == SPRITE_VERSION || version == SPRITEHL_VERSION) datapointer += width * height; realframes++; } } modelradius = sqrt(modelradius); for (i = 0;i < 3;i++) { loadmodel->normalmins[i] = loadmodel->yawmins[i] = loadmodel->rotatedmins[i] = -modelradius; loadmodel->normalmaxs[i] = loadmodel->yawmaxs[i] = loadmodel->rotatedmaxs[i] = modelradius; } loadmodel->radius = modelradius; loadmodel->radius2 = modelradius * modelradius; }
void Mod_IDS2_Load(dp_model_t *mod, void *buffer, void *bufferend) { int i, version; qboolean fullbright; const dsprite2_t *pinqsprite; skinframe_t *skinframe; float modelradius; int texflags = (r_mipsprites.integer ? TEXF_MIPMAP : 0) | TEXF_ISSPRITE | TEXF_PICMIP | TEXF_COMPRESS | TEXF_ALPHA | TEXF_CLAMP; loadmodel->modeldatatypestring = "SPR2"; loadmodel->type = mod_sprite; loadmodel->DrawSky = NULL; loadmodel->Draw = R_Model_Sprite_Draw; loadmodel->DrawDepth = NULL; loadmodel->CompileShadowVolume = NULL; loadmodel->DrawShadowVolume = NULL; loadmodel->DrawLight = NULL; loadmodel->DrawAddWaterPlanes = NULL; pinqsprite = (dsprite2_t *)buffer; version = LittleLong(pinqsprite->version); if (version != SPRITE2_VERSION) Host_Error("Mod_IDS2_Load: %s has wrong version number (%i should be 2 (quake 2)", loadmodel->name, version); loadmodel->numframes = LittleLong (pinqsprite->numframes); if (loadmodel->numframes < 1) Host_Error ("Mod_IDS2_Load: Invalid # of frames: %d", loadmodel->numframes); loadmodel->sprite.sprnum_type = SPR_VP_PARALLEL; loadmodel->synctype = ST_SYNC; // LordHavoc: hack to allow sprites to be non-fullbright fullbright = true; for (i = 0;i < MAX_QPATH && loadmodel->name[i];i++) if (loadmodel->name[i] == '!') fullbright = false; loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes); loadmodel->sprite.sprdata_frames = (mspriteframe_t *)Mem_Alloc(loadmodel->mempool, sizeof(mspriteframe_t) * loadmodel->numframes); loadmodel->num_textures = loadmodel->numframes; loadmodel->num_texturesperskin = 1; loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, sizeof(texture_t) * loadmodel->num_textures); modelradius = 0; for (i = 0;i < loadmodel->numframes;i++) { int origin[2], x, y, width, height; const dsprite2frame_t *pinframe; mspriteframe_t *sprframe; dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "frame %i", i); loadmodel->animscenes[i].firstframe = i; loadmodel->animscenes[i].framecount = 1; loadmodel->animscenes[i].framerate = 10; loadmodel->animscenes[i].loop = true; pinframe = &pinqsprite->frames[i]; origin[0] = LittleLong (pinframe->origin_x); origin[1] = LittleLong (pinframe->origin_y); width = LittleLong (pinframe->width); height = LittleLong (pinframe->height); sprframe = &loadmodel->sprite.sprdata_frames[i]; // note that sp2 origin[0] is positive, where as it is negative in // spr/spr32/hlspr sprframe->left = -origin[0]; sprframe->right = -origin[0] + width; sprframe->up = origin[1]; sprframe->down = origin[1] - height; x = (int)max(sprframe->left * sprframe->left, sprframe->right * sprframe->right); y = (int)max(sprframe->up * sprframe->up, sprframe->down * sprframe->down); if (modelradius < x + y) modelradius = x + y; } if (cls.state != ca_dedicated) { for (i = 0;i < loadmodel->numframes;i++) { const dsprite2frame_t *pinframe; pinframe = &pinqsprite->frames[i]; if (!(skinframe = R_SkinFrame_LoadExternal(pinframe->name, texflags, false))) { Con_Printf("Mod_IDS2_Load: failed to load %s", pinframe->name); skinframe = R_SkinFrame_LoadMissing(); } Mod_SpriteSetupTexture(&loadmodel->data_textures[i], skinframe, fullbright, false); } } modelradius = sqrt(modelradius); for (i = 0;i < 3;i++) { loadmodel->normalmins[i] = loadmodel->yawmins[i] = loadmodel->rotatedmins[i] = -modelradius; loadmodel->normalmaxs[i] = loadmodel->yawmaxs[i] = loadmodel->rotatedmaxs[i] = modelradius; } loadmodel->radius = modelradius; loadmodel->radius2 = modelradius * modelradius; // TODO: Note that isanimated only means whether vertices change due to // the animation. This may happen due to sprframe parameters changing. // Mere texture chanegs OTOH shouldn't require isanimated to be 1. loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1); }