Hello.
Here's a modified version of the patch which doesn't need changing the subtype for harvesting :) I think / hope it works the same as your patch! :) Best regards Nicolas Le lundi 4 janvier 2021, 13:37:52 CET Preston Crow a écrit : > It's much simpler to have a number that can be used as an array index. > > Splitting the harvesting skills simply means there is a case statement > for each one instead of a single case statement. That's the only change > required.
Index: include/config.h =================================================================== --- include/config.h (révision 21722) +++ include/config.h (copie de travail) @@ -515,7 +515,8 @@ #define TEMPLATE_DIR "template-maps" #define ARCHETYPES "archetypes" #define REGIONS "regions.reg" -#define HIGHSCORE "highscore" +#define OLD_HIGHSCORE "highscore" +#define HIGHSCORE_DIR "highscores" #define TREASURES "treasures" #define BANISHFILE "banish_file" Index: server/c_misc.c =================================================================== --- server/c_misc.c (révision 21722) +++ server/c_misc.c (copie de travail) @@ -874,7 +874,7 @@ * @param op * player asking for information. * @param params - * unused. + * options for the hiscore command (typically a match for the names) */ void command_hiscore(object *op, const char *params) { hiscore_display(op, op == NULL ? 9999 : 50, params); Index: server/hiscore.c =================================================================== --- server/hiscore.c (révision 21722) +++ server/hiscore.c (copie de travail) @@ -21,6 +21,8 @@ #include <errno.h> #include <string.h> +#include <sys/stat.h> +#include <sys/types.h> #include "sproto.h" #include "output_file.h" @@ -45,13 +47,15 @@ */ typedef struct { char fname[MAX_BUF]; /**< Filename of the backing file. */ + char skill_name[MAX_BUF]; /**< The name of the skill or "Overall". */ score entry[HIGHSCORE_LENGTH]; /**< The entries in decreasing exp order. */ } score_table; /** * The highscore table. Unused entries are set to zero (except for position). */ -static score_table hiscore_table; +static score_table hiscore_tables[MAX_SKILLS+1]; // One for each skill, plus one for overall +//#define hiscore_table hiscore_tables[0] // Overall score /** * Writes the given score structure to specified buffer. @@ -159,7 +163,11 @@ if (strcmp(sc->killer, "quit") == 0 || strcmp(sc->killer, "left") == 0) { s1 = sc->killer; s2 = "the game"; - } else { + } else if ( strcmp(sc->killer,"a dungeon collapse") == 0 ) { + s1 = "was last"; + s2 = "seen"; + } + else { s1 = "was killed by"; s2 = sc->killer; } @@ -282,10 +290,46 @@ /** * Initializes the module. + * + * @note + * There is one table per skill, as well as the "Overall" table, each saved in a file + * in .../var/crossfire/hiscores/[skill_name] or as configured in config.h. */ void hiscore_init(void) { - snprintf(hiscore_table.fname, sizeof(hiscore_table.fname), "%s/%s", settings.localdir, HIGHSCORE); - hiscore_load(&hiscore_table); + char dirname[MAX_BUF]; + + snprintf(dirname, sizeof(dirname), "%s/%s", settings.localdir, HIGHSCORE_DIR); + mkdir(dirname,0755); + memset(hiscore_tables,0,sizeof(hiscore_tables)); + for (int i=-1;i<MAX_SKILLS;++i) { + const char *name; + int subtype; + + /* + * This gets complicated because the skills are defined internally by the subtype in + * the skill object, but our list of skill names is in the order the skills are + * initialized in. + */ + if ( i == -1 ) { + name = "Overall"; + subtype = 0; + } else { + name = skill_names[i]; + if ( !name || !*name ) continue; // No such skill + subtype = get_skill_client_code(name) + 1; + } + snprintf(hiscore_tables[subtype].fname, sizeof(hiscore_tables[subtype].fname), "%s/%s/%s", settings.localdir, HIGHSCORE_DIR,name); + for ( char *c = hiscore_tables[subtype].fname;*c;++c ) { + if ( *c == ' ' ) *c='_'; /* avoid spaces in file names */ + } + strncpy(hiscore_tables[subtype].skill_name,name,sizeof(hiscore_tables[subtype].skill_name)); + hiscore_load(&hiscore_tables[subtype]); + } + /* Load legacy highscore file if new one was blank */ + if ( hiscore_tables[0].entry[0].exp == 0 ) { + snprintf(hiscore_tables[0].fname, sizeof(hiscore_tables[0].fname), "%s/%s", settings.localdir, OLD_HIGHSCORE); + hiscore_load(&hiscore_tables[0]); + } } /** @@ -328,7 +372,6 @@ if (new_score.killer[0] == '\0') strcpy(new_score.killer, "a dungeon collapse"); new_score.killer[BIG_NAME-1] = '\0'; - new_score.exp = op->stats.exp; if (op->map == NULL) *new_score.maplevel = '\0'; else { @@ -338,7 +381,25 @@ new_score.maxhp = (int)op->stats.maxhp; new_score.maxsp = (int)op->stats.maxsp; new_score.maxgrace = (int)op->stats.maxgrace; - add_score(&hiscore_table, &new_score, &old_score); + FOR_INV_PREPARE(op, tmp) { + if ( tmp->type != SKILL ) continue; + if ( !tmp->stats.exp ) continue; + new_score.exp = tmp->stats.exp; + add_score(&hiscore_tables[get_skill_client_code(tmp->name) + 1], &new_score, &old_score); + if ( 0 && !quiet && new_score.exp > old_score.exp ) { + draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, + "You improved your rating in %s: %"FMT64"",tmp->name,new_score.exp); +#if 0 // This is too verbose + if (old_score.position != -1) + draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, + draw_one_high_score(&old_score, bufscore, sizeof(bufscore))); + draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, + draw_one_high_score(&new_score, bufscore, sizeof(bufscore))); +#endif + } + } FOR_INV_FINISH(); + new_score.exp = op->stats.exp; + add_score(&hiscore_tables[0], &new_score, &old_score); // overall /* Everything below here is just related to print messages * to the player. If quiet is set, we can just return @@ -378,29 +439,91 @@ * maximum number of scores to display. * @param match * if non-empty, will only print players with name or title containing the string (non case-sensitive). + * Other options: -s:[name] -- show the table for the skill 'name' instead of overall + * -s -- show a short list for each skill */ void hiscore_display(object *op, int max, const char *match) { int printed_entries; size_t j; + int skill_match = 0; + int skill_min,skill_max; + int len; + + /* check for per-skill instead of overall report */ + if ( match && strncmp(match,"-s",2)==0 ) { + match += 2; + if ( *match == ':' ) { + ++match; + if ( strchr(match,' ') ) { + len = strchr(match,' ') - match; + } + else len = strlen(match); + for (int i=1;i<MAX_SKILLS;++i) { + if ( strncmp(match,hiscore_tables[i].skill_name,len) == 0 ) { + skill_match = i; + break; + } + } + if ( !skill_match ) { + draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, + "Could not match '%.*s' to a skill",len,match); + return; + } + match += len; + } + else { + skill_match = -1; // flag to show all skills + if ( max < 100 && max > 10 ) max = 10; // Less output per skill + } + } + while ( *match == ' ' ) ++match; - draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, - "[fixed]Nr Score [print] Who <max hp><max sp><max grace>"); + skill_min = skill_max = skill_match; + if ( skill_match == -1 ) { + skill_min = 1; + skill_max = MAX_SKILLS; + } - printed_entries = 0; - for (j = 0; j < HIGHSCORE_LENGTH && hiscore_table.entry[j].name[0] != '\0' && printed_entries < max; j++) { - char scorebuf[MAX_BUF]; - - if (*match != '\0' - && !strcasestr_local(hiscore_table.entry[j].name, match) - && !strcasestr_local(hiscore_table.entry[j].title, match)) - continue; + /* + * Check all skills in skill_names[] order (which should be alphabetical) + */ + for ( int s = -1; s <= MAX_SKILLS; ++s ) { + int skill = s + 1; - draw_one_high_score(&hiscore_table.entry[j], scorebuf, sizeof(scorebuf)); - printed_entries++; + if ( skill < skill_min || skill > skill_max ) continue; + + if ( hiscore_tables[skill].skill_name[0] == 0 ) { + continue; // No such skill + } + if ( hiscore_tables[skill].entry[0].exp == 0 ) { + continue; // No entries for this skill + } + if ( skill == 0 ) { + draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, + "Overall high scores:"); + } else { + draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, + "High scores for the skill [color=red]%s[/color]:",hiscore_tables[skill].skill_name); + } + draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, + "[fixed]Rank Score [print]Who <max hp><max sp><max grace>"); - if (op == NULL) - LOG(llevDebug, "%s\n", scorebuf); - else - draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, scorebuf); + printed_entries = 0; + for (j = 0; j < HIGHSCORE_LENGTH && hiscore_tables[skill].entry[j].name[0] != '\0' && printed_entries < max; j++) { + char scorebuf[MAX_BUF]; + + if (*match != '\0' + && !strcasestr_local(hiscore_tables[skill].entry[j].name, match) + && !strcasestr_local(hiscore_tables[skill].entry[j].title, match)) + continue; + + draw_one_high_score(&hiscore_tables[skill].entry[j], scorebuf, sizeof(scorebuf)); + printed_entries++; + + if (op == NULL) + LOG(llevDebug, "%s\n", scorebuf); + else + draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_HISCORE, scorebuf); + } } } Index: . =================================================================== --- . (révision 21722) +++ . (copie de travail) Modification de propriétés sur . ___________________________________________________________________ Modified: svn:ignore ## -16,3 +16,4 ## .git .dep.inc .gitignore +build
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ crossfire mailing list crossfire@metalforge.org http://mailman.metalforge.org/mailman/listinfo/crossfire