瀏覽代碼

Major updates to the quest system.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@12581 54d463be-8e91-2dee-dedb-b68131a5f0ec
Kevin 17 年之前
父節點
當前提交
302adbf42a

+ 2 - 0
Changelog-Trunk.txt

@@ -4,6 +4,8 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2008/04/13
+	* Some major updates to the quest system, beginning to move it
+	  over to the inter server instead of char server. (r12581) [Kevin]
 	* Added an include in clif.h to avoid a complaint of gcc [Toms]
 	* Quick&dirty reversal of the inter-server behaviour introduced in r3255/r3256:
 	- the behaviour enabled a desynch between the char-server and the map-server

+ 3 - 0
sql-files/upgrade_svn12581.sql

@@ -0,0 +1,3 @@
+ALTER TABLE `quest_objective` ADD COLUMN `char_id` INTEGER UNSIGNED NOT NULL AFTER `num`,
+ DROP PRIMARY KEY,
+ ADD PRIMARY KEY  USING BTREE(`quest_id`, `num`, `char_id`);

+ 2 - 2
src/char_sql/Makefile.in

@@ -14,8 +14,8 @@ COMMON_SQL_OBJ = ../common/obj_sql/sql.o
 COMMON_H = ../common/sql.h
 
 CHAR_OBJ = obj_sql/char.o obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o \
-	obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o
-CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h
+	obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o obj_sql/int_quest.o
+CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h
 
 HAVE_MYSQL=@HAVE_MYSQL@
 ifeq ($(HAVE_MYSQL),yes)

+ 1 - 71
src/char_sql/char.c

@@ -431,7 +431,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
 	int diff = 0;
 	char save_status[128]; //For displaying save information. [Skotlex]
 	struct mmo_charstatus *cp;
-	StringBuf buf, buf2;
+	StringBuf buf;
 
 	if (char_id!=p->char_id) return 0;
 
@@ -644,76 +644,6 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
 			strcat(save_status, " friends");
 	}
 
-	StringBuf_Clear(&buf);
-	StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `quest_id`, `state`) VALUES ", quest_db);
-	for(i=0; i<MAX_QUEST; i++)
-	{
-
-		if(p->quest_log[i].quest_id)
-		{
-			if(diff)
-				StringBuf_AppendStr(&buf, ",");
-			StringBuf_Printf(&buf, "('%d', '%d', '%d')", p->char_id, p->quest_log[i].quest_id, p->quest_log[i].state);
-			diff = 1;
-		}
-
-	}
-
-	if(diff) {
-		if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
-			Sql_ShowDebug(sql_handle);
-		else
-			strcat(save_status, " hotkeys");
-	}
-
-	//save quests
-	StringBuf_Init(&buf2);
-	StringBuf_Clear(&buf);
-	StringBuf_Clear(&buf2);
-	diff = 0;
-	StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `quest_id`, `state`) VALUES ", quest_db);
-	for(i=0; i<MAX_QUEST; i++)
-	{
-
-		if(p->quest_log[i].quest_id)
-		{
-			if(diff)
-				StringBuf_AppendStr(&buf, ",");
-			StringBuf_Printf(&buf, "('%d', '%d', '%d')", p->char_id, p->quest_log[i].quest_id, p->quest_log[i].state);
-			diff = 1;
-
-			StringBuf_Printf(&buf2, "REPLACE INTO `%s` (`quest_id`, `num`, `name`, `count`) VALUES ", quest_obj_db);
-			count = 0;
-			for(j=0; j<p->quest_log[i].num_objectives; j++)
-			{
-
-				if(p->quest_log[i].objectives[j].name)
-				{
-
-					if(count)
-						StringBuf_AppendStr(&buf2, ",");
-					StringBuf_Printf(&buf2, "('%d', '%d', '%s', '%d')", p->quest_log[i].quest_id, j, p->quest_log[i].objectives[j].name, p->quest_log[i].objectives[j].count);
-					count = 1;
-
-				}
-			}
-
-			if(count) {
-				if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf2)) )
-					Sql_ShowDebug(sql_handle);
-			}
-		}
-	}
-
-	if(diff) {
-		if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
-			Sql_ShowDebug(sql_handle);
-		else
-			strcat(save_status, " quests");
-	}
-
-	StringBuf_Destroy(&buf2);
-
 #ifdef HOTKEY_SAVING
 	// hotkeys
 	StringBuf_Clear(&buf);

+ 2 - 0
src/char_sql/char.h

@@ -59,6 +59,8 @@ extern char party_db[256];
 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]
 

+ 112 - 0
src/char_sql/int_quest.c

