+ for (loc = cl.locnodes;loc;loc = loc->next)
+ {
+ if (VectorCompare(loc->mins, loc->maxs))
+ {
+ int len;
+ const char *s;
+ const char *in = loc->name;
+ char name[MAX_INPUTLINE];
+ for (len = 0;len < (int)sizeof(name) - 1 && *in;)
+ {
+ if (*in == ' ') {s = "$loc_name_separator";in++;}
+ else if (!strncmp(in, "SSG", 3)) {s = "$loc_name_ssg";in += 3;}
+ else if (!strncmp(in, "NG", 2)) {s = "$loc_name_ng";in += 2;}
+ else if (!strncmp(in, "SNG", 3)) {s = "$loc_name_sng";in += 3;}
+ else if (!strncmp(in, "GL", 2)) {s = "$loc_name_gl";in += 2;}
+ else if (!strncmp(in, "RL", 2)) {s = "$loc_name_rl";in += 2;}
+ else if (!strncmp(in, "LG", 2)) {s = "$loc_name_lg";in += 2;}
+ else if (!strncmp(in, "GA", 2)) {s = "$loc_name_ga";in += 2;}
+ else if (!strncmp(in, "YA", 2)) {s = "$loc_name_ya";in += 2;}
+ else if (!strncmp(in, "RA", 2)) {s = "$loc_name_ra";in += 2;}
+ else if (!strncmp(in, "MEGA", 4)) {s = "$loc_name_mh";in += 4;}
+ else s = NULL;
+ if (s)
+ {
+ while (len < (int)sizeof(name) - 1 && *s)
+ name[len++] = *s++;
+ continue;
+ }
+ name[len++] = *in++;
+ }
+ name[len] = 0;
+ FS_Printf(outfile, "%.0f %.0f %.0f %s\n", loc->mins[0]*8, loc->mins[1]*8, loc->mins[2]*8, name);
+ }
+ else
+ FS_Printf(outfile, "%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,\"%s\"\n", loc->mins[0], loc->mins[1], loc->mins[2], loc->maxs[0], loc->maxs[1], loc->maxs[2], loc->name);
+ }
+ FS_Close(outfile);
+}
+
+void CL_Locs_Reload_f(void)
+{
+ int i, linenumber, limit, len;
+ const char *s;
+ char *filedata, *text, *textend, *linestart, *linetext, *lineend;
+ fs_offset_t filesize;
+ vec3_t mins, maxs;
+ char locfilename[MAX_QPATH];
+ char name[MAX_INPUTLINE];
+
+ if (cls.state != ca_connected || !cl.worldmodel)
+ {
+ Con_Printf("No level loaded!\n");
+ return;
+ }
+
+ CL_Locs_Clear_f();
+
+ // try maps/something.loc first (LordHavoc: where I think they should be)
+ FS_StripExtension(cl.worldmodel->name, locfilename, sizeof(locfilename));
+ strlcat(locfilename, ".loc", sizeof(locfilename));
+ filedata = (char *)FS_LoadFile(locfilename, cls.levelmempool, false, &filesize);
+ if (!filedata)
+ {
+ // try proquake name as well (LordHavoc: I hate path mangling)
+ FS_StripExtension(va("locs/%s", FS_FileWithoutPath(cl.worldmodel->name)), locfilename, sizeof(locfilename));
+ strlcat(locfilename, ".loc", sizeof(locfilename));
+ filedata = (char *)FS_LoadFile(locfilename, cls.levelmempool, false, &filesize);
+ if (!filedata)
+ return;
+ }
+ text = filedata;
+ textend = filedata + filesize;
+ for (linenumber = 1;text < textend;linenumber++)
+ {
+ linestart = text;
+ for (;text < textend && *text != '\r' && *text != '\n';text++)
+ ;
+ lineend = text;
+ if (text + 1 < textend && *text == '\r' && text[1] == '\n')
+ text++;
+ if (text < textend)
+ text++;
+ // trim trailing whitespace
+ while (lineend > linestart && lineend[-1] <= ' ')
+ lineend--;
+ // trim leading whitespace
+ while (linestart < lineend && *linestart <= ' ')
+ linestart++;
+ // check if this is a comment
+ if (linestart + 2 <= lineend && !strncmp(linestart, "//", 2))
+ continue;
+ linetext = linestart;
+ limit = 3;
+ for (i = 0;i < limit;i++)
+ {
+ if (linetext >= lineend)
+ break;
+ // note: a missing number is interpreted as 0
+ if (i < 3)
+ mins[i] = atof(linetext);
+ else
+ maxs[i - 3] = atof(linetext);
+ // now advance past the number
+ while (linetext < lineend && *linetext > ' ' && *linetext != ',')
+ linetext++;
+ // advance through whitespace
+ if (linetext < lineend)
+ {
+ if (*linetext == ',')
+ {
+ linetext++;
+ limit = 6;
+ // note: comma can be followed by whitespace
+ }
+ if (*linetext <= ' ')
+ {
+ // skip whitespace
+ while (linetext < lineend && *linetext <= ' ')
+ linetext++;
+ }
+ }
+ }
+ // if this is a quoted name, remove the quotes
+ if (i == 6)
+ {
+ if (linetext >= lineend || *linetext != '"')
+ continue; // proquake location names are always quoted
+ lineend--;
+ linetext++;
+ len = min(lineend - linetext, (int)sizeof(name) - 1);
+ memcpy(name, linetext, len);
+ name[len] = 0;
+ // add the box to the list
+ CL_Locs_AddNode(mins, maxs, name);
+ }
+ // if a point was parsed, it needs to be scaled down by 8 (since
+ // point-based loc files were invented by a proxy which dealt
+ // directly with quake protocol coordinates, which are *8), turn
+ // it into a box
+ else if (i == 3)
+ {
+ // interpret silly fuhquake macros
+ for (len = 0;len < (int)sizeof(name) - 1 && linetext < lineend;)
+ {
+ if (*linetext == '$')
+ {
+ if (linetext + 18 <= lineend && !strncmp(linetext, "$loc_name_separator", 19)) {s = " ";linetext += 19;}
+ else if (linetext + 13 <= lineend && !strncmp(linetext, "$loc_name_ssg", 13)) {s = "SSG";linetext += 13;}
+ else if (linetext + 12 <= lineend && !strncmp(linetext, "$loc_name_ng", 12)) {s = "NG";linetext += 12;}
+ else if (linetext + 13 <= lineend && !strncmp(linetext, "$loc_name_sng", 13)) {s = "SNG";linetext += 13;}
+ else if (linetext + 12 <= lineend && !strncmp(linetext, "$loc_name_gl", 12)) {s = "GL";linetext += 12;}
+ else if (linetext + 12 <= lineend && !strncmp(linetext, "$loc_name_rl", 12)) {s = "RL";linetext += 12;}
+ else if (linetext + 12 <= lineend && !strncmp(linetext, "$loc_name_lg", 12)) {s = "LG";linetext += 12;}
+ else if (linetext + 12 <= lineend && !strncmp(linetext, "$loc_name_ga", 12)) {s = "GA";linetext += 12;}
+ else if (linetext + 12 <= lineend && !strncmp(linetext, "$loc_name_ya", 12)) {s = "YA";linetext += 12;}
+ else if (linetext + 12 <= lineend && !strncmp(linetext, "$loc_name_ra", 12)) {s = "RA";linetext += 12;}
+ else if (linetext + 12 <= lineend && !strncmp(linetext, "$loc_name_mh", 12)) {s = "MEGA";linetext += 12;}
+ else s = NULL;
+ if (s)
+ {
+ while (len < (int)sizeof(name) - 1 && *s)
+ name[len++] = *s++;
+ continue;
+ }
+ }
+ name[len++] = *linetext++;
+ }
+ name[len] = 0;
+ // add the point to the list
+ VectorScale(mins, (1.0 / 8.0), mins);
+ CL_Locs_AddNode(mins, mins, name);
+ }
+ else
+ continue;
+ }
+}
+
+/*
+===========
+CL_Shutdown
+===========
+*/
+void CL_Shutdown (void)
+{
+ CL_Particles_Shutdown();
+ CL_Parse_Shutdown();
+
+ Mem_FreePool (&cls.permanentmempool);
+ Mem_FreePool (&cls.levelmempool);