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