@@ -0,0 +1,112 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/mmo.h"
+#include "../common/malloc.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/sql.h"
+#include "../common/timer.h"
+
+#include "char.h"
+#include "inter.h"
+#include "int_quest.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+int mapif_parse_quest_delete(int fd)
+{
+
+	bool success = true;
+	int char_id = RFIFOL(fd,2);
+	int quest_id = RFIFOL(fd,6);
+
+	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);
+		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;
+	WFIFOL(fd,6) = quest_id;
+	WFIFOB(fd,10) = success?1:0;
+	WFIFOSET(fd,11);
+
+	return 0;
+
+}
+
+
+int mapif_parse_quest_add(int fd)
+{
+
+	StringBuf buf;
+	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);
+
+
+	if ( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) 
+	{
+		Sql_ShowDebug(sql_handle);
+		success = false;
+	}
+
+	for(i=0; i<qd.num_objectives && success; i++)
+	{
+
+		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);
+
+		if ( success && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
+		{
+			Sql_ShowDebug(sql_handle);
+			success = false;
+		}
+	}
+
+	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;
+
+}
+
+int inter_quest_parse_frommap(int fd)
+{
+
+	switch(RFIFOW(fd,0))
+	{
+		case 0x3061: mapif_parse_quest_add(fd); break;
+		case 0x3062: mapif_parse_quest_delete(fd); break;
+		default:
+			return 0;
+	}
+	return 1;
+
+}

+ 12 - 0
src/char_sql/int_quest.h

@@ -0,0 +1,12 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef _QUEST_H_
+#define _QUEST_H_
+
+/*questlog system*/
+struct quest;
+
+int inter_quest_parse_frommap(int fd);
+
+#endif

+ 3 - 1
src/char_sql/inter.c

@@ -17,6 +17,7 @@
 #include "int_homun.h"
 #include "int_mail.h"
 #include "int_auction.h"
+#include "int_quest.h"
 
 #include <stdio.h>
 #include <string.h>
@@ -56,7 +57,7 @@ int inter_recv_packet_length[] = {
 	-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,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]
-	 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3060-
+	-1,-1,10, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3060-  Quest system [Kevin]
 	 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,	// 3070-
 	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]
@@ -843,6 +844,7 @@ int inter_parse_frommap(int fd)
 		  || inter_homunculus_parse_frommap(fd)
 		  || inter_mail_parse_frommap(fd)
 		  || inter_auction_parse_frommap(fd)
+		  || inter_quest_parse_frommap(fd)
 		   )
 			break;
 		else

+ 58 - 1
src/map/intif.c

@@ -20,6 +20,7 @@
 #include "atcommand.h"
 #include "mercenary.h" //albator
 #include "mail.h"
+#include "quest.h"
 
 #include <sys/types.h>
 #include <stdio.h>
@@ -36,7 +37,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]
-	 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,
+	 0,11,11, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0, //0x3860  Quests [Kevin]
 	 0, 0, 0, 0,  0, 0, 0, 0,  0, 0, 0, 0,  0, 0,  0, 0,
 	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]
@@ -1398,7 +1399,58 @@ int intif_parse_DeleteHomunculusOk(int fd)
 	return 0;
 }
 
+/**************************************
+
+QUESTLOG SYSTEM FUNCTIONS
+
+***************************************/
+
+int intif_parse_questDelete(int fd)
+{
+	quest_delete_ack(RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOB(fd, 10));
+	return 0;
+}
+
+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);
+
+	return 0;
+}
+
+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 sSize = sizeof(struct quest);
+
+	if(CheckForCharServer())
+		return 0;
+
+	WFIFOHEAD(inter_fd, sSize + 8);
+	WFIFOW(inter_fd,0) = 0x3061;
+	WFIFOW(inter_fd,2) = sSize + 8;
+	WFIFOL(inter_fd,4) = char_id;
+	memcpy(WFIFOP(inter_fd,8), qd, sSize);
+	WFIFOSET(inter_fd,  sSize + 8);
+
+	return 0;
+}
+
 #ifndef TXT_ONLY
+
 /*==========================================
  * MAIL SYSTEM
  * By Zephyrus
@@ -1938,6 +1990,11 @@ int intif_parse(int fd)
 	case 0x3841:	intif_parse_GuildCastleDataSave(fd); break;
 	case 0x3842:	intif_parse_GuildCastleAllDataLoad(fd); break;
 	case 0x3843:	intif_parse_GuildMasterChanged(fd); break;
+
+	//Quest system
+	case 0x3861:	intif_parse_questAdd(fd); break;
+	case 0x3862:	intif_parse_questDelete(fd); break;
+
 #ifndef TXT_ONLY
 // Mail System
 	case 0x3848:	intif_parse_Mail_inboxreceived(fd); break;

+ 4 - 0
src/map/intif.h

@@ -75,6 +75,10 @@ int intif_homunculus_requestload(int account_id, int homun_id);
 int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh);
 int intif_homunculus_requestdelete(int homun_id);
 
+/******QUEST SYTEM*******/
+int intif_quest_delete(int char_id, int quest_id);
+int intif_quest_add(int char_id, struct quest * qd);
+
 #ifndef TXT_ONLY
 // MAIL SYSTEM
 int intif_Mail_requestinbox(int char_id, unsigned char flag);

