Parcourir la source

* Some more updates to Quest Log
- Implemented a new saving mechanism. Now they can be saved every 'autosave_time' in case the char-server is not online when you get a quest.
- Improved 'changequest' code.
- Increase MAX_QUEST_DB to 1200.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@13973 54d463be-8e91-2dee-dedb-b68131a5f0ec

Inkfish il y a 16 ans
Parent
commit
b753cba749
12 fichiers modifiés avec 205 ajouts et 251 suppressions
  1. 2 1
      conf/map_athena.conf
  2. 63 62
      src/char_sql/int_quest.c
  3. 3 0
      src/char_sql/int_quest.h
  4. 1 1
      src/char_sql/inter.c
  5. 1 2
      src/common/mmo.h
  6. 1 1
      src/map/chrif.c
  7. 30 50
      src/map/intif.c
  8. 1 3
      src/map/intif.h
  9. 3 3
      src/map/mob.c
  10. 95 110
      src/map/quest.c
  11. 3 9
      src/map/quest.h
  12. 2 9
      src/map/script.c

+ 2 - 1
conf/map_athena.conf

@@ -107,11 +107,12 @@ minsave_time: 100
 // 8: After hatching/returning to egg a pet.
 // 16: After successfully sending a mail with attachment
 // 32: After successfully submitting an item for auction
+// 64: After successfully get/delete/complete a quest
 // NOTE: These settings decrease the chance of dupes/lost items when there's a
 // server crash at the expense of increasing the map/char server lag. If your 
 // server rarely crashes, but experiences interserver lag, you may want to set
 // these off.
-save_settings: 63
+save_settings: 127
 
 // Message of the day file, when a character logs on, this message is displayed.
 motd_txt: conf/motd.txt

+ 63 - 62
src/char_sql/int_quest.c

@@ -2,6 +2,7 @@
 // For more information, see LICENCE in the main folder
 
 #include "../common/mmo.h"
+#include "../common/db.h"
 #include "../common/malloc.h"
 #include "../common/showmsg.h"
 #include "../common/socket.h"
@@ -57,41 +58,73 @@ int mapif_quests_fromsql(int char_id, struct quest questlog[])
 	return i;
 }
 
-//Delete a quest
-int mapif_parse_quest_delete(int fd)
+//Save quests
+int mapif_parse_quest_save(int fd)
 {
+	int i, j, num2, num1 = (RFIFOW(fd,2)-8)/sizeof(struct quest);
+	int char_id = RFIFOL(fd,4);
+	struct quest qd1[MAX_QUEST_DB],qd2[MAX_QUEST_DB];
+	uint8 buf[MAX_QUEST_DB];
+	int count = 0;
 
-	bool success = true;
-	int char_id = RFIFOL(fd,2);
-	int quest_id = RFIFOL(fd,6);
+	memset(qd1, 0, sizeof(qd1));
+	memset(qd2, 0, sizeof(qd2));
+	memcpy(&qd1, RFIFOP(fd,8), RFIFOW(fd,2)-8);
+	num2 = mapif_quests_fromsql(char_id, qd2);
 
-	if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, quest_id, char_id) )
+	for( i = 0; i < num1; i++ )
 	{
-		Sql_ShowDebug(sql_handle);
-		success = false;
+		ARR_FIND( 0, num2, j, qd1[i].quest_id == qd2[j].quest_id );
+		if( j < num2 ) // Update existed quests
+		{	// Only states and counts are changable.
+			if( qd1[i].state != qd2[j].state || qd1[i].count[0] != qd2[j].count[0] || qd1[i].count[1] != qd2[j].count[1] || qd1[i].count[2] != qd2[j].count[2] )
+				mapif_quest_update(char_id, qd1[i]);
+
+			if( j < (--num2) )
+			{
+				memmove(&qd2[j],&qd2[j+1],sizeof(struct quest)*(num2-j));
+				memset(&qd2[num2], 0, sizeof(struct quest));
+			}
+
+		}
+		else // Add new quests
+		{
+			mapif_quest_add(char_id, qd1[i]);
+
+			WBUFL(buf,count*4) = qd1[i].quest_id;
+			count++;
+		}
 	}
 
