diff options
author | smokexyz <sagunkho@hotmail.com> | 2018-06-30 04:20:03 +0100 |
---|---|---|
committer | Asheraf <acheraf1998@gmail.com> | 2018-07-24 21:41:20 +0100 |
commit | 19aa33a5f61f0996d76d19db7dbe9d81f5daa090 (patch) | |
tree | b54e07d42a58e34820e3131f750b56b7130cb461 /src/map/intif.c | |
parent | 78c75cade7f445231f11395a6faef9b0a55568dc (diff) | |
download | hercules-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.c | 102 |
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; } |