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; i<count; i++){
+ unsigned int slen = strlen(commands_li[i]->command);
// 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.