diff options
-rw-r--r-- | doc/script_commands.txt | 60 | ||||
-rw-r--r-- | src/map/atcommand.c | 8 | ||||
-rw-r--r-- | src/map/battle.c | 2 | ||||
-rw-r--r-- | src/map/clif.c | 6 | ||||
-rw-r--r-- | src/map/pc.c | 9 | ||||
-rw-r--r-- | src/map/pc.h | 12 | ||||
-rw-r--r-- | src/map/script.c | 98 | ||||
-rw-r--r-- | src/map/script.h | 16 | ||||
-rw-r--r-- | src/map/status.c | 3 | ||||
-rw-r--r-- | src/map/unit.c | 2 |
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 |