-	WFIFOHEAD(fd,11);
-	WFIFOW(fd,0) = 0x3862;
-	WFIFOL(fd,2) = char_id;
-	WFIFOL(fd,6) = quest_id;
-	WFIFOB(fd,10) = success?1:0;
-	WFIFOSET(fd,11);
+	for( i = 0; i < num2; i++ ) // Quests not in qd1 but in qd2 are to be erased.
+		mapif_quest_delete(char_id, qd2[i].quest_id);
+
+	WFIFOHEAD(fd,8+4*count);
+	WFIFOW(fd,0) = 0x3861;
+	WFIFOW(fd,2) = 8+4*count;
+	WFIFOL(fd,4) = char_id;
+	memcpy(WFIFOP(fd,8), buf, count*4);
+	WFIFOSET(fd,WFIFOW(fd,2));
 
 	return 0;
+}
 
+//Delete a quest
+int mapif_quest_delete(int char_id, int quest_id)
+{
+	if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, quest_id, char_id) )
+	{
+		Sql_ShowDebug(sql_handle);
+		return -1;
+	}
+
+	return 1;
 }
 
 //Add a quest to a questlog
-int mapif_parse_quest_add(int fd)
+int mapif_quest_add(int char_id, struct quest qd)
 {
-
 	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, "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]);
@@ -99,32 +132,18 @@ int mapif_parse_quest_add(int fd)
 	if ( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) 
 	{
 		Sql_ShowDebug(sql_handle);
-		success = false;
+		return -1;
 	}
 
-	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_Destroy(&buf);
 
-	return 0;
-
+	return 1;
 }
 
 //Update a questlog
-int mapif_parse_quest_update(int fd)
+int mapif_quest_update(int char_id, struct quest qd)
 {
-
 	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);
@@ -132,25 +151,18 @@ int mapif_parse_quest_update(int fd)
 	if ( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) 
 	{
 		Sql_ShowDebug(sql_handle);
-		success = false;
+		return -1;
 	}
 
-	WFIFOHEAD(fd,11);
-	WFIFOW(fd,0) = 0x3863;
-	WFIFOL(fd,2) = char_id;
-	WFIFOL(fd,6) = qd.quest_id;
-	WFIFOB(fd,10) = success?1:0;
-	WFIFOSET(fd,11);
-
 	StringBuf_Destroy(&buf);
 
-	return 0;
-
+	return 1;
 }
 
 //Send questlog to map server
-int mapif_send_quests(int fd, int char_id)
+int mapif_parse_quest_load(int fd)
 {
+	int char_id = RFIFOL(fd,2);
 	struct quest tmp_questlog[MAX_QUEST_DB];
 	int num_quests, i, num_complete = 0;
 	int complete[MAX_QUEST_DB];
@@ -185,25 +197,14 @@ int mapif_send_quests(int fd, int char_id)
 	return 0;
 }
 
-//Map server requesting a character's quest log
-int mapif_parse_loadquestrequest(int fd)
-{
-	mapif_send_quests(fd, RFIFOL(fd,2));
-	return 0;
-}
-
 int inter_quest_parse_frommap(int fd)
 {
-
 	switch(RFIFOW(fd,0))
 	{
-		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;
+		case 0x3060: mapif_parse_quest_load(fd); break;
+		case 0x3061: mapif_parse_quest_save(fd); break;
 		default:
 			return 0;
 	}
 	return 1;
-
 }

+ 3 - 0
src/char_sql/int_quest.h

@@ -8,6 +8,9 @@
 struct quest;
 
 int inter_quest_parse_frommap(int fd);
+int mapif_quest_delete(int char_id, int quest_id);
+int mapif_quest_add(int char_id, struct quest qd);
+int mapif_quest_update(int char_id, struct quest qd);
 
 #endif
 

+ 1 - 1
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,-1,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3060-  Quest system [Kevin] [Inkfish]
+	 6,-1, 0, 0,  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]

+ 1 - 2
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_DB 500 //Max quests that the server will load
+#define MAX_QUEST_DB 1200 //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
@@ -135,7 +135,6 @@ struct quest {
 	int mob[MAX_QUEST_OBJECTIVES];
 	int count[MAX_QUEST_OBJECTIVES];
 	quest_state state;
-	bool save_quest;
 	int num_objectives;
 };
 

+ 1 - 1
src/map/chrif.c

@@ -289,7 +289,7 @@ int chrif_save(struct map_session_data *sd, int flag)
 	if( sd->md && mercenary_get_lifetime(sd->md) > 0 )
 		mercenary_save(sd->md);
 	if( sd->num_quests )
-		quest_save(sd);
+		intif_quest_save(sd);
 
 	return 0;
 }

+ 30 - 50
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,11,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3860  Quests [Kevin] [Inkfish]
+	-1,-1, 0, 0,  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]
@@ -1364,66 +1364,48 @@ int intif_parse_questlog(int fd)
 	return 0;
 }
 
