doc/script_commands.txt | 47 ++++++++++++++++++++++++++++++++++++++++++-----
src/map/pc.c | 6 ++++--
src/map/pc.h | 11 +++++++++++
src/map/script.c | 36 ++++++++++++++++++++++++++++++++++++
src/map/status.c | 4 ++++
5 files changed, 97 insertions(+), 7 deletions(-)
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index 218bb48..5dd9f95 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -5859,12 +5859,11 @@ Examples:
---------------------------------------
-*pcblockmove <id>,<option>;
+*pcblockmove <account ID>,<option>;
-Prevents the given ID from moving when the option != 0, and 0 enables the
-ID to move again. The ID can either be the GID of a monster/NPC or account
-ID of a character, and will run for the attached player if zero is
-supplied.
+Prevents the player from moving when the option > 0, and 0 enables the
+player to move again. The player has to be the account ID of a character,
+and will run for the attached player if zero is supplied.
Examples:
@@ -5874,6 +5873,44 @@ Examples:
// Enables the current char to move again.
pcblockmove getcharid(3),0;
+---------------------------------------
+
+*pcblock <type>,<option>{,<account ID>};
+
+Prevents the player from doing the following actions when the <option> is
+true(1), and false(0) will return the player to original state. If there is
+no account ID given, the script will run for the attached player.
+
+The <type> listed are :-
+ BLOCK_MOVE 1
+ BLOCK_ATTACK 2
+ BLOCK_SKILL 4
+ BLOCK_CHAT 8
+ BLOCK_IMMUNE 16
+
+Examples:
+
+// Make the current attached player invulnerable, same as @monsterignore
+ pcblock BLOCK_IMMUNE, true;
+
+// Prevents the current char from attacking and using skills
+ pcblock BLOCK_ATTACK|BLOCK_SKILL, true, getcharid(3);
+
+---------------------------------------
+
+*checkpcblock({<account ID>})
+
+This command will return the options of the current attached player used by
+'pcblock' command. Additionally, you may insert account ID within the bracket
+to check on another player.
+
+Examples:
+
+ if ( checkpcblock() & BLOCK_IMMUNE )
+ mes "You are invulnerable !";
+
+ if ( checkpcblock() & (BLOCK_ATTACK|BLOCK_SKILL) )
+ mes "You are unable to attack and use any skills";
---------------------------------------
//=====================================
diff --git a/src/map/pc.c b/src/map/pc.c
index 4d4f415..a80bdb0 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -8890,7 +8890,8 @@ bool pc_can_attack( struct map_session_data *sd, int target_id ) {
(sd->sc.data[SC_SIREN] && sd->sc.data[SC_SIREN]->val2 == target_id) ||
sd->sc.data[SC_BLADESTOP] ||
sd->sc.data[SC_DEEP_SLEEP] ||
- sd->sc.data[SC_FALLENEMPIRE] )
+ sd->sc.data[SC_FALLENEMPIRE] ||
+ sd->state.blockedattack )
return false;
return true;
@@ -8906,7 +8907,8 @@ bool pc_can_talk( struct map_session_data *sd ) {
if( sd->sc.data[SC_BERSERK] ||
(sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
- (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
+ (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ||
+ sd->state.blockedchat )
return false;
return true;
diff --git a/src/map/pc.h b/src/map/pc.h
index 2c8b24a..71ef120 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -172,6 +172,9 @@ struct map_session_data {
unsigned int size :2; // for tiny/large types
unsigned int night :1; //Holds whether or not the player currently has the SI_NIGHT effect on. [Skotlex]
unsigned int blockedmove :1;
+ unsigned int blockedattack :1;
+ unsigned int blockedskill :1;
+ unsigned int blockedchat :1;
unsigned int using_fake_npc :1;
unsigned int rewarp :1; //Signals that a player should warp as soon as he is done loading a map. [Skotlex]
unsigned int killer : 1;
@@ -757,6 +760,14 @@ struct autotrade_vending {
struct hplugin_data_store *hdata; ///< HPM Plugin Data Store
};
+enum pc_block_action {
+ BLOCK_MOVE = 0x1,
+ BLOCK_ATTACK = 0x2,
+ BLOCK_SKILL = 0x4,
+ BLOCK_CHAT = 0x8,
+ BLOCK_IMMUNE = 0x10,
+};
+
/*=====================================
* Interface : pc.h
* Generated by HerculesInterfaceMaker
diff --git a/src/map/script.c b/src/map/script.c
index 54d8d33..8f69a86 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -16300,6 +16300,34 @@ BUILDIN(pcblockmove) {
return true;
}
+BUILDIN(pcblock) {
+ int type, flag;
+ TBL_PC *sd = NULL;
+
+ type = script_getnum(st,2);
+ flag = script_getnum(st,3);
+ if ( script_hasdata(st,4) )
+ sd = map->id2sd(script_getnum(st,4));
+ else
+ sd = script->rid2sd(st);
+
+ if ( !sd )
+ return true;
+
+ if ( type & BLOCK_MOVE )
+ sd->state.blockedmove = flag > 0;
+ if ( type & BLOCK_ATTACK )
+ sd->state.blockedattack = flag > 0;
+ if ( type & BLOCK_SKILL )
+ sd->state.blockedskill = flag > 0;
+ if ( type & BLOCK_CHAT )
+ sd->state.blockedchat = flag > 0;
+ if ( type & BLOCK_IMMUNE )
+ sd->state.monster_ignore = flag > 0;
+
+ return true;
+}
+
BUILDIN(pcfollow) {
int id, targetid;
TBL_PC *sd = NULL;
@@ -20234,6 +20262,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(pcfollow,"ii"),
BUILDIN_DEF(pcstopfollow,"i"),
BUILDIN_DEF(pcblockmove,"ii"),
+ BUILDIN_DEF(pcblock,"ii?"),
// <--- [zBuffer] List of player cont commands
// [zBuffer] List of mob control commands --->
BUILDIN_DEF(unitwalk,"ii?"),
@@ -20509,6 +20538,13 @@ void script_hardcoded_constants(void) {
script->set_constant("BG_AREA_WOS",BG_AREA_WOS,false);
script->set_constant("BG_QUEUE",BG_QUEUE,false);
+ /* pc_block_action */
+ script->set_constant("BLOCK_MOVE",BLOCK_MOVE,false);
+ script->set_constant("BLOCK_ATTACK",BLOCK_ATTACK,false);
+ script->set_constant("BLOCK_SKILL",BLOCK_SKILL,false);
+ script->set_constant("BLOCK_CHAT",BLOCK_CHAT,false);
+ script->set_constant("BLOCK_IMMUNE",BLOCK_IMMUNE,false);
+
/* Renewal */
#ifdef RENEWAL
script->set_constant("RENEWAL", 1, false);
diff --git a/src/map/status.c b/src/map/status.c
index 1a07f74..bf6e23b 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1600,6 +1600,10 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if( skill_id ) {
+ if ( src && src->type == BL_PC ) // *pcblock script command
+ if ( ((TBL_PC*)src)->state.blockedskill )
+ return 0;
+
if( src && !(src->type == BL_PC && ((TBL_PC*)src)->skillitem)) { // Items that cast skills using 'itemskill' will not be handled by map_zone_db.
int i;