diff options
author | shennetsind <ind@henn.et> | 2013-04-27 13:33:10 -0300 |
---|---|---|
committer | shennetsind <ind@henn.et> | 2013-04-27 13:33:10 -0300 |
commit | 0f4a50d13538c3e5d3ca4d3822f92217c8da0479 (patch) | |
tree | 2daf0a99ca0104d6a7fa95637e0377e7a9a0d6ed | |
parent | 1f6360f2e157d8eb742a32baed4c5ec7c68c0ef1 (diff) | |
download | hercules-0f4a50d13538c3e5d3ca4d3822f92217c8da0479.tar.gz hercules-0f4a50d13538c3e5d3ca4d3822f92217c8da0479.tar.bz2 hercules-0f4a50d13538c3e5d3ca4d3822f92217c8da0479.tar.xz hercules-0f4a50d13538c3e5d3ca4d3822f92217c8da0479.zip |
Skill ID Processing Overhaul
http://hercules.ws/board/topic/512-skill-id-processing-overhaul/
Signed-off-by: shennetsind <ind@henn.et>
-rw-r--r-- | conf/battle/skill.conf | 4 | ||||
-rw-r--r-- | src/char/char.c | 42 | ||||
-rw-r--r-- | src/common/mmo.h | 3 | ||||
-rw-r--r-- | src/map/atcommand.c | 31 | ||||
-rw-r--r-- | src/map/battle.c | 5 | ||||
-rw-r--r-- | src/map/battle.h | 1 | ||||
-rw-r--r-- | src/map/chrif.c | 54 | ||||
-rw-r--r-- | src/map/chrif.h | 6 | ||||
-rw-r--r-- | src/map/clif.c | 42 | ||||
-rw-r--r-- | src/map/mob.c | 23 | ||||
-rw-r--r-- | src/map/npc.c | 75 | ||||
-rw-r--r-- | src/map/pc.c | 360 | ||||
-rw-r--r-- | src/map/pc.h | 3 | ||||
-rw-r--r-- | src/map/script.c | 4 | ||||
-rw-r--r-- | src/map/skill.c | 508 | ||||
-rw-r--r-- | src/map/skill.h | 16 |
16 files changed, 614 insertions, 563 deletions
diff --git a/conf/battle/skill.conf b/conf/battle/skill.conf index 622ce7877..0f4d6abb6 100644 --- a/conf/battle/skill.conf +++ b/conf/battle/skill.conf @@ -234,10 +234,6 @@ emergency_call: 11 //16: Disable skill from affecting Guild Master guild_aura: 31 -// Max Possible Level of Monster skills -// Note: If your MVPs are too tough, reduce it to 10. -mob_max_skilllvl: 100 - // Allows players to skip menu when casting Teleport level 1 // Menu contains two options. "Random" and "Cancel" skip_teleport_lv1_menu: no 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); |