/** * Sends quest info to the player on login. * * @param sd Player's data * @return 0 in case of success, nonzero otherwise (i.e. the player has no quests) */ int quest_pc_login(TBL_PC *sd) { int i; if( sd->avail_quests == 0 ) return 1; clif_quest_send_list(sd); clif_quest_send_mission(sd); //@TODO[Haru]: Is this necessary? Does quest_send_mission not take care of this? for( i = 0; i < sd->avail_quests; i++ ) clif_quest_update_objective(sd, &sd->quest_log[i]); return 0; }
void quest_update_objective(TBL_PC * sd, int mob) { int i,j; for( i = 0; i < sd->avail_quests; i++ ) { if( sd->quest_log[i].state != Q_ACTIVE ) continue; for( j = 0; j < MAX_QUEST_OBJECTIVES; j++ ) if( quest_db[sd->quest_index[i]].mob[j] == mob && sd->quest_log[i].count[j] < quest_db[sd->quest_index[i]].count[j] ) { sd->quest_log[i].count[j]++; sd->save_quest = true; clif_quest_update_objective(sd,&sd->quest_log[i],sd->quest_index[i]); } } }
/** * Replaces a quest in a player's list with another one. * @param sd : Player's data * @param qid1 : Current quest to replace * @param qid2 : New quest to add * @return 0 in case of success, nonzero otherwise */ int quest_change(TBL_PC *sd, int qid1, int qid2) { int i; struct quest_db *qi = quest_db(qid2); if( qi == &quest_dummy ) { ShowError("quest_change: quest %d not found in DB.\n", qid2); return -1; } if( quest_check(sd, qid2, HAVEQUEST) >= 0 ) { ShowError("quest_change: Character %d already has quest %d.\n", sd->status.char_id, qid2); return -1; } if( quest_check(sd, qid1, HAVEQUEST) < 0 ) { ShowError("quest_change: Character %d doesn't have quest %d.\n", sd->status.char_id, qid1); return -1; } ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == qid1); if( i == sd->avail_quests ) { ShowError("quest_change: Character %d has completed quest %d.\n", sd->status.char_id, qid1); return -1; } memset(&sd->quest_log[i], 0, sizeof(struct quest)); sd->quest_log[i].quest_id = qi->id; if( qi->time ) sd->quest_log[i].time = (unsigned int)(time(NULL) + qi->time); sd->quest_log[i].state = Q_ACTIVE; sd->save_quest = true; clif_quest_delete(sd, qid1); clif_quest_add(sd, &sd->quest_log[i]); clif_quest_update_objective(sd, &sd->quest_log[i]); if( save_settings&CHARSAVE_QUEST ) chrif_save(sd,0); return 0; }
/** * Adds a quest to the player's list. * New quest will be added as Q_ACTIVE. * @param sd : Player's data * @param quest_id : ID of the quest to add. * @return 0 in case of success, nonzero otherwise */ int quest_add(TBL_PC *sd, int quest_id) { int n; struct quest_db *qi = quest_db(quest_id); if( qi == &quest_dummy ) { ShowError("quest_add: quest %d not found in DB.\n", quest_id); return -1; } if( quest_check(sd, quest_id, HAVEQUEST) >= 0 ) { ShowError("quest_add: Character %d already has quest %d.\n", sd->status.char_id, quest_id); return -1; } n = sd->avail_quests; //Insertion point sd->num_quests++; sd->avail_quests++; RECREATE(sd->quest_log, struct quest, sd->num_quests); //The character has some completed quests, make room before them so that they will stay at the end of the array if( sd->avail_quests != sd->num_quests ) memmove(&sd->quest_log[n + 1], &sd->quest_log[n], sizeof(struct quest) * (sd->num_quests-sd->avail_quests)); memset(&sd->quest_log[n], 0, sizeof(struct quest)); sd->quest_log[n].quest_id = qi->id; if( qi->time ) sd->quest_log[n].time = (unsigned int)(time(NULL) + qi->time); sd->quest_log[n].state = Q_ACTIVE; sd->save_quest = true; clif_quest_add(sd, &sd->quest_log[n]); clif_quest_update_objective(sd, &sd->quest_log[n]); if( save_settings&CHARSAVE_QUEST ) chrif_save(sd,0); return 0; }
/** * Updates the quest objectives for a character after killing a monster. * * @param sd Character's data * @param mob_id Monster ID */ void quest_update_objective(TBL_PC *sd, int mob) { int i, j; for( i = 0; i < sd->avail_quests; i++ ) { struct quest_db *qi = NULL; if( sd->quest_log[i].state != Q_ACTIVE ) // Skip inactive quests continue; qi = quest_search(sd->quest_log[i].quest_id); for( j = 0; j < qi->num_objectives; j++ ) { if( qi->mob[j] == mob && sd->quest_log[i].count[j] < qi->count[j] ) { sd->quest_log[i].count[j]++; sd->save_quest = true; clif_quest_update_objective(sd, &sd->quest_log[i]); } } } }