diff --git a/src/common/conf.h b/src/common/conf.h index 666853b..d223505 100644 --- a/src/common/conf.h +++ b/src/common/conf.h @@ -5,7 +5,7 @@ #define _CONF_H_ #include "../common/cbasetypes.h" -#include "libconfig.h" +#include "../../3rdparty/libconfig/libconfig.h" int conf_read_file(config_t *config, const char *config_filename); int config_setting_copy(config_setting_t *parent, const config_setting_t *src); diff --git a/src/common/utils.c b/src/common/utils.c index d799285..6986d9a 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -321,3 +321,15 @@ unsigned int get_percentage(const unsigned int A, const unsigned int B) return (unsigned int)floor(result); } + +///comparator for qsort +//comparing int +int compare_int(const void *a,const void *b) { + int *x = (int *) a; + int *y = (int *) b; + return *x - *y; +} +//comparing string +int compare_str(const void *a,const void *b) { + return (strcmp((char *)a,(char *)b)); +} diff --git a/src/common/utils.h b/src/common/utils.h index 6ce1639..b98452d 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -30,5 +30,7 @@ extern uint16 MakeWord(uint8 byte0, uint8 byte1); extern uint32 MakeDWord(uint16 word0, uint16 word1); int date2version(int date); +int compare_int(const void *a,const void *b); +int compare_str(const void *a,const void *b); #endif /* _UTILS_H_ */ diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 80bc5d0..fcfd94b 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -8486,6 +8486,11 @@ static int atcommand_mutearea_sub(struct block_list *bl,va_list ap) return 0; } +//comparing atcommand +int compare_atc(const void *a,const void *b) { + return compare_str(((struct AtCommandInfo*)a)->command,((struct AtCommandInfo*)b)->command); +} + /*========================================== * type: 1 = commands (@), 2 = charcommands (#) *------------------------------------------*/ @@ -8493,18 +8498,18 @@ static void atcommand_commands_sub(struct map_session_data* sd, const int fd, At { char line_buff[CHATBOX_SIZE]; char* cur = line_buff; - AtCommandInfo* cmd; + AtCommandInfo *cmd, **commands_li; DBIterator *iter = db_iterator(atcommand_db); - int count = 0; + int count = 0, i=0; + CREATE(commands_li, AtCommandInfo *, db_size(atcommand_db)); + memset(line_buff,' ',CHATBOX_SIZE); line_buff[CHATBOX_SIZE-1] = 0; clif_displaymessage(fd, msg_txt(sd,273)); // "Commands available:" for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { - unsigned int slen = 0; - switch( type ) { case COMMAND_CHARCOMMAND: if( cmd->char_groups[sd->group_pos] == 0 ) @@ -8517,9 +8522,14 @@ static void atcommand_commands_sub(struct map_session_data* sd, const int fd, At default: continue; } - - - slen = strlen(cmd->command); + strcpy(commands_li[count]->command,cmd->command); + count++; + } + dbi_destroy(iter); + + qsort(commands_li,count,sizeof(struct AtCommandInfo),compare_atc); + for(i=0; icommand); // flush the text buffer if this command won't fit into it if (slen + cur - line_buff >= CHATBOX_SIZE) { @@ -8528,13 +8538,10 @@ static void atcommand_commands_sub(struct map_session_data* sd, const int fd, At memset(line_buff,' ',CHATBOX_SIZE); line_buff[CHATBOX_SIZE-1] = 0; } - - memcpy(cur,cmd->command,slen); + memcpy(cur,commands_li[i]->command,slen); cur += slen+(10-slen%10); - - count++; } - dbi_destroy(iter); + aFree(commands_li); clif_displaymessage(fd,line_buff); sprintf(atcmd_output, msg_txt(sd,274), count); // "%d commands found." @@ -9307,7 +9314,7 @@ void atcommand_basecommands(void) { ACMD_DEF(langtype), }; AtCommandInfo* atcommand; - int i; + int i = 0; for( i = 0; i < ARRAYLENGTH(atcommand_base); i++ ) { if(atcommand_exists(atcommand_base[i].command)) { // Should not happen if atcommand_base[] array is OK diff --git a/src/map/skill.c b/src/map/skill.c index 39a365a..d0674a5 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1,5 +1,14 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +/** + * \file skill.c + * \brief Skills behaviour implementation + * \author Athena Dev Teams + * + * Module purpose is to handle how skill with interact with player/mob/.. and what kind of actions it will create. + * No dammage calculation is done here nor status effect. + * + * Licensed under GNU GPL + * For more information, see LICENCE in the main folder + */ #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -79,12 +88,15 @@ struct skill_cd { /** * Skill Unit Persistency during endack routes (mostly for songs see bugreport:4574) - **/ + */ DBMap* skillusave_db = NULL; // char_id -> struct skill_usave struct skill_usave { uint16 skill_id, skill_lv; }; +/** + * Skill_dbs + */ struct s_skill_db skill_db[MAX_SKILL_DB]; struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB]; struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB]; @@ -92,29 +104,22 @@ struct skill_usave { struct s_skill_improvise_db { uint16 skill_id; short per;//1-10000 -}; -struct s_skill_improvise_db skill_improvise_db[MAX_SKILL_IMPROVISE_DB]; +} skill_improvise_db[MAX_SKILL_IMPROVISE_DB]; bool skill_reproduce_db[MAX_SKILL_DB]; struct s_skill_changematerial_db { int itemid; short rate; int qty[5]; short qty_rate[5]; -}; -struct s_skill_changematerial_db skill_changematerial_db[MAX_SKILL_PRODUCE_DB]; - -//Warlock +} skill_changematerial_db[MAX_SKILL_PRODUCE_DB]; struct s_skill_spellbook_db { int nameid; uint16 skill_id; int point; -}; - -struct s_skill_spellbook_db skill_spellbook_db[MAX_SKILL_SPELLBOOK_DB]; -//Guillotine Cross +} skill_spellbook_db[MAX_SKILL_SPELLBOOK_DB]; struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB]; - struct s_skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT]; + int firewall_unit_pos; int icewall_unit_pos; int earthstrain_unit_pos; @@ -133,16 +138,24 @@ static inline int splash_target(struct block_list* bl) { #endif } -/// Returns the id of the skill, or 0 if not found. +/** + * Get the associated id of a skillname + * + * \param name : skill name + * \return id of the skill, or 0 if not found. + **/ int skill_name2id(const char* name) { if( name == NULL ) return 0; - return strdb_iget(skilldb_name2id, name); } -/// Maps skill ids to skill db offsets. -/// Returns the skill's array index, or 0 (Unknown Skill). +/** + * Get the db index of a skill_id + * + * \param skill_id : The skill number + * \return the skill's array index, or 0 (Unknown Skill). + **/ int skill_get_index( uint16 skill_id ) { // avoid ranges reserved for mapping guild/homun/mercenary skills if( (skill_id >= GD_SKILLRANGEMIN && skill_id <= GD_SKILLRANGEMAX) @@ -150,7 +163,7 @@ int skill_get_index( uint16 skill_id ) { || (skill_id >= MC_SKILLRANGEMIN && skill_id <= MC_SKILLRANGEMAX) || (skill_id >= EL_SKILLRANGEMIN && skill_id <= EL_SKILLRANGEMAX) ) return 0; - + // map skill id to skill db index if( skill_id >= GD_SKILLBASE ) skill_id = GD_SKILLRANGEMIN + skill_id - GD_SKILLBASE; @@ -168,15 +181,33 @@ int skill_get_index( uint16 skill_id ) { return skill_id; } +/** + * Get the skill_name of a skill_id + * + * \param skill_id : The skill number + * \return the skill's name as a string, could be null + **/ const char* skill_get_name( uint16 skill_id ) { return skill_db[skill_get_index(skill_id)].name; } +/** + * Get the skill_desc of a skill_id + * + * \param skill_id : The skill number + * \return the skill's description as a string, could be null + **/ const char* skill_get_desc( uint16 skill_id ) { return skill_db[skill_get_index(skill_id)].desc; } // out of bounds error checking [celest] +/** + * Get the skill_name of a skill_id + * + * \param skill_id : The skill number + * \return the skill's name as a string, could be null + **/ static void skill_chk(int16* skill_id, uint16 skill_lv) { *skill_id = skill_get_index(*skill_id); // checks/adjusts id if( skill_lv > MAX_SKILL_LEVEL ) *skill_id = 0; @@ -15560,17 +15591,21 @@ int skill_delunit (struct skill_unit* unit) { *------------------------------------------*/ static DBMap* group_db = NULL;// int group_id -> struct skill_unit_group* -/// Returns the target skill_unit_group or NULL if not found. -struct skill_unit_group* skill_id2group(int group_id) -{ +/** + * Returns the target skill_unit_group or NULL if not found. + **/ +struct skill_unit_group* skill_id2group(int group_id) { return (struct skill_unit_group*)idb_get(group_db, group_id); } static int skill_unit_group_newid = MAX_SKILL_DB; -/// Returns a new group_id that isn't being used in group_db. -/// Fatal error if nothing is available. +/** + * Generate a new group_id that isn't being used in group_db. + * @return the new skill_group_id + * @exception Fatal error if nothing is available. + **/ static int skill_get_new_group_id(void) { if( skill_unit_group_newid >= MAX_SKILL_DB && skill_id2group(skill_unit_group_newid) == NULL ) @@ -15590,6 +15625,16 @@ static int skill_get_new_group_id(void) } } +/** + * Function to create a new skill_unit_group. + * @src: caster + * @count : ? + * @skillid : id of skill for group + * @skilllv : level of skill for group + * @unit_id : id of unit attach + * @limit : tick when sug is scheduled for deletion + * @interval : delay between 2 execution of unit for that group + **/ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval) { struct unit_data* ud = unit_bl2ud( src ); @@ -15647,9 +15692,13 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, return group; } -/*========================================== - * - *------------------------------------------*/ +/** + * Function to terminate a skill_unit_group; insert last handling here before sug is being erased. + * @group: skill_unit_group to delete + * @file : (debug) to know wich file as called the func (__FILE__) + * @line : (debug) to know in wich line func is called (__LINE__) + * @func : (debug) to know in wich function it was called (__func__) + **/ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int line, const char* func) { struct block_list* src; @@ -15770,10 +15819,10 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li group->unit_count=0; // locate this group, swap with the last entry and delete it - ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == group ); - ARR_FIND( i, MAX_SKILLUNITGROUP, j, ud->skillunit[j] == NULL ); j--; + ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == group ); //found group + ARR_FIND( i, MAX_SKILLUNITGROUP, j, ud->skillunit[j] == NULL ); j--; //found last entry if( i < MAX_SKILLUNITGROUP ) { - ud->skillunit[i] = ud->skillunit[j]; + if(i != j) ud->skillunit[i] = ud->skillunit[j]; //swap ud->skillunit[j] = NULL; ers_free(skill_unit_ers, group); } else diff --git a/src/map/skill.h b/src/map/skill.h index dcf4411..e1c1bb0 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -20,53 +20,62 @@ struct status_change_entry; #define MAX_ARROW_RESOURCE 5 #define MAX_SKILL_ABRA_DB 350 #define MAX_SKILL_IMPROVISE_DB 50 - #define MAX_SKILL_LEVEL 100 DBMap* skilldb_name2id; -//Constants to identify the skill's inf value: +/** + * \enum e_skill_inf + * \brief Skill casting type propriety + * + * e_skill_inf contains the different type the client accept for a skill + * so he'll know on wich kind of target he could be used + */ enum e_skill_inf { - INF_ATTACK_SKILL = 0x01, - INF_GROUND_SKILL = 0x02, - INF_SELF_SKILL = 0x04, // Skills casted on self where target is automatically chosen + INF_ATTACK_SKILL = 0x01, /*!< Skill should target an ennemy */ + INF_GROUND_SKILL = 0x02, /*!< Skill should target the ground. */ + INF_SELF_SKILL = 0x04, /*!< Skills casted on self where target is automatically chosen */ // 0x08 not assigned - INF_SUPPORT_SKILL = 0x10, - INF_TARGET_TRAP = 0x20, + INF_SUPPORT_SKILL = 0x10, /*!< Skill should a friend/ally */ + INF_TARGET_TRAP = 0x20, /*!< Skill should target a trap */ }; -//Constants to identify a skill's nk value (damage properties) -//The NK value applies only to non INF_GROUND_SKILL skills -//when determining skill castend function to invoke. +/** + * \enum e_skill_nk + * \brief Skill damage type properties + * + * The NK value applies only to non INF_GROUND_SKILL skills + * when determining skill castend function to invoke. + */ enum e_skill_nk { - NK_NO_DAMAGE = 0x01, - NK_SPLASH = 0x02|0x04, // 0x4 = splash & split - NK_SPLASHSPLIT = 0x04, - NK_NO_CARDFIX_ATK = 0x08, - NK_NO_ELEFIX = 0x10, - NK_IGNORE_DEF = 0x20, - NK_IGNORE_FLEE = 0x40, - NK_NO_CARDFIX_DEF = 0x80, + NK_NO_DAMAGE = 0x01, /*!< Skill doesn't inflict dmg */ + NK_SPLASH = 0x02|0x04, /*!< skill have splash effect and should be split CHECKME */ + NK_SPLASHSPLIT = 0x04, /*!< skill have splash effect CHECKME */ + NK_NO_CARDFIX_ATK = 0x08, /*!< Skill not affected by attacker card */ + NK_NO_ELEFIX = 0x10, /*!< Skill not affected by element */ + NK_IGNORE_DEF = 0x20, /*!< Skill ignore target defense */ + NK_IGNORE_FLEE = 0x40, /*!< Skill ignore target flee */ + NK_NO_CARDFIX_DEF = 0x80, /*!< Skill ignore target card */ }; //A skill with 3 would be no damage + splash: area of effect. //Constants to identify a skill's inf2 value. enum e_skill_inf2 { - INF2_QUEST_SKILL = 0x0001, - INF2_NPC_SKILL = 0x0002, //NPC skills are those that players can't have in their skill tree. - INF2_WEDDING_SKILL = 0x0004, - INF2_SPIRIT_SKILL = 0x0008, - INF2_GUILD_SKILL = 0x0010, - INF2_SONG_DANCE = 0x0020, - INF2_ENSEMBLE_SKILL = 0x0040, - INF2_TRAP = 0x0080, - INF2_TARGET_SELF = 0x0100, //Refers to ground placed skills that will target the caster as well (like Grandcross) - INF2_NO_TARGET_SELF = 0x0200, - INF2_PARTY_ONLY = 0x0400, - INF2_GUILD_ONLY = 0x0800, - INF2_NO_ENEMY = 0x1000, - INF2_NOLP = 0x2000, // Spells that can ignore Land Protector - INF2_CHORUS_SKILL = 0x4000, // Chorus skill + INF2_QUEST_SKILL = 0x0001, /*!< Skill is gained by a quest */ + INF2_NPC_SKILL = 0x0002, /*!< NPC skills are those that players can't have in their skill tree. */ + INF2_WEDDING_SKILL = 0x0004, /*!< Skill from wedding */ + INF2_SPIRIT_SKILL = 0x0008, /*!< Skill from soullink effect */ + INF2_GUILD_SKILL = 0x0010, /*!< Skill from guild */ + INF2_SONG_DANCE = 0x0020, /*!< Solo dancing skill (bard/dancer) */ + INF2_ENSEMBLE_SKILL = 0x0040, /*!< Duo dancing skill (bard/dancer) */ + INF2_TRAP = 0x0080, /*!< Traps (could be hit by other skills) */ + INF2_TARGET_SELF = 0x0100, /*!< Refers to ground placed skills that will target the caster as well (like Grandcross) */ + INF2_NO_TARGET_SELF = 0x0200, /*!< For combo, skill autocasted but required a target */ + INF2_PARTY_ONLY = 0x0400, /*!< Skill target limited to party */ + INF2_GUILD_ONLY = 0x0800, /*!< Skill target limited to party */ + INF2_NO_ENEMY = 0x1000, /*!< Skill target can't be ennemy */ + INF2_NOLP = 0x2000, /*!< Spells that can ignore Land Protector */ + INF2_CHORUS_SKILL = 0x4000, /*!< 3rd class ensemble skill (chorus) */ }; //Walk intervals at which chase-skills are attempted to be triggered.