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