Skip to content

Commit

Permalink
Merge pull request #14 from csnv/fix/rogue-plagiarize
Browse files Browse the repository at this point in the history
Fixed Rogue's plagiarize losing skills when copying skills from its own skill tree
  • Loading branch information
csnv authored Apr 14, 2024
2 parents f4eacee + c84f47d commit 5edb9d6
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 21 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
.ycm_extra_conf.py*
Thumbs.db
.vscode
enc_temp_folder

# /
/*.exe
Expand Down
11 changes: 9 additions & 2 deletions src/map/clif.c
Original file line number Diff line number Diff line change
Expand Up @@ -5729,8 +5729,15 @@ static void clif_skillup(struct map_session_data *sd, uint16 skill_id, int skill
WFIFOW(fd, 0) = 0x10e;
WFIFOW(fd, 2) = skill_id;
WFIFOW(fd, 4) = skill_lv;
WFIFOW(fd, 6) = skill->get_sp(skill_id, skill_lv);
WFIFOW(fd, 8) = (flag)?skill->get_range2(&sd->bl, skill_id, skill_lv) : skill->get_range(skill_id, skill_lv);

if (skill_lv > 0) {
WFIFOW(fd, 6) = skill->get_sp(skill_id, skill_lv);
WFIFOW(fd, 8) = (flag)?skill->get_range2(&sd->bl, skill_id, skill_lv) : skill->get_range(skill_id, skill_lv);
} else {
WFIFOW(fd, 6) = 0;
WFIFOW(fd, 8) = 0;
}

if( flag )
WFIFOB(fd,10) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class)) ? 1 : 0;
else
Expand Down
62 changes: 47 additions & 15 deletions src/map/pc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1481,7 +1481,7 @@ static int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_li
*------------------------------------------*/
static int pc_reg_received(struct map_session_data *sd)
{
int i, idx = 0;
int i, idx = 0, knownlv = 0;

nullpo_ret(sd);
sd->vars_ok = true;
Expand Down Expand Up @@ -1520,21 +1520,31 @@ static int pc_reg_received(struct map_session_data *sd)
if ((i = pc->checkskill(sd,RG_PLAGIARISM)) > 0) {
sd->cloneskill_id = pc_readglobalreg(sd,script->add_variable("CLONE_SKILL"));
if (sd->cloneskill_id > 0 && (idx = skill->get_index(sd->cloneskill_id)) > 0) {
knownlv = sd->status.skill[idx].lv;
sd->status.skill[idx].id = sd->cloneskill_id;
sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_variable("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 (knownlv > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT)
sd->status.skill[idx].flag = knownlv + SKILL_FLAG_REPLACED_LV_0;
else
sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
}
}
if ((i = pc->checkskill(sd,SC_REPRODUCE)) > 0) {
sd->reproduceskill_id = pc_readglobalreg(sd,script->add_variable("REPRODUCE_SKILL"));
if( sd->reproduceskill_id > 0 && (idx = skill->get_index(sd->reproduceskill_id)) > 0) {
knownlv = sd->status.skill[idx].lv;
sd->status.skill[idx].id = sd->reproduceskill_id;
sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_variable("REPRODUCE_SKILL_LV"));
if( i < sd->status.skill[idx].lv)
if (sd->status.skill[idx].lv > i)
sd->status.skill[idx].lv = i;
sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;

if (knownlv > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT)
sd->status.skill[idx].flag = knownlv + SKILL_FLAG_REPLACED_LV_0;
else
sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
}
}

Expand Down Expand Up @@ -1644,8 +1654,22 @@ static void pc_calc_skilltree_clear(struct map_session_data *sd)
nullpo_retv(sd);

for (i = 0; i < MAX_SKILL_DB; 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.
// Don't touch these
if (sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED
|| sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED
|| (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0
&& (sd->status.skill[i].id == sd->cloneskill_id || sd->status.skill[i].id == sd->reproduceskill_id))
)
continue;

sd->status.skill[i].id = 0; //First clear skills.

if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) { // Plagiarized skills were already ignored
// 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;
}

/* permanent skills that must be re-checked */
if (sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) {
switch (skill->dbs->db[i].nameid) {
Expand Down Expand Up @@ -1678,14 +1702,6 @@ static int pc_calc_skilltree(struct map_session_data *sd)

pc->calc_skilltree_clear(sd);

for (int i = 0; i < MAX_SKILL_DB; i++) {
if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) {
// 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;
}
}

//Enable Bard/Dancer spirit linked skills.
skill->add_bard_dancer_soullink_songs(sd);

Expand Down Expand Up @@ -1905,7 +1921,7 @@ static int pc_clean_skilltree(struct map_session_data *sd)
sd->status.skill[i].flag = 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;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
}
}

Expand Down Expand Up @@ -7279,6 +7295,21 @@ static int pc_statusup2(struct map_session_data *sd, int type, int val)
return val;
}

