summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/script_commands.txt60
-rw-r--r--src/map/atcommand.c8
-rw-r--r--src/map/battle.c2
-rw-r--r--src/map/clif.c6
-rw-r--r--src/map/pc.c9
-rw-r--r--src/map/pc.h12
-rw-r--r--src/map/script.c98
-rw-r--r--src/map/script.h16
-rw-r--r--src/map/status.c3
-rw-r--r--src/map/unit.c2
10 files changed, 199 insertions, 17 deletions
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index eb0f2a78a..c8fa056d4 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -6189,12 +6189,15 @@ Examples:
---------------------------------------
-*pcblockmove(<id>, <option>)
+*pcblockmove(<account id>, <option>)
-Prevents the given ID from moving when the optionis true , and false
-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.
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ @ /!\ This command is deprecated @
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+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:
@@ -6204,6 +6207,53 @@ Examples:
// Enables the current char to move again.
pcblockmove(getcharid(CHAR_ID_ACCOUNT), false);
+---------------------------------------
+
+*setpcblock(<type>,<option>)
+*checkpcblock()
+
+Prevents the player from doing the following action.
+
+For setpcblock, when the <option> is true(1) will block them, and false(0)
+will allow those actions again.
+
+The checkpcblock command returned value is a bit mask of the currently
+enabled block flags (or PCBLOCK_NONE when none is set).
+
+The <type> listed are a bit mask of the following:
+ PCBLOCK_NONE (only used by checkpcblock)
+ PCBLOCK_MOVE
+ PCBLOCK_ATTACK
+ PCBLOCK_SKILL
+ PCBLOCK_USEITEM
+ PCBLOCK_CHAT
+ PCBLOCK_IMMUNE
+ PCBLOCK_SITSTAND
+ PCBLOCK_COMMANDS
+
+Examples:
+
+// Make the current attached player invulnerable, same as @monsterignore
+ setpcblock(PCBLOCK_IMMUNE, true);
+
+// Prevents the current char from attacking or using skills
+ setpcblock(PCBLOCK_ATTACK|PCBLOCK_SKILL, true);
+
+// Re-enables attack, skills and item use
+ setpcblock(PCBLOCK_ATTACK|PCBLOCK_SKILL|PCBLOCK_ITEM, false);
+
+// checkpcblock related checks
+ if ((checkpcblock() & PCBLOCK_IMMUNE) != 0)
+ mes "You are invulnerable!";
+
+ if ((checkpcblock() & (PCBLOCK_MOVE|PCBLOCK_SITSTAND)) == (PCBLOCK_MOVE|PCBLOCK_SITSTAND))
+ mes "You can't walk or sit";
+
+ if ((checkpcblock() & (PCBLOCK_ATTACK|PCBLOCK_SKILL)) == PCBLOCK_NONE)
+ mes "You can attack and use skills";
+
+ if ((checkpcblock() & PCBLOCK_CHAT) == PCBLOCK_NONE)
+ mes "You can't chat";
---------------------------------------
//=====================================
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index c81196d32..290611c9b 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -7528,11 +7528,11 @@ ACMD(sizeguild)
*------------------------------------------*/
ACMD(monsterignore)
{
- if (!sd->state.monster_ignore) {
- sd->state.monster_ignore = 1;
+ if (!sd->block_action.immune) {
+ sd->block_action.immune = 1;
clif->message(sd->fd, msg_fd(fd,1305)); // You are now immune to attacks.
} else {
- sd->state.monster_ignore = 0;
+ sd->block_action.immune = 0;
clif->message(sd->fd, msg_fd(fd,1306)); // Returned to normal state.
}
@@ -10096,6 +10096,8 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
return false;
}
}
+ if (sd->block_action.commands) // *pcblock script command
+ return false;
if (*message == atcommand->char_symbol)
is_atcommand = false;
diff --git a/src/map/battle.c b/src/map/battle.c
index f257f3c84..6a961afeb 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -6649,7 +6649,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if (t_bl == s_bl)
break;
- if( sd->state.monster_ignore && flag&BCT_ENEMY )
+ if (sd->block_action.immune && flag&BCT_ENEMY)
return 0; // Global immunity only to Attacks
if (sd->status.karma && s_bl->type == BL_PC && BL_UCCAST(BL_PC, s_bl)->status.karma)
state |= BCT_ENEMY; // Characters with bad karma may fight amongst them
diff --git a/src/map/clif.c b/src/map/clif.c
index fa112d40e..3bdea3f7f 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -10489,6 +10489,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
return;
}
+ if (sd->block_action.sitstand) // *pcblock script command
+ break;
+
if (sd->ud.skilltimer != INVALID_TIMER || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING ))
break;
@@ -10516,6 +10519,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
return;
}
+ if (sd->block_action.sitstand) // *pcblock script command
+ break;
+
pc->update_idle_time(sd, BCIDLE_SIT);
pc->setstand(sd);
diff --git a/src/map/pc.c b/src/map/pc.c
index cb56aec77..f2bf042eb 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -5181,6 +5181,9 @@ int pc_useitem(struct map_session_data *sd,int n) {
if( sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0 )
return 0;
+ if (sd->block_action.useitem) // *pcblock script command
+ return 0;
+
if( !pc->isUseitem(sd,n) )
return 0;
@@ -9344,7 +9347,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->block_action.attack)
return false;
return true;
@@ -9360,7 +9364,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) ||
- pc_ismuted(&sd->sc, MANNER_NOCHAT) )
+ pc_ismuted(&sd->sc, MANNER_NOCHAT) ||
+ sd->block_action.chat)
return false;
return true;
diff --git a/src/map/pc.h b/src/map/pc.h
index cb132582b..695add32f 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -201,10 +201,8 @@ struct map_session_data {
unsigned int noask :1; // [LuzZza]
unsigned int trading :1; //[Skotlex] is 1 only after a trade has started.
unsigned int deal_locked :2; //1: Clicked on OK. 2: Clicked on TRADE
- unsigned int monster_ignore :1; // for monsters to ignore a character [Valaris] [zzo]
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 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;
@@ -621,6 +619,16 @@ END_ZEROED_BLOCK;
// HatEffect
VECTOR_DECL(int) hatEffectId;
+ struct {
+ unsigned move : 1;
+ unsigned attack : 1;
+ unsigned skill : 1;
+ unsigned useitem : 1;
+ unsigned chat : 1;
+ unsigned immune : 1;
+ unsigned sitstand : 1;
+ unsigned commands : 1;
+ } block_action;
};
#define EQP_WEAPON EQP_HAND_R
diff --git a/src/map/script.c b/src/map/script.c
index 4b078d745..b9a826b93 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -18117,9 +18117,88 @@ BUILDIN(pcblockmove) {
else
sd = script->rid2sd(st);
- if (sd != NULL)
- sd->state.blockedmove = flag > 0;
+ if (!sd)
+ return true;
+
+ if (flag)
+ sd->block_action.move = 1;
+ else
+ sd->block_action.move = 0;
+
+ return true;
+}
+
+BUILDIN(setpcblock)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+ enum pcblock_action_flag type = script_getnum(st, 2);
+ int state = (script_getnum(st, 3) > 0) ? 1 : 0;
+
+ if (sd == NULL)
+ return true;
+
+ if ((type & PCBLOCK_MOVE) != 0)
+ sd->block_action.move = state;
+
+ if ((type & PCBLOCK_ATTACK) != 0)
+ sd->block_action.attack = state;
+
+ if ((type & PCBLOCK_SKILL) != 0)
+ sd->block_action.skill = state;
+
+ if ((type & PCBLOCK_USEITEM) != 0)
+ sd->block_action.useitem = state;
+
+ if ((type & PCBLOCK_CHAT) != 0)
+ sd->block_action.chat = state;
+
+ if ((type & PCBLOCK_IMMUNE) != 0)
+ sd->block_action.immune = state;
+
+ if ((type & PCBLOCK_SITSTAND) != 0)
+ sd->block_action.sitstand = state;
+
+ if ((type & PCBLOCK_COMMANDS) != 0)
+ sd->block_action.commands = state;
+
+ return true;
+}
+
+BUILDIN(checkpcblock)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+ int retval = PCBLOCK_NONE;
+
+ if (sd == NULL) {
+ script_pushint(st, PCBLOCK_NONE);
+ return true;
+ }
+
+ if (sd->block_action.move != 0)
+ retval |= PCBLOCK_MOVE;
+
+ if (sd->block_action.attack != 0)
+ retval |= PCBLOCK_ATTACK;
+
+ if (sd->block_action.skill != 0)
+ retval |= PCBLOCK_SKILL;
+
+ if (sd->block_action.useitem != 0)
+ retval |= PCBLOCK_USEITEM;
+
+ if (sd->block_action.chat != 0)
+ retval |= PCBLOCK_CHAT;
+
+ if (sd->block_action.immune != 0)
+ retval |= PCBLOCK_IMMUNE;
+
+ if (sd->block_action.sitstand != 0)
+ retval |= PCBLOCK_SITSTAND;
+
+ if (sd->block_action.commands != 0)
+ retval |= PCBLOCK_COMMANDS;
+ script_pushint(st, retval);
return true;
}
@@ -24594,7 +24673,9 @@ void script_parse_builtin(void) {
BUILDIN_DEF(rid2name,"i"),
BUILDIN_DEF(pcfollow,"ii"),
BUILDIN_DEF(pcstopfollow,"i"),
- BUILDIN_DEF(pcblockmove,"ii"),
+ BUILDIN_DEF_DEPRECATED(pcblockmove,"ii"), // Deprecated 2018-05-04
+ BUILDIN_DEF(setpcblock, "ii"),
+ BUILDIN_DEF(checkpcblock, ""),
// <--- [zBuffer] List of player cont commands
// [zBuffer] List of mob control commands --->
BUILDIN_DEF(getunittype,"i"),
@@ -25168,6 +25249,17 @@ void script_hardcoded_constants(void)
script->set_constant("MST_AROUND3", MST_AROUND3, false, false);
script->set_constant("MST_AROUND4", MST_AROUND4, false, false);
script->set_constant("MST_AROUND", MST_AROUND , false, false);
+
+ script->constdb_comment("pc block constants, use with *setpcblock* and *checkpcblock*");
+ script->set_constant("PCBLOCK_NONE", PCBLOCK_NONE, false, false);
+ script->set_constant("PCBLOCK_MOVE", PCBLOCK_MOVE, false, false);
+ script->set_constant("PCBLOCK_ATTACK", PCBLOCK_ATTACK, false, false);
+ script->set_constant("PCBLOCK_SKILL", PCBLOCK_SKILL, false, false);
+ script->set_constant("PCBLOCK_USEITEM", PCBLOCK_USEITEM, false, false);
+ script->set_constant("PCBLOCK_CHAT", PCBLOCK_CHAT, false, false);
+ script->set_constant("PCBLOCK_IMMUNE", PCBLOCK_IMMUNE, false, false);
+ script->set_constant("PCBLOCK_SITSTAND", PCBLOCK_SITSTAND, false, false);
+ script->set_constant("PCBLOCK_COMMANDS", PCBLOCK_COMMANDS, false, false);
script->constdb_comment("private airship responds");
script->set_constant("P_AIRSHIP_NONE", P_AIRSHIP_NONE, false, false);
diff --git a/src/map/script.h b/src/map/script.h
index 9cd673263..a0cfb7692 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -456,6 +456,22 @@ enum script_iteminfo_types {
};
/**
+ * Player blocking actions related flags.
+ */
+enum pcblock_action_flag {
+ PCBLOCK_NONE = 0x00,
+ PCBLOCK_MOVE = 0x01,
+ PCBLOCK_ATTACK = 0x02,
+ PCBLOCK_SKILL = 0x04,
+ PCBLOCK_USEITEM = 0x08,
+ PCBLOCK_CHAT = 0x10,
+ PCBLOCK_IMMUNE = 0x20,
+ PCBLOCK_SITSTAND = 0x40,
+ PCBLOCK_COMMANDS = 0x80,
+ PCBLOCK_ALL = 0xFF,
+};
+
+/**
* Structures
**/
diff --git a/src/map/status.c b/src/map/status.c
index 7d3734903..45a8f86bf 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1761,6 +1761,9 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if (src != NULL && src->type != BL_PC && status->isdead(src))
return 0;
+ if (sd != NULL && sd->block_action.skill && skill_id) // *pcblock script command
+ return 0;
+
if (!skill_id) { //Normal attack checks.
if (!(st->mode&MD_CANATTACK))
return 0; //This mode is only needed for melee attacking.
diff --git a/src/map/unit.c b/src/map/unit.c
index 597c6b45b..36e095b4b 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1091,7 +1091,7 @@ int unit_can_move(struct block_list *bl)
pc_issit(sd) ||
sd->state.vending ||
sd->state.buyingstore ||
- sd->state.blockedmove
+ sd->block_action.move
))
return 0; //Can't move