diff options
author | Inkfish <Inkfish@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2009-07-25 20:55:35 +0000 |
---|---|---|
committer | Inkfish <Inkfish@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2009-07-25 20:55:35 +0000 |
commit | 34b37179c0895f0b0acc4377bf2bfe5edfcff9ce (patch) | |
tree | d650d9bc108404fa0949d5ec2754d96cde31926b | |
parent | a93b8b9c2537bd8359d647ae23e90d084d019535 (diff) | |
download | hercules-34b37179c0895f0b0acc4377bf2bfe5edfcff9ce.tar.gz hercules-34b37179c0895f0b0acc4377bf2bfe5edfcff9ce.tar.bz2 hercules-34b37179c0895f0b0acc4377bf2bfe5edfcff9ce.tar.xz hercules-34b37179c0895f0b0acc4377bf2bfe5edfcff9ce.zip |
Rewrote Quest Log system.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13959 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r-- | Changelog-Trunk.txt | 2 | ||||
-rw-r--r-- | conf/inter_athena.conf | 3 | ||||
-rw-r--r-- | db/const.txt | 4 | ||||
-rw-r--r-- | db/packet_db.txt | 4 | ||||
-rw-r--r-- | doc/script_commands.txt | 54 | ||||
-rw-r--r-- | src/char_sql/char.c | 5 | ||||
-rw-r--r-- | src/char_sql/char.h | 1 | ||||
-rw-r--r-- | src/char_sql/int_quest.c | 115 | ||||
-rw-r--r-- | src/char_sql/inter.c | 2 | ||||
-rw-r--r-- | src/common/mmo.h | 21 | ||||
-rw-r--r-- | src/map/chrif.c | 2 | ||||
-rw-r--r-- | src/map/clif.c | 91 | ||||
-rw-r--r-- | src/map/clif.h | 3 | ||||
-rw-r--r-- | src/map/intif.c | 39 | ||||
-rw-r--r-- | src/map/intif.h | 1 | ||||
-rw-r--r-- | src/map/map.c | 2 | ||||
-rw-r--r-- | src/map/mob.c | 4 | ||||
-rw-r--r-- | src/map/pc.h | 6 | ||||
-rw-r--r-- | src/map/quest.c | 303 | ||||
-rw-r--r-- | src/map/quest.h | 27 | ||||
-rw-r--r-- | src/map/script.c | 77 |
21 files changed, 504 insertions, 262 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 625a5bd83..cefedfa91 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,8 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. +09/07/25 + * Rewrote Quest Log system. 09/07/21 * Added proper bounds of INT_MIN to INT_MAX for hp/sp when being sent to/from status_damage/status_heal for negative values because of INT_MAX being (-INT_MIN - 1). [Paradox924X] 09/07/17 diff --git a/conf/inter_athena.conf b/conf/inter_athena.conf index e7fe1a3bd..bd2176a56 100644 --- a/conf/inter_athena.conf +++ b/conf/inter_athena.conf @@ -120,8 +120,7 @@ pet_db: pet friend_db: friends mail_db: mail auction_db: auction -quest_db: quest -quest_obj_db: quest_objective +quest_db: questlog // Map Database Tables item_db_db: item_db diff --git a/db/const.txt b/db/const.txt index 0698bba85..1e667f204 100644 --- a/db/const.txt +++ b/db/const.txt @@ -1781,3 +1781,7 @@ TW_TOWER 812 4_M_MOCASS1 997 4_M_MOCASS2 998 4_M_MUT1 999 + +HAVEQUEST 0 +PLAYTIME 1 +HUNTING 2 diff --git a/db/packet_db.txt b/db/packet_db.txt index cd6eae1d9..540d92c23 100644 --- a/db/packet_db.txt +++ b/db/packet_db.txt @@ -1003,7 +1003,7 @@ packet_ver: 22 0x02b3,107 0x02b4,6 0x02b5,-1 -0x02b6,7 +0x02b6,7,queststate,2:6 0x02b7,7 0x02b8,22 0x02b9,191 @@ -1017,7 +1017,7 @@ packet_ver: 22 0x02c4,26,partyinvite2,2 0x02c5,30 0x02c6,30 -0x02c7,7,replypartyinvite2,2,6 +0x02c7,7,replypartyinvite2,2:6 0x02c8,3 0x02c9,3 0x02ca,3 diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 3b2fab576..880167797 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -130,6 +130,8 @@ //= Extended the behaviour of duplicates (warps/shops/cashshops). [FlavioJS] //= 3.26.20090702 //= Replaced 'bonusautoscript' by 'autobonus'. [Inkfish] +//= 3.27.20090725 +//= Added Quest Log related commands. [Inkfish] //========================================================= This document is a reference manual for all the scripting commands and functions @@ -6527,5 +6529,57 @@ instance times out while inactive. --------------------------------------- +======================== +|8.- Quest Log commands.| +======================== +--------------------------------------- + +*setquest <ID>; + +Place quest of <ID> in the users quest log, the state of which is "active". + +--------------------------------------- + +*completequest <ID>; + +Change the state for the given quest <ID> to "complete" and remove from the users quest log. + +--------------------------------------- + +*erasequest <ID>; + +Remove the quest of the given <ID> from the user's quest log. + +--------------------------------------- + +*changequest <ID>,<ID2>; + +Remove quest of the given <ID> from the user's quest log, and change state to "complete". +Add quest of the <ID2> to the the quest log, and the state is "active". + +--------------------------------------- + +checkquest(<ID>{,PLAYTIME|HUNTING}); + +If no additonal argument supplied, return the state of the quest: + -1 = Quest not started (not in quest log) + 0 = Quest has been given, but the state is "inactive" + 1 = Quest has been given, and the state is "active" + 2 = Quest comepleted + +If parameter "PLAYTIME" is supplied: + -1 = Quest not started (not in quest log) + 0 = the time limit has not yet been reached + 1 = the time limit has not been reached but the quest is marked as complete + 2 = the time limit has been reached + +If parameter "HUNTING" is supplied: + -1 = Quest not started (not in quest log) + 0 = you haven't killed all of the target monsters and the time limit has not been reached. + 1 = you haven't killed all of the target monsters but the time limit has been reached. + 2 = you've killed all of the target monsters + +--------------------------------------- + Whew. That's about all of them. diff --git a/src/char_sql/char.c b/src/char_sql/char.c index d0e5643cc..fe9025935 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -58,8 +58,7 @@ char mail_db[256] = "mail"; // MAIL SYSTEM char auction_db[256] = "auction"; // Auctions System char friend_db[256] = "friends"; char hotkey_db[256] = "hotkey"; -char quest_db[256] = "quest"; -char quest_obj_db[256] = "quest_objective"; +char quest_db[256] = "questlog"; //If your code editor is having problems syntax highlighting this file, uncomment this and RECOMMENT IT BEFORE COMPILING //#undef TXT_SQL_CONVERT @@ -3639,8 +3638,6 @@ void sql_config_read(const char* cfgName) strcpy(hotkey_db,w2); else if(!strcmpi(w1,"quest_db")) strcpy(quest_db,w2); - else if(!strcmpi(w1,"quest_obj_db")) - strcpy(quest_obj_db, w2); #ifndef TXT_SQL_CONVERT else if(!strcmpi(w1,"db_path")) strcpy(db_path,w2); diff --git a/src/char_sql/char.h b/src/char_sql/char.h index 33c4544b2..a40340cfb 100644 --- a/src/char_sql/char.h +++ b/src/char_sql/char.h @@ -59,7 +59,6 @@ extern char pet_db[256]; extern char mail_db[256]; extern char auction_db[256]; extern char quest_db[256]; -extern char quest_obj_db[256]; extern int db_use_sqldbs; // added for sql item_db read for char server [Valaris] diff --git a/src/char_sql/int_quest.c b/src/char_sql/int_quest.c index 53c2d3cda..5c59a5ba0 100644 --- a/src/char_sql/int_quest.c +++ b/src/char_sql/int_quest.c @@ -20,10 +20,8 @@ //Load entire questlog for a character int mapif_quests_fromsql(int char_id, struct quest questlog[]) { - - int count, i, j, num; + int i; struct quest tmp_quest; - struct quest_objective tmp_quest_objective; SqlStmt * stmt; stmt = SqlStmt_Malloc(sql_handle); @@ -34,42 +32,29 @@ int mapif_quests_fromsql(int char_id, struct quest questlog[]) } memset(&tmp_quest, 0, sizeof(struct quest)); - memset(&tmp_quest_objective, 0, sizeof(struct quest_objective)); - if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `quest_id`, `state` FROM `%s` WHERE `char_id`=? LIMIT %d", quest_db, MAX_QUEST) + if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `quest_id`, `state`, `time`, `mob1`, `count1`, `mob2`, `count2`, `mob3`, `count3` FROM `%s` WHERE `char_id`=? LIMIT %d", quest_db, MAX_QUEST) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_quest.quest_id, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &tmp_quest.state, 0, NULL, NULL) ) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &tmp_quest.state, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_UINT, &tmp_quest.time, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_INT, &tmp_quest.mob[0], 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_INT, &tmp_quest.count[0], 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 5, SQLDT_INT, &tmp_quest.mob[1], 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_INT, &tmp_quest.count[1], 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 7, SQLDT_INT, &tmp_quest.mob[2], 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 8, SQLDT_INT, &tmp_quest.count[2], 0, NULL, NULL) ) SqlStmt_ShowDebug(stmt); for( i = 0; i < MAX_QUEST && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) { memcpy(&questlog[i], &tmp_quest, sizeof(tmp_quest)); + questlog[i].num_objectives = (!questlog[i].mob[0] ? 0 : !questlog[i].mob[1] ? 1 : !questlog[i].mob[2] ? 2 : 3); } - count = i; - - for( i = 0; i < count; ++i ) - { - if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `num`, `name`, `count` FROM `%s` WHERE `char_id`=? AND `quest_id`=? LIMIT %d", quest_obj_db, MAX_QUEST_OBJECTIVES) - || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) - || SQL_ERROR == SqlStmt_BindParam(stmt, 1, SQLDT_INT, &questlog[i].quest_id, 0) - || SQL_ERROR == SqlStmt_Execute(stmt) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &num, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_STRING, &tmp_quest_objective.name, NAME_LENGTH, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_INT, &tmp_quest_objective.count, 0, NULL, NULL) ) - SqlStmt_ShowDebug(stmt); - - for( j = 0; j < MAX_QUEST && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++j ) - { - memcpy(&questlog[i].objectives[num], &tmp_quest_objective, sizeof(struct quest_objective)); - } - questlog[i].num_objectives = j; - - } SqlStmt_Free(stmt); - return count; + return i; } //Delete a quest @@ -86,12 +71,6 @@ int mapif_parse_quest_delete(int fd) success = false; } - if ( success && SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_obj_db, quest_id, char_id) ) - { - Sql_ShowDebug(sql_handle); - success = false; - } - WFIFOHEAD(fd,11); WFIFOW(fd,0) = 0x3862; WFIFOL(fd,2) = char_id; @@ -111,13 +90,11 @@ int mapif_parse_quest_add(int fd) bool success = true; int char_id = RFIFOL(fd,4); struct quest qd; - int i; memcpy(&qd, RFIFOP(fd,8), RFIFOW(fd,2)-8); StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`) VALUES ('%d', '%d', '%d')", quest_db, qd.quest_id, char_id, qd.state); - + StringBuf_Printf(&buf, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`, `time`, `mob1`, `count1`, `mob2`, `count2`, `mob3`, `count3`) VALUES ('%d', '%d', '%d','%d', '%d', '%d', '%d', '%d', '%d', '%d')", quest_db, qd.quest_id, char_id, qd.state, qd.time, qd.mob[0], qd.count[0], qd.mob[1], qd.count[1], qd.mob[2], qd.count[2]); if ( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { @@ -125,22 +102,41 @@ int mapif_parse_quest_add(int fd) success = false; } - for(i=0; i<qd.num_objectives && success; i++) - { + WFIFOHEAD(fd,11); + WFIFOW(fd,0) = 0x3861; + WFIFOL(fd,2) = char_id; + WFIFOL(fd,6) = qd.quest_id; + WFIFOB(fd,10) = success?1:0; + WFIFOSET(fd,11); - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s`(`quest_id`, `char_id`, `num`, `name`, `count`) VALUES ('%d', '%d', '%d', '%s', '%d')", - quest_obj_db, qd.quest_id, char_id, i, qd.objectives[i].name, qd.objectives[i].count); + StringBuf_Destroy(&buf); - if ( success && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) - { - Sql_ShowDebug(sql_handle); - success = false; - } + return 0; + +} + +//Update a questlog +int mapif_parse_quest_update(int fd) +{ + + StringBuf buf; + bool success = true; + int char_id = RFIFOL(fd,4); + struct quest qd; + + memcpy(&qd, RFIFOP(fd,8), RFIFOW(fd,2)-8); + + StringBuf_Init(&buf); + StringBuf_Printf(&buf, "UPDATE `%s` SET `state`='%d', `count1`='%d', `count2`='%d', `count3`='%d' WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, qd.state, qd.count[0], qd.count[1], qd.count[2], qd.quest_id, char_id); + + if ( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + { + Sql_ShowDebug(sql_handle); + success = false; } WFIFOHEAD(fd,11); - WFIFOW(fd,0) = 0x3861; + WFIFOW(fd,0) = 0x3863; WFIFOL(fd,2) = char_id; WFIFOL(fd,6) = qd.quest_id; WFIFOB(fd,10) = success?1:0; @@ -155,14 +151,12 @@ int mapif_parse_quest_add(int fd) //Send questlog to map server int mapif_send_quests(int fd, int char_id) { - struct quest tmp_questlog[MAX_QUEST]; - int num_quests, i; + int num_quests, i, num_complete = 0; + int complete[MAX_QUEST]; - for(i=0; i<MAX_QUEST; i++) - { - memset(&tmp_questlog[i], 0, sizeof(struct quest)); - } + memset(tmp_questlog, 0, sizeof(tmp_questlog)); + memset(complete, 0, sizeof(complete)); num_quests = mapif_quests_fromsql(char_id, tmp_questlog); @@ -171,11 +165,21 @@ int mapif_send_quests(int fd, int char_id) WFIFOW(fd,2) = num_quests*sizeof(struct quest)+8; WFIFOL(fd,4) = char_id; - for(i=0; i<num_quests; i++) + //Active and inactive quests + for( i = 0; i < num_quests; i++ ) { - memcpy(WFIFOP(fd,i*sizeof(struct quest)+8), &tmp_questlog[i], sizeof(struct quest)); + if( tmp_questlog[i].state == Q_COMPLETE ) + { + complete[num_complete++] = i; + continue; + } + memcpy(WFIFOP(fd,(i-num_complete)*sizeof(struct quest)+8), &tmp_questlog[i], sizeof(struct quest)); } + // Completed quests + for( i = num_quests - num_complete; i < num_quests; i++ ) + memcpy(WFIFOP(fd,i*sizeof(struct quest)+8), &tmp_questlog[complete[i-num_quests+num_complete]], sizeof(struct quest)); + WFIFOSET(fd,num_quests*sizeof(struct quest)+8); return 0; @@ -196,6 +200,7 @@ int inter_quest_parse_frommap(int fd) case 0x3060: mapif_parse_loadquestrequest(fd); break; case 0x3061: mapif_parse_quest_add(fd); break; case 0x3062: mapif_parse_quest_delete(fd); break; + case 0x3063: mapif_parse_quest_update(fd); break; default: return 0; } diff --git a/src/char_sql/inter.c b/src/char_sql/inter.c index 5c8d30c54..5b61ab281 100644 --- a/src/char_sql/inter.c +++ b/src/char_sql/inter.c @@ -51,7 +51,7 @@ int inter_recv_packet_length[] = { -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1, // 3030- 5, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040- -1,-1,10,10, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus] - 6,-1,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] + 6,-1,10,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish] -1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3070- Mercenary packets [Zephyrus] 48,14,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3080- -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator] diff --git a/src/common/mmo.h b/src/common/mmo.h index 933893697..029f5e115 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -50,7 +50,7 @@ #define MAX_GUILDCASTLE 34 // Updated to include new entries for WoE:SE. [L0ne_W0lf] #define MAX_GUILDLEVEL 50 #define MAX_GUARDIANS 8 //Local max per castle. [Skotlex] -#define MAX_QUEST 25 //Max quests for a PC +#define MAX_QUEST_DB 500 //Max quests that the server will load #define MAX_QUEST_OBJECTIVES 3 //Max quest objectives for a quest #define MIN_HAIR_STYLE battle_config.min_hair_style @@ -126,24 +126,17 @@ enum item_types { }; -//Questlog system [Kevin] -typedef enum quest_state { Q_INACTIVE, Q_ACTIVE } quest_state; - -struct quest_objective { - - char name[NAME_LENGTH]; - int count; - -}; +//Questlog system [Kevin] [Inkfish] +typedef enum quest_state { Q_INACTIVE, Q_ACTIVE, Q_COMPLETE } quest_state; struct quest { - int quest_id; + unsigned int time; + int mob[MAX_QUEST_OBJECTIVES]; + int count[MAX_QUEST_OBJECTIVES]; quest_state state; - int num_objectives; - int time; - struct quest_objective objectives[MAX_QUEST_OBJECTIVES]; + int num_objectives; }; struct item { diff --git a/src/map/chrif.c b/src/map/chrif.c index aba1accee..63aa5dac0 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -288,6 +288,8 @@ int chrif_save(struct map_session_data *sd, int flag) merc_save(sd->hd); if( sd->md && mercenary_get_lifetime(sd->md) > 0 ) mercenary_save(sd->md); + if( sd->num_quests ) + quest_save(sd); return 0; } diff --git a/src/map/clif.c b/src/map/clif.c index 855d4c6f0..783a3d399 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -8189,8 +8189,6 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) mail_clear(sd); #endif - quest_pc_login(sd); - if(map[sd->bl.m].flag.loadevent) // Lance npc_script_event(sd, NPCE_LOADMAP); @@ -12548,39 +12546,28 @@ void clif_parse_EquipTick(int fd, struct map_session_data* sd) } /*========================================== - * Questlog System [Kevin] - * 02B5 <packet_len>.W <ignored>.L { }.10B* <-- UNKOWN PACKET - * 02B6 <quest_id>.L <state>.B + * Questlog System [Kevin] [Inkfish] *------------------------------------------*/ - -void clif_parse_questStateAck(int fd, struct map_session_data * sd) -{ - -} - //Send simple list of quests upon login //* 02B1 <packet_len>.W <ignored>.L { <quest_id>.L <state>.B }.5B* void clif_send_questlog(struct map_session_data * sd) { int fd = sd->fd; int i; + int len = sd->avail_quests*5+8; - WFIFOHEAD(fd,sd->num_quests*5+8); + WFIFOHEAD(fd,len); WFIFOW(fd, 0) = 0x02B1; - WFIFOW(fd, 2) = sd->num_quests*5+8; + WFIFOW(fd, 2) = len; + WFIFOL(fd, 4) = sd->avail_quests; - for(i=0; i<MAX_QUEST; i++) + for( i = 0; i < sd->avail_quests; i++ ) { - if(!sd->quest_log[i].quest_id) - continue; - - WFIFOL(fd, i*5+8) = sd->quest_log[i].quest_id; WFIFOB(fd, i*5+12) = sd->quest_log[i].state; - } - WFIFOSET(fd, WFIFOW(fd, 2)); + WFIFOSET(fd, len); } @@ -12590,31 +12577,29 @@ void clif_send_questlog_info(struct map_session_data * sd) { int fd = sd->fd; int i, j; + int len = sd->avail_quests*104+8; + struct mob_db *mob; - WFIFOHEAD(fd,sd->num_quests*104+8); + WFIFOHEAD(fd, len); WFIFOW(fd, 0) = 0x02B2; - WFIFOW(fd, 2) = sd->num_quests*104+8; + WFIFOW(fd, 2) = len; + WFIFOL(fd, 4) = sd->avail_quests; - for(i=0; i<MAX_QUEST; i++) + for( i = 0; i < sd->avail_quests; i++ ) { - if(!sd->quest_log[i].quest_id) - continue; - WFIFOL(fd, i*104+8) = sd->quest_log[i].quest_id; - - // I have no idea what the time field does [Kevin] - WFIFOL(fd, i*104+16) = 0; + WFIFOL(fd, i*104+16) = sd->quest_log[i].time; WFIFOW(fd, i*104+20) = sd->quest_log[i].num_objectives; - for(j=0; j<sd->quest_log[i].num_objectives; j++) + for( j = 0 ; j < sd->quest_log[i].num_objectives; j++ ) { - WFIFOW(fd, i*104+26+j*30) = sd->quest_log[i].objectives[j].count; - memcpy(WFIFOP(fd, i*104+28+j*30), sd->quest_log[i].objectives[j].name, NAME_LENGTH); + WFIFOW(fd, i*104+26+j*30) = sd->quest_log[i].count[j]; + mob = mob_db(sd->quest_log[i].mob[j]); + memcpy(WFIFOP(fd, i*104+28+j*30), mob?mob->jname:"NULL", NAME_LENGTH); } - } - WFIFOSET(fd, WFIFOW(fd, 2)); + WFIFOSET(fd, len); } //Send info when objective info needs an update @@ -12623,23 +12608,24 @@ void clif_send_quest_info(struct map_session_data * sd, struct quest * qd) { int fd = sd->fd; int i; + //int len = MAX_QUEST_OBJECTIVES*30+17; + struct mob_db *mob; - WFIFOHEAD(fd,qd->num_objectives*30+17); + WFIFOHEAD(fd, packet_len(0x02B3)); WFIFOW(fd, 0) = 0x02B3; WFIFOL(fd, 2) = qd->quest_id; WFIFOB(fd, 6) = qd->state; - - //Same time value thing - WFIFOW(fd, 11) = 0; + WFIFOL(fd, 11) = qd->time; WFIFOW(fd, 15) = qd->num_objectives; - for(i=0; i<qd->num_objectives; i++) + for( i = 0; i < qd->num_objectives; i++ ) { - WFIFOW(fd, i*30+21) = qd->objectives[i].count; - memcpy(WFIFOP(fd, i*30+23), qd->objectives[i].name, NAME_LENGTH); + WFIFOW(fd, i*30+21) = qd->count[i]; + mob = mob_db(qd->mob[i]); + memcpy(WFIFOP(fd, i*30+23), mob?mob->jname:"NULL", NAME_LENGTH); } - WFIFOSET(fd, qd->num_objectives*30+17); + WFIFOSET(fd, packet_len(0x02B3)); } //Send delete msg @@ -12648,11 +12634,18 @@ void clif_send_quest_delete(struct map_session_data * sd, int quest_id) { int fd = sd->fd; - WFIFOHEAD(fd, 6); + WFIFOHEAD(fd, packet_len(0x02B4)); WFIFOW(fd, 0) = 0x02B4; WFIFOL(fd, 2) = quest_id; - WFIFOSET(fd, 6); + WFIFOSET(fd, packet_len(0x02B4)); +} +// * 02B5 <packet_len>.W <ignored>.L { }.10B* <-- UNKOWN PACKET + +// * 02B6 <quest_id>.L <state>.B +void clif_parse_questStateAck(int fd, struct map_session_data * sd) +{ + quest_update_status(sd, RFIFOL(fd,2), RFIFOB(fd,6)?Q_ACTIVE:Q_INACTIVE); } //Change active state of the quest @@ -12661,11 +12654,11 @@ void clif_send_quest_status(struct map_session_data * sd, int quest_id, bool act { int fd = sd->fd; - WFIFOHEAD(fd, 7); + WFIFOHEAD(fd, packet_len(0x02B7)); WFIFOW(fd, 0) = 0x02B7; WFIFOL(fd, 2) = quest_id; - WFIFOB(fd, 6) = active?1:0; - WFIFOSET(fd, 7); + WFIFOB(fd, 6) = active; + WFIFOSET(fd, packet_len(0x02B7)); } /*========================================== @@ -13416,7 +13409,7 @@ static int packetdb_readdb(void) 0, 0, 0, 6, 0, 0, 0, 0, 0, 8, 18, 0, 0, 0, 0, 0, 0, 4, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0,191, 0, 0, 0, 0, 0, 0, + 0, 0, 0,117, 6, 0, 7, 7, 0,191, 0, 0, 0, 0, 0, 0, //#0x02C0 0, 0, 0, 0, 0, 30, 0, 0, 0, 3, 0, 65, 4, 71, 10, 0, 0, 0, 0, 0, 0, 0, 6, -1, 10, 10, 3, 0, -1, 32, 6, 0, @@ -13632,6 +13625,8 @@ static int packetdb_readdb(void) {clif_parse_Auction_cancel,"auctioncancel"}, {clif_parse_Auction_close,"auctionclose"}, {clif_parse_Auction_bid,"auctionbid"}, + // Quest Log System + {clif_parse_questStateAck,"queststate"}, #endif {clif_parse_cashshop_buy,"cashshopbuy"}, {clif_parse_ViewPlayerEquip,"viewplayerequip"}, diff --git a/src/map/clif.h b/src/map/clif.h index de39ece38..15dda870b 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -431,14 +431,13 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts void clif_viewequip_fail(struct map_session_data* sd); void clif_equipcheckbox(struct map_session_data* sd); -//quest system [Kevin] +//quest system [Kevin] [Inkfish] void clif_send_questlog(struct map_session_data * sd); void clif_send_questlog_info(struct map_session_data * sd); void clif_send_quest_info(struct map_session_data * sd, struct quest * qd); void clif_send_quest_delete(struct map_session_data * sd, int quest_id); void clif_send_quest_status(struct map_session_data * sd, int quest_id, bool active); - int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type); int do_final_clif(void); int do_init_clif(void); diff --git a/src/map/intif.c b/src/map/intif.c index e6b5768b4..d077aa881 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -38,7 +38,7 @@ static const int packet_len_table[]={ 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 9, 9,-1,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840 -1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] - -1,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] + -1,11,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3870 Mercenaries [Zephyrus] 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] @@ -1340,21 +1340,26 @@ int intif_request_questlog(TBL_PC *sd) int intif_parse_questlog(int fd) { - - int num_quests = (RFIFOB(fd, 2)-8)/sizeof(struct quest); int char_id = RFIFOL(fd, 4); int i; TBL_PC * sd = map_charid2sd(char_id); //User not online anymore if(!sd) - return 0; + return -1; - for(i=0; i<num_quests; i++) + sd->avail_quests = sd->num_quests = (RFIFOB(fd, 2)-8)/sizeof(struct quest); + + memset(&sd->quest_log, 0, sizeof(sd->quest_log)); + + for( i = 0; i < sd->num_quests; i++ ) { memcpy(&sd->quest_log[i], RFIFOP(fd, i*sizeof(struct quest)+8), sizeof(struct quest)); + if( sd->quest_log[i].state == Q_COMPLETE ) + sd->avail_quests--; } - sd->num_quests = num_quests; + + quest_pc_login(sd); return 0; } @@ -1401,6 +1406,27 @@ int intif_quest_add(int char_id, struct quest * qd) return 0; } +int intif_quest_save(int char_id, struct quest * qd) +{ + if(CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd, sizeof(struct quest) + 8); + WFIFOW(inter_fd,0) = 0x3063; + WFIFOW(inter_fd,2) = sizeof(struct quest) + 8; + WFIFOL(inter_fd,4) = char_id; + memcpy(WFIFOP(inter_fd,8), qd, sizeof(struct quest)); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + + return 0; +} + +int intif_parse_questSave(int fd) +{ + quest_save_ack(RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOB(fd, 10)); + return 0; +} + #ifndef TXT_ONLY /*========================================== @@ -2038,6 +2064,7 @@ int intif_parse(int fd) case 0x3860: intif_parse_questlog(fd); break; case 0x3861: intif_parse_questAdd(fd); break; case 0x3862: intif_parse_questDelete(fd); break; + case 0x3863: intif_parse_questSave(fd); break; #ifndef TXT_ONLY // Mail System diff --git a/src/map/intif.h b/src/map/intif.h index 38effaaf9..51389bd5b 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -77,6 +77,7 @@ int intif_homunculus_requestdelete(int homun_id); int intif_request_questlog(struct map_session_data * sd); int intif_quest_delete(int char_id, int quest_id); int intif_quest_add(int char_id, struct quest * qd); +int intif_quest_save(int char_id, struct quest * qd); // MERCENARY SYSTEM int intif_mercenary_create(struct s_mercenary *merc); diff --git a/src/map/map.c b/src/map/map.c index f5b980506..b1bf03126 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -32,6 +32,7 @@ #include "unit.h" #include "battle.h" #include "battleground.h" +#include "quest.h" #include "script.h" #include "mapreg.h" #include "guild.h" @@ -4081,6 +4082,7 @@ int do_init(int argc, char *argv[]) do_init_pet(); do_init_merc(); do_init_mercenary(); + do_init_quest(); do_init_npc(); do_init_unit(); do_init_battleground(); diff --git a/src/map/mob.c b/src/map/mob.c index e6fa8d2fd..abcb9f469 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -32,6 +32,8 @@ #include "script.h" #include "atcommand.h" #include "date.h" +#include "quest.h" + #include <stdio.h> #include <stdlib.h> @@ -1992,6 +1994,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) } pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count); } + if( sd->avail_quests ) + quest_update_objective(sd, md->class_); } // filter out entries not eligible for exp distribution diff --git a/src/map/pc.h b/src/map/pc.h index 90e055c17..925db7184 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -377,9 +377,11 @@ struct map_session_data { bool changed; // if true, should sync with charserver on next mailbox request } mail; - //Quest log system [Kevin] + //Quest log system [Kevin] [Inkfish] int num_quests; - struct quest quest_log[MAX_QUEST]; + int avail_quests; + bool save_quest[MAX_QUEST_DB]; + struct quest quest_log[MAX_QUEST_DB]; // temporary debug [flaviojs] const char* debug_file; diff --git a/src/map/quest.c b/src/map/quest.c index 057c46d7c..ccde85a07 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -33,46 +33,61 @@ #include <stdarg.h> #include <time.h> +#define MAX_QUEST 25 + //Send quest info on login int quest_pc_login(TBL_PC * sd) { - if(sd->num_quests == 0) return 1; clif_send_questlog(sd); clif_send_questlog_info(sd); + return 0; } -int quest_add(TBL_PC * sd, struct quest * qd) +int quest_add(TBL_PC * sd, int quest_id) { - int i; + int i, j, count; - //Search to see if this quest exists - ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == qd->quest_id); + if( quest_check_quest(sd, quest_id, HAVEQUEST) >= 0 ) + { + ShowError("quest_add: you already have quest %d.\n",quest_id); + return -1; + } - //Already have this quest - if(i!=MAX_QUEST) - return 1; + if( (j = quest_search_db(quest_id)) < 0 ) + { + ShowError("quest_add: quest %d not found in DB.\n",quest_id); + return -1; + } - //Find empty quest log spot - ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == 0); + if( sd->num_quests >= MAX_QUEST_DB || sd->avail_quests >= MAX_QUEST ) + { + ShowError("quest_add: your quest log is full.(max quests: %d, max incompleted quests: %d)\n", MAX_QUEST_DB, MAX_QUEST); + return 1; + } - //Quest log is full - if(i == MAX_QUEST) - return -1; + i = sd->avail_quests; + memmove(&sd->quest_log[i+1], &sd->quest_log[i], sizeof(struct quest)*(sd->num_quests-sd->avail_quests)); + memset(&sd->quest_log[i], 0, sizeof(struct quest)); + sd->quest_log[i].quest_id = quest_db[j].id; + if( quest_db[j].time ) + sd->quest_log[i].time = (unsigned int)(time(NULL) + quest_db[j].time); + sd->quest_log[i].state = Q_ACTIVE; + for( count = 0; count < MAX_QUEST_OBJECTIVES && quest_db[j].mob[count]; count++ ) + sd->quest_log[i].mob[count] = quest_db[j].mob[count]; + sd->quest_log[i].num_objectives = count; - //Copy over quest data - memcpy(&sd->quest_log[i], qd, sizeof(struct quest)); sd->num_quests++; + sd->avail_quests++; //Notify inter server - intif_quest_add(sd->status.char_id, qd); + intif_quest_add(sd->status.char_id, &sd->quest_log[i]); return 0; - } int quest_add_ack(int char_id, int quest_id, int success) @@ -83,26 +98,21 @@ int quest_add_ack(int char_id, int quest_id, int success) ///Player no longer on map if(!sd) return -1; + + ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id); + if( i == sd->avail_quests ) + return -1; //Shouldn't happen! - //Search for quest - ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id); - - //Quest not found, shouldn't happen? - if(i == MAX_QUEST) - return -1; - - if(success) - { - //Notify client - clif_send_quest_info(sd, &sd->quest_log[i]); - } + if( success ) + clif_send_quest_info(sd, &sd->quest_log[i]); //Notify client else { + sd->avail_quests--; + if( sd->num_quests < MAX_QUEST_DB && sd->quest_log[i+1].quest_id ) + memmove(&sd->quest_log[i], &sd->quest_log[i+1], sizeof(struct quest)*(sd->num_quests-i)); + memset(&sd->quest_log[--sd->num_quests], 0, sizeof(struct quest)); ShowError("Quest %d for character %d could not be added!\n", quest_id, char_id); - - //Zero quest - memset(&sd->quest_log[i], 0, sizeof(struct quest)); - sd->num_quests--; + return 1; } return 0; @@ -110,25 +120,20 @@ int quest_add_ack(int char_id, int quest_id, int success) int quest_delete(TBL_PC * sd, int quest_id) { - - int i; - //Search for quest - ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id); - - //Quest not found - if(i == MAX_QUEST) + if( quest_check_quest(sd, quest_id, HAVEQUEST) < 0 ) //Quest not found + { + ShowError("quest_delete: quest %d not found in your quest log.\n",quest_id); return -1; + } intif_quest_delete(sd->status.char_id, quest_id); return 0; - } int quest_delete_ack(int char_id, int quest_id, int success) { - int i; TBL_PC * sd = map_charid2sd(char_id); @@ -137,65 +142,229 @@ int quest_delete_ack(int char_id, int quest_id, int success) return -1; //Search for quest - ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id); - - //Quest not found - if(i == MAX_QUEST) + ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id); + if(i == sd->num_quests) //Shouldn't happen! return -1; if(success) { + if( sd->quest_log[i].state != Q_COMPLETE ) + sd->avail_quests--; + if( sd->num_quests < MAX_QUEST_DB && sd->quest_log[i+1].quest_id ) + memmove(&sd->quest_log[i], &sd->quest_log[i+1], sizeof(struct quest)*(sd->num_quests-i)); + memset(&sd->quest_log[--sd->num_quests], 0, sizeof(struct quest)); + clif_send_quest_delete(sd, quest_id); + } + else + { + ShowError("Quest %d for character %d could not be deleted!\n", quest_id, char_id); + return 1; + } - //Zero quest - memset(&sd->quest_log[i], 0, sizeof(struct quest)); - sd->num_quests--; + return 0; +} - //Notify client - clif_send_quest_delete(sd, quest_id); +void quest_update_objective(TBL_PC * sd, int mob) +{ + int i,j; - return 1; + 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( sd->quest_log[i].mob[j] == mob ) + { + sd->quest_log[i].count[j]++; + sd->save_quest[i] = true; + //clif_send_quest_info(sd, &sd->quest_log[i]); //TODO: Figure out the real packet [Inkfish] + //break; + } + } +} + +int quest_update_status(TBL_PC * sd, int quest_id, int status) +{ + int i; + //Search for quest + ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id); // Only status of active and inactive quests can't be updated and completed quests can't [Inkfish] + if(i == sd->avail_quests) //Quest not found + { + ShowError("Quest %d not found in your quest log!\n", quest_id); + return -1; + } + + sd->quest_log[i].state = (quest_state)status; + if( status != Q_COMPLETE ) + { + clif_send_quest_status(sd, quest_id, (bool)status); + sd->save_quest[i] = true; } else - ShowError("Quest %d for character %d could not be deleted!\n", quest_id, char_id); + { + struct quest tmp_quest; + + clif_send_quest_delete(sd, quest_id); + sd->avail_quests--; + + memcpy(&tmp_quest, &sd->quest_log[i],sizeof(struct quest)); + memcpy(&sd->quest_log[i], &sd->quest_log[sd->avail_quests],sizeof(struct quest)); + memcpy(&sd->quest_log[sd->avail_quests], &tmp_quest,sizeof(struct quest)); + + sd->save_quest[sd->avail_quests] = true; + } return 0; +} + +int quest_save(TBL_PC * sd) +{ + int i; + for( i = 0; i < sd->num_quests; i++ ) + if( sd->save_quest[i] ) + intif_quest_save(sd->status.char_id, &sd->quest_log[i]); + + return 0; } -int quest_update_objective(TBL_PC * sd, int quest_id, int objective_num, const char * name, int count) +int quest_save_ack(int char_id, int quest_id, int success) { int i; + TBL_PC * sd = map_charid2sd(char_id); - //Search for quest - ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id); - - //Quest not found - if(i == MAX_QUEST) + ///Player no longer on map + if(!sd) return -1; - memcpy(&sd->quest_log[i].objectives[objective_num].name, name, NAME_LENGTH); - sd->quest_log[i].objectives[objective_num].count = count; + //Search for quest + ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id); + if(i == sd->num_quests) //Quest not found + return -1; - //Notify client - clif_send_quest_info(sd, &sd->quest_log[i]); + if(success) + sd->save_quest[i] = false; + else + { + ShowError("Quest %d for character %d could not be saved!\n", quest_id, char_id); + return 1; + } return 0; } -bool quest_has_quest(TBL_PC * sd, int quest_id) +int quest_check_quest(TBL_PC * sd, int quest_id, quest_check_type type) { int i; - ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id); + ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id); + if(i == sd->num_quests) + return -1; + + switch( type ) + { + case HAVEQUEST: + return sd->quest_log[i].state; + case PLAYTIME: + return (sd->quest_log[i].time < (unsigned int)time(NULL) ? 2 : sd->quest_log[i].state == Q_COMPLETE ? 1 : 0); + case HUNTING: + { + int j = quest_search_db(quest_id); + + if( j < 0 ) + { + ShowError("quest_check_quest: quest not found in DB\n"); + return -1; + } + + if( sd->quest_log[i].count[0] < quest_db[j].count[0] || sd->quest_log[i].count[1] < quest_db[j].count[1] || sd->quest_log[i].count[2] < quest_db[j].count[2] ) + { + if( sd->quest_log[i].time < (unsigned int)time(NULL) ) + return 1; + + return 0; + } + + return 2; + } + default: + ShowError("quest_check_quest: Unknown parameter %d",type); + break; + } - return (i != MAX_QUEST); + return -1; } -int quest_update_status(TBL_PC * sd, int quest_id, bool status) +int quest_search_db(int quest_id) { + int i; + ARR_FIND(0, MAX_QUEST_DB,i,quest_id == quest_db[i].id); + if( i == MAX_QUEST_DB ) + return -1; + + return i; +} + +int quest_read_db(void) +{ + FILE *fp; + char line[1024]; + int j,k = 0; + char *str[20],*p,*np; + + sprintf(line, "%s/quest_db.txt", db_path); + if( (fp=fopen(line,"r"))==NULL ){ + ShowError("can't read %s\n", line); + return -1; + } + + while(fgets(line, sizeof(line), fp)) + { + if(line[0]=='/' && line[1]=='/') + continue; + memset(str,0,sizeof(str)); + + for( j = 0, p = line; j < 8;j++ ) + { + if((np=strchr(p,','))!=NULL) + { + str[j] = p; + *np = 0; + p = np + 1; + } + else + { + ShowError("quest_read_db: insufficient columes in line %s\n", line); + continue; + } + } + if(str[0]==NULL) + continue; + + memset(&quest_db[k], 0, sizeof(quest_db[0])); + + quest_db[k].id = atoi(str[0]); + quest_db[k].time = atoi(str[1]); + quest_db[k].mob[0] = atoi(str[2]); + quest_db[k].count[0] = atoi(str[3]); + quest_db[k].mob[1] = atoi(str[4]); + quest_db[k].count[1] = atoi(str[5]); + quest_db[k].mob[2] = atoi(str[6]); + quest_db[k].count[2] = atoi(str[7]); + //memcpy(quest_db[k].name, str[8], sizeof(str[8])); + k++; + } + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","quest_db.txt"); return 0; } + +void do_init_quest(void) +{ + quest_read_db(); +} diff --git a/src/map/quest.h b/src/map/quest.h index c8fa98246..16870d381 100644 --- a/src/map/quest.h +++ b/src/map/quest.h @@ -4,19 +4,34 @@ #ifndef _QUEST_H_ #define _QUEST_H_ +typedef enum quest_check_type { HAVEQUEST, PLAYTIME, HUNTING } quest_check_type; + +struct s_quest_db { + int id; + unsigned int time; + int mob[MAX_QUEST_OBJECTIVES]; + int count[MAX_QUEST_OBJECTIVES]; + //char name[NAME_LENGTH]; +}; +struct s_quest_db quest_db[MAX_QUEST_DB]; + int quest_pc_login(TBL_PC * sd); -int quest_load_info(TBL_PC * sd, struct mmo_charstatus * st); -int quest_make_savedata(TBL_PC * sd); -int quest_add(TBL_PC * sd, struct quest * qd); +int quest_add(TBL_PC * sd, int quest_id); int quest_add_ack(int char_id, int quest_id, int success); int quest_delete(TBL_PC * sd, int quest_id); int quest_delete_ack(int char_id, int quest_id, int success); -int quest_update_objective(TBL_PC * sd, int quest_id, int objective_num, const char * name, int count); -int quest_update_status(TBL_PC * sd, int quest_id, bool status); +void quest_update_objective(TBL_PC * sd, int mob); +int quest_update_status(TBL_PC * sd, int quest_id, int status); +int quest_save(TBL_PC * sd); +int quest_save_ack(int char_id, int quest_id, int success); + +int quest_check_quest(TBL_PC * sd, int quest_id, quest_check_type type); + +int quest_search_db(int quest_id); -bool quest_has_quest(TBL_PC * sd, int quest_id); +void do_init_quest(); #endif diff --git a/src/map/script.c b/src/map/script.c index 9edab3e2a..1efd85c6c 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -13426,81 +13426,53 @@ BUILDIN_FUNC(readbook) Questlog script commands *******************/ -BUILDIN_FUNC(getquest) +BUILDIN_FUNC(setquest) { - TBL_PC * sd = script_rid2sd(st); - struct quest qd; - int i, count = 0; - char * temp; - - memset(&qd, 0, sizeof(struct quest)); - - qd.quest_id = script_getnum(st, 2); - qd.time = script_getnum(st, 3); - qd.state = Q_ACTIVE; - - for(i=0; i<(script_lastdata(st)-3) && (i/2) < MAX_QUEST_OBJECTIVES; i+=2) - { - temp = (char*)script_getstr(st, i+4); - memcpy(&qd.objectives[i/2].name, temp, NAME_LENGTH); - temp = NULL; - qd.objectives[i/2].count = script_getnum(st, i+5); - count++; - } - - qd.num_objectives = count; - - quest_add(sd, &qd); + quest_add(sd, script_getnum(st, 2)); return 0; - } -BUILDIN_FUNC(deletequest) +BUILDIN_FUNC(erasequest) { - TBL_PC * sd = script_rid2sd(st); - int qid = script_getnum(st, 2); - quest_delete(sd, qid); + quest_delete(sd, script_getnum(st, 2)); return 0; - } -BUILDIN_FUNC(setquestobjective) +BUILDIN_FUNC(completequest) { - TBL_PC * sd = script_rid2sd(st); - int qid = script_getnum(st, 2); - int num = script_getnum(st, 3); - const char * str = script_getstr(st, 4); - int count = script_getnum(st, 5); - - quest_update_objective(sd, qid, num, str, count); + quest_update_status(sd, script_getnum(st, 2), Q_COMPLETE); return 0; } -BUILDIN_FUNC(hasquest) +BUILDIN_FUNC(changequest) { - TBL_PC * sd = script_rid2sd(st); - int qid = script_getnum(st, 2); + int q1 = script_getnum(st, 2), q2 = script_getnum(st, 3); - script_pushint(st, quest_has_quest(sd, qid)?1:0); + if( quest_check_quest(sd, q1, HAVEQUEST) == Q_ACTIVE && quest_add(sd, q2) >= 0 ) + { + quest_update_status(sd, q1, Q_COMPLETE); + intif_quest_save(sd->status.char_id, &sd->quest_log[sd->avail_quests]); + } return 0; } -BUILDIN_FUNC(setqueststatus) +BUILDIN_FUNC(checkquest) { - TBL_PC * sd = script_rid2sd(st); - int qid = script_getnum(st, 2); - bool active = script_getnum(st, 3)?true:false; + quest_check_type type = HAVEQUEST; + + if( script_hasdata(st, 3) ) + type = (quest_check_type)script_getnum(st, 3); - quest_update_status(sd, qid, active); + script_pushint(st, quest_check_quest(sd, script_getnum(st, 2), type)); return 0; } @@ -14472,11 +14444,6 @@ struct script_function buildin_func[] = { BUILDIN_DEF(openauction,""), BUILDIN_DEF(checkcell,"siii"), BUILDIN_DEF(setcell,"siiiiii"), - BUILDIN_DEF(getquest, "ii*"), - BUILDIN_DEF(deletequest, "i"), - BUILDIN_DEF(setquestobjective, "iisi"), - BUILDIN_DEF(setqueststatus, "ii"), - BUILDIN_DEF(hasquest, "i"), BUILDIN_DEF(setwall,"siiiiis"), BUILDIN_DEF(delwall,"s"), BUILDIN_DEF(mercenary_create,"ii"), @@ -14519,5 +14486,11 @@ struct script_function buildin_func[] = { BUILDIN_DEF(instance_id,"?"), BUILDIN_DEF(instance_warpall,"sii"), BUILDIN_DEF(instance_set_timeout,"ii?"), + //Quest Log System [Inkfish] + BUILDIN_DEF(setquest, "i"), + BUILDIN_DEF(erasequest, "i"), + BUILDIN_DEF(completequest, "i"), + BUILDIN_DEF(checkquest, "i*"), + BUILDIN_DEF(changequest, "ii"), {NULL,NULL,NULL}, }; |