/**
* Check skill_id is part of character's own skill tree
*/
static bool pc_isownskill(struct map_session_data *sd, uint16 skill_id)
{
nullpo_ret(sd);

int class_idx = pc->class2idx(sd->status.class);
int i;

ARR_FIND(0, MAX_SKILL_TREE, i, pc->skill_tree[class_idx][i].id == 0 || pc->skill_tree[class_idx][i].id == skill_id);

return i < MAX_SKILL_TREE && pc->skill_tree[class_idx][i].id == skill_id;
}

/*==========================================
* Update skill_lv for player sd
* Skill point allocation
Expand Down Expand Up @@ -12829,6 +12860,7 @@ void pc_defaults(void)
pc->maxparameterincrease = pc_maxparameterincrease;
pc->statusup = pc_statusup;
pc->statusup2 = pc_statusup2;
pc->isownskill = pc_isownskill;
pc->skillup = pc_skillup;
pc->allskillup = pc_allskillup;
pc->resetlvl = pc_resetlvl;
Expand Down
1 change: 1 addition & 0 deletions src/map/pc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,7 @@ END_ZEROED_BLOCK; /* End */
int (*maxparameterincrease) (struct map_session_data* sd, int type);
bool (*statusup) (struct map_session_data *sd, int type, int increase);
int (*statusup2) (struct map_session_data *sd,int type,int val);
bool (*isownskill) (struct map_session_data* sd, uint16 skill_id);
int (*skillup) (struct map_session_data *sd,uint16 skill_id);
int (*allskillup) (struct map_session_data *sd);
int (*resetlvl) (struct map_session_data *sd,int type);
Expand Down
33 changes: 30 additions & 3 deletions src/map/skill.c
Original file line number Diff line number Diff line change
Expand Up @@ -3662,18 +3662,31 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li
break;
}

int cidx, idx, lv = 0;
int cidx, idx, knownlv, lv = 0;
cidx = skill->get_index(copy_skill);
switch(can_copy(tsd, copy_skill)) {
case 1: // Plagiarism
{

knownlv = pc->checkskill(tsd, copy_skill);
if (knownlv >= skill_lv)
break;

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, false);
#if PACKETVER_MAIN_NUM >= 20190807 || PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190918
if (pc->isownskill(tsd, tsd->cloneskill_id))
clif->skillup(tsd, tsd->cloneskill_id, 0, 1);
#endif
} else if (tsd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0) {
tsd->status.skill[idx].lv = tsd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0;
tsd->status.skill[idx].flag = SKILL_FLAG_PERMANENT;
clif->addskill(tsd, tsd->cloneskill_id);
}
}

Expand All @@ -3685,22 +3698,36 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li

tsd->status.skill[cidx].id = copy_skill;
tsd->status.skill[cidx].lv = lv;
tsd->status.skill[cidx].flag = SKILL_FLAG_PLAGIARIZED;
tsd->status.skill[cidx].flag = knownlv > 0 ? knownlv + SKILL_FLAG_REPLACED_LV_0 : SKILL_FLAG_PLAGIARIZED;
clif->addskill(tsd, copy_skill);
}
break;
case 2: // Reproduce
{
knownlv = pc->checkskill(tsd, copy_skill);
lv = sc ? sc->data[SC__REPRODUCE]->val1 : 1;

if (knownlv >= lv)
break;

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, false);
#if PACKETVER_MAIN_NUM >= 20190807 || PACKETVER_RE_NUM >= 20190807 || PACKETVER_ZERO_NUM >= 20190918
if (pc->isownskill(tsd, tsd->reproduceskill_id))
clif->skillup(tsd, tsd->reproduceskill_id, 0, 1);
#endif
} else if (tsd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0) {
tsd->status.skill[idx].lv = tsd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0;
tsd->status.skill[idx].flag = SKILL_FLAG_PERMANENT;
clif->addskill(tsd, tsd->reproduceskill_id);
}
}

lv = min(lv, skill->get_max(copy_skill));

tsd->reproduceskill_id = copy_skill;
Expand All @@ -3709,7 +3736,7 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li

