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