-int intif_parse_questDelete(int fd)
+int intif_parse_questsave(int fd)
 {
-	quest_delete_ack(RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOB(fd, 10));
-	return 0;
-}
+	TBL_PC * sd = map_charid2sd(RFIFOL(fd, 4));
+	int i,j;
+	int count = (RFIFOW(fd, 2) - 8) / 4;
 
-int intif_quest_delete(int char_id, int quest_id)
-{
-	if(CheckForCharServer())
-		return 0;
-
-	WFIFOHEAD(inter_fd, 10);
-	WFIFOW(inter_fd,0) = 0x3062;
-	WFIFOL(inter_fd,2) = char_id;
-	WFIFOL(inter_fd,6) = quest_id;
-	WFIFOSET(inter_fd, 10);
+	if( !sd )
+		return -1;
 
-	return 0;
-}
+	for( i = 0; i < count; i++ )
+	{
+		int qid = RFIFOL(fd, 4*i+8);
+		
+		ARR_FIND(0, sd->avail_quests, j, sd->quest_log[j].quest_id == qid);
+		if(j == sd->avail_quests) //shouldn't happen
+		{
+			ShowError("intif_parse_questsave: Quest %d not found in your quest log!\n", qid);
+			continue;
+		}
+		//This packet can't go before 'close' and 'next'. That's weird and why I send it here. [Inkfish]
+		clif_send_quest_info(sd, &sd->quest_log[j]);
+	}
 
-int intif_parse_questAdd(int fd)
-{
-	quest_add_ack(RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOB(fd, 10));
 	return 0;
 }
 
-int intif_quest_add(int char_id, struct quest * qd)
+int intif_quest_save(TBL_PC *sd)
 {
+	int len;
 
 	if(CheckForCharServer())
 		return 0;
 
-	WFIFOHEAD(inter_fd, sizeof(struct quest) + 8);
-	WFIFOW(inter_fd,0) = 0x3061;
-	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_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));
+	len = sizeof(struct quest)*sd->num_quests + 8;
 
-	return 0;
-}
+	WFIFOHEAD(inter_fd, len);
+	WFIFOW(inter_fd,0) = 0x3061;
+	WFIFOW(inter_fd,2) = len;
+	WFIFOL(inter_fd,4) = sd->status.char_id;
+	memcpy(WFIFOP(inter_fd,8), &sd->quest_log, sizeof(struct quest)*sd->num_quests);
+	WFIFOSET(inter_fd,  len);
 
-int intif_parse_questSave(int fd)
-{
-	quest_save_ack(RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOB(fd, 10));
 	return 0;
 }
 
@@ -2062,9 +2044,7 @@ int intif_parse(int fd)
 
 	//Quest system
 	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;
+	case 0x3861:	intif_parse_questsave(fd); break;
 
 #ifndef TXT_ONLY
 // Mail System

+ 1 - 3
src/map/intif.h

@@ -75,9 +75,7 @@ int intif_homunculus_requestdelete(int homun_id);
 
 /******QUEST SYTEM*******/
 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);
+int intif_quest_save(struct map_session_data * sd);
 
 // MERCENARY SYSTEM
 int intif_mercenary_create(struct s_mercenary *merc);

+ 3 - 3
src/map/mob.c

@@ -34,7 +34,6 @@
 #include "date.h"
 #include "quest.h"
 
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -1993,9 +1992,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 				clif_mission_info(sd, temp, 0);
 			}
 			pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count);
+
+			if( sd->avail_quests )
+				quest_update_objective(sd, md->class_);
 		}
-		if( sd->avail_quests )
-			quest_update_objective(sd, md->class_);
 	}
 
 	// filter out entries not eligible for exp distribution

+ 95 - 110
src/map/quest.c

@@ -12,7 +12,6 @@
 #include "../common/utils.h"
 
 #include "map.h"
-#include "chrif.h"
 #include "pc.h"
 #include "npc.h"
 #include "itemdb.h"
@@ -26,6 +25,7 @@
 #include "clif.h"
 #include "quest.h"
 #include "intif.h"
