summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/atcommand.c21
-rw-r--r--src/map/clif.c24
-rw-r--r--src/map/map.h17
-rw-r--r--src/map/pc.c15
4 files changed, 76 insertions, 1 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index ea92f34..d10139f 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -220,6 +220,8 @@ ATCOMMAND_FUNC(set_magic); // [Fate]
ATCOMMAND_FUNC(magic_info); // [Fate]
ATCOMMAND_FUNC(log); // [Fate]
ATCOMMAND_FUNC(tee); // [Fate]
+ATCOMMAND_FUNC(invisible); // [Fate]
+ATCOMMAND_FUNC(visible); // [Fate]
#ifndef TXT_ONLY
ATCOMMAND_FUNC(checkmail); // [Valaris]
@@ -471,6 +473,8 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_Log, "@l", 60, atcommand_log }, // [Fate]
{ AtCommand_Tee, "@tee", 60, atcommand_tee }, // [Fate]
{ AtCommand_Tee, "@t", 60, atcommand_tee }, // [Fate]
+ { AtCommand_Tee, "@invisible", 60, atcommand_invisible }, // [Fate]
+ { AtCommand_Tee, "@visible", 60, atcommand_visible }, // [Fate]
#ifndef TXT_ONLY // sql-only commands
{ AtCommand_CheckMail, "@checkmail", 1, atcommand_listmail }, // [Valaris]
@@ -8037,3 +8041,20 @@ atcommand_tee(const int fd, struct map_session_data* sd,
clif_message(&sd->bl, data);
return 0;
}
+
+int
+atcommand_invisible(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ pc_invisibility(sd, 1);
+ return 0;
+}
+
+int
+atcommand_visible(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ pc_invisibility(sd, 0);
+ return 0;
+}
+
diff --git a/src/map/clif.c b/src/map/clif.c
index 653865b..82860e5 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -286,6 +286,27 @@ int clif_send(unsigned char *buf, int len, struct block_list *bl, int type) {
if (type != ALL_CLIENT) {
nullpo_retr(0, bl);
+
+ if (bl->type == BL_PC) {
+ struct map_session_data *sd = (struct map_session_data *) bl;
+ if (sd->status.option & OPTION_INVISIBILITY) {
+ // Obscure hidden GMs
+
+ switch (type) {
+ case AREA:
+ case AREA_WOC:
+ type = SELF;
+ break;
+
+ case AREA_WOS:
+ case AREA_WOSC:
+ return;
+
+ default:
+ break;
+ }
+ }
+ }
}
switch(type) {
@@ -3565,6 +3586,9 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
{
int len;
+ if (dstsd->status.option & OPTION_INVISIBILITY)
+ return;
+
nullpo_retv(sd);
nullpo_retv(dstsd);
diff --git a/src/map/map.h b/src/map/map.h
index afaf61e..d407016 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -41,7 +41,22 @@
#define DEFAULT_AUTOSAVE_INTERVAL 60*1000
-#define OPTION_HIDE 0x40
+// [Fate] status.option properties. These are persistent status changes.
+// IDs that are not listed are not used in the code (to the best of my knowledge)
+#define OPTION_HIDE2 0x0002 // apparently some weaker non-GM hide
+#define OPTION_CLOAK 0x0004
+#define OPTION_10 0x0010
+#define OPTION_20 0x0020
+#define OPTION_HIDE 0x0040 // [Fate] This is the GM `@hide' flag
+#define OPTION_800 0x0800
+#define OPTION_INVISIBILITY 0x1000 // [Fate] Complete invisibility to other clients
+#define OPTION_SCRIBE 0x2000 // [Fate] Auto-logging of nearby comments
+#define OPTION_CHASEWALK 0x4000
+
+// Below are special clif_changestatus() IDs reserved for option updates
+#define CLIF_OPTION_SC_BASE 0x1000
+#define CLIF_OPTION_SC_INVISIBILITY (CLIF_OPTION_SC_BASE)
+#define CLIF_OPTION_SC_SCRIBE (CLIF_OPTION_SC_BASE + 1)
enum { BL_NUL, BL_PC, BL_NPC, BL_MOB, BL_ITEM, BL_CHAT, BL_SKILL, BL_PET, BL_SPELL };
enum { WARP, SHOP, SCRIPT, MONS, MESSAGE };
diff --git a/src/map/pc.c b/src/map/pc.c
index 62e2cd5..bed6fc6 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -7765,3 +7765,18 @@ pc_cleanup(struct map_session_data *sd)
{
magic_stop_completely(sd);
}
+
+
+void
+pc_invisibility(struct map_session_data *sd, int enabled)
+{
+ if (enabled && !(sd->status.option & OPTION_INVISIBILITY)) {
+ clif_clearchar_area(&sd->bl, 3);
+ sd->status.option |= OPTION_INVISIBILITY;
+ clif_status_change(&sd->bl, CLIF_OPTION_SC_INVISIBILITY, 1);
+ } else {
+ sd->status.option &= ~OPTION_INVISIBILITY;
+ clif_status_change(&sd->bl, CLIF_OPTION_SC_INVISIBILITY, 0);
+ pc_setpos(sd, map[sd->bl.m].name, sd->bl.x, sd->bl.y, 3);
+ }
+}