diff --git a/db/re/item_db.txt b/db/re/item_db.txt index 7c7daba3c4..b17d3d4d27 100644 --- a/db/re/item_db.txt +++ b/db/re/item_db.txt @@ -11037,7 +11037,7 @@ 23191,Varetyr_Spear_Scroll_1_5,Level 5 Varetyr Spear,11,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "SO_VARETYR_SPEAR",5; },{},{} 23192,Diamond_Dust_Scroll_1_5,Level 5 Diamond Dust,11,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "SO_DIAMONDDUST",5; },{},{} 23193,Crimson_Rock_Scroll_1_5,Level 5 Crimson Rock,11,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_CRIMSONROCK",5; },{},{} -23194,Sienna_Execrate_Scroll_1_5,Level 5 Sienna Execrate,11,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_SIENNAEXECRATE",5; },{},{} +23194,Sienna_Execrate_Scroll_1_5,Level 5 Sienna Execrate,11,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_SIENNAEXECRATE",5,true; },{},{} //=================================================================== // Shadow Equipments //=================================================================== diff --git a/doc/script_commands.txt b/doc/script_commands.txt index d1074b5e7e..5a5732a87d 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -4754,18 +4754,24 @@ The default setting, 'item_enabled_npc', is defined in 'conf/battle/items.conf'. --------------------------------------- -*itemskill <skill id>,<skill level>; -*itemskill "<skill name>",<skill level>; +*itemskill <skill id>,<skill level>{,<keep requirement>}; +*itemskill "<skill name>",<skill level>{,<keep requirement>}; This command is meant for item scripts to replicate single-use skills in usable items. It will not work properly if there is a visible dialog window or menu. If the skill is self or auto-targeting, it will be used immediately; otherwise a target cursor is shown. +If <keep requirement> parameter is set to true, the skill's requirements will be checked. +By default, the requirements for item skills are not checked, and therefore the default value is false. + // When Anodyne is used, it will cast Endure (8), Level 1, as if the actual // skill has been used from skill tree. 605,Anodyne,Anodyne,11,2000,0,100,,,,,10477567,2,,,,,{ itemskill 8,1; },{} +// When Sienna_Execrate_Scroll_1_5 is used, it will cast Sienna Execrate Level 5 and consume 2 Red_Gemstones. +23194,Sienna_Execrate_Scroll_1_5,Level 5 Sienna Execrate,11,10,,10,,,,,0xFFFFFFFF,63,2,,,,,,{ itemskill "WL_SIENNAEXECRATE",5,true; },{},{} + --------------------------------------- *consumeitem <item id>{,<char_id>}; diff --git a/src/map/pc.h b/src/map/pc.h index 418bd633a3..a415fc69bc 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -307,6 +307,7 @@ struct map_session_data { time_t emotionlasttime; // to limit flood with emotion packets short skillitem,skillitemlv; + bool skillitem_keep_requirement; uint16 skill_id_old,skill_lv_old; uint16 skill_id_dance,skill_lv_dance; short cook_mastery; // range: [0,1999] [Inkfish] diff --git a/src/map/script.c b/src/map/script.c index 40412585f2..8844629e4a 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9563,6 +9563,7 @@ BUILDIN_FUNC(itemskill) { int id; int lv; + bool keep_requirement; TBL_PC* sd; struct script_data *data; @@ -9574,9 +9575,15 @@ BUILDIN_FUNC(itemskill) get_val(st, data); // Convert into value in case of a variable id = ( data_isstring(data) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); lv = script_getnum(st,3); + if (script_hasdata(st, 4)) { + keep_requirement = (script_getnum(st, 4) != 0); + } else { + keep_requirement = false; + } sd->skillitem=id; sd->skillitemlv=lv; + sd->skillitem_keep_requirement = keep_requirement; clif_item_skill(sd,id,lv); return SCRIPT_CMD_SUCCESS; } @@ -21916,7 +21923,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(gettimestr,"si"), BUILDIN_DEF(openstorage,""), BUILDIN_DEF(guildopenstorage,""), - BUILDIN_DEF(itemskill,"vi"), + BUILDIN_DEF(itemskill,"vi?"), BUILDIN_DEF(produce,"i"), BUILDIN_DEF(cooking,"i"), BUILDIN_DEF(monster,"siisii???"), diff --git a/src/map/skill.c b/src/map/skill.c index 8756da41e1..726d35568c 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -645,7 +645,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd) * It has been confirmed on a official server (thanks to Yommy) that item-cast skills bypass all the restrictions above * Also, without this check, an exploit where an item casting + healing (or any other kind buff) isn't deleted after used on a restricted map */ - if( sd->skillitem == skill_id ) + if( sd->skillitem == skill_id && !sd->skillitem_keep_requirement ) return false; // Check skill restrictions [Celest] if( (!map_flag_vs(m) && skill_get_nocast (skill_id) & 1) || @@ -6109,6 +6109,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui sd->state.abra_flag = 1; sd->skillitem = abra_skill_id; sd->skillitemlv = abra_skill_lv; + sd->skillitem_keep_requirement = false; clif_item_skill(sd, abra_skill_id, abra_skill_lv); } else @@ -9993,6 +9994,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui sd->state.abra_flag = 2; sd->skillitem = improv_skill_id; sd->skillitemlv = improv_skill_lv; + sd->skillitem_keep_requirement = false; clif_item_skill(sd, improv_skill_id, improv_skill_lv); } else { struct unit_data *ud = unit_bl2ud(src); @@ -11210,8 +11212,8 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) skill_blockpc_start(sd,BD_ADAPTATION,3000); } - if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish] - sd->skillitem = sd->skillitemlv = 0; + if (sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL) // they just set the data so leave it as it is.[Inkfish] + sd->skillitem = sd->skillitemlv = sd->skillitem_keep_requirement = 0; if (ud->skilltimer == INVALID_TIMER) { if(md) md->skill_idx = -1; @@ -11269,7 +11271,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) //sent in ALL cases, even cases where skill_check_condition fails //which would lead to double 'skill failed' messages u.u [Skotlex] if(sd) - sd->skillitem = sd->skillitemlv = 0; + sd->skillitem = sd->skillitemlv = sd->skillitem_keep_requirement = 0; else if(md) md->skill_idx = -1; return 0; @@ -11406,7 +11408,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) status_change_end(src, SC_CAMOUFLAGE, INVALID_TIMER); // Applies to the first skill if active if( sd && sd->skillitem != AL_WARP ) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish] - sd->skillitem = sd->skillitemlv = 0; + sd->skillitem = sd->skillitemlv = sd->skillitem_keep_requirement = 0; if (ud->skilltimer == INVALID_TIMER) { if (md) md->skill_idx = -1; @@ -11422,7 +11424,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) ud->canact_tick = tick; ud->skill_id = ud->skill_lv = 0; if(sd) - sd->skillitem = sd->skillitemlv = 0; + sd->skillitem = sd->skillitemlv = sd->skillitem_keep_requirement = 0; else if(md) md->skill_idx = -1; return 0; @@ -12358,7 +12360,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char } skill_consume_requirement(sd,sd->menuskill_id,lv,2); - sd->skillitem = sd->skillitemlv = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish] + sd->skillitem = sd->skillitemlv = sd->skillitem_keep_requirement = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish] if((group=skill_unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==NULL) { skill_failed(sd); @@ -14739,7 +14741,8 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i else if( sd->status.inventory[i].expire_time == 0 ) pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); // Rental usable items are not consumed until expiration } - return true; + if(!sd->skillitem_keep_requirement) + return true; } if( pc_is90overweight(sd) ) { @@ -15587,7 +15590,7 @@ bool skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, break; } - if( sd->skillitem == skill_id ) // Casting finished (Item skill or Hocus-Pocus) + if( sd->skillitem == skill_id && !sd->skillitem_keep_requirement ) // Casting finished (Item skill or Hocus-Pocus) return true; if( pc_is90overweight(sd) ) { @@ -15850,7 +15853,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 if( !sd ) return req; - if( sd->skillitem == skill_id ) + if( sd->skillitem == skill_id && !sd->skillitem_keep_requirement ) return req; // Item skills and Hocus-Pocus don't have requirements.[Inkfish] sc = &sd->sc;