From 5591664de540bb0ece487e6d4a2fb9f65d73db5b Mon Sep 17 00:00:00 2001 From: kinther Date: Mon, 15 Dec 2025 14:52:15 -0800 Subject: [PATCH] Hidden emote update --- src/act.h | 10 +++++++++- src/act.other.c | 8 ++++---- src/act.wizard.c | 51 ++++++++++++++++++++++++++++++++++++++++++----- src/interpreter.c | 2 ++ 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/act.h b/src/act.h index d8ebc22..04c7ac3 100644 --- a/src/act.h +++ b/src/act.h @@ -243,6 +243,10 @@ void clear_scan_results(struct char_data *ch); bool scan_can_target(struct char_data *ch, struct char_data *tch); bool scan_confirm_target(struct char_data *ch, struct char_data *tch); void stealth_process_room_movement(struct char_data *ch, room_rnum room, int dir, bool leaving); +int get_stealth_skill_value(struct char_data *ch); +int roll_stealth_check(struct char_data *ch); +bool can_scan_for_sneak(struct char_data *ch); +int roll_scan_perception(struct char_data *ch); /***************************************************************************** @@ -275,7 +279,7 @@ void perform_immort_vis(struct char_data *ch); void snoop_check(struct char_data *ch); bool change_player_name(struct char_data *ch, struct char_data *vict, char *new_name); bool AddRecentPlayer(char *chname, char *chhost, bool newplr, bool cpyplr); -void perform_emote(struct char_data *ch, char *argument, bool possessive); +void perform_emote(struct char_data *ch, char *argument, bool possessive, bool hidden); /* Functions with subcommands */ /* do_date */ ACMD(do_date); @@ -287,8 +291,12 @@ ACMD(do_echo); /* do emote */ ACMD(do_emote); ACMD(do_pemote); +ACMD(do_hemote); +ACMD(do_phemote); #define SCMD_EMOTE 0 #define SCMD_PEMOTE 1 +#define SCMD_HEMOTE 2 +#define SCMD_PHEMOTE 3 /* do_last */ ACMD(do_last); #define SCMD_LIST_ALL 1 diff --git a/src/act.other.c b/src/act.other.c index 855a904..d1544b9 100644 --- a/src/act.other.c +++ b/src/act.other.c @@ -191,7 +191,7 @@ ACMD(do_not_here) #define STEALTH_BASE_DC 10 -static int get_stealth_skill_value(struct char_data *ch) +int get_stealth_skill_value(struct char_data *ch) { int skill = GET_SKILL(ch, SKILL_STEALTH); int legacy = MAX(GET_SKILL(ch, SKILL_HIDE), GET_SKILL(ch, SKILL_SNEAK)); @@ -204,7 +204,7 @@ static int get_stealth_skill_value(struct char_data *ch) return skill; } -static int roll_stealth_check(struct char_data *ch) +int roll_stealth_check(struct char_data *ch) { int skill = get_stealth_skill_value(ch); int bonus = GET_ABILITY_MOD(GET_DEX(ch)) + GET_PROFICIENCY(skill); @@ -225,7 +225,7 @@ static int sneak_effect_duration(struct char_data *ch) return MAX(1, skill / 10); } -static bool can_scan_for_sneak(struct char_data *ch) +bool can_scan_for_sneak(struct char_data *ch) { if (!AFF_FLAGGED(ch, AFF_SCAN)) return FALSE; @@ -238,7 +238,7 @@ static bool can_scan_for_sneak(struct char_data *ch) return TRUE; } -static int roll_scan_perception(struct char_data *ch) +int roll_scan_perception(struct char_data *ch) { int bonus = GET_ABILITY_MOD(GET_WIS(ch)) + GET_PROFICIENCY(GET_SKILL(ch, SKILL_PERCEPTION)); diff --git a/src/act.wizard.c b/src/act.wizard.c index 82af0a0..ea41640 100644 --- a/src/act.wizard.c +++ b/src/act.wizard.c @@ -867,11 +867,32 @@ static void build_replacement(const struct emote_tok *tok, strlcpy(out, "something", outsz); } +static bool hidden_emote_can_view(struct char_data *actor, + struct char_data *viewer, + int stealth_total) { + int opposed; + + if (!viewer || viewer == actor) + return TRUE; + if (GET_LEVEL(viewer) >= LVL_IMMORT) + return TRUE; + if (!AWAKE(viewer)) + return FALSE; + + if (can_scan_for_sneak(viewer)) + opposed = roll_scan_perception(viewer); + else + opposed = rand_number(1, 20); + + return opposed >= stealth_total; +} + /* ===================== Main entry ===================== */ -void perform_emote(struct char_data *ch, char *argument, bool possessive) { +void perform_emote(struct char_data *ch, char *argument, bool possessive, bool hidden) { char base[MAX_STRING_LENGTH]; char with_placeholders[MAX_STRING_LENGTH]; int at_count = 0; + int stealth_total = 0; struct emote_tok toks[MAX_EMOTE_TOKENS]; int tokc = 0; @@ -879,6 +900,9 @@ void perform_emote(struct char_data *ch, char *argument, bool possessive) { skip_spaces(&argument); if (!*argument) { send_to_char(ch, "Yes... but what?\r\n"); return; } + if (hidden) + stealth_total = roll_stealth_check(ch); + /* Only one '@' allowed (inserts actor name/possessive at that spot) */ for (const char *c = argument; *c; ++c) if (*c == '@') at_count++; if (at_count > 1) { send_to_char(ch, "You can only use '@' once in an emote.\r\n"); return; } @@ -973,6 +997,8 @@ void perform_emote(struct char_data *ch, char *argument, bool possessive) { for (struct descriptor_data *d = descriptor_list; d; d = d->next) { if (STATE(d) != CON_PLAYING || !d->character) continue; if (IN_ROOM(d->character) != IN_ROOM(ch)) continue; + if (hidden && !hidden_emote_can_view(ch, d->character, stealth_total)) + continue; char msg[MAX_STRING_LENGTH]; strlcpy(msg, with_placeholders, sizeof(msg)); @@ -991,8 +1017,13 @@ void perform_emote(struct char_data *ch, char *argument, bool possessive) { collapse_spaces(msg); capitalize_sentences(msg); - if (d->character == ch) act(msg, FALSE, ch, NULL, NULL, TO_CHAR); - else act(msg, FALSE, ch, NULL, d->character, TO_VICT); + if (d->character == ch) { + act(msg, FALSE, ch, NULL, NULL, TO_CHAR); + } else if (hidden) { + send_to_char(d->character, "You notice:\r\n%s\r\n", msg); + } else { + act(msg, FALSE, ch, NULL, d->character, TO_VICT); + } } } /* =================== End emote engine =================== */ @@ -1051,12 +1082,22 @@ ACMD(do_echo) ACMD(do_emote) { - perform_emote(ch, argument, FALSE); + perform_emote(ch, argument, FALSE, FALSE); } ACMD(do_pemote) { - perform_emote(ch, argument, TRUE); + perform_emote(ch, argument, TRUE, FALSE); +} + +ACMD(do_hemote) +{ + perform_emote(ch, argument, FALSE, TRUE); +} + +ACMD(do_phemote) +{ + perform_emote(ch, argument, TRUE, TRUE); } ACMD(do_send) diff --git a/src/interpreter.c b/src/interpreter.c index f5fc96a..ff01474 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -137,6 +137,7 @@ cpp_extern const struct command_info cmd_info[] = { { "eat" , "ea" , POS_RESTING , do_eat , 0, SCMD_EAT }, { "echo" , "ec" , POS_SLEEPING, do_echo , LVL_IMMORT, SCMD_ECHO }, { "emote" , "em" , POS_RESTING , do_emote , 0, SCMD_EMOTE }, + { "hemote" , "hem" , POS_RESTING , do_hemote , 0, SCMD_HEMOTE }, { "enter" , "ent" , POS_STANDING, do_enter , 0, 0 }, { "equipment", "eq" , POS_SLEEPING, do_equipment, 0, 0 }, { "exits" , "ex" , POS_RESTING , do_exits , 0, 0 }, @@ -223,6 +224,7 @@ cpp_extern const struct command_info cmd_info[] = { { "put" , "p" , POS_RESTING , do_put , 0, 0 }, { "peace" , "pe" , POS_DEAD , do_peace , LVL_BUILDER, 0 }, { "pemote" , "pem" , POS_SLEEPING, do_pemote , 0, SCMD_PEMOTE }, + { "phemote" , "phem" , POS_SLEEPING, do_phemote , 0, SCMD_PHEMOTE }, { "pick" , "pi" , POS_STANDING, do_gen_door , 1, SCMD_PICK }, { "page" , "pag" , POS_DEAD , do_page , 1, 0 }, { "pardon" , "pardon" , POS_DEAD , do_wizutil , LVL_GOD, SCMD_PARDON },