|
@@ -934,12 +934,12 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd,
|
|
clif_updatestatus(b_sd, SP_JOBEXP);
|
|
clif_updatestatus(b_sd, SP_JOBEXP);
|
|
|
|
|
|
// Baby Skills
|
|
// Baby Skills
|
|
- pc_skill(b_sd, WE_BABY, 1, ADDSKILL_PERMANENT);
|
|
|
|
- pc_skill(b_sd, WE_CALLPARENT, 1, ADDSKILL_PERMANENT);
|
|
|
|
|
|
+ pc_skill(b_sd, WE_BABY, 1, 0);
|
|
|
|
+ pc_skill(b_sd, WE_CALLPARENT, 1, 0);
|
|
|
|
|
|
// Parents Skills
|
|
// Parents Skills
|
|
- pc_skill(p1_sd, WE_CALLBABY, 1, ADDSKILL_PERMANENT);
|
|
|
|
- pc_skill(p2_sd, WE_CALLBABY, 1, ADDSKILL_PERMANENT);
|
|
|
|
|
|
+ pc_skill(p1_sd, WE_CALLBABY, 1, 0);
|
|
|
|
+ pc_skill(p2_sd, WE_CALLBABY, 1, 0);
|
|
|
|
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -1248,7 +1248,6 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
|
|
* Check if player have any item cooldowns on
|
|
* Check if player have any item cooldowns on
|
|
**/
|
|
**/
|
|
pc_itemcd_do(sd,true);
|
|
pc_itemcd_do(sd,true);
|
|
- pc_validate_skill(sd);
|
|
|
|
|
|
|
|
#ifdef BOUND_ITEMS
|
|
#ifdef BOUND_ITEMS
|
|
// Party bound item check
|
|
// Party bound item check
|
|
@@ -1356,7 +1355,7 @@ void pc_reg_received(struct map_session_data *sd)
|
|
|
|
|
|
if ((i = pc_checkskill(sd,RG_PLAGIARISM)) > 0) {
|
|
if ((i = pc_checkskill(sd,RG_PLAGIARISM)) > 0) {
|
|
sd->cloneskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM));
|
|
sd->cloneskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM));
|
|
- if (sd->cloneskill_idx > 0) {
|
|
|
|
|
|
+ if (sd->cloneskill_idx >= 0) {
|
|
sd->status.skill[sd->cloneskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM);
|
|
sd->status.skill[sd->cloneskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM);
|
|
sd->status.skill[sd->cloneskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM_LV);
|
|
sd->status.skill[sd->cloneskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM_LV);
|
|
if (sd->status.skill[sd->cloneskill_idx].lv > i)
|
|
if (sd->status.skill[sd->cloneskill_idx].lv > i)
|
|
@@ -1366,7 +1365,7 @@ void pc_reg_received(struct map_session_data *sd)
|
|
}
|
|
}
|
|
if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) {
|
|
if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) {
|
|
sd->reproduceskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_REPRODUCE));
|
|
sd->reproduceskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_REPRODUCE));
|
|
- if (sd->reproduceskill_idx > 0) {
|
|
|
|
|
|
+ if (sd->reproduceskill_idx >= 0) {
|
|
sd->status.skill[sd->reproduceskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE);
|
|
sd->status.skill[sd->reproduceskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE);
|
|
sd->status.skill[sd->reproduceskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE_LV);
|
|
sd->status.skill[sd->reproduceskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE_LV);
|
|
if (i < sd->status.skill[sd->reproduceskill_idx].lv)
|
|
if (i < sd->status.skill[sd->reproduceskill_idx].lv)
|
|
@@ -1449,20 +1448,21 @@ void pc_reg_received(struct map_session_data *sd)
|
|
|
|
|
|
static int pc_calc_skillpoint(struct map_session_data* sd)
|
|
static int pc_calc_skillpoint(struct map_session_data* sd)
|
|
{
|
|
{
|
|
- uint16 i, skill_point = 0;
|
|
|
|
|
|
+ uint16 i, skill_point=0;
|
|
|
|
|
|
nullpo_ret(sd);
|
|
nullpo_ret(sd);
|
|
|
|
|
|
- for(i = 1; i < MAX_SKILL; i++) {
|
|
|
|
- if( sd->status.skill[i].id && sd->status.skill[i].lv > 0) {
|
|
|
|
- uint16 inf2 = skill_get_inf2(sd->status.skill[i].id);
|
|
|
|
- if ((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) &&
|
|
|
|
|
|
+ for(i=1;i<MAX_SKILL;i++){
|
|
|
|
+ uint8 skill_lv;
|
|
|
|
+ if( (skill_lv = pc_checkskill(sd,i)) > 0) {
|
|
|
|
+ uint16 inf2 = skill_get_inf2(i);
|
|
|
|
+ if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) &&
|
|
!(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex]
|
|
!(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex]
|
|
- )
|
|
|
|
- {
|
|
|
|
|
|
+ ) {
|
|
if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
|
|
if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
|
|
- skill_point += sd->status.skill[i].lv;
|
|
|
|
- else if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0)
|
|
|
|
|
|
+ skill_point += skill_lv;
|
|
|
|
+ else
|
|
|
|
+ if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0)
|
|
skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
|
|
skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1471,57 +1471,6 @@ static int pc_calc_skillpoint(struct map_session_data* sd)
|
|
return skill_point;
|
|
return skill_point;
|
|
}
|
|
}
|
|
|
|
|
|
-static bool pc_grant_allskills(struct map_session_data *sd, bool addlv) {
|
|
|
|
- uint16 i = 0;
|
|
|
|
-
|
|
|
|
- if (!sd || !pc_has_permission(sd, PC_PERM_ALL_SKILL) || !SKILL_MAX_DB())
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Dummy skills must NOT be added here otherwise they'll be displayed in the,
|
|
|
|
- * skill tree and since they have no icons they'll give resource errors
|
|
|
|
- * Get ALL skills except npc/guild ones. [Skotlex]
|
|
|
|
- * Don't add SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage]
|
|
|
|
- **/
|
|
|
|
- for( i = 0; i < MAX_SKILL; i++ ) {
|
|
|
|
- uint16 skill_id = skill_idx2id(i);
|
|
|
|
- if (!skill_id || (skill_get_inf2(skill_id)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)))
|
|
|
|
- continue;
|
|
|
|
- switch (skill_id) {
|
|
|
|
- case SM_SELFPROVOKE:
|
|
|
|
- case AB_DUPLELIGHT_MELEE:
|
|
|
|
- case AB_DUPLELIGHT_MAGIC:
|
|
|
|
- case WL_CHAINLIGHTNING_ATK:
|
|
|
|
- case WL_TETRAVORTEX_FIRE:
|
|
|
|
- case WL_TETRAVORTEX_WATER:
|
|
|
|
- case WL_TETRAVORTEX_WIND:
|
|
|
|
- case WL_TETRAVORTEX_GROUND:
|
|
|
|
- case WL_SUMMON_ATK_FIRE:
|
|
|
|
- case WL_SUMMON_ATK_WIND:
|
|
|
|
- case WL_SUMMON_ATK_WATER:
|
|
|
|
- case WL_SUMMON_ATK_GROUND:
|
|
|
|
- case LG_OVERBRAND_BRANDISH:
|
|
|
|
- case LG_OVERBRAND_PLUSATK:
|
|
|
|
- case WM_SEVERE_RAINSTORM_MELEE:
|
|
|
|
- case RL_R_TRIP_PLUSATK:
|
|
|
|
- case SG_DEVIL:
|
|
|
|
- case MO_TRIPLEATTACK:
|
|
|
|
- case RG_SNATCHER:
|
|
|
|
- continue;
|
|
|
|
- default:
|
|
|
|
- {
|
|
|
|
- uint8 lv = (uint8)skill_get_max(skill_id);
|
|
|
|
- if (lv > 0) {
|
|
|
|
- sd->status.skill[i].id = skill_id;
|
|
|
|
- if (addlv)
|
|
|
|
- sd->status.skill[i].lv = lv;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return true;
|
|
|
|
-}
|
|
|
|
|
|
|
|
/*==========================================
|
|
/*==========================================
|
|
* Calculation of skill level.
|
|
* Calculation of skill level.
|
|
@@ -1529,8 +1478,8 @@ static bool pc_grant_allskills(struct map_session_data *sd, bool addlv) {
|
|
*------------------------------------------*/
|
|
*------------------------------------------*/
|
|
void pc_calc_skilltree(struct map_session_data *sd)
|
|
void pc_calc_skilltree(struct map_session_data *sd)
|
|
{
|
|
{
|
|
- int i, flag;
|
|
|
|
- int c = 0;
|
|
|
|
|
|
+ int i,flag;
|
|
|
|
+ int c=0;
|
|
|
|
|
|
nullpo_retv(sd);
|
|
nullpo_retv(sd);
|
|
i = pc_calc_skilltree_normalize_job(sd);
|
|
i = pc_calc_skilltree_normalize_job(sd);
|
|
@@ -1547,52 +1496,41 @@ void pc_calc_skilltree(struct map_session_data *sd)
|
|
sd->status.skill[i].id = 0; //First clear skills.
|
|
sd->status.skill[i].id = 0; //First clear skills.
|
|
/* permanent skills that must be re-checked */
|
|
/* permanent skills that must be re-checked */
|
|
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) {
|
|
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) {
|
|
- uint16 sk_id = skill_idx2id(i);
|
|
|
|
- if (!sk_id) {
|
|
|
|
- sd->status.skill[i].id = 0;
|
|
|
|
- sd->status.skill[i].lv = 0;
|
|
|
|
- sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- switch (sk_id) {
|
|
|
|
|
|
+ switch( i ) {
|
|
case NV_TRICKDEAD:
|
|
case NV_TRICKDEAD:
|
|
if( (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) {
|
|
if( (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) {
|
|
- sd->status.skill[i].id = 0;
|
|
|
|
- sd->status.skill[i].lv = 0;
|
|
|
|
- sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
|
|
|
|
+ sd->status.skill[i].id = 0;
|
|
|
|
+ sd->status.skill[i].lv = 0;
|
|
|
|
+ sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- for( i = 0; i < MAX_SKILL; i++ ) {
|
|
|
|
- uint16 skill_id = 0;
|
|
|
|
-
|
|
|
|
- // Restore original level of skills after deleting earned skills.
|
|
|
|
- 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 ) {
|
|
|
|
|
|
+ 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].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;
|
|
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
}
|
|
}
|
|
|
|
|
|
- //Enable Bard/Dancer spirit linked skills.
|
|
|
|
- if (!(skill_id = skill_idx2id(i)) || skill_id < DC_HUMMING || skill_id > DC_SERVICEFORYOU)
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- if( &sd->sc && sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER ) {
|
|
|
|
- //Link Dancer skills to bard.
|
|
|
|
- if( sd->status.sex ) {
|
|
|
|
|
|
+ if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= 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 )
|
|
if( sd->status.skill[i-8].lv < 10 )
|
|
continue;
|
|
continue;
|
|
- sd->status.skill[i].id = skill_id;
|
|
|
|
|
|
+ sd->status.skill[i].id = i;
|
|
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].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
|
|
sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
|
|
}
|
|
}
|
|
- //Link Bard skills to dancer.
|
|
|
|
- else {
|
|
|
|
|
|
+ else
|
|
|
|
+ { //Link bard skills to dancer.
|
|
if( sd->status.skill[i].lv < 10 )
|
|
if( sd->status.skill[i].lv < 10 )
|
|
continue;
|
|
continue;
|
|
- sd->status.skill[i-8].id = skill_id - 8;
|
|
|
|
|
|
+ sd->status.skill[i-8].id = i - 8;
|
|
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].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
|
|
sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill
|
|
}
|
|
}
|
|
@@ -1602,84 +1540,105 @@ void pc_calc_skilltree(struct map_session_data *sd)
|
|
// Removes Taekwon Ranker skill bonus
|
|
// Removes Taekwon Ranker skill bonus
|
|
if ((sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON) {
|
|
if ((sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON) {
|
|
uint16 c_ = pc_class2idx(JOB_TAEKWON);
|
|
uint16 c_ = pc_class2idx(JOB_TAEKWON);
|
|
-
|
|
|
|
for (i = 0; i < MAX_SKILL_TREE; i++) {
|
|
for (i = 0; i < MAX_SKILL_TREE; i++) {
|
|
- uint16 sk_id = skill_tree[c_][i].id;
|
|
|
|
- uint16 sk_idx = 0;
|
|
|
|
-
|
|
|
|
- if (!sk_id || !(sk_idx = skill_get_index(skill_tree[c_][i].id)))
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- if (sd->status.skill[sk_idx].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[sk_idx].flag != SKILL_FLAG_PERM_GRANTED) {
|
|
|
|
- if (sk_id == NV_BASIC || sk_id == NV_FIRSTAID || sk_id == WE_CALLBABY)
|
|
|
|
|
|
+ uint16 x = skill_get_index(skill_tree[c_][i].id), skid = sd->status.skill[x].id;
|
|
|
|
+ if (skid && x > 0 && sd->status.skill[x].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[x].flag != SKILL_FLAG_PERM_GRANTED) {
|
|
|
|
+ if (skid == NV_BASIC || skid == NV_FIRSTAID || skid == WE_CALLBABY)
|
|
continue;
|
|
continue;
|
|
- sd->status.skill[sk_idx].id = 0;
|
|
|
|
- sd->status.skill[sk_idx].lv = 0;
|
|
|
|
- sd->status.skill[sk_idx].flag = SKILL_FLAG_PERMANENT;
|
|
|
|
|
|
+ sd->status.skill[x].id = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- // Grant all skills
|
|
|
|
- pc_grant_allskills(sd, false);
|
|
|
|
|
|
+ if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) {
|
|
|
|
+ for( i = 0; i < MAX_SKILL; i++ ) {
|
|
|
|
+ switch(i) {
|
|
|
|
+ /**
|
|
|
|
+ * 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
|
|
|
|
+ **/
|
|
|
|
+ case SM_SELFPROVOKE:
|
|
|
|
+ case AB_DUPLELIGHT_MELEE:
|
|
|
|
+ case AB_DUPLELIGHT_MAGIC:
|
|
|
|
+ case WL_CHAINLIGHTNING_ATK:
|
|
|
|
+ case WL_TETRAVORTEX_FIRE:
|
|
|
|
+ case WL_TETRAVORTEX_WATER:
|
|
|
|
+ case WL_TETRAVORTEX_WIND:
|
|
|
|
+ case WL_TETRAVORTEX_GROUND:
|
|
|
|
+ case WL_SUMMON_ATK_FIRE:
|
|
|
|
+ case WL_SUMMON_ATK_WIND:
|
|
|
|
+ case WL_SUMMON_ATK_WATER:
|
|
|
|
+ case WL_SUMMON_ATK_GROUND:
|
|
|
|
+ case LG_OVERBRAND_BRANDISH:
|
|
|
|
+ case LG_OVERBRAND_PLUSATK:
|
|
|
|
+ case WM_SEVERE_RAINSTORM_MELEE:
|
|
|
|
+ case RL_R_TRIP_PLUSATK:
|
|
|
|
+ continue;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if( skill_get_inf2(i)&(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;
|
|
|
|
+ }
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
|
|
do {
|
|
do {
|
|
- uint16 skid = 0;
|
|
|
|
-
|
|
|
|
|
|
+ short skid=0;
|
|
flag = 0;
|
|
flag = 0;
|
|
- for (i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].id) > 0; i++) {
|
|
|
|
- bool fail = false;
|
|
|
|
- uint16 sk_idx = skill_get_index(skid);
|
|
|
|
-
|
|
|
|
- if (sd->status.skill[sk_idx].id)
|
|
|
|
|
|
+ for( i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].id) > 0; i++ )
|
|
|
|
+ {
|
|
|
|
+ int f;
|
|
|
|
+ if( sd->status.skill[skid].id )
|
|
continue; //Skill already known.
|
|
continue; //Skill already known.
|
|
|
|
|
|
- if (!battle_config.skillfree) {
|
|
|
|
- uint8 j;
|
|
|
|
|
|
+ f = 1;
|
|
|
|
+ if(!battle_config.skillfree) {
|
|
|
|
+ int j;
|
|
for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) {
|
|
for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) {
|
|
- uint16 sk_need_id = skill_tree[c][i].need[j].id;
|
|
|
|
- uint16 sk_need_idx = 0;
|
|
|
|
-
|
|
|
|
- if (sk_need_id && (sk_need_idx = skill_get_index(sk_need_id))) {
|
|
|
|
- short sk_need = 0;
|
|
|
|
-
|
|
|
|
- if (sd->status.skill[sk_need_idx].id == 0 || sd->status.skill[sk_need_idx].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[sk_need_idx].flag == SKILL_FLAG_PLAGIARIZED)
|
|
|
|
- sk_need = sk_need_id; //Not learned.
|
|
|
|
- else if (sd->status.skill[sk_need_idx].flag >= SKILL_FLAG_REPLACED_LV_0) //Real learned level
|
|
|
|
- sk_need = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0;
|
|
|
|
|
|
+ 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)
|
|
|
|
+ k = 0; //Not learned.
|
|
else
|
|
else
|
|
- sk_need = pc_checkskill(sd,sk_need_id);
|
|
|
|
-
|
|
|
|
- if (sk_need < skill_tree[c][i].need[j].lv) {
|
|
|
|
- fail = true;
|
|
|
|
|
|
+ if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real learned 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)
|
|
|
|
+ {
|
|
|
|
+ f = 0;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- if (sd->status.job_level < skill_tree[c][i].joblv) { //We need to get the actual class in this case
|
|
|
|
|
|
+ if( sd->status.job_level < skill_tree[c][i].joblv ) { //We need to get the actual class in this case
|
|
int class_ = pc_mapid2jobid(sd->class_, sd->status.sex);
|
|
int class_ = pc_mapid2jobid(sd->class_, sd->status.sex);
|
|
class_ = pc_class2idx(class_);
|
|
class_ = pc_class2idx(class_);
|
|
if (class_ == c || (class_ != c && sd->status.job_level < skill_tree[class_][i].joblv))
|
|
if (class_ == c || (class_ != c && sd->status.job_level < skill_tree[class_][i].joblv))
|
|
- fail = true; // job level requirement wasn't satisfied
|
|
|
|
|
|
+ f = 0; // job level requirement wasn't satisfied
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (!fail) {
|
|
|
|
- int inf2 = skill_get_inf2(skid);
|
|
|
|
|
|
+ if( f ) {
|
|
|
|
+ int inf2;
|
|
|
|
+ inf2 = skill_get_inf2(skid);
|
|
|
|
|
|
- if (!sd->status.skill[skid].lv && (
|
|
|
|
|
|
+ if(!sd->status.skill[skid].lv && (
|
|
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
|
|
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
|
|
inf2&INF2_WEDDING_SKILL ||
|
|
inf2&INF2_WEDDING_SKILL ||
|
|
(inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT])
|
|
(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.
|
|
continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills.
|
|
|
|
|
|
- sd->status.skill[sk_idx].id = skid;
|
|
|
|
|
|
+ sd->status.skill[skid].id = skid;
|
|
|
|
|
|
if(inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed.
|
|
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[sk_idx].lv = 1; // need to manually specify a skill level
|
|
|
|
- sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
|
|
|
|
|
|
+ sd->status.skill[skid].lv = 1; // need to manually specify a skill level
|
|
|
|
+ sd->status.skill[skid].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill.
|
|
}
|
|
}
|
|
flag = 1; // skill list has changed, perform another pass
|
|
flag = 1; // skill list has changed, perform another pass
|
|
}
|
|
}
|
|
@@ -1687,7 +1646,7 @@ void pc_calc_skilltree(struct map_session_data *sd)
|
|
} while(flag);
|
|
} while(flag);
|
|
|
|
|
|
if( c > 0 && sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) ) {
|
|
if( c > 0 && sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) ) {
|
|
- unsigned short skid = 0;
|
|
|
|
|
|
+ short skid=0;
|
|
/* Taekwon Ranker Bonus Skill Tree
|
|
/* Taekwon Ranker Bonus Skill Tree
|
|
============================================
|
|
============================================
|
|
- Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking.
|
|
- Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking.
|
|
@@ -1695,28 +1654,25 @@ void pc_calc_skilltree(struct map_session_data *sd)
|
|
- (sd->status.skill_point == 0) to wait until all skill points are assigned to avoid problems with Job Change quest. */
|
|
- (sd->status.skill_point == 0) to wait until all skill points are assigned to avoid problems with Job Change quest. */
|
|
|
|
|
|
for( i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].id) > 0; i++ ) {
|
|
for( i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].id) > 0; i++ ) {
|
|
- uint16 sk_idx = 0;
|
|
|
|
- if (!(sk_idx = skill_get_index(skid)))
|
|
|
|
- continue;
|
|
|
|
if( (skill_get_inf2(skid)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
|
|
if( (skill_get_inf2(skid)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
|
|
continue; //Do not include Quest/Wedding skills.
|
|
continue; //Do not include Quest/Wedding skills.
|
|
- if( sd->status.skill[sk_idx].id == 0 ) { //do we really want skid as index ? //Lighta
|
|
|
|
- sd->status.skill[sk_idx].id = skid;
|
|
|
|
- sd->status.skill[sk_idx].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill.
|
|
|
|
|
|
+ if( sd->status.skill[skid].id == 0 ) { //do we really want skid as index ? //Lighta
|
|
|
|
+ sd->status.skill[skid].id = skid;
|
|
|
|
+ sd->status.skill[skid].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill.
|
|
} else if( skid != NV_BASIC )
|
|
} else if( skid != NV_BASIC )
|
|
- sd->status.skill[sk_idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[sk_idx].lv; // Remember original level
|
|
|
|
- sd->status.skill[sk_idx].lv = skill_tree_get_max(skid, sd->status.class_);
|
|
|
|
|
|
+ sd->status.skill[skid].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[skid].lv; // Remember original level
|
|
|
|
+ sd->status.skill[skid].lv = skill_tree_get_max(skid, sd->status.class_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//Checks if you can learn a new skill after having leveled up a skill.
|
|
//Checks if you can learn a new skill after having leveled up a skill.
|
|
-static void pc_check_skilltree(struct map_session_data *sd)
|
|
|
|
|
|
+static void pc_check_skilltree(struct map_session_data *sd, int skill)
|
|
{
|
|
{
|
|
- int i, flag = 0;
|
|
|
|
- int c = 0;
|
|
|
|
|
|
+ int i,id=0,flag;
|
|
|
|
+ int c=0;
|
|
|
|
|
|
- if (battle_config.skillfree)
|
|
|
|
|
|
+ if(battle_config.skillfree)
|
|
return; //Function serves no purpose if this is set
|
|
return; //Function serves no purpose if this is set
|
|
|
|
|
|
i = pc_calc_skilltree_normalize_job(sd);
|
|
i = pc_calc_skilltree_normalize_job(sd);
|
|
@@ -1726,54 +1682,44 @@ static void pc_check_skilltree(struct map_session_data *sd)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
c = pc_class2idx(c);
|
|
c = pc_class2idx(c);
|
|
-
|
|
|
|
do {
|
|
do {
|
|
- uint16 skid = 0;
|
|
|
|
-
|
|
|
|
flag = 0;
|
|
flag = 0;
|
|
- for (i = 0; i < MAX_SKILL_TREE && (skid = skill_tree[c][i].id) > 0; i++ ) {
|
|
|
|
- uint16 sk_idx = skill_get_index(skid);
|
|
|
|
- bool fail = false;
|
|
|
|
- uint8 j = 0;
|
|
|
|
-
|
|
|
|
- if (sd->status.skill[sk_idx].id) //Already learned
|
|
|
|
|
|
+ for( i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++ )
|
|
|
|
+ {
|
|
|
|
+ int j, f = 1;
|
|
|
|
+ if( sd->status.skill[id].id ) //Already learned
|
|
continue;
|
|
continue;
|
|
-
|
|
|
|
- for (j = 0; j < MAX_PC_SKILL_REQUIRE; j++) {
|
|
|
|
- uint16 sk_need_id = skill_tree[c][i].need[j].id;
|
|
|
|
- uint16 sk_need_idx = 0;
|
|
|
|
-
|
|
|
|
- if (sk_need_id && (sk_need_idx = skill_get_index(sk_need_id))) {
|
|
|
|
- short sk_need = sk_need_id;
|
|
|
|
-
|
|
|
|
- if (sd->status.skill[sk_need_idx].id == 0 || sd->status.skill[sk_need_idx].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[sk_need_idx].flag == SKILL_FLAG_PLAGIARIZED)
|
|
|
|
- sk_need = 0; //Not learned.
|
|
|
|
- else if (sd->status.skill[sk_need_idx].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level
|
|
|
|
- sk_need = sd->status.skill[sk_need_idx].flag - SKILL_FLAG_REPLACED_LV_0;
|
|
|
|
|
|
+ for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ){
|
|
|
|
+ int k = skill_tree[c][i].need[j].id;
|
|
|
|
+ if( k != 0 ){
|
|
|
|
+ if( sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED )
|
|
|
|
+ k = 0; //Not learned.
|
|
else
|
|
else
|
|
- sk_need = pc_checkskill(sd,sk_need_id);
|
|
|
|
-
|
|
|
|
- if (sk_need < skill_tree[c][i].need[j].lv) {
|
|
|
|
- fail = true;
|
|
|
|
|
|
+ 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 )
|
|
|
|
+ {
|
|
|
|
+ f = 0;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- if( fail )
|
|
|
|
|
|
+ if( !f )
|
|
continue;
|
|
continue;
|
|
if( sd->status.job_level < skill_tree[c][i].joblv )
|
|
if( sd->status.job_level < skill_tree[c][i].joblv )
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- j = skill_get_inf2(skid);
|
|
|
|
- if( !sd->status.skill[sk_idx].lv && (
|
|
|
|
|
|
+ j = skill_get_inf2(id);
|
|
|
|
+ if( !sd->status.skill[id].lv && (
|
|
(j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
|
|
(j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
|
|
j&INF2_WEDDING_SKILL ||
|
|
j&INF2_WEDDING_SKILL ||
|
|
(j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT])
|
|
(j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT])
|
|
) )
|
|
) )
|
|
continue; //Cannot be learned via normal means.
|
|
continue; //Cannot be learned via normal means.
|
|
|
|
|
|
- sd->status.skill[sk_idx].id = skid;
|
|
|
|
|
|
+ sd->status.skill[id].id = id;
|
|
flag = 1;
|
|
flag = 1;
|
|
}
|
|
}
|
|
} while(flag);
|
|
} while(flag);
|
|
@@ -1785,12 +1731,14 @@ void pc_clean_skilltree(struct map_session_data *sd)
|
|
{
|
|
{
|
|
uint16 i;
|
|
uint16 i;
|
|
for (i = 0; i < MAX_SKILL; 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].id = 0;
|
|
sd->status.skill[i].lv = 0;
|
|
sd->status.skill[i].lv = 0;
|
|
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
}
|
|
}
|
|
- 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].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
|
|
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
}
|
|
}
|
|
@@ -3868,78 +3816,74 @@ void pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type
|
|
* 2 - Like 1, except the level granted can stack with previously learned level.
|
|
* 2 - Like 1, except the level granted can stack with previously learned level.
|
|
* 4 - Like 0, except the skill will ignore skill tree (saves through job changes and resets).
|
|
* 4 - Like 0, except the skill will ignore skill tree (saves through job changes and resets).
|
|
*------------------------------------------*/
|
|
*------------------------------------------*/
|
|
-bool pc_skill(TBL_PC* sd, uint16 skill_id, int level, enum e_addskill_type type) {
|
|
|
|
- uint16 idx = 0;
|
|
|
|
|
|
+int pc_skill(TBL_PC* sd, int id, int level, int flag)
|
|
|
|
+{
|
|
nullpo_ret(sd);
|
|
nullpo_ret(sd);
|
|
|
|
|
|
- if (!skill_id || !(idx = skill_get_index(skill_id))) {
|
|
|
|
- ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", skill_id);
|
|
|
|
- return false;
|
|
|
|
|
|
+ if( id <= 0 || id >= MAX_SKILL || skill_db[id].name == NULL) {
|
|
|
|
+ ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", id);
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
- if (level > MAX_SKILL_LEVEL) {
|
|
|
|
|
|
+ if( level > MAX_SKILL_LEVEL ) {
|
|
ShowError("pc_skill: Skill level %d too high. Max lv supported is %d\n", level, MAX_SKILL_LEVEL);
|
|
ShowError("pc_skill: Skill level %d too high. Max lv supported is %d\n", level, MAX_SKILL_LEVEL);
|
|
- return false;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
- if (type == ADDSKILL_TEMP_ADDLEVEL && sd->status.skill[idx].lv + level > MAX_SKILL_LEVEL) {
|
|
|
|
- ShowWarning("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d. Set to max level.\n", level, MAX_SKILL_LEVEL, sd->status.skill[idx].lv);
|
|
|
|
- level = MAX_SKILL_LEVEL - sd->status.skill[idx].lv;
|
|
|
|
|
|
+ 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);
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- switch (type) {
|
|
|
|
- case ADDSKILL_PERMANENT: //Set skill data overwriting whatever was there before.
|
|
|
|
- sd->status.skill[idx].id = skill_id;
|
|
|
|
- sd->status.skill[idx].lv = level;
|
|
|
|
- sd->status.skill[idx].flag = SKILL_FLAG_PERMANENT;
|
|
|
|
- if (level == 0) { //Remove skill.
|
|
|
|
- sd->status.skill[idx].id = 0;
|
|
|
|
- clif_deleteskill(sd,skill_id);
|
|
|
|
|
|
+ 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;
|
|
|
|
+ if( level == 0 ) { //Remove skill.
|
|
|
|
+ sd->status.skill[id].id = 0;
|
|
|
|
+ clif_deleteskill(sd,id);
|
|
} else
|
|
} else
|
|
- clif_addskill(sd,skill_id);
|
|
|
|
- if (!skill_get_inf(skill_id)) //Only recalculate for passive skills.
|
|
|
|
|
|
+ clif_addskill(sd,id);
|
|
|
|
+ if( !skill_get_inf(id) ) //Only recalculate for passive skills.
|
|
status_calc_pc(sd, SCO_NONE);
|
|
status_calc_pc(sd, SCO_NONE);
|
|
break;
|
|
break;
|
|
-
|
|
|
|
- case ADDSKILL_TEMP: //Item bonus skill.
|
|
|
|
- if (sd->status.skill[idx].id != 0) {
|
|
|
|
- if (sd->status.skill[idx].lv >= level)
|
|
|
|
- return true;
|
|
|
|
- if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) //Non-granted skill, store it's level.
|
|
|
|
- sd->status.skill[idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[idx].lv;
|
|
|
|
|
|
+ case 1: //Item bonus skill.
|
|
|
|
+ if( sd->status.skill[id].id == id ) {
|
|
|
|
+ if( sd->status.skill[id].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;
|
|
} else {
|
|
} else {
|
|
- sd->status.skill[idx].id = skill_id;
|
|
|
|
- sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY;
|
|
|
|
|
|
+ sd->status.skill[id].id = id;
|
|
|
|
+ sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY;
|
|
}
|
|
}
|
|
- sd->status.skill[idx].lv = level;
|
|
|
|
|
|
+ sd->status.skill[id].lv = level;
|
|
break;
|
|
break;
|
|
-
|
|
|
|
- case ADDSKILL_TEMP_ADDLEVEL: //Add skill bonus on top of what you had.
|
|
|
|
- if (sd->status.skill[idx].id != 0) {
|
|
|
|
- if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT)
|
|
|
|
- sd->status.skill[idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[idx].lv; // Store previous level.
|
|
|
|
|
|
+ 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.
|
|
} else {
|
|
} else {
|
|
- sd->status.skill[idx].id = skill_id;
|
|
|
|
- sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill.
|
|
|
|
|
|
+ sd->status.skill[id].id = id;
|
|
|
|
+ sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill.
|
|
}
|
|
}
|
|
- sd->status.skill[idx].lv += level;
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case ADDSKILL_PERMANENT_GRANTED: //Permanent granted skills ignore the skill tree
|
|
|
|
- sd->status.skill[idx].id = skill_id;
|
|
|
|
- sd->status.skill[idx].lv = level;
|
|
|
|
- sd->status.skill[idx].flag = SKILL_FLAG_PERM_GRANTED;
|
|
|
|
- if (level == 0) { //Remove skill.
|
|
|
|
- sd->status.skill[idx].id = 0;
|
|
|
|
- clif_deleteskill(sd,skill_id);
|
|
|
|
|
|
+ sd->status.skill[id].lv += level;
|
|
|
|
+ break;
|
|
|
|
+ case 4: //Permanent granted skills ignore the skill tree
|
|
|
|
+ sd->status.skill[id].id = id;
|
|
|
|
+ sd->status.skill[id].lv = level;
|
|
|
|
+ sd->status.skill[id].flag = SKILL_FLAG_PERM_GRANTED;
|
|
|
|
+ if( level == 0 ) { //Remove skill.
|
|
|
|
+ sd->status.skill[id].id = 0;
|
|
|
|
+ clif_deleteskill(sd,id);
|
|
} else
|
|
} else
|
|
- clif_addskill(sd,skill_id);
|
|
|
|
- if (!skill_get_inf(skill_id)) //Only recalculate for passive skills.
|
|
|
|
|
|
+ clif_addskill(sd,id);
|
|
|
|
+ if( !skill_get_inf(id) ) //Only recalculate for passive skills.
|
|
status_calc_pc(sd, SCO_NONE);
|
|
status_calc_pc(sd, SCO_NONE);
|
|
break;
|
|
break;
|
|
-
|
|
|
|
- default:
|
|
|
|
- return false;
|
|
|
|
|
|
+ default: //Unknown flag?
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
- return true;
|
|
|
|
|
|
+ return 1;
|
|
}
|
|
}
|
|
/*==========================================
|
|
/*==========================================
|
|
* Append a card to an item ?
|
|
* Append a card to an item ?
|
|
@@ -5485,8 +5429,8 @@ int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 sk
|
|
int cooldown = 0, cooldownlen = ARRAYLENGTH(sd->skillcooldown);
|
|
int cooldown = 0, cooldownlen = ARRAYLENGTH(sd->skillcooldown);
|
|
|
|
|
|
if (!idx) return 0;
|
|
if (!idx) return 0;
|
|
- if (skill_db[idx]->cooldown[skill_lv - 1])
|
|
|
|
- cooldown = skill_db[idx]->cooldown[skill_lv - 1];
|
|
|
|
|
|
+ if (skill_db[idx].cooldown[skill_lv - 1])
|
|
|
|
+ cooldown = skill_db[idx].cooldown[skill_lv - 1];
|
|
|
|
|
|
ARR_FIND(0, cooldownlen, i, sd->skillcooldown[i].id == skill_id);
|
|
ARR_FIND(0, cooldownlen, i, sd->skillcooldown[i].id == skill_id);
|
|
if (i < cooldownlen) {
|
|
if (i < cooldownlen) {
|
|
@@ -5499,23 +5443,24 @@ int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 sk
|
|
/*==========================================
|
|
/*==========================================
|
|
* Return player sd skill_lv learned for given skill
|
|
* Return player sd skill_lv learned for given skill
|
|
*------------------------------------------*/
|
|
*------------------------------------------*/
|
|
-uint8 pc_checkskill(struct map_session_data *sd, uint16 skill_id)
|
|
|
|
|
|
+uint8 pc_checkskill(struct map_session_data *sd,uint16 skill_id)
|
|
{
|
|
{
|
|
- uint16 i = 0, idx = 0;
|
|
|
|
- if (sd == NULL)
|
|
|
|
- return 0;
|
|
|
|
- if ((idx = skill_get_index(skill_id)) == 0) {
|
|
|
|
- ShowError("pc_checkskill: Invalid skill id %d (char_id=%d).\n", skill_id, sd->status.char_id);
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- if (SKILL_CHK_GUILD(skill_id) ) {
|
|
|
|
|
|
+ if(sd == NULL) return 0;
|
|
|
|
+ if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) {
|
|
struct guild *g;
|
|
struct guild *g;
|
|
|
|
|
|
if( sd->status.guild_id>0 && (g=sd->guild)!=NULL)
|
|
if( sd->status.guild_id>0 && (g=sd->guild)!=NULL)
|
|
return guild_checkskill(g,skill_id);
|
|
return guild_checkskill(g,skill_id);
|
|
return 0;
|
|
return 0;
|
|
|
|
+ } else if(skill_id >= ARRAYLENGTH(sd->status.skill) ) {
|
|
|
|
+ ShowError("pc_checkskill: Invalid skill id %d (char_id=%d).\n", skill_id, sd->status.char_id);
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
- return sd->status.skill[idx].lv;
|
|
|
|
|
|
+
|
|
|
|
+ if(sd->status.skill[skill_id].id == skill_id)
|
|
|
|
+ return (sd->status.skill[skill_id].lv);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -6687,57 +6632,52 @@ int pc_statusup2(struct map_session_data* sd, int type, int val)
|
|
* Update skill_lv for player sd
|
|
* Update skill_lv for player sd
|
|
* Skill point allocation
|
|
* Skill point allocation
|
|
*------------------------------------------*/
|
|
*------------------------------------------*/
|
|
-void pc_skillup(struct map_session_data *sd,uint16 skill_id)
|
|
|
|
|
|
+int pc_skillup(struct map_session_data *sd,uint16 skill_id)
|
|
{
|
|
{
|
|
- uint16 idx = skill_get_index(skill_id);
|
|
|
|
-
|
|
|
|
- nullpo_retv(sd);
|
|
|
|
-
|
|
|
|
- if (!idx) {
|
|
|
|
- if (skill_id)
|
|
|
|
- ShowError("pc_skillup: Player attempts to level up invalid skill '%d'\n", skill_id);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ nullpo_ret(sd);
|
|
|
|
|
|
- // Level up guild skill
|
|
|
|
- if (SKILL_CHK_GUILD(skill_id)) {
|
|
|
|
|
|
+ if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL )
|
|
|
|
+ {
|
|
guild_skillup(sd, skill_id);
|
|
guild_skillup(sd, skill_id);
|
|
- return;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
- // Level up homunculus skill
|
|
|
|
- else if (sd->hd && SKILL_CHK_HOMUN(skill_id)) {
|
|
|
|
|
|
+
|
|
|
|
+ if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd )
|
|
|
|
+ {
|
|
hom_skillup(sd->hd, skill_id);
|
|
hom_skillup(sd->hd, skill_id);
|
|
- return;
|
|
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
- else {
|
|
|
|
- if( sd->status.skill_point > 0 &&
|
|
|
|
- sd->status.skill[idx].id &&
|
|
|
|
- sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
|
|
|
|
- sd->status.skill[idx].lv < skill_tree_get_max(skill_id, sd->status.class_) )
|
|
|
|
- {
|
|
|
|
- int lv, range, upgradable;
|
|
|
|
- sd->status.skill[idx].lv++;
|
|
|
|
- sd->status.skill_point--;
|
|
|
|
- if( !skill_get_inf(skill_id) )
|
|
|
|
- status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills.
|
|
|
|
- else if( sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) )
|
|
|
|
- pc_calc_skilltree(sd); // Required to grant all TK Ranker skills.
|
|
|
|
- else
|
|
|
|
- pc_check_skilltree(sd); // Check if a new skill can Lvlup
|
|
|
|
-
|
|
|
|
- lv = sd->status.skill[idx].lv;
|
|
|
|
- range = skill_get_range2(&sd->bl, skill_id, lv);
|
|
|
|
- upgradable = (lv < skill_tree_get_max(sd->status.skill[idx].id, sd->status.class_)) ? 1 : 0;
|
|
|
|
- clif_skillup(sd,skill_id,lv,range,upgradable);
|
|
|
|
- clif_updatestatus(sd,SP_SKILLPOINT);
|
|
|
|
- if( skill_id == GN_REMODELING_CART ) /* cart weight info was updated by status_calc_pc */
|
|
|
|
- clif_updatestatus(sd,SP_CARTINFO);
|
|
|
|
- if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown
|
|
|
|
- clif_skillinfoblock(sd);
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ if(skill_id >= MAX_SKILL )
|
|
|
|
+ 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_) )
|
|
|
|
+ {
|
|
|
|
+ int lv,range, upgradable;
|
|
|
|
+ sd->status.skill[skill_id].lv++;
|
|
|
|
+ sd->status.skill_point--;
|
|
|
|
+ if( !skill_get_inf(skill_id) )
|
|
|
|
+ status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills.
|
|
|
|
+ else if( sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) )
|
|
|
|
+ pc_calc_skilltree(sd); // Required to grant all TK Ranker skills.
|
|
else
|
|
else
|
|
- ShowDebug("Skill Level up failed. ID:%d idx:%d (CID=%d. AID=%d)\n", skill_id, idx, sd->status.char_id, sd->status.account_id);
|
|
|
|
|
|
+ pc_check_skilltree(sd, skill_id); // Check if a new skill can Lvlup
|
|
|
|
+
|
|
|
|
+ lv = sd->status.skill[skill_id].lv;
|
|
|
|
+ range = skill_get_range2(&sd->bl, skill_id, lv);
|
|
|
|
+ upgradable = (lv < skill_tree_get_max(sd->status.skill[skill_id].id, sd->status.class_)) ? 1 : 0;
|
|
|
|
+ clif_skillup(sd,skill_id,lv,range,upgradable);
|
|
|
|
+ clif_updatestatus(sd,SP_SKILLPOINT);
|
|
|
|
+ if( skill_id == GN_REMODELING_CART ) /* cart weight info was updated by status_calc_pc */
|
|
|
|
+ clif_updatestatus(sd,SP_CARTINFO);
|
|
|
|
+ if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown
|
|
|
|
+ clif_skillinfoblock(sd);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*==========================================
|
|
/*==========================================
|
|
@@ -6749,7 +6689,7 @@ int pc_allskillup(struct map_session_data *sd)
|
|
|
|
|
|
nullpo_ret(sd);
|
|
nullpo_ret(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) {
|
|
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) {
|
|
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].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;
|
|
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
@@ -6758,23 +6698,34 @@ int pc_allskillup(struct map_session_data *sd)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (!pc_grant_allskills(sd, true)) {
|
|
|
|
- uint16 sk_id;
|
|
|
|
- for (i = 0; i < MAX_SKILL_TREE && (sk_id = skill_tree[pc_class2idx(sd->status.class_)][i].id) > 0;i++){
|
|
|
|
- int inf2 = 0;
|
|
|
|
- uint16 sk_idx = 0;
|
|
|
|
- if (!sk_id || !(sk_idx = skill_get_index(sk_id)))
|
|
|
|
- continue;
|
|
|
|
- inf2 = skill_get_inf2(sk_id);
|
|
|
|
|
|
+ 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 ) {
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ int id;
|
|
|
|
+ for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id)>0;i++){
|
|
|
|
+ int inf2 = skill_get_inf2(id);
|
|
if (
|
|
if (
|
|
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
|
|
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
|
|
(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) ||
|
|
(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) ||
|
|
- sk_id == SG_DEVIL
|
|
|
|
|
|
+ id==SG_DEVIL
|
|
)
|
|
)
|
|
continue; //Cannot be learned normally.
|
|
continue; //Cannot be learned normally.
|
|
|
|
|
|
- sd->status.skill[sk_idx].id = sk_id;
|
|
|
|
- sd->status.skill[sk_idx].lv = skill_tree_get_max(sk_id, sd->status.class_); // celest
|
|
|
|
|
|
+ sd->status.skill[id].id = id;
|
|
|
|
+ sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); // celest
|
|
}
|
|
}
|
|
}
|
|
}
|
|
status_calc_pc(sd,SCO_NONE);
|
|
status_calc_pc(sd,SCO_NONE);
|
|
@@ -6814,8 +6765,8 @@ int pc_resetlvl(struct map_session_data* sd,int type)
|
|
if(sd->status.class_ == JOB_NOVICE_HIGH) {
|
|
if(sd->status.class_ == JOB_NOVICE_HIGH) {
|
|
sd->status.status_point=100; // not 88 [celest]
|
|
sd->status.status_point=100; // not 88 [celest]
|
|
// give platinum skills upon changing
|
|
// give platinum skills upon changing
|
|
- pc_skill(sd,NV_FIRSTAID,1,ADDSKILL_PERMANENT);
|
|
|
|
- pc_skill(sd,NV_TRICKDEAD,1,ADDSKILL_PERMANENT);
|
|
|
|
|
|
+ pc_skill(sd,142,1,0);
|
|
|
|
+ pc_skill(sd,143,1,0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -6989,11 +6940,9 @@ int pc_resetskill(struct map_session_data* sd, int flag)
|
|
|
|
|
|
for( i = 1; i < MAX_SKILL; i++ )
|
|
for( i = 1; i < MAX_SKILL; i++ )
|
|
{
|
|
{
|
|
- uint8 lv = sd->status.skill[i].lv;
|
|
|
|
|
|
+ int lv = sd->status.skill[i].lv;
|
|
int inf2;
|
|
int inf2;
|
|
- uint16 skill_id = skill_idx2id(i);
|
|
|
|
- if (lv == 0 || skill_id == 0)
|
|
|
|
- continue;
|
|
|
|
|
|
+ if (lv < 1) continue;
|
|
|
|
|
|
inf2 = skill_get_inf2(i);
|
|
inf2 = skill_get_inf2(i);
|
|
|
|
|
|
@@ -7001,7 +6950,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
// Don't reset trick dead if not a novice/baby
|
|
// Don't reset trick dead if not a novice/baby
|
|
- if( skill_id == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
|
|
|
|
|
|
+ if( i == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
|
|
{
|
|
{
|
|
sd->status.skill[i].lv = 0;
|
|
sd->status.skill[i].lv = 0;
|
|
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
|
|
@@ -7009,13 +6958,13 @@ int pc_resetskill(struct map_session_data* sd, int flag)
|
|
}
|
|
}
|
|
|
|
|
|
// do not reset basic skill
|
|
// do not reset basic skill
|
|
- if( skill_id == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
|
|
|
|
|
|
+ if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
|
|
continue;
|
|
continue;
|
|
|
|
|
|
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED )
|
|
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED )
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- if( flag&4 && !skill_ischangesex(skill_id) )
|
|
|
|
|
|
+ if( flag&4 && !skill_ischangesex(i) )
|
|
continue;
|
|
continue;
|
|
|
|
|
|
if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn )
|
|
if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn )
|
|
@@ -8064,26 +8013,26 @@ bool pc_jobchange(struct map_session_data *sd,int job, char upper)
|
|
pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd);
|
|
pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd);
|
|
}
|
|
}
|
|
|
|
|
|
- if(sd->cloneskill_idx > 0) {
|
|
|
|
|
|
+ if(sd->cloneskill_idx >= 0) {
|
|
if( sd->status.skill[sd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
|
|
if( sd->status.skill[sd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
|
|
sd->status.skill[sd->cloneskill_idx].id = 0;
|
|
sd->status.skill[sd->cloneskill_idx].id = 0;
|
|
sd->status.skill[sd->cloneskill_idx].lv = 0;
|
|
sd->status.skill[sd->cloneskill_idx].lv = 0;
|
|
sd->status.skill[sd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT;
|
|
sd->status.skill[sd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT;
|
|
clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM));
|
|
clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_PLAGIARISM));
|
|
}
|
|
}
|
|
- sd->cloneskill_idx = 0;
|
|
|
|
|
|
+ sd->cloneskill_idx = -1;
|
|
pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM, 0);
|
|
pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM, 0);
|
|
pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM_LV, 0);
|
|
pc_setglobalreg(sd,SKILL_VAR_PLAGIARISM_LV, 0);
|
|
}
|
|
}
|
|
|
|
|
|
- if(sd->reproduceskill_idx > 0) {
|
|
|
|
|
|
+ if(sd->reproduceskill_idx >= 0) {
|
|
if( sd->status.skill[sd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
|
|
if( sd->status.skill[sd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
|
|
sd->status.skill[sd->reproduceskill_idx].id = 0;
|
|
sd->status.skill[sd->reproduceskill_idx].id = 0;
|
|
sd->status.skill[sd->reproduceskill_idx].lv = 0;
|
|
sd->status.skill[sd->reproduceskill_idx].lv = 0;
|
|
sd->status.skill[sd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT;
|
|
sd->status.skill[sd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT;
|
|
clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_REPRODUCE));
|
|
clif_deleteskill(sd,pc_readglobalreg(sd,SKILL_VAR_REPRODUCE));
|
|
}
|
|
}
|
|
- sd->reproduceskill_idx = 0;
|
|
|
|
|
|
+ sd->reproduceskill_idx = -1;
|
|
pc_setglobalreg(sd,SKILL_VAR_REPRODUCE,0);
|
|
pc_setglobalreg(sd,SKILL_VAR_REPRODUCE,0);
|
|
pc_setglobalreg(sd,SKILL_VAR_REPRODUCE_LV,0);
|
|
pc_setglobalreg(sd,SKILL_VAR_REPRODUCE_LV,0);
|
|
}
|
|
}
|
|
@@ -11334,32 +11283,6 @@ uint64 pc_generate_unique_id(struct map_session_data *sd) {
|
|
return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++;
|
|
return ((uint64)sd->status.char_id << 32) | sd->status.uniqueitem_counter++;
|
|
}
|
|
}
|
|
|
|
|
|
-/**
|
|
|
|
- * Validating skill from player after logged on
|
|
|
|
- * @param sd
|
|
|
|
- **/
|
|
|
|
-void pc_validate_skill(struct map_session_data *sd) {
|
|
|
|
- if (sd) {
|
|
|
|
- uint16 i = 0, count = 0;
|
|
|
|
- struct s_skill tmp_skills[MAX_SKILL] = {{ 0 }};
|
|
|
|
-
|
|
|
|
- memcpy(tmp_skills, sd->status.skill, sizeof(sd->status.skill));
|
|
|
|
- memset(sd->status.skill, 0, sizeof(sd->status.skill));
|
|
|
|
-
|
|
|
|
- for (i = 0; i < MAX_SKILL; i++) {
|
|
|
|
- uint16 idx = 0;
|
|
|
|
- if (tmp_skills[i].id == 0 || tmp_skills[i].lv == 0)
|
|
|
|
- continue;
|
|
|
|
- if ((idx = skill_get_index(tmp_skills[i].id))) {
|
|
|
|
- memcpy(&sd->status.skill[idx], &tmp_skills[i], sizeof(tmp_skills[i]));
|
|
|
|
- count++;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- ShowWarning("pc_validate_skill: Removing invalid skill '%d' from player (AID=%d CID=%d).\n", tmp_skills[i].id, sd->status.account_id, sd->status.char_id);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/*==========================================
|
|
/*==========================================
|
|
* pc Init/Terminate
|
|
* pc Init/Terminate
|
|
*------------------------------------------*/
|
|
*------------------------------------------*/
|