]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/scores.qc
add generic csqc scoreboard managing beginning (does nothing yet)
[divverent/nexuiz.git] / data / qcsrc / server / scores.qc
1 .entity scorekeeper;
2 entity teamscorekeepers[16];
3 string scores_label[MAX_SCORE];
4 float scores_flags[MAX_SCORE];
5 string teamscores_label[MAX_TEAMSCORE];
6 float teamscores_flags[MAX_TEAMSCORE];
7 float teamscores_entities_count;
8 var .float scores_primary;
9 var .float teamscores_primary;
10
11 .float Version;
12 .float(entity to) SendEntity;
13
14 vector ScoreField_Compare(entity t1, entity t2, .float field, float fieldflags, vector previous) // returns: cmp value, best prio
15 {
16         if(fieldflags & SFL_SORT_PRIO_MASK < previous_y)
17                 return previous;
18         if(t1.field == t2.field)
19                 return previous;
20
21         previous_y = fieldflags & SFL_SORT_PRIO_MASK;
22
23         if(fieldflags & SFL_DECREASING)
24                 previous_x = (t1.field - t2.field);
25         else
26                 previous_x = (t2.field - t1.field);
27
28         return previous;
29 }
30
31 /*
32  * teamscore entities
33  */
34
35 void TeamScore_SendEntity(entity to)
36 {
37         float i;
38
39         WriteByte(MSG_ENTITY, ENT_CLIENT_TEAMSCORES);
40         WriteByte(MSG_ENTITY, self.team);
41         for(i = 0; i < MAX_TEAMSCORE; ++i)
42                 WriteShort(MSG_ENTITY, self.teamscores[i]);
43 }
44
45 void TeamScore_Spawn(float t, string name)
46 {
47         entity ts;
48         ts = spawn();
49         ts.classname = "csqc_score_team";
50         ts.SendEntity = TeamScore_SendEntity;
51         ts.netname = name; // not used yet, FIXME
52         ts.Version = 1; // immediately send, so csqc knows about the team
53         teamscorekeepers[t] = ts;
54         ++teamscores_entities_count;
55 }
56
57 void TeamScore_Add(entity player, float scorefield, float score)
58 {
59         entity s;
60         s = teamscorekeepers[player.team];
61         if(!s)
62                 error("Adding score to unknown team!");
63         s.(teamscores[scorefield]) += score;
64         s.Version += 1;
65 }
66
67 float TeamScore_Compare(entity t1, entity t2)
68 {
69         if(!t1 || !t2) return (!t2) - !t1;
70
71         vector result;
72         float i;
73         for(i = 0; i < MAX_TEAMSCORE; ++i)
74                 result = ScoreField_Compare(t1, t2, teamscores[i], teamscores_flags[i], result);
75         return result_x;
76 }
77
78 /*
79  * the scoreinfo entity
80  */
81
82 void ScoreInfo_SetLabel_PlayerScore(float i, string label, float scoreflags)
83 {
84         scores_label[i] = label;
85         scores_flags[i] = scoreflags;
86         if(scoreflags & SFL_SORT_PRIO_MASK == SFL_SORT_PRIO_PRIMARY)
87                 scores_primary = scores[i];
88 }
89
90 void ScoreInfo_SetLabel_TeamScore(float i, string label, float scoreflags)
91 {
92         teamscores_label[i] = label;
93         teamscores_flags[i] = scoreflags;
94         if(scoreflags & SFL_SORT_PRIO_MASK == SFL_SORT_PRIO_PRIMARY)
95                 teamscores_primary = teamscores[i];
96 }
97
98 void ScoreInfo_SendEntity(entity to)
99 {
100         WriteByte(MSG_ENTITY, ENT_CLIENT_SCORES_INFO);
101         float i;
102         for(i = 0; i < MAX_SCORE; ++i)
103         {
104                 WriteString(MSG_ENTITY, scores_label[i]);
105                 WriteByte(MSG_ENTITY, scores_flags[i]);
106         }
107         for(i = 0; i < MAX_TEAMSCORE; ++i)
108         {
109                 WriteString(MSG_ENTITY, teamscores_label[i]);
110                 WriteByte(MSG_ENTITY, teamscores_flags[i]);
111         }
112 }
113
114 void ScoreInfo_Init(float teams)
115 {
116         if(teams >= 1)
117                 TeamScore_Spawn(COLOR_TEAM1, "Red");
118         if(teams >= 2)
119                 TeamScore_Spawn(COLOR_TEAM2, "Blue");
120         if(teams >= 3)
121                 TeamScore_Spawn(COLOR_TEAM3, "Yellow");
122         if(teams >= 4)
123                 TeamScore_Spawn(COLOR_TEAM4, "Pink");
124         entity si;
125         si = spawn();
126         si.classname = "csqc_score_info";
127         si.SendEntity = ScoreInfo_SendEntity;
128         si.Version = 1;
129 }
130
131 /*
132  * per-player score entities
133  */
134
135 void PlayerScore_SendEntity()
136 {
137         float i;
138
139         WriteByte(MSG_ENTITY, ENT_CLIENT_SCORES);
140         WriteByte(MSG_ENTITY, num_for_edict(self.owner));
141         for(i = 0; i < MAX_SCORE; ++i)
142                 WriteShort(MSG_ENTITY, self.scores[i]);
143 }
144
145 void PlayerScore_Clear(entity player)
146 {
147         entity sk;
148         float i;
149
150         if(!teamscores_entities_count)
151         {
152                 sk = player.scorekeeper;
153                 for(i = 0; i < MAX_SCORE; ++i)
154                         sk.(scores[i]) = 0;
155                 sk.Version += 1;
156         }
157 }
158
159 void PlayerScore_Attach(entity player)
160 {
161         entity sk;
162         if(player.scorekeeper)
163                 error("player already has a scorekeeper");
164         sk = spawn();
165         sk.owner = player;
166         sk.SendEntity = PlayerScore_SendEntity;
167         player.scorekeeper = sk;
168 }
169
170 void PlayerScore_Detach(entity player)
171 {
172         if(!player.scorekeeper)
173                 error("player has no scorekeeper");
174         remove(player.scorekeeper);
175         player.scorekeeper = world;
176 }
177
178 void PlayerScore_Add(entity player, float scorefield, float score)
179 {
180         entity s;
181         s = player.scorekeeper;
182         if(!s)
183                 error("Adding score to unknown player!");
184         s.(scores[scorefield]) += score;
185         s.Version += 1;
186 }
187
188 float PlayerScore_Compare(entity t1, entity t2)
189 {
190         if(!t1 || !t2) return (!t2) - !t1;
191
192         vector result;
193         float i;
194         for(i = 0; i < MAX_TEAMSCORE; ++i)
195                 result = ScoreField_Compare(t1, t2, scores[i], scores_flags[i], result);
196         return result_x;
197 }
198
199 void WinningConditionHelper()
200 {
201         float c;
202         if(teamscores_entities_count)
203         {
204                 float t;
205                 WinningConditionHelper_equality = 1;
206                 WinningConditionHelper_winnerteam = 0;
207                 for(t = 1; t < 16; ++t)
208                 {
209                         c = TeamScore_Compare(teamscorekeepers[WinningConditionHelper_winnerteam], teamscorekeepers[t]);
210                         if(c == 0)
211                                 WinningConditionHelper_equality = 1;
212                         else if(c < 0)
213                         {
214                                 WinningConditionHelper_equality = 0;
215                                 WinningConditionHelper_winnerteam = t;
216                         }
217                 }
218
219                 WinningConditionHelper_topscore = teamscorekeepers[WinningConditionHelper_winnerteam].teamscores_primary;
220
221                 WinningConditionHelper_winner = world;
222                 if(WinningConditionHelper_equality)
223                         WinningConditionHelper_winnerteam = -1;
224         }
225         else
226         {
227                 entity p;
228                 WinningConditionHelper_equality = 1;
229                 WinningConditionHelper_winner = world;
230                 FOR_EACH_PLAYER(p)
231                 {
232                         c = PlayerScore_Compare(WinningConditionHelper_winner.scorekeeper, p.scorekeeper);
233                         if(c == 0)
234                                 WinningConditionHelper_equality = 1;
235                         else if(c < 0)
236                         {
237                                 WinningConditionHelper_equality = 0;
238                                 WinningConditionHelper_winner = p;
239                         }
240                 }
241
242                 WinningConditionHelper_topscore = WinningConditionHelper_winner.scorekeeper.scores_primary;
243
244                 if(WinningConditionHelper_equality)
245                         WinningConditionHelper_winner = world;
246                 WinningConditionHelper_winnerteam = -1;
247         }
248 }