1 | /* |
1 | /* |
2 | CrossFire, A Multiplayer game for X-windows |
2 | * CrossFire, A Multiplayer game for X-windows |
3 | |
3 | * |
|
|
4 | * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team |
4 | Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
5 | * Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
5 | Copyright (C) 1992 Frank Tore Johansen |
6 | * Copyright (C) 1992 Frank Tore Johansen |
6 | |
7 | * |
7 | This program is free software; you can redistribute it and/or modify |
8 | * This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by |
9 | * it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | * the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. |
11 | * (at your option) any later version. |
11 | |
12 | * |
12 | This program is distributed in the hope that it will be useful, |
13 | * This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
16 | * GNU General Public License for more details. |
16 | |
17 | * |
17 | You should have received a copy of the GNU General Public License |
18 | * You should have received a copy of the GNU General Public License |
18 | along with this program; if not, write to the Free Software |
19 | * along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | |
21 | * |
21 | The authors can be reached via e-mail at crossfire-devel@real-time.com |
22 | * The authors can be reached via e-mail at <crossfire@schmorp.de> |
22 | */ |
23 | */ |
23 | |
24 | |
24 | #include <global.h> |
25 | #include <global.h> |
25 | #ifndef __CEXTRACT__ |
|
|
26 | # include <sproto.h> |
26 | #include <sproto.h> |
27 | #endif |
|
|
28 | |
27 | |
29 | /* |
28 | /* |
30 | * The score structure is used when treating new high-scores |
29 | * The score structure is used when treating new high-scores |
31 | */ |
30 | */ |
32 | |
|
|
33 | typedef struct scr |
31 | typedef struct scr |
34 | { |
32 | { |
35 | char name[BIG_NAME]; /* name */ |
33 | char name[64]; // name */ |
36 | char title[BIG_NAME]; /* Title */ |
34 | char title[64]; // Title */ |
37 | char killer[BIG_NAME]; /* name (+ title) or "quit" */ |
35 | char killer[64]; // name (+ title) or "quit" */ |
38 | sint64 exp; /* Experience */ |
36 | sint64 exp; // Experience */ |
39 | char maplevel[BIG_NAME]; /* Killed on what level */ |
37 | char maplevel[128]; // Killed on what level */ |
40 | int maxhp, maxsp, maxgrace; /* Max hp, sp, grace when killed */ |
38 | int maxhp, maxsp, maxgrace; // Max hp, sp, grace when killed */ |
41 | int position; /* Position in the highscore list */ |
39 | int position; // Position in the highscore list */ |
42 | } score; |
40 | } score; |
43 | |
41 | |
44 | /* |
42 | /* |
45 | * spool works mostly like strtok(char *, ":"), but it can also |
43 | * spool works mostly like strtok(char *, ":"), but it can also |
46 | * log a specified error message if something goes wrong. |
44 | * log a specified error message if something goes wrong. |
… | |
… | |
82 | */ |
80 | */ |
83 | |
81 | |
84 | static void |
82 | static void |
85 | copy_score (score *sc1, score *sc2) |
83 | copy_score (score *sc1, score *sc2) |
86 | { |
84 | { |
87 | strncpy (sc2->name, sc1->name, BIG_NAME); |
85 | assign (sc2->name , sc1->name); |
88 | sc2->name[BIG_NAME - 1] = '\0'; |
86 | assign (sc2->title , sc1->title); |
89 | strncpy (sc2->title, sc1->title, BIG_NAME); |
|
|
90 | sc2->title[BIG_NAME - 1] = '\0'; |
|
|
91 | strncpy (sc2->killer, sc1->killer, BIG_NAME); |
87 | assign (sc2->killer , sc1->killer); |
92 | sc2->killer[BIG_NAME - 1] = '\0'; |
88 | assign (sc2->maplevel, sc1->maplevel); |
93 | sc2->exp = sc1->exp; |
89 | sc2->exp = sc1->exp; |
94 | strcpy (sc2->maplevel, sc1->maplevel); |
|
|
95 | sc2->maxhp = sc1->maxhp; |
90 | sc2->maxhp = sc1->maxhp; |
96 | sc2->maxsp = sc1->maxsp; |
91 | sc2->maxsp = sc1->maxsp; |
97 | sc2->maxgrace = sc1->maxgrace; |
92 | sc2->maxgrace = sc1->maxgrace; |
98 | } |
93 | } |
99 | |
94 | |
… | |
… | |
105 | static char * |
100 | static char * |
106 | put_score (score *sc) |
101 | put_score (score *sc) |
107 | { |
102 | { |
108 | static char buf[MAX_BUF]; |
103 | static char buf[MAX_BUF]; |
109 | |
104 | |
110 | sprintf (buf, "%s:%s:%lld:%s:%s:%d:%d:%d", sc->name, sc->title, (long long) sc->exp, sc->killer, sc->maplevel, |
105 | sprintf (buf, "%s:%s:%" PRId64 ":%s:%s:%d:%d:%d", |
|
|
106 | sc->name, sc->title, (sint64)sc->exp, sc->killer, |
111 | sc->maxhp, sc->maxsp, sc->maxgrace); |
107 | sc->maplevel, sc->maxhp, sc->maxsp, sc->maxgrace); |
112 | return buf; |
108 | return buf; |
113 | } |
109 | } |
114 | |
110 | |
115 | /* |
111 | /* |
116 | * The oposite of put_score, get_score reads from the given buffer into |
112 | * The oposite of put_score, get_score reads from the given buffer into |
… | |
… | |
125 | |
121 | |
126 | if ((cp = strchr (bp, '\n')) != NULL) |
122 | if ((cp = strchr (bp, '\n')) != NULL) |
127 | *cp = '\0'; |
123 | *cp = '\0'; |
128 | |
124 | |
129 | if ((cp = spool (bp, "name")) == NULL) |
125 | if ((cp = spool (bp, "name")) == NULL) |
130 | return NULL; |
126 | return 0; |
131 | strncpy (sc.name, cp, BIG_NAME); |
|
|
132 | sc.name[BIG_NAME - 1] = '\0'; |
|
|
133 | |
127 | |
|
|
128 | assign (sc.name, cp); |
|
|
129 | |
134 | if ((cp = spool (NULL, "title")) == NULL) |
130 | if ((cp = spool (0, "title")) == NULL) |
135 | return NULL; |
131 | return 0; |
136 | strncpy (sc.title, cp, BIG_NAME); |
|
|
137 | sc.title[BIG_NAME - 1] = '\0'; |
|
|
138 | |
132 | |
|
|
133 | assign (sc.title, cp); |
|
|
134 | |
139 | if ((cp = spool (NULL, "score")) == NULL) |
135 | if ((cp = spool (0, "score")) == NULL) |
140 | return NULL; |
136 | return 0; |
141 | long long exp; |
|
|
142 | |
137 | |
143 | sscanf (cp, "%lld", &exp); |
138 | sscanf (cp, "%" SCNd64, &sc.exp); |
144 | sc.exp = exp; |
|
|
145 | |
139 | |
146 | if ((cp = spool (NULL, "killer")) == NULL) |
140 | if ((cp = spool (0, "killer")) == NULL) |
147 | return NULL; |
141 | return 0; |
148 | strncpy (sc.killer, cp, BIG_NAME); |
|
|
149 | sc.killer[BIG_NAME - 1] = '\0'; |
|
|
150 | |
142 | |
|
|
143 | assign (sc.killer, cp); |
|
|
144 | |
151 | if ((cp = spool (NULL, "map")) == NULL) |
145 | if ((cp = spool (0, "map")) == NULL) |
152 | return NULL; |
146 | return 0; |
153 | strncpy (sc.maplevel, cp, BIG_NAME); |
|
|
154 | sc.maplevel[BIG_NAME - 1] = '\0'; |
|
|
155 | |
147 | |
|
|
148 | assign (sc.maplevel, cp); |
|
|
149 | |
156 | if ((cp = spool (NULL, "maxhp")) == NULL) |
150 | if ((cp = spool (0, "maxhp")) == NULL) |
157 | return NULL; |
151 | return 0; |
|
|
152 | |
158 | sscanf (cp, "%d", &sc.maxhp); |
153 | sscanf (cp, "%d", &sc.maxhp); |
159 | |
154 | |
160 | if ((cp = spool (NULL, "maxsp")) == NULL) |
155 | if ((cp = spool (0, "maxsp")) == NULL) |
161 | return NULL; |
156 | return 0; |
|
|
157 | |
162 | sscanf (cp, "%d", &sc.maxsp); |
158 | sscanf (cp, "%d", &sc.maxsp); |
163 | |
159 | |
164 | if ((cp = spool (NULL, "maxgrace")) == NULL) |
160 | if ((cp = spool (0, "maxgrace")) == NULL) |
165 | return NULL; |
161 | return 0; |
|
|
162 | |
166 | sscanf (cp, "%d", &sc.maxgrace); |
163 | sscanf (cp, "%d", &sc.maxgrace); |
167 | return ≻ |
164 | return ≻ |
168 | } |
165 | } |
169 | |
166 | |
170 | static char * |
167 | static char * |
… | |
… | |
269 | score *old_score; |
266 | score *old_score; |
270 | |
267 | |
271 | if (op->stats.exp == 0) |
268 | if (op->stats.exp == 0) |
272 | return; |
269 | return; |
273 | |
270 | |
274 | if (!op->contr->name_changed) |
|
|
275 | { |
|
|
276 | if (op->stats.exp > 0) |
|
|
277 | { |
|
|
278 | new_draw_info (NDI_UNIQUE, 0, op, "As you haven't changed your name, you won't"); |
|
|
279 | new_draw_info (NDI_UNIQUE, 0, op, "get into the high-score list."); |
|
|
280 | } |
|
|
281 | return; |
|
|
282 | } |
|
|
283 | if (QUERY_FLAG (op, FLAG_WAS_WIZ)) |
|
|
284 | { |
|
|
285 | new_draw_info (NDI_UNIQUE, 0, op, "Since you have been in wizard mode,"); |
|
|
286 | new_draw_info (NDI_UNIQUE, 0, op, "you can't enter the high-score list."); |
|
|
287 | return; |
|
|
288 | } |
|
|
289 | if (op->contr->explore) |
|
|
290 | { |
|
|
291 | new_draw_info (NDI_UNIQUE, 0, op, "Since you were in explore mode,"); |
|
|
292 | new_draw_info (NDI_UNIQUE, 0, op, "you can't enter the high-score list."); |
|
|
293 | return; |
|
|
294 | } |
|
|
295 | strncpy (new_score.name, op->name, BIG_NAME); |
271 | assign (new_score.name, op->name); |
296 | new_score.name[BIG_NAME - 1] = '\0'; |
272 | assign (new_score.title, op->title.length () ? &op->title : op->contr->title); |
297 | strncpy (new_score.title, op->contr->own_title, BIG_NAME); |
273 | assign (new_score.killer, op->contr->killer[0] ? op->contr->killer : "a dungeon collapse"); |
298 | if (new_score.title[0] == '\0') |
274 | assign (new_score.maplevel, op->map ? op->map->name ? &op->map->name : &op->map->path : ""); |
299 | strncpy (new_score.title, op->contr->title, BIG_NAME); |
275 | |
300 | new_score.title[BIG_NAME - 1] = '\0'; |
|
|
301 | strncpy (new_score.killer, op->contr->killer, BIG_NAME); |
|
|
302 | if (new_score.killer[0] == '\0') |
|
|
303 | strcpy (new_score.killer, "a dungeon collapse"); |
|
|
304 | new_score.killer[BIG_NAME - 1] = '\0'; |
|
|
305 | new_score.exp = op->stats.exp; |
276 | new_score.exp = op->stats.exp; |
306 | if (op->map == NULL) |
|
|
307 | *new_score.maplevel = '\0'; |
|
|
308 | else |
|
|
309 | { |
|
|
310 | strncpy (new_score.maplevel, op->map->name ? op->map->name : op->map->path, BIG_NAME - 1); |
|
|
311 | new_score.maplevel[BIG_NAME - 1] = '\0'; |
|
|
312 | } |
|
|
313 | new_score.maxhp = (int) op->stats.maxhp; |
277 | new_score.maxhp = op->stats.maxhp; |
314 | new_score.maxsp = (int) op->stats.maxsp; |
278 | new_score.maxsp = op->stats.maxsp; |
315 | new_score.maxgrace = (int) op->stats.maxgrace; |
279 | new_score.maxgrace = op->stats.maxgrace; |
|
|
280 | |
316 | if ((old_score = add_score (&new_score)) == NULL) |
281 | if ((old_score = add_score (&new_score)) == NULL) |
317 | { |
282 | { |
318 | new_draw_info (NDI_UNIQUE, 0, op, "Error in the highscore list."); |
283 | new_draw_info (NDI_UNIQUE, 0, op, "Error in the highscore list."); |
319 | return; |
284 | return; |
320 | } |
285 | } |
|
|
286 | |
321 | if (new_score.position == -1) |
287 | if (new_score.position == -1) |
322 | { |
288 | { |
323 | new_score.position = HIGHSCORE_LENGTH + 1; /* Not strictly correct... */ |
289 | new_score.position = HIGHSCORE_LENGTH + 1; /* Not strictly correct... */ |
324 | if (!strcmp (old_score->name, new_score.name)) |
290 | if (!strcmp (old_score->name, new_score.name)) |
325 | new_draw_info (NDI_UNIQUE, 0, op, "You didn't beat your last highscore:"); |
291 | new_draw_info (NDI_UNIQUE, 0, op, "You didn't beat your last highscore:"); |
… | |
… | |
327 | new_draw_info (NDI_UNIQUE, 0, op, "You didn't enter the highscore list:"); |
293 | new_draw_info (NDI_UNIQUE, 0, op, "You didn't enter the highscore list:"); |
328 | new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (old_score)); |
294 | new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (old_score)); |
329 | new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (&new_score)); |
295 | new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (&new_score)); |
330 | return; |
296 | return; |
331 | } |
297 | } |
|
|
298 | |
332 | if (old_score->exp >= new_score.exp) |
299 | if (old_score->exp >= new_score.exp) |
333 | new_draw_info (NDI_UNIQUE, 0, op, "You didn't beat your last score:"); |
300 | new_draw_info (NDI_UNIQUE, 0, op, "You didn't beat your last score:"); |
334 | else |
301 | else |
335 | new_draw_info (NDI_UNIQUE, 0, op, "You beat your last score:"); |
302 | new_draw_info (NDI_UNIQUE, 0, op, "You beat your last score:"); |
336 | |
303 | |
337 | new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (old_score)); |
304 | new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (old_score)); |
338 | new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (&new_score)); |
305 | new_draw_info (NDI_UNIQUE, 0, op, draw_one_high_score (&new_score)); |
339 | } |
306 | } |
340 | |
|
|
341 | |
|
|
342 | |
307 | |
343 | /* displays the high score file. object is the calling object |
308 | /* displays the high score file. object is the calling object |
344 | * (null if being called via command line.) max is the maximum |
309 | * (null if being called via command line.) max is the maximum |
345 | * number of scores to display. match, if set, is the name or class |
310 | * number of scores to display. match, if set, is the name or class |
346 | * to match to. |
311 | * to match to. |
… | |
… | |
391 | } |
356 | } |
392 | /* Replaced what seemed to an overly complicated word wrap method |
357 | /* Replaced what seemed to an overly complicated word wrap method |
393 | * still word wraps, but assumes at most 2 lines of data. |
358 | * still word wraps, but assumes at most 2 lines of data. |
394 | * mw - 2-12-97 |
359 | * mw - 2-12-97 |
395 | */ |
360 | */ |
396 | strncpy (buf, scorebuf, MAX_BUF); |
361 | assign (buf, scorebuf); |
397 | buf[MAX_BUF - 1] = '\0'; |
362 | |
398 | cp = buf; |
363 | cp = buf; |
399 | while (strlen (cp) > maxchar) |
364 | while (strlen (cp) > maxchar) |
400 | { |
365 | { |
401 | bp = cp + maxchar - 1; |
366 | bp = cp + maxchar - 1; |
402 | while (*bp != ' ' && bp > cp) |
367 | while (*bp != ' ' && bp > cp) |
403 | bp--; |
368 | bp--; |
404 | *bp = '\0'; |
369 | *bp = '\0'; |
|
|
370 | |
405 | if (op == NULL) |
371 | if (op == NULL) |
406 | { |
|
|
407 | LOG (llevDebug, "%s\n", cp); |
372 | LOG (llevDebug, "%s\n", cp); |
408 | } |
|
|
409 | else |
373 | else |
410 | { |
|
|
411 | new_draw_info (NDI_UNIQUE, 0, op, cp); |
374 | new_draw_info (NDI_UNIQUE, 0, op, cp); |
412 | } |
375 | |
413 | sprintf (buf, " %s", bp + 1); |
376 | sprintf (buf, " %s", bp + 1); |
414 | cp = buf; |
377 | cp = buf; |
415 | i++; |
378 | i++; |
416 | } |
379 | } |
|
|
380 | |
417 | if (op == NULL) |
381 | if (op == NULL) |
418 | LOG (llevDebug, "%s\n", buf); |
382 | LOG (llevDebug, "%s\n", buf); |
419 | else |
383 | else |
420 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
384 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
421 | } |
385 | } |
|
|
386 | |
422 | close_and_delete (fp, comp); |
387 | close_and_delete (fp, comp); |
423 | } |
388 | } |