diff options
Diffstat (limited to 'src/map/script.c')
-rw-r--r-- | src/map/script.c | 107 |
1 files changed, 106 insertions, 1 deletions
diff --git a/src/map/script.c b/src/map/script.c index c68f7c856..cba844c1a 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" @@ -9582,6 +9583,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]) @@ -9619,6 +9625,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 @@ -9666,6 +9675,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); } @@ -13208,6 +13220,7 @@ static BUILDIN(setmapflag) case MF_PVP_NOGUILD: map->list[m].flag.pvp_noguild = 1; break; case MF_GVG: { struct block_list bl; + memset(&bl, 0, sizeof(bl)); map->list[m].flag.gvg = 1; clif->map_property_mapall(m, MAPPROPERTY_AGITZONE); bl.type = BL_NUL; @@ -13294,6 +13307,7 @@ static BUILDIN(removemapflag) case MF_NOZENYPENALTY: map->list[m].flag.nozenypenalty = 0; break; case MF_PVP: { struct block_list bl; + memset(&bl, 0, sizeof(bl)); bl.type = BL_NUL; bl.m = m; map->list[m].flag.pvp = 0; @@ -13305,6 +13319,7 @@ static BUILDIN(removemapflag) case MF_PVP_NOGUILD: map->list[m].flag.pvp_noguild = 0; break; case MF_GVG: { struct block_list bl; + memset(&bl, 0, sizeof(bl)); bl.type = BL_NUL; bl.m = m; map->list[m].flag.gvg = 0; @@ -13372,6 +13387,7 @@ static BUILDIN(pvpon) struct s_mapiterator* iter; struct block_list bl; + memset(&bl, 0, sizeof(bl)); str = script_getstr(st,2); m = map->mapname2mapid(str); if( m < 0 || map->list[m].flag.pvp ) @@ -13432,6 +13448,7 @@ static BUILDIN(pvpoff) const char *str; struct block_list bl; + memset(&bl, 0, sizeof(bl)); str=script_getstr(st,2); m = map->mapname2mapid(str); if(m < 0 || !map->list[m].flag.pvp) @@ -13461,6 +13478,7 @@ static BUILDIN(gvgon) if(m >= 0 && !map->list[m].flag.gvg) { struct block_list bl; + memset(&bl, 0, sizeof(bl)); if( !strdb_exists(map->zone_db,MAP_ZONE_GVG_NAME) ) { ShowError("buildin_gvgon: zone_db missing '%s'\n",MAP_ZONE_GVG_NAME); return true; @@ -13485,6 +13503,7 @@ static BUILDIN(gvgoff) m = map->mapname2mapid(str); if(m >= 0 && map->list[m].flag.gvg) { struct block_list bl; + memset(&bl, 0, sizeof(bl)); map->zone_change2(m, map->list[m].prev_zone); map->list[m].flag.gvg = 0; clif->map_property_mapall(m, MAPPROPERTY_NOTHING); @@ -17772,14 +17791,26 @@ static BUILDIN(getd) char varname[100]; const char *buffer; int elem; + int id; buffer = script_getstr(st, 2); if (sscanf(buffer, "%99[^[][%d]", varname, &elem) < 2) elem = 0; + id = script->search_str(varname); + + if (id < 0 || script->str_data[id].type == C_NOP) { + id = script->add_str(varname); + script->str_data[id].type = C_NAME; + } else if (script->str_data[id].type != C_NAME) { + ShowError("script:getd: `%s` is already used by something that is not a variable.\n", varname); + st->state = END; + return false; + } + // Push the 'pointer' so it's more flexible [Lance] - script->push_val(st->stack, C_NAME, reference_uid(script->add_str(varname), elem),NULL); + script->push_val(st->stack, C_NAME, reference_uid(id, elem),NULL); return true; } @@ -21254,6 +21285,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) @@ -25166,6 +25269,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"), |