Index: common/quest.c =================================================================== RCS file: /cvsroot/crossfire/crossfire/common/quest.c,v retrieving revision 1.5 diff -C5 -r1.5 quest.c *** common/quest.c 13 Oct 2005 07:22:43 -0000 1.5 --- common/quest.c 15 Nov 2005 02:15:00 -0000 *************** *** 35,45 **** #include #ifndef __CEXTRACT__ #include #endif #include - #include "quest.h" #define QUEST_NAME( op ) op->name_pl #define TASK_NAME( op ) op->custom_name #if 0 --- 35,44 ---- *************** *** 69,78 **** --- 68,167 ---- return 0; return 1; } #endif + /* Called during server startup */ + void init_questhints() { + FILE *fp; + char filename[MAX_BUF]; + int comp; + + if(first_questhint!=NULL) /* Only do this once */ + return; + + sprintf(filename,create_pathname(QUESTHINT_PATH)); + LOG(llevDebug,"Reading questhints from %s...", filename); + if((fp=open_and_uncompress(filename,0,&comp))==NULL) { + LOG(llevError," Can't open questhints file %s in init_questhints.\n", filename); + return; + } + char buf[HUGE_BUF], fields[7][HUGE_BUF]; + int msgpos=0; + questhint *new, *quest; + + while (fgets(buf, HUGE_BUF-1, fp)!=NULL) { + if (sscanf(buf,"%[^:]:%[^:]:%[^:]:%[^:]:%[^:]:%[^:]:%[^\n]\n", + fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6])!=7) { + LOG(llevError,"Warning - malformed quest hint entry: %s\n", buf); + continue; + } + new = malloc(sizeof(questhint)); + new->markername = strdup_local(fields[0]); + new->minlevel = atoi(fields[1]); + new->midlevel = atoi(fields[2]); + new->maxlevel = atoi(fields[3]); + new->reg = get_region_by_name(fields[4]); + new->chance = atoi(fields[5]); + new->text = strdup_local(fields[6]); + /* find the last questhint in the list, and append to it */ + for (quest=first_questhint; quest!=NULL && quest->next!=NULL; quest=quest->next); + if (!quest) first_questhint=new; + else quest->next=new; + new = NULL; + } + close_and_delete(fp, comp); + LOG(llevDebug,"done.\n"); + } + + typedef struct quest_values { + questhint *quest; + uint8 value; + } quest_values; + + /* returns a string pointer to an appropriate quest hint for the given player */ + const char *get_questhint(object *pl) { + questhint *quest; + quest_values questvalues[1000]; + int questhint_value; + int questcount=0; + int value_total = 0; + int quest_result, i; + if (!pl || pl->type != PLAYER) return NULL; + if (!first_questhint) return NULL; + for (quest = first_questhint; quest!=NULL; quest=quest->next) { + questhint_value = get_questhint_value(quest, pl); + if (questhint_value > 0) { + questvalues[questcount].quest = quest; + value_total += questhint_value; + questvalues[questcount].value =value_total; + questcount++; + } + } + quest_result = rndm(1, value_total); + for (i = 0; i = quest_result) + return questvalues[i].quest->text; + } + return NULL; + } + + /* Given a questhint, tells us how good it is that the player should be given this hint. + * zero means that it is a bad hint to give the player + */ + uint8 get_questhint_value(questhint *quest, object *pl) { + int level; + if (!pl || pl->type != PLAYER || !quest) return 0; + level = pl->level; + if (level < quest->minlevel || level > quest->maxlevel) + return 0; + if ( region_is_child_of_region(pl->map->region, quest->reg) != 1) + return 0; + /* Note we aren't yet checking that the player is on the quest already, that should go here eventually */ + return quest->chance; + } + int quest_is_quest_marker( object* marker, int task ) { if ( marker->type != QUEST ) return 0; if ( task && !TASK_NAME(marker) ) Index: include/global.h =================================================================== RCS file: /cvsroot/crossfire/crossfire/include/global.h,v retrieving revision 1.61 diff -C5 -r1.61 global.h *** include/global.h 24 Oct 2005 20:48:15 -0000 1.61 --- include/global.h 15 Nov 2005 02:15:05 -0000 *************** *** 155,164 **** --- 155,167 ---- #include "recipe.h" /* Now for spells */ #include "spells.h" + /* Now for quests */ + #include "quest.h" + #include "funcpoint.h" /***************************************************************************** * GLOBAL VARIABLES: * *****************************************************************************/ *************** *** 175,184 **** --- 178,188 ---- EXTERN artifactlist *first_artifactlist; EXTERN archetype *first_archetype; EXTERN objectlink *first_friendly_object; /* Objects monsters will go after */ EXTERN godlink *first_god; EXTERN racelink *first_race; + EXTERN questhint *first_questhint; #define NROF_COMPRESS_METHODS 4 EXTERN char *uncomp[NROF_COMPRESS_METHODS][3]; /* * The editor uses these (will get them out of here later): Index: include/libproto.h =================================================================== RCS file: /cvsroot/crossfire/crossfire/include/libproto.h,v retrieving revision 1.82 diff -C5 -r1.82 libproto.h *** include/libproto.h 1 Nov 2005 10:08:17 -0000 1.82 --- include/libproto.h 15 Nov 2005 02:15:05 -0000 *************** *** 274,283 **** --- 274,286 ---- /* player.c */ extern void free_player(player *pl); extern int atnr_is_dragon_enabled(int attacknr); extern int is_dragon_pl(object *op); /* quest.c */ + extern void init_questhints(); + extern const char *get_questhint(object *pl); + extern uint8 get_questhint_value(questhint *quest, object *pl); extern int quest_is_quest_marker(object *marker, int task); extern int quest_is_in_progress(object *marker, int task); extern int quest_is_completed(object *marker, int task); extern const char *quest_get_name(object *marker); extern object *quest_get_player_quest(object *pl, const char *name, const char *name_pl); Index: include/quest.h =================================================================== RCS file: /cvsroot/crossfire/crossfire/include/quest.h,v retrieving revision 1.1 diff -C5 -r1.1 quest.h *** include/quest.h 14 Jul 2005 16:21:32 -0000 1.1 --- include/quest.h 15 Nov 2005 02:15:05 -0000 *************** *** 7,11 **** --- 7,25 ---- #define QUEST_START " start" /* End of slaying field of force indicating a completed quest */ #define QUEST_END " end" #endif /* QUEST_H */ + + #define QUESTHINT_PATH "quests/hints" + + /* Quest hint definition */ + typedef struct quest_hint { + const char *markername; + uint8 minlevel; + uint8 midlevel; + uint8 maxlevel; + uint8 chance; + const region *reg; + const char *text; + struct quest_hint *next; + } questhint; Index: server/init.c =================================================================== RCS file: /cvsroot/crossfire/crossfire/server/init.c,v retrieving revision 1.69 diff -C5 -r1.69 init.c *** server/init.c 28 Oct 2005 19:08:53 -0000 1.69 --- server/init.c 15 Nov 2005 02:15:12 -0000 *************** *** 769,778 **** --- 769,779 ---- init_archetype_pointers(); /* Setup global pointers to archetypes */ init_races(); /* overwrite race designations using entries in lib/races file */ init_gods(); /* init linked list of gods from archs*/ init_readable(); /* inits useful arrays for readable texts */ init_formulae(); /* If not called before, reads formulae from file */ + init_questhints(); /* used to lead players vaguely towards quests */ switch(settings.dumpvalues) { case 1: print_monsters(); exit(0); Index: server/monster.c =================================================================== RCS file: /cvsroot/crossfire/crossfire/server/monster.c,v retrieving revision 1.95 diff -C5 -r1.95 monster.c *** server/monster.c 9 Nov 2005 19:34:17 -0000 1.95 --- server/monster.c 15 Nov 2005 02:15:20 -0000 *************** *** 1505,1519 **** { const char *cp=msg, *cp1, *cp2; char *cp3, regex[MAX_BUF], gotmatch=0; while (1) { ! if (strncmp(cp, "@match ", 7)) { ! LOG(llevDebug,"find_matching_message: Invalid message %s", msg); ! return NULL; ! } ! else { /* Find the end of the line, and copy the regex portion into it */ cp2 = strchr(cp+7, '\n'); strncpy(regex, cp+7, (cp2 - cp -7 )); regex[cp2 - cp -7] = 0; --- 1505,1515 ---- { const char *cp=msg, *cp1, *cp2; char *cp3, regex[MAX_BUF], gotmatch=0; while (1) { ! if (!strncmp(cp, "@match ", 7)) { /* Find the end of the line, and copy the regex portion into it */ cp2 = strchr(cp+7, '\n'); strncpy(regex, cp+7, (cp2 - cp -7 )); regex[cp2 - cp -7] = 0; *************** *** 1554,1563 **** --- 1550,1567 ---- } gotmatch = 0; if (cp1) cp = cp1 + 1; else return NULL; } + else if (!strncmp(cp, "@questhint", 10)) { + cp3 = strdup_local(get_questhint(pl)); + return cp3; + } + else { + LOG(llevDebug,"find_matching_message: Invalid message %s", msg); + return NULL; + } } /* Should never get reached */ } /* This function looks for an object or creature that is listening.