summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c42
-rw-r--r--src/common/mmo.h3
-rw-r--r--src/map/atcommand.c31
-rw-r--r--src/map/battle.c5
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/chrif.c54
-rw-r--r--src/map/chrif.h6
-rw-r--r--src/map/clif.c42
-rw-r--r--src/map/mob.c23
-rw-r--r--src/map/npc.c75
-rw-r--r--src/map/pc.c360
-rw-r--r--src/map/pc.h3
-rw-r--r--src/map/script.c4
-rw-r--r--src/map/skill.c508
-rw-r--r--src/map/skill.h16
15 files changed, 614 insertions, 559 deletions
diff --git a/src/char/char.c b/src/char/char.c
index be98af10e..d5064eee2 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -146,6 +146,8 @@ unsigned int save_flag = 0;
// Initial position (it's possible to set it in conf file)
struct point start_point = { 0, 53, 111 };
+unsigned short skillid2idx[MAX_SKILL_ID];
+
//-----------------------------------------------------
// Auth database
//-----------------------------------------------------
@@ -565,18 +567,10 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
strcat(save_status, " memo");
}
- //FIXME: is this neccessary? [ultramage]
- for(i=0;i<MAX_SKILL;i++)
- if ((p->skill[i].lv != 0) && (p->skill[i].id == 0))
- p->skill[i].id = i; // Fix skill tree
-
-
//skills
- if( memcmp(p->skill, cp->skill, sizeof(p->skill)) )
- {
+ if( memcmp(p->skill, cp->skill, sizeof(p->skill)) ) {
//`skill` (`char_id`, `id`, `lv`)
- if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, p->char_id) )
- {
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, p->char_id) ) {
Sql_ShowDebug(sql_handle);
errors++;
}
@@ -1278,10 +1272,9 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
if( tmp_skill.flag != SKILL_FLAG_PERM_GRANTED )
tmp_skill.flag = SKILL_FLAG_PERMANENT;
- for( i = 0; i < MAX_SKILL && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i )
- {
- if( tmp_skill.id < ARRAYLENGTH(p->skill) )
- memcpy(&p->skill[tmp_skill.id], &tmp_skill, sizeof(tmp_skill));
+ for( i = 0; i < MAX_SKILL && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) {
+ if( skillid2idx[tmp_skill.id] )
+ memcpy(&p->skill[skillid2idx[tmp_skill.id]], &tmp_skill, sizeof(tmp_skill));
else
ShowWarning("mmo_char_fromsql: ignoring invalid skill (id=%u,lv=%u) of character %s (AID=%d,CID=%d)\n", tmp_skill.id, tmp_skill.lv, p->name, p->account_id, p->char_id);
}
@@ -2702,7 +2695,22 @@ int parse_frommap(int fd)
RFIFOSKIP(fd,RFIFOW(fd,2));
break;
-
+ case 0x2b0b:
+ if( RFIFOREST(fd) < RFIFOW(fd, 2) )
+ return 0;
+ memset(&skillid2idx, 0, sizeof(skillid2idx));
+ j = RFIFOW(fd, 2) - 4;
+ if( j )
+ j /= 4;
+ for(i = 0; i < j; i++) {
+ if( RFIFOW(fd, 4 + (i*4)) > MAX_SKILL_ID ) {
+ ShowWarning("Error skillid2dx[%d] = %d failed, %d is higher than MAX_SKILL_ID (%d)\n",RFIFOW(fd, 4 + (i*4)), RFIFOW(fd, 6 + (i*4)),RFIFOW(fd, 4 + (i*4)),MAX_SKILL_ID);
+ continue;
+ }
+ skillid2idx[RFIFOW(fd, 4 + (i*4))] = RFIFOW(fd, 6 + (i*4));
+ }
+ RFIFOSKIP(fd, RFIFOW(fd, 2));
+ break;
case 0x2afa: // Receiving map names list from the map-server
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
@@ -4920,8 +4928,8 @@ void do_shutdown(void)
}
-int do_init(int argc, char **argv)
-{
+int do_init(int argc, char **argv) {
+ memset(&skillid2idx, 0, sizeof(skillid2idx));
//Read map indexes
mapindex_init();
start_point.map = mapindex_name2id("new_zone01");
diff --git a/src/common/mmo.h b/src/common/mmo.h
index e19c8f94d..7bbcd65cd 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -79,7 +79,8 @@
#define MAX_ZENY 1000000000
#define MAX_FAME 1000000000
#define MAX_CART 100
-#define MAX_SKILL 3100
+#define MAX_SKILL 1460
+#define MAX_SKILL_ID 10015 //[Ind/Hercules] max used skill id
#define GLOBAL_REG_NUM 256 // max permanent character variables per char
#define ACCOUNT_REG_NUM 64 // max permanent local account variables per account
#define ACCOUNT_REG2_NUM 16 // max permanent global account variables per account
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index e3b4077cb..85332905e 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -3111,7 +3111,7 @@ ACMD(allskill)
*------------------------------------------*/
ACMD(questskill)
{
- uint16 skill_id;
+ uint16 skill_id, index;
nullpo_retr(-1, sd);
if (!message || !*message || (skill_id = atoi(message)) <= 0)
@@ -3131,7 +3131,7 @@ ACMD(questskill)
return false;
}
- if (skill_id >= MAX_SKILL_DB) {
+ if( !(index = skill->get_index(skill_id)) ) {
clif->message(fd, msg_txt(198)); // This skill number doesn't exist.
return false;
}
@@ -3139,7 +3139,7 @@ ACMD(questskill)
clif->message(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill.
return false;
}
- if (pc_checkskill(sd, skill_id) > 0) {
+ if (pc_checkskill2(sd, index) > 0) {
clif->message(fd, msg_txt(196)); // You already have this quest skill.
return false;
}
@@ -3155,7 +3155,7 @@ ACMD(questskill)
*------------------------------------------*/
ACMD(lostskill)
{
- uint16 skill_id;
+ uint16 skill_id, index;
nullpo_retr(-1, sd);
if (!message || !*message || (skill_id = atoi(message)) <= 0)
@@ -3175,7 +3175,7 @@ ACMD(lostskill)
return false;
}
- if (skill_id >= MAX_SKILL) {
+ if ( !( index = skill->get_index(skill_id) ) ) {
clif->message(fd, msg_txt(198)); // This skill number doesn't exist.
return false;
}
@@ -3183,13 +3183,13 @@ ACMD(lostskill)
clif->message(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill.
return false;
}
- if (pc_checkskill(sd, skill_id) == 0) {
+ if (pc_checkskill2(sd, index) == 0) {
clif->message(fd, msg_txt(201)); // You don't have this quest skill.
return false;
}
- sd->status.skill[skill_id].lv = 0;
- sd->status.skill[skill_id].flag = 0;
+ sd->status.skill[index].lv = 0;
+ sd->status.skill[index].flag = 0;
clif->deleteskill(sd,skill_id);
clif->message(fd, msg_txt(71)); // You have forgotten the skill.
@@ -8728,13 +8728,14 @@ ACMD(unloadnpcfile) {
return true;
}
ACMD(cart) {
-#define MC_CART_MDFY(x) \
-sd->status.skill[MC_PUSHCART].id = x?MC_PUSHCART:0; \
-sd->status.skill[MC_PUSHCART].lv = x?1:0; \
-sd->status.skill[MC_PUSHCART].flag = x?1:0;
+#define MC_CART_MDFY(x,idx) \
+sd->status.skill[idx].id = x?MC_PUSHCART:0; \
+sd->status.skill[idx].lv = x?1:0; \
+sd->status.skill[idx].flag = x?1:0;
int val = atoi(message);
bool need_skill = pc_checkskill(sd, MC_PUSHCART) ? false : true;
+ unsigned int index = skill->get_index(MC_PUSHCART);
if( !message || !*message || val < 0 || val > MAX_CARTS ) {
sprintf(atcmd_output, msg_txt(1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>).
@@ -8748,18 +8749,18 @@ sd->status.skill[MC_PUSHCART].flag = x?1:0;
}
if( need_skill ) {
- MC_CART_MDFY(1);
+ MC_CART_MDFY(1,index);
}
if( pc_setcart(sd, val) ) {
if( need_skill ) {
- MC_CART_MDFY(0);
+ MC_CART_MDFY(0,index);
}
return false;/* @cart failed */
}
if( need_skill ) {
- MC_CART_MDFY(0);
+ MC_CART_MDFY(0,index);
}
clif->message(fd, msg_txt(1392)); // Cart Added
diff --git a/src/map/battle.c b/src/map/battle.c
index 7df79e772..7bfb54fdd 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -5047,9 +5047,9 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
}
if (sd) {
if( wd.flag&BF_SHORT && sc && sc->data[SC__AUTOSHADOWSPELL] && rnd()%100 < sc->data[SC__AUTOSHADOWSPELL]->val3 &&
- sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id != 0 && sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].flag == SKILL_FLAG_PLAGIARIZED )
+ sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].id != 0 && sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].flag == SKILL_FLAG_PLAGIARIZED )
{
- int r_skill = sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id,
+ int r_skill = sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].id,
r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2;
if (r_skill != AL_HOLYLIGHT && r_skill != PR_MAGNUS) {
@@ -5849,7 +5849,6 @@ static const struct _battle_data {
{ "show_hp_sp_gain", &battle_config.show_hp_sp_gain, 1, 0, 1, },
{ "mob_npc_event_type", &battle_config.mob_npc_event_type, 1, 0, 1, },
{ "character_size", &battle_config.character_size, 1|2, 0, 1|2, },
- { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, },
{ "retaliate_to_master", &battle_config.retaliate_to_master, 1, 0, 1, },
{ "rare_drop_announce", &battle_config.rare_drop_announce, 0, 0, 10000, },
{ "duel_allow_pvp", &battle_config.duel_allow_pvp, 0, 0, 1, },
diff --git a/src/map/battle.h b/src/map/battle.h
index 9305cb3eb..fd6a6d7bd 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -360,7 +360,6 @@ struct Battle_Config {
int mob_npc_event_type; //Determines on who the npc_event is executed. [Skotlex]
int character_size; // if riders have size=2, and baby class riders size=1 [Lupus]
- int mob_max_skilllvl; // Max possible skill level [Lupus]
int rare_drop_announce; // chance <= to show rare drops global announces
int retaliate_to_master; //Whether when a mob is attacked by another mob, it will retaliate versus the mob or the mob's master. [Skotlex]
diff --git a/src/map/chrif.c b/src/map/chrif.c
index b816ca4b5..e2ce37e28 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -68,7 +68,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
//2b08: Outgoing, chrif_searchcharid -> '...'
//2b09: Incoming, map_addchariddb -> 'Adds a name to the nick db'
//2b0a: Incoming/Outgoing, socket_datasync()
-//2b0b: FREE
+//2b0b: Outgoing, update charserv skillid2idx
//2b0c: Outgoing, chrif_changeemail -> 'change mail address ...'
//2b0d: Incoming, chrif_changedsex -> 'Change sex of acc XY'
//2b0e: Outgoing, chrif_char_ask_name -> 'Do some operations (change sex, ban / unban etc)'
@@ -470,6 +470,7 @@ int chrif_connectack(int fd) {
}
socket_datasync(fd, true);
+ chrif_skillid2idx(fd);
return 0;
}
@@ -882,21 +883,23 @@ int chrif_changedsex(int fd) {
// reset skill of some job
if ((sd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER) {
- int i;
+ int i, idx = 0;
// remove specifical skills of Bard classes
for(i = 315; i <= 322; i++) {
- if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) {
- sd->status.skill_point += sd->status.skill[i].lv;
- sd->status.skill[i].id = 0;
- sd->status.skill[i].lv = 0;
+ idx = skill->get_index(i);
+ if (sd->status.skill[idx].id > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) {
+ sd->status.skill_point += sd->status.skill[idx].lv;
+ sd->status.skill[idx].id = 0;
+ sd->status.skill[idx].lv = 0;
}
}
// remove specifical skills of Dancer classes
for(i = 323; i <= 330; i++) {
- if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) {
- sd->status.skill_point += sd->status.skill[i].lv;
- sd->status.skill[i].id = 0;
- sd->status.skill[i].lv = 0;
+ idx = skill->get_index(i);
+ if (sd->status.skill[idx].id > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) {
+ sd->status.skill_point += sd->status.skill[idx].lv;
+ sd->status.skill[idx].id = 0;
+ sd->status.skill[idx].lv = 0;
}
}
clif->updatestatus(sd, SP_SKILLPOINT);
@@ -963,20 +966,21 @@ int chrif_divorceack(int char_id, int partner_id) {
*------------------------------------------*/
int chrif_deadopt(int father_id, int mother_id, int child_id) {
struct map_session_data* sd;
+ int idx = skill->get_index(WE_CALLBABY);
if( father_id && ( sd = map_charid2sd(father_id) ) != NULL && sd->status.child == child_id ) {
sd->status.child = 0;
- sd->status.skill[WE_CALLBABY].id = 0;
- sd->status.skill[WE_CALLBABY].lv = 0;
- sd->status.skill[WE_CALLBABY].flag = 0;
+ sd->status.skill[idx].id = 0;
+ sd->status.skill[idx].lv = 0;
+ sd->status.skill[idx].flag = 0;
clif->deleteskill(sd,WE_CALLBABY);
}
if( mother_id && ( sd = map_charid2sd(mother_id) ) != NULL && sd->status.child == child_id ) {
sd->status.child = 0;
- sd->status.skill[WE_CALLBABY].id = 0;
- sd->status.skill[WE_CALLBABY].lv = 0;
- sd->status.skill[WE_CALLBABY].flag = 0;
+ sd->status.skill[idx].id = 0;
+ sd->status.skill[idx].lv = 0;
+ sd->status.skill[idx].flag = 0;
clif->deleteskill(sd,WE_CALLBABY);
}
@@ -1370,6 +1374,24 @@ void chrif_keepalive(int fd) {
void chrif_keepalive_ack(int fd) {
session[fd]->flag.ping = 0;/* reset ping state, we received a packet */
}
+void chrif_skillid2idx(int fd) {
+ int i, count = 0;
+
+ if( fd == 0 ) fd = char_fd;
+
+ WFIFOHEAD(fd,4 + (MAX_SKILL * 4));
+ WFIFOW(fd,0) = 0x2b0b;
+ for(i = 0; i < MAX_SKILL; i++) {
+ if( skill_db[i].nameid ) {
+ WFIFOW(fd, 4 + (count*4)) = skill_db[i].nameid;
+ WFIFOW(fd, 6 + (count*4)) = i;
+ count++;
+ }
+ }
+ WFIFOW(fd,2) = 4 + (count * 4);
+ WFIFOSET(fd,4 + (count * 4));
+
+}
/*==========================================
*
*------------------------------------------*/
diff --git a/src/map/chrif.h b/src/map/chrif.h
index 0aadb1a7b..9c7142905 100644
--- a/src/map/chrif.h
+++ b/src/map/chrif.h
@@ -1,5 +1,6 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#ifndef _CHRIF_H_
#define _CHRIF_H_
@@ -65,5 +66,6 @@ int do_final_chrif(void);
int do_init_chrif(void);
int chrif_flush_fifo(void);
+void chrif_skillid2idx(int fd);
#endif /* _CHRIF_H_ */
diff --git a/src/map/clif.c b/src/map/clif.c
index 19ac1df9c..9fdde148e 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -4862,10 +4862,8 @@ void clif_skillinfoblock(struct map_session_data *sd)
WFIFOHEAD(fd, MAX_SKILL * 37 + 4);
WFIFOW(fd,0) = 0x10f;
- for ( i = 0, len = 4; i < MAX_SKILL; i++)
- {
- if( (id = sd->status.skill[i].id) != 0 )
- {
+ for ( i = 0, len = 4; i < MAX_SKILL; i++) {
+ if( (id = sd->status.skill[i].id) != 0 ) {
// workaround for bugreport:5348
if (len + 37 > 8192)
break;
@@ -4902,25 +4900,25 @@ void clif_skillinfoblock(struct map_session_data *sd)
/// 0111 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B
void clif_addskill(struct map_session_data *sd, int id)
{
- int fd;
+ int fd, idx = skill->get_index(id);
nullpo_retv(sd);
fd = sd->fd;
if (!fd) return;
- if( sd->status.skill[id].id <= 0 )
+ if( sd->status.skill[idx].id <= 0 )
return;
WFIFOHEAD(fd, packet_len(0x111));
WFIFOW(fd,0) = 0x111;
WFIFOW(fd,2) = id;
WFIFOL(fd,4) = skill->get_inf(id);
- WFIFOW(fd,8) = sd->status.skill[id].lv;
- WFIFOW(fd,10) = skill->get_sp(id,sd->status.skill[id].lv);
- WFIFOW(fd,12)= skill->get_range2(&sd->bl, id,sd->status.skill[id].lv);
+ WFIFOW(fd,8) = sd->status.skill[idx].lv;
+ WFIFOW(fd,10) = skill->get_sp(id,sd->status.skill[idx].lv);
+ WFIFOW(fd,12)= skill->get_range2(&sd->bl, id,sd->status.skill[idx].lv);
safestrncpy((char*)WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH);
- if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT )
+ if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT )
WFIFOB(fd,38) = (sd->status.skill[id].lv < skill->tree_get_max(id, sd->status.class_))? 1:0;
else
WFIFOB(fd,38) = 0;
@@ -4950,9 +4948,8 @@ void clif_deleteskill(struct map_session_data *sd, int id)
/// Updates a skill in the skill tree (ZC_SKILLINFO_UPDATE).
/// 010e <skill id>.W <level>.W <sp cost>.W <attack range>.W <upgradable>.B
-void clif_skillup(struct map_session_data *sd,uint16 skill_id)
-{
- int fd;
+void clif_skillup(struct map_session_data *sd,uint16 skill_id) {
+ int fd, idx = skill->get_index(skill_id);
nullpo_retv(sd);
@@ -4960,10 +4957,10 @@ void clif_skillup(struct map_session_data *sd,uint16 skill_id)
WFIFOHEAD(fd,packet_len(0x10e));
WFIFOW(fd,0) = 0x10e;
WFIFOW(fd,2) = skill_id;
- WFIFOW(fd,4) = sd->status.skill[skill_id].lv;
- WFIFOW(fd,6) = skill->get_sp(skill_id,sd->status.skill[skill_id].lv);
- WFIFOW(fd,8) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[skill_id].lv);
- WFIFOB(fd,10) = (sd->status.skill[skill_id].lv < skill->tree_get_max(sd->status.skill[skill_id].id, sd->status.class_)) ? 1 : 0;
+ WFIFOW(fd,4) = sd->status.skill[idx].lv;
+ WFIFOW(fd,6) = skill->get_sp(skill_id,sd->status.skill[idx].lv);
+ WFIFOW(fd,8) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[idx].lv);
+ WFIFOB(fd,10) = (sd->status.skill[idx].lv < skill->tree_get_max(sd->status.skill[idx].id, sd->status.class_)) ? 1 : 0;
WFIFOSET(fd,packet_len(0x10e));
}
@@ -4973,16 +4970,17 @@ void clif_skillup(struct map_session_data *sd,uint16 skill_id)
void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf)
{
const int fd = sd->fd;
+ int idx = skill->get_index(skill_id);
WFIFOHEAD(fd,packet_len(0x7e1));
WFIFOW(fd,0) = 0x7e1;
WFIFOW(fd,2) = skill_id;
WFIFOL(fd,4) = inf?inf:skill->get_inf(skill_id);
- WFIFOW(fd,8) = sd->status.skill[skill_id].lv;
- WFIFOW(fd,10) = skill->get_sp(skill_id,sd->status.skill[skill_id].lv);
- WFIFOW(fd,12) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[skill_id].lv);
- if( sd->status.skill[skill_id].flag == SKILL_FLAG_PERMANENT )
- WFIFOB(fd,14) = (sd->status.skill[skill_id].lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0;
+ WFIFOW(fd,8) = sd->status.skill[idx].lv;
+ WFIFOW(fd,10) = skill->get_sp(skill_id,sd->status.skill[idx].lv);
+ WFIFOW(fd,12) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[idx].lv);
+ if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT )
+ WFIFOB(fd,14) = (sd->status.skill[idx].lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0;
else
WFIFOB(fd,14) = 0;
WFIFOSET(fd,packet_len(0x7e1));
diff --git a/src/map/mob.c b/src/map/mob.c
index f68f85455..885897e62 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -3379,9 +3379,10 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
//Go Backwards to give better priority to advanced skills.
for (i=0,j = MAX_SKILL_TREE-1;j>=0 && i< MAX_MOBSKILL ;j--) {
+ int idx = skill_tree[pc_class2idx(sd->status.class_)][j].idx;
skill_id = skill_tree[pc_class2idx(sd->status.class_)][j].id;
- if (!skill_id || sd->status.skill[skill_id].lv < 1 ||
- (skill->get_inf2(skill_id)&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL))
+ if (!skill_id || sd->status.skill[idx].lv < 1 ||
+ (skill_db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL))
)
continue;
for(h = 0; h < map[sd->bl.m].zone->disabled_skills_count; h++) {
@@ -3401,12 +3402,12 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
/**
* The clone should be able to cast the skill (e.g. have the required weapon) bugreport:5299)
**/
- if( !skill->check_condition_castbegin(sd,skill_id,sd->status.skill[skill_id].lv) )
+ if( !skill->check_condition_castbegin(sd,skill_id,sd->status.skill[idx].lv) )
continue;
memset (&ms[i], 0, sizeof(struct mob_skill));
ms[i].skill_id = skill_id;
- ms[i].skill_lv = sd->status.skill[skill_id].lv;
+ ms[i].skill_lv = sd->status.skill[idx].lv;
ms[i].state = MSS_ANY;
ms[i].permillage = 500*battle_config.mob_skill_rate/100; //Default chance of all skills: 5%
ms[i].emotion = -1;
@@ -3414,7 +3415,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
ms[i].casttime = skill->cast_fix(&sd->bl,skill_id, ms[i].skill_lv);
ms[i].delay = 5000+skill->delay_fix(&sd->bl,skill_id, ms[i].skill_lv);
- inf = skill->get_inf(skill_id);
+ inf = skill_db[idx].inf;
if (inf&INF_ATTACK_SKILL) {
ms[i].target = MST_TARGET;
ms[i].cond1 = MSC_ALWAYS;
@@ -4256,6 +4257,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
struct mob_skill *ms, gms;
int mob_id;
int i =0, j, tmp;
+ uint16 sidx = 0;
mob_id = atoi(str[0]);
@@ -4302,8 +4304,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
//Skill ID
j=atoi(str[3]);
- if (j<=0 || j>MAX_SKILL_DB) //fixed Lupus
- {
+ if ( !(sidx = skill->get_index(j) ) ) {
if (mob_id < 0)
ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for all mobs\n", j);
else
@@ -4314,7 +4315,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
//Skill lvl
j= atoi(str[4])<=0 ? 1 : atoi(str[4]);
- ms->skill_lv= j>battle_config.mob_max_skilllvl ? battle_config.mob_max_skilllvl : j; //we strip max skill level
+ ms->skill_lv= j;
//Apply battle_config modifiers to rate (permillage) and delay [Skotlex]
tmp = atoi(str[5]);
@@ -4345,16 +4346,16 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
}
//Check that the target condition is right for the skill type. [Skotlex]
- if (skill->get_casttype(ms->skill_id) == CAST_GROUND) {//Ground skill.
+ if ( skill->get_casttype2(sidx) == CAST_GROUND) {//Ground skill.
if (ms->target > MST_AROUND) {
ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target for ground skill %d (%s) for %s.\n",
- ms->skill_id, skill->get_name(ms->skill_id),
+ ms->skill_id, skill_db[sidx].name,
mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite);
ms->target = MST_TARGET;
}
} else if (ms->target > MST_MASTER) {
ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n",
- ms->skill_id, skill->get_name(ms->skill_id),
+ ms->skill_id, skill_db[sidx].name,
mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite);
ms->target = MST_TARGET;
}
diff --git a/src/map/npc.c b/src/map/npc.c
index dee5f4f50..a9fdb5ea6 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1506,7 +1506,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
{
struct npc_data* nd;
double z;
- int i,j,w,skill,new_;
+ int i,j,w,skill_t,new_, idx = skill->get_index(MC_DISCOUNT);
nullpo_retr(3, sd);
nullpo_retr(3, item_list);
@@ -1521,8 +1521,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
w = 0;
new_ = 0;
// process entries in buy list, one by one
- for( i = 0; i < n; ++i )
- {
+ for( i = 0; i < n; ++i ) {
int nameid, amount, value;
// find this entry in the shop's sell list
@@ -1541,20 +1540,19 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
if( !itemdb_exists(nameid) )
return 3; // item no longer in itemdb
- if( !itemdb_isstackable(nameid) && amount > 1 )
- { //Exploit? You can't buy more than 1 of equipment types o.O
+ if( !itemdb_isstackable(nameid) && amount > 1 ) {
+ //Exploit? You can't buy more than 1 of equipment types o.O
ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n",
sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid);
amount = item_list[i*2+0] = 1;
}
- if( nd->master_nd )
- {// Script-controlled shops decide by themselves, what can be bought and for what price.
+ if( nd->master_nd ) {
+ // Script-controlled shops decide by themselves, what can be bought and for what price.
continue;
}
- switch( pc_checkadditem(sd,nameid,amount) )
- {
+ switch( pc_checkadditem(sd,nameid,amount) ) {
case ADDITEM_EXIST:
break;
@@ -1584,16 +1582,14 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
pc_payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
- for( i = 0; i < n; ++i )
- {
+ for( i = 0; i < n; ++i ) {
int nameid = item_list[i*2+1];
int amount = item_list[i*2+0];
struct item item_tmp;
if (itemdb_type(nameid) == IT_PETEGG)
pet_create_egg(sd, nameid);
- else
- {
+ else {
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = nameid;
item_tmp.identify = 1;
@@ -1603,14 +1599,12 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
}
// custom merchant shop exp bonus
- if( battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0 )
- {
- if( sd->status.skill[MC_DISCOUNT].flag >= SKILL_FLAG_REPLACED_LV_0 )
- skill = sd->status.skill[MC_DISCOUNT].flag - SKILL_FLAG_REPLACED_LV_0;
+ if( battle_config.shop_exp > 0 && z > 0 && (skill_t = pc_checkskill2(sd,idx)) > 0 ) {
+ if( sd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0 )
+ skill_t = sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0;
- if( skill > 0 )
- {
- z = z * (double)skill * (double)battle_config.shop_exp/10000.;
+ if( skill_t > 0 ) {
+ z = z * (double)skill_t * (double)battle_config.shop_exp/10000.;
if( z < 1 )
z = 1;
pc_gainexp(sd,NULL,0,(int)z, false);
@@ -1684,41 +1678,36 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
{
double z;
- int i,skill;
+ int i,skill_t, idx = skill->get_index(MC_OVERCHARGE);
struct npc_data *nd;
nullpo_retr(1, sd);
nullpo_retr(1, item_list);
- if( ( nd = npc_checknear(sd, map_id2bl(sd->npc_shopid)) ) == NULL || nd->subtype != SHOP )
- {
+ if( ( nd = npc_checknear(sd, map_id2bl(sd->npc_shopid)) ) == NULL || nd->subtype != SHOP ) {
return 1;
}
z = 0;
// verify the sell list
- for( i = 0; i < n; i++ )
- {
+ for( i = 0; i < n; i++ ) {
int nameid, amount, idx, value;
idx = item_list[i*2]-2;
amount = item_list[i*2+1];
- if( idx >= MAX_INVENTORY || idx < 0 || amount < 0 )
- {
+ if( idx >= MAX_INVENTORY || idx < 0 || amount < 0 ) {
return 1;
}
nameid = sd->status.inventory[idx].nameid;
- if( !nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < amount )
- {
+ if( !nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < amount ) {
return 1;
}
- if( nd->master_nd )
- {// Script-controlled shops decide by themselves, what can be sold and at what price.
+ if( nd->master_nd ) {// Script-controlled shops decide by themselves, what can be sold and at what price.
continue;
}
@@ -1727,23 +1716,19 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
z+= (double)value*amount;
}
- if( nd->master_nd )
- {// Script-controlled shops
+ if( nd->master_nd ) { // Script-controlled shops
return npc_selllist_sub(sd, n, item_list, nd->master_nd);
}
// delete items
- for( i = 0; i < n; i++ )
- {
+ for( i = 0; i < n; i++ ) {
int amount, idx;
idx = item_list[i*2]-2;
amount = item_list[i*2+1];
- if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET )
- {
- if( search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 )
- {
+ if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) {
+ if( search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 ) {
intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2]));
}
}
@@ -1757,14 +1742,12 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
pc_getzeny(sd, (int)z, LOG_TYPE_NPC, NULL);
// custom merchant shop exp bonus
- if( battle_config.shop_exp > 0 && z > 0 && ( skill = pc_checkskill(sd,MC_OVERCHARGE) ) > 0)
- {
- if( sd->status.skill[MC_OVERCHARGE].flag >= SKILL_FLAG_REPLACED_LV_0 )
- skill = sd->status.skill[MC_OVERCHARGE].flag - SKILL_FLAG_REPLACED_LV_0;
+ if( battle_config.shop_exp > 0 && z > 0 && ( skill_t = pc_checkskill2(sd,idx) ) > 0) {
+ if( sd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0 )
+ skill_t = sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0;
- if( skill > 0 )
- {
- z = z * (double)skill * (double)battle_config.shop_exp/10000.;
+ if( skill_t > 0 ) {
+ z = z * (double)skill_t * (double)battle_config.shop_exp/10000.;
if( z < 1 )
z = 1;
pc_gainexp(sd, NULL, 0, (int)z, false);
diff --git a/src/map/pc.c b/src/map/pc.c
index 671cea6c4..afc92594b 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -940,19 +940,16 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
// Checks and fixes to character status data, that are required
// in case of configuration change or stuff, which cannot be
// checked on char-server.
- if( sd->status.hair < MIN_HAIR_STYLE || sd->status.hair > MAX_HAIR_STYLE )
- {
+ if( sd->status.hair < MIN_HAIR_STYLE || sd->status.hair > MAX_HAIR_STYLE ) {
sd->status.hair = MIN_HAIR_STYLE;
}
- if( sd->status.hair_color < MIN_HAIR_COLOR || sd->status.hair_color > MAX_HAIR_COLOR )
- {
+ if( sd->status.hair_color < MIN_HAIR_COLOR || sd->status.hair_color > MAX_HAIR_COLOR ) {
sd->status.hair_color = MIN_HAIR_COLOR;
}
- if( sd->status.clothes_color < MIN_CLOTH_COLOR || sd->status.clothes_color > MAX_CLOTH_COLOR )
- {
+ if( sd->status.clothes_color < MIN_CLOTH_COLOR || sd->status.clothes_color > MAX_CLOTH_COLOR ) {
sd->status.clothes_color = MIN_CLOTH_COLOR;
}
-
+
//Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation.
if(!sd->status.hp) pc_setdead(sd);
sd->state.connect_new = 1;
@@ -1145,7 +1142,7 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
*------------------------------------------*/
int pc_reg_received(struct map_session_data *sd)
{
- int i,j;
+ int i,j, idx = 0;
sd->change_level_2nd = pc_readglobalreg(sd,"jobchange_level");
sd->change_level_3rd = pc_readglobalreg(sd,"jobchange_level_3rd");
@@ -1158,15 +1155,14 @@ int pc_reg_received(struct map_session_data *sd)
// Cooking Exp
sd->cook_mastery = pc_readglobalreg(sd,"COOK_MASTERY");
- if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON )
- { // Better check for class rather than skill to prevent "skill resets" from unsetting this
+ if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
+ // Better check for class rather than skill to prevent "skill resets" from unsetting this
sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID");
sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT");
}
//SG map and mob read [Komurka]
- for(i=0;i<MAX_PC_FEELHATE;i++) //for now - someone need to make reading from txt/sql
- {
+ for(i=0;i<MAX_PC_FEELHATE;i++) { //for now - someone need to make reading from txt/sql
if ((j = pc_readglobalreg(sd,sg_info[i].feel_var))!=0) {
sd->feel_map[i].index = j;
sd->feel_map[i].m = map_mapindex2mapid(j);
@@ -1179,22 +1175,22 @@ int pc_reg_received(struct map_session_data *sd)
if ((i = pc_checkskill(sd,RG_PLAGIARISM)) > 0) {
sd->cloneskill_id = pc_readglobalreg(sd,"CLONE_SKILL");
- if (sd->cloneskill_id > 0) {
- sd->status.skill[sd->cloneskill_id].id = sd->cloneskill_id;
- sd->status.skill[sd->cloneskill_id].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV");
- if (sd->status.skill[sd->cloneskill_id].lv > i)
- sd->status.skill[sd->cloneskill_id].lv = i;
- sd->status.skill[sd->cloneskill_id].flag = SKILL_FLAG_PLAGIARIZED;
+ if (sd->cloneskill_id > 0 && (idx = skill->get_index(sd->cloneskill_id))) {
+ sd->status.skill[idx].id = sd->cloneskill_id;
+ sd->status.skill[idx].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV");
+ if (sd->status.skill[idx].lv > i)
+ sd->status.skill[idx].lv = i;
+ sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
}
}
if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) {
sd->reproduceskill_id = pc_readglobalreg(sd,"REPRODUCE_SKILL");
- if( sd->reproduceskill_id > 0) {
- sd->status.skill[sd->reproduceskill_id].id = sd->reproduceskill_id;
- sd->status.skill[sd->reproduceskill_id].lv = pc_readglobalreg(sd,"REPRODUCE_SKILL_LV");
- if( i < sd->status.skill[sd->reproduceskill_id].lv)
- sd->status.skill[sd->reproduceskill_id].lv = i;
- sd->status.skill[sd->reproduceskill_id].flag = SKILL_FLAG_PLAGIARIZED;
+ if( sd->reproduceskill_id > 0 && (idx = skill->get_index(sd->reproduceskill_id))) {
+ sd->status.skill[idx].id = sd->reproduceskill_id;
+ sd->status.skill[idx].lv = pc_readglobalreg(sd,"REPRODUCE_SKILL_LV");
+ if( i < sd->status.skill[idx].lv)
+ sd->status.skill[idx].lv = i;
+ sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
}
}
//Weird... maybe registries were reloaded?
@@ -1263,15 +1259,14 @@ static int pc_calc_skillpoint(struct map_session_data* sd)
nullpo_ret(sd);
for(i=1;i<MAX_SKILL;i++){
- if( (skill_lv = pc_checkskill(sd,i)) > 0) {
- inf2 = skill->get_inf2(i);
+ if( (skill_lv = pc_checkskill2(sd,i)) > 0) {
+ inf2 = skill_db[i].inf2;
if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) &&
!(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex]
) {
if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
skill_point += skill_lv;
- else
- if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0)
+ else if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0)
skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
}
}
@@ -1298,13 +1293,13 @@ int pc_calc_skilltree(struct map_session_data *sd)
return 1;
}
c = pc_class2idx(c);
-
+
for( i = 0; i < MAX_SKILL; i++ ) {
if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
sd->status.skill[i].id = 0; //First clear skills.
/* permanent skills that must be re-checked */
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) {
- switch( i ) {
+ switch( skill_db[i].nameid ) {
case NV_TRICKDEAD:
if( (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) {
sd->status.skill[i].id = 0;
@@ -1316,29 +1311,26 @@ int pc_calc_skilltree(struct map_session_data *sd)
}
}
- for( i = 0; i < MAX_SKILL; i++ )
- {
+ for( i = 0; i < MAX_SKILL; i++ ) {
if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
{ // Restore original level of skills after deleting earned skills.
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
}
- if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU )
+ if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && skill_db[i].nameid >= DC_HUMMING && skill_db[i].nameid <= DC_SERVICEFORYOU )
{ //Enable Bard/Dancer spirit linked skills.
if( sd->status.sex )
{ //Link dancer skills to bard.
if( sd->status.skill[i-8].lv < 10 )
continue;
- sd->status.skill[i].id = i;
+ sd->status.skill[i].id = skill_db[i].nameid;
sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill
sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
- }
- else
- { //Link bard skills to dancer.
+ } else { //Link bard skills to dancer.
if( sd->status.skill[i].lv < 10 )
continue;
- sd->status.skill[i-8].id = i - 8;
+ sd->status.skill[i-8].id = skill_db[i-8].nameid;
sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill
sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
}
@@ -1347,7 +1339,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) {
for( i = 0; i < MAX_SKILL; i++ ) {
- switch(i) {
+ switch(skill_db[i].nameid) {
/**
* Dummy skills must be added here otherwise they'll be displayed in the,
* skill tree and since they have no icons they'll give resource errors
@@ -1371,20 +1363,19 @@ int pc_calc_skilltree(struct map_session_data *sd)
default:
break;
}
- if( skill->get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL) )
+ if( skill_db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL) )
continue; //Only skills you can't have are npc/guild ones
- if( skill->get_max(i) > 0 )
- sd->status.skill[i].id = i;
+ if( skill_db[i].max > 0 )
+ sd->status.skill[i].id = skill_db[i].nameid;
}
return 0;
}
do {
flag = 0;
- for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ )
- {
- int f;
- if( sd->status.skill[id].id )
+ for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) {
+ int f, idx = skill_tree[c][i].idx;
+ if( sd->status.skill[idx].id )
continue; //Skill already known.
f = 1;
@@ -1392,17 +1383,15 @@ int pc_calc_skilltree(struct map_session_data *sd)
int j;
for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) {
int k;
- if((k=skill_tree[c][i].need[j].id))
- {
- if (sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED)
+ if((k=skill_tree[c][i].need[j].id)) {
+ int idx2 = skill_tree[c][i].need[j].idx;
+ if (sd->status.skill[idx2].id == 0 || sd->status.skill[idx2].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[idx2].flag == SKILL_FLAG_PLAGIARIZED)
k = 0; //Not learned.
+ else if (sd->status.skill[idx2].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
+ k = sd->status.skill[idx2].flag - SKILL_FLAG_REPLACED_LV_0;
else
- if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
- k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0;
- else
- k = pc_checkskill(sd,k);
- if (k < skill_tree[c][i].need[j].lv)
- {
+ k = pc_checkskill2(sd,idx2);
+ if (k < skill_tree[c][i].need[j].lv) {
f = 0;
break;
}
@@ -1411,23 +1400,22 @@ int pc_calc_skilltree(struct map_session_data *sd)
if( sd->status.job_level < skill_tree[c][i].joblv )
f = 0; // job level requirement wasn't satisfied
}
-
if( f ) {
int inf2;
- inf2 = skill->get_inf2(id);
-
- if(!sd->status.skill[id].lv && (
+ inf2 = skill_db[idx].inf2;
+
+ if(!sd->status.skill[idx].lv && (
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
inf2&INF2_WEDDING_SKILL ||
(inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT])
))
continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills.
- sd->status.skill[id].id = id;
+ sd->status.skill[idx].id = id;
if(inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed.
- sd->status.skill[id].lv = 1; // need to manually specify a skill level
- sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
+ sd->status.skill[idx].lv = 1; // need to manually specify a skill level
+ sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
}
flag = 1; // skill list has changed, perform another pass
}
@@ -1443,22 +1431,19 @@ int pc_calc_skilltree(struct map_session_data *sd)
- (c > 0) to avoid grant Novice Skill Tree in case of Skill Reset (need more logic)
- (sd->status.skill_point == 0) to wait until all skill points are asigned to avoid problems with Job Change quest. */
- for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ )
- {
- if( (skill->get_inf2(id)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
+ for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) {
+ int idx = skill_tree[c][i].idx;
+ if( (skill_db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
continue; //Do not include Quest/Wedding skills.
- if( sd->status.skill[id].id == 0 )
- {
- sd->status.skill[id].id = id;
- sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill.
- }
- else if( id != NV_BASIC)
- {
- sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Remember original level
+ if( sd->status.skill[idx].id == 0 ) {
+ sd->status.skill[idx].id = id;
+ sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill.
+ } else if( id != NV_BASIC) {
+ sd->status.skill[idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[idx].lv; // Remember original level
}
- sd->status.skill[id].lv = skill->tree_get_max(id, sd->status.class_);
+ sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_);
}
}
@@ -1483,26 +1468,22 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill_id)
c = pc_class2idx(c);
do {
flag = 0;
- for( i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++ )
- {
- int j, f = 1, k;
+ for( i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++ ) {
+ int j, f = 1, k, idx = skill_tree[c][i].idx;
- if( sd->status.skill[id].id ) //Already learned
+ if( sd->status.skill[idx].id ) //Already learned
continue;
- for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ )
- {
- if( (k = skill_tree[c][i].need[j].id) )
- {
- if( sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED )
+ for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) {
+ if( (k = skill_tree[c][i].need[j].id) ) {
+ int idx2 = skill_tree[c][i].need[j].idx;
+ if( sd->status.skill[idx2].id == 0 || sd->status.skill[idx2].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[idx2].flag == SKILL_FLAG_PLAGIARIZED )
k = 0; //Not learned.
+ else if( sd->status.skill[idx2].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
+ k = sd->status.skill[idx2].flag - SKILL_FLAG_REPLACED_LV_0;
else
- if( sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
- k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0;
- else
- k = pc_checkskill(sd,k);
- if( k < skill_tree[c][i].need[j].lv )
- {
+ k = pc_checkskill2(sd,idx2);
+ if( k < skill_tree[c][i].need[j].lv ) {
f = 0;
break;
}
@@ -1513,15 +1494,15 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill_id)
if( sd->status.job_level < skill_tree[c][i].joblv )
continue;
- j = skill->get_inf2(id);
- if( !sd->status.skill[id].lv && (
+ j = skill_db[idx].inf2;
+ if( !sd->status.skill[idx].lv && (
(j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
j&INF2_WEDDING_SKILL ||
(j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT])
) )
continue; //Cannot be learned via normal means.
- sd->status.skill[id].id = id;
+ sd->status.skill[idx].id = id;
flag = 1;
}
} while(flag);
@@ -1533,14 +1514,11 @@ int pc_clean_skilltree(struct map_session_data *sd)
{
int i;
for (i = 0; i < MAX_SKILL; i++){
- if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED)
- {
+ if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) {
sd->status.skill[i].id = 0;
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
- }
- else
- if (sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0){
+ } else if (sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0) {
sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = 0;
}
@@ -3452,11 +3430,11 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4
* 2 - Like 1, except the level granted can stack with previously learned level.
* 3 - Grant skill unconditionally and forever (persistent to job changes and skill resets)
*------------------------------------------*/
-int pc_skill(TBL_PC* sd, int id, int level, int flag)
-{
+int pc_skill(TBL_PC* sd, int id, int level, int flag) {
+ uint16 index = 0;
nullpo_ret(sd);
- if( id <= 0 || id >= MAX_SKILL || skill_db[id].name == NULL) {
+ if( !(index = skill->get_index(id)) || skill_db[index].name == NULL) {
ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", id);
return 0;
}
@@ -3464,56 +3442,56 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag)
ShowError("pc_skill: Skill level %d too high. Max lv supported is %d\n", level, MAX_SKILL_LEVEL);
return 0;
}
- if( flag == 2 && sd->status.skill[id].lv + level > MAX_SKILL_LEVEL ) {
- ShowError("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d\n", level, MAX_SKILL_LEVEL, sd->status.skill[id].lv);
+ if( flag == 2 && sd->status.skill[index].lv + level > MAX_SKILL_LEVEL ) {
+ ShowError("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d\n", level, MAX_SKILL_LEVEL, sd->status.skill[index].lv);
return 0;
}
switch( flag ){
case 0: //Set skill data overwriting whatever was there before.
- sd->status.skill[id].id = id;
- sd->status.skill[id].lv = level;
- sd->status.skill[id].flag = SKILL_FLAG_PERMANENT;
+ sd->status.skill[index].id = id;
+ sd->status.skill[index].lv = level;
+ sd->status.skill[index].flag = SKILL_FLAG_PERMANENT;
if( level == 0 ) { //Remove skill.
- sd->status.skill[id].id = 0;
+ sd->status.skill[index].id = 0;
clif->deleteskill(sd,id);
} else
clif->addskill(sd,id);
- if( !skill->get_inf(id) ) //Only recalculate for passive skills.
+ if( !skill_db[index].inf ) //Only recalculate for passive skills.
status_calc_pc(sd, 0);
break;
case 1: //Item bonus skill.
- if( sd->status.skill[id].id == id ) {
- if( sd->status.skill[id].lv >= level )
+ if( sd->status.skill[index].id == id ) {
+ if( sd->status.skill[index].lv >= level )
return 0;
- if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level.
- sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv;
+ if( sd->status.skill[index].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level.
+ sd->status.skill[index].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[index].lv;
} else {
- sd->status.skill[id].id = id;
- sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY;
+ sd->status.skill[index].id = id;
+ sd->status.skill[index].flag = SKILL_FLAG_TEMPORARY;
}
- sd->status.skill[id].lv = level;
+ sd->status.skill[index].lv = level;
break;
case 2: //Add skill bonus on top of what you had.
- if( sd->status.skill[id].id == id ) {
- if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT )
- sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level.
+ if( sd->status.skill[index].id == id ) {
+ if( sd->status.skill[index].flag == SKILL_FLAG_PERMANENT )
+ sd->status.skill[index].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[index].lv; // Store previous level.
} else {
- sd->status.skill[id].id = id;
- sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill.
+ sd->status.skill[index].id = id;
+ sd->status.skill[index].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill.
}
- sd->status.skill[id].lv += level;
+ sd->status.skill[index].lv += level;
break;
case 3:
- sd->status.skill[id].id = id;
- sd->status.skill[id].lv = level;
- sd->status.skill[id].flag = SKILL_FLAG_PERM_GRANTED;
+ sd->status.skill[index].id = id;
+ sd->status.skill[index].lv = level;
+ sd->status.skill[index].flag = SKILL_FLAG_PERM_GRANTED;
if( level == 0 ) { //Remove skill.
- sd->status.skill[id].id = 0;
+ sd->status.skill[index].id = 0;
clif->deleteskill(sd,id);
} else
clif->addskill(sd,id);
- if( !skill->get_inf(id) ) //Only recalculate for passive skills.
+ if( !skill_db[index].inf ) //Only recalculate for passive skills.
status_calc_pc(sd, 0);
break;
default: //Unknown flag?
@@ -4959,8 +4937,8 @@ int pc_memo(struct map_session_data* sd, int pos)
/*==========================================
* Return player sd skill_lv learned for given skill
*------------------------------------------*/
-int pc_checkskill(struct map_session_data *sd,uint16 skill_id)
-{
+int pc_checkskill(struct map_session_data *sd,uint16 skill_id) {
+ uint16 index = 0;
if(sd == NULL) return 0;
if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) {
struct guild *g;
@@ -4968,16 +4946,34 @@ int pc_checkskill(struct map_session_data *sd,uint16 skill_id)
if( sd->status.guild_id>0 && (g=sd->guild)!=NULL)
return guild_checkskill(g,skill_id);
return 0;
- } else if(skill_id >= ARRAYLENGTH(sd->status.skill) ) {
+ } else if(!(index = skill->get_index(skill_id)) || index >= ARRAYLENGTH(sd->status.skill) ) {
ShowError("pc_checkskill: Invalid skill id %d (char_id=%d).\n", skill_id, sd->status.char_id);
return 0;
}
- if(sd->status.skill[skill_id].id == skill_id)
- return (sd->status.skill[skill_id].lv);
+ if(sd->status.skill[index].id == skill_id)
+ return (sd->status.skill[index].lv);
return 0;
}
+int pc_checkskill2(struct map_session_data *sd,uint16 index) {
+ if(sd == NULL) return 0;
+ if(index >= ARRAYLENGTH(sd->status.skill) ) {
+ ShowError("pc_checkskill: Invalid skill index %d (char_id=%d).\n", index, sd->status.char_id);
+ return 0;
+ }
+ if( skill_db[index].nameid >= GD_SKILLBASE && skill_db[index].nameid < GD_MAX ) {
+ struct guild *g;
+
+ if( sd->status.guild_id>0 && (g=sd->guild)!=NULL)
+ return guild_checkskill(g,skill_db[index].nameid);
+ return 0;
+ }
+ if(sd->status.skill[index].id == skill_db[index].nameid)
+ return (sd->status.skill[index].lv);
+
+ return 0;
+}
/*==========================================
* Chk if we still have the correct weapon to continue the skill (actually status)
@@ -6048,33 +6044,31 @@ int pc_statusup2(struct map_session_data* sd, int type, int val)
* Update skill_lv for player sd
* Skill point allocation
*------------------------------------------*/
-int pc_skillup(struct map_session_data *sd,uint16 skill_id)
-{
+int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
+ uint16 index = 0;
nullpo_ret(sd);
- if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL )
- {
+ if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL ) {
guild_skillup(sd, skill_id);
return 0;
}
- if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd )
- {
+ if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd ) {
merc_hom_skillup(sd->hd, skill_id);
return 0;
}
- if(skill_id >= MAX_SKILL )
+ if( !(index = skill->get_index(skill_id)) )
return 0;
if( sd->status.skill_point > 0 &&
- sd->status.skill[skill_id].id &&
- sd->status.skill[skill_id].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
- sd->status.skill[skill_id].lv < skill->tree_get_max(skill_id, sd->status.class_) )
+ sd->status.skill[index].id &&
+ sd->status.skill[index].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
+ sd->status.skill[index].lv < skill->tree_get_max(skill_id, sd->status.class_) )
{
- sd->status.skill[skill_id].lv++;
+ sd->status.skill[index].lv++;
sd->status.skill_point--;
- if( !skill->get_inf(skill_id) )
+ if( !skill_db[index].inf )
status_calc_pc(sd,0); // Only recalculate for passive skills.
else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) )
pc_calc_skilltree(sd); // Required to grant all TK Ranger skills.
@@ -6110,25 +6104,25 @@ int pc_allskillup(struct map_session_data *sd)
}
}
- if (pc_has_permission(sd, PC_PERM_ALL_SKILL))
- { //Get ALL skills except npc/guild ones. [Skotlex]
+ if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { //Get ALL skills except npc/guild ones. [Skotlex]
//and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage]
for(i=0;i<MAX_SKILL;i++){
- switch( i ) {
+ switch( skill_db[i].nameid ) {
case SG_DEVIL:
case MO_TRIPLEATTACK:
case RG_SNATCHER:
continue;
default:
- if( !(skill->get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) )
- if ( ( sd->status.skill[i].lv = skill->get_max(i) ) )//Nonexistant skills should return a max of 0 anyway.
- sd->status.skill[i].id = i;
+ if( !(skill_db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) )
+ if ( ( sd->status.skill[i].lv = skill_db[i].max ) )//Nonexistant skills should return a max of 0 anyway.
+ sd->status.skill[i].id = skill_db[i].nameid;
}
}
} else {
int inf2;
for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id)>0;i++){
- inf2 = skill->get_inf2(id);
+ int idx = skill_tree[pc_class2idx(sd->status.class_)][i].idx;
+ inf2 = skill_db[idx].inf2;
if (
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) ||
@@ -6136,8 +6130,8 @@ int pc_allskillup(struct map_session_data *sd)
)
continue; //Cannot be learned normally.
- sd->status.skill[id].id = id;
- sd->status.skill[id].lv = skill->tree_get_max(id, sd->status.class_); // celest
+ sd->status.skill[idx].id = id;
+ sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); // celest
}
}
status_calc_pc(sd,0);
@@ -6351,26 +6345,27 @@ int pc_resetskill(struct map_session_data* sd, int flag)
merc_hom_vaporize(sd, 0);
}
- for( i = 1; i < MAX_SKILL; i++ )
- {
+ for( i = 1; i < MAX_SKILL; i++ ) {
+ uint16 skill_id = 0;
lv = sd->status.skill[i].lv;
if (lv < 1) continue;
- inf2 = skill->get_inf2(i);
+ inf2 = skill_db[i].inf2;
if( inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL) ) //Avoid reseting wedding/linker skills.
continue;
-
+
+ skill_id = skill_db[i].nameid;
+
// Don't reset trick dead if not a novice/baby
- if( i == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
- {
+ if( skill_id == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) {
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
continue;
}
// do not reset basic skill
- if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
+ if( skill_id == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
continue;
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED )
@@ -6379,10 +6374,9 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( flag&4 && !skill_ischangesex(i) )
continue;
- if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn )
- { //Only handle quest skills in a special way when you can't learn them manually
- if( battle_config.quest_skill_reset && !(flag&2) )
- { //Wipe them
+ if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn ) {
+ //Only handle quest skills in a special way when you can't learn them manually
+ if( battle_config.quest_skill_reset && !(flag&2) ) { //Wipe them
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
}
@@ -6394,8 +6388,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0 )
skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
- if( !(flag&2) )
- {// reset
+ if( !(flag&2) ) {// reset
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
}
@@ -6405,8 +6398,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
sd->status.skill_point += skill_point;
- if( flag&1 )
- {
+ if( flag&1 ) {
clif->updatestatus(sd,SP_SKILLPOINT);
clif->skillinfoblock(sd);
status_calc_pc(sd,0);
@@ -7339,7 +7331,7 @@ static int jobchange_killclone(struct block_list *bl, va_list ap)
int pc_jobchange(struct map_session_data *sd,int job, int upper)
{
int i, fame_flag=0;
- int b_class;
+ int b_class, idx = 0;
nullpo_ret(sd);
@@ -7379,10 +7371,11 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
}
if(sd->cloneskill_id) {
- if( sd->status.skill[sd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED ) {
- sd->status.skill[sd->cloneskill_id].id = 0;
- sd->status.skill[sd->cloneskill_id].lv = 0;
- sd->status.skill[sd->cloneskill_id].flag = 0;
+ idx = skill->get_index(sd->cloneskill_id);
+ if( sd->status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED ) {
+ sd->status.skill[idx].id = 0;
+ sd->status.skill[idx].lv = 0;
+ sd->status.skill[idx].flag = 0;
clif->deleteskill(sd,sd->cloneskill_id);
}
sd->cloneskill_id = 0;
@@ -7391,10 +7384,11 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
}
if(sd->reproduceskill_id) {
- if( sd->status.skill[sd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) {
- sd->status.skill[sd->reproduceskill_id].id = 0;
- sd->status.skill[sd->reproduceskill_id].lv = 0;
- sd->status.skill[sd->reproduceskill_id].flag = 0;
+ idx = skill->get_index(sd->reproduceskill_id);
+ if( sd->status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED ) {
+ sd->status.skill[idx].id = 0;
+ sd->status.skill[idx].lv = 0;
+ sd->status.skill[idx].flag = 0;
clif->deleteskill(sd,sd->reproduceskill_id);
}
sd->reproduceskill_id = 0;
@@ -9464,24 +9458,22 @@ static bool pc_readdb_skilltree(char* fields[], int columns, int current)
//This is to avoid adding two lines for the same skill. [Skotlex]
ARR_FIND( 0, MAX_SKILL_TREE, skill_idx, skill_tree[idx][skill_idx].id == 0 || skill_tree[idx][skill_idx].id == skill_id );
- if( skill_idx == MAX_SKILL_TREE )
- {
+ if( skill_idx == MAX_SKILL_TREE ) {
ShowWarning("pc_readdb_skilltree: Unable to load skill %hu into job %d's tree. Maximum number of skills per class has been reached.\n", skill_id, class_);
return false;
- }
- else if(skill_tree[idx][skill_idx].id)
- {
+ } else if(skill_tree[idx][skill_idx].id) {
ShowNotice("pc_readdb_skilltree: Overwriting skill %hu for job class %d.\n", skill_id, class_);
}
skill_tree[idx][skill_idx].id = skill_id;
+ skill_tree[idx][skill_idx].idx = skill->get_index(skill_id);
skill_tree[idx][skill_idx].max = skill_lv;
skill_tree[idx][skill_idx].joblv = joblv;
- for(i = 0; i < MAX_PC_SKILL_REQUIRE; i++)
- {
- skill_tree[idx][skill_idx].need[i].id = atoi(fields[i*2+offset]);
- skill_tree[idx][skill_idx].need[i].lv = atoi(fields[i*2+offset+1]);
+ for(i = 0; i < MAX_PC_SKILL_REQUIRE; i++) {
+ skill_tree[idx][skill_idx].need[i].id = atoi(fields[i*2+offset]);
+ skill_tree[idx][skill_idx].need[i].idx = skill->get_index(atoi(fields[i*2+offset]));
+ skill_tree[idx][skill_idx].need[i].lv = atoi(fields[i*2+offset+1]);
}
return true;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index ff65d9824..4f421f7c2 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -717,6 +717,7 @@ int pc_equippoint(struct map_session_data *sd,int n);
int pc_setinventorydata(struct map_session_data *sd);
int pc_checkskill(struct map_session_data *sd,uint16 skill_id);
+int pc_checkskill2(struct map_session_data *sd,uint16 index);
int pc_checkallowskill(struct map_session_data *sd);
int pc_checkequip(struct map_session_data *sd,int pos);
@@ -879,10 +880,12 @@ const char * job_name(int class_);
struct skill_tree_entry {
short id;
+ unsigned short idx;
unsigned char max;
unsigned char joblv;
struct {
short id;
+ unsigned short idx;
unsigned char lv;
} need[MAX_PC_SKILL_REQUIRE];
}; // Celest
diff --git a/src/map/script.c b/src/map/script.c
index 6cc235ad1..fbe3a31df 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -16477,9 +16477,7 @@ BUILDIN(areamobuseskill)
range = script_getnum(st,5);
mobid = script_getnum(st,6);
skill_id = ( script_isstring(st,7) ? skill->name2id(script_getstr(st,7)) : script_getnum(st,7) );
- if( (skill_lv = script_getnum(st,8)) > battle_config.mob_max_skilllvl )
- skill_lv = battle_config.mob_max_skilllvl;
-
+ skill_lv = script_getnum(st,8);
casttime = script_getnum(st,9);
cancel = script_getnum(st,10);
emotion = script_getnum(st,11);
diff --git a/src/map/skill.c b/src/map/skill.c
index d3c4a2bc5..c705d1425 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -154,7 +154,18 @@ int skill_get_index( uint16 skill_id ) {
skill_id = MC_SKILLRANGEMIN + skill_id - MC_SKILLBASE;
else if( skill_id >= HM_SKILLBASE )
skill_id = HM_SKILLRANGEMIN + skill_id - HM_SKILLBASE;
-
+ //[Ind/Hercules] GO GO GO LESS! - http://hercules.ws/board/topic/512-skill-id-processing-overhaul/
+ else if( skill_id > 1019 && skill_id < 8001 ) {
+ if( skill_id < 2057 ) // 1020 - 2000 are empty
+ skill_id = 1020 + skill_id - 2001;
+ else if( skill_id < 2549 ) // 2057 - 2200 are empty
+ skill_id = (1020+57) + skill_id - 2201;
+ else if ( skill_id < 3036 ) // 2549 - 3000 are empty
+ skill_id = (1020+57+348) + skill_id - 3001;
+ else if ( skill_id < 5019 ) //3036 - 5000 are empty
+ skill_id = (1020+57+348+1966) + skill_id - 5001;
+ }
+
// validate result
if( !skill_id || skill_id >= MAX_SKILL_DB )
return 0;
@@ -171,58 +182,57 @@ const char* skill_get_desc( uint16 skill_id ) {
}
// out of bounds error checking [celest]
-void skill_chk(int16* skill_id, uint16 skill_lv) {
+void skill_chk(int16* skill_id) {
*skill_id = skill->get_index(*skill_id); // checks/adjusts id
- if( skill_lv > MAX_SKILL_LEVEL ) *skill_id = 0;
}
-#define skill_get(var,id,lv) { skill->chk(&id,lv); if(!id) return 0; return var; }
-
+#define skill_get(var,id) { skill->chk(&id); if(!id) return 0; return var; }
+#define skill_get2(var,id,lv) { skill->chk(&id); if(!id) return 0; if( lv > MAX_SKILL_LEVEL ) { int lv2 = lv; lv = skill_db[id].max; return (var) + (lv2-lv); } return var; }
// Skill DB
-int skill_get_hit( uint16 skill_id ) { skill_get (skill_db[skill_id].hit, skill_id, 1); }
-int skill_get_inf( uint16 skill_id ) { skill_get (skill_db[skill_id].inf, skill_id, 1); }
-int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get (skill_db[skill_id].element[skill_lv-1], skill_id, skill_lv); }
-int skill_get_nk( uint16 skill_id ) { skill_get (skill_db[skill_id].nk, skill_id, 1); }
-int skill_get_max( uint16 skill_id ) { skill_get (skill_db[skill_id].max, skill_id, 1); }
-int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get (skill_db[skill_id].range[skill_lv-1], skill_id, skill_lv); }
-int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get ( (skill_db[skill_id].splash[skill_lv-1]>=0?skill_db[skill_id].splash[skill_lv-1]:AREA_SIZE), skill_id, skill_lv); }
-int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].hp[skill_lv-1], skill_id, skill_lv); }
-int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].sp[skill_lv-1], skill_id, skill_lv); }
-int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].hp_rate[skill_lv-1], skill_id, skill_lv); }
-int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].sp_rate[skill_lv-1], skill_id, skill_lv); }
-int skill_get_state(uint16 skill_id) { skill_get (skill_db[skill_id].state, skill_id, 1); }
-int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { skill_get (skill_db[skill_id].spiritball[skill_lv-1], skill_id, skill_lv); }
-int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].itemid[idx], skill_id, 1); }
-int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].amount[idx], skill_id, 1); }
-int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].zeny[skill_lv-1], skill_id, skill_lv); }
-int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].num[skill_lv-1], skill_id, skill_lv); }
-int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].cast[skill_lv-1], skill_id, skill_lv); }
-int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].delay[skill_lv-1], skill_id, skill_lv); }
-int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].walkdelay[skill_lv-1], skill_id, skill_lv); }
-int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].upkeep_time[skill_lv-1], skill_id, skill_lv); }
-int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].upkeep_time2[skill_lv-1], skill_id, skill_lv); }
-int skill_get_castdef( uint16 skill_id ) { skill_get (skill_db[skill_id].cast_def_rate, skill_id, 1); }
-int skill_get_weapontype( uint16 skill_id ) { skill_get (skill_db[skill_id].weapon, skill_id, 1); }
-int skill_get_ammotype( uint16 skill_id ) { skill_get (skill_db[skill_id].ammo, skill_id, 1); }
-int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].ammo_qty[skill_lv-1], skill_id, skill_lv); }
-int skill_get_inf2( uint16 skill_id ) { skill_get (skill_db[skill_id].inf2, skill_id, 1); }
-int skill_get_castcancel( uint16 skill_id ) { skill_get (skill_db[skill_id].castcancel, skill_id, 1); }
-int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].maxcount[skill_lv-1], skill_id, skill_lv); }
-int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].blewcount[skill_lv-1], skill_id, skill_lv); }
-int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].mhp[skill_lv-1], skill_id, skill_lv); }
-int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].castnodex[skill_lv-1], skill_id, skill_lv); }
-int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get (skill_db[skill_id].delaynodex[skill_lv-1], skill_id, skill_lv); }
-int skill_get_type( uint16 skill_id ) { skill_get (skill_db[skill_id].skill_type, skill_id, 1); }
-int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill_db[skill_id].unit_id[flag], skill_id, 1); }
-int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_interval, skill_id, 1); }
-int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].unit_range[skill_lv-1], skill_id, skill_lv); }
-int skill_get_unit_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BCT_ALL, skill_id, 1); }
-int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BL_ALL, skill_id, 1); }
-int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_flag, skill_id, 1); }
-int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get (skill_db[skill_id].unit_layout_type[skill_lv-1], skill_id, skill_lv); }
-int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].cooldown[skill_lv-1], skill_id, skill_lv); }
+int skill_get_hit( uint16 skill_id ) { skill_get (skill_db[skill_id].hit, skill_id); }
+int skill_get_inf( uint16 skill_id ) { skill_get (skill_db[skill_id].inf, skill_id); }
+int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_db[skill_id].element[skill_lv-1], skill_id, skill_lv); }
+int skill_get_nk( uint16 skill_id ) { skill_get (skill_db[skill_id].nk, skill_id); }
+int skill_get_max( uint16 skill_id ) { skill_get (skill_db[skill_id].max, skill_id); }
+int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_db[skill_id].range[skill_lv-1], skill_id, skill_lv); }
+int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get2 ( (skill_db[skill_id].splash[skill_lv-1]>=0?skill_db[skill_id].splash[skill_lv-1]:AREA_SIZE), skill_id, skill_lv); }
+int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].hp[skill_lv-1], skill_id, skill_lv); }
+int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].sp[skill_lv-1], skill_id, skill_lv); }
+int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].hp_rate[skill_lv-1], skill_id, skill_lv); }
+int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].sp_rate[skill_lv-1], skill_id, skill_lv); }
+int skill_get_state(uint16 skill_id) { skill_get (skill_db[skill_id].state, skill_id); }
+int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { skill_get2 (skill_db[skill_id].spiritball[skill_lv-1], skill_id, skill_lv); }
+int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].itemid[idx], skill_id); }
+int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].amount[idx], skill_id); }
+int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].zeny[skill_lv-1], skill_id, skill_lv); }
+int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].num[skill_lv-1], skill_id, skill_lv); }
+int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].cast[skill_lv-1], skill_id, skill_lv); }
+int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].delay[skill_lv-1], skill_id, skill_lv); }
+int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].walkdelay[skill_lv-1], skill_id, skill_lv); }
+int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].upkeep_time[skill_lv-1], skill_id, skill_lv); }
+int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].upkeep_time2[skill_lv-1], skill_id, skill_lv); }
+int skill_get_castdef( uint16 skill_id ) { skill_get (skill_db[skill_id].cast_def_rate, skill_id); }
+int skill_get_weapontype( uint16 skill_id ) { skill_get (skill_db[skill_id].weapon, skill_id); }
+int skill_get_ammotype( uint16 skill_id ) { skill_get (skill_db[skill_id].ammo, skill_id); }
+int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].ammo_qty[skill_lv-1], skill_id, skill_lv); }
+int skill_get_inf2( uint16 skill_id ) { skill_get (skill_db[skill_id].inf2, skill_id); }
+int skill_get_castcancel( uint16 skill_id ) { skill_get (skill_db[skill_id].castcancel, skill_id); }
+int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].maxcount[skill_lv-1], skill_id, skill_lv); }
+int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].blewcount[skill_lv-1], skill_id, skill_lv); }
+int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].mhp[skill_lv-1], skill_id, skill_lv); }
+int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].castnodex[skill_lv-1], skill_id, skill_lv); }
+int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].delaynodex[skill_lv-1], skill_id, skill_lv); }
+int skill_get_type( uint16 skill_id ) { skill_get (skill_db[skill_id].skill_type, skill_id); }
+int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill_db[skill_id].unit_id[flag], skill_id); }
+int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_interval, skill_id); }
+int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].unit_range[skill_lv-1], skill_id, skill_lv); }
+int skill_get_unit_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BCT_ALL, skill_id); }
+int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BL_ALL, skill_id); }
+int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_flag, skill_id); }
+int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].unit_layout_type[skill_lv-1], skill_id, skill_lv); }
+int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].cooldown[skill_lv-1], skill_id, skill_lv); }
#ifdef RENEWAL_CAST
-int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ){ skill_get (skill_db[skill_id].fixed_cast[skill_lv-1], skill_id, skill_lv); }
+int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].fixed_cast[skill_lv-1], skill_id, skill_lv); }
#endif
int skill_tree_get_max(uint16 skill_id, int b_class)
{
@@ -255,6 +265,22 @@ int skill_get_casttype (uint16 skill_id) {
return CAST_DAMAGE;
}
+int skill_get_casttype2 (uint16 index) {
+ int inf = skill_db[index].inf;
+ if (inf&(INF_GROUND_SKILL))
+ return CAST_GROUND;
+ if (inf&INF_SUPPORT_SKILL)
+ return CAST_NODAMAGE;
+ if (inf&INF_SELF_SKILL) {
+ if(skill_db[index].inf2&INF2_NO_TARGET_SELF)
+ return CAST_DAMAGE; //Combo skill.
+ return CAST_NODAMAGE;
+ }
+ if (skill_db[index].nk&NK_NO_DAMAGE)
+ return CAST_NODAMAGE;
+ return CAST_DAMAGE;
+}
+
//Returns actual skill range taking into account attack range and AC_OWL [Skotlex]
int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
int range;
@@ -467,7 +493,7 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b
if( !(sd->sc.data[SC__REPRODUCE]) && (skill_id >= RK_ENCHANTBLADE && skill_id <= SR_RIDEINLIGHTNING) )
return 0;
// Reproduce will only copy skills according on the list. [Jobbie]
- else if( sd->sc.data[SC__REPRODUCE] && !skill_reproduce_db[skill_id] )
+ else if( sd->sc.data[SC__REPRODUCE] && !skill_reproduce_db[skill->get_index(skill_id)] )
return 0;
return 1;
@@ -2505,7 +2531,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
&& (!sc || !sc->data[SC_PRESERVE])
&& damage < tsd->battle_status.hp)
{ //Updated to not be able to copy skills if the blow will kill you. [Skotlex]
- int copy_skill = skill_id;
+ int copy_skill = skill_id, cidx = 0;
/**
* Copy Referal: dummy skills should point to their source upon copying
**/
@@ -2535,36 +2561,43 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
copy_skill = LG_OVERBRAND;
break;
}
-
- if ((tsd->status.skill[copy_skill].id == 0 || tsd->status.skill[copy_skill].flag == SKILL_FLAG_PLAGIARIZED) &&
+ cidx = skill->get_index(copy_skill);
+ if ((tsd->status.skill[cidx].id == 0 || tsd->status.skill[cidx].flag == SKILL_FLAG_PLAGIARIZED) &&
can_copy(tsd,copy_skill,bl)) // Split all the check into their own function [Aru]
{
- int lv;
+ int lv, idx = 0;
if( sc && sc->data[SC__REPRODUCE] && (lv = sc->data[SC__REPRODUCE]->val1) ) {
//Level dependent and limitation.
lv = min(lv,skill->get_max(copy_skill));
- if( tsd->reproduceskill_id && tsd->status.skill[tsd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) {
- tsd->status.skill[tsd->reproduceskill_id].id = 0;
- tsd->status.skill[tsd->reproduceskill_id].lv = 0;
- tsd->status.skill[tsd->reproduceskill_id].flag = 0;
- clif->deleteskill(tsd,tsd->reproduceskill_id);
+ idx = skill->get_index(tsd->reproduceskill_id);
+ if( tsd->reproduceskill_id ) {
+ idx = skill->get_index(tsd->reproduceskill_id);
+ if(tsd->status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED ) {
+ tsd->status.skill[idx].id = 0;
+ tsd->status.skill[idx].lv = 0;
+ tsd->status.skill[idx].flag = 0;
+ clif->deleteskill(tsd,tsd->reproduceskill_id);
+ }
}
tsd->reproduceskill_id = copy_skill;
pc_setglobalreg(tsd, "REPRODUCE_SKILL", copy_skill);
pc_setglobalreg(tsd, "REPRODUCE_SKILL_LV", lv);
- tsd->status.skill[copy_skill].id = copy_skill;
- tsd->status.skill[copy_skill].lv = lv;
- tsd->status.skill[copy_skill].flag = SKILL_FLAG_PLAGIARIZED;
+ tsd->status.skill[cidx].id = copy_skill;
+ tsd->status.skill[cidx].lv = lv;
+ tsd->status.skill[cidx].flag = SKILL_FLAG_PLAGIARIZED;
clif->addskill(tsd,copy_skill);
} else {
lv = skill_lv;
- if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED){
- tsd->status.skill[tsd->cloneskill_id].id = 0;
- tsd->status.skill[tsd->cloneskill_id].lv = 0;
- tsd->status.skill[tsd->cloneskill_id].flag = 0;
- clif->deleteskill(tsd,tsd->cloneskill_id);
+ if ( tsd->cloneskill_id ) {
+ idx = skill->get_index(tsd->cloneskill_id);
+ if ( tsd->status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED){
+ tsd->status.skill[idx].id = 0;
+ tsd->status.skill[idx].lv = 0;
+ tsd->status.skill[idx].flag = 0;
+ clif->deleteskill(tsd,tsd->cloneskill_id);
+ }
}
if ((type = pc_checkskill(tsd,RG_PLAGIARISM)) < lv)
@@ -2574,10 +2607,10 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
pc_setglobalreg(tsd, "CLONE_SKILL", copy_skill);
pc_setglobalreg(tsd, "CLONE_SKILL_LV", lv);
- tsd->status.skill[skill_id].id = copy_skill;
- tsd->status.skill[skill_id].lv = lv;
- tsd->status.skill[skill_id].flag = SKILL_FLAG_PLAGIARIZED;
- clif->addskill(tsd,skill_id);
+ tsd->status.skill[idx].id = copy_skill;
+ tsd->status.skill[idx].lv = lv;
+ tsd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
+ clif->addskill(tsd,copy_skill);
}
}
}
@@ -8010,7 +8043,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
break;
case SC_AUTOSHADOWSPELL:
if( sd ) {
- if( sd->status.skill[sd->reproduceskill_id].id || sd->status.skill[sd->cloneskill_id].id ) {
+ int idx1 = skill->get_index(sd->reproduceskill_id), idx2 = skill->get_index(sd->cloneskill_id);
+ if( sd->status.skill[idx1].id || sd->status.skill[idx2].id ) {
sc_start(src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax]
clif->autoshadowspell_list(sd);
clif->skill_nodamage(src,bl,skill_id,1,1);
@@ -16573,22 +16607,24 @@ int skill_spellbook (struct map_session_data *sd, int nameid) {
return 1;
}
int skill_select_menu(struct map_session_data *sd,uint16 skill_id) {
- int id, lv, prob, aslvl = 0;
+ int id, lv, prob, aslvl = 0, idx = 0;
nullpo_ret(sd);
if (sd->sc.data[SC_STOP]) {
aslvl = sd->sc.data[SC_STOP]->val1;
status_change_end(&sd->bl,SC_STOP,INVALID_TIMER);
}
+
+ idx = skill->get_index(skill_id);
if( skill_id >= GS_GLITTERING || skill->get_type(skill_id) != BF_MAGIC ||
- (id = sd->status.skill[skill_id].id) == 0 || sd->status.skill[skill_id].flag != SKILL_FLAG_PLAGIARIZED ) {
+ (id = sd->status.skill[idx].id) == 0 || sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED ) {
clif->skill_fail(sd,SC_AUTOSHADOWSPELL,0,0);
return 0;
}
lv = (aslvl + 1) / 2; // The level the skill will be autocasted
- lv = min(lv,sd->status.skill[skill_id].lv);
+ lv = min(lv,sd->status.skill[idx].lv);
prob = (aslvl == 10) ? 15 : (32 - 2 * aslvl); // Probability at level 10 was increased to 15.
sc_start4(&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill->get_time(SC_AUTOSHADOWSPELL,aslvl));
return 0;
@@ -16981,163 +17017,156 @@ void skill_init_unit_layout (void) {
for (i=0;i<MAX_SKILL_DB;i++) {
if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1)
continue;
- if( i >= HM_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX ) {
- int skill = i;
-
- if( i >= EL_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX ) {
- skill -= EL_SKILLRANGEMIN;
- skill += EL_SKILLBASE;
- }
- if( skill == EL_FIRE_MANTLE ) {
+
+ switch (skill_db[i].nameid) {
+ case MG_FIREWALL:
+ case WZ_ICEWALL:
+ case WL_EARTHSTRAIN://Warlock
+ // these will be handled later
+ break;
+ case PR_SANCTUARY:
+ case NPC_EVILLAND: {
+ static const int dx[] = {
+ -1, 0, 1,-2,-1, 0, 1, 2,-2,-1,
+ 0, 1, 2,-2,-1, 0, 1, 2,-1, 0, 1};
+ static const int dy[]={
+ -2,-2,-2,-1,-1,-1,-1,-1, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2};
+ skill_unit_layout[pos].count = 21;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ break;
+ case PR_MAGNUS: {
+ static const int dx[] = {
+ -1, 0, 1,-1, 0, 1,-3,-2,-1, 0,
+ 1, 2, 3,-3,-2,-1, 0, 1, 2, 3,
+ -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,-1, 0, 1};
+ static const int dy[] = {
+ -3,-3,-3,-2,-2,-2,-1,-1,-1,-1,
+ -1,-1,-1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3};
+ skill_unit_layout[pos].count = 33;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ break;
+ case MH_POISON_MIST:
+ case AS_VENOMDUST: {
+ static const int dx[] = {-1, 0, 0, 0, 1};
+ static const int dy[] = { 0,-1, 0, 1, 0};
+ skill_unit_layout[pos].count = 5;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ break;
+ case CR_GRANDCROSS:
+ case NPC_GRANDDARKNESS: {
+ static const int dx[] = {
+ 0, 0,-1, 0, 1,-2,-1, 0, 1, 2,
+ -4,-3,-2,-1, 0, 1, 2, 3, 4,-2,
+ -1, 0, 1, 2,-1, 0, 1, 0, 0};
+ static const int dy[] = {
+ -4,-3,-2,-2,-2,-1,-1,-1,-1,-1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 2, 3, 4};
+ skill_unit_layout[pos].count = 29;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ break;
+ case PF_FOGWALL: {
+ static const int dx[] = {
+ -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2};
+ static const int dy[] = {
+ -1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
+ skill_unit_layout[pos].count = 15;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ break;
+ case PA_GOSPEL: {
+ static const int dx[] = {
+ -1, 0, 1,-1, 0, 1,-3,-2,-1, 0,
+ 1, 2, 3,-3,-2,-1, 0, 1, 2, 3,
+ -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,
+ -1, 0, 1};
+ static const int dy[] = {
+ -3,-3,-3,-2,-2,-2,-1,-1,-1,-1,
+ -1,-1,-1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 3, 3, 3};
+ skill_unit_layout[pos].count = 33;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ break;
+ case NJ_KAENSIN: {
+ static const int dx[] = {-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2};
+ static const int dy[] = { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2};
+ skill_unit_layout[pos].count = 24;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ break;
+ case NJ_TATAMIGAESHI: {
+ //Level 1 (count 4, cross of 3x3)
+ static const int dx1[] = {-1, 1, 0, 0};
+ static const int dy1[] = { 0, 0,-1, 1};
+ //Level 2-3 (count 8, cross of 5x5)
+ static const int dx2[] = {-2,-1, 1, 2, 0, 0, 0, 0};
+ static const int dy2[] = { 0, 0, 0, 0,-2,-1, 1, 2};
+ //Level 4-5 (count 12, cross of 7x7
+ static const int dx3[] = {-3,-2,-1, 1, 2, 3, 0, 0, 0, 0, 0, 0};
+ static const int dy3[] = { 0, 0, 0, 0, 0, 0,-3,-2,-1, 1, 2, 3};
+ //lv1
+ j = 0;
+ skill_unit_layout[pos].count = 4;
+ memcpy(skill_unit_layout[pos].dx,dx1,sizeof(dx1));
+ memcpy(skill_unit_layout[pos].dy,dy1,sizeof(dy1));
+ skill_db[i].unit_layout_type[j] = pos;
+ //lv2/3
+ j++;
+ pos++;
+ skill_unit_layout[pos].count = 8;
+ memcpy(skill_unit_layout[pos].dx,dx2,sizeof(dx2));
+ memcpy(skill_unit_layout[pos].dy,dy2,sizeof(dy2));
+ skill_db[i].unit_layout_type[j] = pos;
+ skill_db[i].unit_layout_type[++j] = pos;
+ //lv4/5
+ j++;
+ pos++;
+ skill_unit_layout[pos].count = 12;
+ memcpy(skill_unit_layout[pos].dx,dx3,sizeof(dx3));
+ memcpy(skill_unit_layout[pos].dy,dy3,sizeof(dy3));
+ skill_db[i].unit_layout_type[j] = pos;
+ skill_db[i].unit_layout_type[++j] = pos;
+ //Fill in the rest using lv 5.
+ for (;j<MAX_SKILL_LEVEL;j++)
+ skill_db[i].unit_layout_type[j] = pos;
+ //Skip, this way the check below will fail and continue to the next skill.
+ pos++;
+ }
+ break;
+ case GN_WALLOFTHORN: {
+ static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0};
+ static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2};
+ skill_unit_layout[pos].count = 16;
+ memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
+ memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
+ }
+ break;
+ case EL_FIRE_MANTLE: {
static const int dx[] = {-1, 0, 1, 1, 1, 0,-1,-1};
static const int dy[] = { 1, 1, 1, 0,-1,-1,-1, 0};
skill_unit_layout[pos].count = 8;
memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
- }
- } else {
- switch (i) {
- case MG_FIREWALL:
- case WZ_ICEWALL:
- case WL_EARTHSTRAIN://Warlock
- // these will be handled later
- break;
- case PR_SANCTUARY:
- case NPC_EVILLAND: {
- static const int dx[] = {
- -1, 0, 1,-2,-1, 0, 1, 2,-2,-1,
- 0, 1, 2,-2,-1, 0, 1, 2,-1, 0, 1};
- static const int dy[]={
- -2,-2,-2,-1,-1,-1,-1,-1, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2};
- skill_unit_layout[pos].count = 21;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
- }
- break;
- case PR_MAGNUS: {
- static const int dx[] = {
- -1, 0, 1,-1, 0, 1,-3,-2,-1, 0,
- 1, 2, 3,-3,-2,-1, 0, 1, 2, 3,
- -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,-1, 0, 1};
- static const int dy[] = {
- -3,-3,-3,-2,-2,-2,-1,-1,-1,-1,
- -1,-1,-1, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3};
- skill_unit_layout[pos].count = 33;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
- }
- break;
- case MH_POISON_MIST:
- case AS_VENOMDUST: {
- static const int dx[] = {-1, 0, 0, 0, 1};
- static const int dy[] = { 0,-1, 0, 1, 0};
- skill_unit_layout[pos].count = 5;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
- }
- break;
- case CR_GRANDCROSS:
- case NPC_GRANDDARKNESS: {
- static const int dx[] = {
- 0, 0,-1, 0, 1,-2,-1, 0, 1, 2,
- -4,-3,-2,-1, 0, 1, 2, 3, 4,-2,
- -1, 0, 1, 2,-1, 0, 1, 0, 0};
- static const int dy[] = {
- -4,-3,-2,-2,-2,-1,-1,-1,-1,-1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
- 1, 1, 1, 1, 2, 2, 2, 3, 4};
- skill_unit_layout[pos].count = 29;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
- }
- break;
- case PF_FOGWALL: {
- static const int dx[] = {
- -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2};
- static const int dy[] = {
- -1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
- skill_unit_layout[pos].count = 15;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
- }
- break;
- case PA_GOSPEL: {
- static const int dx[] = {
- -1, 0, 1,-1, 0, 1,-3,-2,-1, 0,
- 1, 2, 3,-3,-2,-1, 0, 1, 2, 3,
- -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,
- -1, 0, 1};
- static const int dy[] = {
- -3,-3,-3,-2,-2,-2,-1,-1,-1,-1,
- -1,-1,-1, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
- 3, 3, 3};
- skill_unit_layout[pos].count = 33;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
- }
- break;
- case NJ_KAENSIN: {
- static const int dx[] = {-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2};
- static const int dy[] = { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2};
- skill_unit_layout[pos].count = 24;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
- }
- break;
- case NJ_TATAMIGAESHI: {
- //Level 1 (count 4, cross of 3x3)
- static const int dx1[] = {-1, 1, 0, 0};
- static const int dy1[] = { 0, 0,-1, 1};
- //Level 2-3 (count 8, cross of 5x5)
- static const int dx2[] = {-2,-1, 1, 2, 0, 0, 0, 0};
- static const int dy2[] = { 0, 0, 0, 0,-2,-1, 1, 2};
- //Level 4-5 (count 12, cross of 7x7
- static const int dx3[] = {-3,-2,-1, 1, 2, 3, 0, 0, 0, 0, 0, 0};
- static const int dy3[] = { 0, 0, 0, 0, 0, 0,-3,-2,-1, 1, 2, 3};
- //lv1
- j = 0;
- skill_unit_layout[pos].count = 4;
- memcpy(skill_unit_layout[pos].dx,dx1,sizeof(dx1));
- memcpy(skill_unit_layout[pos].dy,dy1,sizeof(dy1));
- skill_db[i].unit_layout_type[j] = pos;
- //lv2/3
- j++;
- pos++;
- skill_unit_layout[pos].count = 8;
- memcpy(skill_unit_layout[pos].dx,dx2,sizeof(dx2));
- memcpy(skill_unit_layout[pos].dy,dy2,sizeof(dy2));
- skill_db[i].unit_layout_type[j] = pos;
- skill_db[i].unit_layout_type[++j] = pos;
- //lv4/5
- j++;
- pos++;
- skill_unit_layout[pos].count = 12;
- memcpy(skill_unit_layout[pos].dx,dx3,sizeof(dx3));
- memcpy(skill_unit_layout[pos].dy,dy3,sizeof(dy3));
- skill_db[i].unit_layout_type[j] = pos;
- skill_db[i].unit_layout_type[++j] = pos;
- //Fill in the rest using lv 5.
- for (;j<MAX_SKILL_LEVEL;j++)
- skill_db[i].unit_layout_type[j] = pos;
- //Skip, this way the check below will fail and continue to the next skill.
- pos++;
- }
- break;
- case GN_WALLOFTHORN: {
- static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0};
- static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2};
- skill_unit_layout[pos].count = 16;
- memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx));
- memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy));
- }
- break;
- default:
- ShowError("unknown unit layout at skill %d\n",i);
- break;
- }
+ }
+ break;
+ default:
+ ShowError("unknown unit layout at skill %d\n",i);
+ break;
}
if (!skill_unit_layout[pos].count)
continue;
@@ -17353,7 +17382,8 @@ bool skill_parse_row_skilldb(char* split[], int columns, int current) {
idx = skill->get_index(skill_id);
if( !idx ) // invalid skill id
return false;
-
+
+ skill_db[idx].nameid = skill_id;
skill->split_atoi(split[1],skill_db[idx].range);
skill_db[idx].hit = atoi(split[2]);
skill_db[idx].inf = atoi(split[3]);
@@ -17562,7 +17592,7 @@ bool skill_parse_row_producedb(char* split[], int columns, int current) {
skill_produce_db[current].mat_id[y] = atoi(split[x]);
skill_produce_db[current].mat_amount[y] = atoi(split[x+1]);
}
-
+
return true;
}
@@ -17766,7 +17796,23 @@ void skill_readdb(void) {
void skill_reload (void) {
struct s_mapiterator *iter;
struct map_session_data *sd;
+ int i,c,k;
+
skill->read_db();
+
+ //[Ind/Hercules] refresh index cache
+ for(c = 0; c < CLASS_COUNT; c++) {
+ for( i = 0; i < MAX_SKILL_TREE; i++ ) {
+ if( skill_tree[c][i].id ) {
+ skill_tree[c][i].idx = skill->get_index(skill_tree[c][i].id);
+ for(k = 0; k < MAX_PC_SKILL_REQUIRE; k++) {
+ if( skill_tree[c][i].need[k].id )
+ skill_tree[c][i].need[k].idx = skill->get_index(skill_tree[c][i].need[k].id);
+ }
+ }
+ }
+ }
+ chrif_skillid2idx(0);
/* lets update all players skill tree : so that if any skill modes were changed they're properly updated */
iter = mapit_getallusers();
for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
@@ -17778,8 +17824,7 @@ void skill_reload (void) {
/*==========================================
*
*------------------------------------------*/
-int do_init_skill (void)
-{
+int do_init_skill (void) {
skilldb_name2id = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0);
skill->read_db();
@@ -17864,7 +17909,8 @@ void skill_defaults(void) {
skill->get_name = skill_get_name;
skill->get_desc = skill_get_desc;
skill->chk = skill_chk;
- skill->get_casttype = skill_get_casttype;
+ skill->get_casttype = skill_get_casttype;
+ skill->get_casttype2 = skill_get_casttype2;
skill->name2id = skill_name2id;
skill->isammotype = skill_isammotype;
skill->castend_id = skill_castend_id;
diff --git a/src/map/skill.h b/src/map/skill.h
index 3e2fc7936..553dabd6d 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -24,13 +24,13 @@ struct square;
**/
#define MAX_SKILL_DB MAX_SKILL
#define MAX_SKILL_PRODUCE_DB 270
-#define MAX_PRODUCE_RESOURCE 12
-#define MAX_SKILL_ARROW_DB 150
+#define MAX_PRODUCE_RESOURCE 10
+#define MAX_SKILL_ARROW_DB 140
#define MAX_ARROW_RESOURCE 5
-#define MAX_SKILL_ABRA_DB 350
-#define MAX_SKILL_IMPROVISE_DB 50
-#define MAX_SKILL_LEVEL 100
-#define MAX_SKILL_UNIT_LAYOUT 50
+#define MAX_SKILL_ABRA_DB 210
+#define MAX_SKILL_IMPROVISE_DB 30
+#define MAX_SKILL_LEVEL 10
+#define MAX_SKILL_UNIT_LAYOUT 45
#define MAX_SQUARE_LAYOUT 5 // 11*11 Placement of a maximum unit
#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1))
#define MAX_SKILLTIMERSKILL 15
@@ -1575,6 +1575,7 @@ struct skill_condition {
// Database skills
struct s_skill_db {
+ unsigned short nameid;
char name[NAME_LENGTH];
char desc[40];
int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max;
@@ -1748,9 +1749,10 @@ struct skill_interface {
const char* (*get_name) ( uint16 skill_id );
const char* (*get_desc) ( uint16 skill_id );
/* check */
- void (*chk) (int16* skill_id, uint16 skill_lv);
+ void (*chk) (int16* skill_id);
/* whether its CAST_GROUND, CAST_DAMAGE or CAST_NODAMAGE */
int (*get_casttype) (uint16 skill_id);
+ int (*get_casttype2) (uint16 index);
int (*name2id) (const char* name);
int (*isammotype) (struct map_session_data *sd, int skill);
int (*castend_id) (int tid, unsigned int tick, int id, intptr_t data);