void QE_CheckAutoSave( void ){ static time_t s_start; time_t now; time( &now ); if ( modified != 1 || !s_start ) { s_start = now; return; } if ( ( now - s_start ) > ( 60 * g_PrefsDlg.m_nAutoSave ) ) { if ( g_PrefsDlg.m_bAutoSave ) { CString strMsg; strMsg = g_PrefsDlg.m_bSnapShots ? "Autosaving snapshot..." : "Autosaving..."; Sys_Printf( strMsg ); Sys_Printf( "\n" ); Sys_Status( strMsg,0 ); // only snapshot if not working on a default map if ( g_PrefsDlg.m_bSnapShots && stricmp( currentmap, "unnamed.map" ) != 0 ) { Map_Snapshot(); } else { Map_SaveFile( ValueForKey( g_qeglobals.d_project_entity, "autosave" ), false ); } Sys_Status( "Autosaving...Saved.", 0 ); modified = 2; } else { Sys_Printf( "Autosave skipped...\n" ); Sys_Status( "Autosave skipped...", 0 ); } s_start = now; } }
/* ==================== Entity_UpdateSoundEmitter Deletes the soundEmitter if the entity should not emit a sound due to it not having one, being filtered away, or the sound mode being turned off. Creates or updates the soundEmitter if needed ==================== */ void Entity_UpdateSoundEmitter( entity_t *ent ) { bool playing = false; // if an entity doesn't have any brushes at all, don't do anything // if the brush isn't displayed (filtered or culled), don't do anything if ( g_pParentWnd->GetCamera()->GetSoundMode() && ent->brushes.onext != &ent->brushes && !FilterBrush(ent->brushes.onext) ) { // check for sounds const char *v = ValueForKey( ent, "s_shader" ); if ( v[0] ) { refSound_t sound; gameEdit->ParseSpawnArgsToRefSound( &ent->epairs, &sound ); if ( !sound.waitfortrigger ) // waitfortrigger will not start playing immediately { if ( !ent->soundEmitter ) { ent->soundEmitter = g_qeglobals.sw->AllocSoundEmitter(); } playing = true; ent->soundEmitter->UpdateEmitter( ent->origin, 0, &sound.parms ); // always play on a single channel, so updates always override ent->soundEmitter->StartSound( sound.shader, SCHANNEL_ONE ); } } } // delete the soundEmitter if not used if ( !playing && ent->soundEmitter ) { ent->soundEmitter->Free( true ); ent->soundEmitter = NULL; } }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void DispGetFaceInfo( mapbrush_t *pBrush ) { int i; side_t *pSide; // we don't support displacement on entities at the moment!! if( pBrush->entitynum != 0 ) { char* pszEntityName = ValueForKey( &entities[pBrush->entitynum], "classname" ); Error( "Error: displacement found on a(n) %s entity - not supported\n", pszEntityName ); } for( i = 0; i < pBrush->numsides; i++ ) { pSide = &pBrush->original_sides[i]; if( pSide->pMapDisp ) { // error checking!! if( pSide->winding->numpoints != 4 ) Error( "Trying to create a non-quad displacement!\n" ); pSide->pMapDisp->face.originalface = pSide; pSide->pMapDisp->face.texinfo = pSide->texinfo; pSide->pMapDisp->face.dispinfo = -1; pSide->pMapDisp->face.planenum = pSide->planenum; pSide->pMapDisp->face.numpoints = pSide->winding->numpoints; pSide->pMapDisp->face.w = CopyWinding( pSide->winding ); pSide->pMapDisp->face.contents = pBrush->contents; pSide->pMapDisp->face.merged = FALSE; pSide->pMapDisp->face.split[0] = FALSE; pSide->pMapDisp->face.split[1] = FALSE; pSide->pMapDisp->entitynum = pBrush->entitynum; pSide->pMapDisp->brushSideID = pSide->id; } } }
//----------------------------------------------------------------------------- // Compute the bounding box, excluding 3D skybox + skybox, add it to keyvalues //----------------------------------------------------------------------------- void ComputeBoundsNoSkybox( ) { // Iterate over all world leaves, skip those which are part of skybox Vector mins, maxs; ClearBounds (mins, maxs); AddNodeToBounds( dmodels[0].headnode, g_SkyAreas, mins, maxs ); AddDispsToBounds( dmodels[0].headnode, g_SkyAreas, mins, maxs ); // Add the bounds to the worldspawn data for (int i = 0; i < num_entities; ++i) { char* pEntity = ValueForKey(&entities[i], "classname"); if (!strcmp(pEntity, "worldspawn")) { char string[32]; sprintf (string, "%i %i %i", (int)mins[0], (int)mins[1], (int)mins[2]); SetKeyValue (&entities[i], "world_mins", string); sprintf (string, "%i %i %i", (int)maxs[0], (int)maxs[1], (int)maxs[2]); SetKeyValue (&entities[i], "world_maxs", string); break; } } }
static qboolean HasUniqueEntityName(const entity_t * ent, const char *name) { int i; entity_t *ent2; const char *name2; for(i = 0; i < numEntities; i++) { ent2 = &entities[i]; if(ent == ent2) continue; name2 = ValueForKey(ent2, "name"); if(!Q_stricmp(name, name2)) { return qfalse; } } return qtrue; }
vec_t FloatForKey( entity_t *ent, char *key ) { char *k; k = ValueForKey( ent, key ); return atof( k ); }
/** * @brief Perform an entity check */ void CheckEntities (void) { Check_InitEntityDefs(); for (int i = 0; i < num_entities; i++) { entity_t* e = &entities[i]; const char* name = ValueForKey(e, "classname"); const entityDef_t* ed = ED_GetEntityDef(name); const epair_t* kvp; const entityKeyDef_t* kd; if (!ed) { /* check that a definition exists */ Check_Printf(VERB_CHECK, false, i, -1, "Not defined in entities.ufo: %s\n", name); continue; } /* check alignment of info_.+_start */ if (Check_IsInfoStart(name) && !Check_InfoStartAligned(ed, e)) Check_Printf(VERB_CHECK, false, i, -1, "Misaligned %s\n", name); if (Q_strstart(name, "func_")) /* func_* entities should have brushes */ Check_EntityWithBrushes(e, name, i); /* check all keys in the entity - make sure they are OK */ for (kvp = e->epairs; kvp; kvp = kvp->next) { kd = ED_GetKeyDefEntity(ed, kvp->key, 0); /* zero means ignore abstract (radiant only) keys */ if (!kd) { /* make sure it has a definition */ Check_Printf(VERB_CHECK, false, i, -1, "Not defined in entities.ufo: %s in %s\n", kvp->key, name); continue; } if (ED_CheckKey(kd, kvp->value) == ED_ERROR) { /* check values against type and range definitions in entities.ufo */ Check_Printf(VERB_CHECK, false, i, -1, "%s\n", ED_GetLastError()); continue; } if (Q_streq("target", kvp->key) || Q_streq("targetname", kvp->key)) { if (!Check_TargetExists(kvp)) { Check_Printf(VERB_CHECK, false, i, -1, "%s with %s of %s: no corresponding entity with %s with matching value\n", ed->classname, kvp->key, kvp->value, Q_streq("target", kvp->key) ? "targetname" : "target"); } } } /* check keys in the entity definition - make sure mandatory ones are present */ for (kd = ed->keyDefs; kd->name; kd++) { if (kd->flags & ED_MANDATORY) { const char* keyNameInEnt = ValueForKey(e, kd->name); if (keyNameInEnt[0] == '\0') { const char* defaultVal = kd->defaultVal; const bool hasDefault = defaultVal ? true : false; Check_Printf(VERB_CHECK, hasDefault, i, -1, "Mandatory key missing from entity: %s in %s", kd->name, name); if (defaultVal) { Check_Printf(VERB_CHECK, hasDefault, i, -1, ", supplying default: %s", defaultVal); SetKeyValue(e, kd->name, defaultVal); } Check_Printf(VERB_CHECK, hasDefault, i, -1, "\n"); } } } } }
void RunBsp( char* command ) { char sys[2048]; char batpath[2048]; char outputpath[2048]; char temppath[1024]; char name[2048]; char cWork[2048]; FILE* hFile; BOOL ret; PROCESS_INFORMATION ProcessInformation; STARTUPINFO startupinfo; HWND hwndPClient = NULL; g_hWnd = g_pParentWnd->GetSafeHwnd(); SetInspectorMode( W_CONSOLE ); g_tBegin = CTime::GetCurrentTime(); DWORD dwExitcode; ret = GetExitCodeProcess( g_hToolThread, &dwExitcode ); if ( dwExitcode != STILL_ACTIVE ) g_hToolThread = NULL; if ( bsp_process || g_hToolThread ) { Sys_Printf( "BSP is still going...\n" ); return; } outputpath[0] = '\0'; GetTempPath( 512, temppath ); CString strOutFile = temppath; AddSlash( strOutFile ); strOutFile += "junk.txt"; sprintf( outputpath, " >>%s\r\n", strOutFile ); strcpy( name, currentmap ); if ( region_active ) { Map_SaveFile( name, false ); StripExtension( name ); strcat( name, ".reg" ); } Map_SaveFile( name, region_active ); // FIXME: this code just gets worse and worse CString strPath, strFile; char* rsh = ValueForKey( g_qeglobals.d_project_entity, "rshcmd" ); if ( rsh == NULL ) { ExtractPath_and_Filename( name, strPath, strFile ); AddSlash( strPath ); BuildShortPathName( strPath, cWork, 1024 ); strcat( cWork, strFile ); } else { strcpy( cWork, name ); } hwndPClient = FindWindow( NULL, "Q3Map Process Client" ); if ( hwndPClient == NULL ) { hwndPClient = FindAnyWindow( "Q3Map Process Client" ); } Sys_Printf( "Window info for Process Client %i\n", reinterpret_cast<int>( hwndPClient ) ); bool processServer = ( rsh && strlen( rsh ) > 0 && hwndPClient ); QE_ExpandBspString( command, sys, cWork, processServer ); // if we can find the q3map process server running // we will submit maps to it instead of via createprocess // if ( processServer ) { CString str; char cBuff[2048]; char* pStart = sys; char* pEnd = strstr( pStart, "&&" ); while ( pEnd ) { int nLen = pEnd - pStart - 1; strncpy( cBuff, pStart, nLen ); cBuff[nLen] = 0; str = cBuff; FindReplace( str, rsh, "" ); str.TrimLeft( ' ' ); str.TrimRight( ' ' ); ATOM a = GlobalAddAtom( str ); PostMessage( hwndPClient, wm_AddCommand, 0, ( LPARAM )a ); pStart = pEnd + 2; pEnd = strstr( pStart, "&&" ); } str = pStart; FindReplace( str, rsh, "" ); str.TrimLeft( ' ' ); str.TrimRight( ' ' ); ATOM a = GlobalAddAtom( str ); PostMessage( hwndPClient, wm_AddCommand, 0, ( LPARAM )a ); Sys_Printf( "Commands sent to Q3Map Process Client\n" ); return; } CString strSys = sys; FindReplace( strSys, "&&", outputpath ); strcpy( sys, strSys ); strcat( sys, outputpath ); Sys_ClearPrintf(); Sys_Printf( "==================\nRunning bsp command...\n" ); Sys_Printf( "\n%s\n", sys ); //++timo removed the old way BSP commands .. dumping to junk.txt doesn't work on my win98 box // FIXME : will most likely break Quake2 BSP commands, is fitted to a one-lined sys command // // write qe3bsp.bat // //const char *basePath = ValueForKey(g_qeglobals.d_project_entity, "basepath"); //if(basePath) { //const char *mapName = //sprintf(batpath,"%s/maps/%s.bat",basePath,mapName); strcpy( batpath, currentmap ); char* dot = strchr( batpath, '.' ); strcpy( dot, ".bat" ); //} else { // sprintf (batpath, "%sqe3bsp.bat", temppath); //} hFile = fopen( batpath, "w" ); if ( !hFile ) Error( "Can't write to %s", batpath ); fprintf( hFile, sys ); fclose( hFile ); Pointfile_Delete(); // delete junk.txt file remove( strOutFile ); GetStartupInfo( &startupinfo ); ret = CreateProcess( batpath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupinfo, &ProcessInformation ); if ( !ret ) Error( "CreateProcess failed" ); bsp_process = ProcessInformation.hProcess; Sleep( 100 ); // give the new process a chance to open it's window BringWindowToTop( g_qeglobals.d_hwndMain ); // pop us back on top #if 0 // // write qe3bsp.bat // sprintf( batpath, "%sqe3bsp.bat", temppath ); hFile = fopen( batpath, "w" ); if ( !hFile ) Error( "Can't write to %s", batpath ); fprintf( hFile, sys ); fclose( hFile ); // // write qe3bsp2.bat // sprintf( batpath, "%sqe3bsp2.bat", temppath ); hFile = fopen( batpath, "w" ); if ( !hFile ) Error( "Can't write to %s", batpath ); fprintf( hFile, "%sqe3bsp.bat > %s", temppath, outputpath ); fclose( hFile ); Pointfile_Delete(); GetStartupInfo( &startupinfo ); ret = CreateProcess( batpath, // pointer to name of executable module NULL, // pointer to command line string NULL, // pointer to process security attributes NULL, // pointer to thread security attributes FALSE, // handle inheritance flag 0 /*DETACHED_PROCESS*/, // creation flags NULL, // pointer to new environment block NULL, // pointer to current directory name &startupinfo, // pointer to STARTUPINFO &ProcessInformation // pointer to PROCESS_INFORMATION ); if ( !ret ) Error( "CreateProcess failed" ); bsp_process = ProcessInformation.hProcess; Sleep( 100 ); // give the new process a chance to open it's window //BringWindowToTop( g_qeglobals.d_hwndMain ); // pop us back on top //SetFocus (g_qeglobals.d_hwndCamera); #endif }
/* ================== CalcVis ================== */ void CalcVis(void) { int i, minvis, maxvis; const char *value; double mu, sigma, totalvis, totalvis2; /* ydnar: rr2do2's farplane code */ farPlaneDist = 0.0f; value = ValueForKey(&entities[0], "_farplanedist"); /* proper '_' prefixed key */ if(value[0] == '\0') value = ValueForKey(&entities[0], "fogclip"); /* wolf compatibility */ if(value[0] == '\0') value = ValueForKey(&entities[0], "distancecull"); /* sof2 compatibility */ if(value[0] != '\0') { farPlaneDist = atof(value); if(farPlaneDist > 0.0f) Sys_Printf("farplane distance = %.1f\n", farPlaneDist); else farPlaneDist = 0.0f; } Sys_Printf("\n--- BasePortalVis (%d) ---\n", numportals * 2); RunThreadsOnIndividual(numportals * 2, qtrue, BasePortalVis); // RunThreadsOnIndividual (numportals*2, qtrue, BetterPortalVis); SortPortals(); if(fastvis) { CalcFastVis(); } else if(noPassageVis) { CalcPortalVis(); } else if(passageVisOnly) { CalcPassageVis(); } else { CalcPassagePortalVis(); } // // assemble the leaf vis lists by oring and compressing the portal lists // Sys_Printf("creating leaf vis...\n"); for(i = 0; i < portalclusters; i++) ClusterMerge(i); totalvis = 0; totalvis2 = 0; minvis = -1; maxvis = -1; for(i = 0; i < MAX_MAP_LEAFS; ++i) if(clustersizehistogram[i]) { if(debugCluster) Sys_FPrintf(SYS_VRB, "%4i clusters have exactly %4i visible clusters\n", clustersizehistogram[i], i); /* cast is to prevent integer overflow */ totalvis += ((double)i) * ((double)clustersizehistogram[i]); totalvis2 += ((double)i) * ((double)i) * ((double)clustersizehistogram[i]); if(minvis < 0) minvis = i; maxvis = i; } mu = totalvis / portalclusters; sigma = sqrt(totalvis2 / portalclusters - mu * mu); Sys_Printf("Total clusters: %i\n", portalclusters); Sys_Printf("Total visible clusters: %.0f\n", totalvis); Sys_Printf("Average clusters visible: %.2f (%.3f%%/total)\n", mu, mu / portalclusters * 100.0); Sys_Printf(" Standard deviation: %.2f (%.3f%%/total, %.3f%%/avg)\n", sigma, sigma / portalclusters * 100.0, sigma / mu * 100.0); Sys_Printf(" Minimum: %i (%.3f%%/total, %.3f%%/avg)\n", minvis, minvis / (double)portalclusters * 100.0, minvis / mu * 100.0); Sys_Printf(" Maximum: %i (%.3f%%/total, %.3f%%/avg)\n", maxvis, maxvis / (double)portalclusters * 100.0, maxvis / mu * 100.0); }
/* =========== FillOutside =========== */ node_t *FillOutside (node_t *node, qboolean leakfile) { int s; vec_t *v; int i; qboolean inside; qboolean ret; vec3_t origin; char *cl; qprintf ("----- FillOutside ----\n"); if (nofill) { printf ("skipped\n"); return node; } // // place markers for all entities so // we know if we leak inside // inside = false; for (i=1 ; i<num_entities ; i++) { GetVectorForKey (&entities[i], "origin", origin); if (!VectorCompare(origin, vec3_origin)) { cl = ValueForKey (&entities[i], "classname"); origin[2] += 1; // so objects on floor are ok // nudge playerstart around if needed so clipping hulls allways // have a vlaid point if (!strcmp (cl, "info_player_start")) { int x, y; for (x=-16 ; x<=16 ; x += 16) { for (y=-16 ; y<=16 ; y += 16) { origin[0] += x; origin[1] += y; if (PlaceOccupant (i, origin, node)) { inside = true; goto gotit; } origin[0] -= x; origin[1] -= y; } } gotit: ; } else { if (PlaceOccupant (i, origin, node)) inside = true; } } } if (!inside) { printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum); return node; } s = !(outside_node.portals->nodes[1] == &outside_node); // first check to see if an occupied leaf is hit outleafs = 0; valid++; prevleaknode = NULL; if (leakfile) { pointfile = fopen (pointfilename, "w"); if (!pointfile) Error ("Couldn't open %s\n", pointfilename); StripExtension (pointfilename); strcat (pointfilename, ".lin"); linefile = fopen (pointfilename, "w"); if (!linefile) Error ("Couldn't open %s\n", pointfilename); } ret = RecursiveFillOutside (outside_node.portals->nodes[s], false); if (leakfile) { fclose (pointfile); fclose (linefile); } if (ret) { printf("LEAK LEAK LEAK\n"); GetVectorForKey (&entities[hit_occupied], "origin", origin); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n" , origin[0], origin[1], origin[2]); qprintf ("no filling performed\n"); qprintf ("point file and line file generated\n"); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); if (leakonly) Error ("Stopped by leak."); return node; } // now go back and fill things in valid++; RecursiveFillOutside (outside_node.portals->nodes[s], true); // remove faces and nodes from filled in leafs c_falsenodes = 0; c_free_faces = 0; c_keep_faces = 0; node = ClearOutFaces_r (node); qprintf ("%5i outleafs\n", outleafs); qprintf ("%5i freed faces\n", c_free_faces); qprintf ("%5i keep faces\n", c_keep_faces); qprintf ("%5i falsenodes\n", c_falsenodes); // save portal file for vis tracing if (leakfile) WritePortalfile (node); return node; }
BOOL CALLBACK EditCommandDlgProc ( HWND hwndDlg, // handle to dialog box UINT uMsg, // message WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { char key[1024]; char value[1024]; const char *temp; int index; HWND hOwner; hOwner = GetParent (hwndDlg); switch (uMsg) { case WM_INITDIALOG: index = SendDlgItemMessage (hOwner, IDC_CMD_LIST, LB_GETCURSEL, 0, 0); if (index >= 0) { SendDlgItemMessage(hOwner, IDC_CMD_LIST, LB_GETTEXT, index, (LPARAM) (LPCTSTR) key); temp = ValueForKey (g_qeglobals.d_project_entity, key); strcpy (value, temp); SetDlgItemText(hwndDlg, IDC_CMDMENUTEXT, key); SetDlgItemText(hwndDlg, IDC_CMDCOMMAND, value); } return FALSE; break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if (!GetDlgItemText(hwndDlg, IDC_CMDMENUTEXT, key, 64)) { common->Printf ("Command not added\n"); return FALSE; } if (!GetDlgItemText(hwndDlg, IDC_CMDCOMMAND, value, 64)) { common->Printf ("Command not added\n"); return FALSE; } //if (key[0] == 'b' && key[1] == 's' && key[2] == 'p') //{ SetKeyValue (g_qeglobals.d_project_entity, key, value); FillBSPMenu (); //} //else // common->Printf ("BSP commands must be preceded by \"bsp\""); EndDialog(hwndDlg, 1); return TRUE; case IDCANCEL: EndDialog(hwndDlg, 0); return TRUE; } } return FALSE; }
void Parse_Serverinfo(server_data *s, char *info) { int i, j; char *pinfo; char *tmp; s->passed_filters = 1; s->support_teams = false; // by default server does't support team info per player if (strncmp(info, "\xFF\xFF\xFF\xFFn", 5)) { SetPing(s, -1); return; } pinfo = strchr(info, '\n'); if (pinfo != NULL) *(pinfo++) = 0; info += 5; while (*info == '\\' && s->keysn < MAX_KEYS) { char *i2, *i3; i2 = strchr(info+1, '\\'); if (i2 == NULL) break; i3 = strchr(i2+1, '\\'); if (i3 == NULL) i3 = info + strlen(info); s->keys[s->keysn] = (char *) Q_malloc(i2-info); strlcpy(s->keys[s->keysn], info+1, i2-info); s->values[s->keysn] = (char *) Q_malloc(i3-i2); strlcpy(s->values[s->keysn], i2+1, i3-i2); s->keysn++; info = i3; } // read players for (i = s->spectatorsn = s->playersn = 0; pinfo && strchr(pinfo, '\n'); i++) { qbool spec; int id, frags, time, ping, slen; char name[100], skin[100], team[100]; char *nameptr = name; int top, bottom; int pos; if (s->playersn + s->spectatorsn >= MAX_PLAYERS) break; // man pos = 0; pos += ReadInt(pinfo+pos, &id); pos += ReadInt(pinfo+pos, &frags); pos += ReadInt(pinfo+pos, &time); pos += ReadInt(pinfo+pos, &ping); pos += ReadString(pinfo+pos, name); pos += ReadString(pinfo+pos, skin); pos += ReadInt(pinfo+pos, &top); pos += ReadInt(pinfo+pos, &bottom); pos += ReadString(pinfo+pos, team); if (team[0]) s->support_teams = true; // seems server support team info per player if (ping > 0) { // seems player if relay on ping spec = false; s->playersn++; } else // spec { spec = true; slen = strlen(name); s->spectatorsn++; ping = -ping; if (name[0] == '\\' && name[1] == 's' && name[2] == '\\') nameptr = name+3; // strip \s\<name> else if (slen > 3 && name[slen-3] == '(' && name[slen-2] == 's' && name[slen-1] == ')') name[slen-3] = 0; // strip <name>(s) for old servers } s->players[i] = (playerinfo *)Q_malloc(sizeof(playerinfo)); s->players[i]->id = id; s->players[i]->frags = frags; s->players[i]->time = time; s->players[i]->ping = ping; s->players[i]->spec = spec; s->players[i]->top = Sbar_ColorForMap(top); s->players[i]->bottom = Sbar_ColorForMap(bottom); strlcpy(s->players[i]->name, nameptr, sizeof(s->players[0]->name)); strlcpy(s->players[i]->skin, skin, sizeof(s->players[0]->skin)); strlcpy(s->players[i]->team, team, sizeof(s->players[0]->team)); pinfo = strchr(pinfo, '\n') + 1; } { void *swap; int n; // sort players by frags n = s->playersn + s->spectatorsn - 2; for (i = 0; i <= n; i++) for (j = n; j >= i; j--) if (s->players[j] && s->players[j+1] && s->players[j]->frags < s->players[j+1]->frags) { swap = (void*)s->players[j]; s->players[j] = s->players[j+1]; s->players[j+1] = (playerinfo*)swap; } // sort keys n = s->keysn - 2; for (i = 0; i <= n; i++) for (j = n; j >= i; j--) if (strcasecmp(s->keys[j], s->keys[j+1]) > 0) { swap = (void*)s->keys[j]; s->keys[j] = s->keys[j+1]; s->keys[j+1] = (char*)swap; swap = (void*)s->values[j]; s->values[j] = s->values[j+1]; s->values[j+1] = (char*)swap; } } // fill-in display s->qwfwd = SB_IsServerQWfwd(s); tmp = ValueForKey(s, "hostname"); if (tmp != NULL) snprintf (s->display.name, sizeof (s->display.name),"%-.*s", COL_NAME, tmp); else return; tmp = ValueForKey(s, "fraglimit"); if (tmp != NULL) snprintf(s->display.fraglimit, sizeof (s->display.fraglimit), "%*.*s", COL_FRAGLIMIT, COL_FRAGLIMIT, strlen(tmp) > COL_FRAGLIMIT ? "999" : tmp); tmp = ValueForKey(s, "timelimit"); if (tmp != NULL) snprintf(s->display.timelimit, sizeof (s->display.timelimit), "%*.*s", COL_TIMELIMIT, COL_TIMELIMIT, strlen(tmp) > COL_TIMELIMIT ? "99" : tmp); tmp = ValueForKey(s, "*gamedir"); s->qizmo = false; if (tmp != NULL) snprintf(s->display.gamedir, sizeof (s->display.gamedir) ,"%.*s", COL_GAMEDIR, tmp==NULL ? "" : tmp); else { tmp = ValueForKey(s, "*progs"); if (tmp != NULL && !strcmp(tmp, "666")) { snprintf(s->display.gamedir, sizeof (s->display.gamedir), "qizmo"); s->qizmo = true; } } tmp = ValueForKey(s, "map"); if (tmp != NULL) snprintf(s->display.map, sizeof (s->display.map), "%-.*s", COL_MAP, tmp==NULL ? "" : tmp); tmp = ValueForKey(s, "maxclients"); if (!tmp || strlen(tmp) > 2) tmp = "99"; i = s->playersn > 99 ? 99 : s->playersn; if (i < 1) { s->occupancy = SERVER_EMPTY; } else if (i > 0 && i < atoi(tmp)) { s->occupancy = SERVER_NONEMPTY; } else { s->occupancy = SERVER_FULL; } if (tmp != NULL) snprintf(s->display.players, sizeof (s->display.players), "%2d/%-2s", i, tmp==NULL ? "" : tmp); }
// AJM: addded in // ===================================================================================== // GetParamsFromEnt // this function is called from parseentity when it encounters the // info_compile_parameters entity. each tool should have its own version of this // to handle its own specific settings. // ===================================================================================== void GetParamsFromEnt(entity_t* mapent) { int iTmp; Log("\nCompile Settings detected from info_compile_parameters entity\n"); // verbose(choices) : "Verbose compile messages" : 0 = [ 0 : "Off" 1 : "On" ] iTmp = IntForKey(mapent, "verbose"); if (iTmp == 1) { g_verbose = true; } else if (iTmp == 0) { g_verbose = false; } Log("%30s [ %-9s ]\n", "Compile Option", "setting"); Log("%30s [ %-9s ]\n", "Verbose Compile Messages", g_verbose ? "on" : "off"); // estimate(choices) :"Estimate Compile Times?" : 0 = [ 0: "Yes" 1: "No" ] if (IntForKey(mapent, "estimate")) { g_estimate = true; } else { g_estimate = false; } Log("%30s [ %-9s ]\n", "Estimate Compile Times", g_estimate ? "on" : "off"); // priority(choices) : "Priority Level" : 0 = [ 0 : "Normal" 1 : "High" -1 : "Low" ] if (!strcmp(ValueForKey(mapent, "priority"), "1")) { g_threadpriority = eThreadPriorityHigh; Log("%30s [ %-9s ]\n", "Thread Priority", "high"); } else if (!strcmp(ValueForKey(mapent, "priority"), "-1")) { g_threadpriority = eThreadPriorityLow; Log("%30s [ %-9s ]\n", "Thread Priority", "low"); } /* hlvis(choices) : "HLVIS" : 2 = [ 0 : "Off" 1 : "Fast" 2 : "Normal" 3 : "Full" ] */ iTmp = IntForKey(mapent, "hlvis"); if (iTmp == 0) { Fatal(assume_TOOL_CANCEL, "%s flag was not checked in info_compile_parameters entity, execution of %s cancelled", g_Program, g_Program); CheckFatal(); } else if (iTmp == 1) { g_fastvis = true; g_fullvis = false; } else if (iTmp == 2) { g_fastvis = false; g_fullvis = false; } else if (iTmp == 3) { g_fullvis = true; g_fastvis = false; } Log("%30s [ %-9s ]\n", "Fast VIS", g_fastvis ? "on" : "off"); Log("%30s [ %-9s ]\n", "Full VIS", g_fullvis ? "on" : "off" ); /////////////////// Log("\n"); }
void WriteMiptex (void) { int i, success; byte *miptex_data; dmiptexlump_t *miptex_lumps; char *path, *currentpath; miptexfile_t *m; path = ValueForKey (&entities[0], "_wad"); if (!path || !path[0]) { path = ValueForKey (&entities[0], "wad"); if (!path || !path[0]) { printf ("WriteMiptex: no wads specified in \"wad\" key in worldspawn\n"); texdatasize = 0; return; } } nummiptexfiles = 0; currentpath = path; while (*currentpath) { getwadname(wadname, ¤tpath); if (wadname[0]) { success = false; // try prepending each -wadpath on the commandline to the wad name for (i = 1;i < myargc;i++) { if (!Q_strcasecmp("-wadpath", myargv[i])) { i++; if (i < myargc) { sprintf(wadfilename, "%s%s", myargv[i], wadname); if ((success = loadwad(wadfilename) >= 0)) break; } } } if (!success) { // if the map name has a path, we can try loading the wad from there ExtractFilePath(bspfilename, wadfilename); if (wadfilename[0]) { strcat(wadfilename, wadname); if (!(success = loadwad(wadfilename) >= 0)) { // try the parent directory ExtractFilePath(bspfilename, wadfilename); strcat(wadfilename, "../"); strcat(wadfilename, wadname); success = loadwad(wadfilename) >= 0; } } } if (!success) { // try the wadname itself success = loadwad(wadname) >= 0; } if (!success) printf("Could not find wad \"%s\" using -wadpath options or in the same directory as the map or it's parent directory, so there!\n", wadname); } } for (i = 0;i < nummiptex;i++) CleanupName(miptex[i], miptex[i]); AddAnimatingTextures(); miptex_lumps = (dmiptexlump_t *)dtexdata; miptex_data = (byte *)&miptex_lumps->dataofs[nummiptex]; miptex_lumps->nummiptex = nummiptex; for (i=0 ; i < nummiptex ; i++) { printf("miptex used: %s", miptex[i]); m = FindMipTexFile(miptex[i]); if (m) { if (miptex_data + m->size - dtexdata >= MAX_MAP_MIPTEX) { miptex_lumps->dataofs[i] = -1; printf(" (MAX_MAP_MIPTEX exceeded)\n"); } else if (ReadMipTexFile(m, miptex_data)) { miptex_lumps->dataofs[i] = -1; printf(" (READ ERROR)\n"); } else { miptex_lumps->dataofs[i] = miptex_data - (byte *)miptex_lumps; printf("\n"); miptex_data += m->size; } } else { miptex_lumps->dataofs[i] = -1; printf(" (NOT FOUND)\n"); } } texdatasize = miptex_data - dtexdata; }
//=========================================================================== // Marks all nodes that can be reached by entites // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== qboolean FloodEntities(tree_t *tree) { int i; int x, y; vec3_t origin; char *cl; qboolean inside; node_t *headnode; headnode = tree->headnode; Log_Print("------ FloodEntities -------\n"); inside = false; tree->outside_node.occupied = 0; //start at entity 1 not the world ( = 0) for(i = 1; i < num_entities; i++) { GetVectorForKey(&entities[i], "origin", origin); if(VectorCompare(origin, vec3_origin)) { continue; } cl = ValueForKey(&entities[i], "classname"); origin[2] += 1; //so objects on floor are ok // Log_Print("flooding from entity %d: %s\n", i, cl); //nudge playerstart around if needed so clipping hulls allways //have a valid point if(!strcmp(cl, "info_player_start")) { for(x = -16; x <= 16; x += 16) { for(y = -16; y <= 16; y += 16) { origin[0] += x; origin[1] += y; if(PlaceOccupant(headnode, origin, &entities[i])) { inside = true; x = 999; //stop for this info_player_start break; } //end if origin[0] -= x; origin[1] -= y; } //end for } //end for } //end if else { if(PlaceOccupant(headnode, origin, &entities[i])) { inside = true; } //end if } //end else } //end for if(!inside) { Log_Print("WARNING: no entities inside\n"); } //end if else if(tree->outside_node.occupied) { Log_Print("WARNING: entity reached from outside\n"); } //end else if return (qboolean)(inside && !tree->outside_node.occupied); } //end of the function FloodEntities
/* ================ ParseMapEntity ================ */ qboolean ParseMapEntity (void) { entity_t *mapent; epair_t *e; side_t *s; int i, j; int startbrush, startsides; vec_t newdist; mapbrush_t *b; if (!GetToken (true)) return false; if (strcmp (token, "{") ) Error ("ParseEntity: { not found"); if (num_entities == MAX_MAP_ENTITIES) Error ("num_entities == MAX_MAP_ENTITIES"); startbrush = nummapbrushes; startsides = nummapbrushsides; mapent = &entities[num_entities]; num_entities++; memset (mapent, 0, sizeof(*mapent)); mapent->firstbrush = nummapbrushes; mapent->numbrushes = 0; // mapent->portalareas[0] = -1; // mapent->portalareas[1] = -1; do { if (!GetToken (true)) Error ("ParseEntity: EOF without closing brace"); if (!strcmp (token, "}") ) break; if (!strcmp (token, "{") ) ParseBrush (mapent); else { e = ParseEpair (); e->next = mapent->epairs; mapent->epairs = e; } } while (1); GetVectorForKey (mapent, "origin", mapent->origin); // // if there was an origin brush, offset all of the planes and texinfo // if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) { for (i=0 ; i<mapent->numbrushes ; i++) { b = &mapbrushes[mapent->firstbrush + i]; for (j=0 ; j<b->numsides ; j++) { s = &b->original_sides[j]; newdist = mapplanes[s->planenum].dist - DotProduct (mapplanes[s->planenum].normal, mapent->origin); s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist); s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum], &side_brushtextures[s-brushsides], mapent->origin); } MakeBrushWindings (b); } } // group entities are just for editor convenience // toss all brushes into the world entity if (!strcmp ("func_group", ValueForKey (mapent, "classname"))) { MoveBrushesToWorld (mapent); mapent->numbrushes = 0; return true; } // areaportal entities move their brushes, but don't eliminate // the entity if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname"))) { char str[128]; if (mapent->numbrushes != 1) Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1); b = &mapbrushes[nummapbrushes-1]; b->contents = CONTENTS_AREAPORTAL; c_areaportals++; mapent->areaportalnum = c_areaportals; // set the portal number as "style" sprintf (str, "%i", c_areaportals); SetKeyValue (mapent, "style", str); MoveBrushesToWorld (mapent); return true; } return true; }
void CreateMapFogs( void ){ int i; entity_t *entity; brush_t *brush; fog_t *fog; vec3_t invFogDir; const char *globalFog; /* skip? */ if ( nofog ) { return; } /* note it */ Sys_FPrintf( SYS_VRB, "--- CreateMapFogs ---\n" ); /* walk entities */ for ( i = 0; i < numEntities; i++ ) { /* get entity */ entity = &entities[ i ]; /* walk entity brushes */ for ( brush = entity->brushes; brush != NULL; brush = brush->next ) { /* ignore non-fog brushes */ if ( brush->contentShader->fogParms == qfalse ) { continue; } /* test limit */ if ( numMapFogs >= MAX_MAP_FOGS ) { Error( "Exceeded MAX_MAP_FOGS (%d)", MAX_MAP_FOGS ); } /* set up fog */ fog = &mapFogs[ numMapFogs++ ]; fog->si = brush->contentShader; fog->brush = brush; fog->visibleSide = -1; /* if shader specifies an explicit direction, then find a matching brush side with an opposed normal */ if ( VectorLength( fog->si->fogDir ) ) { /* flip it */ VectorScale( fog->si->fogDir, -1.0f, invFogDir ); /* find the brush side */ for ( i = 0; i < brush->numsides; i++ ) { if ( VectorCompare( invFogDir, mapplanes[ brush->sides[ i ].planenum ].normal ) ) { fog->visibleSide = i; //% Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide ); break; } } } } } /* ydnar: global fog */ globalFog = ValueForKey( &entities[ 0 ], "_fog" ); if ( globalFog[ 0 ] == '\0' ) { globalFog = ValueForKey( &entities[ 0 ], "fog" ); } if ( globalFog[ 0 ] != '\0' ) { /* test limit */ if ( numMapFogs >= MAX_MAP_FOGS ) { Error( "Exceeded MAX_MAP_FOGS (%d) trying to add global fog", MAX_MAP_FOGS ); } /* note it */ Sys_FPrintf( SYS_VRB, "Map has global fog shader %s\n", globalFog ); /* set up fog */ fog = &mapFogs[ numMapFogs++ ]; fog->si = ShaderInfoForShaderNull( globalFog ); if ( fog->si == NULL ) { Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog ); } fog->brush = NULL; fog->visibleSide = -1; /* set as default fog */ defaultFogNum = numMapFogs - 1; /* mark all worldspawn brushes as fogged */ for ( brush = entities[ 0 ].brushes; brush != NULL; brush = brush->next ) ApplySurfaceParm( "fog", &brush->contentFlags, NULL, &brush->compileFlags ); } /* emit some stats */ Sys_FPrintf( SYS_VRB, "%9d fogs\n", numMapFogs ); }
void CheckBspProcess( void ) { char outputpath[1024]; char temppath[512]; DWORD exitcode; char* out; BOOL ret; if ( !bsp_process ) return; ret = GetExitCodeProcess( bsp_process, &exitcode ); if ( !ret ) Error( "GetExitCodeProcess failed" ); if ( exitcode == STILL_ACTIVE ) return; bsp_process = 0; GetTempPath( 512, temppath ); sprintf( outputpath, "%sjunk.txt", temppath ); LoadFile( outputpath, ( void** )&out ); Sys_Printf( "%s", out ); Sys_Printf( "\ncompleted.\n" ); free( out ); CTime tEnd = CTime::GetCurrentTime(); CTimeSpan tElapsed = tEnd - g_tBegin; CString strElapsed; strElapsed.Format( "Run time was %i hours, %i minutes and %i seconds", tElapsed.GetHours(), tElapsed.GetMinutes(), tElapsed.GetSeconds() ); Sys_Printf( strElapsed.GetBuffer( 0 ) ); Sys_Beep(); Pointfile_Check(); // run game if no PointFile and pref is set //++timo needs to stop after BSP if leaked .. does run through vis and light instead .. if ( g_PrefsDlg.m_bRunQuake == TRUE && !g_qeglobals.d_pointfile_display_list ) { char cCurDir[1024]; GetCurrentDirectory( 1024, cCurDir ); CString strExePath = "../../qio.exe"; //= g_PrefsDlg.m_strQuake2; CString strOrgPath; CString strOrgFile; ExtractPath_and_Filename( currentmap, strOrgPath, strOrgFile ); if ( g_PrefsDlg.m_bSetGame == TRUE ) // run in place with set game.. don't copy map { CString strBasePath = ValueForKey( g_qeglobals.d_project_entity, "basepath" ); strExePath += " +set game "; strExePath += strBasePath; WinExec( strExePath, SW_SHOW ); } else { CString strCopyPath = strExePath; char* pBuffer = strCopyPath.GetBufferSetLength( _MAX_PATH + 1 ); pBuffer[strCopyPath.ReverseFind( '\\' ) + 1] = '\0'; strCopyPath.ReleaseBuffer(); SetCurrentDirectory( strCopyPath ); CString strOrgPath; CString strOrgFile; ExtractPath_and_Filename( currentmap, strOrgPath, strOrgFile ); AddSlash( strCopyPath ); FindReplace( strOrgFile, ".map", ".bsp" ); //++timo modified for Quake3 !! strCopyPath += "baseq3\\maps\\"; strCopyPath += strOrgFile; AddSlash( strOrgPath ); strOrgPath += strOrgFile; bool bRun = ( strOrgPath.CompareNoCase( strCopyPath ) == 0 ); if ( !bRun ) bRun = ( CopyFile( strOrgPath, strCopyPath, FALSE ) == TRUE ); if ( bRun ) { FindReplace( strOrgFile, ".bsp", "" ); strExePath += " +map "; strExePath += strOrgFile; WinExec( strExePath, SW_SHOW ); } } SetCurrentDirectory( cCurDir ); } }
void QE_ExpandBspString( char* bspaction, char* out, char* mapname, bool useTemps ) { char* in; char src[2048]; char rsh[2048]; char base[2048]; const char* basePath; const char* modDir; strcpy( src, mapname ); strlwr( src ); in = strstr( src, "maps/" ); if ( !in ) { in = strstr( src, "maps\\" ); } if ( in ) { in += 5; strcpy( base, in ); in = base; while ( *in ) { if ( *in == '\\' ) { *in = '/'; } in++; } } else { ExtractFileName( mapname, base ); } if ( useTemps ) { CString str; CString strExt = "map"; if ( strstr( mapname, ".reg" ) ) { strExt = "reg"; } str.Format( "%s/maps/%i.%s", ValueForKey( g_qeglobals.d_project_entity, "remotebasepath" ), ::GetTickCount(), strExt ); CopyFile( mapname, str, FALSE ); sprintf( src, "-tempname %s %s/maps/%s", str, ValueForKey( g_qeglobals.d_project_entity, "remotebasepath" ), base ); } else { sprintf( src, "%s/maps/%s", ValueForKey( g_qeglobals.d_project_entity, "remotebasepath" ), base ); } strcpy( rsh, ValueForKey( g_qeglobals.d_project_entity, "rshcmd" ) ); QE_ConvertDOSToUnixName( src, src ); in = ValueForKey( g_qeglobals.d_project_entity, bspaction ); basePath = ValueForKey( g_qeglobals.d_project_entity, "basepath" ); modDir = ValueForKey( g_qeglobals.d_project_entity, "moddir" ); if ( modDir[0] == '/' || modDir[0] == '\\' ) modDir++; while ( *in ) { if ( in[0] == '!' ) { strcpy( out, rsh ); out += strlen( rsh ); in++; continue; } if ( in[0] == '$' ) { strcpy( out, "-gamedir " ); out += strlen( "-gamedir " ); strcpy( out, basePath ); out += strlen( basePath ); //strcpy(out,modDir); //out += strlen(modDir); *out = ' '; out++; strcpy( out, src ); out += strlen( src ); in++; continue; } if ( in[0] == '@' ) { *out++ = '"'; in++; continue; } *out++ = *in++; } *out = 0; }
void ProcessWorldModel( void ) { int i, s; entity_t *e; tree_t *tree; face_t *faces; qboolean ignoreLeaks, leaked; xmlNodePtr polyline, leaknode; char level[ 2 ], shader[ 1024 ]; const char *value; /* sets integer blockSize from worldspawn "_blocksize" key if it exists */ value = ValueForKey( &entities[ 0 ], "_blocksize" ); if( value[ 0 ] == '\0' ) value = ValueForKey( &entities[ 0 ], "blocksize" ); if( value[ 0 ] == '\0' ) value = ValueForKey( &entities[ 0 ], "chopsize" ); /* sof2 */ if( value[ 0 ] != '\0' ) { /* scan 3 numbers */ s = sscanf( value, "%d %d %d", &blockSize[ 0 ], &blockSize[ 1 ], &blockSize[ 2 ] ); /* handle legacy case */ if( s == 1 ) { blockSize[ 1 ] = blockSize[ 0 ]; blockSize[ 2 ] = blockSize[ 0 ]; } } Sys_Printf( "block size = { %d %d %d }\n", blockSize[ 0 ], blockSize[ 1 ], blockSize[ 2 ] ); /* sof2: ignore leaks? */ value = ValueForKey( &entities[ 0 ], "_ignoreleaks" ); /* ydnar */ if( value[ 0 ] == '\0' ) value = ValueForKey( &entities[ 0 ], "ignoreleaks" ); if( value[ 0 ] == '1' ) ignoreLeaks = qtrue; else ignoreLeaks = qfalse; /* begin worldspawn model */ BeginModel(); e = &entities[ 0 ]; e->firstDrawSurf = 0; /* ydnar: gs mods */ ClearMetaTriangles(); /* check for patches with adjacent edges that need to lod together */ PatchMapDrawSurfs( e ); /* build an initial bsp tree using all of the sides of all of the structural brushes */ faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes ); tree = FaceBSP( faces ); MakeTreePortals( tree ); FilterStructuralBrushesIntoTree( e, tree ); /* see if the bsp is completely enclosed */ if( FloodEntities( tree ) || ignoreLeaks ) { /* rebuild a better bsp tree using only the sides that are visible from the inside */ FillOutside( tree->headnode ); /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */ ClipSidesIntoTree( e, tree ); /* build a visible face tree */ faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes ); FreeTree( tree ); tree = FaceBSP( faces ); MakeTreePortals( tree ); FilterStructuralBrushesIntoTree( e, tree ); leaked = qfalse; /* ydnar: flood again for skybox */ if( skyboxPresent ) FloodEntities( tree ); } else { Sys_FPrintf( SYS_NOXML, "**********************\n" ); Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" ); Sys_FPrintf( SYS_NOXML, "**********************\n" ); polyline = LeakFile( tree ); leaknode = xmlNewNode( NULL, "message" ); xmlNodeSetContent( leaknode, "MAP LEAKED\n" ); xmlAddChild( leaknode, polyline ); level[0] = (int) '0' + SYS_ERR; level[1] = 0; xmlSetProp( leaknode, "level", (char*) &level ); xml_SendNode( leaknode ); if( leaktest ) { Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n"); exit( 0 ); } leaked = qtrue; /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */ ClipSidesIntoTree( e, tree ); } /* save out information for visibility processing */ NumberClusters( tree ); if( !leaked ) WritePortalFile( tree ); /* flood from entities */ FloodAreas( tree ); /* create drawsurfs for triangle models */ AddTriangleModels( e ); /* create drawsurfs for surface models */ AddEntitySurfaceModels( e ); /* generate bsp brushes from map brushes */ EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes ); /* add references to the detail brushes */ FilterDetailBrushesIntoTree( e, tree ); /* drawsurfs that cross fog boundaries will need to be split along the fog boundary */ if( !nofog ) FogDrawSurfaces( e ); /* subdivide each drawsurf as required by shader tesselation */ if( !nosubdivide ) SubdivideFaceSurfaces( e, tree ); /* add in any vertexes required to fix t-junctions */ if( !notjunc ) FixTJunctions( e ); /* ydnar: classify the surfaces */ ClassifyEntitySurfaces( e ); /* ydnar: project decals */ MakeEntityDecals( e ); /* ydnar: meta surfaces */ MakeEntityMetaTriangles( e ); SmoothMetaTriangles(); FixMetaTJunctions(); MergeMetaTriangles(); /* ydnar: debug portals */ if( debugPortals ) MakeDebugPortalSurfs( tree ); /* ydnar: fog hull */ value = ValueForKey( &entities[ 0 ], "_foghull" ); if( value[ 0 ] != '\0' ) { sprintf( shader, "textures/%s", value ); MakeFogHullSurfs( e, tree, shader ); } /* ydnar: bug 645: do flares for lights */ for( i = 0; i < numEntities && emitFlares; i++ ) { entity_t *light, *target; const char *value, *flareShader; vec3_t origin, targetOrigin, normal, color; int lightStyle; /* get light */ light = &entities[ i ]; value = ValueForKey( light, "classname" ); if( !strcmp( value, "light" ) ) { /* get flare shader */ flareShader = ValueForKey( light, "_flareshader" ); value = ValueForKey( light, "_flare" ); if( flareShader[ 0 ] != '\0' || value[ 0 ] != '\0' ) { /* get specifics */ GetVectorForKey( light, "origin", origin ); GetVectorForKey( light, "_color", color ); lightStyle = IntForKey( light, "_style" ); if( lightStyle == 0 ) lightStyle = IntForKey( light, "style" ); /* handle directional spotlights */ value = ValueForKey( light, "target" ); if( value[ 0 ] != '\0' ) { /* get target light */ target = FindTargetEntity( value ); if( target != NULL ) { GetVectorForKey( target, "origin", targetOrigin ); VectorSubtract( targetOrigin, origin, normal ); VectorNormalize( normal, normal ); } } else //% VectorClear( normal ); VectorSet( normal, 0, 0, -1 ); /* create the flare surface (note shader defaults automatically) */ DrawSurfaceForFlare( mapEntityNum, origin, normal, color, (char*) flareShader, lightStyle ); } } } /* add references to the final drawsurfs in the apropriate clusters */ FilterDrawsurfsIntoTree( e, tree ); /* match drawsurfaces back to original brushsides (sof2) */ FixBrushSides( e ); /* finish */ EndModel( e, tree->headnode ); FreeTree( tree ); }
static void SetCloneModelNumbers( void ) { int i, j; int models; char modelValue[ 10 ]; const char *value, *value2, *value3; /* start with 1 (worldspawn is model 0) */ models = 1; for( i = 1; i < numEntities; i++ ) { /* only entities with brushes or patches get a model number */ if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL ) continue; /* is this a clone? */ value = ValueForKey( &entities[ i ], "_clone" ); if( value[ 0 ] != '\0' ) continue; /* add the model key */ sprintf( modelValue, "*%d", models ); SetKeyValue( &entities[ i ], "model", modelValue ); /* increment model count */ models++; } /* fix up clones */ for( i = 1; i < numEntities; i++ ) { /* only entities with brushes or patches get a model number */ if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL ) continue; /* is this a clone? */ value = ValueForKey( &entities[ i ], "_ins" ); if( value[ 0 ] == '\0' ) value = ValueForKey( &entities[ i ], "_instance" ); if( value[ 0 ] == '\0' ) value = ValueForKey( &entities[ i ], "_clone" ); if( value[ 0 ] == '\0' ) continue; /* find an entity with matching clone name */ for( j = 0; j < numEntities; j++ ) { /* is this a clone parent? */ value2 = ValueForKey( &entities[ j ], "_clonename" ); if( value2[ 0 ] == '\0' ) continue; /* do they match? */ if( strcmp( value, value2 ) == 0 ) { /* get the model num */ value3 = ValueForKey( &entities[ j ], "model" ); if( value3[ 0 ] == '\0' ) { Sys_Printf( "WARNING: Cloned entity %s referenced entity without model\n", value2 ); continue; } models = atoi( &value2[ 1 ] ); /* add the model key */ sprintf( modelValue, "*%d", models ); SetKeyValue( &entities[ i ], "model", modelValue ); /* nuke the brushes/patches for this entity (fixme: leak!) */ entities[ i ].brushes = NULL; entities[ i ].patches = NULL; } } } }
static void PopulateTraceNodes(void) { int i, m, frame, castShadows; float temp; entity_t *e; const char *value; picoModel_t *model; vec3_t origin, scale, angles; matrix_t rotation; matrix_t transform; /* add worldspawn triangles */ MatrixIdentity(transform); PopulateWithBSPModel(&bspModels[0], transform); /* walk each entity list */ for(i = 1; i < numEntities; i++) { /* get entity */ e = &entities[i]; /* get shadow flags */ castShadows = ENTITY_CAST_SHADOWS; GetEntityShadowFlags(e, NULL, &castShadows, NULL); /* early out? */ if(!castShadows) continue; /* get entity origin */ GetVectorForKey(e, "origin", origin); /* get "angle" (yaw) or "angles" (pitch yaw roll) */ MatrixIdentity(rotation); angles[0] = angles[1] = angles[2] = 0.0f; value = ValueForKey(e, "angle"); if(value[0] != '\0') { angles[1] = atof(value); MatrixFromAngles(rotation, angles[PITCH], angles[YAW], angles[ROLL]); } value = ValueForKey(e, "angles"); if(value[0] != '\0') { sscanf(value, "%f %f %f", &angles[0], &angles[1], &angles[2]); MatrixFromAngles(rotation, angles[PITCH], angles[YAW], angles[ROLL]); } value = ValueForKey(e, "rotation"); if(value[0] != '\0') { sscanf(value, "%f %f %f %f %f %f %f %f %f", &rotation[0], &rotation[1], &rotation[2], &rotation[4], &rotation[5], &rotation[6], &rotation[8], &rotation[9], &rotation[10]); } /* get scale */ scale[0] = scale[1] = scale[2] = 1.0f; temp = FloatForKey(e, "modelscale"); if(temp != 0.0f) scale[0] = scale[1] = scale[2] = temp; value = ValueForKey(e, "modelscale_vec"); if(value[0] != '\0') sscanf(value, "%f %f %f", &scale[0], &scale[1], &scale[2]); MatrixMultiplyScale(rotation, scale[0], scale[1], scale[2]); /* set transform matrix */ MatrixIdentity(transform); MatrixSetupTransformFromRotation(transform, rotation, origin); //% m4x4_pivoted_transform_by_vec3(transform, origin, angles, eXYZ, scale, vec3_origin); /* get model */ value = ValueForKey(e, "model"); /* switch on model type */ switch (value[0]) { /* no model */ case '\0': break; /* bsp model */ case '*': m = atoi(&value[1]); if(m <= 0 || m >= numBSPModels) continue; PopulateWithBSPModel(&bspModels[m], transform); break; /* external model */ default: frame = IntForKey(e, "_frame"); model = LoadModel((char *)value, frame); if(model == NULL) continue; PopulateWithPicoModel(castShadows, model, transform); continue; } /* get model2 */ value = ValueForKey(e, "model2"); /* switch on model type */ switch (value[0]) { /* no model */ case '\0': break; /* bsp model */ case '*': m = atoi(&value[1]); if(m <= 0 || m >= numBSPModels) continue; PopulateWithBSPModel(&bspModels[m], transform); break; /* external model */ default: frame = IntForKey(e, "_frame2"); model = LoadModel((char *)value, frame); if(model == NULL) continue; PopulateWithPicoModel(castShadows, model, transform); continue; } } }
// FIXME: turn this into an MFC dialog BOOL CALLBACK ProjectDlgProc ( HWND hwndDlg, // handle to dialog box UINT uMsg, // message WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { char key[1024]; char value[1024]; int index; switch (uMsg) { case WM_INITDIALOG: SetDlgItemText(hwndDlg, IDC_PRJBASEPATH, ValueForKey (g_qeglobals.d_project_entity, "basepath")); SetDlgItemText(hwndDlg, IDC_PRJMAPSPATH, ValueForKey (g_qeglobals.d_project_entity, "mapspath")); SetDlgItemText(hwndDlg, IDC_PRJRSHCMD, ValueForKey (g_qeglobals.d_project_entity, "rshcmd")); SetDlgItemText(hwndDlg, IDC_PRJREMOTEBASE, ValueForKey (g_qeglobals.d_project_entity, "remotebasepath")); SetDlgItemText(hwndDlg, IDC_PRJENTITYPATH, ValueForKey (g_qeglobals.d_project_entity, "entitypath")); SetDlgItemText(hwndDlg, IDC_PRJTEXPATH, ValueForKey (g_qeglobals.d_project_entity, "texturepath")); UpdateBSPCommandList (hwndDlg); // Timo // additional fields CheckDlgButton( hwndDlg, IDC_CHECK_BPRIMIT, (g_qeglobals.m_bBrushPrimitMode) ? BST_CHECKED : BST_UNCHECKED ); // SendMessage( ::GetDlgItem( hwndDlg, IDC_CHECK_BPRIMIT ), BM_SETCHECK, (WPARAM) g_qeglobals.m_bBrushPrimitMode, 0 ); return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_ADDCMD: // DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ADDCMD, g_qeglobals.d_hwndMain, AddCommandDlgProc); DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ADDCMD, hwndDlg, AddCommandDlgProc); UpdateBSPCommandList (hwndDlg); break; case IDC_EDITCMD: // DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ADDCMD, g_qeglobals.d_hwndMain, EditCommandDlgProc); DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ADDCMD, hwndDlg, EditCommandDlgProc); UpdateBSPCommandList (hwndDlg); break; case IDC_REMCMD: index = SendDlgItemMessage (hwndDlg, IDC_CMD_LIST, LB_GETCURSEL, 0, 0); SendDlgItemMessage(hwndDlg, IDC_CMD_LIST, LB_GETTEXT, index, (LPARAM) (LPCTSTR) key); DeleteKey (g_qeglobals.d_project_entity, key); common->Printf ("Selected %d\n", index); UpdateBSPCommandList (hwndDlg); break; case IDOK: GetDlgItemText(hwndDlg, IDC_PRJBASEPATH, value, 1024); SetKeyValue (g_qeglobals.d_project_entity, "basepath", value); GetDlgItemText(hwndDlg, IDC_PRJMAPSPATH, value, 1024); SetKeyValue (g_qeglobals.d_project_entity, "mapspath", value); GetDlgItemText(hwndDlg, IDC_PRJRSHCMD, value, 1024); SetKeyValue (g_qeglobals.d_project_entity, "rshcmd", value); GetDlgItemText(hwndDlg, IDC_PRJREMOTEBASE, value, 1024); SetKeyValue (g_qeglobals.d_project_entity, "remotebasepath", value); GetDlgItemText(hwndDlg, IDC_PRJENTITYPATH, value, 1024); SetKeyValue (g_qeglobals.d_project_entity, "entitypath", value); GetDlgItemText(hwndDlg, IDC_PRJTEXPATH, value, 1024); SetKeyValue (g_qeglobals.d_project_entity, "texturepath", value); // Timo // read additional fields if ( IsDlgButtonChecked( hwndDlg, IDC_CHECK_BPRIMIT ) ) { g_qeglobals.m_bBrushPrimitMode = TRUE; } else { g_qeglobals.m_bBrushPrimitMode = FALSE; } SetKeyValue ( g_qeglobals.d_project_entity, "brush_primit", ( g_qeglobals.m_bBrushPrimitMode ? "1" : "0" ) ); EndDialog(hwndDlg, 1); QE_SaveProject(g_strProject); return TRUE; case IDCANCEL: EndDialog(hwndDlg, 0); return TRUE; } } return FALSE; }
void Eclass_Init(){ GSList *pFiles; // start by creating the default unknown eclass eclass_bad = EClass_Create( "UNKNOWN_CLASS", 0, 0.5, 0,NULL,NULL,NULL ); // now scan the definitions _EClassTable *pTable = &g_EClassDefTable; while ( pTable ) { // read in all scripts/*.<extension> pFiles = vfsGetFileList( "scripts", pTable->m_pfnGetExtension() ); if ( pFiles ) { GSList *pFile = pFiles; while ( pFile ) { /*! \todo the MP/SP filtering rules need to be CLEANED UP and SANITIZED */ // HACK // JKII SP/MP mapping mode if ( g_pGameDescription->mGameFile == "jk2.game" || g_pGameDescription->mGameFile == "ja.game" ) { if ( !strcmp( ValueForKey( g_qeglobals.d_project_entity, "gamemode" ), "sp" ) ) { // SP mapping, ignore mp_*.def char *name = (char *)pFile->data; if ( name[0] == 'm' && name[1] == 'p' && name[2] == '_' ) { Sys_Printf( "Single Player mapping mode. Ignoring '%s'\n", name ); pFile = pFile->next; continue; } } else { // MP mapping, ignore sp_*.def char *name = (char *)pFile->data; if ( name[0] == 's' && name[1] == 'p' && name[2] == '_' ) { Sys_Printf( "Multiplayer mapping mode. Ignoring '%s'\n", name ); pFile = pFile->next; continue; } } } // RIANT // STVEF SP/MP mapping mode else if ( g_pGameDescription->mGameFile == "stvef.game" ) { if ( !strcmp( ValueForKey( g_qeglobals.d_project_entity, "gamemode" ), "sp" ) ) { // SP mapping, ignore mp_*.def char *name = (char *)pFile->data; if ( name[0] == 'm' && name[1] == 'p' && name[2] == '_' || name[0] == 'h' && name[1] == 'm' && name[2] == '_' ) { Sys_Printf( "Single Player mapping mode. Ignoring '%s'\n", name ); pFile = pFile->next; continue; } } else { // HM mapping, ignore sp_*.def char *name = (char *)pFile->data; if ( name[0] == 's' && name[1] == 'p' && name[2] == '_' ) { Sys_Printf( "HoloMatch mapping mode. Ignoring '%s'\n", name ); pFile = pFile->next; continue; } } } // for a given name, we grab the first .def in the vfs // this allows to override baseq3/scripts/entities.def for instance char relPath[PATH_MAX]; strcpy( relPath, "scripts/" ); strcat( relPath, (char*)pFile->data ); char *fullpath = vfsGetFullPath( relPath, 0, 0 ); if ( !fullpath ) { Sys_FPrintf( SYS_ERR, "Failed to find the full path for \"%s\" in the VFS\n", relPath ); } else{ pTable->m_pfnScanFile( fullpath ); } if ( g_pGameDescription->mEClassSingleLoad ) { break; } pFile = pFile->next; } vfsClearFileDirList( &pFiles ); pFiles = NULL; } else{ Sys_FPrintf( SYS_ERR, "Didn't find any scripts/*.%s files to load EClass information\n", pTable->m_pfnGetExtension() ); } // we deal with two formats max, if the other table exists, loop again if ( g_bHaveEClassExt && pTable == &g_EClassDefTable ) { pTable = &g_EClassExtTable; } else{ pTable = NULL; // done, exit } } Eclass_CreateSpriteModelPaths(); }
void SetLightStyles( void ) { int i, j, style, numStyles; qboolean keepLights; const char *t; entity_t *e; epair_t *ep, *next; char value[ 10 ]; char lightTargets[ MAX_SWITCHED_LIGHTS ][ 64 ]; int lightStyles[ MAX_SWITCHED_LIGHTS ]; /* ydnar: determine if we keep lights in the bsp */ t = ValueForKey( &entities[ 0 ], "_keepLights" ); keepLights = (t[ 0 ] == '1') ? qtrue : qfalse; /* any light that is controlled (has a targetname) must have a unique style number generated for it */ numStyles = 0; for( i = 1; i < numEntities; i++ ) { e = &entities[ i ]; t = ValueForKey( e, "classname" ); if( Q_strncasecmp( t, "light", 5 ) ) continue; t = ValueForKey( e, "targetname" ); if( t[ 0 ] == '\0' ) { /* ydnar: strip the light from the BSP file */ if( keepLights == qfalse ) { ep = e->epairs; while( ep != NULL ) { next = ep->next; free( ep->key ); free( ep->value ); free( ep ); ep = next; } e->epairs = NULL; numStrippedLights++; } /* next light */ continue; } /* get existing style */ style = IntForKey( e, "style" ); if( style < LS_NORMAL || style > LS_NONE ) Error( "Invalid lightstyle (%d) on entity %d", style, i ); /* find this targetname */ for( j = 0; j < numStyles; j++ ) if( lightStyles[ j ] == style && !strcmp( lightTargets[ j ], t ) ) break; /* add a new style */ if( j >= numStyles ) { if( numStyles == MAX_SWITCHED_LIGHTS ) Error( "MAX_SWITCHED_LIGHTS (%d) exceeded, reduce the number of lights with targetnames", MAX_SWITCHED_LIGHTS ); strcpy( lightTargets[ j ], t ); lightStyles[ j ] = style; numStyles++; } /* set explicit style */ sprintf( value, "%d", 32 + j ); SetKeyValue( e, "style", value ); /* set old style */ if( style != LS_NORMAL ) { sprintf( value, "%d", style ); SetKeyValue( e, "switch_style", value ); } } /* emit some statistics */ Sys_FPrintf( SYS_VRB, "%9d light entities stripped\n", numStrippedLights ); }
/* ================= ParseMapEntity parses a single entity out of a map file ================= */ static bool ParseMapEntity( bool onlyLights ) { epair_t *ep; token_t token; const char *classname, *value; float lightmapScale; char shader[ MAX_SHADERPATH ]; shaderInfo_t *celShader = NULL; brush_t *brush; parseMesh_t *patch; bool funcGroup; int castShadows, recvShadows; static bool map_type = false; if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES|SC_COMMENT_SEMICOLON, &token )) return false; // end of .map file if( com.stricmp( token.string, "{" )) Sys_Break( "ParseEntity: found %s instead {\n", token.string ); if( numEntities >= MAX_MAP_ENTITIES ) Sys_Break( "MAX_MAP_ENTITIES limit exceeded\n" ); entitySourceBrushes = 0; mapEnt = &entities[numEntities]; numEntities++; memset( mapEnt, 0, sizeof( *mapEnt )); mapEnt->mapEntityNum = numMapEntities; numMapEntities++; while( 1 ) { if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES|SC_COMMENT_SEMICOLON, &token )) Sys_Break( "ParseEntity: EOF without closing brace\n" ); if( !com.stricmp( token.string, "}" )) break; if( !com.stricmp( token.string, "{" )) { // parse a brush or patch if( !Com_ReadToken( mapfile, SC_ALLOW_NEWLINES, &token )) break; if( !com.stricmp( token.string, "patchDef2" )) { numMapPatches++; ParsePatch( onlyLights ); g_bBrushPrimit = BRUSH_RADIANT; } else if( !com.stricmp( token.string, "terrainDef" )) { MsgDev( D_WARN, "Terrain entity parsing not supported in this build.\n" ); Com_SkipBracedSection( mapfile, 0 ); g_bBrushPrimit = BRUSH_RADIANT; } else if( !com.stricmp( token.string, "brushDef" )) { // parse brush primitive g_bBrushPrimit = BRUSH_RADIANT; ParseBrush( onlyLights ); } else { if( g_bBrushPrimit == BRUSH_RADIANT ) Sys_Break( "mixed brush primitive with another format\n" ); if( g_bBrushPrimit == BRUSH_UNKNOWN ) g_bBrushPrimit = BRUSH_WORLDCRAFT_21; // QuArK or WorldCraft map (unknown at this point) Com_SaveToken( mapfile, &token ); ParseBrush( onlyLights ); } entitySourceBrushes++; } else { // parse a key / value pair ep = ParseEpair( mapfile, &token ); if( !com.strcmp( ep->key, "mapversion" )) { if( com.atoi( ep->value ) == VALVE_FORMAT ) { Msg( "Valve Format Map detected\n" ); g_bBrushPrimit = BRUSH_WORLDCRAFT_22; } else if( com.atoi( ep->value ) == GEARBOX_FORMAT ) { Msg( "Gearcraft Format Map detected\n" ); g_bBrushPrimit = BRUSH_GEARCRAFT_40; } else g_bBrushPrimit = BRUSH_WORLDCRAFT_21; } if( ep->key[0] != '\0' && ep->value[0] != '\0' ) { ep->next = mapEnt->epairs; mapEnt->epairs = ep; } } } if( !map_type && g_bBrushPrimit != BRUSH_UNKNOWN ) { MAPTYPE(); map_type = true; } classname = ValueForKey( mapEnt, "classname" ); if( onlyLights && com.strnicmp( classname, "light", 5 )) { numEntities--; return true; } if( !com.stricmp( "func_group", classname )) funcGroup = true; else funcGroup = false; // worldspawn (and func_groups) default to cast/recv shadows in worldspawn group if( funcGroup || mapEnt->mapEntityNum == 0 ) { castShadows = WORLDSPAWN_CAST_SHADOWS; recvShadows = WORLDSPAWN_RECV_SHADOWS; } else // other entities don't cast any shadows, but recv worldspawn shadows { castShadows = ENTITY_CAST_SHADOWS; recvShadows = ENTITY_RECV_SHADOWS; } // get explicit shadow flags GetEntityShadowFlags( mapEnt, NULL, &castShadows, &recvShadows ); // get lightmap scaling value for this entity if( com.strcmp( "", ValueForKey( mapEnt, "lightmapscale" )) || com.strcmp( "", ValueForKey( mapEnt, "_lightmapscale" ))) { // get lightmap scale from entity lightmapScale = FloatForKey( mapEnt, "lightmapscale" ); if( lightmapScale <= 0.0f ) lightmapScale = FloatForKey( mapEnt, "_lightmapscale" ); if( lightmapScale > 0.0f ) Msg( "Entity %d (%s) has lightmap scale of %.4f\n", mapEnt->mapEntityNum, classname, lightmapScale ); } else lightmapScale = 0.0f; // get cel shader :) for this entity value = ValueForKey( mapEnt, "_celshader" ); if( value[0] == '\0' ) value = ValueForKey( &entities[0], "_celshader" ); if( value[0] != '\0' ) { com.snprintf( shader, sizeof( shader ), "textures/%s", value ); celShader = ShaderInfoForShader( shader ); Msg( "Entity %d (%s) has cel shader %s\n", mapEnt->mapEntityNum, classname, celShader->shader ); } else celShader = NULL; // attach stuff to everything in the entity for( brush = mapEnt->brushes; brush != NULL; brush = brush->next ) { brush->entityNum = mapEnt->mapEntityNum; brush->castShadows = castShadows; brush->recvShadows = recvShadows; brush->lightmapScale = lightmapScale; brush->celShader = celShader; } for( patch = mapEnt->patches; patch != NULL; patch = patch->next ) { patch->entityNum = mapEnt->mapEntityNum; patch->castShadows = castShadows; patch->recvShadows = recvShadows; patch->lightmapScale = lightmapScale; patch->celShader = celShader; } SetEntityBounds( mapEnt ); // load shader index map (equivalent to old terrain alphamap) LoadEntityIndexMap( mapEnt ); // get entity origin and adjust brushes GetVectorForKey( mapEnt, "origin", mapEnt->origin ); if( mapEnt->origin[0] || mapEnt->origin[1] || mapEnt->origin[2] ) AdjustBrushesForOrigin( mapEnt ); // group_info entities are just for editor grouping if( !com.stricmp( "group_info", classname )) { numEntities--; return true; } // group entities are just for editor convenience, toss all brushes into worldspawn if( funcGroup ) { MoveBrushesToWorld( mapEnt ); numEntities--; return true; } return true; }
int WriteASEFile(char *filename) { int i, j, s, modelNum; FILE *f; dshader_t *shader; dmodel_t *dm; drawSurface_t *ds; entity_t *e; vec3_t origin; const char *key; char name[1024], base[1024]; Sys_Printf("writing %s\n", filename); f = fopen(filename, "wb"); if(!f) Error("Can't write %s\b", filename); // print header fprintf(f, "*3DSMAX_ASCIIEXPORT\t200\r\n"); fprintf(f, "*COMMENT\t\"Generated by XMap (XreaL) -bsp2ase\"\r\n"); fprintf(f, "*SCENE\t{\r\n"); fprintf(f, "\t*SCENE_FILENAME\t\"%s\"\r\n", base); fprintf(f, "\t*SCENE_FIRSTFRAME\t0\r\n"); fprintf(f, "\t*SCENE_LASTFRAME\t100\r\n"); fprintf(f, "\t*SCENE_FRAMESPEED\t30\r\n"); fprintf(f, "\t*SCENE_TICKSPERFRAME\t160\r\n"); fprintf(f, "\t*SCENE_BACKGROUND_STATIC\t0.0000\t0.0000\t0.0000\r\n"); fprintf(f, "\t*SCENE_AMBIENT_STATIC\t0.0000\t0.0000\t0.0000\r\n"); fprintf(f, "}\r\n"); // print materials fprintf(f, "*MATERIAL_LIST\t{\r\n"); fprintf(f, "\t*MATERIAL_COUNT\t%d\r\n", numShaders); for(i = 0; i < numShaders; i++) { shader = &dshaders[i]; ConvertShader(f, shader, i); } fprintf(f, "}\r\n"); // walk entity list for(i = 0; i < numEntities; i++) { // get entity and model e = &entities[i]; if(i == 0) { modelNum = 0; } else { key = ValueForKey(e, "model"); if(key[0] != '*') { continue; } modelNum = atoi(key + 1); } dm = &dmodels[modelNum]; // get entity origin key = ValueForKey(e, "origin"); if(key[0] == '\0') VectorClear(origin); else GetVectorForKey(e, "origin", origin); // convert model for(j = 0; j < dm->numSurfaces; j++) { s = j + dm->firstSurface; ds = &drawSurfaces[s]; ConvertSurface(f, dm, modelNum, ds, s, origin); } } // close the file fclose(f); // return to sender return 0; }
/* ============= FloodEntities Marks all nodes that can be reached by entites ============= */ qboolean FloodEntities (tree_t *tree) { int i; Vector origin; char *cl; qboolean inside; node_t *headnode; headnode = tree->headnode; qprintf ("--- FloodEntities ---\n"); inside = false; tree->outside_node.occupied = 0; for (i=1 ; i<num_entities ; i++) { GetVectorForKey (&entities[i], "origin", origin); if (VectorCompare(origin, vec3_origin)) continue; cl = ValueForKey (&entities[i], "classname"); origin[2] += 1; // so objects on floor are ok // nudge playerstart around if needed so clipping hulls allways // have a valid point if (!strcmp (cl, "info_player_start")) { int x, y; for (x=-16 ; x<=16 ; x += 16) { for (y=-16 ; y<=16 ; y += 16) { origin[0] += x; origin[1] += y; if (PlaceOccupant (headnode, origin, &entities[i])) { inside = true; goto gotit; } origin[0] -= x; origin[1] -= y; } } gotit: ; } else { if (PlaceOccupant (headnode, origin, &entities[i])) inside = true; } } if (!inside) { qprintf ("no entities in open -- no filling\n"); } if (tree->outside_node.occupied) { qprintf ("entity reached from outside -- no filling\n" ); } return (qboolean)(inside && !tree->outside_node.occupied); }
/* ================= LoadEntityIndexMap based on LoadAlphaMap() from terrain.c, a little more generic ================= */ void LoadEntityIndexMap( entity_t *e ) { int i, size, numLayers; const char *value, *indexMapFilename, *shader; char offset[ 4096 ], *search, *space; rgbdata_t *image; byte *pixels; uint *pixels32; indexMap_t *im; brush_t *b; parseMesh_t *p; if( e->brushes == NULL && e->patches == NULL ) return; value = ValueForKey( e, "_indexmap" ); if( value[0] == '\0' ) value = ValueForKey( e, "alphamap" ); if( value[0] == '\0' ) return; indexMapFilename = value; // get number of layers (support legacy "layers" key as well) value = ValueForKey( e, "_layers" ); if( value[0] == '\0' ) value = ValueForKey( e, "layers" ); if( value[0] == '\0' ) { Msg( "Warning: Entity with index/alpha map \"%s\" has missing \"_layers\" or \"layers\" key\n", indexMapFilename ); Msg( "Entity will not be textured properly. Check your keys/values.\n" ); return; } numLayers = com.atoi( value ); if( numLayers < 1 ) { Msg( "Warning: Entity with index/alpha map \"%s\" has < 1 layer (%d)\n", indexMapFilename, numLayers ); Msg( "Entity will not be textured properly. Check your keys/values.\n" ); return; } // get base shader name (support legacy "shader" key as well) value = ValueForKey( mapEnt, "_shader" ); if( value[0] == '\0' ) value = ValueForKey( e, "shader" ); if( value[0] == '\0' ) { Msg( "Warning: Entity with index/alpha map \"%s\" has missing \"_shader\" or \"shader\" key\n", indexMapFilename ); Msg( "Entity will not be textured properly. Check your keys/values.\n" ); return; } shader = value; MsgDev( D_NOTE, "Entity %d (%s) has shader index map \"%s\"\n", mapEnt->mapEntityNum, ValueForKey( e, "classname" ), indexMapFilename ); image = FS_LoadImage( indexMapFilename, NULL, 0 ); if( !image ) return; Image_Process( &image, 0, 0, IMAGE_FORCE_RGBA ); size = image->width * image->height; pixels = Malloc( size ); pixels32 = (uint *)image->buffer; for( i = 0; i < size; i++ ) { pixels[i] = ((pixels32[i] & 0xFF) * numLayers) / 256; if( pixels[i] >= numLayers ) pixels[i] = numLayers - 1; } // the index map must be at least 2x2 pixels if( image->width < 2 || image->height < 2 ) { Msg( "Warning: Entity with index/alpha map \"%s\" is smaller than 2x2 pixels\n", indexMapFilename ); Msg( "Entity will not be textured properly. Check your keys/values.\n" ); FS_FreeImage( image ); return; } // create a new index map im = Malloc( sizeof( *im )); im->w = image->width; im->h = image->height; im->numLayers = numLayers; com.strncpy( im->name, indexMapFilename, sizeof( im->name )); com.strncpy( im->shader, shader, sizeof( im->shader )); im->pixels = pixels; value = ValueForKey( mapEnt, "_offsets" ); if( value[0] == '\0' ) value = ValueForKey( e, "offsets" ); if( value[0] != '\0' ) { // value is a space-seperated set of numbers com.strncpy( offset, value, sizeof( offset )); search = offset; for( i = 0; i < 256 && *search != '\0'; i++ ) { space = com.strstr( search, " " ); if( space != NULL ) *space = '\0'; im->offsets[i] = com.atof( search ); if( space == NULL ) break; search = space + 1; } } // store the index map in every brush/patch in the entity for( b = e->brushes; b != NULL; b = b->next ) b->im = im; for( p = e->patches; p != NULL; p = p->next ) p->im = im; FS_FreeImage( image ); }
qtexture_t* WINAPI QERApp_Try_Texture_ForName(const char* name) { qtexture_t *q; char f1[1024],f2[1024]; unsigned char *pPixels = NULL; int nWidth,nHeight; // convert the texture name to the standard format we use in qtexture_t char *stdName = CleanTextureName(name); // use the hash table q = NULL; g_qeglobals.d_qtexmap->Lookup( stdName, (void *&)q ); if (q) return q; #ifdef QTEXMAP_DEBUG for (q=g_qeglobals.d_qtextures ; q ; q=q->next) { if (!strcmp(stdName, q->name)) { Sys_Printf("ERROR: %s is not in texture map, but was found in texture list\n"); return q; } } #endif #if 0 for (q=g_qeglobals.d_qtextures ; q ; q=q->next) { if (!strcmp(stdName, q->name)) return q; } #endif //++timo TODO: say something about loading the file? // try loading the texture //++timo FIXME: "texturepath" is no use now? sprintf(f1, "%s/%s", ValueForKey (g_qeglobals.d_project_entity, "basepath"), name); QE_ConvertDOSToUnixName( f2, f1 ); // NOTE: we may need a global strategy to support default extensions etc. strcpy(f1,f2); // check wether a filename extension was provided // NOTE: only works for 3 letters extensions ( .tga .jpg ... ) if (f1[strlen(f1)-4] == '.') { // try straight loading LoadImage( f1, &pPixels, &nWidth, &nHeight ); } if (!pPixels) { // try adding extensions, .tga first sprintf(f2,"%s.tga",f1); LoadImage( f2, &pPixels, &nWidth, &nHeight ); if (!pPixels) { // .jpg sprintf(f2,"%s.jpg",f1); LoadImage( f2, &pPixels, &nWidth, &nHeight ); } } if (!pPixels) // we failed return NULL; else { // TODO: display .pk3 file name if loaded from .pk3 (needs to write a VFS .. sort of) Sys_Printf("LOADED: %s\n", f2 ); } // instanciate a new qtexture_t // NOTE: when called by a plugin we must make sure we have set Radiant's GL context before binding the texture // we'll be binding the GL texture now // need to check we are using a right GL context // with GL plugins that have their own window, the GL context may be the plugin's, in which case loading textures will bug HDC currentHDC = qwglGetCurrentDC(); HGLRC currentHGLRC = qwglGetCurrentContext(); //++timo FIXME: this may duplicate with qtexture_t* WINAPI QERApp_Texture_ForName (const char *name) //++timo FIXME: we need a list of lawfull GL contexts or something? // I'd rather always use the same GL context for binding... if (currentHDC != g_qeglobals.d_hdcBase || currentHGLRC != g_qeglobals.d_hglrcBase) { #ifdef _DEBUG Sys_Printf("Switching context!\n"); #endif qwglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase ); } //++timo TODO: remove that and use our own implementation? q = Texture_LoadTGATexture( pPixels, nWidth, nHeight, NULL, 0, 0, 0); free(pPixels); // fill qtexture_t information //++timo FIXME: filename will be removed .. name for qtexture_t is actually the filename now // NOTE: see qtexture_s::name for naming conventions, must remove filename extension strcpy( q->filename, name ); strcpy( q->name, name ); // only strip extension if extension there is! if (q->name[strlen(q->name)-4] == '.') q->name[strlen(q->name)-4]='\0'; // hook into the main qtexture_t list q->next = g_qeglobals.d_qtextures; g_qeglobals.d_qtextures = q; // push it in the map g_qeglobals.d_qtexmap->SetAt( q->name, q ); return q; }