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