summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/atcommands.txt17
-rw-r--r--doc/script_commands.txt11
-rw-r--r--src/map/atcommand.c56
-rw-r--r--src/map/atcommand.h10
-rw-r--r--src/map/clif.c212
-rw-r--r--src/map/pc.h1
-rw-r--r--src/map/script.c13
-rw-r--r--src/map/unit.c10
8 files changed, 219 insertions, 111 deletions
diff --git a/doc/atcommands.txt b/doc/atcommands.txt
index 0cddc1680..65c3bb091 100644
--- a/doc/atcommands.txt
+++ b/doc/atcommands.txt
@@ -968,10 +968,19 @@ If no position is given, the command defaults to headgear.
---------------------------------------
-@fakename {<text string>}
-
-Temporarily changes name to the specified string.
-If no string is given, the character's real name will be re-applied.
+@fakename {<options>} {<fake_name>}
+
+Temporarily changes the character's name to <fake_name>.
+If no parameter is passed, the character's real name will be re-applied.
+The <options> parameter is used, to modify which names will be displayed.
+The fake name will always be displayed, regardless of <options>.
+Valid <options> flags (combinable):
+ 0 - Only the fake name is displayed. (Default value.)
+ 1 - Display party name.
+ 2 - Display guild name.
+ 4 - Display guild position.
+ 8 - Display clan position.
+ 16 - Display title.
---------------------------------------
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index 392aa0c1f..3b77aeb2c 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -6575,17 +6575,22 @@ Examples:
---------------------------------------
-*setpcblock(<type>,<option>)
-*checkpcblock()
+*setpcblock(<type>, <option>{, <account id>})
+*checkpcblock({<account id>})
-Prevents the player from doing the following action.
+Prevents a character 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 setpcblock command returns 1 on success or 0 if no character was attached.
+
The checkpcblock command returned value is a bit mask of the currently
enabled block flags (or PCBLOCK_NONE when none is set).
+Parameter <account id> is optional for both commands.
+If omitted, the currently attached character is used.
+
The <type> listed are a bit mask of the following:
PCBLOCK_NONE (only used by checkpcblock)
PCBLOCK_MOVE
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 6d7898fde..91ddc3ef9 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -7892,39 +7892,61 @@ ACMD(monsterignore)
return true;
}
-/*==========================================
- * @fakename
- * => Gives your character a fake name. [Valaris]
- *------------------------------------------*/
+
+/**
+ * Temporarily changes the character's name to the specified string.
+ *
+ * @code{.herc}
+ * @fakename {<options>} {<fake_name>}
+ * @endcode
+ *
+ **/
ACMD(fakename)
{
- if (!*message)
- {
- if (sd->fakename[0])
- {
+ if (*message == '\0') {
+ if (sd->fakename[0] != '\0') {
sd->fakename[0] = '\0';
+ sd->fakename_options = FAKENAME_OPTION_NONE;
clif->blname_ack(0, &sd->bl);
- if( sd->disguise )
+
+ if (sd->disguise != 0) // Another packet should be sent so the client updates the name for sd.
clif->blname_ack(sd->fd, &sd->bl);
- clif->message(sd->fd, msg_fd(fd,1307)); // Returned to real name.
+
+ clif->message(sd->fd, msg_fd(fd, 1307)); // Returned to real name.
return true;
}
- clif->message(sd->fd, msg_fd(fd,1308)); // You must enter a name.
+ clif->message(sd->fd, msg_fd(fd, 1308)); // You must enter a name.
return false;
}
- if (strlen(message) < 2)
- {
- clif->message(sd->fd, msg_fd(fd,1309)); // Fake name must be at least two characters.
+ int options = FAKENAME_OPTION_NONE;
+ char buf[NAME_LENGTH] = {'\0'};
+ const char *fake_name = NULL;
+
+ if (sscanf(message, "%d %23[^\n]", &options, buf) == 2) {
+ fake_name = buf;
+ } else {
+ options = FAKENAME_OPTION_NONE;
+ fake_name = message;
+ }
+
+ if (strlen(fake_name) < 2) {
+ clif->message(sd->fd, msg_fd(fd, 1309)); // Fake name must be at least two characters.
return false;
}
- safestrncpy(sd->fakename, message, sizeof(sd->fakename));
+ if (options < FAKENAME_OPTION_NONE)
+ options = FAKENAME_OPTION_NONE;
+
+ safestrncpy(sd->fakename, fake_name, sizeof(sd->fakename));
+ sd->fakename_options = options;
clif->blname_ack(0, &sd->bl);
- if (sd->disguise) // Another packet should be sent so the client updates the name for sd
+
+ if (sd->disguise != 0) // Another packet should be sent so the client updates the name for sd.
clif->blname_ack(sd->fd, &sd->bl);
- clif->message(sd->fd, msg_fd(fd,1310)); // Fake name enabled.
+
+ clif->message(sd->fd, msg_fd(fd, 1310)); // Fake name enabled.
return true;
}
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index 66827b3b2..f3a5155ab 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -54,6 +54,16 @@ typedef enum {
COMMAND_CHARCOMMAND = 2,
} AtCommandType;
+/** @fakename display option flags **/
+enum fakename_option_flag {
+ FAKENAME_OPTION_NONE = 0x00,
+ FAKENAME_OPTION_SHOW_PARTYNAME = 0x01,
+ FAKENAME_OPTION_SHOW_GUILDNAME = 0x02,
+ FAKENAME_OPTION_SHOW_GUILDPOSITION = 0x04,
+ FAKENAME_OPTION_SHOW_CLANPOSITION = 0x08,
+ FAKENAME_OPTION_SHOW_TITLE = 0x10
+};
+
/**
* Typedef
**/
diff --git a/src/map/clif.c b/src/map/clif.c
index e68028d9d..496a8beda 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9382,82 +9382,98 @@ static void clif_send_selforarea(int fd, struct block_list *bl, const void *buf,
}
}
-/// Updates the object's (bl) name on client.
-/// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
-/// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
-/// 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+/**
+ * Updates a character's name on client.
+ *
+ * @code
+ * 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME)
+ * 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+ * 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param bl The related character's block list.
+ *
+ **/
static void clif_pcname_ack(int fd, struct block_list *bl)
{
nullpo_retv(bl);
Assert_retv(bl->type == BL_PC);
- struct PACKET_ZC_ACK_REQNAMEALL packet = { 0 };
- int len = sizeof(struct PACKET_ZC_ACK_REQNAMEALL);
+ struct PACKET_ZC_ACK_REQNAMEALL packet = {0};
+ packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
packet.gid = bl->id;
const struct map_session_data *ssd = BL_UCCAST(BL_PC, bl);
- if (ssd->fakename[0] != '\0') {
- packet.packet_id = reqName;
- len = sizeof(struct packet_reqname_ack);
- } else {
- packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
- len = sizeof(struct PACKET_ZC_ACK_REQNAMEALL);
- }
-
- //Requesting your own "shadow" name. [Skotlex]
- if (ssd->fd == fd && ssd->disguise != -1) {
+ if (ssd->fd == fd && ssd->disguise != -1) // Requesting your own "shadow" name.
packet.gid = -bl->id;
- }
- if (ssd->fakename[0] != '\0') {
+ if (ssd->fakename[0] != '\0')
memcpy(packet.name, ssd->fakename, NAME_LENGTH);
- } else {
-#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO)
- // Title System [Dastgir/Hercules]
- if (ssd->status.title_id > 0) {
- packet.title_id = ssd->status.title_id;
- }
-#endif
+ else
memcpy(packet.name, ssd->status.name, NAME_LENGTH);
- const struct party_data *p = NULL;
- int ps = -1;
- if (ssd->status.party_id != 0) {
- p = party->search(ssd->status.party_id);
- }
- const struct guild *g = NULL;
- if (ssd->status.guild_id != 0) {
- if ((g = ssd->guild) != NULL) {
- int i;
- ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id);
- if (i < g->max_member)
- ps = g->member[i].position;
- }
- }
+ const struct party_data *p = NULL;
- if (!battle_config.display_party_name && g == NULL) {
- // do not display party unless the player is also in a guild
- p = NULL;
- }
+ if (ssd->status.party_id != 0)
+ p = party->search(ssd->status.party_id);
+
+ const struct guild *g = NULL;
+ int pos_idx = INDEX_NOT_FOUND;
+
+ if (ssd->status.guild_id != 0 && (g = ssd->guild) != NULL) {
+ int i;
+ int acc_id = ssd->status.account_id;
+ int chr_id = ssd->status.char_id;
- if (p != NULL) {
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == acc_id && g->member[i].char_id == chr_id);
+
+ if (i < g->max_member)
+ pos_idx = g->member[i].position;
+ }
+
+ if (battle_config.display_party_name == 0 && g == NULL)
+ p = NULL; // Do not display party name, unless the character is also in a guild.
+
+ if (p != NULL) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_PARTYNAME) != 0)
+ || ssd->fakename[0] == '\0') {
memcpy(packet.party_name, p->party.name, NAME_LENGTH);
}
+ }
- if (g != NULL && ps >= 0 && ps < MAX_GUILDPOSITION) {
+ if (g != NULL && pos_idx >= 0 && pos_idx < MAX_GUILDPOSITION) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_GUILDNAME) != 0)
+ || ssd->fakename[0] == '\0') {
memcpy(packet.guild_name, g->name,NAME_LENGTH);
- memcpy(packet.position_name, g->position[ps].name, NAME_LENGTH);
}
- else if (ssd->status.clan_id != 0) {
- struct clan *c = clan->search(ssd->status.clan_id);
- if (c != 0) {
+
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_GUILDPOSITION) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.position_name, g->position[pos_idx].name, NAME_LENGTH);
+ }
+ } else if (ssd->status.clan_id != 0) {
+ struct clan *c = clan->search(ssd->status.clan_id);
+
+ if (c != 0) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_CLANPOSITION) != 0)
+ || ssd->fakename[0] == '\0') {
memcpy(packet.position_name, c->name, NAME_LENGTH);
}
}
}
- clif->send_selforarea(fd, bl, &packet, len);
+#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO) // Title system.
+ if (ssd->status.title_id > 0) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_TITLE) != 0)
+ || ssd->fakename[0] == '\0') {
+ packet.title_id = ssd->status.title_id;
+ }
+ }
+#endif
+
+ clif->send_selforarea(fd, bl, &packet, sizeof(struct PACKET_ZC_ACK_REQNAMEALL));
}
/// Updates the object's (bl) name on client.
@@ -9748,56 +9764,90 @@ static void clif_blname_ack(int fd, struct block_list *bl)
}
}
-//Used to update when a char leaves a party/guild. [Skotlex]
-//Needed because when you send a 0x95 packet, the client will not remove the cached party/guild info that is not sent.
+/**
+ * Updates a character's name on client when leaving a party/guild.
+ *
+ * @code
+ * 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL)
+ * 0A30 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B <title id>.L (ZC_ACK_REQNAMEALL2)
+ * @endcode
+ *
+ * @param ssd The related character.
+ *
+ **/
static void clif_charnameupdate(struct map_session_data *ssd)
{
- int ps = -1;
- struct party_data *p = NULL;
- struct guild *g = NULL;
- struct PACKET_ZC_ACK_REQNAMEALL packet = { 0 };
-
nullpo_retv(ssd);
- if (ssd->fakename[0])
- return; //No need to update as the party/guild was not displayed anyway.
-
+ struct PACKET_ZC_ACK_REQNAMEALL packet = {0};
packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
packet.gid = ssd->bl.id;
- memcpy(packet.name, ssd->status.name, NAME_LENGTH);
+ if (ssd->fakename[0] != '\0')
+ memcpy(packet.name, ssd->fakename, NAME_LENGTH);
+ else
+ memcpy(packet.name, ssd->status.name, NAME_LENGTH);
- if (!battle_config.display_party_name) {
- if (ssd->status.party_id > 0 && ssd->status.guild_id > 0 && (g = ssd->guild) != NULL)
- p = party->search(ssd->status.party_id);
- } else {
- if (ssd->status.party_id > 0)
- p = party->search(ssd->status.party_id);
- }
+ struct party_data *p = NULL;
+
+ if (ssd->status.party_id != 0)
+ p = party->search(ssd->status.party_id);
+
+ struct guild *g = NULL;
+ int pos_idx = INDEX_NOT_FOUND;
- if (ssd->status.guild_id > 0 && (g = ssd->guild) != NULL) {
+ if (ssd->status.guild_id != 0 && (g = ssd->guild) != NULL) {
int i;
- ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id);
- if( i < g->max_member ) ps = g->member[i].position;
+ int acc_id = ssd->status.account_id;
+ int chr_id = ssd->status.char_id;
+
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == acc_id && g->member[i].char_id == chr_id);
+
+ if (i < g->max_member)
+ pos_idx = g->member[i].position;
}
- if (p != NULL)
- memcpy(packet.party_name, p->party.name, NAME_LENGTH);
+ if (battle_config.display_party_name == 0 && g == NULL)
+ p = NULL; // Do not display party name, unless the character is also in a guild.
- if (g != NULL && ps >= 0 && ps < MAX_GUILDPOSITION) {
- memcpy(packet.guild_name, g->name,NAME_LENGTH);
- memcpy(packet.position_name, g->position[ps].name, NAME_LENGTH);
+ if (p != NULL) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_PARTYNAME) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.party_name, p->party.name, NAME_LENGTH);
+ }
}
-#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO)
- // Achievement System [Dastgir/Hercules]
+ if (g != NULL && pos_idx >= 0 && pos_idx < MAX_GUILDPOSITION) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_GUILDNAME) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.guild_name, g->name,NAME_LENGTH);
+ }
+
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_GUILDPOSITION) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.position_name, g->position[pos_idx].name, NAME_LENGTH);
+ }
+ } else if (ssd->status.clan_id != 0) {
+ struct clan *c = clan->search(ssd->status.clan_id);
+
+ if (c != 0) {
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_CLANPOSITION) != 0)
+ || ssd->fakename[0] == '\0') {
+ memcpy(packet.position_name, c->name, NAME_LENGTH);
+ }
+ }
+ }
+
+#if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined(PACKETVER_ZERO) // Title system.
if (ssd->status.title_id > 0) {
- packet.title_id = ssd->status.title_id;
+ if ((ssd->fakename[0] != '\0' && (ssd->fakename_options & FAKENAME_OPTION_SHOW_TITLE) != 0)
+ || ssd->fakename[0] == '\0') {
+ packet.title_id = ssd->status.title_id;
+ }
}
#endif
- // Update nearby clients
- clif->send(&packet, sizeof(packet), &ssd->bl, AREA);
+ clif->send(&packet, sizeof(packet), &ssd->bl, AREA); // Update nearby clients.
}
/// Taekwon Jump (TK_HIGHJUMP) effect (ZC_HIGHJUMP).
diff --git a/src/map/pc.h b/src/map/pc.h
index 6f932c447..2699b7882 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -497,6 +497,7 @@ END_ZEROED_BLOCK;
int change_level_3rd; // job level when changing from 2nd to 3rd class [jobchange_level_3rd in global_reg_value]
char fakename[NAME_LENGTH]; // fake names [Valaris]
+ int fakename_options; // Fake name display options.
int duel_group; // duel vars [LuzZza]
int duel_invite;
diff --git a/src/map/script.c b/src/map/script.c
index ca13e8861..3d5534a47 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -19263,12 +19263,14 @@ static BUILDIN(pcblockmove)
static BUILDIN(setpcblock)
{
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd = script_hasdata(st, 4) ? script->id2sd(st, script_getnum(st, 4)) : script->rid2sd(st);
enum pcblock_action_flag type = script_getnum(st, 2);
int state = (script_getnum(st, 3) > 0) ? 1 : 0;
- if (sd == NULL)
+ if (sd == NULL) {
+ script_pushint(st, 0);
return true;
+ }
if ((type & PCBLOCK_MOVE) != 0)
sd->block_action.move = state;
@@ -19297,12 +19299,13 @@ static BUILDIN(setpcblock)
if ((type & PCBLOCK_NPC) != 0)
sd->block_action.npc = state;
+ script_pushint(st, 1);
return true;
}
static BUILDIN(checkpcblock)
{
- struct map_session_data *sd = script->rid2sd(st);
+ struct map_session_data *sd = script_hasdata(st, 2) ? script->id2sd(st, script_getnum(st, 2)) : script->rid2sd(st);
int retval = PCBLOCK_NONE;
if (sd == NULL) {
@@ -27146,8 +27149,8 @@ static void script_parse_builtin(void)
BUILDIN_DEF(pcfollow,"ii"),
BUILDIN_DEF(pcstopfollow,"i"),
BUILDIN_DEF_DEPRECATED(pcblockmove,"ii"), // Deprecated 2018-05-04
- BUILDIN_DEF(setpcblock, "ii"),
- BUILDIN_DEF(checkpcblock, ""),
+ BUILDIN_DEF(setpcblock, "ii?"),
+ BUILDIN_DEF(checkpcblock, "?"),
// <--- [zBuffer] List of player cont commands
// [zBuffer] List of mob control commands --->
BUILDIN_DEF(getunittype,"i"),
diff --git a/src/map/unit.c b/src/map/unit.c
index 015f755bb..d484056f9 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -96,6 +96,8 @@ static struct unit_data *unit_bl2ud(struct block_list *bl)
return &BL_UCAST(BL_MER, bl)->ud;
case BL_ELEM:
return &BL_UCAST(BL_ELEM, bl)->ud;
+ case BL_SKILL: // No assertion to not spam the server console when attacking a skill type unit such as Ice Wall.
+ return NULL;
default:
Assert_retr(NULL, false);
}
@@ -128,6 +130,8 @@ static const struct unit_data *unit_cbl2ud(const struct block_list *bl)
return &BL_UCCAST(BL_MER, bl)->ud;
case BL_ELEM:
return &BL_UCCAST(BL_ELEM, bl)->ud;
+ case BL_SKILL: // No assertion to not spam the server console when attacking a skill type unit such as Ice Wall.
+ return NULL;
default:
Assert_retr(NULL, false);
}
@@ -326,7 +330,7 @@ static int unit_warpto_master(struct block_list *master_bl, struct block_list *s
static int unit_walk_toxy_timer(int tid, int64 tick, int id, intptr_t data)
{
struct block_list *bl = map->id2bl(id);
- if (bl == NULL || bl->prev == NULL) // Stop moved because it is missing from the block_list
+ if (bl == NULL)
return 1;
struct unit_data *ud = unit->bl2ud(bl);
if (ud == NULL)
@@ -336,8 +340,12 @@ static int unit_walk_toxy_timer(int tid, int64 tick, int id, intptr_t data)
ShowError("unit_walk_timer mismatch %d != %d\n",ud->walktimer,tid);
return 1;
}
+
ud->walktimer = INVALID_TIMER;
+ if (bl->prev == NULL) // Stop moved because it is missing from the block_list.
+ return 1;
+
if (ud->walkpath.path_pos >= ud->walkpath.path_len)
return 1;