summaryrefslogtreecommitdiff
path: root/src/map/intif.c
diff options
context:
space:
mode:
authorsmokexyz <sagunkho@hotmail.com>2018-06-30 04:20:03 +0100
committerAsheraf <acheraf1998@gmail.com>2018-07-24 21:41:20 +0100
commit19aa33a5f61f0996d76d19db7dbe9d81f5daa090 (patch)
treeb54e07d42a58e34820e3131f750b56b7130cb461 /src/map/intif.c
parent78c75cade7f445231f11395a6faef9b0a55568dc (diff)
downloadhercules-19aa33a5f61f0996d76d19db7dbe9d81f5daa090.tar.gz
hercules-19aa33a5f61f0996d76d19db7dbe9d81f5daa090.tar.bz2
hercules-19aa33a5f61f0996d76d19db7dbe9d81f5daa090.tar.xz
hercules-19aa33a5f61f0996d76d19db7dbe9d81f5daa090.zip
Implementation of the official Achievement System.
Source: http://ro.gnjoy.com/news/update/View.asp?seq=163&curpage=1 Script Commands - ``` achievement_progress(<ach_id>,<obj_idx>,<progress>,<incremental?>{,<char_id>}); ``` Includes an achievement_db.conf generator that reads from the item_db, mob_db (server side) and achievement_list.lub files to determine valid achievement entries based on item/monster availability. Achievements containing unsupported entries are commented out. This feature, although renewal-only in official servers, is capable of being used in pre-renewal mode on Hercules. Does not include the title system yet. A big thanks to - @MishimaHaruna for constantly reviewing. @4144 for all the support. @Asheraf for a lot of official information. Co-authored-by: "Dastgir" <dastgirp@gmail.com>
Diffstat (limited to 'src/map/intif.c')
-rw-r--r--src/map/intif.c102
1 files changed, 101 insertions, 1 deletions
diff --git a/src/map/intif.c b/src/map/intif.c
index 393058a8a..a5dc9c575 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -41,6 +41,8 @@
#include "map/quest.h"
#include "map/rodex.h"
#include "map/storage.h"
+#include "map/achievement.h"
+
#include "common/memmgr.h"
#include "common/nullpo.h"
#include "common/showmsg.h"
@@ -1730,6 +1732,98 @@ static void intif_parse_DeleteHomunculusOk(int fd)
ShowError("Homunculus data delete failure\n");
}
+/***************************************
+ * ACHIEVEMENT SYSTEM FUNCTIONS
+ ***************************************/
+/**
+ * Sends a request to the inter-server to load
+ * and send a character's achievement data.
+ * @packet [out] 0x3012 <char_id>.L
+ * @param sd pointer to map_session_data.
+ */
+static void intif_achievements_request(struct map_session_data *sd)
+{
+ nullpo_retv(sd);
+
+ if (intif->CheckForCharServer())
+ return;
+
+ WFIFOHEAD(inter_fd, 6);
+ WFIFOW(inter_fd, 0) = 0x3012;
+ WFIFOL(inter_fd, 2) = sd->status.char_id;
+ WFIFOSET(inter_fd, 6);
+}
+
+/**
+ * Handles reception of achievement data for a character from the inter-server.
+ * @packet [in] 0x3810 <packet_len>.W <char_id>.L <char_achievements[]>.P
+ * @param fd socket descriptor.
+ */
+static void intif_parse_achievements_load(int fd)
+{
+ int size = RFIFOW(fd, 2);
+ int char_id = RFIFOL(fd, 4);
+ int payload_count = (size - 8) / sizeof(struct achievement);
+ struct map_session_data *sd = map->charid2sd(char_id);
+ int i = 0;
+
+ if (sd == NULL) {
+ ShowError("intif_parse_achievements_load: Parse request for achievements received but character is offline!\n");
+ return;
+ }
+
+ if (VECTOR_LENGTH(sd->achievement) > 0) {
+ ShowError("intif_parse_achievements_load: Achievements already loaded! Possible multiple calls from the inter-server received.\n");
+ return;
+ }
+
+ VECTOR_ENSURE(sd->achievement, payload_count, 1);
+
+ for (i = 0; i < payload_count; i++) {
+ struct achievement t_ach = { 0 };
+
+ memcpy(&t_ach, RFIFOP(fd, 8 + i * sizeof(struct achievement)), sizeof(struct achievement));
+
+ if (achievement->get(t_ach.id) == NULL) {
+ ShowError("intif_parse_achievements_load: Invalid Achievement %d received from character %d. Ignoring...\n", t_ach.id, char_id);
+ continue;
+ }
+
+ VECTOR_PUSH(sd->achievement, t_ach);
+ }
+
+ clif->achievement_send_list(fd, sd);
+ sd->achievements_received = true;
+}
+
+/**
+ * Send character's achievement data to the inter-server.
+ * @packet 0x3013 <packet_len>.W <char_id>.L <achievements[]>.P
+ * @param sd pointer to map session data.
+ */
+static void intif_achievements_save(struct map_session_data *sd)
+{
+ int packet_len = 0, payload_size = 0, i = 0;
+
+ nullpo_retv(sd);
+ /* check for character server. */
+ if (intif->CheckForCharServer())
+ return;
+ /* Return if no data. */
+ if (!(payload_size = VECTOR_LENGTH(sd->achievement) * sizeof(struct achievement)))
+ return;
+
+ packet_len = payload_size + 8;
+
+ WFIFOHEAD(inter_fd, packet_len);
+ WFIFOW(inter_fd, 0) = 0x3013;
+ WFIFOW(inter_fd, 2) = packet_len;
+ WFIFOL(inter_fd, 4) = sd->status.char_id;
+ for (i = 0; i < VECTOR_LENGTH(sd->achievement); i++)
+ memcpy(WFIFOP(inter_fd, 8 + i * sizeof(struct achievement)), &VECTOR_INDEX(sd->achievement, i), sizeof(struct achievement));
+ WFIFOSET(inter_fd, packet_len);
+}
+
/**************************************
* QUESTLOG SYSTEM FUNCTIONS *
**************************************/
@@ -2799,6 +2893,7 @@ static int intif_parse(int fd)
case 0x3806: intif->pChangeNameOk(fd); break;
case 0x3807: intif->pMessageToFD(fd); break;
case 0x3808: intif->pAccountStorageSaveAck(fd); break;
+ case 0x3810: intif->pAchievementsLoad(fd); break;
case 0x3818: intif->pLoadGuildStorage(fd); break;
case 0x3819: intif->pSaveGuildStorage(fd); break;
case 0x3820: intif->pPartyCreated(fd); break;
@@ -2896,7 +2991,7 @@ void intif_defaults(void)
{
const int packet_len_table [INTIF_PACKET_LEN_TABLE_SIZE] = {
-1,-1,27,-1, -1,-1,37,-1, 7, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f
- 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810
+ -1, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 Achievements [Smokexyz/Hercules]
39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820
10,-1,15, 0, 79,23, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830
-1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
@@ -3001,6 +3096,9 @@ void intif_defaults(void)
intif->CheckForCharServer = CheckForCharServer;
/* */
intif->itembound_req = intif_itembound_req;
+ /* Achievement System */
+ intif->achievements_request = intif_achievements_request;
+ intif->achievements_save = intif_achievements_save;
/* parse functions */
intif->pWisMessage = intif_parse_WisMessage;
intif->pWisEnd = intif_parse_WisEnd;
@@ -3073,4 +3171,6 @@ void intif_defaults(void)
intif->pRodexCheckName = intif_parse_RodexCheckName;
/* Clan System */
intif->pRecvClanMemberAction = intif_parse_RecvClanMemberAction;
+ /* Achievement System */
+ intif->pAchievementsLoad = intif_parse_achievements_load;
}