]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/gamec/miscfunctions.c
%l: strstr really ate all my tempstrings, as expected...
[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, float check_dangerous) ServerConsoleEcho =
8 {
9         local string ch;
10         localcmd("echo \"");
11         if(check_dangerous)
12         {
13                 while(strlen(s))
14                 {
15                         ch = substring(s, 0, 1);
16                         if(ch != "\"" && ch != "\r" && ch != "\n")
17                                 localcmd(ch);
18                         s = substring(s, 1, strlen(s) - 1);
19                 }
20         }
21         else
22         {
23                 localcmd(s);
24         }
25         localcmd("\"\n");
26 }
27
28 void(string s, float check_dangerous) GameLogEcho =
29 {
30         string fn;
31         float matches;
32
33         if(cvar("sv_eventlog_files"))
34         {
35                 if(!logfile_open)
36                 {
37                         logfile_open = TRUE;
38                         matches = cvar("sv_eventlog_files_counter") + 1;
39                         cvar_set("sv_eventlog_files_counter", ftos(matches));
40                         fn = ftos(matches);
41                         if(strlen(fn) < 8)
42                                 fn = strcat(substring("00000000", 0, 8 - strlen(fn)), fn);
43                         fn = strcat(cvar_string("sv_eventlog_files_nameprefix"), fn, cvar_string("sv_eventlog_files_namesuffix"));
44                         logfile = fopen(fn, FILE_APPEND);
45                 }
46                 if(logfile >= 0)
47                         fputs(logfile, strcat(s, "\n"));
48         }
49         if(cvar("sv_eventlog_console"))
50         {
51                 ServerConsoleEcho(s, check_dangerous);
52         }
53 }
54
55 void() GameLogInit =
56 {
57         logfile_open = 0;
58         // will be opened later
59 }
60
61 void() GameLogClose =
62 {
63         if(logfile_open && logfile >= 0)
64         {
65                 fclose(logfile);
66                 logfile = -1;
67         }
68 }
69
70 float math_mod(float a, float b)
71 {
72         return a - (floor(a / b) * b);
73 }
74
75 string linewrap(string s, float l)
76 {
77         string t;
78
79         t = "";
80         while(l < strlen(s))
81         {
82                 t = strcat(t, substring(s, 0, l), "\n");
83                 s = substring(s, l+1, strlen(s));
84         }
85         return strcat(t, s);
86 }
87
88 vector find_floor(vector org)
89 {
90         traceline(org + '0 0 5', org - '0 0 255', TRUE, self);
91         if (trace_fraction < 1)
92                 return trace_endpos;
93         else
94                 return org;
95 }
96
97 void relocate_spawnpoint()
98 {
99         if(self.noalign)
100                 return;
101
102         setorigin(self, find_floor(self.origin) + '0 0 30');
103 }
104
105 // NOTE: DO NOT USE THIS FUNCTION TOO OFTEN.
106 // IT WILL MOST PROBABLY DESTROY _ALL_ OTHER TEMP
107 // STRINGS AND TAKE QUITE LONG. haystack and needle MUST
108 // BE CONSTANT OR strzoneD!
109 float(string haystack, string needle, float offset) strstr =
110 {
111         float len, endpos;
112         string found;
113         len = strlen(needle);
114         endpos = strlen(haystack) - len;
115         while(offset < endpos)
116         {
117                 found = substring(haystack, offset, len);
118                 if(found == needle)
119                         return offset;
120                 offset = offset + 1;
121         }
122         return -1;
123 }
124
125 float NUM_NEAREST_ENTITIES = 4;
126 entity nearest_entity[NUM_NEAREST_ENTITIES];
127 float nearest_length[NUM_NEAREST_ENTITIES];
128 entity(vector point, .string field, string value, vector axismod) findnearest =
129 {
130         entity localhead;
131         float i;
132         float j;
133         float len;
134         vector dist;
135
136         float num_nearest;
137         num_nearest = 0;
138
139         localhead = find(world, field, value);
140         while(localhead)
141         {
142                 if((localhead.items == IT_KEY1 || localhead.items == IT_KEY2) && localhead.target == "###item###")
143                         dist = localhead.oldorigin;
144                 else
145                         dist = localhead.origin;
146                 dist = dist - point;
147                 dist = dist_x * axismod_x * '1 0 0' + dist_y * axismod_y * '0 1 0' + dist_z * axismod_z * '0 0 1';
148                 len = vlen(dist);
149
150                 for(i = 0; i < num_nearest; ++i)
151                 {
152                         if(len < nearest_length[i])
153                                 break;
154                 }
155
156                 // now i tells us where to insert at
157                 //   INSERTION SORT! YOU'VE SEEN IT! RUN!
158                 if(i < NUM_NEAREST_ENTITIES)
159                 {
160                         for(j = NUM_NEAREST_ENTITIES - 1; j >= i; --j)
161                         {
162                                 nearest_length[j + 1] = nearest_length[j];
163                                 nearest_entity[j + 1] = nearest_entity[j];
164                         }
165                         nearest_length[i] = len;
166                         nearest_entity[i] = localhead;
167                         if(num_nearest < NUM_NEAREST_ENTITIES)
168                                 num_nearest = num_nearest + 1;
169                 }
170                 
171                 localhead = find(localhead, field, value);
172         }
173
174         // now use the first one from our list that we can see
175         for(i = 0; i < num_nearest; ++i)
176         {
177                 traceline(point, nearest_entity[i].origin, TRUE, world);
178                 if(trace_fraction == 1)
179                 {
180                         if(i != 0)
181                         {
182                                 dprint("Nearest point (");
183                                 dprint(nearest_entity[0].netname);
184                                 dprint(") is not visible, using a visible one.\n");
185                         }
186                         return nearest_entity[i];
187                 }
188         }
189
190         if(num_nearest == 0)
191                 return world;
192
193         dprint("Not seeing any location point, using nearest as fallback.\n");
194         /* DEBUGGING CODE:
195         dprint("Candidates were: ");
196         for(j = 0; j < num_nearest; ++j)
197         {
198                 if(j != 0)
199                         dprint(", ");
200                 dprint(nearest_entity[j].netname);
201         }
202         dprint("\n");
203         */
204
205         return nearest_entity[0];
206 }
207
208 void() target_location =
209 {   
210         self.classname = "target_location";
211         // location name in netname
212         // eventually support: count, teamgame selectors, line of sight?
213 };  
214
215 void() info_location =
216 {   
217         self.classname = "target_location";
218         self.message = self.netname;
219 };  
220
221 string(string msg) formatmessage =
222 {
223         float p;
224         float n;
225         string msg_save;
226         string escape;
227         string replacement;
228         msg_save = strzone(msg);
229         p = 0;
230         n = 7;
231         while(1)
232         {
233                 if(n < 1)
234                         break; // too many replacements
235                 n = n - 1;
236                 p = strstr(msg_save, "%", p); // NOTE: this destroys msg as it's a tempstring!
237                 if(p < 0)
238                         break;
239                 replacement = substring(msg_save, p, 2);
240                 escape = substring(msg_save, p + 1, 1);
241                 if(escape == "%")
242                         replacement = "%";
243                 else if(escape == "a")
244                         replacement = ftos(floor(self.armorvalue));
245                 else if(escape == "h")
246                         replacement = ftos(floor(self.health));
247                 else if(escape == "l")
248                 {
249                         entity loc;
250                         replacement = "somewhere";
251                         loc = findnearest(self.origin, classname, "target_location", '1 1 1');
252                         if(loc)
253                         {
254                                 replacement = loc.message;
255                         }
256                         else
257                         {
258                                 loc = findnearest(self.origin, target, "###item###", '1 1 4');
259                                 if(loc)
260                                         replacement = loc.netname;
261                         }
262                 }
263                 else if(escape == "x")
264                 {
265                         if(self.cursor_trace_ent)
266                                 replacement = self.cursor_trace_ent.netname;
267                         else
268                                 replacement = "nothing";
269                 }
270                 msg = strcat(substring(msg_save, 0, p), replacement);
271                 msg = strcat(msg, substring(msg_save, p+2, strlen(msg_save) - (p+2)));
272                 strunzone(msg_save);
273                 msg_save = strzone(msg);
274                 p = p + 2;
275         }
276         msg = strcat(msg_save);
277         strunzone(msg_save);
278         return msg;
279 }