+ 74 - 7
src/map/quest.c

@@ -25,6 +25,7 @@
 #include "log.h"
 #include "clif.h"
 #include "quest.h"
+#include "intif.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -67,13 +68,46 @@ int quest_add(TBL_PC * sd, struct quest * qd)
 	memcpy(&sd->quest_log[i], qd, sizeof(struct quest));
 	sd->num_quests++;
 
-	//Notify client
-	clif_send_quest_info(sd, &sd->quest_log[i]);
+	//Notify inter server
+	intif_quest_add(sd->status.char_id, qd);
 
 	return 0;
 
 }
 
+int quest_add_ack(int char_id, int quest_id, int success)
+{
+	int i;
+	TBL_PC * sd = map_charid2sd(char_id);
+
+	///Player no longer on map
+	if(!sd)
+		return -1;
+
+	//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]);
+	}
+	else
+	{
+		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 0;
+}
+
 int quest_delete(TBL_PC * sd, int quest_id)
 {
 
@@ -83,14 +117,47 @@ int quest_delete(TBL_PC * sd, int quest_id)
 	ARR_FIND(0, MAX_QUEST, i, sd->quest_log[i].quest_id == quest_id);
 
 	//Quest not found
-	if(i != MAX_QUEST)
+	if(i == MAX_QUEST)
 		return -1;
 
-	//Zero quest
-	memset(&sd->quest_log[i], 0, sizeof(struct quest));
+	intif_quest_delete(sd->status.char_id, quest_id);
 
-	//Notify client
-	clif_send_quest_delete(sd, 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);
+
+	///Player no longer on map
+	if(!sd)
+		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)
+		return -1;
+
+	if(success)
+	{
+
+		//Zero quest
+		memset(&sd->quest_log[i], 0, sizeof(struct quest));
+		sd->num_quests--;
+
+		//Notify client
+		clif_send_quest_delete(sd, quest_id);
+
+		return 1;
+
+	}
+	else
+		ShowError("Quest %d for character %d could not be deleted!\n", quest_id, char_id);
 
 	return 0;
 

+ 5 - 0
src/map/quest.h

@@ -7,8 +7,13 @@
 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_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);
 

+ 8 - 0
vcproj-6/char-server_sql.dsp

@@ -251,6 +251,14 @@ SOURCE=..\src\char_sql\int_storage.h
 # End Source File
 # Begin Source File
 
+SOURCE=..\src\char_sql\int_quest.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_quest.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\char_sql\inter.c
 # End Source File
 # Begin Source File

+ 6 - 0
vcproj-7.1/char-server_sql.vcproj

@@ -191,6 +191,12 @@
 			<File
 				RelativePath="..\src\char_sql\int_storage.h">
 			</File>
+			<File
+				RelativePath="..\src\char_sql\int_quest.c">
+			</File>
+			<File
+				RelativePath="..\src\char_sql\int_quest.h">
+			</File>
 			<File
 				RelativePath="..\src\char_sql\inter.c">
 			</File>

+ 8 - 0
vcproj-8/char-server_sql.vcproj

@@ -401,6 +401,14 @@
 				RelativePath="..\src\char_sql\int_storage.h"
 				>
 			</File>
+			<File
+				RelativePath="..\src\char_sql\int_quest.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\char_sql\int_quest.h"
+				>
+			</File>
 			<File
 				RelativePath="..\src\char_sql\inter.c"
 				>

+ 9 - 1
vcproj-9/char-server_sql.vcproj

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="9,00"
+	Version="9.00"
 	Name="char-server_sql"
 	ProjectGUID="{D356871D-58E1-450B-967A-E4E9646175AF}"
 	RootNamespace="char-server_sql"
@@ -391,6 +391,14 @@
 				RelativePath="..\src\char_sql\int_pet.h"
 				>
 			</File>
+			<File
+				RelativePath="..\src\char_sql\int_quest.c"
+				>
+			</File>
+			<File
+				RelativePath="..\src\char_sql\int_quest.h"
+				>
+			</File>
 			<File
 				RelativePath="..\src\char_sql\int_storage.c"
 				>