summaryrefslogtreecommitdiff
path: root/src/char
diff options
context:
space:
mode:
authorsmokexyz <sagunkho@hotmail.com>2017-06-03 00:29:11 +0800
committerAsheraf <acheraf1998@gmail.com>2018-07-24 21:41:14 +0100
commit78c75cade7f445231f11395a6faef9b0a55568dc (patch)
treeea355aea2cbfd8bb8fdeaf0f1dd7065e961cd9d5 /src/char
parentea76a9c9e2a59158b0d30e4df8c3b06fb19a3778 (diff)
downloadhercules-78c75cade7f445231f11395a6faef9b0a55568dc.tar.gz
hercules-78c75cade7f445231f11395a6faef9b0a55568dc.tar.bz2
hercules-78c75cade7f445231f11395a6faef9b0a55568dc.tar.xz
hercules-78c75cade7f445231f11395a6faef9b0a55568dc.zip
Add achievement source files.
Co-authored-by: "Dastgir" <dastgirp@gmail.com>
Diffstat (limited to 'src/char')
-rw-r--r--src/char/Makefile.in8
-rw-r--r--src/char/int_achievement.c252
-rw-r--r--src/char/int_achievement.h53
3 files changed, 309 insertions, 4 deletions
diff --git a/src/char/Makefile.in b/src/char/Makefile.in
index 49fc8ec92..b79958679 100644
--- a/src/char/Makefile.in
+++ b/src/char/Makefile.in
@@ -40,12 +40,12 @@ MT19937AR_D = $(THIRDPARTY_D)/mt19937ar
MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
-CHAR_C = char.c HPMchar.c loginif.c mapif.c geoip.c inter.c int_auction.c int_clan.c int_elemental.c int_guild.c \
- int_homun.c int_mail.c int_mercenary.c int_party.c int_pet.c \
+CHAR_C = char.c HPMchar.c loginif.c mapif.c geoip.c inter.c int_achievement.c int_auction.c int_clan.c int_elemental.c \
+ int_guild.c int_homun.c int_mail.c int_mercenary.c int_party.c int_pet.c \
int_quest.c int_rodex.c int_storage.c pincode.c
CHAR_OBJ = $(addprefix obj_sql/, $(patsubst %.c,%.o,$(CHAR_C)))
-CHAR_H = char.h HPMchar.h loginif.h mapif.h geoip.h inter.h int_auction.h int_clan.h int_elemental.h int_guild.h \
- int_homun.h int_mail.h int_mercenary.h int_party.h int_pet.h \
+CHAR_H = char.h HPMchar.h loginif.h mapif.h geoip.h inter.h int_achievement.h int_auction.h int_clan.h int_elemental.h
+ int_guild.h int_homun.h int_mail.h int_mercenary.h int_party.h int_pet.h \
int_quest.h int_rodex.h int_storage.h pincode.h
CHAR_PH =
diff --git a/src/char/int_achievement.c b/src/char/int_achievement.c
new file mode 100644
index 000000000..14311ecf0
--- /dev/null
+++ b/src/char/int_achievement.c
@@ -0,0 +1,252 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2017 Hercules Dev Team
+* Copyright (C) Smokexyz
+*
+* Hercules is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#define HERCULES_CORE
+
+#include "int_achievement.h"
+
+#include "char/char.h"
+#include "char/inter.h"
+#include "char/mapif.h"
+
+#include "common/db.h"
+#include "common/memmgr.h"
+#include "common/mmo.h"
+#include "common/nullpo.h"
+#include "common/showmsg.h"
+#include "common/socket.h"
+#include "common/sql.h"
+#include "common/strlib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static struct inter_achievement_interface inter_achievement_s;
+struct inter_achievement_interface *inter_achievement;
+
+/**
+ * Saves changed achievements for a character.
+ * @param[in] char_id character identifier.
+ * @param[out] cp pointer to loaded achievements.
+ * @param[in] p pointer to map-sent character achievements.
+ * @return number of achievements saved.
+ */
+static int inter_achievement_tosql(int char_id, struct char_achievements *cp, const struct char_achievements *p)
+{
+ StringBuf buf;
+ int i = 0, rows = 0;
+
+ nullpo_ret(cp);
+ nullpo_ret(p);
+ Assert_ret(char_id > 0);
+
+ StrBuf->Init(&buf);
+ StrBuf->Printf(&buf, "REPLACE INTO `%s` (`char_id`, `ach_id`, `completed_at`, `rewarded_at`", char_achievement_db);
+ for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; i++)
+ StrBuf->Printf(&buf, ", `obj_%d`", i);
+ StrBuf->AppendStr(&buf, ") VALUES ");
+
+ for (i = 0; i < VECTOR_LENGTH(*p); i++) {
+ int j = 0;
+ bool save = false;
+ struct achievement *pa = &VECTOR_INDEX(*p, i), *cpa = NULL;
+
+ ARR_FIND(0, VECTOR_LENGTH(*cp), j, ((cpa = &VECTOR_INDEX(*cp, j)) && cpa->id == pa->id));
+
+ if (j == VECTOR_LENGTH(*cp))
+ save = true;
+ else if (memcmp(cpa, pa, sizeof(struct achievement)) != 0)
+ save = true;
+
+ if (save) {
+ StrBuf->Printf(&buf, "%s('%d', '%d', '%"PRId64"', '%"PRId64"'", rows ?", ":"", char_id, pa->id, (int64)pa->completed_at, (int64)pa->rewarded_at);
+ for (j = 0; j < MAX_ACHIEVEMENT_OBJECTIVES; j++)
+ StrBuf->Printf(&buf, ", '%d'", pa->objective[j]);
+ StrBuf->AppendStr(&buf, ")");
+ rows++;
+ }
+ }
+
+ if (rows > 0 && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
+ Sql_ShowDebug(inter->sql_handle);
+ StrBuf->Destroy(&buf); // Destroy the buffer.
+ return 0;
+ }
+ // Destroy the buffer.
+ StrBuf->Destroy(&buf);
+
+ if (rows) {
+ ShowInfo("achievements saved for char %d (total: %d, saved: %d)\n", char_id, VECTOR_LENGTH(*p), rows);
+
+ /* Sync with inter-db acheivements. */
+ VECTOR_CLEAR(*cp);
+ VECTOR_ENSURE(*cp, VECTOR_LENGTH(*p), 1);
+ VECTOR_PUSHARRAY(*cp, VECTOR_DATA(*p), VECTOR_LENGTH(*p));
+ }
+
+ return rows;
+}
+
+/**
+ * Retrieves all achievements of a character.
+ * @param[in] char_id character identifier.
+ * @param[out] cp pointer to character achievements structure.
+ * @return true on success, false on failure.
+ */
+static bool inter_achievement_fromsql(int char_id, struct char_achievements *cp)
+{
+ StringBuf buf;
+ char *data;
+ int i = 0, num_rows = 0;
+
+ nullpo_ret(cp);
+
+ Assert_ret(char_id > 0);
+
+ // char_achievements (`char_id`, `ach_id`, `completed_at`, `rewarded_at`, `obj_0`, `obj_2`, ...`obj_9`)
+ StrBuf->Init(&buf);
+ StrBuf->AppendStr(&buf, "SELECT `ach_id`, `completed_at`, `rewarded_at`");
+ for (i = 0; i < MAX_ACHIEVEMENT_OBJECTIVES; i++)
+ StrBuf->Printf(&buf, ", `obj_%d`", i);
+ StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id` = '%d' ORDER BY `ach_id`", char_achievement_db, char_id);
+
+ if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
+ Sql_ShowDebug(inter->sql_handle);
+ StrBuf->Destroy(&buf);
+ return false;
+ }
+
+ VECTOR_CLEAR(*cp);
+
+ if ((num_rows = (int) SQL->NumRows(inter->sql_handle)) != 0) {
+ int j = 0;
+
+ VECTOR_ENSURE(*cp, num_rows, 1);
+
+ for (i = 0; i < num_rows && SQL_SUCCESS == SQL->NextRow(inter->sql_handle); i++) {
+ struct achievement t_ach = { 0 };
+ SQL->GetData(inter->sql_handle, 0, &data, NULL); t_ach.id = atoi(data);
+ SQL->GetData(inter->sql_handle, 1, &data, NULL); t_ach.completed_at = atoi(data);
+ SQL->GetData(inter->sql_handle, 2, &data, NULL); t_ach.rewarded_at = atoi(data);
+ /* Objectives */
+ for (j = 0; j < MAX_ACHIEVEMENT_OBJECTIVES; j++) {
+ SQL->GetData(inter->sql_handle, j + 3, &data, NULL);
+ t_ach.objective[j] = atoi(data);
+ }
+ /* Add Entry */
+ VECTOR_PUSH(*cp, t_ach);
+ }
+ }
+
+ SQL->FreeResult(inter->sql_handle);
+
+ StrBuf->Destroy(&buf);
+
+ if (num_rows > 0)
+ ShowInfo("achievements loaded for char %d (total: %d)\n", char_id, num_rows);
+
+ return true;
+}
+
+/**
+ * Handles checking of map server packets and calls appropriate functions.
+ * @param fd socket descriptor.
+ * @return 0 on failure, 1 on succes.
+ */
+static int inter_achievement_parse_frommap(int fd)
+{
+ RFIFOHEAD(fd);
+
+ switch (RFIFOW(fd,0)) {
+ case 0x3012:
+ mapif->pLoadAchievements(fd);
+ break;
+ case 0x3013:
+ mapif->pSaveAchievements(fd);
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * Initialization function
+ */
+static int inter_achievement_sql_init(void)
+{
+ // Initialize the loaded db storage.
+ // used as a comparand against map-server achievement data before saving.
+ inter_achievement->char_achievements = idb_alloc(DB_OPT_RELEASE_DATA);
+ return 1;
+}
+
+/**
+ * This function ensures idb's entry.
+ */
+static struct DBData inter_achievement_ensure_char_achievements(union DBKey key, va_list args)
+{
+ struct char_achievements *ca = NULL;
+
+ CREATE(ca, struct char_achievements, 1);
+ VECTOR_INIT(*ca);
+
+ return DB->ptr2data(ca);
+}
+
+/**
+ * Cleaning function called through db_destroy()
+ */
+static int inter_achievement_char_achievements_clear(union DBKey key, struct DBData *data, va_list args)
+{
+ struct char_achievements *ca = DB->data2ptr(data);
+
+ VECTOR_CLEAR(*ca);
+
+ return 0;
+}
+
+/**
+ * Finalization function.
+ */
+static void inter_achievement_sql_final(void)
+{
+ inter_achievement->char_achievements->destroy(inter_achievement->char_achievements, inter_achievement->char_achievements_clear);
+}
+
+/**
+ * Inter-achievement interface.
+ */
+void inter_achievement_defaults(void)
+{
+ inter_achievement = &inter_achievement_s;
+ /* */
+ inter_achievement->ensure_char_achievements = inter_achievement_ensure_char_achievements;
+ /* */
+ inter_achievement->sql_init = inter_achievement_sql_init;
+ inter_achievement->sql_final = inter_achievement_sql_final;
+ /* */
+ inter_achievement->tosql = inter_achievement_tosql;
+ inter_achievement->fromsql = inter_achievement_fromsql;
+ /* */
+ inter_achievement->parse_frommap = inter_achievement_parse_frommap;
+ inter_achievement->char_achievements_clear = inter_achievement_char_achievements_clear;
+}
diff --git a/src/char/int_achievement.h b/src/char/int_achievement.h
new file mode 100644
index 000000000..4a44a798d
--- /dev/null
+++ b/src/char/int_achievement.h
@@ -0,0 +1,53 @@
+/**
+* This file is part of Hercules.
+* http://herc.ws - http://github.com/HerculesWS/Hercules
+*
+* Copyright (C) 2017 Hercules Dev Team
+* Copyright (C) Smokexyz
+*
+* Hercules is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef CHAR_INT_ACHIEVEMENT_H
+#define CHAR_INT_ACHIEVEMENT_H
+
+#include "common/hercules.h"
+#include "common/db.h"
+
+struct achievement;
+struct char_achievements;
+
+/**
+ * inter_achievement Interface
+ */
+struct inter_achievement_interface {
+ struct DBMap *char_achievements;
+ /* */
+ int (*sql_init) (void);
+ void (*sql_final) (void);
+ /* */
+ int (*tosql) (int char_id, struct char_achievements *cp, const struct char_achievements *p);
+ bool (*fromsql) (int char_id, struct char_achievements *a);
+ /* */
+ struct DBData(*ensure_char_achievements) (union DBKey key, va_list args);
+ int (*char_achievements_clear) (union DBKey key, struct DBData *data, va_list args);
+ /* */
+ int (*parse_frommap) (int fd);
+};
+
+#ifdef HERCULES_CORE
+void inter_achievement_defaults(void);
+#endif // HERCULES_CORE
+
+HPShared struct inter_achievement_interface *inter_achievement;
+#endif /* CHAR_INT_ACHIEVEMENT_H */