00001
00025 #include "notice.h"
00026 #include "color.h"
00027 #include "player.h"
00028 #include <assert.h>
00029
00034 #define MAX_NOTICES 4
00035
00041 #define SPACING 2
00042
00047 struct Notice_t {
00051 RenderItem text;
00055 Uint32 expiryTime;
00059 Uint8 type;
00060 };
00061
00062 typedef struct Notice_t Notice;
00063
00068 static Notice notices[MAX_NOTICES] = { 0 };
00069
00075 static Notice *order[MAX_NOTICES] = {
00076 ¬ices[0], ¬ices[1], ¬ices[2], ¬ices[3]
00077 };
00078
00083 static int timeouts = 0;
00084
00089 static int notimeouts = 0;
00090
00098 static void RemoveOneNotice(int index) {
00099 Notice *n = order[index];
00100 assert(index < MAX_NOTICES);
00101
00102 ClearRenderItem(&(n->text));
00103
00104 RemoveRenderItem(&(n->text));
00105
00106 SDL_FreeSurface(n->text.data);
00107 n->text.data = NULL;
00108
00109 if (n->expiryTime == NOTICE_NOEXPIRATION) {
00110 notimeouts--;
00111 }
00112 else {
00113 timeouts--;
00114 }
00115
00116 for (; index < MAX_NOTICES - 1; index++) {
00117
00118 (order[index] = order[index + 1])->text.loc.y = -1;
00119 }
00120
00121 order[MAX_NOTICES - 1] = n;
00122 }
00123
00124 void AddNotice(Uint32 expiryTime, Uint8 type, rtsa_char *format, ...) {
00125 Notice *n;
00126 va_list args;
00127 int ind;
00128 Bool add = TRUE;
00129 assert(type < NOTICE_MAXTYPE);
00130
00131
00132 if ((ind = timeouts + notimeouts) >= MAX_NOTICES) {
00133
00134 add = FALSE;
00135
00136 if (notimeouts == MAX_NOTICES) {
00137
00138 return;
00139 }
00140
00141 ClearRenderItem(&((n = order[ind = MAX_NOTICES - 1])->text));
00142 }
00143 else {
00144
00145 n = order[ind];
00146 }
00147
00148 if (expiryTime == NOTICE_NOEXPIRATION) {
00149
00150 for (; ind > notimeouts; ind--) {
00151
00152 (order[ind] = order[ind - 1])->text.loc.y = -1;
00153 }
00154
00155 order[ind] = n;
00156
00157 if (add) {
00158 notimeouts++;
00159 }
00160 }
00161 else if (add) {
00162 timeouts++;
00163 }
00164 assert(timeouts + notimeouts <= MAX_NOTICES);
00165
00166 va_start(args, format);
00167
00168 TextRenderStringV(&(n->text), FONT_SCORE, dInfo.pw >> 1,
00169 colorFmtInd[COLOR_BLACK], format, args);
00170
00171 va_end(args);
00172
00173 n->text.loc.y = -1;
00174
00175 n->expiryTime = expiryTime;
00176 n->type = type;
00177
00178 if (add) {
00179 AddRenderItem(&(n->text), LAYER_TEXT);
00180 }
00181 }
00182
00183 extern Uint32 frameTime;
00184
00185 void AddScoreNotice(int killerId, int killedId, int score) {
00186 Player *s = &players[killerId];
00187 Player *l = &players[killedId];
00188
00189 assert((killerId < MAX_PLAYERS) && (killedId < MAX_PLAYERS));
00190
00191 if (s->team == l->team) {
00192
00193 if (s->pid == localPlayer) {
00194 AddNotice(frameTime + 3000, NOTICE_LOCALTEAMKILL,
00195 strings[STRING_LOCALTEAMKILLER], l->name);
00196 }
00197
00198 else if (l->pid == localPlayer) {
00199 AddNotice(frameTime + 3000, NOTICE_LOCALTEAMKILL,
00200 strings[STRING_LOCALTEAMKILLED], s->name);
00201 }
00202 else {
00203 AddNotice(frameTime + 3000, NOTICE_TEAMKILL,
00204 strings[STRING_TEAMKILL], s->name, l->name);
00205 }
00206 }
00207 else {
00208
00209 if (s->pid == localPlayer) {
00210 AddNotice(frameTime + 3000, NOTICE_LOCALKILL,
00211 strings[STRING_LOCALKILL], l->name, score);
00212 }
00213 else {
00214 AddNotice(frameTime + 3000, NOTICE_KILL,
00215 strings[STRING_KILL], s->name, l->name, score);
00216 }
00217 }
00218 }
00219
00220 void RemoveNotice(Uint8 type) {
00221 int loop;
00222 for (loop = timeouts + notimeouts - 1; loop >= 0; loop--) {
00223
00224 if (order[loop]->type == type) {
00225 RemoveOneNotice(loop);
00226
00227 break;
00228 }
00229 }
00230 }
00231
00232 void RemoveAllNotices() {
00233 int loop;
00234 for (loop = timeouts + notimeouts - 1; loop >= 0; loop--) {
00235
00236 ClearRenderItem(&(order[loop]->text));
00237
00238 RemoveRenderItem(&(order[loop]->text));
00239
00240 SDL_FreeSurface(order[loop]->text.data);
00241 order[loop]->text.data = NULL;
00242 }
00243
00244 timeouts = notimeouts = 0;
00245 }
00246
00247 void UpdateNotices(Uint32 time) {
00248 Bool placeRemaining = FALSE;
00249 int loop, top = TOP_MARGIN;
00250 Notice *n;
00251 for (loop = 0; loop < timeouts + notimeouts; ) {
00252
00253 if ((n = order[loop])->expiryTime <= time) {
00254
00255 RemoveOneNotice(loop);
00256
00257 placeRemaining = TRUE;
00258
00259 continue;
00260 }
00261
00262 if (placeRemaining || (n->text.loc.y == -1)) {
00263
00264 placeRemaining = TRUE;
00265
00266
00267 n->text.loc.x = (dInfo.pw >> 1) - (n->text.loc.w >> 1);
00268
00269 n->text.loc.y = top;
00270
00271 PlaceRenderItem(&(n->text));
00272 }
00273
00274 top = SPACING + n->text.loc.y + n->text.loc.h;
00275
00276 loop++;
00277 }
00278 }
00279