+#include "chrif.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -45,7 +45,7 @@ struct s_quest_db quest_db[MAX_QUEST_DB];
 //Send quest info on login
 int quest_pc_login(TBL_PC * sd)
 {
-	if(sd->num_quests == 0)
+	if(sd->avail_quests == 0)
 		return 1;
 
 	clif_send_questlog(sd);
@@ -59,7 +59,13 @@ int quest_add(TBL_PC * sd, int quest_id)
 
 	int i, j, count;
 
-	if( quest_check_quest(sd, quest_id, HAVEQUEST) >= 0 )
+	if( sd->num_quests >= MAX_QUEST_DB )
+	{
+		ShowError("quest_add: your quest log is full.(max quests: %d)\n", MAX_QUEST_DB);
+		return 1;
+	}
+
+	if( quest_check(sd, quest_id, HAVEQUEST) >= 0 )
 	{
 		ShowError("quest_add: you already have quest %d.\n",quest_id);
 		return -1;
@@ -71,14 +77,9 @@ int quest_add(TBL_PC * sd, int quest_id)
 		return -1;
 	}
 
-	if( sd->num_quests >= MAX_QUEST_DB )
-	{
-		ShowError("quest_add: your quest log is full.(max quests: %d)\n", MAX_QUEST_DB);
-		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 )
@@ -91,82 +92,99 @@ int quest_add(TBL_PC * sd, int quest_id)
 	sd->num_quests++;
 	sd->avail_quests++;
 
-	//Notify inter server
-	intif_quest_add(sd->status.char_id, &sd->quest_log[i]);
+	if( save_settings&64 )
+		chrif_save(sd,0);
+	else
+		intif_quest_save(sd);
 
 	return 0;
 }
 
-int quest_add_ack(int char_id, int quest_id, int success)
+int quest_change(TBL_PC * sd, int qid1, int qid2)
 {
-	int i;
-	TBL_PC * sd = map_charid2sd(char_id);
 
-	///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!
+	int i, j, count;
 
-	if( success )
-		clif_send_quest_info(sd, &sd->quest_log[i]); //Notify client
-	else
+	if( sd->num_quests >= MAX_QUEST_DB )
 	{
-		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);
+		ShowError("quest_change: your quest log is full.(max quests: %d)\n", MAX_QUEST_DB);
 		return 1;
 	}
 
-	return 0;
-}
+	if( quest_check(sd, qid2, HAVEQUEST) >= 0 )
+	{
+		ShowError("quest_change: you already have quest %d.\n",qid2);
+		return -1;
+	}
 
-int quest_delete(TBL_PC * sd, int quest_id)
-{
-	//Search for quest
-	if( quest_check_quest(sd, quest_id, HAVEQUEST) < 0 ) //Quest not found
+	if( quest_check(sd, qid1, HAVEQUEST) < 0 )
 	{
-		ShowError("quest_delete: quest %d not found in your quest log.\n",quest_id);
+		ShowError("quest_change: you don't have quest %d.\n",qid1);
 		return -1;
 	}
 
-	intif_quest_delete(sd->status.char_id, quest_id);
+	if( (j = quest_search_db(qid2)) < 0 )
+	{
+		ShowError("quest_change: quest %d not found in DB.\n",qid2);
+		return -1;
+	}
+
+	ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == qid1);
+	if(i == sd->avail_quests)
+	{
+		ShowError("quest_change: Quest %d not found in your quest log!\n", qid1);
+		return -1;
+	}
+
+	// Complete quest
+	sd->quest_log[i].state = Q_COMPLETE;
+	memcpy(&sd->quest_log[sd->num_quests], &sd->quest_log[i],sizeof(struct quest));
+	clif_send_quest_delete(sd, qid1);
+
+	// Add new quest
+	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;
+
+	sd->num_quests++;
+
+	if( save_settings&64 )
+		chrif_save(sd,0);
+	else
+		intif_quest_save(sd);
 
 	return 0;
 }
 
-int quest_delete_ack(int char_id, int quest_id, int success)
+int quest_delete(TBL_PC * sd, int quest_id)
 {
 	int i;
-	TBL_PC * sd = map_charid2sd(char_id);
-
-	///Player no longer on map
-	if(!sd)
-		return -1;
 
 	//Search for 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(i == sd->num_quests)
 	{
-		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);
+		ShowError("quest_delete: quest %d not found in your quest log.\n",quest_id);
+		return -1;
 	}
+
+	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);
+
+	if( save_settings&64 )
+		chrif_save(sd,0);
 	else
-	{
-		ShowError("Quest %d for character %d could not be deleted!\n", quest_id, char_id);
-		return 1;
-	}
+		intif_quest_save(sd);
 
 	return 0;
 }
