summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2020-06-01 04:18:52 +0200
committerGitHub <noreply@github.com>2020-06-01 04:18:52 +0200
commit530af7e587899f66854447e2b8251cbf12c481c3 (patch)
tree74453a3f8e6fdeaa3349132b820e29ec8fee8d7b
parent8a4667a265227587dcc288f75dfe948f5df46034 (diff)
parent9a64eca5235da46655ca64ba5916c6fd4d90208a (diff)
downloadhercules-530af7e587899f66854447e2b8251cbf12c481c3.tar.gz
hercules-530af7e587899f66854447e2b8251cbf12c481c3.tar.bz2
hercules-530af7e587899f66854447e2b8251cbf12c481c3.tar.xz
hercules-530af7e587899f66854447e2b8251cbf12c481c3.zip
Merge pull request #2718 from Kenpachi2k13/prere_use_items_skills_in_npc
Add/extend battle flags to enable item/skill usage while interacting with NPC
-rw-r--r--conf/map/battle/items.conf12
-rw-r--r--conf/map/battle/skill.conf8
-rw-r--r--doc/script_commands.txt41
-rw-r--r--src/map/battle.c3
-rw-r--r--src/map/battle.h2
-rw-r--r--src/map/clif.c22
-rw-r--r--src/map/pc.c3
-rw-r--r--src/map/pc.h8
-rw-r--r--src/map/script.c77
-rw-r--r--src/map/skill.h7
10 files changed, 145 insertions, 38 deletions
diff --git a/conf/map/battle/items.conf b/conf/map/battle/items.conf
index 4788d7b30..ef383e19b 100644
--- a/conf/map/battle/items.conf
+++ b/conf/map/battle/items.conf
@@ -100,10 +100,14 @@ autospell_stacking: false
// Default: true (official)
item_restricted_consumption_type: true
-// Enable all NPC to allow changing of equipments while interacting? (Note 1)
-// Script commands 'enable_items/disable_items' will not be override. (see doc/script_commands.txt)
-// Default: true (official)
-item_enabled_npc: true
+// Which item actions are allowed while interacting with NPC? (Note 3)
+// Script commands 'enable_items/disable_items' will not be overridden. (See doc/script_commands.txt.)
+// 0x0 (ITEMENABLEDNPC_NONE) - Don't allow any item actions.
+// 0x1 (ITEMENABLEDNPC_EQUIP) - Allow changing equipment.
+// 0x2 (ITEMENABLEDNPC_CONSUME) - Allow consuming usable items.
+// Official RE: 0x1 (Default value.)
+// Official Pre-RE: 0x3
+item_enabled_npc: 0x1
// Unequip the equipments that has disabled by map_zone_db.conf ?
// 0 : disabled equipments and cards are nullify (official)
diff --git a/conf/map/battle/skill.conf b/conf/map/battle/skill.conf
index a40b52124..fe9ca638a 100644
--- a/conf/map/battle/skill.conf
+++ b/conf/map/battle/skill.conf
@@ -347,3 +347,11 @@ stormgust_knockback: true
// 0 : (official) Magic Rod's animation occurs every time it is used.
// 1 : Magic Rod's animation would not occur unless a spell was absorbed. (old behavior)
magicrod_type: 0
+
+// Which skills are allowed to use while interacting with NPC?
+// 0 (SKILLENABLEDNPC_NONE) - Don't allow using skills.
+// 1 (SKILLENABLEDNPC_SELF) - Allow using non-damaging self skills.
+// 2 (SKILLENABLEDNPC_ALL) - Allow using all skills.
+// Official RE: 0 (Default value.)
+// Official Pre-RE: 1
+skill_enabled_npc: 0
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index 707aab9d6..a585695bd 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -5685,21 +5685,32 @@ Example:
---------------------------------------
-*enable_items()
-*disable_items()
-
-These commands enable/disable changing of equipments while an NPC is
-running. When disable_items() is run, equipments cannot be changed
-during scripts until enable_items() is called or the script has
-terminated. To avoid possible exploits, when disable_items() is invoked,
-it will only disable changing equips while running that script in
-particular. Note that if a different script also calls disable_items(),
-it will override the last call (so you may want to call this command at
-the start of your script without assuming the effect is still in
-effect).
-If 'item_enabled_npc' option is set to true in 'conf/map/battle/items.conf' all
-NPC are allowing changing of equipment by default except for those have been
-set with 'disable_items'.
+*enable_items({<flag>})
+*enableitemuse({<flag>})
+*disable_items({<flag>})
+*disableitemuse({<flag>})
+
+These commands enable/disable item actions while interacting with a NPC.
+When disable_items() is invoked, item actions defined by <flag> are disabled
+during scripts until enable_items() is called or the script has terminated.
+To avoid possible exploits, when disable_items() is invoked, it will only
+disable item actions while running that script in particular.
+Note that if a different script also invokes disable_items(), it will override
+the last call so you may want to call this command at the start of your
+script without assuming the effect is still in effect.
+If <flag> is omitted all item actions will be disabled.
+The enable_items() command enables item actions defined by <flag> during
+scripts until disable_items() is invoked or the script has terminated.
+If <flag> is omitted it defaults to 'item_enabled_npc' battle flag.
+For a list of supported flags have a look at the description of
+'item_enabled_npc' battle flag in 'conf/map/battle/items.conf'.
+Unless disable_items() or enable_items() is invoked the script will use
+'item_enabled_npc' battle flag by default.
+
+Example:
+
+ // This will disable changing equipment during this script.
+ disable_items(ITEMENABLEDNPC_EQUIP);
---------------------------------------
diff --git a/src/map/battle.c b/src/map/battle.c
index 236ed70b7..611154953 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -7378,7 +7378,7 @@ static const struct battle_data {
{ "item_restricted_consumption_type", &battle_config.item_restricted_consumption_type,1, 0, 1, },
{ "unequip_restricted_equipment", &battle_config.unequip_restricted_equipment, 0, 0, 3, },
{ "max_walk_path", &battle_config.max_walk_path, 17, 1, MAX_WALKPATH, },
- { "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, 1, },
+ { "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, INT_MAX, },
{ "gm_ignore_warpable_area", &battle_config.gm_ignore_warpable_area, 0, 2, 100, },
{ "packet_obfuscation", &battle_config.packet_obfuscation, 1, 0, 3, },
{ "client_accept_chatdori", &battle_config.client_accept_chatdori, 0, 0, INT_MAX, },
@@ -7425,6 +7425,7 @@ static const struct battle_data {
{ "min_item_sell_price", &battle_config.min_item_sell_price, 0, 0, INT_MAX, },
{ "display_fake_hp_when_dead", &battle_config.display_fake_hp_when_dead, 1, 0, 1, },
{ "magicrod_type", &battle_config.magicrod_type, 0, 0, 1, },
+ { "skill_enabled_npc", &battle_config.skill_enabled_npc, 0, 0, INT_MAX, },
{ "features/enable_achievement_system", &battle_config.feature_enable_achievement, 1, 0, 1, },
{ "ping_timer_inverval", &battle_config.ping_timer_interval, 30, 0, 99999999, },
{ "ping_time", &battle_config.ping_time, 20, 0, 99999999, },
diff --git a/src/map/battle.h b/src/map/battle.h
index bb907d5b9..55ee32445 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -580,6 +580,8 @@ struct Battle_Config {
int magicrod_type;
+ int skill_enabled_npc;
+
int feature_enable_achievement;
int ping_timer_interval;
diff --git a/src/map/clif.c b/src/map/clif.c
index 6d67b5114..409889f90 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -12042,7 +12042,7 @@ static void clif_parse_EquipItem(int fd, struct map_session_data *sd)
return; //Out of bounds check.
if( sd->npc_id ) {
- if ( !sd->npc_item_flag )
+ if ((sd->npc_item_flag & ITEMENABLEDNPC_EQUIP) == 0)
return;
} else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1)
; //You can equip/unequip stuff while storage is open/under status changes
@@ -12087,7 +12087,7 @@ static void clif_parse_UnequipItem(int fd, struct map_session_data *sd)
}
if( sd->npc_id ) {
- if ( !sd->npc_item_flag )
+ if ((sd->npc_item_flag & ITEMENABLEDNPC_EQUIP) == 0)
return;
} else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1)
; //You can equip/unequip stuff while storage is open/under status changes
@@ -12838,7 +12838,11 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
// Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex]
pc->update_idle_time(sd, BCIDLE_USESKILLTOID);
- if (sd->npc_id || sd->state.workinprogress & 1) {
+ bool allow_self_skill = ((tmp & INF_SELF_SKILL) != 0 && (skill->get_nk(skill_id) & NK_NO_DAMAGE) != 0);
+ allow_self_skill = (allow_self_skill && battle_config.skill_enabled_npc == SKILLENABLEDNPC_SELF);
+
+ if ((sd->npc_id != 0 && !allow_self_skill && battle_config.skill_enabled_npc != SKILLENABLEDNPC_ALL)
+ || (sd->state.workinprogress & 1) != 0) {
#if PACKETVER >= 20110308
clif->msgtable(sd, MSG_BUSY);
#else
@@ -12847,7 +12851,7 @@ static void clif_useSkillToIdReal(int fd, struct map_session_data *sd, int skill
return;
}
- if (pc_cant_act(sd)
+ if (pc_cant_act_except_npc(sd)
&& skill_id != RK_REFRESH
&& !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN))
&& (sd->state.storage_flag != STORAGE_FLAG_CLOSED && !(tmp&INF_SELF_SKILL)) // SELF skills can be used with the storage open, issue: 8027
@@ -12984,7 +12988,8 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
return;
}
- if (sd->state.workinprogress & 1) {
+ if ((sd->npc_id != 0 && battle_config.skill_enabled_npc != SKILLENABLEDNPC_ALL)
+ || (sd->state.workinprogress & 1) != 0) {
#if PACKETVER >= 20110308
clif->msgtable(sd, MSG_BUSY);
#else
@@ -13054,7 +13059,7 @@ static void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) __attr
/// There are various variants of this packet, some of them have padding between fields.
static void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd)
{
- if (pc_cant_act(sd))
+ if (pc_cant_act_except_npc(sd))
return;
if (pc_issit(sd))
return;
@@ -13075,7 +13080,7 @@ static void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd
/// There are various variants of this packet, some of them have padding between fields.
static void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd)
{
- if (pc_cant_act(sd))
+ if (pc_cant_act_except_npc(sd))
return;
if (pc_issit(sd))
return;
@@ -13104,7 +13109,8 @@ static void clif_parse_UseSkillMap(int fd, struct map_session_data *sd)
return;
// It is possible to use teleport with the storage window open issue:8027
- if (pc_cant_act(sd) && (sd->state.storage_flag == STORAGE_FLAG_CLOSED && skill_id != AL_TELEPORT)) {
+ if ((pc_cant_act_except_npc(sd) && sd->state.storage_flag == STORAGE_FLAG_CLOSED && skill_id != AL_TELEPORT)
+ || (sd->npc_id != 0 && battle_config.skill_enabled_npc != SKILLENABLEDNPC_ALL)) {
clif_menuskill_clear(sd);
return;
}
diff --git a/src/map/pc.c b/src/map/pc.c
index 4497ef54f..73b41db5a 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -5163,7 +5163,8 @@ static int pc_useitem(struct map_session_data *sd, int n)
nullpo_ret(sd);
Assert_ret(n >= 0 && n < sd->status.inventorySize);
- if (sd->npc_id || sd->state.workinprogress & 1) {
+ if ((sd->npc_id != 0 && (sd->npc_item_flag & ITEMENABLEDNPC_CONSUME) == 0)
+ || (sd->state.workinprogress & 1) != 0) {
#if PACKETVER >= 20110308
clif->msgtable(sd, MSG_BUSY);
#else
diff --git a/src/map/pc.h b/src/map/pc.h
index dfc1f886e..f2e911af3 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -103,6 +103,13 @@ enum pc_checkitem_types {
PCCHECKITEM_GSTORAGE = 0x8
};
+/** Bit flags for allowed item actions while interacting with NPC. **/
+enum item_enabled_npc_flags {
+ ITEMENABLEDNPC_NONE = 0x0, //!< Don't allow any item actions while interacting with NPC.
+ ITEMENABLEDNPC_EQUIP = 0x1, //!< Allow changing equipment while interacting with NPC.
+ ITEMENABLEDNPC_CONSUME = 0x2, //!< Allow consuming usable items while interacting with NPC.
+};
+
struct weapon_data {
int atkmods[3];
BEGIN_ZEROED_BLOCK; // all the variables within this block get zero'ed in each call of status_calc_pc
@@ -676,6 +683,7 @@ END_ZEROED_BLOCK;
#define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading )
#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chat_id != 0 || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend || (sd)->state.refine_ui == 1 || (sd)->state.lapine_ui == 1)
#define pc_cant_act_except_lapine(sd) ((sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chat_id != 0 || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend || (sd)->state.refine_ui == 1)
+#define pc_cant_act_except_npc(sd) ( (sd)->state.vending != 0 || (sd)->state.buyingstore != 0 || (sd)->chat_id != 0 || ((sd)->sc.opt1 != 0 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading != 0 || (sd)->state.storage_flag != 0 || (sd)->state.prevend != 0 || (sd)->state.refine_ui == 1 || (sd)->state.lapine_ui == 1)
/* equals pc_cant_act except it doesn't check for chat rooms */
#define pc_cant_act2(sd) ( (sd)->npc_id || (sd)->state.buyingstore || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend || (sd)->state.refine_ui == 1 || (sd)->state.lapine_ui == 1)
diff --git a/src/map/script.c b/src/map/script.c
index 0d04ea31b..763a6c51c 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -9135,22 +9135,71 @@ static BUILDIN(delitemidx)
return true;
}
-/*==========================================
- * Enables/Disables use of items while in an NPC [Skotlex]
- *------------------------------------------*/
+/**
+ * Enable item actions while interacting with NPC.
+ *
+ * @code{.herc}
+ * enableitemuse({<flag>});
+ * enable_items({<flag>});
+ * @endcode
+ *
+ **/
static BUILDIN(enableitemuse)
{
+ int flag = battle_config.item_enabled_npc;
+
+ if (script_hasdata(st, 2)) {
+ if (!script_isinttype(st, 2))
+ return true;
+
+ flag = script_getnum(st, 2);
+ }
+
+ if (flag < 0)
+ return true;
+
struct map_session_data *sd = script->rid2sd(st);
- if (sd != NULL)
- st->npc_item_flag = sd->npc_item_flag = 1;
+
+ if (sd == NULL)
+ return true;
+
+ st->npc_item_flag |= flag;
+ sd->npc_item_flag |= flag;
+
return true;
}
+/**
+ * Disable item actions while interacting with NPC.
+ *
+ * @code{.herc}
+ * disableitemuse({<flag>});
+ * disable_items({<flag>});
+ * @endcode
+ *
+ **/
static BUILDIN(disableitemuse)
{
+ int flag = battle_config.item_enabled_npc;
+
+ if (script_hasdata(st, 2)) {
+ if (!script_isinttype(st, 2))
+ return true;
+
+ flag = script_getnum(st, 2);
+ }
+
+ if (flag < 0)
+ return true;
+
struct map_session_data *sd = script->rid2sd(st);
- if (sd != NULL)
- st->npc_item_flag = sd->npc_item_flag = 0;
+
+ if (sd == NULL)
+ return true;
+
+ st->npc_item_flag &= ~flag;
+ sd->npc_item_flag &= ~flag;
+
return true;
}
@@ -27197,8 +27246,8 @@ static void script_parse_builtin(void)
BUILDIN_DEF(delitem,"vi?"),
BUILDIN_DEF(delitem2,"viiiiiiii?"),
BUILDIN_DEF(delitemidx, "i??"),
- BUILDIN_DEF2(enableitemuse,"enable_items",""),
- BUILDIN_DEF2(disableitemuse,"disable_items",""),
+ BUILDIN_DEF2(enableitemuse, "enable_items", "?"),
+ BUILDIN_DEF2(disableitemuse, "disable_items", "?"),
BUILDIN_DEF(cutin,"si"),
BUILDIN_DEF(viewpoint,"iiiii"),
BUILDIN_DEF(heal,"ii"),
@@ -28247,6 +28296,16 @@ static void script_hardcoded_constants(void)
script->set_constant("PCBLOCK_COMMANDS", PCBLOCK_COMMANDS, false, false);
script->set_constant("PCBLOCK_NPC", PCBLOCK_NPC, false, false);
+ script->constdb_comment("NPC item action constants");
+ script->set_constant("ITEMENABLEDNPC_NONE", ITEMENABLEDNPC_NONE, false, false);
+ script->set_constant("ITEMENABLEDNPC_EQUIP", ITEMENABLEDNPC_EQUIP, false, false);
+ script->set_constant("ITEMENABLEDNPC_CONSUME", ITEMENABLEDNPC_CONSUME, false, false);
+
+ script->constdb_comment("NPC allowed skill use constants");
+ script->set_constant("SKILLENABLEDNPC_NONE", SKILLENABLEDNPC_NONE, false, false);
+ script->set_constant("SKILLENABLEDNPC_SELF", SKILLENABLEDNPC_SELF, false, false);
+ script->set_constant("SKILLENABLEDNPC_ALL", SKILLENABLEDNPC_ALL, false, false);
+
script->constdb_comment("private airship responds");
script->set_constant("P_AIRSHIP_NONE", P_AIRSHIP_NONE, false, false);
script->set_constant("P_AIRSHIP_RETRY", P_AIRSHIP_RETRY, false, false);
diff --git a/src/map/skill.h b/src/map/skill.h
index b9178321d..b505412b6 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -1737,6 +1737,13 @@ enum autocast_type {
AUTOCAST_ITEM, // Used for itemskill() script command.
};
+/** Constants for allowed skill use while interacting with NPC. **/
+enum skill_enabled_npc_flags {
+ SKILLENABLEDNPC_NONE = 0, //!< Don't allow using any skills while interacting with NPC.
+ SKILLENABLEDNPC_SELF = 1, //!< Allow using non-damaging self skills while interacting with NPC.
+ SKILLENABLEDNPC_ALL = 2, //!< Allow using all skills while interacting with NPC.
+};
+
/**
* Structures
**/