summaryrefslogtreecommitdiff
path: root/src/map/script.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/script.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/script.c')
-rw-r--r--src/map/script.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/map/script.c b/src/map/script.c
index 9a5d33604..200a43ba0 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -57,6 +57,7 @@
#include "map/status.h"
#include "map/storage.h"
#include "map/unit.h"
+#include "map/achievement.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
#include "common/db.h"
@@ -9574,6 +9575,11 @@ static BUILDIN(successrefitem)
clif->additem(sd,i,1,0);
pc->equipitem(sd,i,ep);
clif->misceffect(&sd->bl,3);
+
+ achievement->validate_refine(sd, i, true); // Achievements [Smokexyz/Hercules]
+
+ /* The following check is exclusive to characters (possibly only whitesmiths)
+ * that create equipments and refine them to level 10. */
if(sd->status.inventory[i].refine == 10 &&
sd->status.inventory[i].card[0] == CARD0_FORGE &&
sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3])
@@ -9611,6 +9617,9 @@ static BUILDIN(failedrefitem)
if (num > 0 && num <= ARRAYLENGTH(script->equip))
i=pc->checkequip(sd,script->equip[num-1]);
if(i >= 0) {
+ // Call before changing refine to 0.
+ achievement->validate_refine(sd, i, false);
+
sd->status.inventory[i].refine = 0;
pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); //recalculate bonus
clif->refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure
@@ -9658,6 +9667,9 @@ static BUILDIN(downrefitem)
clif->additem(sd,i,1,0);
pc->equipitem(sd,i,ep);
+
+ achievement->validate_refine(sd, i, false); // Achievements [Smokexyz/Hercules]
+
clif->misceffect(&sd->bl,2);
}
@@ -21246,6 +21258,78 @@ static BUILDIN(showevent)
}
/*==========================================
+ * Achievement System [Smokexyz/Hercules]
+ *-----------------------------------------*/
+/**
+ * Validates an objective index for the given achievement.
+ * Can be used for any achievement type.
+ * @command achievement_progress(<ach_id>,<obj_idx>,<progress>,<incremental?>{,<char_id>});
+ * @param aid - achievement ID
+ * @param obj_idx - achievement objective index.
+ * @param progress - objective progress towards goal.
+ * @Param incremental - (boolean) true to add the progress towards the goal,
+ * false to use the progress only as a comparand.
+ * @param account_id - (optional) character ID to perform on.
+ * @return true on success, false on failure.
+ * @push 1 on success, 0 on failure.
+ */
+static BUILDIN(achievement_progress)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+ int aid = script_getnum(st, 2);
+ int obj_idx = script_getnum(st, 3);
+ int progress = script_getnum(st, 4);
+ int incremental = script_getnum(st, 5);
+ int account_id = script_hasdata(st, 6) ? script_getnum(st, 6) : 0;
+ const struct achievement_data *ad = NULL;
+
+ if ((ad = achievement->get(aid)) == NULL) {
+ ShowError("buildin_achievement_progress: Invalid achievement ID %d received.\n", aid);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ if (obj_idx <= 0 || obj_idx > VECTOR_LENGTH(ad->objective)) {
+ ShowError("buildin_achievement_progress: Invalid objective index %d received. (min: %d, max: %d)\n", obj_idx, 0, VECTOR_LENGTH(ad->objective));
+ script_pushint(st, 0);
+ return false;
+ }
+
+ obj_idx--; // convert to array index.
+
+ if (progress <= 0 || progress > VECTOR_INDEX(ad->objective, obj_idx).goal) {
+ ShowError("buildin_achievement_progress: Progress exceeds goal limit for achievement id %d.\n", aid);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ if (incremental < 0 || incremental > 1) {
+ ShowError("buildin_achievement_progress: Argument 4 expects boolean (0/1). provided value: %d\n", incremental);
+ script_pushint(st, 0);
+ return false;
+ }
+
+ if (script_hasdata(st, 6)) {
+ if (account_id <= 0) {
+ ShowError("buildin_achievement_progress: Invalid Account id %d provided.\n", account_id);
+ script_pushint(st, 0);
+ return false;
+ } else if ((sd = map->id2sd(account_id)) == NULL) {
+ ShowError("buildin_achievement_progress: Account with id %d was not found.\n", account_id);
+ script_pushint(st, 0);
+ return false;
+ }
+ }
+
+ if (achievement->validate(sd, aid, obj_idx, progress, incremental ? true : false))
+ script_pushint(st, progress);
+ else
+ script_pushint(st, 0);
+
+ return true;
+}
+
+/*==========================================
* BattleGround System
*------------------------------------------*/
static BUILDIN(waitingroom2bg)
@@ -25124,6 +25208,8 @@ static void script_parse_builtin(void)
BUILDIN_DEF(agitstart2,""),
BUILDIN_DEF(agitend2,""),
BUILDIN_DEF(agitcheck2,""),
+ // Achievements [Smokexyz/Hercules]
+ BUILDIN_DEF(achievement_progress, "iiii?"),
// BattleGround
BUILDIN_DEF(waitingroom2bg,"siiss?"),
BUILDIN_DEF(waitingroom2bg_single,"isiis"),