@@ -184,87 +202,54 @@ void quest_update_objective(TBL_PC * sd, int mob)
 			if( sd->quest_log[i].mob[j] == mob )
 			{
 				sd->quest_log[i].count[j]++;
-				sd->quest_log[i].save_quest = true;
-				//clif_send_quest_info(sd, &sd->quest_log[i]); //TODO: Figure out the real packet [Inkfish]
+
+				// Should figure out the real packet.
+				clif_send_quest_delete(sd, sd->quest_log[i].quest_id);
+				clif_send_quest_info(sd, &sd->quest_log[i]);
 				//break;
 			}
 	}
 }
 
-int quest_update_status(TBL_PC * sd, int quest_id, int status)
+int quest_update_status(TBL_PC * sd, int quest_id, quest_state 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
+	//Only status of active and inactive quests can be updated. Completed quests can't (for now). [Inkfish]
+	ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id);
+	if(i == sd->avail_quests)
 	{
-		ShowError("Quest %d not found in your quest log!\n", quest_id);
+		ShowError("quest_update_status: 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 )
+	sd->quest_log[i].state = status;
+
+	if( status < Q_COMPLETE )
 	{
 		clif_send_quest_status(sd, quest_id, (bool)status);
-		sd->quest_log[i].save_quest = true;
+		return 0;
 	}
-	else
+
+	if( i != (--sd->avail_quests) )
 	{
 		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->quest_log[sd->avail_quests].save_quest = true;
 	}
 
-	return 0;
-}
-
-int quest_save(TBL_PC * sd)
-{
-	int i;
-
-	for( i = 0; i < sd->num_quests; i++ )
-		if( sd->quest_log[i].save_quest )
-			intif_quest_save(sd->status.char_id, &sd->quest_log[i]);
-
-	return 0;
-}
-
-int quest_save_ack(int char_id, int quest_id, int success)
-{
+	clif_send_quest_delete(sd, quest_id);
 
-	int i;
-	TBL_PC * sd = map_charid2sd(char_id);
-
-	///Player no longer on map
-	if(!sd)
-		return -1;
-
-	//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;
-
-	if(success)
-		sd->quest_log[i].save_quest = false;
+	if( save_settings&64 )
+		chrif_save(sd,0);
 	else
-	{
-		ShowError("Quest %d for character %d could not be saved!\n", quest_id, char_id);
-		return 1;
-	}
+		intif_quest_save(sd);
 
 	return 0;
-
 }
 
-int quest_check_quest(TBL_PC * sd, int quest_id, quest_check_type type)
+int quest_check(TBL_PC * sd, int quest_id, quest_check_type type)
 {
 	int i;
 

+ 3 - 9
src/map/quest.h

@@ -9,17 +9,11 @@ typedef enum quest_check_type { HAVEQUEST, PLAYTIME, HUNTING } quest_check_type;
 int quest_pc_login(TBL_PC * sd);
 
 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_change(TBL_PC * sd, int qid1, int qid2);
 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_update_status(TBL_PC * sd, int quest_id, quest_state status);
+int quest_check(TBL_PC * sd, int quest_id, quest_check_type type);
 
 int quest_search_db(int quest_id);
 

+ 2 - 9
src/map/script.c

@@ -13447,21 +13447,14 @@ BUILDIN_FUNC(completequest)
 	TBL_PC * sd = script_rid2sd(st);
 
 	quest_update_status(sd, script_getnum(st, 2), Q_COMPLETE);
-	intif_quest_save(sd->status.char_id, &sd->quest_log[sd->avail_quests]);
 	return 0;
 }
 
 BUILDIN_FUNC(changequest)
 {
 	TBL_PC * sd = script_rid2sd(st);
-	int q1 = script_getnum(st, 2), q2 = script_getnum(st, 3);
-
-	if( quest_check_quest(sd, q1, HAVEQUEST) == Q_ACTIVE && !quest_add(sd, q2) )
-	{
-		quest_update_status(sd, q1, Q_COMPLETE);
-		intif_quest_save(sd->status.char_id, &sd->quest_log[sd->avail_quests]);
-	}
 
+	quest_change(sd, script_getnum(st, 2),script_getnum(st, 3));
 	return 0;
 }
 
@@ -13473,7 +13466,7 @@ BUILDIN_FUNC(checkquest)
 	if( script_hasdata(st, 3) )
 		type = (quest_check_type)script_getnum(st, 3);
 
-	script_pushint(st, quest_check_quest(sd, script_getnum(st, 2), type));
+	script_pushint(st, quest_check(sd, script_getnum(st, 2), type));
 
 	return 0;
 }