tsd->status.skill[cidx].id = copy_skill;
tsd->status.skill[cidx].lv = lv;
tsd->status.skill[cidx].flag = SKILL_FLAG_PLAGIARIZED;
tsd->status.skill[cidx].flag = knownlv > 0 ? knownlv + SKILL_FLAG_REPLACED_LV_0 : SKILL_FLAG_PLAGIARIZED;
clif->addskill(tsd, copy_skill);
}
break;
Expand Down
6 changes: 5 additions & 1 deletion src/map/status.c
Original file line number Diff line number Diff line change
Expand Up @@ -2395,8 +2395,12 @@ static int status_calc_pc_(struct map_session_data *sd, enum e_status_calc_opt o
// Client doesn't delete unavailable skills even if we refresh
// the skill tree, individually delete them.
for (i = 0; i < MAX_SKILL_DB; i++) {
if (b_skill[i].id != 0 && sd->status.skill[i].id == 0)
if (b_skill[i].id != 0 && sd->status.skill[i].id == 0) {
clif->deleteskill(sd, b_skill[i].id, true);
// Skills that belong to the skill tree need to be "downgraded"
if (pc->isownskill(sd, b_skill[i].id))
clif->skillup(sd, b_skill[i].id, 0, 1);
}
}
#endif
clif->skillinfoblock(sd);
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/HPMHooking/HPMHooking.Defs.inc
Original file line number Diff line number Diff line change
Expand Up @@ -7198,6 +7198,8 @@ typedef bool (*HPMHOOK_pre_pc_statusup) (struct map_session_data **sd, int *type
typedef bool (*HPMHOOK_post_pc_statusup) (bool retVal___, struct map_session_data *sd, int type, int increase);
typedef int (*HPMHOOK_pre_pc_statusup2) (struct map_session_data **sd, int *type, int *val);
typedef int (*HPMHOOK_post_pc_statusup2) (int retVal___, struct map_session_data *sd, int type, int val);
typedef bool (*HPMHOOK_pre_pc_isownskill) (struct map_session_data **sd, uint16 *skill_id);
typedef bool (*HPMHOOK_post_pc_isownskill) (bool retVal___, struct map_session_data *sd, uint16 skill_id);
typedef int (*HPMHOOK_pre_pc_skillup) (struct map_session_data **sd, uint16 *skill_id);
typedef int (*HPMHOOK_post_pc_skillup) (int retVal___, struct map_session_data *sd, uint16 skill_id);
typedef int (*HPMHOOK_pre_pc_allskillup) (struct map_session_data **sd);
Expand Down
4 changes: 4 additions & 0 deletions src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
Original file line number Diff line number Diff line change
Expand Up @@ -5176,6 +5176,8 @@ struct {
struct HPMHookPoint *HP_pc_statusup_post;
struct HPMHookPoint *HP_pc_statusup2_pre;
struct HPMHookPoint *HP_pc_statusup2_post;
struct HPMHookPoint *HP_pc_isownskill_pre;
struct HPMHookPoint *HP_pc_isownskill_post;
struct HPMHookPoint *HP_pc_skillup_pre;
struct HPMHookPoint *HP_pc_skillup_post;
struct HPMHookPoint *HP_pc_allskillup_pre;
Expand Down Expand Up @@ -12733,6 +12735,8 @@ struct {
int HP_pc_statusup_post;
int HP_pc_statusup2_pre;
int HP_pc_statusup2_post;
int HP_pc_isownskill_pre;
int HP_pc_isownskill_post;
int HP_pc_skillup_pre;
int HP_pc_skillup_post;
int HP_pc_allskillup_pre;
Expand Down
1 change: 1 addition & 0 deletions src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2653,6 +2653,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(pc->maxparameterincrease, HP_pc_maxparameterincrease) },
{ HP_POP(pc->statusup, HP_pc_statusup) },
{ HP_POP(pc->statusup2, HP_pc_statusup2) },
{ HP_POP(pc->isownskill, HP_pc_isownskill) },
{ HP_POP(pc->skillup, HP_pc_skillup) },
{ HP_POP(pc->allskillup, HP_pc_allskillup) },
{ HP_POP(pc->resetlvl, HP_pc_resetlvl) },
Expand Down
27 changes: 27 additions & 0 deletions src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
Original file line number Diff line number Diff line change
Expand Up @@ -68816,6 +68816,33 @@ int HP_pc_statusup2(struct map_session_data *sd, int type, int val) {
}
return retVal___;
}
bool HP_pc_isownskill(struct map_session_data *sd, uint16 skill_id) {
int hIndex = 0;
bool retVal___ = false;
if (HPMHooks.count.HP_pc_isownskill_pre > 0) {
bool (*preHookFunc) (struct map_session_data **sd, uint16 *skill_id);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_isownskill_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_pc_isownskill_pre[hIndex].func;
retVal___ = preHookFunc(&sd, &skill_id);
}
if (*HPMforce_return) {
*HPMforce_return = false;
return retVal___;
}
}
{
retVal___ = HPMHooks.source.pc.isownskill(sd, skill_id);
}
if (HPMHooks.count.HP_pc_isownskill_post > 0) {
bool (*postHookFunc) (bool retVal___, struct map_session_data *sd, uint16 skill_id);
for (hIndex = 0; hIndex < HPMHooks.count.HP_pc_isownskill_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_pc_isownskill_post[hIndex].func;
retVal___ = postHookFunc(retVal___, sd, skill_id);
}
}
return retVal___;
}
int HP_pc_skillup(struct map_session_data *sd, uint16 skill_id) {
int hIndex = 0;
int retVal___ = 0;
Expand Down

0 comments on commit 5edb9d6

Please sign in to comment.