]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/client/Main.qc
(experimental) CSQC Hud - can be turned off with "sbar_usecsqc 0"
[divverent/nexuiz.git] / data / qcsrc / client / Main.qc
1 // --------------------------------------------------------------------------\r
2 // BEGIN REQUIRED CSQC FUNCTIONS\r
3 //include "main.qh"\r
4 \r
5 \r
6 void() menu_show_error =\r
7 {\r
8         drawstring('0 200', "ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!", '8 8 0', '1 0 0', 1, 0);\r
9 };\r
10 \r
11 // CSQC_Init : Called every time the CSQC code is initialized (essentially at map load)\r
12 // Useful for precaching things\r
13 \r
14 void() menu_sub_null =\r
15 {\r
16 };\r
17 \r
18 float last_pingrequest;\r
19 float parse_ping;\r
20 float ping_line;\r
21 entity pingList;\r
22 float pingbuf;\r
23 \r
24 void CSQC_Init(void)\r
25 {\r
26         float i;\r
27         last_pingrequest = 0;\r
28         parse_ping = 0;\r
29         ping_line = 0;\r
30 \r
31         pingList = spawn();\r
32         pingList.sort_next = NULL;\r
33         pingList.sort_prev = NULL;\r
34         \r
35         menu_visible = FALSE;\r
36         menu_show = menu_show_error;\r
37         menu_action = menu_sub_null;\r
38         //ctf_temp_1 = "";\r
39         localcmd("alias order \"cmd order $*\"");\r
40         //registercmd("ctf_menu");\r
41         registercmd("ons_map");\r
42         //registercmd("menu_action");\r
43 \r
44         registercvar("sbar_usecsqc", "1");\r
45 \r
46         gametype = 0;\r
47 \r
48         gps_start = world;\r
49 \r
50         pingbuf = buf_create();\r
51         for(i = 0; i < maxclients; ++i)\r
52                 bufstr_add(pingbuf, "-", false);\r
53 }\r
54 // CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)\r
55 void CSQC_Shutdown(void)\r
56 {\r
57         entity next;\r
58         \r
59         buf_del(pingbuf);\r
60 \r
61         while(pingList.sort_next)\r
62         {\r
63                 next = pingList.sort_next;\r
64                 pingList.sort_next = next.sort_next;\r
65                 remove(next);\r
66         }\r
67         remove(pingList);\r
68 }\r
69 \r
70 // CSQC_ConsoleCommand : Used to parse commands in the console that have been registered with the "registercmd" function\r
71 // Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it.\r
72 float CSQC_ConsoleCommand(string strMessage)\r
73 {\r
74         local float nReturn;\r
75                 nReturn = FALSE;\r
76                 \r
77         // Tokenize String\r
78         tokenize(strMessage);\r
79         \r
80         // Acquire Command\r
81         local string strCmd;\r
82         strCmd = argv(0);\r
83 \r
84         /*if(strCmd == "ctf_menu") {\r
85                 ctf_menu_show();\r
86                 nReturn = TRUE;\r
87                 } else*/\r
88         if(strCmd == "ons_map") {\r
89                 Cmd_ons_map();\r
90                 nReturn = TRUE;\r
91         }\r
92         \r
93         return nReturn;\r
94 }\r
95 // CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client.\r
96 // Return value should be 1 if CSQC handled the input, otherwise return 0 to have the input passed to the engine.\r
97 // All keys are in ascii.\r
98 // bInputType = 0 is key pressed, 1 is key released, 2 is mouse input.\r
99 // In the case of keyboard input, nPrimary is the ascii code, and nSecondary is 0.\r
100 // In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta.\r
101 float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)\r
102 {\r
103         local float bSkipKey;\r
104         bSkipKey = false;\r
105         if(menu_visible)\r
106                 if(menu_action(bInputType, nPrimary, nSecondary))\r
107                         return TRUE;\r
108         return bSkipKey;\r
109 }\r
110 \r
111 // END REQUIRED CSQC FUNCTIONS\r
112 // --------------------------------------------------------------------------\r
113 \r
114 // --------------------------------------------------------------------------\r
115 // BEGIN OPTIONAL CSQC FUNCTIONS\r
116 \r
117 // CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.\r
118 // The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS.\r
119 void(float bIsNewEntity) CSQC_Ent_Update =\r
120 {\r
121         self.enttype = ReadByte();\r
122         if(self.enttype == ENT_CLIENT_ENTCS)\r
123         {\r
124                 self.sv_entnum = ReadByte();\r
125                 self.origin_x = ReadCoord();\r
126                 self.origin_y = ReadCoord();\r
127                 self.angles_y = ReadCoord();\r
128                 self.origin_z = self.angles_x = self.angles_z = 0;\r
129 \r
130                 if(bIsNewEntity)\r
131                 {\r
132                         //print(strcat("Adding entity: ", ftos(self.sv_entnum), "\n"));\r
133                         self.chain = gps_start;\r
134                         gps_start = self;\r
135                 }\r
136         }\r
137         else\r
138                 error("unknown entity type in CSQC_Ent_Update\n");\r
139         \r
140 };\r
141 // CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed.  Essentially call remove(self) as well.\r
142 void CSQC_Ent_Remove()\r
143 {\r
144         if(self.enttype == ENT_CLIENT_ENTCS)\r
145         {\r
146                 if(gps_start == self)\r
147                         gps_start = self.chain;\r
148                 else\r
149                 {\r
150                         local entity ent;\r
151                         ent = gps_start;\r
152                         \r
153                         while(ent.chain != self && ent.chain != world)\r
154                                 ent = ent.chain;\r
155                         if(ent.chain == self)\r
156                                 ent.chain = self.chain;\r
157                 }\r
158         }\r
159         remove(self);\r
160 }\r
161 \r
162 void Gamemode_Init()\r
163 {\r
164         local string mapinfo, infoline;\r
165         local float len;\r
166         local float file;\r
167         local vector mi_min, mi_max;\r
168 \r
169         draw_enginesbar = true;\r
170         gametype = cvar("gametype");\r
171         if(gametype == GAME_ONSLAUGHT) {\r
172                 if(!strcasecmp(substring(mapname, 0, 5), "maps/"))\r
173                         minimapname = substring(mapname, 5, 999);\r
174                 else\r
175                         minimapname = mapname;\r
176                 len = strlen(minimapname);\r
177                 if(!strcasecmp(substring(minimapname, len-4, 4), ".bsp"))\r
178                         minimapname = substring(minimapname, 0, len-4);\r
179                 \r
180                 mapinfo = strcat("maps/", minimapname, ".info");\r
181                 minimapname = strzone(strcat("gfx/", minimapname, "_mini.tga"));\r
182 \r
183                 mi_min = world.mins;\r
184                 mi_max = world.maxs;\r
185                 \r
186                 file = fopen(mapinfo, FILE_READ);\r
187                 if(file >= 0) {\r
188                         while((infoline = fgets(file))) {\r
189                                 if(!strncasecmp(infoline, "mins", 4)) {\r
190                                         mi_min = stov(substring(infoline, 5, 999));\r
191                                 } else if(!strncasecmp(infoline, "maxs", 4)) {\r
192                                         mi_max = stov(substring(infoline, 5, 999));\r
193                                 } else if(strncasecmp(infoline, "//", 2)) { // don't print comment-style lines\r
194                                         print(strcat("mapinfo: ", infoline, "\n"));\r
195                                 }\r
196                         }\r
197                 } else {\r
198                         print(strcat("^1Error: ^7Mapinfo file '", mapinfo, "' missing! Minimap will be screwed.\n"));\r
199                 }\r
200                 fclose(file);\r
201 \r
202                 print(strcat("Mins: ", vtos(mi_min), "    Maxs: ", vtos(mi_max), "\n"));\r
203                 \r
204                 mi_center = (mi_min + mi_max) * 0.5;\r
205                 mi_scale = mi_max - mi_min;\r
206                 \r
207                 \r
208                 print(strcat("Using ", minimapname, " as minimap.\n"));\r
209                 precache_pic(minimapname);\r
210                 precache_pic("gfx/ons-cp-neutral.tga");\r
211                 precache_pic("gfx/ons-cp-red.tga");\r
212                 precache_pic("gfx/ons-cp-blue.tga");\r
213                 precache_pic("gfx/ons-frame.tga");\r
214                 precache_pic("gfx/ons-frame-team.tga");\r
215         } else if(gametype == GAME_KEYHUNT) {\r
216                 precache_pic("gfx/sb_key_carrying");\r
217                 precache_pic("gfx/sb_key_carrying_outline");\r
218                 draw_enginesbar = false;\r
219         }\r
220 }\r
221 // CSQC_Parse_StuffCmd : Provides the stuffcmd string in the first parameter that the server provided.  To execute standard behavior, simply execute localcmd with the string.\r
222 void CSQC_Parse_StuffCmd(string strMessage)\r
223 {\r
224         localcmd(strMessage);\r
225         // watch for gametype changes!\r
226         if(gametype != cvar("gametype"))\r
227         {\r
228                 Gamemode_Init();\r
229         }\r
230 }\r
231 \r
232 void PingRequest()\r
233 {\r
234         float i;\r
235         entity next;\r
236         \r
237         last_pingrequest = time + 5;\r
238 \r
239         parse_ping = 0;\r
240         ping_line = 0;\r
241         for(i = 0; i < maxclients; ++i)\r
242         {\r
243                 if(strlen(getplayerkey(i, "name")))\r
244                         ++parse_ping;\r
245         }\r
246 \r
247         while(pingList.sort_next)\r
248         {\r
249                 next = pingList.sort_next;\r
250                 pingList.sort_next = next.sort_next;\r
251                 remove(next);\r
252         }\r
253         pingList.sort_prev = NULL;\r
254                 \r
255         localcmd("\nping\n");\r
256 }\r
257 \r
258 // CSQC_Parse_Print : Provides the print string in the first parameter that the server provided.  To execute standard behavior, simply execute print with the string.\r
259 void CSQC_Parse_Print(string strMessage)\r
260 {\r
261         if(!parse_ping)\r
262                 print(strMessage);\r
263         else if(strMessage != "Client ping times:\n")\r
264         {\r
265                 float ping, i, p;\r
266                 entity tmp;\r
267 \r
268                 // pingList.sort_prev = last element\r
269 \r
270                 ping = stof(strMessage);\r
271 \r
272                 /*strMessage = substring(strMessage, 5, 999);\r
273                 print(strcat("Ping for # ", ftos(ping_line), " of ", ftos(parse_ping), " = ", ftos(ping), "   player: "));\r
274                 print(strMessage);\r
275                 print("   searching... ");*/\r
276                 for(i = 0; i < maxclients; ++i)\r
277                 {\r
278                         if(strlen(getplayerkey(i, "name"))) {\r
279                                 ++p;\r
280                                 if(p > ping_line)\r
281                                         break;\r
282                         }\r
283                 }\r
284                 if(i >= maxclients)\r
285                         i = maxclients-1;\r
286                 \r
287                 bufstr_set(pingbuf, i, ftos(ping));\r
288                 /*print(getplayerkey(i, "name"));\r
289                   print("\n");*/\r
290 \r
291                 /*tmp = spawn();\r
292                 tmp.sort_next = tmp.sort_prev = NULL;\r
293                 pingList.sort_prev.sort_next = tmp;\r
294                 pingList.sort_prev = tmp;*/\r
295 \r
296                 ++ping_line;\r
297                 if(ping_line >= parse_ping)\r
298                         parse_ping = false;\r
299         }\r
300 }\r
301 // CSQC_Parse_CenterPrint : Provides the centerprint string in the first parameter that the server provided.  To execute standard behavior, simply execute cprint with the string.\r
302 void CSQC_Parse_CenterPrint(string strMessage)\r
303 {\r
304         cprint(strMessage);\r
305 }\r
306 // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.\r
307 // You must ALWAYS first acquire the temporary ID, which is sent as a byte.\r
308 // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.\r
309 float CSQC_Parse_TempEntity()\r
310 {\r
311         local float bHandled;\r
312                 bHandled  = true;\r
313         // Acquire TE ID\r
314         local float nTEID;\r
315                 nTEID = ReadByte();\r
316                 \r
317         switch(nTEID)\r
318         {\r
319                 //case TE_GUNSHOT:\r
320                 //      Do something cool with TE_GUNSHOT!\r
321                 //      break;\r
322                 default:\r
323                         // No special logic for this temporary entity; return 0 so the engine can handle it\r
324                         bHandled = false;\r
325                         break;\r
326         }\r
327                 \r
328         return bHandled;\r
329 }\r