]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/gamec/miscfunctions.c
removing this makefile also
[divverent/nexuiz.git] / data / qcsrc / server / gamec / miscfunctions.c
1 string W_Name(float weaponid);
2 float(float index) weapon_translateindextoflag;
3
4 float logfile_open;
5 float logfile;
6
7 void(string s) bcenterprint
8 {
9         entity head;
10         head = find(world, classname, "player");
11         while(head)
12         {
13                 if(clienttype(head) == CLIENTTYPE_REAL)
14                         centerprint(head, s);
15                 head = find(head, classname, "player");
16         }
17 }
18
19 void(string s, float check_dangerous) ServerConsoleEcho =
20 {
21         local string ch;
22         localcmd("echo \"");
23         if(check_dangerous)
24         {
25                 while(strlen(s))
26                 {
27                         ch = substring(s, 0, 1);
28                         if(ch != "\"" && ch != "\r" && ch != "\n")
29                                 localcmd(ch);
30                         s = substring(s, 1, strlen(s) - 1);
31                 }
32         }
33         else
34         {
35                 localcmd(s);
36         }
37         localcmd("\"\n");
38 }
39
40 void(string s, float check_dangerous) GameLogEcho =
41 {
42         string fn;
43         float matches;
44
45         if(cvar("sv_eventlog_files"))
46         {
47                 if(!logfile_open)
48                 {
49                         logfile_open = TRUE;
50                         matches = cvar("sv_eventlog_files_counter") + 1;
51                         cvar_set("sv_eventlog_files_counter", ftos(matches));
52                         fn = ftos(matches);
53                         if(strlen(fn) < 8)
54                                 fn = strcat(substring("00000000", 0, 8 - strlen(fn)), fn);
55                         fn = strcat(cvar_string("sv_eventlog_files_nameprefix"), fn, cvar_string("sv_eventlog_files_namesuffix"));
56                         logfile = fopen(fn, FILE_APPEND);
57                 }
58                 if(logfile >= 0)
59                         fputs(logfile, strcat(s, "\n"));
60         }
61         if(cvar("sv_eventlog_console"))
62         {
63                 ServerConsoleEcho(s, check_dangerous);
64         }
65 }
66
67 void() GameLogInit =
68 {
69         logfile_open = 0;
70         // will be opened later
71 }
72
73 void() GameLogClose =
74 {
75         if(logfile_open && logfile >= 0)
76         {
77                 fclose(logfile);
78                 logfile = -1;
79         }
80 }
81
82 float math_mod(float a, float b)
83 {
84         return a - (floor(a / b) * b);
85 }
86
87 string linewrap(string s, float l)
88 {
89         string t;
90
91 /*
92         t = "";
93         while(l < strlen(s))
94         {
95                 t = strcat(t, substring(s, 0, l), "\n");
96                 s = substring(s, l+1, strlen(s));
97         }
98         return strcat(t, s);
99 */
100         // this function seems broken (character wrap, no word wrap)
101         // use WORD wrap instead... importing it from campaign code
102         s = strzone(s);
103         t = Campaign_wordwrap(s, l);
104         strunzone(s);
105         return t;
106 }
107
108 vector find_floor(vector org)
109 {
110         traceline(org + '0 0 5', org - '0 0 255', TRUE, self);
111         if (trace_fraction < 1)
112                 return trace_endpos;
113         else
114                 return org;
115 }
116
117 void relocate_spawnpoint()
118 {
119         vector org, loc;
120         string error_msg;
121
122         error_msg = "spawn point too close to a wall";
123         
124         org = find_floor(self.origin) + '0 0 30';
125
126         traceline(org, org - '18 0 0', TRUE, world);
127         if(trace_fraction < 1)
128         {
129                 loc = trace_endpos;
130                 traceline(loc, loc + '36 0 0', TRUE, world);
131                 if(trace_fraction >= 1 && !self.noalign)
132                         org = loc + '18 0 0';
133                 else
134                 {
135                         objerror(error_msg);
136                         return;
137                 }
138         }
139
140         traceline (org, org - '-18 0 0', TRUE, world);
141         if (trace_fraction < 1)
142         {
143                 loc = trace_endpos;
144                 traceline (loc, loc + '-36 0 0', TRUE, world);
145                 if(trace_fraction >= 1 && !self.noalign)
146                         org = loc + '-18 0 0';
147                 else
148                 {
149                         objerror(error_msg);
150                         return;
151                 }
152         }
153
154         traceline (org, org - '0 18 0' , TRUE, world);
155         if (trace_fraction < 1)
156         {
157                 loc = trace_endpos;
158                 traceline (loc, loc + '0 36 0', TRUE, world);
159                 if(trace_fraction >= 1 && !self.noalign)
160                         org = loc + '0 18 0';
161                 else
162                 {                       
163                         objerror(error_msg);
164                         return;
165                 }
166         }
167
168         traceline (org, org - '0 -18 0', TRUE, world);
169         if (trace_fraction < 1)
170         {
171                 loc = trace_endpos;
172                 traceline (loc, loc + '0 -36 0', TRUE, world);
173                 if(trace_fraction >= 1 && !self.noalign)
174                         org = loc + '0 -18 0';
175                 else
176                 {
177                         objerror(error_msg);
178                         return;
179                 }
180         }
181         
182         if(!self.noalign)
183                 setorigin(self, org);
184 }
185
186 // NOTE: DO NOT USE THIS FUNCTION TOO OFTEN.
187 // IT WILL MOST PROBABLY DESTROY _ALL_ OTHER TEMP
188 // STRINGS AND TAKE QUITE LONG. haystack and needle MUST
189 // BE CONSTANT OR strzoneD!
190 float(string haystack, string needle, float offset) strstr =
191 {
192         float len, endpos;
193         string found;
194         len = strlen(needle);
195         endpos = strlen(haystack) - len;
196         while(offset < endpos)
197         {
198                 found = substring(haystack, offset, len);
199                 if(found == needle)
200                         return offset;
201                 offset = offset + 1;
202         }
203         return -1;
204 }
205
206 float NUM_NEAREST_ENTITIES = 4;
207 entity nearest_entity[NUM_NEAREST_ENTITIES];
208 float nearest_length[NUM_NEAREST_ENTITIES];
209 entity(vector point, .string field, string value, vector axismod) findnearest =
210 {
211         entity localhead;
212         float i;
213         float j;
214         float len;
215         vector dist;
216
217         float num_nearest;
218         num_nearest = 0;
219
220         localhead = find(world, field, value);
221         while(localhead)
222         {
223                 if((localhead.items == IT_KEY1 || localhead.items == IT_KEY2) && localhead.target == "###item###")
224                         dist = localhead.oldorigin;
225                 else
226                         dist = localhead.origin;
227                 dist = dist - point;
228                 dist = dist_x * axismod_x * '1 0 0' + dist_y * axismod_y * '0 1 0' + dist_z * axismod_z * '0 0 1';
229                 len = vlen(dist);
230
231                 for(i = 0; i < num_nearest; ++i)
232                 {
233                         if(len < nearest_length[i])
234                                 break;
235                 }
236
237                 // now i tells us where to insert at
238                 //   INSERTION SORT! YOU'VE SEEN IT! RUN!
239                 if(i < NUM_NEAREST_ENTITIES)
240                 {
241                         for(j = NUM_NEAREST_ENTITIES - 1; j >= i; --j)
242                         {
243                                 nearest_length[j + 1] = nearest_length[j];
244                                 nearest_entity[j + 1] = nearest_entity[j];
245                         }
246                         nearest_length[i] = len;
247                         nearest_entity[i] = localhead;
248                         if(num_nearest < NUM_NEAREST_ENTITIES)
249                                 num_nearest = num_nearest + 1;
250                 }
251                 
252                 localhead = find(localhead, field, value);
253         }
254
255         // now use the first one from our list that we can see
256         for(i = 0; i < num_nearest; ++i)
257         {
258                 traceline(point, nearest_entity[i].origin, TRUE, world);
259                 if(trace_fraction == 1)
260                 {
261                         if(i != 0)
262                         {
263                                 dprint("Nearest point (");
264                                 dprint(nearest_entity[0].netname);
265                                 dprint(") is not visible, using a visible one.\n");
266                         }
267                         return nearest_entity[i];
268                 }
269         }
270
271         if(num_nearest == 0)
272                 return world;
273
274         dprint("Not seeing any location point, using nearest as fallback.\n");
275         /* DEBUGGING CODE:
276         dprint("Candidates were: ");
277         for(j = 0; j < num_nearest; ++j)
278         {
279                 if(j != 0)
280                         dprint(", ");
281                 dprint(nearest_entity[j].netname);
282         }
283         dprint("\n");
284         */
285
286         return nearest_entity[0];
287 }
288
289 void() target_location =
290 {   
291         self.classname = "target_location";
292         // location name in netname
293         // eventually support: count, teamgame selectors, line of sight?
294 };  
295
296 void() info_location =
297 {   
298         self.classname = "target_location";
299         self.message = self.netname;
300 };  
301
302 string NearestLocation(vector p)
303 {
304         entity loc;
305         string ret;
306         ret = "somewhere";
307         loc = findnearest(p, classname, "target_location", '1 1 1');
308         if(loc)
309         {
310                 ret = loc.message;
311         }
312         else
313         {
314                 loc = findnearest(p, target, "###item###", '1 1 4');
315                 if(loc)
316                         ret = loc.netname;
317         }
318         return ret;
319 }
320
321 string(string msg) formatmessage =
322 {
323         float p;
324         float n;
325         string msg_save;
326         string escape;
327         string replacement;
328         msg_save = strzone(msg);
329         p = 0;
330         n = 7;
331         while(1)
332         {
333                 if(n < 1)
334                         break; // too many replacements
335                 n = n - 1;
336                 p = strstr(msg_save, "%", p); // NOTE: this destroys msg as it's a tempstring!
337                 if(p < 0)
338                         break;
339                 replacement = substring(msg_save, p, 2);
340                 escape = substring(msg_save, p + 1, 1);
341                 if(escape == "%")
342                         replacement = "%";
343                 else if(escape == "a")
344                         replacement = ftos(floor(self.armorvalue));
345                 else if(escape == "h")
346                         replacement = ftos(floor(self.health));
347                 else if(escape == "l")
348                         replacement = NearestLocation(self.origin);
349                 else if(escape == "y")
350                         replacement = NearestLocation(self.cursor_trace_endpos);
351                 else if(escape == "d")
352                         replacement = NearestLocation(self.death_origin);
353                 else if(escape == "w")
354                 {
355                         float wep;
356                         wep = self.weapon;
357                         if(!wep)
358                                 wep = self.switchweapon;
359                         if(!wep)
360                                 wep = self.cnt;
361                         replacement = W_Name(wep);
362                 }
363                 else if(escape == "W")
364                 {
365                         if(self.items & IT_SHELLS) replacement = "shells";
366                         else if(self.items & IT_NAILS) replacement = "bullets";
367                         else if(self.items & IT_ROCKETS) replacement = "rockets";
368                         else if(self.items & IT_CELLS) replacement = "cells";
369                         else replacement = "batteries"; // ;)
370                 }
371                 else if(escape == "x")
372                 {
373                         replacement = self.cursor_trace_ent.netname;
374                         if(!replacement || !self.cursor_trace_ent)
375                                 replacement = "nothing";
376                 }
377                 msg = strcat(substring(msg_save, 0, p), replacement);
378                 msg = strcat(msg, substring(msg_save, p+2, strlen(msg_save) - (p+2)));
379                 strunzone(msg_save);
380                 msg_save = strzone(msg);
381                 p = p + 2;
382         }
383         msg = strcat(msg_save);
384         strunzone(msg_save);
385         return msg;
386 }
387
388 /*
389 =============
390 GetCvars
391 =============
392 Called with:
393   0:  sends the request
394   >0: receives a cvar from name=argv(f) value=argv(f+1)
395 */
396 void GetCvars_handleString(float f, .string field, string name)
397 {
398         if(f)
399         {
400                 if(argv(f) == name)
401                         self.field = argv(f + 1);
402         }
403         else
404                 stuffcmd(self, strcat("cmd reportcvar ", name, " $", name, "\n"));
405 }
406 void GetCvars_handleFloat(float f, .float field, string name)
407 {
408         if(f)
409         {
410                 if(argv(f) == name)
411                         self.field = stof(argv(f + 1));
412         }
413         else
414                 stuffcmd(self, strcat("cmd reportcvar ", name, " $", name, "\n"));
415 }
416 void GetCvars(float f)
417 {
418         GetCvars_handleFloat(f, cvar_cl_playerdetailreduction, "cl_playerdetailreduction");
419         GetCvars_handleFloat(f, cvar_cl_nogibs, "cl_nogibs");
420 }
421
422 float fexists(string f)
423 {
424         float fh;
425         fh = fopen(f, FILE_READ);
426         if(fh < 0)
427                 return FALSE;
428         fclose(fh);
429         return TRUE;
430 }