summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpanikon <panikon@zoho.com>2014-07-10 02:02:59 -0300
committerpanikon <panikon@zoho.com>2014-07-10 02:02:59 -0300
commit9dd6ee636b783f1cd57b1be3d02fcc9782ebe2c3 (patch)
treeb633ab7d298a279b21d1cc0fafe8884deccd30f8
parent222345170f781b0cc19dfb99e0820098097a1254 (diff)
downloadhercules-9dd6ee636b783f1cd57b1be3d02fcc9782ebe2c3.tar.gz
hercules-9dd6ee636b783f1cd57b1be3d02fcc9782ebe2c3.tar.bz2
hercules-9dd6ee636b783f1cd57b1be3d02fcc9782ebe2c3.tar.xz
hercules-9dd6ee636b783f1cd57b1be3d02fcc9782ebe2c3.zip
Corrected some SC behaviour, special thanks to Rytech
- Extracted some methods to check SC blocks - Fixed issue that when players couldn't attack they couldn't talk to NPCs with mob view id either Follow up to ec51176326c6028630835538db67826281d34ffe, fixed minor typo
-rw-r--r--src/map/atcommand.c2
-rw-r--r--src/map/clif.c25
-rw-r--r--src/map/pc.c47
-rw-r--r--src/map/pc.h2
-rw-r--r--src/map/unit.c6
5 files changed, 67 insertions, 15 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 9162d1c45..d36e98c41 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -3933,7 +3933,7 @@ ACMD(mount_peco)
return true;
}
if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) {
- if( !pc->checkskill(sd,RA_WUGRIDER) > 0 ) {
+ if( !pc->checkskill(sd,RA_WUGRIDER) ) {
sprintf(atcmd_output, msg_txt(213), skill->get_desc(RA_WUGRIDER)); // You need %s to mount!
clif->message(fd, atcmd_output);
return false;
diff --git a/src/map/clif.c b/src/map/clif.c
index 8ddae3326..750689816 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9866,7 +9866,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
if( atcommand->exec(fd, sd, message, true) )
return;
- 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) )
+ if( !pc->can_talk(sd) )
return;
if( battle_config.min_chat_delay ) { //[Skotlex]
@@ -10113,14 +10113,14 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
return;
}
- if (sd->sc.count &&
- (sd->sc.data[SC_TRICKDEAD] ||
- (sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) ||
- sd->sc.data[SC_BLADESTOP] ||
- sd->sc.data[SC_DEEP_SLEEP] ||
- sd->sc.data[SC__MANHOLE] ||
- sd->sc.data[SC_CURSEDCIRCLE_ATKER] ||
- sd->sc.data[SC_CURSEDCIRCLE_TARGET] ))
+ // Statuses that don't let the player sit / attack / talk with NPCs(targeted)
+ // (not all are included in pc_can_attack)
+ if( sd->sc.count && (
+ sd->sc.data[SC_TRICKDEAD] ||
+ (sd->sc.data[SC_AUTOCOUNTER] && action_type != 0x07) ||
+ sd->sc.data[SC_BLADESTOP] ||
+ sd->sc.data[SC_DEEP_SLEEP] )
+ )
return;
pc_stop_walking(sd, 1);
@@ -10144,10 +10144,6 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
if( sd->sc.option&OPTION_COSTUME )
return;
- if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] ||
- (sd->sc.data[SC_SIREN] && sd->sc.data[SC_SIREN]->val2 == target_id) )
- return;
-
if (!battle_config.sdelay_attack_enable && pc->checkskill(sd, SA_FREECAST) <= 0) {
if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) {
clif->skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0);
@@ -10379,7 +10375,8 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
if ( atcommand->exec(fd, sd, message, true) )
return;
- 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))
+ // Statuses that prevent the player from whispering
+ if( !pc->can_talk(sd) )
return;
if (battle_config.min_chat_delay) { //[Skotlex]
diff --git a/src/map/pc.c b/src/map/pc.c
index 47744a839..b8b6cda46 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -4384,6 +4384,7 @@ int pc_useitem(struct map_session_data *sd,int n) {
if (nameid != ITEMID_NAUTHIZ && sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT && sd->sc.opt1 != OPT1_BURNING)
return 0;
+ // Statuses that don't let the player use items
if (sd->sc.count && (
sd->sc.data[SC_BERSERK] ||
(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) ||
@@ -4396,6 +4397,7 @@ int pc_useitem(struct map_session_data *sd,int n) {
sd->sc.data[SC_WHITEIMPRISON] ||
sd->sc.data[SC_DEEP_SLEEP] ||
sd->sc.data[SC_SATURDAY_NIGHT_FEVER] ||
+ sd->sc.data[SC_COLD] ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM)
))
return 0;
@@ -8131,6 +8133,49 @@ int pc_setmadogear(TBL_PC* sd, int flag)
return 0;
}
+/**
+ * Determines whether a player can attack based on status changes
+ * Why not use status_check_skilluse?
+ * "src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack."
+ * Even ground-based attacks should be blocked by these statuses
+ * Called from unit_attack and unit_attack_timer_sub
+ * @retval true Can attack
+ **/
+bool pc_can_attack( struct map_session_data *sd, int target_id ) {
+ nullpo_retr(false, sd);
+
+ if( sd->sc.data[SC_BASILICA] ||
+ sd->sc.data[SC__SHADOWFORM] ||
+ sd->sc.data[SC__MANHOLE] ||
+ sd->sc.data[SC_CURSEDCIRCLE_ATKER] ||
+ sd->sc.data[SC_CURSEDCIRCLE_TARGET] ||
+ sd->sc.data[SC_COLD] ||
+ sd->sc.data[SC_ALL_RIDING] || // The client doesn't let you, this is to make cheat-safe
+ sd->sc.data[SC_TRICKDEAD] ||
+ (sd->sc.data[SC_SIREN] && sd->sc.data[SC_SIREN]->val2 == target_id) ||
+ sd->sc.data[SC_BLADESTOP] ||
+ sd->sc.data[SC_DEEP_SLEEP] )
+ return false;
+
+ return true;
+}
+
+/**
+ * Determines whether a player can talk/whisper based on status changes
+ * Called from clif_parse_GlobalMessage and clif_parse_WisMessage
+ * @retval true Can talk
+ **/
+bool pc_can_talk( struct map_session_data *sd ) {
+ nullpo_retr(false, 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) )
+ return false;
+
+ return true;
+}
+
/*==========================================
* Check if player can drop an item
*------------------------------------------*/
@@ -10835,6 +10880,8 @@ void pc_defaults(void) {
pc->setstand = pc_setstand;
pc->candrop = pc_candrop;
+ pc->can_talk = pc_can_talk;
+ pc->can_attack = pc_can_attack;
pc->jobid2mapid = pc_jobid2mapid; // Skotlex
pc->mapid2jobid = pc_mapid2jobid; // Skotlex
diff --git a/src/map/pc.h b/src/map/pc.h
index 19e0348d0..1789a8a7b 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -771,6 +771,8 @@ struct pc_interface {
//int (*getrefinebonus) (int lv,int type); FIXME: This function does not exist, nor it is ever called
bool (*can_give_items) (struct map_session_data *sd);
bool (*can_give_bound_items) (struct map_session_data *sd);
+ bool (*can_talk) (struct map_session_data *sd);
+ bool (*can_attack) ( struct map_session_data *sd, int target_id );
bool (*can_use_command) (struct map_session_data *sd, const char *command);
int (*set_group) (struct map_session_data *sd, int group_id);
diff --git a/src/map/unit.c b/src/map/unit.c
index 875eb30af..e5c7c45c1 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -909,6 +909,7 @@ int unit_can_move(struct block_list *bl) {
))
return 0; //Can't move
+ // Status changes that block movement
if (sc) {
if( sc->count
&& (
@@ -1602,6 +1603,10 @@ int unit_attack(struct block_list *src,int target_id,int continuous) {
unit->stop_attack(src);
return 0;
}
+ if( !pc->can_attack(sd, target_id) ) {
+ unit->stop_attack(src);
+ return 0;
+ }
}
if( battle->check_target(src,target,BCT_ENEMY) <= 0 || !status->check_skilluse(src, target, 0, 0) ) {
unit->unattackable(src);
@@ -1791,6 +1796,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
#ifdef OFFICIAL_WALKPATH
|| !path->search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL)
#endif
+ || (sd && !pc->can_attack(sd, ud->target) )
)
return 0; // can't attack under these conditions