]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/domination.qc
Limit pps to correct values, otherwise the client not so rarely shows a negated 0...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / domination.qc
1
2 /*
3 Domination as a plugin for netquake mods
4 by LordHavoc (lordhavoc@ghdigital.com)
5
6 How to add domination points to a mod:
7 1. Add this line to progs.src above world.qc:
8 domination.qc
9 2. Comment out all lines in ClientObituary in client.qc that begin with targ.frags  or attacker.frags.
10 3. Add this above spawnfunc_worldspawn in world.qc:
11 void() dom_init;
12 4. Add this line to the end of spawnfunc_worldspawn in world.qc:
13 dom_init();
14
15 Note: The only teams who can use dom control points are identified by spawnfunc_dom_team entities (if none exist these default to red and blue and use only quake models/sounds).
16 */
17
18 #define DOMPOINTFRAGS frags
19
20 float g_domination_point_amt;
21 float g_domination_point_rate;
22
23 .float enemy_playerid;
24 .entity sprite;
25 .float captime;
26
27 // pps: points per second
28 .float dom_total_pps;
29 .float dom_pps_red;
30 .float dom_pps_blue;
31 .float dom_pps_yellow;
32 .float dom_pps_pink;
33 float total_pps;
34 float pps_red;
35 float pps_blue;
36 float pps_yellow;
37 float pps_pink;
38 void set_dom_state(entity e, float connecting)
39 {
40         if(connecting)  e.dom_total_pps = total_pps;
41                                         e.dom_pps_red = pps_red;
42                                         e.dom_pps_blue = pps_blue;
43         if(c3 >= 0)             e.dom_pps_yellow = pps_yellow;
44         if(c4 >= 0)             e.dom_pps_pink = pps_pink;
45 }
46
47 void() dom_controlpoint_setup;
48
49 void LogDom(string mode, float team_before, entity actor)
50 {
51         string s;
52         if(!cvar("sv_eventlog"))
53                 return;
54         s = strcat(":dom:", mode);
55         s = strcat(s, ":", ftos(team_before));
56         s = strcat(s, ":", ftos(actor.playerid));
57         GameLogEcho(s);
58 }
59
60 void() dom_spawnteams;
61
62 void dompoint_captured ()
63 {
64         local entity head;
65         local float old_delay, old_team, real_team;
66
67         // now that the delay has expired, switch to the latest team to lay claim to this point
68         head = self.owner;
69
70         real_team = self.cnt;
71         self.cnt = -1;
72
73         LogDom("taken", self.team, self.dmg_inflictor);
74         self.dmg_inflictor = world;
75
76         self.goalentity = head;
77         self.model = head.mdl;
78         self.modelindex = head.dmg;
79         self.skin = head.skin;
80
81         //bprint(head.message);
82         //bprint("\n");
83
84         //bprint(^3head.netname);
85         //bprint(head.netname);
86         //bprint(self.message);
87         //bprint("\n");
88
89         float points, wait_time;
90         if (g_domination_point_amt)
91                 points = g_domination_point_amt;
92         else
93                 points = self.frags;
94         if (g_domination_point_rate)
95                 wait_time = g_domination_point_rate;
96         else
97                 wait_time = self.wait;
98
99         bprint("^3", head.netname, "^3", self.message);
100         bprint(" ^7(", ftos(points), " points every ", ftos(wait_time), " seconds)\n");
101
102         if(self.enemy.playerid == self.enemy_playerid)
103                 PlayerScore_Add(self.enemy, SP_DOM_TAKES, 1);
104         else
105                 self.enemy = world;
106
107         if (head.noise != "")
108                 if(self.enemy)
109                         sound(self.enemy, CHAN_AUTO, head.noise, VOL_BASE, ATTN_NORM);
110                 else
111                         sound(self, CHAN_TRIGGER, head.noise, VOL_BASE, ATTN_NORM);
112         if (head.noise1 != "")
113                 play2all(head.noise1);
114
115         //self.nextthink = time + cvar("g_domination_point_rate");
116         //self.think = dompointthink;
117
118         self.delay = time + wait_time;
119
120         // do trigger work
121         old_delay = self.delay;
122         old_team = self.team;
123         self.team = real_team;
124         self.delay = 0;
125         activator = self;
126         SUB_UseTargets ();
127         self.delay = old_delay;
128         self.team = old_team;
129
130         switch(self.team)
131         {
132                 // "fix" pps when slightly under 0 because of approximation errors
133                 case COLOR_TEAM1:
134                         pps_red -= (points/wait_time);
135                         if (pps_red < 0) pps_red = 0;
136                         break;
137                 case COLOR_TEAM2:
138                         pps_blue -= (points/wait_time);
139                         if (pps_blue < 0) pps_blue = 0;
140                         break;
141                 case COLOR_TEAM3:
142                         pps_yellow -= (points/wait_time);
143                         if (pps_yellow < 0) pps_yellow = 0;
144                         break;
145                 case COLOR_TEAM4:
146                         pps_pink -= (points/wait_time);
147                         if (pps_pink < 0) pps_pink = 0;
148         }
149
150         switch(self.goalentity.team)
151         {
152                 // "fix" pps when slightly over total_pps because of approximation errors
153                 case COLOR_TEAM1:
154                         pps_red += (points/wait_time);
155                         if (pps_red > total_pps) pps_red = total_pps;
156                         WaypointSprite_UpdateSprites(self.sprite, "dom-red", "", "");
157                         break;
158                 case COLOR_TEAM2:
159                         pps_blue += (points/wait_time);
160                         if (pps_blue > total_pps) pps_blue = total_pps;
161                         WaypointSprite_UpdateSprites(self.sprite, "dom-blue", "", "");
162                         break;
163                 case COLOR_TEAM3:
164                         pps_yellow += (points/wait_time);
165                         if (pps_yellow > total_pps) pps_yellow = total_pps;
166                         WaypointSprite_UpdateSprites(self.sprite, "dom-yellow", "", "");
167                         break;
168                 case COLOR_TEAM4:
169                         pps_pink += (points/wait_time);
170                         if (pps_pink > total_pps) pps_pink = total_pps;
171                         WaypointSprite_UpdateSprites(self.sprite, "dom-pink", "", "");
172         }
173
174         FOR_EACH_CLIENT(head)
175                 set_dom_state(head, FALSE);
176
177         WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, colormapPaletteColor(self.goalentity.team - 1, 0));
178         WaypointSprite_Ping(self.sprite);
179
180         self.captime = time;
181 };
182
183 void AnimateDomPoint()
184 {
185         if(self.pain_finished > time)
186                 return;
187         self.pain_finished = time + self.t_width;
188         if(self.nextthink > self.pain_finished)
189                 self.nextthink = self.pain_finished;
190
191         self.frame = self.frame + 1;
192         if(self.frame > self.t_length)
193                 self.frame = 0;
194 }
195
196 void dompointthink()
197 {
198         local float fragamt;
199
200         self.nextthink = time + 0.1;
201
202         //self.frame = self.frame + 1;
203         //if(self.frame > 119)
204         //      self.frame = 0;
205         AnimateDomPoint();
206
207         // give points
208
209         if (gameover || self.delay > time || time < game_starttime)     // game has ended, don't keep giving points
210                 return;
211
212         if(g_domination_point_rate)
213                 self.delay = time + g_domination_point_rate;
214         else
215                 self.delay = time + self.wait;
216
217         // give credit to the team
218         // NOTE: this defaults to 0
219         if (self.goalentity.netname != "")
220         {
221                 if(g_domination_point_amt)
222                         fragamt = g_domination_point_amt;
223                 else
224                         fragamt = self.DOMPOINTFRAGS;
225                 TeamScore_AddToTeam(self.goalentity.team, ST_SCORE, fragamt);
226                 TeamScore_AddToTeam(self.goalentity.team, ST_DOM_TICKS, fragamt);
227
228                 // give credit to the individual player, if he is still there
229                 if (self.enemy.playerid == self.enemy_playerid)
230                 {
231                         PlayerScore_Add(self.enemy, SP_SCORE, fragamt);
232                         PlayerScore_Add(self.enemy, SP_DOM_TICKS, fragamt);
233                 }
234                 else
235                         self.enemy = world;
236         }
237 }
238
239 void dompointtouch()
240 {
241         local entity head;
242         if (other.classname != "player")
243                 return;
244         if (other.health < 1)
245                 return;
246
247         if(time < self.captime + 0.3)
248                 return;
249
250         // only valid teams can claim it
251         head = find(world, classname, "dom_team");
252         while (head && head.team != other.team)
253                 head = find(head, classname, "dom_team");
254         if (!head || head.netname == "" || head == self.goalentity)
255                 return;
256
257         // delay capture
258
259         self.team = self.goalentity.team; // this stores the PREVIOUS team!
260
261         self.cnt = other.team;
262         self.owner = head; // team to switch to after the delay
263         self.dmg_inflictor = other;
264
265         // self.state = 1;
266         // self.delay = time + cvar("g_domination_point_capturetime");
267         //self.nextthink = time + cvar("g_domination_point_capturetime");
268         //self.think = dompoint_captured;
269
270         // go to neutral team in the mean time
271         head = find(world, classname, "dom_team");
272         while (head && head.netname != "")
273                 head = find(head, classname, "dom_team");
274         if(head == world)
275                 return;
276
277         WaypointSprite_UpdateSprites(self.sprite, "dom-neut", "", "");
278         WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, '0 1 1');
279         WaypointSprite_Ping(self.sprite);
280
281         self.goalentity = head;
282         self.model = head.mdl;
283         self.modelindex = head.dmg;
284         self.skin = head.skin;
285
286         self.enemy = other; // individual player scoring
287         self.enemy_playerid = other.playerid;
288         dompoint_captured();
289 };
290
291 /*QUAKED spawnfunc_dom_team (0 .5 .8) (-32 -32 -24) (32 32 32)
292 Team declaration for Domination gameplay, this allows you to decide what team
293 names and control point models are used in your map.
294
295 Note: If you use spawnfunc_dom_team entities you must define at least 3 and only two
296 can have netname set!  The nameless team owns all control points at start.
297
298 Keys:
299 "netname"
300  Name of the team (for example Red Team, Blue Team, Green Team, Yellow Team, Life, Death, etc)
301 "cnt"
302  Scoreboard color of the team (for example 4 is red and 13 is blue)
303 "model"
304  Model to use for control points owned by this team (for example
305  "progs/b_g_key.mdl" is a gold keycard, and "progs/b_s_key.mdl" is a silver
306  keycard)
307 "skin"
308  Skin of the model to use (for team skins on a single model)
309 "noise"
310  Sound to play when this team captures a point.
311  (this is a localized sound, like a small alarm or other effect)
312 "noise1"
313  Narrator speech to play when this team captures a point.
314  (this is a global sound, like "Red team has captured a control point")
315 */
316
317 void spawnfunc_dom_team()
318 {
319         if(!g_domination || cvar("g_domination_teams_override") >= 2)
320         {
321                 remove(self);
322                 return;
323         }
324         precache_model(self.model);
325         if (self.noise != "")
326                 precache_sound(self.noise);
327         if (self.noise1 != "")
328                 precache_sound(self.noise1);
329         self.classname = "dom_team";
330         setmodel(self, self.model); // precision not needed
331         self.mdl = self.model;
332         self.dmg = self.modelindex;
333         self.model = "";
334         self.modelindex = 0;
335         // this would have to be changed if used in quakeworld
336         if(self.cnt)
337                 self.team = self.cnt + 1; // WHY are these different anyway?
338 };
339
340 void dom_controlpoint_setup()
341 {
342         local entity head;
343         // find the spawnfunc_dom_team representing unclaimed points
344         head = find(world, classname, "dom_team");
345         while(head && head.netname != "")
346                 head = find(head, classname, "dom_team");
347         if (!head)
348                 objerror("no spawnfunc_dom_team with netname \"\" found\n");
349
350         // copy important properties from spawnfunc_dom_team entity
351         self.goalentity = head;
352         setmodel(self, head.mdl); // precision already set
353         self.skin = head.skin;
354
355         self.cnt = -1;
356
357         if(!self.message)
358                 self.message = " has captured a control point";
359
360         if(!self.DOMPOINTFRAGS)
361                 self.DOMPOINTFRAGS = 1;
362         if(!self.wait)
363                 self.wait = 5;
364
365         if(!self.t_width)
366                 self.t_width = 0.02; // frame animation rate
367         if(!self.t_length)
368                 self.t_length = 239; // maximum frame
369
370         self.think = dompointthink;
371         self.nextthink = time;
372         self.touch = dompointtouch;
373         self.solid = SOLID_TRIGGER;
374         self.flags = FL_ITEM;
375         setsize(self, '-32 -32 -32', '32 32 32');
376         setorigin(self, self.origin + '0 0 20');
377         droptofloor();
378
379         waypoint_spawnforitem(self);
380         WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite);
381         WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, '0 1 1');
382 };
383
384
385
386 // player has joined game, get him on a team
387 // depreciated
388 /*void dom_player_join_team(entity pl)
389 {
390         entity head;
391         float c1, c2, c3, c4, totalteams, smallestteam, smallestteam_count, selectedteam;
392         float balance_teams, force_balance, balance_type;
393
394         balance_teams = cvar("g_balance_teams");
395         balance_teams = cvar("g_balance_teams_force");
396
397         c1 = c2 = c3 = c4 = -1;
398         totalteams = 0;
399
400         // first find out what teams are allowed
401         head = find(world, classname, "dom_team");
402         while(head)
403         {
404                 if(head.netname != "")
405                 {
406                         //if(head.team == pl.team)
407                         //      selected = head;
408                         if(head.team == COLOR_TEAM1)
409                         {
410                                         c1 = 0;
411                         }
412                         if(head.team == COLOR_TEAM2)
413                         {
414                                         c2 = 0;
415                         }
416                         if(head.team == COLOR_TEAM3)
417                         {
418                                         c3 = 0;
419                         }
420                         if(head.team == COLOR_TEAM4)
421                         {
422                                         c4 = 0;
423                         }
424                 }
425                 head = find(head, classname, "dom_team");
426         }
427
428         // make sure there are at least 2 teams to join
429         if(c1 >= 0)
430                 totalteams = totalteams + 1;
431         if(c2 >= 0)
432                 totalteams = totalteams + 1;
433         if(c3 >= 0)
434                 totalteams = totalteams + 1;
435         if(c4 >= 0)
436                 totalteams = totalteams + 1;
437
438         if(totalteams <= 1)
439                 error("dom_player_join_team: Too few teams available for domination\n");
440
441         // whichever teams that are available are set to 0 instead of -1
442
443         // if we don't care what team he ends up on, put him on whatever team he entered as.
444         // if he's not on a valid team, then put him on the smallest team
445         if(!balance_teams && !force_balance)
446         {
447                 if(     c1 >= 0 && pl.team == COLOR_TEAM1)
448                         selectedteam = pl.team;
449                 else if(c2 >= 0 && pl.team == COLOR_TEAM2)
450                         selectedteam = pl.team;
451                 else if(c3 >= 0 && pl.team == COLOR_TEAM3)
452                         selectedteam = pl.team;
453                 else if(c4 >= 0 && pl.team == COLOR_TEAM4)
454                         selectedteam = pl.team;
455                 else
456                         selectedteam = -1;
457                 if(selectedteam > 0)
458                 {
459                         SetPlayerColors(pl, selectedteam - 1);
460                         return;
461                 }
462                 // otherwise end up on the smallest team (handled below)
463         }
464
465         // now count how many players are on each team already
466
467         head = find(world, classname, "player");
468         while(head)
469         {
470                 //if(head.netname != "")
471                 {
472                         if(head.team == COLOR_TEAM1)
473                         {
474                                 if(c1 >= 0)
475                                         c1 = c1 + 1;
476                         }
477                         if(head.team == COLOR_TEAM2)
478                         {
479                                 if(c2 >= 0)
480                                         c2 = c2 + 1;
481                         }
482                         if(head.team == COLOR_TEAM3)
483                         {
484                                 if(c3 >= 0)
485                                         c3 = c3 + 1;
486                         }
487                         if(head.team == COLOR_TEAM4)
488                         {
489                                 if(c4 >= 0)
490                                         c4 = c4 + 1;
491                         }
492                 }
493                 head = find(head, classname, "player");
494         }
495
496         // c1...c4 now have counts of each team
497         // figure out which is smallest, giving priority to the team the player is already on as a tie-breaker
498
499         smallestteam = 0;
500         smallestteam_count = 999;
501
502         // 2 gives priority to what team you're already on, 1 goes in order
503         balance_type = 1;
504
505         if(balance_type == 1)
506         {
507                 if(c1 >= 0 && c1 < smallestteam_count)
508                 {
509                         smallestteam = 1;
510                         smallestteam_count = c1;
511                 }
512                 if(c2 >= 0 && c2 < smallestteam_count)
513                 {
514                         smallestteam = 2;
515                         smallestteam_count = c2;
516                 }
517                 if(c3 >= 0 && c3 < smallestteam_count)
518                 {
519                         smallestteam = 3;
520                         smallestteam_count = c3;
521                 }
522                 if(c4 >= 0 && c4 < smallestteam_count)
523                 {
524                         smallestteam = 4;
525                         smallestteam_count = c4;
526                 }
527         }
528         else
529         {
530                 if(c1 >= 0 && (c1 < smallestteam_count ||
531                                         (c1 == smallestteam_count && self.team == COLOR_TEAM1) ) )
532                 {
533                         smallestteam = 1;
534                         smallestteam_count = c1;
535                 }
536                 if(c2 >= 0 && c2 < (c2 < smallestteam_count ||
537                                         (c2 == smallestteam_count && self.team == COLOR_TEAM2) ) )
538                 {
539                         smallestteam = 2;
540                         smallestteam_count = c2;
541                 }
542                 if(c3 >= 0 && c3 < (c3 < smallestteam_count ||
543                                         (c3 == smallestteam_count && self.team == COLOR_TEAM3) ) )
544                 {
545                         smallestteam = 3;
546                         smallestteam_count = c3;
547                 }
548                 if(c4 >= 0 && c4 < (c4 < smallestteam_count ||
549                                         (c4 == smallestteam_count && self.team == COLOR_TEAM4) ) )
550                 {
551                         smallestteam = 4;
552                         smallestteam_count = c4;
553                 }
554         }
555
556         if(smallestteam == 1)
557         {
558                 selectedteam = COLOR_TEAM1 - 1;
559         }
560         if(smallestteam == 2)
561         {
562                 selectedteam = COLOR_TEAM2 - 1;
563         }
564         if(smallestteam == 3)
565         {
566                 selectedteam = COLOR_TEAM3 - 1;
567         }
568         if(smallestteam == 4)
569         {
570                 selectedteam = COLOR_TEAM4 - 1;
571         }
572
573         SetPlayerColors(pl, selectedteam);
574 }
575 */
576 /*QUAKED spawnfunc_dom_controlpoint (0 .5 .8) (-16 -16 -24) (16 16 32)
577 Control point for Domination gameplay.
578 */
579 void spawnfunc_dom_controlpoint()
580 {
581         if(!g_domination)
582         {
583                 remove(self);
584                 return;
585         }
586         self.think = dom_controlpoint_setup;
587         self.nextthink = time + 0.1;
588         self.reset = dom_controlpoint_setup;
589
590         if(!self.scale)
591                 self.scale = 0.6;
592
593         //if(!self.glow_size)
594         //      self.glow_size = cvar("g_domination_point_glow");
595         self.effects = self.effects | EF_LOWPRECISION;
596         if (cvar("g_domination_point_fullbright"))
597                 self.effects |= EF_FULLBRIGHT;
598         
599         float points, waittime;
600         if (g_domination_point_rate)
601                 points += g_domination_point_rate;
602         else
603                 points += self.frags;
604         if (g_domination_point_amt)
605                 waittime += g_domination_point_amt;
606         else
607                 waittime += self.wait;
608         total_pps += points/waittime;
609 };
610
611 // code from here on is just to support maps that don't have control point and team entities
612 void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, string capsound, string capnarration, string capmessage)
613 {
614         local entity oldself;
615         oldself = self;
616         self = spawn();
617         self.classname = "dom_team";
618         self.netname = teamname;
619         self.cnt = teamcolor;
620         self.model = pointmodel;
621         self.skin = pointskin;
622         self.noise = capsound;
623         self.noise1 = capnarration;
624         self.message = capmessage;
625
626         // this code is identical to spawnfunc_dom_team
627         setmodel(self, self.model); // precision not needed
628         self.mdl = self.model;
629         self.dmg = self.modelindex;
630         self.model = "";
631         self.modelindex = 0;
632         // this would have to be changed if used in quakeworld
633         self.team = self.cnt + 1;
634
635         //eprint(self);
636         self = oldself;
637 };
638
639 void dom_spawnpoint(vector org)
640 {
641         local entity oldself;
642         oldself = self;
643         self = spawn();
644         self.classname = "dom_controlpoint";
645         self.think = spawnfunc_dom_controlpoint;
646         self.nextthink = time;
647         setorigin(self, org);
648         spawnfunc_dom_controlpoint();
649         self = oldself;
650 };
651
652 // spawn some default teams if the map is not set up for domination
653 void dom_spawnteams()
654 {
655         float numteams;
656         if(cvar("g_domination_teams_override") < 2)
657                 numteams = cvar("g_domination_default_teams");
658         else
659                 numteams = cvar("g_domination_teams_override");
660         // LordHavoc: edit this if you want to change defaults
661         dom_spawnteam("Red", COLOR_TEAM1-1, "models/domination/dom_red.md3", 0, "domination/claim.wav", "", "Red team has captured a control point");
662         dom_spawnteam("Blue", COLOR_TEAM2-1, "models/domination/dom_blue.md3", 0, "domination/claim.wav", "", "Blue team has captured a control point");
663         if(numteams > 2)
664                 dom_spawnteam("Yellow", COLOR_TEAM3-1, "models/domination/dom_yellow.md3", 0, "domination/claim.wav", "", "Yellow team has captured a control point");
665         if(numteams > 3)
666                 dom_spawnteam("Pink", COLOR_TEAM4-1, "models/domination/dom_pink.md3", 0, "domination/claim.wav", "", "Pink team has captured a control point");
667         dom_spawnteam("", 0, "models/domination/dom_unclaimed.md3", 0, "", "", "");
668 };
669
670 void dom_delayedinit()
671 {
672         local entity head;
673
674         // if no teams are found, spawn defaults, if custom teams are set, use them
675         if (find(world, classname, "dom_team") == world || cvar("g_domination_teams_override") >= 2)
676                 dom_spawnteams();
677         // if no control points are found, spawn defaults
678         if (find(world, classname, "dom_controlpoint") == world)
679         {
680                 // here follow default domination points for each map
681                 /*
682                 if (world.model == "maps/e1m1.bsp")
683                 {
684                         dom_spawnpoint('0 0 0');
685                 }
686                 else
687                 */
688                 {
689                         // if no supported map was found, make every deathmatch spawn a point
690                         head = find(world, classname, "info_player_deathmatch");
691                         while (head)
692                         {
693                                 dom_spawnpoint(head.origin);
694                                 head = find(head, classname, "info_player_deathmatch");
695                         }
696                 }
697         }
698
699         ScoreRules_dom();
700 };
701
702 void dom_init()
703 {
704         // we have to precache default models/sounds even if they might not be
705         // used because spawnfunc_worldspawn is executed before any other entities are read,
706         // so we don't even know yet if this map is set up for domination...
707         precache_model("models/domination/dom_red.md3");
708         precache_model("models/domination/dom_blue.md3");
709         precache_model("models/domination/dom_yellow.md3");
710         precache_model("models/domination/dom_pink.md3");
711         precache_model("models/domination/dom_unclaimed.md3");
712         precache_sound("domination/claim.wav");
713         InitializeEntity(world, dom_delayedinit, INITPRIO_GAMETYPE);
714
715         addstat(STAT_DOM_TOTAL_PPS, AS_FLOAT, dom_total_pps);
716         addstat(STAT_DOM_PPS_RED, AS_FLOAT, dom_pps_red);
717         addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue);
718         if(c3 >= 0) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow);
719         if(c4 >= 0) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink);
720
721         g_domination_point_rate = cvar("g_domination_point_rate");
722         g_domination_point_amt = cvar("g_domination_point_amt");
723
724         // teamplay is always on in domination, defaults to hurt self but not teammates
725         //if(!teams_matter)
726         //      cvar_set("teamplay", "3");
727 };
728