/**
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
* Copyright (C) 2018 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 MAP_ACHIEVEMENT_H
#define MAP_ACHIEVEMENT_H
#include "common/hercules.h"
#include "common/db.h"
#include "map/map.h" // enum status_point_types
#define ACHIEVEMENT_NAME_LENGTH 50
#define OBJECTIVE_DESCRIPTION_LENGTH 100
struct achievement;
struct map_session_data;
struct char_achievements;
/**
* Achievement Types
*/
enum achievement_types {
// Quest
ACH_QUEST, // achievement and objective specific
// PC Kills
ACH_KILL_PC_TOTAL,
ACH_KILL_PC_JOB,
ACH_KILL_PC_JOBTYPE,
// Mob Kills
ACH_KILL_MOB_CLASS,
// PC Damage
ACH_DAMAGE_PC_MAX,
ACH_DAMAGE_PC_TOTAL,
ACH_DAMAGE_PC_REC_MAX,
ACH_DAMAGE_PC_REC_TOTAL,
// Mob Damage
ACH_DAMAGE_MOB_MAX,
ACH_DAMAGE_MOB_TOTAL,
ACH_DAMAGE_MOB_REC_MAX,
ACH_DAMAGE_MOB_REC_TOTAL,
// Job
ACH_JOB_CHANGE,
// Status
ACH_STATUS,
ACH_STATUS_BY_JOB,
ACH_STATUS_BY_JOBTYPE,
// Chatroom
ACH_CHATROOM_CREATE_DEAD,
ACH_CHATROOM_CREATE,
ACH_CHATROOM_MEMBERS,
// Friend
ACH_FRIEND_ADD,
// Party
ACH_PARTY_CREATE,
ACH_PARTY_JOIN,
// Marriage
ACH_MARRY,
// Adoption
ACH_ADOPT_BABY,
ACH_ADOPT_PARENT,
// Zeny
ACH_ZENY_HOLD,
ACH_ZENY_GET_ONCE,
ACH_ZENY_GET_TOTAL,
ACH_ZENY_SPEND_ONCE,
ACH_ZENY_SPEND_TOTAL,
// Equipment
ACH_EQUIP_REFINE_SUCCESS,
ACH_EQUIP_REFINE_FAILURE,
ACH_EQUIP_REFINE_SUCCESS_TOTAL,
ACH_EQUIP_REFINE_FAILURE_TOTAL,
ACH_EQUIP_REFINE_SUCCESS_WLV,
ACH_EQUIP_REFINE_FAILURE_WLV,
ACH_EQUIP_REFINE_SUCCESS_ID,
ACH_EQUIP_REFINE_FAILURE_ID,
// Items
ACH_ITEM_GET_COUNT,
ACH_ITEM_GET_COUNT_ITEMTYPE,
ACH_ITEM_GET_WORTH,
ACH_ITEM_SELL_WORTH,
// Monsters
ACH_PET_CREATE,
// Achievement
ACH_ACHIEVE,
ACH_ACHIEVEMENT_RANK,
ACH_TYPE_MAX
};
enum unique_criteria_types {
CRITERIA_UNIQUE_NONE,
CRITERIA_UNIQUE_ACHIEVE_ID,
CRITERIA_UNIQUE_ITEM_ID,
CRITERIA_UNIQUE_STATUS_TYPE,
CRITERIA_UNIQUE_WEAPON_LV
};
/**
* Achievement Objective Structure
*
* @see achievement_type_requires_criteria()
* @see achievement_criteria_mobid()
* @see achievement_criteria_jobid()
* @see achievement_criteria_itemid()
* @see achievement_criteria_stattype()
* @see achievement_criteria_itemtype()
* @see achievement_criteria_weaponlv()
*/
struct achievement_objective {
int goal;
char description[OBJECTIVE_DESCRIPTION_LENGTH];
/**
* Those criteria that do not make sense if stacked together.
* union identifier is set in unique_type. (@see unique_criteria_type)
*/
union {
int achieve_id;
int itemid;
enum status_point_types status_type;
int weapon_lv;
} unique;
enum unique_criteria_types unique_type;
/* */
uint32 item_type;
int mobid;
VECTOR_DECL(int) jobid;
};
struct achievement_reward_item {
int id, amount;
};
struct achievement_rewards {
int title_id;
struct script_code *bonus;
VECTOR_DECL(struct achievement_reward_item) item;
};
/**
* Achievement Data Structure
*/
struct achievement_data {
int id;
char name[ACHIEVEMENT_NAME_LENGTH];
enum achievement_types type;
int points;
VECTOR_DECL(struct achievement_objective) objective;
struct achievement_rewards rewards;
};
// Achievements types that use Mob ID as criteria.
#define achievement_criteria_mobid(t) ( \
(t) == ACH_KILL_MOB_CLASS \
|| (t) == ACH_PET_CREATE )
// Achievements types that use JobID vector as criteria.
#define achievement_criteria_jobid(t) ( \
(t) == ACH_KILL_PC_JOB \
|| (t) == ACH_KILL_PC_JOBTYPE \
|| (t) == ACH_JOB_CHANGE \
|| (t) == ACH_STATUS_BY_JOB \
|| (t) == ACH_STATUS_BY_JOBTYPE )
// Achievements types that use Item ID as criteria.
#define achievement_criteria_itemid(t) ( \
(t) == ACH_ITEM_GET_COUNT \
|| (t) == ACH_EQUIP_REFINE_SUCCESS_ID \
|| (t) == ACH_EQUIP_REFINE_FAILURE_ID )
// Achievements types that use status type parameter as criteria.
#define achievement_criteria_stattype(t) ( \
(t) == ACH_STATUS \
|| (t) == ACH_STATUS_BY_JOB \
|| (t) == ACH_STATUS_BY_JOBTYPE )
// Achievements types that use item type mask as criteria.
#define achievement_criteria_itemtype(t) ( \
(t) == ACH_ITEM_GET_COUNT_ITEMTYPE )
// Achievements types that use weapon level as criteria.
#define achievement_criteria_weaponlv(t) ( \
(t) == ACH_EQUIP_REFINE_SUCCESS_WLV \
|| (t) == ACH_EQUIP_REFINE_FAILURE_WLV )
// Valid status types for objective criteria.
#define achievement_valid_status_types(s) ( \
(s) == SP_STR \
|| (s) == SP_AGI \
|| (s) == SP_VIT \
|| (s) == SP_INT \
|| (s) == SP_DEX \
|| (s) == SP_LUK \
|| (s) == SP_BASELEVEL || (s) == SP_JOBLEVEL )
struct achievement_interface {
struct DBMap *db; // int id -> struct achievement_data *
/* */
VECTOR_DECL(int) rank_exp; // Achievement Rank Exp Requirements
VECTOR_DECL(int) category[ACH_TYPE_MAX]; /* A collection of Ids per type for faster processing. */
/* */
void (*init) (bool minimal);
void (*final) (void);
/* */
int (*db_finalize) (union DBKey key, struct DBData *data, va_list args);
/* */
void (*readdb)(void);
/* */
bool (*readdb_objectives_sub) (const struct config_setting_t *conf, int index, struct achievement_data *entry);
bool (*readdb_objectives) (const struct config_setting_t *conf, struct achievement_data *entry);
/* */
bool (*readdb_validate_criteria_mobid) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
bool (*readdb_validate_criteria_jobid) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
bool (*readdb_validate_criteria_itemid) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
bool (*readdb_validate_criteria_statustype) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
bool (*readdb_validate_criteria_itemtype) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
bool (*readdb_validate_criteria_weaponlv) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
bool (*readdb_validate_criteria_achievement) (const struct config_setting_t *t, struct achievement_objective *obj, enum achievement_types type, int entry_id, int obj_idx);
/* */
bool (*readdb_rewards) (const struct config_setting_t *conf, struct achievement_data *entry, const char *source);
void (*readdb_validate_reward_items) (const struct config_setting_t *t, struct achievement_data *entry);
bool (*readdb_validate_reward_item_sub) (const struct config_setting_t *t, int element, struct achievement_data *entry);
void (*readdb_validate_reward_bonus) (const struct config_setting_t *t, struct achievement_data *entry, const char *source);
void (*readdb_validate_reward_titleid) (const struct config_setting_t *t, struct achievement_data *entry);
/* */
void (*readdb_additional_fields) (const struct config_setting_t *conf, struct achievement_data *entry, const char *source);
/* */
void (*readdb_ranks) (void);
/* */
const struct achievement_data *(*get) (int aid);
struct achievement *(*ensure) (struct map_session_data *sd, const struct achievement_data *ad);
/* */
void (*calculate_totals) (const struct map_session_data *sd, int *points, int *completed, int *rank, int *curr_rank_points);
bool (*check_complete) (struct map_session_data *sd, const struct achievement_data *ad);
void (*progress_add) (struct map_session_data *sd, const struct achievement_data *ad, unsigned int obj_idx, int progress);
void (*progress_set) (struct map_session_data *sd, const struct achievement_data *ad, unsigned int obj_idx, int progress);
bool (*check_criteria) (const struct achievement_objective *objective, const struct achievement_objective *criteria);
/* */
bool (*validate) (struct map_session_data *sd, int aid, unsigned int obj_idx, int progress, bool additive);
int (*validate_type) (struct map_session_data *sd, enum achievement_types type, const struct achievement_objective *criteria, bool additive);
/* */
void (*validate_mob_kill) (struct map_session_data *sd, int mob_id);
void (*validate_mob_damage) (struct map_session_data *sd, unsigned int damage, bool received);
void (*validate_pc_kill) (struct map_session_data *sd, struct map_session_data *dstsd);
void (*validate_pc_damage) (struct map_session_data *sd, struct map_session_data *dstsd, unsigned int damage);
void (*validate_jobchange) (struct map_session_data *sd);
void (*validate_stats) (struct map_session_data *sd, enum status_point_types stat_type, int progress);
void (*validate_chatroom_create) (struct map_session_data *sd);
void (*validate_chatroom_members) (struct map_session_data *sd, int progress);
void (*validate_friend_add) (struct map_session_data *sd);
void (*validate_party_create) (struct map_session_data *sd);
void (*validate_marry) (struct map_session_data *sd);
void (*validate_adopt) (struct map_session_data *sd, bool parent);
void (*validate_zeny) (struct map_session_data *sd, int amount);
void (*validate_refine) (struct map_session_data *sd, unsigned int idx, bool success);
void (*validate_item_get) (struct map_session_data *sd, int nameid, int amount);
void (*validate_item_sell) (struct map_session_data *sd, int nameid, int amount);
void (*validate_achieve) (struct map_session_data *sd, int achid);
void (*validate_taming) (struct map_session_data *sd, int class);
void (*validate_achievement_rank) (struct map_session_data *sd, int rank);
/* */
bool (*type_requires_criteria) (enum achievement_types type);
};
#ifdef HERCULES_CORE
void achievement_defaults(void);
#endif // HERCULES_CORE
HPShared struct achievement_interface *achievement;
#endif // MAP_ACHIEVEMENT_H