]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - data/qcsrc/server/monsters/mode_management.qc
Transform this too, from Quake's trigger_changelevel
[voretournament/voretournament.git] / data / qcsrc / server / monsters / mode_management.qc
1 \r
2 string(float c) colorname =\r
3 {\r
4         // yikes, the quake color set is HARD to describe\r
5         // many are easy, but, uh, 2 browns???\r
6         // 2 purples???\r
7         // that 'pink' is hard to classify\r
8         // I think 'biege' is a fairly good name for color 10\r
9         // oh well, gotta do all the color names...\r
10         if (c ==  0) return "white";\r
11         else if (c ==  1) return "brown";\r
12         else if (c ==  2) return "lightblue";\r
13         else if (c ==  3) return "green";\r
14         else if (c ==  4) return "red";\r
15         else if (c ==  5) return "lighterbrown";\r
16         else if (c ==  6) return "orange";\r
17         else if (c ==  7) return "pink";\r
18         else if (c ==  8) return "purple";\r
19         else if (c ==  9) return "redishpurple";\r
20         else if (c == 10) return "biege";\r
21         else if (c == 11) return "aqua";\r
22         else if (c == 12) return "yellow";\r
23         else if (c == 13) return "blue";\r
24         else if (c == 14) return "flamingorange";\r
25         else if (c == 15) return "psychadelic";\r
26         else              return "INVALID COLOR";\r
27 };\r
28 \r
29 float mode_shirtmustmatchpants;\r
30 float mode_numteams;\r
31 float mode_allowedteams[17];\r
32 float mode_teamcount[17];\r
33 float mode_teamscore[17];\r
34 \r
35 void() mode_initallowedteams =\r
36 {\r
37         local float c;\r
38         c = 0;\r
39         while(c < 17)\r
40         {\r
41                 mode_allowedteams[c] = FALSE;\r
42                 c = c + 1;\r
43         }\r
44         mode_allowedteams[5] = TRUE; // red\r
45         mode_allowedteams[14] = TRUE; // blue\r
46         if (deathmatch == DM_ELIM\r
47          || deathmatch == DM_ONEVSALL\r
48          || deathmatch == DM_CTF_2TEAM\r
49          || deathmatch == DM_DOMINATION\r
50          || deathmatch == DM_SUPERDOMINATION)\r
51                 mode_numteams = 2;\r
52         else if (deathmatch == DM_CTF_3TEAM)\r
53         {\r
54                 mode_numteams = 3;\r
55                 mode_allowedteams[13] = TRUE; // yellow\r
56         }\r
57         else\r
58         {\r
59                 mode_numteams = 16;\r
60                 c = 1;\r
61                 while(c < 17)\r
62                 {\r
63                         mode_allowedteams[c] = TRUE;\r
64                         c = c + 1;\r
65                 }\r
66         }\r
67 };\r
68 \r
69 float(float t) validteam =\r
70 {\r
71         return mode_allowedteams[t];\r
72 };\r
73 \r
74 float() weakestteam =\r
75 {\r
76         local float bestteam;\r
77         local float bestteamcount;\r
78         local float headcount;\r
79         local float c;\r
80         bestteam = -1;\r
81         bestteamcount = 0;\r
82         c = 1;\r
83         while (c < 17)\r
84         {\r
85                 if (mode_allowedteams[c])\r
86                 {\r
87                         headcount = mode_teamcount[c];\r
88                         if (bestteamcount > headcount || bestteam == -1)\r
89                         {\r
90                                 bestteamcount = headcount;\r
91                                 bestteam = c;\r
92                         }\r
93                 }\r
94                 c = c + 1;\r
95         }\r
96         return bestteam;\r
97 };\r
98 \r
99 void() updateteams =\r
100 {\r
101         local entity head;\r
102         local float c;\r
103         c = 1;\r
104         while (c < 17)\r
105         {\r
106                 mode_teamcount[c] = 0;\r
107                 mode_teamscore[c] = 0;\r
108                 c = c + 1;\r
109         }\r
110         c = 0;\r
111         head = nextent(world);\r
112         while (c < maxclients)\r
113         {\r
114                 mode_teamcount[head.team] = mode_teamcount[head.team] + 1;\r
115                 mode_teamscore[head.team] = mode_teamscore[head.team] + head.frags;\r
116                 c = c + 1;\r
117                 head = nextent(head);\r
118         }\r
119 };\r
120 \r
121 float(float p) checkteamcolor =\r
122 {\r
123         if (!validteam(p + 1))\r
124                 p = weakestteam() - 1;\r
125         return p;\r
126 };\r
127 \r
128 void(float c) SV_ChangeTeam =\r
129 {\r
130         local float pants, shirt, old;\r
131         old = self.clientcolors & 15;\r
132         if (c >= 0)\r
133         {\r
134                 pants = c & 15;\r
135                 shirt = (c / 16) & 15;\r
136         }\r
137         else\r
138         {\r
139                 pants = -1;\r
140                 shirt = -1;\r
141         }\r
142         pants = checkteamcolor(pants);\r
143         if (mode_shirtmustmatchpants || shirt < 0)\r
144                 shirt = pants;\r
145         setcolor(self, pants + shirt * 16);\r
146         if (pants != old && old >= 0 && teamplay && deathmatch)\r
147         {\r
148                 T_Damage(self, self, self, 0, 0, " changed teams", DT_TELEFRAG, self.origin, '0 0 0', Obituary_Generic);\r
149                 self.frags = 0;\r
150                 PutClientInServer ();\r
151         }\r
152 };\r
153 \r
154 void() checkinvalidteam =\r
155 {\r
156         // call SV_ChangeTeam to trigger the weakestteam change\r
157         if (!validteam(self.team))\r
158                 SV_ChangeTeam(self.team - 1);\r
159 };\r
160 \r
161 \r
162 string dmmessage;\r
163 \r
164 void(string m) setdm =\r
165 {\r
166         dmmessage = m;\r
167         if (cvar_string("deathmatch") != m)\r
168                 cvar_set("deathmatch", m);\r
169 }\r
170 \r
171 void(string m) setteamplay =\r
172 {\r
173         dmmessage = m;\r
174         if (cvar_string("teamplay") != m)\r
175                 cvar_set("teamplay", m);\r
176 }\r
177 \r
178 void() mode_updatecvars =\r
179 {\r
180         local float dm, tp;\r
181         dm = cvar("deathmatch");\r
182         tp = cvar("teamplay");\r
183         // now set deathmatch cvar\r
184         if (dm ==  0) setdm("0?Dark Places - Coop");\r
185         else if (dm ==  1) setdm("1?Dark Places - Deathmatch");\r
186         else if (dm ==  2) setdm("2?Dark Places - Deathmatch 2 (can only pickup gun once)");\r
187         else if (dm ==  3) setdm("3?Dark Places - Deathmatch 3 (quick ammo respawn)");\r
188         else if (dm ==  5) setdm("5?Dark Places - Frag Fest (spawn with full pack)");\r
189 //      else if (dm ==  6) setdm("6?Dark Places - Random Weapons (spawn with 2 random weapons)"); // removed\r
190         else if (dm ==  7) setdm("7?Dark Places - Monsters");\r
191 //      else if (dm ==  8) setdm("8?Dark Places - Elimination");\r
192 //      else if (dm ==  9) setdm("9?Dark Places - Kill The Leader Mode");\r
193         else if (dm == 10) setdm("10?Dark Places - Capture The Flag - 2 Team");\r
194         else if (dm == 11) setdm("11?Dark Places - Capture The Flag - 3 Team");\r
195         else if (dm == 12) setdm("12?Dark Places - Domination");\r
196         else if (dm == 13) setdm("13?Dark Places - Monster Capture The Flag - 2 Team");\r
197         else if (dm == 14) setdm("14?Dark Places - Super Domination");\r
198         else if (dm == 30) setdm("30?Dark Places - Role Playing Game");\r
199         else                               setdm("1?Dark Places - Deathmatch");\r
200 \r
201         // now set teamplay cvar\r
202         if (dm == 0) setteamplay("4?Dark Places - Coop (Can't hurt other players)");\r
203         //else if (dm == 8) setteamplay("3?Dark Places - Elimination");\r
204         //else if (dm == 9) setteamplay("3?Dark Places - Kill The Leader");\r
205         else if (dm == 10) setteamplay("3?Dark Places - Capture The Flag - 2 Team");\r
206         else if (dm == 11) setteamplay("3?Dark Places - Capture The Flag - 3 Team");\r
207         else if (dm == 12) setteamplay("3?Dark Places - Domination");\r
208         else if (dm == 13) setteamplay("3?Dark Places - Monster Capture The Flag - 2 Team");\r
209         else\r
210         {\r
211                 if (tp == 0) setteamplay("0?Dark Places - No Teamplay");\r
212                 else if (tp == 1) setteamplay("1?Dark Places - No team damage");\r
213                 else if (tp == 2) setteamplay("2?Dark Places - Can hurt anyone");\r
214                 else if (tp == 3) setteamplay("3?Dark Places - No team damage, but can hurt self");\r
215                 else              setteamplay("0?Dark Places - No Teamplay");\r
216         }\r
217 };\r
218 \r
219 float nextcvarupdate;\r
220 void() deathmatch7update;\r
221 void() modeupdate =\r
222 {\r
223         if (time > nextcvarupdate)\r
224         {\r
225                 nextcvarupdate = time + 1;\r
226                 mode_updatecvars();\r
227         }\r
228         deathmatch7update();\r
229 };\r
230 \r
231 // true if items should respawn\r
232 float itemrespawn;\r
233 // when the next monster spawning check will occur in deathmatch 7 mode\r
234 float spawnchecktime;\r
235 \r
236 void() precachemonsters;\r
237 void() superdomination_precache;\r
238 void() modesetup =\r
239 {\r
240         mode_shirtmustmatchpants = deathmatch >= DM_TEAM_MODS_START && deathmatch < DM_TEAM_MODS_END;\r
241         mode_initallowedteams();\r
242 \r
243         itemrespawn = cvar("deathmatch") + cvar("coop");\r
244 \r
245         // don't spawn any monsters until 15 seconds\r
246         spawnchecktime = 15;\r
247         if (deathmatch == 7 || cvar("spawnmonsters") >= 1)\r
248                 precachemonsters();\r
249 \r
250         superdomination_precache();\r
251 };\r
252 \r
253 float monsterspawn;\r
254 void() spawnmonster_think =\r
255 {\r
256         //local float c;\r
257         local void() sfunc;\r
258         self.nextthink = time;\r
259         if (time > self.cnt)\r
260         {\r
261                 remove(self);\r
262                 return;\r
263         }\r
264         if (vlen(self.velocity) > 5)\r
265                 return; // try again later\r
266 \r
267         //if (!(self.flags & FL_FLY))\r
268         //      droptofloor();\r
269         // don't spawn if something is in the way\r
270         /*\r
271         // walk around a lot\r
272         if (walkmove(0,0))\r
273         {\r
274                 if (self.lefty > 0)\r
275                 {\r
276                         c = 100;\r
277                         self.lefty = self.lefty - 1;\r
278                         self.angles = '0 0 0';\r
279                         while(c > 0)\r
280                         {\r
281                                 c = c - 1;\r
282                                 if (!walkmove(self.angles_y, 16))\r
283                                         self.angles_y = random() * 360;\r
284                         }\r
285                         self.angles = '0 0 0';\r
286                         return;\r
287                 }\r
288         }\r
289         */\r
290         // don't spawn if something is in the way\r
291         if (!walkmove(0,0))\r
292         {\r
293                 self.lefty = 10;\r
294                 setorigin(self, self.dest);\r
295                 self.flags = self.flags - (self.flags & FL_ONGROUND);\r
296                 self.velocity = randomvec() * 700 + '0 0 1000';\r
297                 return;\r
298         }\r
299         newmis = findchain(classname, "player");\r
300         while (newmis)\r
301         {\r
302                 if (vlen(newmis.origin - self.origin) < 300)\r
303                         return;\r
304                 newmis = newmis.chain;\r
305         }\r
306 \r
307         if (self.netname == "monster_fish")\r
308         {\r
309                 if (pointcontents(self.origin) != CONTENT_WATER)\r
310                 {\r
311                         remove(self);\r
312                         return;\r
313                 }\r
314         }\r
315 \r
316         // spawn in\r
317         self.movetype = MOVETYPE_NONE;\r
318         self.solid = SOLID_NOT;\r
319         self.velocity = '0 0 0';\r
320         self.flags = 0;\r
321         self.model = "";\r
322         self.modelindex = 0;\r
323         setorigin(self, self.origin);\r
324         self.angles = '0 360 0' * random();\r
325         self.classname = self.netname;\r
326         self.netname = "";\r
327         self.cnt = 0;\r
328         self.think = SUB_Remove;\r
329         sfunc = self.th_run;\r
330         self.th_run = SUB_Null;\r
331         te_teleport(self.origin);\r
332         monsterspawn = TRUE;\r
333         sfunc();\r
334         monsterspawn = FALSE;\r
335 };\r
336 \r
337 void(vector org, float c1, float c2, string cname, void() spawnfunc, vector m1, vector m2) spawnmonster =\r
338 {\r
339         local float c;\r
340         c = (c2 - c1) * random() + c1;\r
341         c = rint(c);\r
342         while (c > 0)\r
343         {\r
344                 c = c - 1;\r
345 \r
346                 newmis = spawn();\r
347                 newmis.cnt = time + 10;\r
348                 if (cname == "monster_wizard")\r
349                         newmis.cnt = time + 2;\r
350                 newmis.lefty = 10;\r
351                 newmis.dest = org;\r
352                 newmis.classname = "spawningmonster";\r
353                 newmis.netname = cname;\r
354                 newmis.solid = SOLID_TRIGGER;\r
355                 newmis.movetype = MOVETYPE_TOSS;\r
356                 newmis.flags = FL_MONSTER; // make this count as a monster even though it hasn't spawned in yet\r
357                 newmis.velocity = randomvec() * 700 + '0 0 1000';\r
358                 newmis.th_run = spawnfunc;\r
359                 newmis.think = spawnmonster_think;\r
360                 newmis.nextthink = time + random() * 0.5 + 0.3;\r
361                 setorigin(newmis, org);\r
362                 setmodel(newmis, "progs/s_explod.spr");\r
363                 setsize(newmis, m1, m2);\r
364         }\r
365 };\r
366 \r
367 void() monster_army;\r
368 void() monster_demon1;\r
369 void() monster_dog;\r
370 void() monster_enforcer;\r
371 void() monster_hell_knight;\r
372 void() monster_knight;\r
373 void() monster_ogre;\r
374 void() monster_shalrath;\r
375 void() monster_shambler;\r
376 void() monster_tarbaby;\r
377 void() monster_wizard;\r
378 void() monster_zombie;\r
379 void() monster_fish;\r
380 void() monster_hellfish;\r
381 \r
382 void() spawnmonsters =\r
383 {\r
384         local float r;\r
385         local vector org;\r
386         local entity head, e;\r
387         head = findchain(classname, "info_player_deathmatch");\r
388         if (head == world)\r
389         {\r
390                 head = findchain(classname, "info_player_coop");\r
391                 if (head == world)\r
392                 {\r
393                         head = findchain(classname, "info_player_start");\r
394                         if (head == world)\r
395                                 return;\r
396                 }\r
397         }\r
398 \r
399         // count the spawn points\r
400         r = 0;\r
401         e = head;\r
402         while (e)\r
403         {\r
404                 r = r + 1;\r
405                 e = e.chain;\r
406         }\r
407 \r
408         // pick a random one\r
409         r = random() * r;\r
410         e = head;\r
411         while (r > 0)\r
412         {\r
413                 r = r - 1;\r
414                 org = e.origin;\r
415                 e = e.chain;\r
416         }\r
417 \r
418         // pick a type of monster\r
419         if (cvar("registered"))\r
420         {\r
421                 r = floor(random() * 13);\r
422                 if (r > 12)\r
423                         r = 12;\r
424         }\r
425         else\r
426         {\r
427                 r = floor(random() * 8);\r
428                 if (r > 7)\r
429                         r = 7;\r
430         }\r
431              if (r ==  0) spawnmonster(org,  5, 10, "monster_army"       , monster_army       , '-16 -16 -24', '16 16 32');\r
432         else if (r ==  1) spawnmonster(org,  3,  6, "monster_demon1"     , monster_demon1     , '-32 -32 -24', '32 32 64');\r
433         else if (r ==  2) spawnmonster(org,  6, 12, "monster_dog"        , monster_dog        , '-16 -16 -24', '16 16 32');\r
434         else if (r ==  3) spawnmonster(org,  6, 12, "monster_knight"     , monster_knight     , '-16 -16 -24', '16 16 32');\r
435         else if (r ==  4) spawnmonster(org,  3,  6, "monster_ogre"       , monster_ogre       , '-32 -32 -24', '32 32 64');\r
436         else if (r ==  5) spawnmonster(org,  1,  1, "monster_shambler"   , monster_shambler   , '-32 -32 -24', '32 32 64');\r
437         else if (r ==  6) spawnmonster(org,  6, 10, "monster_wizard"     , monster_wizard     , '-16 -16 -24', '16 16 32');\r
438         else if (r ==  7) spawnmonster(org,  8, 16, "monster_zombie"     , monster_zombie     , '-16 -16 -24', '16 16 32');\r
439         else if (r ==  8) spawnmonster(org,  4,  8, "monster_enforcer"   , monster_enforcer   , '-16 -16 -24', '16 16 32');\r
440         else if (r ==  9) spawnmonster(org,  4,  8, "monster_hell_knight", monster_hell_knight, '-16 -16 -24', '16 16 32');\r
441         else if (r == 10) spawnmonster(org,  1,  3, "monster_shalrath"   , monster_shalrath   , '-32 -32 -24', '32 32 64');\r
442         else if (r == 11) spawnmonster(org, 10, 15, "monster_tarbaby"    , monster_tarbaby    , '-16 -16 -24', '16 16 32');\r
443         else if (r == 12) spawnmonster(org,  4,  8, "monster_fish"       , monster_fish       , '-16 -16 -24', '16 16 32');\r
444 };\r
445 \r
446 float monstersprecached;\r
447 void() precachemonster_army;\r
448 void() precachemonster_demon1;\r
449 void() precachemonster_dog;\r
450 void() precachemonster_enforcer;\r
451 void() precachemonster_hell_knight;\r
452 void() precachemonster_knight;\r
453 void() precachemonster_ogre;\r
454 void() precachemonster_shalrath;\r
455 void() precachemonster_shambler;\r
456 void() precachemonster_tarbaby;\r
457 void() precachemonster_wizard;\r
458 void() precachemonster_zombie;\r
459 void() precachemonster_fish;\r
460 \r
461 void() precachemonsters =\r
462 {\r
463         precachemonster_army();\r
464         precachemonster_demon1();\r
465         precachemonster_dog();\r
466         precachemonster_knight();\r
467         precachemonster_ogre();\r
468         precachemonster_shambler();\r
469         precachemonster_wizard();\r
470         precachemonster_zombie();\r
471         if (cvar("registered"))\r
472         {\r
473                 precachemonster_enforcer();\r
474                 precachemonster_hell_knight();\r
475                 precachemonster_shalrath();\r
476                 precachemonster_tarbaby();\r
477                 precachemonster_fish();\r
478         }\r
479         monstersprecached = TRUE;\r
480 };\r
481 \r
482 float spawnedexitmonsters;\r
483 void() deathmatch7update =\r
484 {\r
485         local entity e;\r
486         local float f, monster_count, monsters;\r
487         if (skill >= 5)\r
488         if (!deathmatch)\r
489         {\r
490                 if (!spawnedexitmonsters)\r
491                 if (time >= 2)\r
492                 {\r
493                         spawnedexitmonsters = TRUE;\r
494                         e = find(world, classname, "target_changelevel");\r
495                         while (e)\r
496                         {\r
497                                 spawnmonster(e.origin + (e.mins + e.maxs) * 0.5, 8, 8, "monster_hellfish", monster_hellfish, '-16 -16 -24', '16 16 32');\r
498                                 e = find(e, classname, "target_changelevel");\r
499                         }\r
500                 }\r
501                 return;\r
502         }\r
503         if (time < spawnchecktime)\r
504                 return;\r
505         if (!monstersprecached)\r
506                 return;\r
507         spawnchecktime = time + 0.2;\r
508         monsters = 0;\r
509         if (deathmatch == 7)\r
510                 monsters = 50;\r
511         f = cvar("spawnmonsters");\r
512         if (f >= 1)\r
513                 monsters = f;\r
514         if (monsters < 1)\r
515                 return;\r
516         monster_count = 0;\r
517         e = findchainflags(flags, FL_MONSTER);\r
518         while (e)\r
519         {\r
520                 monster_count = monster_count + 1;\r
521                 e = e.chain;\r
522         }\r
523         if (monster_count >= monsters)\r
524                 return;\r
525         spawnmonsters();\r
526 }\r