Add skill_plagiarism script commands (#6304)

* Allow players to copy skills with script command skill_plagiarism.
* Plagiarized skills can be cleared with script command skill_plagiarism_reset.
This commit is contained in:
HAO YAN
2022-10-20 23:16:46 +08:00
committed by GitHub
parent 7d19b4bbdd
commit c3a171da81
6 changed files with 134 additions and 19 deletions

View File

@@ -6278,6 +6278,24 @@ it just removes non-permanent script.
---------------------------------------
*plagiarizeskill <skill_id>,<level>;
Enable the player to plagiarize specific skills that are copyable.
Return 1 on success, 0 otherwise.
---------------------------------------
*plagiarizeskillreset <flag>;
Remove a plagiarized skill from the player.
Return 1 on success, 0 otherwise.
Flag constants:
1 - Use for Plagiarism Skill
2 - Use for Reproduce Skill
---------------------------------------
*skill <skill id>,<level>{,<flag>};
*skill "<skill name>",<level>{,<flag>};
*addtoskill <skill id>,<level>{,<flag>};

View File

@@ -51,6 +51,7 @@
#include "pc_groups.hpp"
#include "pet.hpp" // pet_unlocktarget()
#include "quest.hpp"
#include "skill.hpp" // skill_isCopyable()
#include "script.hpp" // struct script_reg, struct script_regstr
#include "searchstore.hpp" // struct s_search_store_info
#include "status.hpp" // OPTION_*, struct weapon_atk
@@ -5087,6 +5088,93 @@ bool pc_skill(struct map_session_data* sd, uint16 skill_id, int level, enum e_ad
}
return true;
}
/**
* Set's a player's plagiarized skill.
* @param sd: Player
* @param skill_id: Skill to be plagiarized
* @param skill_lv: Skill level to be plagiarized
* @return True on success or false otherwise
*/
bool pc_skill_plagiarism(map_session_data &sd, uint16 skill_id, uint16 skill_lv)
{
skill_id = skill_dummy2skill_id(skill_id);
uint16 idx = skill_get_index(skill_id);
// Use skill index, avoiding out-of-bound array [Cydh]
if (idx == 0) {
ShowWarning("pc_skill_plagiarism: invalid skill idx 0 for skill %d.\n", skill_id);
return false;
}
skill_lv = cap_value(skill_lv, 1, skill_get_max(skill_id));
int type = skill_isCopyable(&sd, skill_id);
if (type == 1) {
pc_skill_plagiarism_reset(sd, type);
sd.cloneskill_idx = idx;
pc_setglobalreg(&sd, add_str(SKILL_VAR_PLAGIARISM), skill_id);
pc_setglobalreg(&sd, add_str(SKILL_VAR_PLAGIARISM_LV), skill_lv);
} else if (type == 2) {
pc_skill_plagiarism_reset(sd, type);
sd.reproduceskill_idx = idx;
pc_setglobalreg(&sd, add_str(SKILL_VAR_REPRODUCE), skill_id);
pc_setglobalreg(&sd, add_str(SKILL_VAR_REPRODUCE_LV), skill_lv);
} else {
ShowWarning("pc_skill_plagiarism: skill %d is not copyable.\n", skill_id);
return false;
}
sd.status.skill[idx].id = skill_id;
sd.status.skill[idx].lv = skill_lv;
sd.status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
clif_addskill(&sd, skill_id);
return true;
}
/**
* Clear plagiarized skills from a player.
* @param sd: Player
* @param type: 1 for Plagiarism or 2 for Reproduce
* @return True on success or false otherwise
*/
bool pc_skill_plagiarism_reset(map_session_data &sd, uint8 type)
{
uint16 idx;
if (type == 1)
idx = sd.cloneskill_idx;
else if (type == 2)
idx = sd.reproduceskill_idx;
else {
ShowError("pc_skill_plagiarism_reset: Unknown type %d.\n", type);
return false;
}
if (sd.status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED) {
uint16 skill_id = sd.status.skill[idx].id;
sd.status.skill[idx].id = 0;
sd.status.skill[idx].lv = 0;
sd.status.skill[idx].flag = SKILL_FLAG_PERMANENT;
clif_deleteskill(&sd, skill_id);
if (type == 1) {
sd.cloneskill_idx = 0;
pc_setglobalreg(&sd, add_str(SKILL_VAR_PLAGIARISM), 0);
pc_setglobalreg(&sd, add_str(SKILL_VAR_PLAGIARISM_LV), 0);
}
else if (type == 2) {
sd.reproduceskill_idx = 0;
pc_setglobalreg(&sd, add_str(SKILL_VAR_REPRODUCE), 0);
pc_setglobalreg(&sd, add_str(SKILL_VAR_REPRODUCE_LV), 0);
}
}
return true;
}
/*==========================================
* Append a card to an item ?
*------------------------------------------*/
@@ -10302,27 +10390,11 @@ bool pc_jobchange(struct map_session_data *sd,int job, char upper)
}
if(sd->cloneskill_idx > 0) {
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].lv = 0;
sd->status.skill[sd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT;
clif_deleteskill(sd, static_cast<int>(pc_readglobalreg(sd, add_str(SKILL_VAR_PLAGIARISM))));
}
sd->cloneskill_idx = 0;
pc_setglobalreg(sd, add_str(SKILL_VAR_PLAGIARISM), 0);
pc_setglobalreg(sd, add_str(SKILL_VAR_PLAGIARISM_LV), 0);
pc_skill_plagiarism_reset(*sd, 1);
}
if(sd->reproduceskill_idx > 0) {
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].lv = 0;
sd->status.skill[sd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT;
clif_deleteskill(sd, static_cast<int>(pc_readglobalreg(sd, add_str(SKILL_VAR_REPRODUCE))));
}
sd->reproduceskill_idx = 0;
pc_setglobalreg(sd, add_str(SKILL_VAR_REPRODUCE), 0);
pc_setglobalreg(sd, add_str(SKILL_VAR_REPRODUCE_LV), 0);
pc_skill_plagiarism_reset(*sd, 2);
}
if ( (b_class&MAPID_UPPERMASK) != (sd->class_&MAPID_UPPERMASK) ) { //Things to remove when changing class tree.

View File

@@ -1431,6 +1431,8 @@ enum e_addskill_type {
};
bool pc_skill(struct map_session_data *sd, uint16 skill_id, int level, enum e_addskill_type type);
bool pc_skill_plagiarism(map_session_data &sd, uint16 skill_id, uint16 skill_lv);
bool pc_skill_plagiarism_reset(map_session_data &sd, uint8 type);
int pc_insert_card(struct map_session_data *sd,int idx_card,int idx_equip);

View File

@@ -10177,6 +10177,26 @@ BUILDIN_FUNC(petautobonus3) {
return SCRIPT_CMD_SUCCESS;
}
BUILDIN_FUNC(skill_plagiarism)
{
TBL_PC *sd;
if (script_rid2sd(sd))
script_pushint(st, pc_skill_plagiarism(*sd, script_getnum(st, 2), script_getnum(st, 3)));
return SCRIPT_CMD_SUCCESS;
}
BUILDIN_FUNC(skill_plagiarism_reset)
{
TBL_PC *sd;
if (!script_rid2sd(sd))
script_pushint(st, pc_skill_plagiarism_reset(*sd, script_getnum(st, 2)));
return SCRIPT_CMD_SUCCESS;
}
/// Changes the level of a player skill.
/// <flag> defaults to 1
/// <flag>=0 : set the level of the skill
@@ -26808,6 +26828,8 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(petautobonus,"sii??"),
BUILDIN_DEF2(petautobonus,"petautobonus2","sii??"),
BUILDIN_DEF(petautobonus3,"siiv?"),
BUILDIN_DEF(skill_plagiarism, "ii"),
BUILDIN_DEF(skill_plagiarism_reset, "i"),
BUILDIN_DEF(skill,"vi?"),
BUILDIN_DEF2(skill,"addtoskill","vi?"), // [Valaris]
BUILDIN_DEF(guildskill,"vi"),

View File

@@ -799,7 +799,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
* @return 0 - Cannot be copied; 1 - Can be copied by Plagiarism 2 - Can be copied by Reproduce
* @author Aru - for previous check; Jobbie for class restriction idea; Cydh expands the copyable skill
*/
static int8 skill_isCopyable(struct map_session_data *sd, uint16 skill_id) {
int8 skill_isCopyable(struct map_session_data *sd, uint16 skill_id) {
uint16 skill_idx = skill_get_index(skill_id);
if (!skill_idx)

View File

@@ -611,6 +611,7 @@ int skill_autospell(struct map_session_data *md,uint16 skill_id);
int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal);
bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce);
int8 skill_isCopyable(struct map_session_data *sd, uint16 skill_id);
// Abnormal status
bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd);